1 #include <config.h>
2 #include <errno.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <ctype.h>
7 #include <assert.h>
8 #include <unistd.h>
9 #include <sys/stat.h>
10 
11 #include "agent.h"
12 #include "../common/i18n.h"
13 #include "../common/sexp-parse.h"
14 
15 int
divert_tpm2_pksign(ctrl_t ctrl,const char * desc_text,const unsigned char * digest,size_t digestlen,int algo,const unsigned char * shadow_info,unsigned char ** r_sig,size_t * r_siglen)16 divert_tpm2_pksign (ctrl_t ctrl, const char *desc_text,
17                     const unsigned char *digest, size_t digestlen, int algo,
18                     const unsigned char *shadow_info, unsigned char **r_sig,
19                     size_t *r_siglen)
20 {
21   (void)desc_text;
22   (void)algo;
23   return agent_tpm2d_pksign(ctrl, digest, digestlen,
24 			    shadow_info, r_sig, r_siglen);
25 }
26 
27 
28 static gpg_error_t
agent_write_tpm2_shadow_key(ctrl_t ctrl,const unsigned char * grip,unsigned char * shadow_info)29 agent_write_tpm2_shadow_key (ctrl_t ctrl, const unsigned char *grip,
30 			     unsigned char *shadow_info)
31 {
32   gpg_error_t err;
33   unsigned char *shdkey;
34   unsigned char *pkbuf;
35   size_t len;
36   gcry_sexp_t s_pkey;
37 
38   err = agent_public_key_from_file (ctrl, grip, &s_pkey);
39   len = gcry_sexp_sprint(s_pkey, GCRYSEXP_FMT_CANON, NULL, 0);
40   pkbuf = xtrymalloc (len);
41   gcry_sexp_sprint (s_pkey, GCRYSEXP_FMT_CANON, pkbuf, len);
42   gcry_sexp_release (s_pkey);
43 
44   err = agent_shadow_key_type (pkbuf, shadow_info, "tpm2-v1", &shdkey);
45   xfree (pkbuf);
46   if (err)
47     {
48       log_error ("shadowing the key failed: %s\n", gpg_strerror (err));
49       return err;
50     }
51 
52   len = gcry_sexp_canon_len (shdkey, 0, NULL, NULL);
53   err = agent_write_private_key (grip, shdkey, len, 1 /*force*/,
54                                  NULL, NULL, 0);
55   xfree (shdkey);
56   if (err)
57     log_error ("error writing key: %s\n", gpg_strerror (err));
58 
59   return err;
60 }
61 
62 int
divert_tpm2_writekey(ctrl_t ctrl,const unsigned char * grip,gcry_sexp_t s_skey)63 divert_tpm2_writekey (ctrl_t ctrl, const unsigned char *grip,
64                       gcry_sexp_t s_skey)
65 {
66   int ret;
67   /* shadow_info is always shielded so no special handling required */
68   unsigned char *shadow_info;
69 
70   ret = agent_tpm2d_writekey(ctrl, &shadow_info, s_skey);
71   if (!ret) {
72     ret = agent_write_tpm2_shadow_key (ctrl, grip, shadow_info);
73     xfree (shadow_info);
74   }
75   return ret;
76 }
77 
78 int
divert_tpm2_pkdecrypt(ctrl_t ctrl,const char * desc_text,const unsigned char * cipher,const unsigned char * shadow_info,char ** r_buf,size_t * r_len,int * r_padding)79 divert_tpm2_pkdecrypt (ctrl_t ctrl, const char *desc_text,
80                        const unsigned char *cipher,
81                        const unsigned char *shadow_info,
82                        char **r_buf, size_t *r_len, int *r_padding)
83 {
84   const unsigned char *s;
85   size_t n;
86 
87   *r_padding = -1;
88 
89   (void)desc_text;
90 
91   s = cipher;
92   if (*s != '(')
93     return gpg_error (GPG_ERR_INV_SEXP);
94   s++;
95   n = snext (&s);
96   if (!n)
97     return gpg_error (GPG_ERR_INV_SEXP);
98   if (!smatch (&s, n, "enc-val"))
99     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
100   if (*s != '(')
101     return gpg_error (GPG_ERR_UNKNOWN_SEXP);
102   s++;
103   n = snext (&s);
104   if (!n)
105     return gpg_error (GPG_ERR_INV_SEXP);
106   if (smatch (&s, n, "rsa"))
107     {
108       *r_padding = 0;
109       if (*s != '(')
110         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
111       s++;
112       n = snext (&s);
113       if (!n)
114         return gpg_error (GPG_ERR_INV_SEXP);
115       if (!smatch (&s, n, "a"))
116         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
117       n = snext (&s);
118     }
119   else if (smatch (&s, n, "ecdh"))
120     {
121       if (*s != '(')
122         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
123       s++;
124       n = snext (&s);
125       if (!n)
126         return gpg_error (GPG_ERR_INV_SEXP);
127       if (smatch (&s, n, "s"))
128         {
129           n = snext (&s);
130           s += n;
131           if (*s++ != ')')
132             return gpg_error (GPG_ERR_INV_SEXP);
133           if (*s++ != '(')
134             return gpg_error (GPG_ERR_UNKNOWN_SEXP);
135           n = snext (&s);
136           if (!n)
137             return gpg_error (GPG_ERR_INV_SEXP);
138         }
139       if (!smatch (&s, n, "e"))
140         return gpg_error (GPG_ERR_UNKNOWN_SEXP);
141       n = snext (&s);
142     }
143   else
144     return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
145 
146   return agent_tpm2d_pkdecrypt (ctrl, s, n, shadow_info, r_buf, r_len);
147 }
148