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