diff options
-rw-r--r-- | crypto/asymmetric_keys/asym_tpm.c | 82 |
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 | */ | ||
115 | static 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 |