1 /********************************************************************************/
2 /* */
3 /* OpenSSL Crypto Utilities */
4 /* Written by Ken Goldman */
5 /* IBM Thomas J. Watson Research Center */
6 /* */
7 /* (c) Copyright IBM Corporation 2018 - 2020. */
8 /* */
9 /* All rights reserved. */
10 /* */
11 /* Redistribution and use in source and binary forms, with or without */
12 /* modification, are permitted provided that the following conditions are */
13 /* met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright notice, */
16 /* this list of conditions and the following disclaimer. */
17 /* */
18 /* Redistributions in binary form must reproduce the above copyright */
19 /* notice, this list of conditions and the following disclaimer in the */
20 /* documentation and/or other materials provided with the distribution. */
21 /* */
22 /* Neither the names of the IBM Corporation nor the names of its */
23 /* contributors may be used to endorse or promote products derived from */
24 /* this software without specific prior written permission. */
25 /* */
26 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
27 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
28 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR */
29 /* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
30 /* HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
31 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
32 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, */
33 /* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY */
34 /* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT */
35 /* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE */
36 /* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
37 /********************************************************************************/
38
39 /* These functions are worthwhile sample code that probably (judgment call) do not belong in the TSS
40 library.
41
42 They abstract out crypto library functions.
43
44 They show how to convert public or private EC or RSA among PEM format <-> EVP format <-> EC_KEY
45 or RSA format <-> binary arrays <-> TPM format TPM2B_PRIVATE, TPM2B_SENSITIVE, TPM2B_PUBLIC
46 usable for loadexternal or import.
47
48 There are functions to convert public keys from TPM <-> RSA, ECC <-> PEM, and to verify a TPM
49 signature using a PEM format public key.
50 */
51
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <string.h>
55 #include <stdint.h>
56 #include <limits.h>
57
58 #ifndef TPM_TSS_NORSA
59 #include <openssl/rsa.h>
60 #endif /* TPM_TSS_NORSA */
61 #include <openssl/objects.h>
62 #include <openssl/evp.h>
63 #include <openssl/pem.h>
64
65 #ifndef TPM_TSS_NOECC
66 #include <openssl/ec.h>
67 #endif
68
69 #ifndef TPM_TSS_NOFILE
70 #include <ibmtss/tssfile.h>
71 #endif
72 #include <ibmtss/tssutils.h>
73 #include <ibmtss/tssmarshal.h>
74 #include <ibmtss/tsscrypto.h>
75 #include <ibmtss/tsscryptoh.h>
76 #include <ibmtss/Implementation.h>
77
78 #include "objecttemplates.h"
79 #include "cryptoutils.h"
80
81 /* verbose tracing flag shared by command line utilities */
82
83 int tssUtilsVerbose;
84
85 /* openssl compatibility functions, during the transition from 1.0.1, 1.0.2, 1.1.0, 1.1.1. Some
86 structures were made opaque, with gettters and setters. Some parameters were made const. Some
87 function names changed. */
88
89 /* Some functions add const to parameters as of openssl 1.1.0 */
90
91 /* These functions are only required for OpenSSL 1.0. OpenSSL 1.1 has them, and the structures are
92 opaque. */
93
94 #if OPENSSL_VERSION_NUMBER < 0x10100000
95
ECDSA_SIG_set0(ECDSA_SIG * sig,BIGNUM * r,BIGNUM * s)96 int ECDSA_SIG_set0(ECDSA_SIG *sig, BIGNUM *r, BIGNUM *s)
97 {
98 if (r == NULL || s == NULL)
99 return 0;
100 BN_clear_free(sig->r);
101 BN_clear_free(sig->s);
102 sig->r = r;
103 sig->s = s;
104 return 1;
105 }
106
ECDSA_SIG_get0(const ECDSA_SIG * sig,const BIGNUM ** pr,const BIGNUM ** ps)107 void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
108 {
109 if (pr != NULL) {
110 *pr = sig->r;
111 }
112 if (ps != NULL) {
113 *ps = sig->s;
114 }
115 return;
116 }
117
X509_get0_tbs_sigalg(const X509 * x)118 const X509_ALGOR *X509_get0_tbs_sigalg(const X509 *x)
119 {
120 return x->cert_info->signature;
121 }
122
RSA_get0_key(const RSA * rsaKey,const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d)123 void RSA_get0_key(const RSA *rsaKey,
124 const BIGNUM **n,
125 const BIGNUM **e,
126 const BIGNUM **d)
127 {
128 if (n != NULL) {
129 *n = rsaKey->n;
130 }
131 if (e != NULL) {
132 *e = rsaKey->e;
133 }
134 if (d != NULL) {
135 *d = rsaKey->d;
136 }
137 return;
138 }
139
RSA_get0_factors(const RSA * rsaKey,const BIGNUM ** p,const BIGNUM ** q)140 void RSA_get0_factors(const RSA *rsaKey,
141 const BIGNUM **p,
142 const BIGNUM **q)
143 {
144 if (p != NULL) {
145 *p = rsaKey->p;
146 }
147 if (q != NULL) {
148 *q = rsaKey->q;
149 }
150 return;
151 }
152
153 #endif /* pre openssl 1.1 */
154
155 /* These functions are only required for OpenSSL 1.0.1 OpenSSL 1.0.2 has them, and the structures
156 are opaque. In 1.1.0, the parameters became const. */
157
158 #if OPENSSL_VERSION_NUMBER < 0x10002000
159
X509_get0_signature(OSSLCONST ASN1_BIT_STRING ** psig,OSSLCONST X509_ALGOR ** palg,const X509 * x)160 void X509_get0_signature(OSSLCONST ASN1_BIT_STRING **psig,
161 OSSLCONST X509_ALGOR **palg, const X509 *x)
162 {
163 *psig = x->signature;
164 *palg = x->sig_alg;
165 return;
166 }
167
168 #endif /* pre openssl 1.0.2 */
169
170 #ifndef TPM_TSS_NOFILE
171
172 /* getCryptoLibrary() returns a string indicating the underlying crypto library.
173
174 It can be used for programs that must account for library differences.
175 */
176
getCryptoLibrary(const char ** name)177 void getCryptoLibrary(const char **name)
178 {
179 *name = "openssl";
180 return;
181 }
182
183 /* convertPemToEvpPrivKey() converts a PEM key file to an openssl EVP_PKEY key pair */
184
convertPemToEvpPrivKey(EVP_PKEY ** evpPkey,const char * pemKeyFilename,const char * password)185 TPM_RC convertPemToEvpPrivKey(EVP_PKEY **evpPkey, /* freed by caller */
186 const char *pemKeyFilename,
187 const char *password)
188 {
189 TPM_RC rc = 0;
190 FILE *pemKeyFile = NULL;
191
192 if (rc == 0) {
193 rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @2 */
194 }
195 if (rc == 0) {
196 *evpPkey = PEM_read_PrivateKey(pemKeyFile, NULL, NULL, (void *)password);
197 if (*evpPkey == NULL) {
198 printf("convertPemToEvpPrivKey: Error reading key file %s\n", pemKeyFilename);
199 rc = EXIT_FAILURE;
200 }
201 }
202 if (pemKeyFile != NULL) {
203 fclose(pemKeyFile); /* @2 */
204 }
205 return rc;
206 }
207
208 #endif /* TPM_TSS_NOFILE */
209
210 #ifndef TPM_TSS_NOFILE
211
212 /* convertPemToEvpPubKey() converts a PEM public key file to an openssl EVP_PKEY public key */
213
convertPemToEvpPubKey(EVP_PKEY ** evpPkey,const char * pemKeyFilename)214 TPM_RC convertPemToEvpPubKey(EVP_PKEY **evpPkey, /* freed by caller */
215 const char *pemKeyFilename)
216 {
217 TPM_RC rc = 0;
218 FILE *pemKeyFile = NULL;
219
220 if (rc == 0) {
221 rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @2 */
222 }
223 if (rc == 0) {
224 *evpPkey = PEM_read_PUBKEY(pemKeyFile, NULL, NULL, NULL);
225 if (*evpPkey == NULL) {
226 printf("convertPemToEvpPubKey: Error reading key file %s\n", pemKeyFilename);
227 rc = EXIT_FAILURE;
228 }
229 }
230 if (pemKeyFile != NULL) {
231 fclose(pemKeyFile); /* @2 */
232 }
233 return rc;
234 }
235
236 #endif /* TPM_TSS_NOFILE */
237
238 #ifndef TPM_TSS_NOFILE
239
240 /* convertPemToRsaPrivKey() converts a PEM format keypair file to a library specific RSA key
241 token.
242
243 The return is void because the structure is opaque to the caller. This accomodates other crypto
244 libraries.
245
246 rsaKey is an RSA structure
247 */
248
convertPemToRsaPrivKey(void ** rsaKey,const char * pemKeyFilename,const char * password)249 TPM_RC convertPemToRsaPrivKey(void **rsaKey, /* freed by caller */
250 const char *pemKeyFilename,
251 const char *password)
252 {
253 TPM_RC rc = 0;
254 FILE *pemKeyFile = NULL;
255
256 if (rc == 0) {
257 rc = TSS_File_Open(&pemKeyFile, pemKeyFilename, "rb"); /* closed @1 */
258 }
259 if (rc == 0) {
260 *rsaKey = (void *)PEM_read_RSAPrivateKey(pemKeyFile, NULL, NULL, (void *)password);
261 if (*rsaKey == NULL) {
262 printf("convertPemToRsaPrivKey: Error in OpenSSL PEM_read_RSAPrivateKey()\n");
263 rc = EXIT_FAILURE;
264 }
265 }
266 if (pemKeyFile != NULL) {
267 fclose(pemKeyFile); /* @1 */
268 }
269 return rc;
270 }
271
272 #endif /* TPM_TSS_NOFILE */
273
274 #ifndef TPM_TSS_NOECC
275
276 /* convertEvpPkeyToEckey retrieves the EC_KEY key token from the EVP_PKEY */
277
convertEvpPkeyToEckey(EC_KEY ** ecKey,EVP_PKEY * evpPkey)278 TPM_RC convertEvpPkeyToEckey(EC_KEY **ecKey, /* freed by caller */
279 EVP_PKEY *evpPkey)
280 {
281 TPM_RC rc = 0;
282
283 if (rc == 0) {
284 *ecKey = EVP_PKEY_get1_EC_KEY(evpPkey);
285 if (*ecKey == NULL) {
286 printf("convertEvpPkeyToEckey: Error extracting EC key from EVP_PKEY\n");
287 rc = EXIT_FAILURE;
288 }
289 }
290 return rc;
291 }
292
293 #endif /* TPM_TSS_NOECC */
294
295 /* convertEvpPkeyToRsakey() retrieves the RSA key token from the EVP_PKEY */
296
convertEvpPkeyToRsakey(RSA ** rsaKey,EVP_PKEY * evpPkey)297 TPM_RC convertEvpPkeyToRsakey(RSA **rsaKey, /* freed by caller */
298 EVP_PKEY *evpPkey)
299 {
300 TPM_RC rc = 0;
301
302 if (rc == 0) {
303 *rsaKey = EVP_PKEY_get1_RSA(evpPkey);
304 if (*rsaKey == NULL) {
305 printf("convertEvpPkeyToRsakey: EVP_PKEY_get1_RSA failed\n");
306 rc = EXIT_FAILURE;
307 }
308 }
309 return rc;
310 }
311
312 #ifndef TPM_TSS_NOECC
313
314 /* convertEcKeyToPrivateKeyBin() converts an OpenSSL EC_KEY to a binary array
315
316 FIXME Only supports NIST P256 curve.
317 */
318
convertEcKeyToPrivateKeyBin(int * privateKeyBytes,uint8_t ** privateKeyBin,const EC_KEY * ecKey)319 TPM_RC convertEcKeyToPrivateKeyBin(int *privateKeyBytes,
320 uint8_t **privateKeyBin, /* freed by caller */
321 const EC_KEY *ecKey)
322 {
323 TPM_RC rc = 0;
324 const EC_GROUP *ecGroup = NULL;
325 int nid;
326 const BIGNUM *privateKeyBn = NULL;
327 int bnBytes;
328
329 /* get the group from the key */
330 if (rc == 0) {
331 ecGroup = EC_KEY_get0_group(ecKey);
332 if (ecGroup == NULL) {
333 printf("convertEcKeyToPrivateKeyBin: Error extracting EC group from EC key\n");
334 rc = TSS_RC_EC_KEY_CONVERT;
335 }
336 }
337 /* and then the curve from the group */
338 if (rc == 0) {
339 nid = EC_GROUP_get_curve_name(ecGroup);
340 /* map NID to size of private key */
341 switch (nid) {
342 case NID_X9_62_prime256v1:
343 *privateKeyBytes = 32;
344 break;
345 default:
346 printf("convertEcKeyToPrivateKeyBin: Error, curve NID %u not supported\n", nid);
347 rc = TSS_RC_EC_KEY_CONVERT;
348 }
349 }
350 /* get the ECC private key as a BIGNUM from the EC_KEY */
351 if (rc == 0) {
352 privateKeyBn = EC_KEY_get0_private_key(ecKey);
353 }
354 /* sanity check the BN size against the curve */
355 if (rc == 0) {
356 bnBytes = BN_num_bytes(privateKeyBn);
357 if (bnBytes > *privateKeyBytes) {
358 printf("convertEcKeyToPrivateKeyBin: Error, private key %d bytes too large for curve\n",
359 bnBytes);
360 rc = TSS_RC_EC_KEY_CONVERT;
361 }
362 }
363 /* allocate a buffer for the private key array based on the curve */
364 if (rc == 0) {
365 rc = TSS_Malloc(privateKeyBin, *privateKeyBytes);
366 }
367 /* convert the private key bignum to binary */
368 if (rc == 0) {
369 /* TPM rev 116 required the ECC private key to be zero padded in the duplicate parameter of
370 import */
371 memset(*privateKeyBin, 0, *privateKeyBytes - bnBytes);
372 BN_bn2bin(privateKeyBn, (*privateKeyBin) + (*privateKeyBytes - bnBytes));
373 if (tssUtilsVerbose) TSS_PrintAll("convertEcKeyToPrivateKeyBin:", *privateKeyBin, *privateKeyBytes);
374 }
375 return rc;
376 }
377
378 #endif /* TPM_TSS_NOECC */
379
380 /* convertRsaKeyToPrivateKeyBin() converts an OpenSSL RSA key token private prime p to a binary
381 array */
382
convertRsaKeyToPrivateKeyBin(int * privateKeyBytes,uint8_t ** privateKeyBin,const RSA * rsaKey)383 TPM_RC convertRsaKeyToPrivateKeyBin(int *privateKeyBytes,
384 uint8_t **privateKeyBin, /* freed by caller */
385 const RSA *rsaKey)
386 {
387 TPM_RC rc = 0;
388 const BIGNUM *p = NULL;
389 const BIGNUM *q;
390
391 /* get the private primes */
392 if (rc == 0) {
393 rc = getRsaKeyParts(NULL, NULL, NULL, &p, &q, rsaKey);
394 }
395 /* allocate a buffer for the private key array */
396 if (rc == 0) {
397 *privateKeyBytes = BN_num_bytes(p);
398 rc = TSS_Malloc(privateKeyBin, *privateKeyBytes);
399 }
400 /* convert the private key bignum to binary */
401 if (rc == 0) {
402 BN_bn2bin(p, *privateKeyBin);
403 }
404 return rc;
405 }
406
407
408 #ifndef TPM_TSS_NOECC
409
410 /* convertEcKeyToPublicKeyBin() converts an OpenSSL EC_KEY public key token to a binary array */
411
convertEcKeyToPublicKeyBin(int * modulusBytes,uint8_t ** modulusBin,const EC_KEY * ecKey)412 TPM_RC convertEcKeyToPublicKeyBin(int *modulusBytes,
413 uint8_t **modulusBin, /* freed by caller */
414 const EC_KEY *ecKey)
415 {
416 TPM_RC rc = 0;
417 const EC_POINT *ecPoint = NULL;
418 const EC_GROUP *ecGroup = NULL;
419
420 if (rc == 0) {
421 ecPoint = EC_KEY_get0_public_key(ecKey);
422 if (ecPoint == NULL) {
423 printf("convertEcKeyToPublicKeyBin: Error extracting EC point from EC public key\n");
424 rc = TSS_RC_EC_KEY_CONVERT;
425 }
426 }
427 if (rc == 0) {
428 ecGroup = EC_KEY_get0_group(ecKey);
429 if (ecGroup == NULL) {
430 printf("convertEcKeyToPublicKeyBin: Error extracting EC group from EC public key\n");
431 rc = TSS_RC_EC_KEY_CONVERT;
432 }
433 }
434 /* get the public modulus */
435 if (rc == 0) {
436 *modulusBytes = EC_POINT_point2oct(ecGroup, ecPoint,
437 POINT_CONVERSION_UNCOMPRESSED,
438 NULL, 0, NULL);
439 }
440 if (rc == 0) {
441 rc = TSS_Malloc(modulusBin, *modulusBytes);
442 }
443 if (rc == 0) {
444 EC_POINT_point2oct(ecGroup, ecPoint,
445 POINT_CONVERSION_UNCOMPRESSED,
446 *modulusBin, *modulusBytes, NULL);
447 if (tssUtilsVerbose) TSS_PrintAll("convertEcKeyToPublicKeyBin:", *modulusBin, *modulusBytes);
448 }
449 return rc;
450 }
451
452 #endif /* TPM_TSS_NOECC */
453
454 /* convertRsaKeyToPublicKeyBin() converts from an openssl RSA key token to a public modulus */
455
convertRsaKeyToPublicKeyBin(int * modulusBytes,uint8_t ** modulusBin,void * rsaKey)456 TPM_RC convertRsaKeyToPublicKeyBin(int *modulusBytes,
457 uint8_t **modulusBin, /* freed by caller */
458 void *rsaKey)
459 {
460 TPM_RC rc = 0;
461 const BIGNUM *n = NULL;
462 const BIGNUM *e;
463 const BIGNUM *d;
464
465 /* get the public modulus from the RSA key token */
466 if (rc == 0) {
467 rc = getRsaKeyParts(&n, &e, &d, NULL, NULL, rsaKey);
468 }
469 if (rc == 0) {
470 *modulusBytes = BN_num_bytes(n);
471 }
472 if (rc == 0) {
473 rc = TSS_Malloc(modulusBin, *modulusBytes);
474 }
475 if (rc == 0) {
476 BN_bn2bin(n, *modulusBin);
477 }
478 return rc;
479 }
480
481 #ifdef TPM_TPM20
482
483 #ifndef TPM_TSS_NOECC
484
485 /* convertEcPrivateKeyBinToPrivate() converts an EC 'privateKeyBin' to either a
486 TPM2B_PRIVATE or a TPM2B_SENSITIVE
487
488 */
489
convertEcPrivateKeyBinToPrivate(TPM2B_PRIVATE * objectPrivate,TPM2B_SENSITIVE * objectSensitive,int privateKeyBytes,uint8_t * privateKeyBin,const char * password)490 TPM_RC convertEcPrivateKeyBinToPrivate(TPM2B_PRIVATE *objectPrivate,
491 TPM2B_SENSITIVE *objectSensitive,
492 int privateKeyBytes,
493 uint8_t *privateKeyBin,
494 const char *password)
495 {
496 TPM_RC rc = 0;
497 TPMT_SENSITIVE tSensitive;
498 TPM2B_SENSITIVE bSensitive;
499
500 if (rc == 0) {
501 if (((objectPrivate == NULL) && (objectSensitive == NULL)) ||
502 ((objectPrivate != NULL) && (objectSensitive != NULL))) {
503 printf("convertEcPrivateKeyBinToPrivate: Only one result supported\n");
504 rc = EXIT_FAILURE;
505 }
506 }
507 /* In some cases, the sensitive data is not encrypted and the integrity value is not present.
508 When an integrity value is not needed, it is not present and it is not represented by an
509 Empty Buffer.
510
511 In this case, the TPM2B_PRIVATE will just be a marshaled TPM2B_SENSITIVE, which is a
512 marshaled TPMT_SENSITIVE */
513
514 /* construct TPMT_SENSITIVE */
515 if (rc == 0) {
516 /* This shall be the same as the type parameter of the associated public area. */
517 tSensitive.sensitiveType = TPM_ALG_ECC;
518 tSensitive.seedValue.b.size = 0;
519 /* key password converted to TPM2B */
520 rc = TSS_TPM2B_StringCopy(&tSensitive.authValue.b, password,
521 sizeof(tSensitive.authValue.t.buffer));
522 }
523 if (rc == 0) {
524 if (privateKeyBytes > 32) { /* hard code NISTP256 */
525 printf("convertEcPrivateKeyBinToPrivate: Error, private key size %u not 32\n",
526 privateKeyBytes);
527 rc = EXIT_FAILURE;
528 }
529 }
530 if (rc == 0) {
531 tSensitive.sensitive.ecc.t.size = privateKeyBytes;
532 memcpy(tSensitive.sensitive.ecc.t.buffer, privateKeyBin, privateKeyBytes);
533 }
534 /* FIXME common code for EC and RSA */
535 /* marshal the TPMT_SENSITIVE into a TPM2B_SENSITIVE */
536 if (rc == 0) {
537 if (objectPrivate != NULL) {
538 uint32_t size = sizeof(bSensitive.t.sensitiveArea); /* max size */
539 uint8_t *buffer = bSensitive.b.buffer; /* pointer that can move */
540 bSensitive.t.size = 0; /* required before marshaling */
541 rc = TSS_TPMT_SENSITIVE_Marshalu(&tSensitive,
542 &bSensitive.b.size, /* marshaled size */
543 &buffer, /* marshal here */
544 &size); /* max size */
545 }
546 else { /* return TPM2B_SENSITIVE */
547 objectSensitive->t.sensitiveArea = tSensitive;
548 }
549 }
550 /* marshal the TPM2B_SENSITIVE (as a TPM2B_PRIVATE, see above) into a TPM2B_PRIVATE */
551 if (rc == 0) {
552 if (objectPrivate != NULL) {
553 uint32_t size = sizeof(objectPrivate->t.buffer); /* max size */
554 uint8_t *buffer = objectPrivate->t.buffer; /* pointer that can move */
555 objectPrivate->t.size = 0; /* required before marshaling */
556 rc = TSS_TPM2B_PRIVATE_Marshalu((TPM2B_PRIVATE *)&bSensitive,
557 &objectPrivate->t.size, /* marshaled size */
558 &buffer, /* marshal here */
559 &size); /* max size */
560 }
561 }
562 return rc;
563 }
564
565 #endif /* TPM_TSS_NOECC */
566 #endif /* TPM_TPM20 */
567
568 #ifdef TPM_TPM20
569
570 /* convertRsaPrivateKeyBinToPrivate() converts an RSA prime 'privateKeyBin' to either a
571 TPM2B_PRIVATE or a TPM2B_SENSITIVE
572
573 */
574
convertRsaPrivateKeyBinToPrivate(TPM2B_PRIVATE * objectPrivate,TPM2B_SENSITIVE * objectSensitive,int privateKeyBytes,uint8_t * privateKeyBin,const char * password)575 TPM_RC convertRsaPrivateKeyBinToPrivate(TPM2B_PRIVATE *objectPrivate,
576 TPM2B_SENSITIVE *objectSensitive,
577 int privateKeyBytes,
578 uint8_t *privateKeyBin,
579 const char *password)
580 {
581 TPM_RC rc = 0;
582 TPMT_SENSITIVE tSensitive;
583 TPM2B_SENSITIVE bSensitive;
584
585 if (rc == 0) {
586 if (((objectPrivate == NULL) && (objectSensitive == NULL)) ||
587 ((objectPrivate != NULL) && (objectSensitive != NULL))) {
588 printf("convertRsaPrivateKeyBinToPrivate: Only one result supported\n");
589 rc = EXIT_FAILURE;
590 }
591 }
592 /* In some cases, the sensitive data is not encrypted and the integrity value is not present.
593 When an integrity value is not needed, it is not present and it is not represented by an
594 Empty Buffer.
595
596 In this case, the TPM2B_PRIVATE will just be a marshaled TPM2B_SENSITIVE, which is a
597 marshaled TPMT_SENSITIVE */
598
599 /* construct TPMT_SENSITIVE */
600 if (rc == 0) {
601 /* This shall be the same as the type parameter of the associated public area. */
602 tSensitive.sensitiveType = TPM_ALG_RSA;
603 /* generate a seed for storage keys */
604 tSensitive.seedValue.b.size = 32; /* FIXME hard coded seed length */
605 rc = TSS_RandBytes(tSensitive.seedValue.b.buffer, tSensitive.seedValue.b.size);
606 }
607 /* key password converted to TPM2B */
608 if (rc == 0) {
609 rc = TSS_TPM2B_StringCopy(&tSensitive.authValue.b, password,
610 sizeof(tSensitive.authValue.t.buffer));
611 }
612 if (rc == 0) {
613 if ((size_t)privateKeyBytes > sizeof(tSensitive.sensitive.rsa.t.buffer)) {
614 printf("convertRsaPrivateKeyBinToPrivate: "
615 "Error, private key modulus %d greater than %lu\n",
616 privateKeyBytes, (unsigned long)sizeof(tSensitive.sensitive.rsa.t.buffer));
617 rc = EXIT_FAILURE;
618 }
619 }
620 if (rc == 0) {
621 tSensitive.sensitive.rsa.t.size = privateKeyBytes;
622 memcpy(tSensitive.sensitive.rsa.t.buffer, privateKeyBin, privateKeyBytes);
623 }
624 /* FIXME common code for EC and RSA */
625 /* marshal the TPMT_SENSITIVE into a TPM2B_SENSITIVE */
626 if (rc == 0) {
627 if (objectPrivate != NULL) {
628 uint32_t size = sizeof(bSensitive.t.sensitiveArea); /* max size */
629 uint8_t *buffer = bSensitive.b.buffer; /* pointer that can move */
630 bSensitive.t.size = 0; /* required before marshaling */
631 rc = TSS_TPMT_SENSITIVE_Marshalu(&tSensitive,
632 &bSensitive.b.size, /* marshaled size */
633 &buffer, /* marshal here */
634 &size); /* max size */
635 }
636 else { /* return TPM2B_SENSITIVE */
637 objectSensitive->t.sensitiveArea = tSensitive;
638 }
639 }
640 /* marshal the TPM2B_SENSITIVE (as a TPM2B_PRIVATE, see above) into a TPM2B_PRIVATE */
641 if (rc == 0) {
642 if (objectPrivate != NULL) {
643 uint32_t size = sizeof(objectPrivate->t.buffer); /* max size */
644 uint8_t *buffer = objectPrivate->t.buffer; /* pointer that can move */
645 objectPrivate->t.size = 0; /* required before marshaling */
646 rc = TSS_TPM2B_PRIVATE_Marshalu((TPM2B_PRIVATE *)&bSensitive,
647 &objectPrivate->t.size, /* marshaled size */
648 &buffer, /* marshal here */
649 &size); /* max size */
650 }
651 }
652 return rc;
653 }
654
655 #endif /* TPM_TPM20 */
656
657 #ifndef TPM_TSS_NOECC
658
659 /* convertEcPublicKeyBinToPublic() converts an EC modulus and other parameters to a TPM2B_PUBLIC
660
661 FIXME Only supports NIST P256 curve.
662 */
663
convertEcPublicKeyBinToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,TPMI_ECC_CURVE curveID,int modulusBytes,uint8_t * modulusBin)664 TPM_RC convertEcPublicKeyBinToPublic(TPM2B_PUBLIC *objectPublic,
665 int keyType,
666 TPMI_ALG_SIG_SCHEME scheme,
667 TPMI_ALG_HASH nalg,
668 TPMI_ALG_HASH halg,
669 TPMI_ECC_CURVE curveID,
670 int modulusBytes,
671 uint8_t *modulusBin)
672 {
673 TPM_RC rc = 0;
674
675 scheme = scheme; /* scheme parameter not supported yet */
676 if (rc == 0) {
677 if (modulusBytes != 65) { /* 1 for compression + 32 + 32 */
678 printf("convertEcPublicKeyBinToPublic: public modulus expected 65 bytes, actual %u\n",
679 modulusBytes);
680 rc = EXIT_FAILURE;
681 }
682 }
683 if (rc == 0) {
684 /* Table 184 - Definition of TPMT_PUBLIC Structure */
685 objectPublic->publicArea.type = TPM_ALG_ECC;
686 objectPublic->publicArea.nameAlg = nalg;
687 objectPublic->publicArea.objectAttributes.val = TPMA_OBJECT_NODA;
688 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
689 switch (keyType) {
690 case TYPE_SI:
691 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_SIGN;
692 objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
693 objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDSA;
694 break;
695 case TYPE_ST: /* for public part only */
696 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
697 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_RESTRICTED;
698 objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_AES;
699 objectPublic->publicArea.parameters.eccDetail.symmetric.keyBits.aes = 128;
700 objectPublic->publicArea.parameters.eccDetail.symmetric.mode.aes = TPM_ALG_CFB;
701 objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_NULL;
702 break;
703 case TYPE_DEN: /* for public and private part */
704 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
705 objectPublic->publicArea.objectAttributes.val &= ~TPMA_OBJECT_RESTRICTED;
706 objectPublic->publicArea.parameters.eccDetail.symmetric.algorithm = TPM_ALG_NULL;
707 objectPublic->publicArea.parameters.eccDetail.scheme.scheme = TPM_ALG_ECDH;
708 break;
709 }
710 objectPublic->publicArea.authPolicy.t.size = 0;
711 /* Table 152 - Definition of TPMU_ASYM_SCHEME Union */
712 objectPublic->publicArea.parameters.eccDetail.scheme.details.ecdsa.hashAlg = halg;
713 objectPublic->publicArea.parameters.eccDetail.curveID = curveID;
714 objectPublic->publicArea.parameters.eccDetail.kdf.scheme = TPM_ALG_NULL;
715 objectPublic->publicArea.parameters.eccDetail.kdf.details.mgf1.hashAlg = halg;
716
717 objectPublic->publicArea.unique.ecc.x.t.size = 32;
718 memcpy(objectPublic->publicArea.unique.ecc.x.t.buffer, modulusBin +1, 32);
719
720 objectPublic->publicArea.unique.ecc.y.t.size = 32;
721 memcpy(objectPublic->publicArea.unique.ecc.y.t.buffer, modulusBin +33, 32);
722 }
723 return rc;
724 }
725
726 #endif /* TPM_TSS_NOECC */
727
728 /* convertRsaPublicKeyBinToPublic() converts a public modulus to a TPM2B_PUBLIC structure. */
729
convertRsaPublicKeyBinToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,int modulusBytes,uint8_t * modulusBin)730 TPM_RC convertRsaPublicKeyBinToPublic(TPM2B_PUBLIC *objectPublic,
731 int keyType,
732 TPMI_ALG_SIG_SCHEME scheme,
733 TPMI_ALG_HASH nalg,
734 TPMI_ALG_HASH halg,
735 int modulusBytes,
736 uint8_t *modulusBin)
737 {
738 TPM_RC rc = 0;
739
740 if (rc == 0) {
741 if ((size_t)modulusBytes > sizeof(objectPublic->publicArea.unique.rsa.t.buffer)) {
742 printf("convertRsaPublicKeyBinToPublic: Error, "
743 "public key modulus %d greater than %lu\n", modulusBytes,
744 (unsigned long)sizeof(objectPublic->publicArea.unique.rsa.t.buffer));
745 rc = EXIT_FAILURE;
746 }
747 }
748 if (rc == 0) {
749 /* Table 184 - Definition of TPMT_PUBLIC Structure */
750 objectPublic->publicArea.type = TPM_ALG_RSA;
751 objectPublic->publicArea.nameAlg = nalg;
752 objectPublic->publicArea.objectAttributes.val = TPMA_OBJECT_NODA;
753 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_USERWITHAUTH;
754 switch (keyType) {
755 case TYPE_SI:
756 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_SIGN;
757 objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
758 break;
759 case TYPE_ST: /* for public part only */
760 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
761 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_RESTRICTED;
762 objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_AES;
763 objectPublic->publicArea.parameters.rsaDetail.symmetric.keyBits.aes = 128;
764 objectPublic->publicArea.parameters.rsaDetail.symmetric.mode.aes = TPM_ALG_CFB;
765 break;
766 case TYPE_DEN: /* for public and private part */
767 objectPublic->publicArea.objectAttributes.val |= TPMA_OBJECT_DECRYPT;
768 objectPublic->publicArea.objectAttributes.val &= ~TPMA_OBJECT_RESTRICTED;
769 objectPublic->publicArea.parameters.rsaDetail.symmetric.algorithm = TPM_ALG_NULL;
770 break;
771 }
772 objectPublic->publicArea.authPolicy.t.size = 0;
773 /* Table 182 - Definition of TPMU_PUBLIC_PARMS Union <IN/OUT, S> */
774 objectPublic->publicArea.parameters.rsaDetail.scheme.scheme = scheme;
775 objectPublic->publicArea.parameters.rsaDetail.scheme.details.rsassa.hashAlg = halg;
776 objectPublic->publicArea.parameters.rsaDetail.keyBits = modulusBytes * 8;
777 objectPublic->publicArea.parameters.rsaDetail.exponent = 0;
778
779 objectPublic->publicArea.unique.rsa.t.size = modulusBytes;
780 memcpy(objectPublic->publicArea.unique.rsa.t.buffer, modulusBin, modulusBytes);
781 }
782 return rc;
783 }
784
785 #ifdef TPM_TPM20
786 #ifndef TPM_TSS_NOECC
787
788 /* convertEcKeyToPrivate() converts an openssl EC_KEY to token to either a TPM2B_PRIVATE or
789 TPM2B_SENSITIVE
790 */
791
convertEcKeyToPrivate(TPM2B_PRIVATE * objectPrivate,TPM2B_SENSITIVE * objectSensitive,EC_KEY * ecKey,const char * password)792 TPM_RC convertEcKeyToPrivate(TPM2B_PRIVATE *objectPrivate,
793 TPM2B_SENSITIVE *objectSensitive,
794 EC_KEY *ecKey,
795 const char *password)
796 {
797 TPM_RC rc = 0;
798 int privateKeyBytes;
799 uint8_t *privateKeyBin = NULL;
800
801 /* convert an openssl EC_KEY token to a binary array */
802 if (rc == 0) {
803 rc = convertEcKeyToPrivateKeyBin(&privateKeyBytes,
804 &privateKeyBin, /* freed @1 */
805 ecKey);
806 }
807 if (rc == 0) {
808 rc = convertEcPrivateKeyBinToPrivate(objectPrivate,
809 objectSensitive,
810 privateKeyBytes,
811 privateKeyBin,
812 password);
813 }
814 free(privateKeyBin); /* @1 */
815 return rc;
816 }
817
818 #endif /* TPM_TSS_NOECC */
819
820 /* convertRsaKeyToPrivate() converts an openssl RSA key token to either a TPM2B_PRIVATE or
821 TPM2B_SENSITIVE
822 */
823
convertRsaKeyToPrivate(TPM2B_PRIVATE * objectPrivate,TPM2B_SENSITIVE * objectSensitive,RSA * rsaKey,const char * password)824 TPM_RC convertRsaKeyToPrivate(TPM2B_PRIVATE *objectPrivate,
825 TPM2B_SENSITIVE *objectSensitive,
826 RSA *rsaKey,
827 const char *password)
828 {
829 TPM_RC rc = 0;
830 int privateKeyBytes;
831 uint8_t *privateKeyBin = NULL;
832
833 /* convert an openssl RSA key token private prime p to a binary array */
834 if (rc == 0) {
835 rc = convertRsaKeyToPrivateKeyBin(&privateKeyBytes,
836 &privateKeyBin, /* freed @1 */
837 rsaKey);
838 }
839 /* convert an RSA prime 'privateKeyBin' to either a TPM2B_PRIVATE or a TPM2B_SENSITIVE */
840 if (rc == 0) {
841 rc = convertRsaPrivateKeyBinToPrivate(objectPrivate,
842 objectSensitive,
843 privateKeyBytes,
844 privateKeyBin,
845 password);
846 }
847 free(privateKeyBin); /* @1 */
848 return rc;
849 }
850
851 #ifndef TPM_TSS_NOECC
852
853 /* convertEcKeyToPublic() converts an EC_KEY to a TPM2B_PUBLIC */
854
convertEcKeyToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,EC_KEY * ecKey)855 TPM_RC convertEcKeyToPublic(TPM2B_PUBLIC *objectPublic,
856 int keyType,
857 TPMI_ALG_SIG_SCHEME scheme,
858 TPMI_ALG_HASH nalg,
859 TPMI_ALG_HASH halg,
860 EC_KEY *ecKey)
861 {
862 TPM_RC rc = 0;
863 int modulusBytes;
864 uint8_t *modulusBin = NULL;
865 TPMI_ECC_CURVE curveID;
866
867 if (rc == 0) {
868 rc = convertEcKeyToPublicKeyBin(&modulusBytes,
869 &modulusBin, /* freed @1 */
870 ecKey);
871 }
872 if (rc == 0) {
873 rc = getEcCurve(&curveID, ecKey);
874 }
875 if (rc == 0) {
876 rc = convertEcPublicKeyBinToPublic(objectPublic,
877 keyType,
878 scheme,
879 nalg,
880 halg,
881 curveID,
882 modulusBytes,
883 modulusBin);
884 }
885 free(modulusBin); /* @1 */
886 return rc;
887 }
888
889 #endif /* TPM_TSS_NOECC */
890
891 /* convertRsaKeyToPublic() converts from an openssl RSA key token to a TPM2B_PUBLIC */
892
convertRsaKeyToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,void * rsaKey)893 TPM_RC convertRsaKeyToPublic(TPM2B_PUBLIC *objectPublic,
894 int keyType,
895 TPMI_ALG_SIG_SCHEME scheme,
896 TPMI_ALG_HASH nalg,
897 TPMI_ALG_HASH halg,
898 void *rsaKey)
899 {
900 TPM_RC rc = 0;
901 int modulusBytes;
902 uint8_t *modulusBin = NULL;
903
904 /* openssl RSA key token to a public modulus */
905 if (rc == 0) {
906 rc = convertRsaKeyToPublicKeyBin(&modulusBytes,
907 &modulusBin, /* freed @1 */
908 rsaKey);
909 }
910 /* public modulus to TPM2B_PUBLIC */
911 if (rc == 0) {
912 rc = convertRsaPublicKeyBinToPublic(objectPublic,
913 keyType,
914 scheme,
915 nalg,
916 halg,
917 modulusBytes,
918 modulusBin);
919 }
920 free(modulusBin); /* @1 */
921 return rc;
922 }
923
924 #endif
925
926 #ifndef TPM_TSS_NOFILE
927 #ifdef TPM_TPM20
928 #ifndef TPM_TSS_NOECC
929
930 /* convertEcPemToKeyPair() converts a PEM file to a TPM2B_PUBLIC and TPM2B_PRIVATE */
931
convertEcPemToKeyPair(TPM2B_PUBLIC * objectPublic,TPM2B_PRIVATE * objectPrivate,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * pemKeyFilename,const char * password)932 TPM_RC convertEcPemToKeyPair(TPM2B_PUBLIC *objectPublic,
933 TPM2B_PRIVATE *objectPrivate,
934 int keyType,
935 TPMI_ALG_SIG_SCHEME scheme,
936 TPMI_ALG_HASH nalg,
937 TPMI_ALG_HASH halg,
938 const char *pemKeyFilename,
939 const char *password)
940 {
941 TPM_RC rc = 0;
942 EVP_PKEY *evpPkey = NULL;
943 EC_KEY *ecKey = NULL;
944
945 /* convert a PEM file to an openssl EVP_PKEY */
946 if (rc == 0) {
947 rc = convertPemToEvpPrivKey(&evpPkey, /* freed @1 */
948 pemKeyFilename,
949 password);
950 }
951 if (rc == 0) {
952 rc = convertEvpPkeyToEckey(&ecKey, /* freed @2 */
953 evpPkey);
954 }
955 if (rc == 0) {
956 rc = convertEcKeyToPrivate(objectPrivate, /* TPM2B_PRIVATE */
957 NULL, /* TPM2B_SENSITIVE */
958 ecKey,
959 password);
960 }
961 if (rc == 0) {
962 rc = convertEcKeyToPublic(objectPublic,
963 keyType,
964 scheme,
965 nalg,
966 halg,
967 ecKey);
968 }
969 EC_KEY_free(ecKey); /* @2 */
970 if (evpPkey != NULL) {
971 EVP_PKEY_free(evpPkey); /* @1 */
972 }
973 return rc;
974 }
975
976 #endif /* TPM_TSS_NOECC */
977 #endif
978 #endif
979
980 #ifndef TPM_TSS_NOFILE
981 #ifdef TPM_TPM20
982 #ifndef TPM_TSS_NOECC
983
984 /* convertEcPemToPublic() converts an ECC P256 signing public key in PEM format to a
985 TPM2B_PUBLIC */
986
convertEcPemToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * pemKeyFilename)987 TPM_RC convertEcPemToPublic(TPM2B_PUBLIC *objectPublic,
988 int keyType,
989 TPMI_ALG_SIG_SCHEME scheme,
990 TPMI_ALG_HASH nalg,
991 TPMI_ALG_HASH halg,
992 const char *pemKeyFilename)
993 {
994 TPM_RC rc = 0;
995 EVP_PKEY *evpPkey = NULL;
996 EC_KEY *ecKey = NULL;
997
998 if (rc == 0) {
999 rc = convertPemToEvpPubKey(&evpPkey, /* freed @1 */
1000 pemKeyFilename);
1001 }
1002 if (rc == 0) {
1003 rc = convertEvpPkeyToEckey(&ecKey, /* freed @2 */
1004 evpPkey);
1005 }
1006 if (rc == 0) {
1007 rc = convertEcKeyToPublic(objectPublic,
1008 keyType,
1009 scheme,
1010 nalg,
1011 halg,
1012 ecKey);
1013 }
1014 if (ecKey != NULL) {
1015 EC_KEY_free(ecKey); /* @2 */
1016 }
1017 if (evpPkey != NULL) {
1018 EVP_PKEY_free(evpPkey); /* @1 */
1019 }
1020 return rc;
1021 }
1022
1023 #endif /* TPM_TSS_NOECC */
1024 #endif
1025 #endif
1026
1027 #ifndef TPM_TSS_NOFILE
1028 #ifdef TPM_TPM20
1029 #ifndef TPM_TSS_NORSA
1030
1031 /* convertRsaPemToKeyPair() converts an RSA PEM file to a TPM2B_PUBLIC and TPM2B_PRIVATE */
1032
convertRsaPemToKeyPair(TPM2B_PUBLIC * objectPublic,TPM2B_PRIVATE * objectPrivate,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * pemKeyFilename,const char * password)1033 TPM_RC convertRsaPemToKeyPair(TPM2B_PUBLIC *objectPublic,
1034 TPM2B_PRIVATE *objectPrivate,
1035 int keyType,
1036 TPMI_ALG_SIG_SCHEME scheme,
1037 TPMI_ALG_HASH nalg,
1038 TPMI_ALG_HASH halg,
1039 const char *pemKeyFilename,
1040 const char *password)
1041 {
1042 TPM_RC rc = 0;
1043 EVP_PKEY *evpPkey = NULL;
1044 RSA *rsaKey = NULL;
1045
1046 if (rc == 0) {
1047 rc = convertPemToEvpPrivKey(&evpPkey, /* freed @1 */
1048 pemKeyFilename,
1049 password);
1050 }
1051 if (rc == 0) {
1052 rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */
1053 evpPkey);
1054 }
1055 if (rc == 0) {
1056 rc = convertRsaKeyToPrivate(objectPrivate, /* TPM2B_PRIVATE */
1057 NULL, /* TPM2B_SENSITIVE */
1058 rsaKey,
1059 password);
1060 }
1061 if (rc == 0) {
1062 rc = convertRsaKeyToPublic(objectPublic,
1063 keyType,
1064 scheme,
1065 nalg,
1066 halg,
1067 rsaKey);
1068 }
1069 TSS_RsaFree(rsaKey); /* @2 */
1070 if (evpPkey != NULL) {
1071 EVP_PKEY_free(evpPkey); /* @1 */
1072 }
1073 return rc;
1074 }
1075
1076 #endif /* TPM_TSS_NORSA */
1077 #endif /* TPM_TPM20 */
1078 #endif /* TPM_TSS_NOFILE */
1079
1080 #ifndef TPM_TSS_NOFILE
1081 #ifdef TPM_TPM20
1082 #ifndef TPM_TSS_NOECC
1083
1084 /* convertEcDerToKeyPair() converts an EC keypair stored in DER to a TPM2B_PUBLIC and
1085 TPM2B_SENSITIVE. Useful for LoadExternal.
1086
1087 */
1088
convertEcDerToKeyPair(TPM2B_PUBLIC * objectPublic,TPM2B_SENSITIVE * objectSensitive,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * derKeyFilename,const char * password)1089 TPM_RC convertEcDerToKeyPair(TPM2B_PUBLIC *objectPublic,
1090 TPM2B_SENSITIVE *objectSensitive,
1091 int keyType,
1092 TPMI_ALG_SIG_SCHEME scheme,
1093 TPMI_ALG_HASH nalg,
1094 TPMI_ALG_HASH halg,
1095 const char *derKeyFilename,
1096 const char *password)
1097 {
1098 TPM_RC rc = 0;
1099 EC_KEY *ecKey = NULL;
1100 unsigned char *derBuffer = NULL;
1101 size_t derSize;
1102
1103 /* read the DER file */
1104 if (rc == 0) {
1105 rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
1106 &derSize,
1107 derKeyFilename);
1108 }
1109 if (rc == 0) {
1110 const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
1111 ecKey = d2i_ECPrivateKey(NULL, &tmpPtr, derSize); /* freed @2 */
1112 if (ecKey == NULL) {
1113 printf("convertEcDerToKeyPair: could not convert key to EC_KEY\n");
1114 rc = TPM_RC_VALUE;
1115 }
1116 }
1117 if (rc == 0) {
1118 rc = convertEcKeyToPrivate(NULL, /* TPM2B_PRIVATE */
1119 objectSensitive, /* TPM2B_SENSITIVE */
1120 ecKey,
1121 password);
1122 }
1123 if (rc == 0) {
1124 rc = convertEcKeyToPublic(objectPublic,
1125 keyType,
1126 scheme,
1127 nalg,
1128 halg,
1129 ecKey);
1130 }
1131 free(derBuffer); /* @1 */
1132 if (ecKey != NULL) {
1133 EC_KEY_free(ecKey); /* @2 */
1134 }
1135 return rc;
1136 }
1137
1138 /* convertEcDerToPublic() converts an EC public key stored in DER to a TPM2B_PUBLIC. Useful to
1139 calculate a Name.
1140
1141 */
1142
convertEcDerToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * derKeyFilename)1143 TPM_RC convertEcDerToPublic(TPM2B_PUBLIC *objectPublic,
1144 int keyType,
1145 TPMI_ALG_SIG_SCHEME scheme,
1146 TPMI_ALG_HASH nalg,
1147 TPMI_ALG_HASH halg,
1148 const char *derKeyFilename)
1149 {
1150 TPM_RC rc = 0;
1151 EVP_PKEY *evpPkey = NULL;
1152 EC_KEY *ecKey = NULL;
1153 unsigned char *derBuffer = NULL;
1154 size_t derSize;
1155
1156 /* read the DER file */
1157 if (rc == 0) {
1158 rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
1159 &derSize,
1160 derKeyFilename);
1161 }
1162 if (rc == 0) {
1163 const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
1164 evpPkey = d2i_PUBKEY(NULL, &tmpPtr, derSize); /* freed @2 */
1165 if (evpPkey == NULL) {
1166 printf("convertEcDerToPublic: could not convert key to EVP_PKEY\n");
1167 rc = TPM_RC_VALUE;
1168 }
1169 }
1170 if (rc == 0) {
1171 rc = convertEvpPkeyToEckey(&ecKey, /* freed @3 */
1172 evpPkey);
1173 }
1174 if (rc == 0) {
1175 rc = convertEcKeyToPublic(objectPublic,
1176 keyType,
1177 scheme,
1178 nalg,
1179 halg,
1180 ecKey);
1181 }
1182 free(derBuffer); /* @1 */
1183 if (evpPkey != NULL) {
1184 EVP_PKEY_free(evpPkey); /* @1 */
1185 }
1186 if (ecKey != NULL) {
1187 EC_KEY_free(ecKey); /* @2 */
1188 }
1189 return rc;
1190 }
1191
1192 #endif /* TPM_TSS_NOECC */
1193 #endif
1194 #endif
1195
1196 #ifndef TPM_TSS_NOFILE
1197 #ifdef TPM_TPM20
1198 #ifndef TPM_TSS_NORSA
1199
1200 /* convertRsaDerToKeyPair() converts an RSA keypair stored in DER to a TPM2B_PUBLIC and
1201 TPM2B_SENSITIVE. Useful for LoadExternal.
1202
1203 */
1204
convertRsaDerToKeyPair(TPM2B_PUBLIC * objectPublic,TPM2B_SENSITIVE * objectSensitive,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * derKeyFilename,const char * password)1205 TPM_RC convertRsaDerToKeyPair(TPM2B_PUBLIC *objectPublic,
1206 TPM2B_SENSITIVE *objectSensitive,
1207 int keyType,
1208 TPMI_ALG_SIG_SCHEME scheme,
1209 TPMI_ALG_HASH nalg,
1210 TPMI_ALG_HASH halg,
1211 const char *derKeyFilename,
1212 const char *password)
1213 {
1214 TPM_RC rc = 0;
1215 RSA *rsaKey = NULL;
1216 unsigned char *derBuffer = NULL;
1217 size_t derSize;
1218
1219 /* read the DER file */
1220 if (rc == 0) {
1221 rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
1222 &derSize,
1223 derKeyFilename);
1224 }
1225 if (rc == 0) {
1226 const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
1227 rsaKey = d2i_RSAPrivateKey(NULL, &tmpPtr, derSize); /* freed @2 */
1228 if (rsaKey == NULL) {
1229 printf("convertRsaDerToKeyPair: could not convert key to RSA\n");
1230 rc = TPM_RC_VALUE;
1231 }
1232 }
1233 if (rc == 0) {
1234 rc = convertRsaKeyToPrivate(NULL, /* TPM2B_PRIVATE */
1235 objectSensitive, /* TPM2B_SENSITIVE */
1236 rsaKey,
1237 password);
1238 }
1239 if (rc == 0) {
1240 rc = convertRsaKeyToPublic(objectPublic,
1241 keyType,
1242 scheme,
1243 nalg,
1244 halg,
1245 rsaKey);
1246 }
1247 free(derBuffer); /* @1 */
1248 TSS_RsaFree(rsaKey); /* @2 */
1249 return rc;
1250 }
1251
1252 /* convertRsaDerToPublic() converts an RSA public key stored in DER to a TPM2B_PUBLIC. Useful to
1253 calculate a Name.
1254
1255 */
1256
convertRsaDerToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * derKeyFilename)1257 TPM_RC convertRsaDerToPublic(TPM2B_PUBLIC *objectPublic,
1258 int keyType,
1259 TPMI_ALG_SIG_SCHEME scheme,
1260 TPMI_ALG_HASH nalg,
1261 TPMI_ALG_HASH halg,
1262 const char *derKeyFilename)
1263 {
1264 TPM_RC rc = 0;
1265 RSA *rsaKey = NULL;
1266 unsigned char *derBuffer = NULL;
1267 size_t derSize;
1268
1269 /* read the DER file */
1270 if (rc == 0) {
1271 rc = TSS_File_ReadBinaryFile(&derBuffer, /* freed @1 */
1272 &derSize,
1273 derKeyFilename);
1274 }
1275 if (rc == 0) {
1276 const unsigned char *tmpPtr = derBuffer; /* because pointer moves */
1277 rsaKey = d2i_RSA_PUBKEY(NULL, &tmpPtr, derSize); /* freed @2 */
1278 if (rsaKey == NULL) {
1279 printf("convertRsaDerToPublic: could not convert key to RSA\n");
1280 rc = TPM_RC_VALUE;
1281 }
1282 }
1283 if (rc == 0) {
1284 rc = convertRsaKeyToPublic(objectPublic,
1285 keyType,
1286 scheme,
1287 nalg,
1288 halg,
1289 rsaKey);
1290 }
1291 free(derBuffer); /* @1 */
1292 TSS_RsaFree(rsaKey); /* @2 */
1293 return rc;
1294 }
1295
1296 #endif /* TPM_TSS_NORSA */
1297 #endif /* TPM_TPM20 */
1298 #endif /* TPM_TSS_NOFILE */
1299
1300 #ifndef TPM_TSS_NOFILE
1301 #ifdef TPM_TPM20
1302
1303 /* convertRsaPemToPublic() converts an RSA public key in PEM format to a TPM2B_PUBLIC */
1304
convertRsaPemToPublic(TPM2B_PUBLIC * objectPublic,int keyType,TPMI_ALG_SIG_SCHEME scheme,TPMI_ALG_HASH nalg,TPMI_ALG_HASH halg,const char * pemKeyFilename)1305 TPM_RC convertRsaPemToPublic(TPM2B_PUBLIC *objectPublic,
1306 int keyType,
1307 TPMI_ALG_SIG_SCHEME scheme,
1308 TPMI_ALG_HASH nalg,
1309 TPMI_ALG_HASH halg,
1310 const char *pemKeyFilename)
1311 {
1312 TPM_RC rc = 0;
1313 EVP_PKEY *evpPkey = NULL;
1314 RSA *rsaKey = NULL;
1315
1316 if (rc == 0) {
1317 rc = convertPemToEvpPubKey(&evpPkey, /* freed @1 */
1318 pemKeyFilename);
1319 }
1320 if (rc == 0) {
1321 rc = convertEvpPkeyToRsakey(&rsaKey, /* freed @2 */
1322 evpPkey);
1323 }
1324 if (rc == 0) {
1325 rc = convertRsaKeyToPublic(objectPublic,
1326 keyType,
1327 scheme,
1328 nalg,
1329 halg,
1330 rsaKey);
1331 }
1332 RSA_free(rsaKey); /* @2 */
1333 if (evpPkey != NULL) {
1334 EVP_PKEY_free(evpPkey); /* @1 */
1335 }
1336 return rc;
1337 }
1338
1339 #endif
1340 #endif
1341
1342 /* getRsaKeyParts() gets the RSA key parts from an OpenSSL RSA key token.
1343
1344 If n is not NULL, returns n, e, and d. If p is not NULL, returns p and q.
1345 */
1346
getRsaKeyParts(const BIGNUM ** n,const BIGNUM ** e,const BIGNUM ** d,const BIGNUM ** p,const BIGNUM ** q,const RSA * rsaKey)1347 TPM_RC getRsaKeyParts(const BIGNUM **n,
1348 const BIGNUM **e,
1349 const BIGNUM **d,
1350 const BIGNUM **p,
1351 const BIGNUM **q,
1352 const RSA *rsaKey)
1353 {
1354 TPM_RC rc = 0;
1355 if (n != NULL) {
1356 RSA_get0_key(rsaKey, n, e, d);
1357 }
1358 if (p != NULL) {
1359 RSA_get0_factors(rsaKey, p, q);
1360 }
1361 return rc;
1362 }
1363
1364 /* returns the type (EVP_PKEY_RSA or EVP_PKEY_EC) of the EVP_PKEY.
1365
1366 */
1367
getRsaPubkeyAlgorithm(EVP_PKEY * pkey)1368 int getRsaPubkeyAlgorithm(EVP_PKEY *pkey)
1369 {
1370 int pkeyType; /* RSA or EC */
1371 pkeyType = EVP_PKEY_base_id(pkey);
1372 return pkeyType;
1373 }
1374
1375 #ifndef TPM_TSS_NOFILE
1376
1377 /* convertPublicToPEM() saves a PEM format public key from a TPM2B_PUBLIC
1378
1379 */
1380
convertPublicToPEM(const TPM2B_PUBLIC * public,const char * pemFilename)1381 TPM_RC convertPublicToPEM(const TPM2B_PUBLIC *public,
1382 const char *pemFilename)
1383 {
1384 TPM_RC rc = 0;
1385 EVP_PKEY *evpPubkey = NULL; /* OpenSSL public key, EVP format */
1386
1387 /* convert TPM2B_PUBLIC to EVP_PKEY */
1388 if (rc == 0) {
1389 switch (public->publicArea.type) {
1390 #ifndef TPM_TSS_NORSA
1391 case TPM_ALG_RSA:
1392 rc = convertRsaPublicToEvpPubKey(&evpPubkey, /* freed @1 */
1393 &public->publicArea.unique.rsa);
1394 break;
1395 #endif /* TPM_TSS_NORSA */
1396 #ifndef TPM_TSS_NOECC
1397 case TPM_ALG_ECC:
1398 rc = convertEcPublicToEvpPubKey(&evpPubkey, /* freed @1 */
1399 &public->publicArea.unique.ecc);
1400 break;
1401 #endif /* TPM_TSS_NOECC */
1402 default:
1403 printf("convertPublicToPEM: Unknown publicArea.type %04hx unsupported\n",
1404 public->publicArea.type);
1405 rc = TSS_RC_NOT_IMPLEMENTED;
1406 break;
1407 }
1408 }
1409 /* write the openssl structure in PEM format */
1410 if (rc == 0) {
1411 rc = convertEvpPubkeyToPem(evpPubkey,
1412 pemFilename);
1413
1414 }
1415 if (evpPubkey != NULL) {
1416 EVP_PKEY_free(evpPubkey); /* @1 */
1417 }
1418 return rc;
1419 }
1420
1421 #endif /* TPM_TSS_NOFILE */
1422
1423 #ifndef TPM_TSS_NORSA
1424
1425 /* convertRsaPublicToEvpPubKey() converts an RSA TPM2B_PUBLIC to a EVP_PKEY.
1426
1427 */
1428
convertRsaPublicToEvpPubKey(EVP_PKEY ** evpPubkey,const TPM2B_PUBLIC_KEY_RSA * tpm2bRsa)1429 TPM_RC convertRsaPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */
1430 const TPM2B_PUBLIC_KEY_RSA *tpm2bRsa)
1431 {
1432 TPM_RC rc = 0;
1433 int irc;
1434 RSA *rsaPubKey = NULL;
1435
1436 if (rc == 0) {
1437 *evpPubkey = EVP_PKEY_new();
1438 if (*evpPubkey == NULL) {
1439 printf("convertRsaPublicToEvpPubKey: EVP_PKEY failed\n");
1440 rc = TSS_RC_OUT_OF_MEMORY;
1441 }
1442 }
1443 /* TPM to RSA token */
1444 if (rc == 0) {
1445 /* public exponent */
1446 unsigned char earr[3] = {0x01, 0x00, 0x01};
1447 rc = TSS_RSAGeneratePublicTokenI
1448 ((void **)&rsaPubKey, /* freed as part of EVP_PKEY */
1449 tpm2bRsa->t.buffer, /* public modulus */
1450 tpm2bRsa->t.size,
1451 earr, /* public exponent */
1452 sizeof(earr));
1453 }
1454 /* RSA token to EVP */
1455 if (rc == 0) {
1456 irc = EVP_PKEY_assign_RSA(*evpPubkey, rsaPubKey);
1457 if (irc == 0) {
1458 TSS_RsaFree(rsaPubKey); /* because not assigned tp EVP_PKEY */
1459 printf("convertRsaPublicToEvpPubKey: EVP_PKEY_assign_RSA failed\n");
1460 rc = TSS_RC_RSA_KEY_CONVERT;
1461 }
1462 }
1463 return rc;
1464 }
1465
1466 #endif /* TPM_TSS_NORSA */
1467
1468 #ifndef TPM_TSS_NOECC
1469
1470 /* convertEcPublicToEvpPubKey() converts an EC TPMS_ECC_POINT to an EVP_PKEY.
1471 */
1472
convertEcPublicToEvpPubKey(EVP_PKEY ** evpPubkey,const TPMS_ECC_POINT * tpmsEccPoint)1473 TPM_RC convertEcPublicToEvpPubKey(EVP_PKEY **evpPubkey, /* freed by caller */
1474 const TPMS_ECC_POINT *tpmsEccPoint)
1475 {
1476 TPM_RC rc = 0;
1477 int irc;
1478 EC_GROUP *ecGroup = NULL;
1479 EC_KEY *ecKey = NULL;
1480 BIGNUM *x = NULL; /* freed @2 */
1481 BIGNUM *y = NULL; /* freed @3 */
1482
1483 if (rc == 0) {
1484 ecKey = EC_KEY_new(); /* freed @1 */
1485 if (ecKey == NULL) {
1486 printf("convertEcPublicToEvpPubKey: Error creating EC_KEY\n");
1487 rc = TSS_RC_OUT_OF_MEMORY;
1488 }
1489 }
1490 if (rc == 0) {
1491 ecGroup = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1); /* freed @4 */
1492 if (ecGroup == NULL) {
1493 printf("convertEcPublicToEvpPubKey: Error in EC_GROUP_new_by_curve_name\n");
1494 rc = TSS_RC_OUT_OF_MEMORY;
1495 }
1496 }
1497 if (rc == 0) {
1498 /* returns void */
1499 EC_GROUP_set_asn1_flag(ecGroup, OPENSSL_EC_NAMED_CURVE);
1500 }
1501 /* assign curve to EC_KEY */
1502 if (rc == 0) {
1503 irc = EC_KEY_set_group(ecKey, ecGroup);
1504 if (irc != 1) {
1505 printf("convertEcPublicToEvpPubKey: Error in EC_KEY_set_group\n");
1506 rc = TSS_RC_EC_KEY_CONVERT;
1507 }
1508 }
1509 if (rc == 0) {
1510 rc = convertBin2Bn(&x, /* freed @2 */
1511 tpmsEccPoint->x.t.buffer,
1512 tpmsEccPoint->x.t.size);
1513 }
1514 if (rc == 0) {
1515 rc = convertBin2Bn(&y, /* freed @3 */
1516 tpmsEccPoint->y.t.buffer,
1517 tpmsEccPoint->y.t.size);
1518 }
1519 if (rc == 0) {
1520 irc = EC_KEY_set_public_key_affine_coordinates(ecKey, x, y);
1521 if (irc != 1) {
1522 printf("convertEcPublicToEvpPubKey: "
1523 "Error converting public key from X Y to EC_KEY format\n");
1524 rc = TSS_RC_EC_KEY_CONVERT;
1525 }
1526 }
1527 if (rc == 0) {
1528 *evpPubkey = EVP_PKEY_new(); /* freed by caller */
1529 if (*evpPubkey == NULL) {
1530 printf("convertEcPublicToEvpPubKey: EVP_PKEY failed\n");
1531 rc = TSS_RC_OUT_OF_MEMORY;
1532 }
1533 }
1534 if (rc == 0) {
1535 irc = EVP_PKEY_set1_EC_KEY(*evpPubkey, ecKey);
1536 if (irc != 1) {
1537 printf("convertEcPublicToEvpPubKey: "
1538 "Error converting public key from EC to EVP format\n");
1539 rc = TSS_RC_EC_KEY_CONVERT;
1540 }
1541 }
1542 if (ecGroup != NULL) {
1543 EC_GROUP_free(ecGroup); /* @4 */
1544 }
1545 if (ecKey != NULL) {
1546 EC_KEY_free(ecKey); /* @1 */
1547 }
1548 if (x != NULL) {
1549 BN_free(x); /* @2 */
1550 }
1551 if (y != NULL) {
1552 BN_free(y); /* @3 */
1553 }
1554 return rc;
1555 }
1556
1557 #endif /* TPM_TSS_NOECC */
1558
1559 #ifndef TPM_TSS_NOFILE
1560
convertEvpPubkeyToPem(EVP_PKEY * evpPubkey,const char * pemFilename)1561 TPM_RC convertEvpPubkeyToPem(EVP_PKEY *evpPubkey,
1562 const char *pemFilename)
1563 {
1564 TPM_RC rc = 0;
1565 int irc;
1566 FILE *pemFile = NULL;
1567
1568 if (rc == 0) {
1569 pemFile = fopen(pemFilename, "wb"); /* close @1 */
1570 if (pemFile == NULL) {
1571 printf("convertEvpPubkeyToPem: Unable to open PEM file %s for write\n", pemFilename);
1572 rc = TSS_RC_FILE_OPEN;
1573 }
1574 }
1575 if (rc == 0) {
1576 irc = PEM_write_PUBKEY(pemFile, evpPubkey);
1577 if (irc == 0) {
1578 printf("convertEvpPubkeyToPem: Unable to write PEM file %s\n", pemFilename);
1579 rc = TSS_RC_FILE_WRITE;
1580 }
1581 }
1582 if (pemFile != NULL) {
1583 fclose(pemFile); /* @1 */
1584 }
1585 return rc;
1586 }
1587
1588 #endif
1589 #ifndef TPM_TSS_NOFILE
1590
1591 /* verifySignatureFromPem() verifies the signature 'tSignature' against the digest 'message' using
1592 the public key in the PEM format file 'pemFilename'.
1593
1594 */
1595
verifySignatureFromPem(unsigned char * message,unsigned int messageSize,TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,const char * pemFilename)1596 TPM_RC verifySignatureFromPem(unsigned char *message,
1597 unsigned int messageSize,
1598 TPMT_SIGNATURE *tSignature,
1599 TPMI_ALG_HASH halg,
1600 const char *pemFilename)
1601 {
1602 TPM_RC rc = 0;
1603 EVP_PKEY *evpPkey = NULL; /* OpenSSL public key, EVP format */
1604
1605 /* read the public key from PEM format */
1606 if (rc == 0) {
1607 rc = convertPemToEvpPubKey(&evpPkey, /* freed @1*/
1608 pemFilename);
1609 }
1610 /* RSA or EC */
1611 if (rc == 0) {
1612 switch(tSignature->sigAlg) {
1613 #ifndef TPM_TSS_NORSA
1614 case TPM_ALG_RSASSA:
1615 case TPM_ALG_RSAPSS:
1616 rc = verifyRSASignatureFromEvpPubKey(message,
1617 messageSize,
1618 tSignature,
1619 halg,
1620 evpPkey);
1621 break;
1622 #else
1623 halg = halg;
1624 #endif /* TPM_TSS_NORSA */
1625 #ifndef TPM_TSS_NOECC
1626 case TPM_ALG_ECDSA:
1627 rc = verifyEcSignatureFromEvpPubKey(message,
1628 messageSize,
1629 tSignature,
1630 evpPkey);
1631 break;
1632 #endif /* TPM_TSS_NOECC */
1633 default:
1634 printf("verifySignatureFromPem: Unknown signature algorithm %04x\n", tSignature->sigAlg);
1635 rc = TSS_RC_BAD_SIGNATURE_ALGORITHM;
1636 }
1637 }
1638 if (evpPkey != NULL) {
1639 EVP_PKEY_free(evpPkey); /* @1 */
1640 }
1641 return rc;
1642 }
1643
1644 #endif
1645
1646 #ifndef TPM_TSS_NORSA
1647
1648 /* verifyRSASignatureFromEvpPubKey() verifies the signature 'tSignature' against the digest
1649 'message' using the RSA public key in evpPkey.
1650
1651 */
1652
verifyRSASignatureFromEvpPubKey(unsigned char * message,unsigned int messageSize,TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,EVP_PKEY * evpPkey)1653 TPM_RC verifyRSASignatureFromEvpPubKey(unsigned char *message,
1654 unsigned int messageSize,
1655 TPMT_SIGNATURE *tSignature,
1656 TPMI_ALG_HASH halg,
1657 EVP_PKEY *evpPkey)
1658 {
1659 TPM_RC rc = 0;
1660 RSA *rsaPubKey = NULL; /* OpenSSL public key, RSA format */
1661
1662 /* construct the RSA key token */
1663 if (rc == 0) {
1664 rsaPubKey = EVP_PKEY_get1_RSA(evpPkey); /* freed @1 */
1665 if (rsaPubKey == NULL) {
1666 printf("verifyRSASignatureFromEvpPubKey: EVP_PKEY_get1_RSA failed\n");
1667 rc = TSS_RC_RSA_KEY_CONVERT;
1668 }
1669 }
1670 if (rc == 0) {
1671 rc = verifyRSASignatureFromRSA(message,
1672 messageSize,
1673 tSignature,
1674 halg,
1675 rsaPubKey);
1676 }
1677 TSS_RsaFree(rsaPubKey); /* @1 */
1678 return rc;
1679 }
1680
1681 /* signRSAFromRSA() signs digest to signature, using th4 RSA key rsaKey. */
1682
signRSAFromRSA(uint8_t * signature,size_t * signatureLength,size_t signatureSize,const uint8_t * digest,size_t digestLength,TPMI_ALG_HASH hashAlg,void * rsaKey)1683 TPM_RC signRSAFromRSA(uint8_t *signature, size_t *signatureLength,
1684 size_t signatureSize,
1685 const uint8_t *digest, size_t digestLength,
1686 TPMI_ALG_HASH hashAlg,
1687 void *rsaKey)
1688 {
1689 TPM_RC rc = 0;
1690 int irc;
1691 int nid; /* openssl hash algorithm */
1692
1693 /* map the hash algorithm to the openssl NID */
1694 if (rc == 0) {
1695 switch (hashAlg) {
1696 case TPM_ALG_SHA1:
1697 nid = NID_sha1;
1698 break;
1699 case TPM_ALG_SHA256:
1700 nid = NID_sha256;
1701 break;
1702 case TPM_ALG_SHA384:
1703 nid = NID_sha384;
1704 break;
1705 case TPM_ALG_SHA512:
1706 nid = NID_sha512;
1707 break;
1708 default:
1709 printf("signRSAFromRSA: Error, hash algorithm %04hx unsupported\n", hashAlg);
1710 rc = TSS_RC_BAD_HASH_ALGORITHM;
1711 }
1712 }
1713 /* validate that the length of the resulting signature will fit in the
1714 signature array */
1715 if (rc == 0) {
1716 unsigned int keySize = RSA_size(rsaKey);
1717 if (keySize > signatureSize) {
1718 printf("signRSAFromRSA: Error, private key length %u > signature buffer %u\n",
1719 keySize, (unsigned int)signatureSize);
1720 rc = TSS_RC_INSUFFICIENT_BUFFER;
1721 }
1722 }
1723 if (rc == 0) {
1724 unsigned int siglen;
1725 irc = RSA_sign(nid,
1726 digest, digestLength,
1727 signature, &siglen,
1728 rsaKey);
1729 *signatureLength = siglen;
1730 if (irc != 1) {
1731 printf("signRSAFromRSA: Error in OpenSSL RSA_sign()\n");
1732 rc = TSS_RC_RSA_SIGNATURE;
1733 }
1734 }
1735 return rc;
1736 }
1737
1738 /* verifyRSASignatureFromRSA() verifies the signature 'tSignature' against the digest 'message'
1739 using the RSA public key in the OpenSSL RSA format.
1740
1741 Supports RSASSA and RSAPSS schemes.
1742 */
1743
verifyRSASignatureFromRSA(unsigned char * message,unsigned int messageSize,TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,void * rsaPubKey)1744 TPM_RC verifyRSASignatureFromRSA(unsigned char *message,
1745 unsigned int messageSize,
1746 TPMT_SIGNATURE *tSignature,
1747 TPMI_ALG_HASH halg,
1748 void *rsaPubKey)
1749 {
1750 TPM_RC rc = 0;
1751 int irc;
1752 int nid = 0; /* initialized these two to suppress false gcc -O3
1753 warnings */
1754 const EVP_MD *md = NULL;
1755 /* map from hash algorithm to openssl nid */
1756 if (rc == 0) {
1757 switch (halg) {
1758 case TPM_ALG_SHA1:
1759 nid = NID_sha1;
1760 md = EVP_sha1();
1761 break;
1762 case TPM_ALG_SHA256:
1763 nid = NID_sha256;
1764 md = EVP_sha256();
1765 break;
1766 case TPM_ALG_SHA384:
1767 nid = NID_sha384;
1768 md = EVP_sha384();
1769 break;
1770 case TPM_ALG_SHA512:
1771 nid = NID_sha512;
1772 md = EVP_sha512();
1773 break;
1774 default:
1775 printf("verifyRSASignatureFromRSA: Unknown hash algorithm %04x\n", halg);
1776 rc = TSS_RC_BAD_HASH_ALGORITHM;
1777 }
1778 }
1779 /* verify the signature */
1780 if (tSignature->sigAlg == TPM_ALG_RSASSA) {
1781 if (rc == 0) {
1782 irc = RSA_verify(nid,
1783 message, messageSize,
1784 tSignature->signature.rsassa.sig.t.buffer,
1785 tSignature->signature.rsassa.sig.t.size,
1786 rsaPubKey);
1787 if (irc != 1) {
1788 printf("verifyRSASignatureFromRSA: Bad signature\n");
1789 rc = TSS_RC_RSA_SIGNATURE;
1790 }
1791 }
1792 }
1793 else if (tSignature->sigAlg == TPM_ALG_RSAPSS) {
1794 uint8_t decryptedSig[sizeof(tSignature->signature.rsapss.sig.t.buffer)];
1795 if (rc == 0) {
1796 irc = RSA_public_decrypt(tSignature->signature.rsapss.sig.t.size,
1797 tSignature->signature.rsapss.sig.t.buffer,
1798 decryptedSig,
1799 rsaPubKey,
1800 RSA_NO_PADDING);
1801 if (irc == -1) {
1802 printf("verifyRSASignatureFromRSA: RSAPSS Bad signature\n");
1803 rc = TSS_RC_RSA_SIGNATURE;
1804 }
1805 }
1806 if (rc == 0) {
1807 irc = RSA_verify_PKCS1_PSS(rsaPubKey,
1808 message,
1809 md,
1810 decryptedSig,
1811 -2); /* salt length recovered from signature*/
1812 if (irc != 1) {
1813 printf("verifyRSASignatureFromRSA: RSAPSS Bad signature\n");
1814 rc = TSS_RC_RSA_SIGNATURE;
1815 }
1816 }
1817 }
1818 else {
1819 printf("verifyRSASignatureFromRSA: Bad signature scheme %04x\n",
1820 tSignature->sigAlg);
1821 }
1822 return rc;
1823 }
1824
1825 #endif /* TPM_TSS_NORSA */
1826
1827 #ifndef TPM_TSS_NOECC
1828
1829 /* verifyEcSignatureFromEvpPubKey() verifies the signature 'tSignature' against the digest 'message'
1830 using the EC public key in evpPkey.
1831
1832 */
1833
verifyEcSignatureFromEvpPubKey(unsigned char * message,unsigned int messageSize,TPMT_SIGNATURE * tSignature,EVP_PKEY * evpPkey)1834 TPM_RC verifyEcSignatureFromEvpPubKey(unsigned char *message,
1835 unsigned int messageSize,
1836 TPMT_SIGNATURE *tSignature,
1837 EVP_PKEY *evpPkey)
1838 {
1839 TPM_RC rc = 0;
1840 int irc;
1841 EC_KEY *ecKey = NULL;
1842 BIGNUM *r = NULL;
1843 BIGNUM *s = NULL;
1844 ECDSA_SIG *ecdsaSig = NULL;
1845
1846 /* construct the EC key token */
1847 if (rc == 0) {
1848 ecKey = EVP_PKEY_get1_EC_KEY(evpPkey); /* freed @1 */
1849 if (ecKey == NULL) {
1850 printf("verifyEcSignatureFromEvpPubKey: EVP_PKEY_get1_EC_KEY failed\n");
1851 rc = TSS_RC_EC_KEY_CONVERT;
1852 }
1853 }
1854 /* construct the ECDSA_SIG signature token */
1855 if (rc == 0) {
1856 rc = convertBin2Bn(&r, /* freed @2 */
1857 tSignature->signature.ecdsa.signatureR.t.buffer,
1858 tSignature->signature.ecdsa.signatureR.t.size);
1859 }
1860 if (rc == 0) {
1861 rc = convertBin2Bn(&s, /* freed @2 */
1862 tSignature->signature.ecdsa.signatureS.t.buffer,
1863 tSignature->signature.ecdsa.signatureS.t.size);
1864 }
1865 /* ECDSA_SIG_new() allocates an empty ECDSA_SIG structure. */
1866 if (rc == 0) {
1867 ecdsaSig = ECDSA_SIG_new(); /* freed @2 */
1868 if (ecdsaSig == NULL) {
1869 printf("verifyEcSignatureFromEvpPubKey: Error creating ECDSA_SIG_new\n");
1870 rc = TSS_RC_OUT_OF_MEMORY;
1871 }
1872 }
1873 if (rc == 0) {
1874 int irc = ECDSA_SIG_set0(ecdsaSig, r, s);
1875 if (irc != 1) {
1876 printf("verifyEcSignatureFromEvpPubKey: Error in ECDSA_SIG_set0()\n");
1877 rc = TSS_RC_EC_KEY_CONVERT;
1878 }
1879 }
1880 /* verify the signature */
1881 if (rc == 0) {
1882 irc = ECDSA_do_verify(message, messageSize,
1883 ecdsaSig, ecKey);
1884 if (irc != 1) { /* quote signature did not verify */
1885 printf("verifyEcSignatureFromEvpPubKey: Bad signature\n");
1886 rc = TSS_RC_EC_SIGNATURE;
1887 }
1888 }
1889 if (ecKey != NULL) {
1890 EC_KEY_free(ecKey); /* @1 */
1891 }
1892 /* if the ECDSA_SIG was allocated correctly, r and s are implicitly freed */
1893 if (ecdsaSig != NULL) {
1894 ECDSA_SIG_free(ecdsaSig); /* @2 */
1895 }
1896 /* if not, explicitly free */
1897 else {
1898 if (r != NULL) BN_free(r); /* @2 */
1899 if (s != NULL) BN_free(s); /* @2 */
1900 }
1901 return rc;
1902 }
1903
1904 #endif /* TPM_TSS_NOECC */
1905
1906 #ifndef TPM_TSS_NOFILE
1907
1908 /* verifySignatureFromHmacKey() verifies the signature (MAC) against the digest 'message'
1909 using the HMAC key in raw binary format.
1910 */
1911
verifySignatureFromHmacKey(unsigned char * message,unsigned int messageSize,TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,const char * hmacKeyFilename)1912 TPM_RC verifySignatureFromHmacKey(unsigned char *message,
1913 unsigned int messageSize,
1914 TPMT_SIGNATURE *tSignature,
1915 TPMI_ALG_HASH halg,
1916 const char *hmacKeyFilename)
1917 {
1918 TPM_RC rc = 0;
1919 TPM2B_KEY hmacKey;
1920 uint32_t sizeInBytes;
1921
1922 /* read the HMAC key */
1923 if (rc == 0) {
1924 rc = TSS_File_Read2B(&hmacKey.b,
1925 sizeof(hmacKey.t.buffer),
1926 hmacKeyFilename);
1927 }
1928 if (rc == 0) {
1929 sizeInBytes = TSS_GetDigestSize(halg);
1930 rc = TSS_HMAC_Verify(&tSignature->signature.hmac,
1931 &hmacKey, /* input HMAC key */
1932 sizeInBytes,
1933 messageSize, message,
1934 0, NULL);
1935 }
1936 return rc;
1937 }
1938
1939 #endif /* TPM_TSS_NOFILE */
1940
1941 /* convertRsaBinToTSignature() converts an RSA binary signature to a TPMT_SIGNATURE */
1942
convertRsaBinToTSignature(TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,uint8_t * signatureBin,size_t signatureBinLen)1943 TPM_RC convertRsaBinToTSignature(TPMT_SIGNATURE *tSignature,
1944 TPMI_ALG_HASH halg,
1945 uint8_t *signatureBin,
1946 size_t signatureBinLen)
1947 {
1948 TPM_RC rc = 0;
1949
1950 tSignature->sigAlg = TPM_ALG_RSASSA;
1951 tSignature->signature.rsassa.hash = halg;
1952 tSignature->signature.rsassa.sig.t.size = (uint16_t)signatureBinLen;
1953 memcpy(&tSignature->signature.rsassa.sig.t.buffer, signatureBin, signatureBinLen);
1954 return rc;
1955 }
1956
1957 #ifdef TPM_TPM20
1958 #ifndef TPM_TSS_NOECC
1959
1960 /* convertEcBinToTSignature() converts an EC binary signature to a TPMT_SIGNATURE */
1961
convertEcBinToTSignature(TPMT_SIGNATURE * tSignature,TPMI_ALG_HASH halg,const uint8_t * signatureBin,size_t signatureBinLen)1962 TPM_RC convertEcBinToTSignature(TPMT_SIGNATURE *tSignature,
1963 TPMI_ALG_HASH halg,
1964 const uint8_t *signatureBin,
1965 size_t signatureBinLen)
1966 {
1967 TPM_RC rc = 0;
1968 ECDSA_SIG *ecSig = NULL;
1969 int rBytes;
1970 int sBytes;
1971 const BIGNUM *pr = NULL;
1972 const BIGNUM *ps = NULL;
1973
1974 if (rc == 0) {
1975 tSignature->sigAlg = TPM_ALG_ECDSA;
1976 tSignature->signature.ecdsa.hash = halg;
1977 }
1978 /* convert DER to ECDSA_SIG */
1979 if (rc == 0) {
1980 ecSig = d2i_ECDSA_SIG(NULL, &signatureBin, signatureBinLen); /* freed @1 */
1981 if (ecSig == NULL) {
1982 printf("convertEcBinToTSignature: could not convert signature to ECDSA_SIG\n");
1983 rc = TPM_RC_VALUE;
1984 }
1985 }
1986 /* check that the signature size agrees with the currently hard coded P256 curve */
1987 if (rc == 0) {
1988 ECDSA_SIG_get0(ecSig, &pr, &ps);
1989 rBytes = BN_num_bytes(pr);
1990 sBytes = BN_num_bytes(ps);
1991 if ((rBytes > 32) ||
1992 (sBytes > 32)) {
1993 printf("convertEcBinToTSignature: signature rBytes %u or sBytes %u greater than 32\n",
1994 rBytes, sBytes);
1995 rc = TPM_RC_VALUE;
1996 }
1997 }
1998 /* extract the raw signature bytes from the openssl structure BIGNUMs */
1999 if (rc == 0) {
2000 tSignature->signature.ecdsa.signatureR.t.size = rBytes;
2001 tSignature->signature.ecdsa.signatureS.t.size = sBytes;
2002
2003 BN_bn2bin(pr, (unsigned char *)&tSignature->signature.ecdsa.signatureR.t.buffer);
2004 BN_bn2bin(ps, (unsigned char *)&tSignature->signature.ecdsa.signatureS.t.buffer);
2005 if (tssUtilsVerbose) {
2006 TSS_PrintAll("convertEcBinToTSignature: signature R",
2007 tSignature->signature.ecdsa.signatureR.t.buffer,
2008 tSignature->signature.ecdsa.signatureR.t.size);
2009 TSS_PrintAll("convertEcBinToTSignature: signature S",
2010 tSignature->signature.ecdsa.signatureS.t.buffer,
2011 tSignature->signature.ecdsa.signatureS.t.size);
2012 }
2013 }
2014 if (ecSig != NULL) {
2015 ECDSA_SIG_free(ecSig); /* @1 */
2016 }
2017 return rc;
2018 }
2019
2020 #endif /* TPM_TSS_NOECC */
2021
2022 #ifndef TPM_TSS_NOECC
2023
2024 /* getEcCurve() gets the TCG algorithm ID curve associated with the openssl EC_KEY */
2025
getEcCurve(TPMI_ECC_CURVE * curveID,const EC_KEY * ecKey)2026 TPM_RC getEcCurve(TPMI_ECC_CURVE *curveID,
2027 const EC_KEY *ecKey)
2028 {
2029 TPM_RC rc = 0;
2030 const EC_GROUP *ecGroup;
2031 int nid;
2032
2033 if (rc == 0) {
2034 ecGroup = EC_KEY_get0_group(ecKey);
2035 nid = EC_GROUP_get_curve_name(ecGroup); /* openssl NID */
2036 /* NID to TCG curve ID */
2037 switch (nid) {
2038 case NID_X9_62_prime256v1:
2039 *curveID = TPM_ECC_NIST_P256;
2040 break;
2041 default:
2042 printf("getEcCurve: Error, curve NID %u not supported \n", nid);
2043 rc = TSS_RC_EC_KEY_CONVERT;
2044 }
2045 }
2046 return rc;
2047 }
2048
2049 #endif /* TPM_TSS_NOECC */
2050 #endif
2051
2052 /* convertBin2Bn() wraps the openSSL function in an error handler
2053
2054 Converts a char array to bignum
2055 */
2056
convertBin2Bn(BIGNUM ** bn,const unsigned char * bin,unsigned int bytes)2057 TPM_RC convertBin2Bn(BIGNUM **bn, /* freed by caller */
2058 const unsigned char *bin,
2059 unsigned int bytes)
2060 {
2061 TPM_RC rc = 0;
2062
2063 /* BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret);
2064
2065 BN_bin2bn() converts the positive integer in big-endian form of length len at s into a BIGNUM
2066 and places it in ret. If ret is NULL, a new BIGNUM is created.
2067
2068 BN_bin2bn() returns the BIGNUM, NULL on error.
2069 */
2070 if (rc == 0) {
2071 *bn = BN_bin2bn(bin, bytes, *bn);
2072 if (*bn == NULL) {
2073 printf("convertBin2Bn: Error in BN_bin2bn\n");
2074 rc = TSS_RC_BIGNUM;
2075 }
2076 }
2077 return rc;
2078 }
2079
2080