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