]> git.proxmox.com Git - libtpms.git/blame - src/tpm2/crypto/openssl/Helpers.c
tpm12: Use TPM_PrintFourLimit where <= 4 bytes may exist
[libtpms.git] / src / tpm2 / crypto / openssl / Helpers.c
CommitLineData
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
72TPM_RC
73OpenSSLCryptGenerateKeyDes(
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
94evpfunc 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
210BOOL
211OpenSSLEccGetPrivate(
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
243static 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
275LIB_EXPORT const char *
276GetDigestNameByHashAlg(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
287static BOOL
288ComputePrivateExponentD(
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
316LIB_EXPORT TPM_RC
317InitOpenSSLRSAPublicKey(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
361LIB_EXPORT TPM_RC
362InitOpenSSLRSAPrivateKey(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
443LIB_EXPORT TPM_RC
444OpenSSLCryptRsaGenerateKey(
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