]>
Commit | Line | Data |
---|---|---|
8de7f334 SB |
1 | /********************************************************************************/ |
2 | /* */ | |
3 | /* OpenSSL helper functions */ | |
4 | /* Written by Stefan Berger */ | |
5 | /* IBM Thomas J. Watson Research Center */ | |
6 | /* */ | |
7 | /* Licenses and Notices */ | |
8 | /* */ | |
9 | /* 1. Copyright Licenses: */ | |
10 | /* */ | |
11 | /* - Trusted Computing Group (TCG) grants to the user of the source code in */ | |
12 | /* this specification (the "Source Code") a worldwide, irrevocable, */ | |
13 | /* nonexclusive, royalty free, copyright license to reproduce, create */ | |
14 | /* derivative works, distribute, display and perform the Source Code and */ | |
15 | /* derivative works thereof, and to grant others the rights granted herein. */ | |
16 | /* */ | |
17 | /* - The TCG grants to the user of the other parts of the specification */ | |
18 | /* (other than the Source Code) the rights to reproduce, distribute, */ | |
19 | /* display, and perform the specification solely for the purpose of */ | |
20 | /* developing products based on such documents. */ | |
21 | /* */ | |
22 | /* 2. Source Code Distribution Conditions: */ | |
23 | /* */ | |
24 | /* - Redistributions of Source Code must retain the above copyright licenses, */ | |
25 | /* this list of conditions and the following disclaimers. */ | |
26 | /* */ | |
27 | /* - Redistributions in binary form must reproduce the above copyright */ | |
28 | /* licenses, this list of conditions and the following disclaimers in the */ | |
29 | /* documentation and/or other materials provided with the distribution. */ | |
30 | /* */ | |
31 | /* 3. Disclaimers: */ | |
32 | /* */ | |
33 | /* - THE COPYRIGHT LICENSES SET FORTH ABOVE DO NOT REPRESENT ANY FORM OF */ | |
34 | /* LICENSE OR WAIVER, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, WITH */ | |
35 | /* RESPECT TO PATENT RIGHTS HELD BY TCG MEMBERS (OR OTHER THIRD PARTIES) */ | |
36 | /* THAT MAY BE NECESSARY TO IMPLEMENT THIS SPECIFICATION OR OTHERWISE. */ | |
37 | /* Contact TCG Administration (admin@trustedcomputinggroup.org) for */ | |
38 | /* information on specification licensing rights available through TCG */ | |
39 | /* membership agreements. */ | |
40 | /* */ | |
41 | /* - THIS SPECIFICATION IS PROVIDED "AS IS" WITH NO EXPRESS OR IMPLIED */ | |
42 | /* WARRANTIES WHATSOEVER, INCLUDING ANY WARRANTY OF MERCHANTABILITY OR */ | |
43 | /* FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, COMPLETENESS, OR */ | |
44 | /* NONINFRINGEMENT OF INTELLECTUAL PROPERTY RIGHTS, OR ANY WARRANTY */ | |
45 | /* OTHERWISE ARISING OUT OF ANY PROPOSAL, SPECIFICATION OR SAMPLE. */ | |
46 | /* */ | |
47 | /* - Without limitation, TCG and its members and licensors disclaim all */ | |
48 | /* liability, including liability for infringement of any proprietary */ | |
49 | /* rights, relating to use of information in this specification and to the */ | |
50 | /* implementation of this specification, and TCG disclaims all liability for */ | |
51 | /* cost of procurement of substitute goods or services, lost profits, loss */ | |
52 | /* of use, loss of data or any incidental, consequential, direct, indirect, */ | |
53 | /* or special damages, whether under contract, tort, warranty or otherwise, */ | |
54 | /* arising in any way out of use or reliance upon this specification or any */ | |
55 | /* information herein. */ | |
56 | /* */ | |
57 | /* (c) Copyright IBM Corp. and others, 2019 */ | |
58 | /* */ | |
59 | /********************************************************************************/ | |
60 | ||
61 | #include "Tpm.h" | |
62 | #include "Helpers_fp.h" | |
afbb3274 | 63 | #include "TpmToOsslMath_fp.h" |
8de7f334 | 64 | |
bc681a1b SB |
65 | #include "config.h" |
66 | ||
8de7f334 | 67 | #include <openssl/evp.h> |
a572dbc4 | 68 | #include <openssl/rsa.h> |
8de7f334 | 69 | |
4e1cd261 | 70 | #if USE_OPENSSL_FUNCTIONS_SYMMETRIC |
8de7f334 | 71 | |
fee2ae97 SB |
72 | TPM_RC |
73 | OpenSSLCryptGenerateKeyDes( | |
74 | TPMT_SENSITIVE *sensitive // OUT: sensitive area | |
75 | ) | |
76 | { | |
77 | DES_cblock *key; | |
78 | size_t offset; | |
79 | size_t limit; | |
80 | ||
81 | limit = MIN(sizeof(sensitive->sensitive.sym.t.buffer), | |
82 | sensitive->sensitive.sym.t.size); | |
83 | limit = TPM2_ROUNDUP(limit, sizeof(*key)); | |
84 | pAssert(limit < sizeof(sensitive->sensitive.sym.t.buffer)); | |
85 | ||
86 | for (offset = 0; offset < limit; offset += sizeof(*key)) { | |
87 | key = (DES_cblock *)&sensitive->sensitive.sym.t.buffer[offset]; | |
88 | if (DES_random_key(key) != 1) | |
89 | return TPM_RC_NO_RESULT; | |
90 | } | |
91 | return TPM_RC_SUCCESS; | |
92 | } | |
93 | ||
8de7f334 SB |
94 | evpfunc GetEVPCipher(TPM_ALG_ID algorithm, // IN |
95 | UINT16 keySizeInBits, // IN | |
96 | TPM_ALG_ID mode, // IN | |
97 | const BYTE *key, // IN | |
98 | BYTE *keyToUse, // OUT same as key or stretched key | |
99 | UINT16 *keyToUseLen // IN/OUT | |
100 | ) | |
101 | { | |
102 | int i; | |
103 | UINT16 keySizeInBytes = keySizeInBits / 8; | |
104 | evpfunc evpfn = NULL; | |
105 | ||
106 | // key size to array index: 128 -> 0, 192 -> 1, 256 -> 2 | |
107 | i = (keySizeInBits >> 6) - 2; | |
108 | if (i < 0 || i > 2) | |
109 | return NULL; | |
110 | ||
111 | pAssert(*keyToUseLen >= keySizeInBytes) | |
112 | memcpy(keyToUse, key, keySizeInBytes); | |
113 | ||
114 | switch (algorithm) { | |
115 | #if ALG_AES | |
116 | case TPM_ALG_AES: | |
117 | *keyToUseLen = keySizeInBytes; | |
118 | switch (mode) { | |
119 | #if ALG_CTR | |
120 | case ALG_CTR_VALUE: | |
121 | evpfn = (evpfunc []){EVP_aes_128_ctr, EVP_aes_192_ctr, | |
122 | EVP_aes_256_ctr}[i]; | |
123 | break; | |
124 | #endif | |
125 | #if ALG_OFB | |
126 | case ALG_OFB_VALUE: | |
127 | evpfn = (evpfunc[]){EVP_aes_128_ofb, EVP_aes_192_ofb, | |
128 | EVP_aes_256_ofb}[i]; | |
129 | break; | |
130 | #endif | |
131 | #if ALG_CBC | |
132 | case ALG_CBC_VALUE: | |
133 | evpfn = (evpfunc[]){EVP_aes_128_cbc, EVP_aes_192_cbc, | |
134 | EVP_aes_256_cbc}[i]; | |
135 | break; | |
136 | #endif | |
137 | #if ALG_CFB | |
138 | case ALG_CFB_VALUE: | |
139 | evpfn = (evpfunc[]){EVP_aes_128_cfb, EVP_aes_192_cfb, | |
140 | EVP_aes_256_cfb}[i]; | |
141 | break; | |
142 | #endif | |
143 | #if ALG_ECB | |
144 | case ALG_ECB_VALUE: | |
145 | evpfn = (evpfunc[]){EVP_aes_128_ecb, EVP_aes_192_ecb, | |
146 | EVP_aes_256_ecb}[i]; | |
147 | break; | |
148 | #endif | |
149 | } | |
150 | break; | |
151 | #endif | |
152 | #if ALG_TDES | |
153 | case TPM_ALG_TDES: | |
154 | if (keySizeInBits == 128) { | |
155 | pAssert(*keyToUseLen >= BITS_TO_BYTES(192)) | |
156 | // stretch the key | |
157 | memcpy(&keyToUse[16], &keyToUse[0], 8); | |
158 | *keyToUseLen = BITS_TO_BYTES(192); | |
159 | } | |
160 | ||
161 | switch (mode) { | |
162 | #if ALG_CTR | |
163 | case ALG_CTR_VALUE: | |
164 | evpfn = (evpfunc[]){EVP_des_ede3, EVP_des_ede3, NULL}[i]; | |
165 | break; | |
166 | #endif | |
167 | #if ALG_OFB | |
168 | case ALG_OFB_VALUE: | |
169 | evpfn = (evpfunc[]){EVP_des_ede3_ofb, EVP_des_ede3_ofb, NULL}[i]; | |
170 | break; | |
171 | #endif | |
172 | #if ALG_CBC | |
173 | case ALG_CBC_VALUE: | |
174 | evpfn = (evpfunc[]){EVP_des_ede3_cbc, EVP_des_ede3_cbc, NULL}[i]; | |
175 | break; | |
176 | #endif | |
177 | #if ALG_CFB | |
178 | case ALG_CFB_VALUE: | |
179 | evpfn = (evpfunc[]){EVP_des_ede3_cfb64, EVP_des_ede3_cfb64, NULL}[i]; | |
180 | break; | |
181 | #endif | |
182 | #if ALG_ECB | |
183 | case ALG_ECB_VALUE: | |
184 | evpfn = (evpfunc[]){EVP_des_ede3_ecb, EVP_des_ede3_ecb, NULL}[i]; | |
185 | break; | |
186 | #endif | |
187 | } | |
188 | #endif | |
189 | #if ALG_SM4 | |
190 | #error Missing implementation of EVP for SM4 | |
191 | case TPM_ALG_SM4: | |
192 | break; | |
193 | #endif | |
194 | #if ALG_CAMELLIA | |
195 | #error Missing implementation of EVP for Camellia | |
196 | case TPM_ALG_CAMELLIA: | |
197 | break; | |
198 | #endif | |
199 | } | |
200 | ||
201 | if (evpfn == NULL) | |
202 | MemorySet(keyToUse, 0, *keyToUseLen); | |
203 | ||
204 | return evpfn; | |
205 | } | |
206 | ||
4e1cd261 | 207 | #endif // USE_OPENSSL_FUNCTIONS_SYMMETRIC |
afbb3274 SB |
208 | |
209 | #if USE_OPENSSL_FUNCTIONS_EC | |
210 | BOOL | |
211 | OpenSSLEccGetPrivate( | |
212 | bigNum dOut, // OUT: the qualified random value | |
213 | const EC_GROUP *G // IN: the EC_GROUP to use | |
214 | ) | |
215 | { | |
216 | BOOL OK = FALSE; | |
217 | const BIGNUM *D; | |
218 | EC_KEY *eckey = EC_KEY_new(); | |
219 | ||
220 | pAssert(G != NULL); | |
221 | ||
222 | if (!eckey) | |
223 | return FALSE; | |
224 | ||
225 | if (EC_KEY_set_group(eckey, G) != 1) | |
226 | goto Exit; | |
227 | ||
228 | if (EC_KEY_generate_key(eckey) == 1) { | |
229 | OK = TRUE; | |
230 | D = EC_KEY_get0_private_key(eckey); | |
231 | OsslToTpmBn(dOut, D); | |
232 | } | |
233 | ||
234 | Exit: | |
235 | EC_KEY_free(eckey); | |
236 | ||
237 | return OK; | |
238 | } | |
239 | #endif // USE_OPENSSL_FUNCTIONS_EC | |
bc681a1b SB |
240 | |
241 | #if USE_OPENSSL_FUNCTIONS_RSA | |
242 | ||
243 | static const struct hnames { | |
244 | const char *name; | |
245 | TPM_ALG_ID hashAlg; | |
246 | } hnames[HASH_COUNT + 1] = { | |
247 | { | |
248 | #if ALG_SHA1 | |
249 | .name = "sha1", | |
250 | .hashAlg = ALG_SHA1_VALUE, | |
251 | }, { | |
252 | #endif | |
253 | #if ALG_SHA256 | |
254 | .name = "sha256", | |
255 | .hashAlg = ALG_SHA256_VALUE, | |
256 | }, { | |
257 | #endif | |
258 | #if ALG_SHA384 | |
259 | .name = "sha384", | |
260 | .hashAlg = ALG_SHA384_VALUE, | |
261 | }, { | |
262 | #endif | |
263 | #if ALG_SHA512 | |
264 | .name = "sha512", | |
265 | .hashAlg = ALG_SHA512_VALUE, | |
266 | }, { | |
267 | #endif | |
268 | .name = NULL, | |
269 | } | |
270 | }; | |
271 | #if HASH_COUNT != ALG_SHA1 + ALG_SHA256 + ALG_SHA384 + ALG_SHA512 | |
272 | # error Missing entry in hnames array! | |
273 | #endif | |
274 | ||
275 | LIB_EXPORT const char * | |
276 | GetDigestNameByHashAlg(const TPM_ALG_ID hashAlg) | |
277 | { | |
278 | unsigned i; | |
279 | ||
280 | for (i = 0; i < HASH_COUNT; i++) { | |
281 | if (hashAlg == hnames[i].hashAlg) | |
282 | return hnames[i].name; | |
283 | } | |
284 | return NULL; | |
285 | } | |
286 | ||
a572dbc4 SB |
287 | static BOOL |
288 | ComputePrivateExponentD( | |
289 | const BIGNUM *P, // IN: first prime (size is 1/2 of bnN) | |
290 | const BIGNUM *Q, // IN: second prime (size is 1/2 of bnN) | |
291 | const BIGNUM *E, // IN: the public exponent | |
292 | const BIGNUM *N, // IN: the public modulus | |
293 | BIGNUM **D // OUT: | |
294 | ) | |
295 | { | |
296 | BOOL pOK = FALSE; | |
297 | BIGNUM *phi; | |
298 | BN_CTX *ctx; | |
299 | // | |
300 | // compute Phi = (p - 1)(q - 1) = pq - p - q + 1 = n - p - q + 1 | |
301 | phi = BN_dup(N); | |
302 | ctx = BN_CTX_new(); | |
303 | if (phi && ctx) { | |
304 | pOK = BN_sub(phi, phi, P); | |
305 | pOK = pOK && BN_sub(phi, phi, Q); | |
306 | pOK = pOK && BN_add_word(phi, 1); | |
307 | // Compute the multiplicative inverse d = 1/e mod Phi | |
308 | pOK = pOK && (*D = BN_mod_inverse(NULL, E, phi, ctx)) != NULL; | |
309 | } | |
310 | BN_CTX_free(ctx); | |
311 | BN_clear_free(phi); | |
312 | ||
313 | return pOK; | |
314 | } | |
315 | ||
316 | LIB_EXPORT TPM_RC | |
317 | InitOpenSSLRSAPublicKey(OBJECT *key, // IN | |
318 | EVP_PKEY **pkey // OUT | |
319 | ) | |
320 | { | |
321 | TPM_RC retVal; | |
322 | RSA *rsakey = RSA_new(); | |
323 | BIGNUM *N = NULL; | |
324 | BIGNUM *E = BN_new(); | |
325 | BN_ULONG eval; | |
326 | ||
327 | *pkey = EVP_PKEY_new(); | |
328 | ||
329 | if (rsakey == NULL || *pkey == NULL || E == NULL) | |
330 | ERROR_RETURN(TPM_RC_FAILURE); | |
331 | ||
332 | if(key->publicArea.parameters.rsaDetail.exponent != 0) | |
333 | eval = key->publicArea.parameters.rsaDetail.exponent; | |
334 | else | |
335 | eval = RSA_DEFAULT_PUBLIC_EXPONENT; | |
336 | ||
337 | if (BN_set_word(E, eval) != 1) | |
338 | ERROR_RETURN(TPM_RC_FAILURE); | |
339 | ||
340 | N = BN_bin2bn(key->publicArea.unique.rsa.b.buffer, | |
341 | key->publicArea.unique.rsa.b.size, NULL); | |
342 | if (N == NULL || | |
343 | RSA_set0_key(rsakey, N, E, NULL) != 1 || | |
344 | EVP_PKEY_assign_RSA(*pkey, rsakey) == 0) | |
345 | ERROR_RETURN(TPM_RC_FAILURE) | |
346 | ||
347 | RSA_set_flags(rsakey, RSA_FLAG_NO_BLINDING); | |
348 | ||
349 | retVal = TPM_RC_SUCCESS; | |
350 | ||
351 | Exit: | |
352 | if (retVal != TPM_RC_SUCCESS) { | |
353 | RSA_free(rsakey); | |
354 | EVP_PKEY_free(*pkey); | |
355 | *pkey = NULL; | |
356 | } | |
357 | ||
358 | return retVal; | |
359 | } | |
360 | ||
361 | LIB_EXPORT TPM_RC | |
362 | InitOpenSSLRSAPrivateKey(OBJECT *rsaKey, // IN | |
363 | EVP_PKEY **pkey // OUT | |
364 | ) | |
365 | { | |
366 | const BIGNUM *N = NULL; | |
367 | const BIGNUM *E = NULL; | |
368 | BIGNUM *P = NULL; | |
369 | BIGNUM *Q = NULL; | |
370 | BIGNUM *Qr = NULL; | |
371 | BIGNUM *D = NULL; | |
372 | #if CRT_FORMAT_RSA == YES | |
373 | BIGNUM *dP = NULL; | |
374 | BIGNUM *dQ = NULL; | |
375 | BIGNUM *qInv = NULL; | |
376 | #endif | |
377 | RSA *key; | |
378 | BN_CTX *ctx = NULL; | |
379 | TPM_RC retVal = InitOpenSSLRSAPublicKey(rsaKey, pkey); | |
380 | ||
381 | if (retVal != TPM_RC_SUCCESS) | |
382 | return retVal; | |
383 | ||
384 | if(!rsaKey->attributes.privateExp) | |
385 | CryptRsaLoadPrivateExponent(rsaKey); | |
386 | ||
387 | ctx = BN_CTX_new(); | |
388 | Q = BN_new(); | |
389 | Qr = BN_new(); | |
390 | P = BN_bin2bn(rsaKey->sensitive.sensitive.rsa.t.buffer, | |
391 | rsaKey->sensitive.sensitive.rsa.t.size, NULL); | |
392 | if (ctx == NULL || Q == NULL || Qr == NULL || P == NULL) | |
393 | ERROR_RETURN(TPM_RC_FAILURE) | |
394 | ||
395 | key = EVP_PKEY_get0_RSA(*pkey); | |
396 | if (key == NULL) | |
397 | ERROR_RETURN(TPM_RC_FAILURE); | |
398 | RSA_get0_key(key, &N, &E, NULL); | |
399 | ||
400 | /* Q = N/P; no remainder */ | |
401 | BN_div(Q, Qr, N, P, ctx); | |
402 | if(!BN_is_zero(Qr)) | |
403 | ERROR_RETURN(TPM_RC_BINDING); | |
404 | ||
405 | // TODO(stefanb): consider caching D in the OBJECT | |
406 | if (ComputePrivateExponentD(P, Q, E, N, &D) == FALSE || | |
407 | RSA_set0_key(key, NULL, NULL, D) != 1) | |
408 | ERROR_RETURN(TPM_RC_FAILURE); | |
409 | D = NULL; | |
410 | ||
411 | #if CRT_FORMAT_RSA == YES | |
412 | /* CRT parameters are not absolutely needed but may speed up ops */ | |
413 | dP = BigInitialized((bigConst)&rsaKey->privateExponent.dP); | |
414 | dQ = BigInitialized((bigConst)&rsaKey->privateExponent.dQ); | |
415 | qInv = BigInitialized((bigConst)&rsaKey->privateExponent.qInv); | |
416 | if (dP == NULL || dQ == NULL || qInv == NULL || | |
417 | RSA_set0_crt_params(key, dP, dQ, qInv) != 1) | |
418 | ERROR_RETURN(TPM_RC_FAILURE); | |
419 | #endif | |
420 | ||
421 | retVal = TPM_RC_SUCCESS; | |
422 | ||
423 | Exit: | |
424 | BN_CTX_free(ctx); | |
425 | BN_clear_free(P); | |
426 | BN_clear_free(Q); | |
427 | BN_free(Qr); | |
428 | ||
429 | if (retVal != TPM_RC_SUCCESS) { | |
430 | BN_clear_free(D); | |
431 | #if CRT_FORMAT_RSA == YES | |
432 | BN_clear_free(dP); | |
433 | BN_clear_free(dQ); | |
434 | BN_clear_free(qInv); | |
435 | #endif | |
436 | EVP_PKEY_free(*pkey); | |
437 | *pkey = NULL; | |
438 | } | |
439 | ||
440 | return retVal; | |
441 | } | |
442 | ||
6ae0d8c5 SB |
443 | LIB_EXPORT TPM_RC |
444 | OpenSSLCryptRsaGenerateKey( | |
445 | OBJECT *rsaKey, // IN/OUT: The object structure in which | |
446 | // the key is created. | |
447 | UINT32 e, | |
448 | int keySizeInBits | |
449 | ) | |
450 | { | |
451 | TPMT_PUBLIC *publicArea = &rsaKey->publicArea; | |
452 | TPMT_SENSITIVE *sensitive = &rsaKey->sensitive; | |
453 | TPM_RC retVal = TPM_RC_SUCCESS; | |
454 | int rc; | |
455 | RSA *rsa = NULL; | |
456 | const BIGNUM *bnP = NULL; | |
457 | const BIGNUM *bnN = NULL; | |
458 | BIGNUM *bnE = BN_new(); | |
459 | BN_RSA(tmp); | |
460 | ||
461 | if (bnE == NULL || BN_set_word(bnE, e) != 1) | |
462 | ERROR_RETURN(TPM_RC_FAILURE); | |
463 | ||
464 | // Need to initialize the privateExponent structure | |
465 | RsaInitializeExponent(&rsaKey->privateExponent); | |
466 | ||
467 | rsa = RSA_new(); | |
468 | if (rsa == NULL) | |
469 | ERROR_RETURN(TPM_RC_FAILURE); | |
470 | ||
471 | rc = RSA_generate_key_ex(rsa, keySizeInBits, bnE, NULL); | |
472 | if (rc == 0) | |
473 | ERROR_RETURN(TPM_RC_NO_RESULT); | |
474 | ||
475 | RSA_get0_key(rsa, &bnN, NULL, NULL); | |
476 | RSA_get0_factors(rsa, &bnP, NULL); | |
477 | ||
478 | OsslToTpmBn(tmp, bnN); | |
479 | BnTo2B((bigNum)tmp, &publicArea->unique.rsa.b, 0); | |
480 | ||
481 | OsslToTpmBn(tmp, bnP); | |
482 | BnTo2B((bigNum)tmp, &sensitive->sensitive.rsa.b, 0); | |
483 | ||
484 | // CryptRsaGenerateKey calls ComputePrivateExponent; we have to call | |
485 | // it via CryptRsaLoadPrivateExponent | |
486 | retVal = CryptRsaLoadPrivateExponent(rsaKey); | |
487 | ||
488 | Exit: | |
489 | BN_free(bnE); | |
490 | RSA_free(rsa); | |
491 | ||
492 | return retVal; | |
493 | } | |
494 | ||
bc681a1b | 495 | #endif // USE_OPENSSL_FUNCTIONS_RSA |