aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--crypto/asymmetric_keys/asym_tpm.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/crypto/asymmetric_keys/asym_tpm.c b/crypto/asymmetric_keys/asym_tpm.c
index 6a2d33014ecc..e893b5212222 100644
--- a/crypto/asymmetric_keys/asym_tpm.c
+++ b/crypto/asymmetric_keys/asym_tpm.c
@@ -18,8 +18,10 @@
18 18
19#define TPM_ORD_FLUSHSPECIFIC 186 19#define TPM_ORD_FLUSHSPECIFIC 186
20#define TPM_ORD_LOADKEY2 65 20#define TPM_ORD_LOADKEY2 65
21#define TPM_ORD_UNBIND 30
21#define TPM_LOADKEY2_SIZE 59 22#define TPM_LOADKEY2_SIZE 59
22#define TPM_FLUSHSPECIFIC_SIZE 18 23#define TPM_FLUSHSPECIFIC_SIZE 18
24#define TPM_UNBIND_SIZE 63
23 25
24#define TPM_RT_KEY 0x00000001 26#define TPM_RT_KEY 0x00000001
25 27
@@ -107,6 +109,86 @@ static int tpm_flushspecific(struct tpm_buf *tb, uint32_t handle)
107} 109}
108 110
109/* 111/*
112 * Decrypt a blob provided by userspace using a specific key handle.
113 * The handle is a well known handle or previously loaded by e.g. LoadKey2
114 */
115static int tpm_unbind(struct tpm_buf *tb,
116 uint32_t keyhandle, unsigned char *keyauth,
117 const unsigned char *blob, uint32_t bloblen,
118 void *out, uint32_t outlen)
119{
120 unsigned char nonceodd[TPM_NONCE_SIZE];
121 unsigned char enonce[TPM_NONCE_SIZE];
122 unsigned char authdata[SHA1_DIGEST_SIZE];
123 uint32_t authhandle = 0;
124 unsigned char cont = 0;
125 uint32_t ordinal;
126 uint32_t datalen;
127 int ret;
128
129 ordinal = htonl(TPM_ORD_UNBIND);
130 datalen = htonl(bloblen);
131
132 /* session for loading the key */
133 ret = oiap(tb, &authhandle, enonce);
134 if (ret < 0) {
135 pr_info("oiap failed (%d)\n", ret);
136 return ret;
137 }
138
139 /* generate odd nonce */
140 ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
141 if (ret < 0) {
142 pr_info("tpm_get_random failed (%d)\n", ret);
143 return ret;
144 }
145
146 /* calculate authorization HMAC value */
147 ret = TSS_authhmac(authdata, keyauth, SHA1_DIGEST_SIZE, enonce,
148 nonceodd, cont, sizeof(uint32_t), &ordinal,
149 sizeof(uint32_t), &datalen,
150 bloblen, blob, 0, 0);
151 if (ret < 0)
152 return ret;
153
154 /* build the request buffer */
155 INIT_BUF(tb);
156 store16(tb, TPM_TAG_RQU_AUTH1_COMMAND);
157 store32(tb, TPM_UNBIND_SIZE + bloblen);
158 store32(tb, TPM_ORD_UNBIND);
159 store32(tb, keyhandle);
160 store32(tb, bloblen);
161 storebytes(tb, blob, bloblen);
162 store32(tb, authhandle);
163 storebytes(tb, nonceodd, TPM_NONCE_SIZE);
164 store8(tb, cont);
165 storebytes(tb, authdata, SHA1_DIGEST_SIZE);
166
167 ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
168 if (ret < 0) {
169 pr_info("authhmac failed (%d)\n", ret);
170 return ret;
171 }
172
173 datalen = LOAD32(tb->data, TPM_DATA_OFFSET);
174
175 ret = TSS_checkhmac1(tb->data, ordinal, nonceodd,
176 keyauth, SHA1_DIGEST_SIZE,
177 sizeof(uint32_t), TPM_DATA_OFFSET,
178 datalen, TPM_DATA_OFFSET + sizeof(uint32_t),
179 0, 0);
180 if (ret < 0) {
181 pr_info("TSS_checkhmac1 failed (%d)\n", ret);
182 return ret;
183 }
184
185 memcpy(out, tb->data + TPM_DATA_OFFSET + sizeof(uint32_t),
186 min(outlen, datalen));
187
188 return datalen;
189}
190
191/*
110 * Maximum buffer size for the BER/DER encoded public key. The public key 192 * Maximum buffer size for the BER/DER encoded public key. The public key
111 * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048 193 * is of the form SEQUENCE { INTEGER n, INTEGER e } where n is a maximum 2048
112 * bit key and e is usually 65537 194 * bit key and e is usually 65537