1 /* SPDX-License-Identifier: BSD-2-Clause */
2 /*******************************************************************************
3  * Copyright 2018-2019, Fraunhofer SIT sponsored by Infineon Technologies AG
4  * All rights reserved.
5  ******************************************************************************/
6 
7 #ifdef HAVE_CONFIG_H
8 #include <config.h>
9 #endif
10 
11 #include <string.h>
12 
13 #include <openssl/evp.h>
14 #include <openssl/aes.h>
15 #include <openssl/rsa.h>
16 #include <openssl/engine.h>
17 #include <openssl/pem.h>
18 #include <openssl/x509v3.h>
19 #include <curl/curl.h>
20 #include <openssl/err.h>
21 
22 #include "fapi_certificates.h"
23 #include "fapi_util.h"
24 #include "util/aux_util.h"
25 #include "fapi_crypto.h"
26 #define LOGMODULE fapi
27 #include "util/log.h"
28 
29 /** Context to hold temporary values for ifapi_crypto */
30 typedef struct _IFAPI_CRYPTO_CONTEXT {
31     /** The hash engine's context */
32     EVP_MD_CTX *osslContext;
33     /** The currently used hash algorithm */
34     const EVP_MD *osslHashAlgorithm;
35     /** The size of the hash's digest */
36     size_t hashSize;
37 } IFAPI_CRYPTO_CONTEXT;
38 
39 /** A singleton crypto engine for hash operations */
40 static ENGINE *engine = NULL;
41 
42 /**
43  * Returns the signature scheme that is currently used in the FAPI context.
44  *
45  * @param[in] profile The FAPI profile from which the signing scheme is
46  *            retrieved
47  * @param[in] tpmPublic The public key for which the signing key is fetched
48  *            from the FAPI
49  * @param[out] signatureScheme The currently used signature scheme
50  *
51  * @retval TSS2_RC_SUCCESS if the signature scheme was successfully fetched
52  * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
53  * @retval TSS2_FAPI_RC_BAD_VALUE if the key type is not TPM2_ALG_RSA or
54  *         TPM2_ALG_ECC
55  */
56 TPM2_RC
ifapi_get_profile_sig_scheme(const IFAPI_PROFILE * profile,const TPMT_PUBLIC * tpmPublic,TPMT_SIG_SCHEME * signatureScheme)57 ifapi_get_profile_sig_scheme(
58     const IFAPI_PROFILE *profile,
59     const TPMT_PUBLIC *tpmPublic,
60     TPMT_SIG_SCHEME *signatureScheme)
61 {
62     /* Check for NULL parameters */
63     return_if_null(profile, "profile is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
64     return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
65     return_if_null(signatureScheme, "signatureScheme is NULL",
66             TSS2_FAPI_RC_BAD_REFERENCE);
67 
68     /* Determine the appropriate signing scheme */
69     if (tpmPublic->type == TPM2_ALG_RSA) {
70         *signatureScheme = profile->rsa_signing_scheme;
71         return TSS2_RC_SUCCESS;
72     } else if (tpmPublic->type == TPM2_ALG_ECC) {
73         *signatureScheme = profile->ecc_signing_scheme;
74         return TSS2_RC_SUCCESS;
75     } else {
76         return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid key type.");
77     }
78 }
79 
80 static const TPM2B_PUBLIC templateRsaSign = {
81     .size = 0,
82     .publicArea = {
83         .type = TPM2_ALG_RSA,
84         .nameAlg = TPM2_ALG_SHA1,
85         .objectAttributes = (TPMA_OBJECT_USERWITHAUTH |
86                              TPMA_OBJECT_SIGN_ENCRYPT |
87                              TPMA_OBJECT_RESTRICTED |
88                              TPMA_OBJECT_SENSITIVEDATAORIGIN
89                              ),
90         .authPolicy = {
91             .size = 0,
92             .buffer = 0,
93         },
94         .parameters.rsaDetail = {
95             .symmetric = {
96                 .algorithm = TPM2_ALG_NULL,
97                 .keyBits.aes = 128,
98                 .mode.aes = TPM2_ALG_CFB,
99             },
100             .scheme = {
101                 .scheme = TPM2_ALG_RSAPSS,
102                 .details.rsapss.hashAlg = TPM2_ALG_SHA1,
103             },
104             .keyBits = 2048,
105             .exponent = 65537,
106         },
107         .unique.rsa = {
108             .size = 0,
109             .buffer = {},
110         }
111     }
112 };
113 
114 /**
115  * A FAPI template for ECC signing keys
116  */
117 static const TPM2B_PUBLIC templateEccSign = {
118     .size = 0,
119     .publicArea = {
120         .type = TPM2_ALG_ECC,
121         .nameAlg = TPM2_ALG_SHA1,
122         .objectAttributes = (
123                              TPMA_OBJECT_USERWITHAUTH |
124                              TPMA_OBJECT_RESTRICTED |
125                              TPMA_OBJECT_SIGN_ENCRYPT |
126                              TPMA_OBJECT_SENSITIVEDATAORIGIN
127                              ),
128         .authPolicy = {
129             .size = 0,
130         },
131 
132         .parameters.eccDetail = {
133             .symmetric = {
134                 .algorithm = TPM2_ALG_NULL,
135                 .keyBits.aes = 128,
136                 .mode.aes = TPM2_ALG_ECB,
137             },
138             .scheme = {
139                 .scheme = TPM2_ALG_ECDSA,
140                 .details = { .ecdsa = { .hashAlg = TPM2_ALG_SHA256 }},
141             },
142             .curveID = TPM2_ECC_BN_P256,
143             .kdf = { .scheme = TPM2_ALG_NULL, .details = {} }
144         },
145         .unique.ecc = {
146             .x = { .size = 0, .buffer = {} },
147             .y = { .size = 0, .buffer = {} },
148         },
149     },
150 };
151 
152 /**
153  * Initializes a FAPI key template for a given signature algorithm.
154  *
155  * @param[in]  signatureAlgorithm The signature algorithm to use. Must be
156  *             TPM2_ALG_RSA or TPM2_ALG_ECC
157  * @param[out] public The template to initialize
158  *
159  * @retval TSS2_RC_SUCCESS on success
160  * @retval TSS2_FAPI_RC_BAD_REFERENCE if template is NULL
161  * @retval TSS2_FAPI_RC_BAD_VALUE if signatureAlgorithm is not TPM2_ALG_RSA or
162  *         TPM2_ALG_ECC
163  */
164 TSS2_RC
ifapi_initialize_sign_public(TPM2_ALG_ID signatureAlgorithm,TPM2B_PUBLIC * public)165 ifapi_initialize_sign_public(TPM2_ALG_ID signatureAlgorithm,
166         TPM2B_PUBLIC *public) {
167 
168     /* Check for NULL parameters */
169     return_if_null(public, "public is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
170 
171     /* Initialize the template */
172     if (signatureAlgorithm == TPM2_ALG_RSA) {
173         /* RSA key template */
174         memcpy(public, &templateRsaSign, sizeof(TPM2B_PUBLIC));
175     } else if (signatureAlgorithm == TPM2_ALG_ECC) {
176         /* ECC key template */
177         memcpy(public, &templateEccSign, sizeof(TPM2B_PUBLIC));
178     } else {
179         /* Invalid key type */
180         LOG_ERROR("No suitable template found");
181         return TSS2_FAPI_RC_BAD_VALUE;
182     }
183     return TSS2_RC_SUCCESS;
184 }
185 
186 /**
187  * Converts an openSSL BIGNUM into a binary byte buffer using.
188  *
189  * @param[in]  bn The BIGNUM to convert
190  * @param[out] bin The binary buffer to which the bignum is converted
191  * @param[in]  binSize The size of bin in bytes
192  *
193  * @retval 1 if the conversion was successful
194  * @retval 0 if one of the parameters is NULL
195  */
196 static int
ifapi_bn2binpad(const BIGNUM * bn,unsigned char * bin,int binSize)197 ifapi_bn2binpad(const BIGNUM *bn, unsigned char *bin, int binSize)
198 {
199     /* Check for NULL parameters */
200     return_if_null(bn, "bn is NULL", 0);
201     return_if_null(bin, "bin is NULL", 0);
202 
203     /* Convert bn */
204     int bnSize = BN_num_bytes(bn);
205     int offset = binSize - bnSize;
206     memset(bin, 0, offset);
207     BN_bn2bin(bn, bin + offset);
208     return 1;
209 }
210 
211 /**
212  * Returns the singleton hash engine for the use in ifapi_hash operations. If
213  * it does not yet exist, this function creates it.
214  *
215  * @retval A singleton hash engine
216  */
217 static ENGINE *
get_engine()218 get_engine()
219 {
220     /* If an engine is present, it is returned */
221     if (engine)
222         return engine;
223     /* Otherwise, engine is created and returned */
224     engine = ENGINE_by_id(NULL);
225     return engine;
226 }
227 
228 /**
229  * Returns a suitable openSSL hash algorithm identifier for a given TSS hash
230  * algorithm identifier.
231  *
232  * @param[in] hashAlgorithm The TSS hash algorithm identifier
233  *
234  * @retval An openSSL hash algorithm identifier if one that is suitable to
235  *         hashAlgorithm could be found
236  * @retval NULL if no suitable hash algorithm identifier could be found
237  */
238 static const EVP_MD *
get_hash_md(TPM2_ALG_ID hashAlgorithm)239 get_hash_md(TPM2_ALG_ID hashAlgorithm)
240 {
241     switch (hashAlgorithm) {
242     case TPM2_ALG_SHA1:
243         return EVP_sha1();
244     case TPM2_ALG_SHA256:
245         return EVP_sha256();
246     case TPM2_ALG_SHA384:
247         return EVP_sha384();
248     case TPM2_ALG_SHA512:
249         return EVP_sha512();
250     default:
251         return NULL;
252     }
253 }
254 
255 /**
256  * Returns a suitable openSSL RSA signature scheme identifiver for a given TSS
257  * RSA signature scheme identifier.
258  *
259  * @param[in] signatureScheme The TSS RSA signature scheme identifier
260  *
261  * @retval RSA_PCKS1_PSS_PADDING if signatureScheme is TPM2_ALG_RSAPSS
262  * @retval RSA_PKCS1_PADDING if signatureScheme is TPM2_ALG_RSASSA
263  * @retval 0 otherwise
264  */
265 static int
get_sig_scheme(TPM2_ALG_ID signatureScheme)266 get_sig_scheme(TPM2_ALG_ID signatureScheme)
267 {
268     switch (signatureScheme) {
269     case TPM2_ALG_RSAPSS:
270         return RSA_PKCS1_PSS_PADDING;
271     case TPM2_ALG_RSASSA:
272         return RSA_PKCS1_PADDING;
273     default:
274         return 0;
275     }
276 }
277 
278 /**
279  * Convert a TPM ECDSA signature into a DER formatted byte buffer. This can be
280  * used by TLS libraries.
281  *
282  * @param[in]  tpmSignature The signature created by the TPM
283  * @param[out] signature A byte buffer that will hold the DER representation of
284  *             the signature  (callee allocated)
285  * @param[out] signatureSize The size of signature in bytes. May be NULL
286  *
287  * @retval TSS2_RC_SUCCESS on success
288  * @retval TSS2_FAPI_RC_BAD_REFERENCE if tpmSignature is NULL
289  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
290  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
291  */
292 TSS2_RC
ifapi_tpm_ecc_sig_to_der(const TPMT_SIGNATURE * tpmSignature,uint8_t ** signature,size_t * signatureSize)293 ifapi_tpm_ecc_sig_to_der(
294     const TPMT_SIGNATURE *tpmSignature,
295     uint8_t **signature,
296     size_t *signatureSize)
297 {
298     /* Check for NULL parameters */
299     return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
300 
301     ECDSA_SIG *ecdsaSignature = NULL;
302     BIGNUM *bns = NULL, *bnr = NULL;
303     int osslRC;
304     TSS2_RC r;
305     uint8_t *signatureWalking;
306 
307     /* Initialize an OpenSSL ECDSA signature which servers as an intermediate
308      * between the TSS ECDSA signature and the DER byte buffer */
309     ecdsaSignature = ECDSA_SIG_new();
310     goto_if_null(ecdsaSignature, "Out of memory", TSS2_FAPI_RC_MEMORY,
311                  cleanup);
312 
313     bns = BN_bin2bn(&tpmSignature->signature.ecdsa.signatureS.buffer[0],
314                     tpmSignature->signature.ecdsa.signatureS.size, NULL);
315     goto_if_null(bns, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
316 
317     bnr = BN_bin2bn(&tpmSignature->signature.ecdsa.signatureR.buffer[0],
318                     tpmSignature->signature.ecdsa.signatureR.size, NULL);
319     goto_if_null(bnr, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
320 
321 #if OPENSSL_VERSION_NUMBER < 0x10100000
322     ecdsaSignature->s = bns;
323     ecdsaSignature->r = bnr;
324 #else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
325     ECDSA_SIG_set0(ecdsaSignature, bnr, bns);
326 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
327 
328     osslRC = i2d_ECDSA_SIG(ecdsaSignature, NULL);
329     if (osslRC == -1) {
330         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error", cleanup);
331     }
332 
333     /* Initialize the byte buffer for the DER representation */
334     *signature = malloc(osslRC);
335     signatureWalking = *signature;
336     goto_if_null(*signature, "Out of memory", TSS2_FAPI_RC_MEMORY, cleanup);
337 
338     if (signatureSize != NULL) {
339         *signatureSize = osslRC;
340     }
341 
342     /* Convert the OpenSSL ECDSA signature to the DER buffer */
343     osslRC = i2d_ECDSA_SIG(ecdsaSignature, &signatureWalking);
344     if (!osslRC) {
345         free(*signature);
346         if (signatureSize != NULL) {
347             *signatureSize = 0;
348         }
349         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error", cleanup);
350     }
351     r = TSS2_RC_SUCCESS;
352 
353 cleanup:
354     if (ecdsaSignature)
355         ECDSA_SIG_free(ecdsaSignature);
356     return r;
357 }
358 
359 /**
360  * Converts a public RSA key created by the TPM into one that can be used by
361  * OpenSSL.
362  *
363  * @param[in]  tpmPublicKey The public RSA key created by the TPM
364  * @param[out] evpPublicKey The converted public RSA key that can be used by
365  *             OpenSSL
366  *
367  * @retval TSS2_RC_SUCCESS on success
368  * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
369  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
370  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
371  */
372 static TSS2_RC
ossl_rsa_pub_from_tpm(const TPM2B_PUBLIC * tpmPublicKey,EVP_PKEY * evpPublicKey)373 ossl_rsa_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey)
374 {
375     /* Check for NULL parameters */
376     return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
377     return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
378 
379     /* Initialize the RSA parameters */
380     TSS2_RC r;
381     RSA *rsa = RSA_new();
382     BIGNUM *e = BN_new();
383     BIGNUM *d = BN_new();
384     BIGNUM *p = BN_new();
385     BIGNUM *q = BN_new();
386     BIGNUM *dmp1 = BN_new();
387     BIGNUM *dmq1 = BN_new();
388     BIGNUM *iqmp = BN_new();
389     BIGNUM *n = BN_bin2bn(tpmPublicKey->publicArea.unique.rsa.buffer,
390                           tpmPublicKey->publicArea.unique.rsa.size, NULL);
391 
392     if (!n || !e || !d || !p || !q || !dmp1 || !dmq1 || !iqmp || !rsa) {
393         goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup);
394     }
395 
396     BN_set_word(d, 0);
397     BN_set_word(p, 0);
398     BN_set_word(q, 0);
399     BN_set_word(dmp1, 0);
400     BN_set_word(dmq1, 0);
401     BN_set_word(iqmp, 0);
402     uint32_t exp;
403     if (tpmPublicKey->publicArea.parameters.rsaDetail.exponent == 0)
404         exp = 65537;
405     else
406         exp = tpmPublicKey->publicArea.parameters.rsaDetail.exponent;
407     if (1 != BN_set_word(e, exp)) {
408         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
409                    "Could not set exponent.", error_cleanup);
410     }
411 
412 #if OPENSSL_VERSION_NUMBER < 0x10100000
413     rsa->e = e;
414     rsa->n = n;
415     rsa->d = d;
416     rsa->p = p;
417     rsa->q = q;
418     rsa->dmp1 = dmp1;
419     rsa->dmq1 = dmq1;
420     rsa->iqmp = iqmp;
421 #else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
422     RSA_set0_key(rsa, n, e, d);
423     RSA_set0_factors(rsa, p, q);
424     RSA_set0_crt_params(rsa, dmp1, dmq1, iqmp);
425 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
426 
427     /* Assign the parameters to the key */
428     if (!EVP_PKEY_assign_RSA(evpPublicKey, rsa)) {
429         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign rsa key",
430                    error_cleanup);
431     }
432     return TSS2_RC_SUCCESS;
433 
434 error_cleanup:
435     OSSL_FREE(rsa, RSA);
436     OSSL_FREE(e, BN);
437     OSSL_FREE(n, BN);
438     OSSL_FREE(d, BN);
439     OSSL_FREE(p, BN);
440     OSSL_FREE(q, BN);
441     OSSL_FREE(dmp1, BN);
442     OSSL_FREE(dmq1, BN);
443     OSSL_FREE(iqmp, BN);
444     return r;
445 }
446 
447 /**
448  * Converts a public ECC key created by the TPM into one that can be used by
449  * OpenSSL.
450  *
451  * @param[in]  tpmPublicKey The public ECC key created by the TPM
452  * @param[out] evpPublicKey The converted public ECC key that can be used by
453  *             OpenSSL
454  *
455  * @retval TSS2_RC_SUCCESS on success
456  * @retval TSS2_FAPI_RC_BAD_REFERENCE if one of the parameters is NULL
457  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
458  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
459  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
460  *         the function.
461  */
462 static TSS2_RC
ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC * tpmPublicKey,EVP_PKEY * evpPublicKey)463 ossl_ecc_pub_from_tpm(const TPM2B_PUBLIC *tpmPublicKey, EVP_PKEY *evpPublicKey)
464 {
465     /* Check for NULL parameters */
466     return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
467     return_if_null(evpPublicKey, "evpPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
468 
469     TSS2_RC r;
470     EC_GROUP *ecgroup = NULL;
471     int curveId;
472     BIGNUM *x = NULL, *y = NULL;
473     EC_KEY *ecKey = EC_KEY_new();
474     return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
475 
476     /* Find the curve of the ECC key */
477     switch (tpmPublicKey->publicArea.parameters.eccDetail.curveID) {
478     case TPM2_ECC_NIST_P192:
479         curveId = NID_X9_62_prime192v1;
480         break;
481     case TPM2_ECC_NIST_P224:
482         curveId = NID_secp224r1;
483         break;
484     case TPM2_ECC_NIST_P256:
485         curveId = NID_X9_62_prime256v1;
486         break;
487     case TPM2_ECC_NIST_P384:
488         curveId = NID_secp384r1;
489         break;
490     case TPM2_ECC_NIST_P521:
491         curveId = NID_secp521r1;
492         break;
493     default:
494         return_error(TSS2_FAPI_RC_BAD_VALUE,
495                      "ECC curve not implemented.");
496     }
497 
498     /* Initialize the OpenSSL ECC key with its group */
499     ecgroup = EC_GROUP_new_by_curve_name(curveId);
500     goto_if_null(ecgroup, "new EC group.", TSS2_FAPI_RC_GENERAL_FAILURE,
501                   error_cleanup);
502 
503     if (!EC_KEY_set_group(ecKey, ecgroup)) {
504         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EC_KEY_set_group",
505                    error_cleanup);
506     }
507     EC_GROUP_free(ecgroup);
508 
509     /* Set the ECC parameters in the OpenSSL key */
510     x = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.x.buffer,
511                   tpmPublicKey->publicArea.unique.ecc.x.size, NULL);
512 
513     y = BN_bin2bn(tpmPublicKey->publicArea.unique.ecc.y.buffer,
514                   tpmPublicKey->publicArea.unique.ecc.y.size, NULL);
515 
516     if (!x || !y) {
517         goto_error(r, TSS2_FAPI_RC_MEMORY, "Out of memory", error_cleanup);
518     }
519 
520     if (!EC_KEY_set_public_key_affine_coordinates(ecKey, x, y)) {
521         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
522                    "EC_KEY_set_public_key_affine_coordinates", error_cleanup);
523     }
524 
525     if (!EVP_PKEY_assign_EC_KEY(evpPublicKey, ecKey)) {
526         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Assign ecc key",
527                    error_cleanup);
528     }
529     /* Needed for older OSSL versions. */
530     EC_KEY_set_asn1_flag(ecKey, OPENSSL_EC_NAMED_CURVE);
531     OSSL_FREE(y, BN);
532     OSSL_FREE(x, BN);
533     return TSS2_RC_SUCCESS;
534 
535 error_cleanup:
536     OSSL_FREE(y, BN);
537     OSSL_FREE(x, BN);
538     OSSL_FREE(ecKey, EC_KEY);
539     return r;
540 }
541 
542 /**
543  * Convert a TPM public key into a PEM formatted byte buffer. This can be
544  * used by TLS libraries.
545  *
546  * @param[in]  tpmPublicKey The public key created by the TPM
547  * @param[out] pemKey A byte buffer that will hold the PEM representation of
548  *             the public key  (callee allocated)
549  * @param[out] pemKeySize The size of pemKey in bytes
550  *
551  * @retval TSS2_RC_SUCCESS on success
552  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
553  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
554  * @retval TSS2_FAPI_BAD_REFERENCE if tpmPublicKey or pemKeySize are NULL
555  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
556  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
557  *         the function.
558  */
559 TSS2_RC
ifapi_pub_pem_key_from_tpm(const TPM2B_PUBLIC * tpmPublicKey,char ** pemKey,int * pemKeySize)560 ifapi_pub_pem_key_from_tpm(
561     const TPM2B_PUBLIC *tpmPublicKey,
562     char **pemKey,
563     int *pemKeySize)
564 {
565     /* Check for NULL parameters */
566     return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
567     return_if_null(pemKeySize, "pemKeySize is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
568 
569     EVP_PKEY *evpPublicKey = NULL;
570     BIO *bio = NULL;
571     TSS2_RC r = TPM2_RC_SUCCESS;
572 
573     evpPublicKey = EVP_PKEY_new();
574     goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
575 
576     /* Memory IO will be used for OSSL key conversion */
577     bio = BIO_new(BIO_s_mem());
578     goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
579 
580     if (tpmPublicKey->publicArea.type == TPM2_ALG_RSA) {
581         r = ossl_rsa_pub_from_tpm(tpmPublicKey, evpPublicKey);
582     } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC)
583         r = ossl_ecc_pub_from_tpm(tpmPublicKey, evpPublicKey);
584     else {
585         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid alg id.", cleanup);
586     }
587     goto_if_error(r, "Get ossl public key.", cleanup);
588 
589     if (!PEM_write_bio_PUBKEY(bio, evpPublicKey)) {
590         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "PEM_write_bio_PUBKEY",
591                    cleanup);
592     }
593 
594     /* Determine the size of the data written */
595     *pemKeySize = BIO_get_mem_data(bio, pemKey);
596     *pemKey = malloc(*pemKeySize+1);
597     goto_if_null(*pemKey, "Out of memory.", TSS2_FAPI_RC_MEMORY,
598             cleanup);
599     memset(*pemKey, 0, *pemKeySize + 1);
600 
601     /* Get the byte buffer written to the BIO object */
602     int readSize = BIO_read(bio, *pemKey, *pemKeySize);
603     if (readSize != *pemKeySize) {
604         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid BIO_read",
605                    cleanup);
606     }
607 
608 cleanup:
609     EVP_PKEY_free(evpPublicKey);
610     BIO_free(bio);
611     return r;
612 }
613 
614 /** Converts an ECDSA signature from a DER encoded byte buffer into the
615  * TPM format. It can then be verified by the TPM.
616  *
617  * @param[in]  signature A DER encoded byte buffer holding the signature
618  * @param[in]  signatureSize The size of signature in bytes
619  * @param[in]  keySize The size of the verification key
620  * @param[in]  hashAlgorithm The TSS identifier of the hash algorithm to use
621  * @param[out] tpmSignature The signature in the TPM format
622  *
623  * @retval TSS2_RC_SUCCESS on success
624  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
625  * @retval TSS2_FAPI_RC_BAD_REFERENCE if signature or tpmSignature is NULL
626  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
627  */
628 static TSS2_RC
ifapi_ecc_der_sig_to_tpm(const unsigned char * signature,size_t signatureSize,int keySize,TPMI_ALG_HASH hashAlgorithm,TPMT_SIGNATURE * tpmSignature)629 ifapi_ecc_der_sig_to_tpm(
630     const unsigned char *signature,
631     size_t signatureSize,
632     int keySize,
633     TPMI_ALG_HASH hashAlgorithm,
634     TPMT_SIGNATURE *tpmSignature)
635 {
636     /* Check for NULL parameters */
637     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
638     return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
639 
640     /* Initialize the ECDSA signature components */
641     ECDSA_SIG *ecdsaSignature = NULL;
642 #if OPENSSL_VERSION_NUMBER < 0x10100000
643     BIGNUM *bnr;
644     BIGNUM *bns;
645 #else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
646     const BIGNUM *bnr;
647     const BIGNUM *bns;
648 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
649 
650     d2i_ECDSA_SIG(&ecdsaSignature, &signature, signatureSize);
651     return_if_null(ecdsaSignature, "Invalid DER signature",
652                    TSS2_FAPI_RC_GENERAL_FAILURE);
653 
654 #if OPENSSL_VERSION_NUMBER < 0x10100000
655     bns = ecdsaSignature->s;
656     bnr = ecdsaSignature->r;
657 #else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
658     ECDSA_SIG_get0(ecdsaSignature, &bnr, &bns);
659 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
660 
661     /* Writing them to the TPM format signature */
662     tpmSignature->signature.ecdsa.hash = hashAlgorithm;
663     tpmSignature->sigAlg = TPM2_ALG_ECDSA; /**< only ECDSA is used by FAPI */
664     ifapi_bn2binpad(bnr, &tpmSignature->signature.ecdsa.signatureR.buffer[0],
665                        keySize);
666     tpmSignature->signature.ecdsa.signatureR.size = keySize;
667     ifapi_bn2binpad(bns, &tpmSignature->signature.ecdsa.signatureS.buffer[0],
668                        keySize);
669     tpmSignature->signature.ecdsa.signatureS.size = keySize;
670     OSSL_FREE(ecdsaSignature, ECDSA_SIG);
671     //OSSL_FREE(bnr, BN);
672     //OSSL_FREE(bns, BN);
673     return TSS2_RC_SUCCESS;
674 }
675 
676 /** Convert signature from DER to TPM format.
677  *
678  * The signature in DER format is converted to TPM format to
679  * enable verification by the TPM.
680  *
681  * @param[in] tpmPublic The public information of the signature key
682  * @param[in] signature A byte buffer holding the DER encoded signature
683  * @param[in] signatureSize The size of signature in bytes
684  * @param[in] hashAlgorithm The TSS identifier for the hash algorithm used
685  *            to compute the digest
686  * @param[out] tpmSignature The signature in TPM format
687  *
688  * @retval TSS2_RC_SUCCESS on success
689  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
690  * @retval TSS2_FAPI_RC_BAD_REFERENCE if tpmPublic, signature or tpmSignature is NULL
691  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
692  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
693  *         the function.
694  */
695 TSS2_RC
ifapi_der_sig_to_tpm(const TPMT_PUBLIC * tpmPublic,const unsigned char * signature,size_t signatureSize,TPMI_ALG_HASH hashAlgorithm,TPMT_SIGNATURE * tpmSignature)696 ifapi_der_sig_to_tpm(
697     const TPMT_PUBLIC *tpmPublic,
698     const unsigned char *signature,
699     size_t signatureSize,
700     TPMI_ALG_HASH hashAlgorithm,
701     TPMT_SIGNATURE *tpmSignature)
702 {
703     /* Check for NULL parameters */
704     return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
705     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
706     return_if_null(tpmSignature, "tpmSignature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
707 
708     /* Convert the signature */
709     if (tpmPublic->type == TPM2_ALG_RSA) {
710         if (tpmPublic->parameters.rsaDetail.scheme.scheme == TPM2_ALG_RSAPSS) {
711             tpmSignature->sigAlg = TPM2_ALG_RSAPSS;
712             tpmSignature->signature.rsapss.hash = hashAlgorithm;
713             tpmSignature->signature.rsapss.sig.size = signatureSize;
714             memcpy(&tpmSignature->signature.rsapss.sig.buffer[0], signature,
715                     signatureSize);
716         } else if (tpmPublic->parameters.rsaDetail.scheme.scheme == TPM2_ALG_RSASSA) {
717             tpmSignature->sigAlg = TPM2_ALG_RSASSA;
718             tpmSignature->signature.rsassa.hash = hashAlgorithm;
719             tpmSignature->signature.rsassa.sig.size = signatureSize;
720             memcpy(&tpmSignature->signature.rsassa.sig.buffer[0], signature,
721                     signatureSize);
722         } else {
723             return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid RSA scheme.");
724 
725         }
726     } else if (tpmPublic->type == TPM2_ALG_ECC) {
727         return ifapi_ecc_der_sig_to_tpm(signature, signatureSize,
728                                         tpmPublic->unique.ecc.x.size, hashAlgorithm,
729                                         tpmSignature);
730     } else {
731         return_error(TSS2_FAPI_RC_BAD_VALUE, "Invalid key tpye.");
732     }
733     return TSS2_RC_SUCCESS;
734 }
735 
736 /**
737  * Size of the table with the possible padding schemes
738  */
739 #define N_PADDING 2
740 
741 /**
742  * Table with possible padding schemes to guess the one appropriate for
743  * for RSA signature verification
744  */
745 static const int rsaPadding[N_PADDING] = { RSA_PKCS1_PADDING, RSA_PKCS1_PSS_PADDING };
746 
747 /**
748  * Verifies an RSA signature given as a binary byte buffer.
749  *
750  * @param[in] publicKey The public key with which the signature is to be
751  *            verified
752  * @param[in] signature A byte buffer holding the signature to verify
753  * @param[in] signatureSize The size of signature in bytes
754  * @param[in] digest The digest of the signature to verify
755  * @param[in] digestSize The size of digest in bytes. Required to determine the
756  *            hash algorithm
757  *
758  * @retval TSS2_RC_SUCCESS on success
759  * @retval TSS2_FAPI_RC_BAD_REFERENCE if publicKey, signature or digest is NULL
760  * @retval TSS2_FAPI_RC_BAD_VALUE if no hash algorithm that matches digestSize
761  *         could be found
762  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
763  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the signature could not
764  *         be verified
765  */
766 static TSS2_RC
rsa_verify_signature(EVP_PKEY * publicKey,const uint8_t * signature,size_t signatureSize,const uint8_t * digest,size_t digestSize)767 rsa_verify_signature(
768     EVP_PKEY *publicKey,
769     const uint8_t *signature,
770     size_t signatureSize,
771     const uint8_t *digest,
772     size_t digestSize)
773 {
774     /* Check for NULL parameters */
775     return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
776     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
777     return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
778 
779     TSS2_RC r;
780     const EVP_MD *mdType;
781     EVP_PKEY_CTX *ctx = NULL;
782 
783     /* The hash algorithm of the signature is determined by the digest length */
784     switch (digestSize) {
785     case TPM2_SHA1_DIGEST_SIZE:
786         mdType = EVP_sha1();
787         break;
788     case TPM2_SHA256_DIGEST_SIZE:
789         mdType = EVP_sha256();
790         break;
791     case TPM2_SHA384_DIGEST_SIZE:
792         mdType = EVP_sha384();
793         break;
794     case TPM2_SHA512_DIGEST_SIZE:
795         mdType = EVP_sha512();
796         break;
797     default:
798         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Invalid digest size", cleanup);
799     }
800 
801     /* Try all possible padding schemes for verification */
802     for (int i = 0; i < N_PADDING; i++) {
803         ctx = EVP_PKEY_CTX_new(publicKey, NULL);
804         if (!ctx) {
805             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Get pkey context.",
806                        cleanup);
807         }
808         if (EVP_PKEY_verify_init(ctx) <= 0) {
809             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Verify init.",
810                        cleanup);
811         }
812         if (EVP_PKEY_CTX_set_rsa_padding(ctx, rsaPadding[i]) <= 0) {
813             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
814                        "EVP_PKEY_CTX_set_rsa_padding", cleanup);
815         }
816         if (EVP_PKEY_CTX_set_signature_md(ctx, mdType) <= 0) {
817             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
818                        "Verify set signature md.", cleanup);
819         }
820         if (1 != EVP_PKEY_verify(ctx, signature, signatureSize, digest, digestSize)) {
821             /* padding scheme was not appropriate, next should be tried */
822             EVP_PKEY_CTX_free(ctx);
823         } else {
824             /* Verification with selected padding scheme was successful */
825             r = TSS2_RC_SUCCESS;
826             goto cleanup;
827         }
828     }
829     /* Verification was not successful with one of the possible padding schemes */
830     r = TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED;
831 
832 cleanup:
833     EVP_PKEY_CTX_free(ctx);
834     return r;
835 }
836 
837 /**
838  * Verifies an ECDSA signature given as a binary byte buffer.
839  *
840  * @param[in] publicKey The public key with which the signature is to be
841  *            verified
842  * @param[in] signature A byte buffer holding the signature to verify
843  * @param[in] signatureSize The size of signature in bytes
844  * @param[in] digest The digest of the signature to verify
845  * @param[in] digestSize The size of digest in bytes. Required to determine the
846  *            hash algorithm
847  *
848  * @retval TSS2_RC_SUCCESS on success
849  * @retval TSS2_FAPI_RC_BAD_REFERENCE if publicKey, signature or digest is NULL
850  * @retval TSS2_FAPI_RC_BAD_VALUE if no hash algorithm that matches digestSize
851  *         could be found
852  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
853  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the signature could not
854  *         be verified
855  */
856 static TSS2_RC
ecdsa_verify_signature(EVP_PKEY * publicKey,const uint8_t * signature,size_t signatureSize,const uint8_t * digest,size_t digestSize)857 ecdsa_verify_signature(
858     EVP_PKEY *publicKey,
859     const uint8_t *signature,
860     size_t signatureSize,
861     const uint8_t *digest,
862     size_t digestSize)
863 {
864     /* Check for NULL parameters */
865     return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
866     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
867     return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
868 
869     TSS2_RC r = TSS2_RC_SUCCESS;
870     EC_KEY *eccKey = NULL;
871 
872     eccKey = EVP_PKEY_get1_EC_KEY(publicKey);
873 
874     /* Try to verify the signature using ECDSA, note that param 0 is unused */
875     int rc = ECDSA_verify(0, digest, digestSize, signature, signatureSize, eccKey);
876     if (rc == 0) {
877         goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
878                    "ECDSA signature verification failed.", error_cleanup);
879     } else if (rc < 0) {
880         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
881                    "ECDSA signature verification failed.", error_cleanup);
882     }
883 
884 error_cleanup:
885     OSSL_FREE(eccKey, EC_KEY);
886     return r;
887 }
888 
889 /**
890  * Gets an object with the TPM-relevant public information of an OpenSSL
891  * RSA public key.
892  *
893  * @param[in,out] profile The crypto profile from which parameters are retrieved
894  * @param[in]  publicKey The public key for which the public information is
895  *             retrieved
896  * @param[out] tpmPublic The public information of publicKey
897  *
898  * @retval TSS2_RC_SUCCESS on success
899  * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, publicKey or tpmPublic is NULL
900  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
901  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
902  */
903 static TSS2_RC
get_rsa_tpm2b_public_from_evp(EVP_PKEY * publicKey,TPM2B_PUBLIC * tpmPublic)904 get_rsa_tpm2b_public_from_evp(
905     EVP_PKEY *publicKey,
906     TPM2B_PUBLIC *tpmPublic)
907 {
908     /* Check for NULL parameters */
909     return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
910     return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
911 
912     /* Extract the public information */
913     TSS2_RC r = TSS2_RC_SUCCESS;
914     RSA *rsaKey = EVP_PKEY_get1_RSA(publicKey);
915     return_if_null(rsaKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
916     const BIGNUM *e = NULL, *n = NULL;
917     int rsaKeySize = RSA_size(rsaKey);
918 
919 #if OPENSSL_VERSION_NUMBER < 0x10100000
920     e = rsaKey->e;
921     n = rsaKey->n;
922 #else /* OPENSSL_VERSION_NUMBER < 0x10100000 */
923     RSA_get0_key(rsaKey, &n, &e, NULL);
924 #endif /* OPENSSL_VERSION_NUMBER < 0x10100000 */
925     tpmPublic->publicArea.unique.rsa.size = rsaKeySize;
926     if (1 != ifapi_bn2binpad(n, &tpmPublic->publicArea.unique.rsa.buffer[0],
927                              rsaKeySize)) {
928         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
929                    "Write big num byte buffer", cleanup);
930     }
931     tpmPublic->publicArea.parameters.rsaDetail.keyBits = rsaKeySize * 8;
932     tpmPublic->publicArea.parameters.rsaDetail.exponent = BN_get_word(e);
933 
934 cleanup:
935     OSSL_FREE(rsaKey, RSA);
936     return r;
937 }
938 
939 /**
940  * Gets an object with the TPM-relevant public information of an OpenSSL
941  * ECC public key.
942  *
943  * @param[in,out] profile The crypto profile to retrieve parameters from.
944  * @param[in]  publicKey The public key for which the public information is
945  *             retrieved
946  * @param[out] tpmPublic The public information of publicKey
947  *
948  * @retval TSS2_RC_SUCCESS on success
949  * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, publicKey or tpmPublic is NULL
950  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
951  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
952  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
953  *         the function.
954  */
955 static TSS2_RC
get_ecc_tpm2b_public_from_evp(EVP_PKEY * publicKey,TPM2B_PUBLIC * tpmPublic)956 get_ecc_tpm2b_public_from_evp(
957     EVP_PKEY *publicKey,
958     TPM2B_PUBLIC *tpmPublic)
959 {
960     /* Check for NULL parameters */
961     return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
962     return_if_null(tpmPublic, "tpmPublic is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
963 
964     /* Initialize variables that will contain the relevant information */
965     TSS2_RC r = TSS2_RC_SUCCESS;
966     EC_KEY *ecKey = EVP_PKEY_get1_EC_KEY(publicKey);
967     return_if_null(ecKey, "Out of memory.", TSS2_FAPI_RC_MEMORY);
968     const EC_GROUP *ecGroup;
969     const EC_POINT *publicPoint;
970     int curveId;
971     size_t ecKeySize;
972     BIGNUM *bnX = NULL;
973     BIGNUM *bnY = NULL;
974     TPMI_ECC_CURVE tpmCurveId;
975 
976     if (!ecKey) {
977         return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "No ECC key!");
978     }
979 
980     /* Retrieve the relevant information and write it to tpmPublic */
981     ecGroup = EC_KEY_get0_group(ecKey);
982     publicPoint = EC_KEY_get0_public_key(ecKey);
983     curveId = EC_GROUP_get_curve_name(ecGroup);
984     ecKeySize = EC_GROUP_get_degree(ecGroup) / 8;
985     tpmPublic->publicArea.unique.ecc.x.size = ecKeySize;
986     tpmPublic->publicArea.unique.ecc.y.size = ecKeySize;
987 
988     if (!(bnX = BN_new())) {
989         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create bignum", cleanup);
990     }
991 
992     if (!(bnY = BN_new())) {
993         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Create bignum", cleanup);
994     }
995 
996     if (1 != EC_POINT_get_affine_coordinates_GFp(ecGroup, publicPoint,
997                                                  bnX, bnY, NULL)) {
998         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
999                    "Get affine coordinates", cleanup);
1000     }
1001     if (1 != ifapi_bn2binpad(bnX, &tpmPublic->publicArea.unique.ecc.x.buffer[0],
1002                              ecKeySize)) {
1003         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1004                    "Write big num byte buffer", cleanup);
1005     }
1006     if (1 != ifapi_bn2binpad(bnY, &tpmPublic->publicArea.unique.ecc.y.buffer[0],
1007                              ecKeySize)) {
1008         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1009                    "Write big num byte buffer", cleanup);
1010     }
1011     switch (curveId) {
1012     case NID_X9_62_prime192v1:
1013         tpmCurveId = TPM2_ECC_NIST_P192;
1014         break;
1015     case NID_secp224r1:
1016         tpmCurveId = TPM2_ECC_NIST_P224;
1017         break;
1018     case NID_X9_62_prime256v1:
1019         tpmCurveId = TPM2_ECC_NIST_P256;
1020         break;
1021     case NID_secp384r1:
1022         tpmCurveId = TPM2_ECC_NIST_P384;
1023         break;
1024     case NID_secp521r1:
1025         tpmCurveId = TPM2_ECC_NIST_P521;
1026         break;
1027     default:
1028         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
1029                    "Curve %x not implemented", cleanup, curveId);
1030     }
1031     tpmPublic->publicArea.parameters.eccDetail.curveID = tpmCurveId;
1032 
1033 cleanup:
1034     OSSL_FREE(ecKey, EC_KEY);
1035     OSSL_FREE(bnX, BN);
1036     OSSL_FREE(bnY, BN);
1037     return r;
1038 }
1039 
1040 /**
1041  * Converts a given PEM key into an EVP public key object.
1042  *
1043  * @param[in] pemKey A byte buffer holding the PEM key to convert
1044  * @param[out] publicKey An EVP public key
1045  *
1046  * @retval TSS2_FAPI_RC_BAD_REFERENCE if any of the parameters is NULL
1047  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
1048  * @retval TSS2_FAPI_RC_BAD_VALUE if the PEM key could not be decoded
1049  */
1050 static TSS2_RC
ifapi_get_evp_from_pem(const char * pemKey,EVP_PKEY ** publicKey)1051 ifapi_get_evp_from_pem(const char *pemKey, EVP_PKEY **publicKey) {
1052     /* Check for NULL parameters */
1053     return_if_null(pemKey, "pemKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1054     return_if_null(publicKey, "publicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1055 
1056     TSS2_RC r = TSS2_RC_SUCCESS;
1057     BIO *bufio = NULL;
1058 
1059     /* Use BIO for conversion */
1060     bufio = BIO_new_mem_buf((void *)pemKey, strlen(pemKey));
1061     goto_if_null(bufio, "BIO buffer could not be allocated.",
1062                  TSS2_FAPI_RC_MEMORY, cleanup);
1063 
1064     /* Convert the key */
1065     *publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
1066     goto_if_null(*publicKey, "PEM format could not be decoded.",
1067                  TSS2_FAPI_RC_BAD_VALUE, cleanup);
1068 cleanup:
1069     BIO_free(bufio);
1070     return r;
1071 }
1072 
1073 /**
1074  * Returns the TPM algorithm identifier that matches to the signature algorithm
1075  * of a given PEM key.
1076  *
1077  * @param[in] pemKey The public key from which the signature algorithm is retrieved
1078  *
1079  * @retval TPM2_ALG_RSA if pemKey holds an RSA key
1080  * @retval TPM2_ALG_ECC if pemKey holds an ECC key
1081  * @retval TPM2_ALG_ERROR if the signature algorithm could not be determined
1082  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1083  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1084  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1085  *         the function.
1086  */
1087 TPM2_ALG_ID
ifapi_get_signature_algorithm_from_pem(const char * pemKey)1088 ifapi_get_signature_algorithm_from_pem(const char *pemKey) {
1089     /* Check for NULL parameters */
1090     return_if_null(pemKey, "pemKey is NULL", TPM2_ALG_ERROR);
1091 
1092     /* Get an EVP object for the key */
1093     EVP_PKEY * publicKey = NULL;
1094     TPM2_ALG_ID algorithmId = TPM2_ALG_ERROR;
1095     TSS2_RC r = ifapi_get_evp_from_pem(pemKey, &publicKey);
1096     if (r != TSS2_RC_SUCCESS || publicKey == NULL) {
1097         LOG_ERROR("Could not get an EVP key from the PEM key");
1098         algorithmId = TPM2_ALG_ERROR;
1099         goto cleanup;
1100     }
1101 
1102     /* Determine the signature algorithm of the converted key */
1103     if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
1104         algorithmId = TPM2_ALG_RSA;
1105     } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
1106         algorithmId = TPM2_ALG_ECC;
1107     } else {
1108         algorithmId = TPM2_ALG_ERROR;
1109     }
1110 
1111 cleanup:
1112     OSSL_FREE(publicKey, EVP_PKEY);
1113     return algorithmId;
1114 }
1115 
1116 /**
1117  * Gets an object with the TPM-relevant public information of a PEM encoded
1118  * public key. The information is gathered from the key itself and the currently
1119  * used FAPI profile.
1120  *
1121  * @param[in]  pemKey A byte buffer holding the PEM encoded public key for
1122  *             which the public information is retrieved
1123  * @param[out] tpmPublic The public information of pemKey
1124  *
1125  * @retval TSS2_RC_SUCCESS on success
1126  * @retval TSS2_FAPI_RC_BAD_REFERENCE if profile, pemKey or tpmPublic is NULL
1127  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
1128  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1129  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1130  *         the function.
1131  */
1132 TSS2_RC
ifapi_get_tpm2b_public_from_pem(const char * pemKey,TPM2B_PUBLIC * tpmPublic)1133 ifapi_get_tpm2b_public_from_pem(
1134     const char *pemKey,
1135     TPM2B_PUBLIC *tpmPublic)
1136 {
1137     /* Check for NULL parameters */
1138     return_if_null(pemKey, "pemKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1139     return_if_null(tpmPublic, "public is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1140 
1141     TSS2_RC r = TSS2_RC_SUCCESS;
1142     EVP_PKEY *publicKey = NULL;
1143     r = ifapi_get_evp_from_pem(pemKey, &publicKey);
1144     goto_if_error(r, "Get EVP key from PEM", cleanup);
1145 
1146     if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
1147         tpmPublic->publicArea.type = TPM2_ALG_RSA;
1148         r = get_rsa_tpm2b_public_from_evp(publicKey, tpmPublic);
1149         goto_if_error(r, "Get public for RSA key.", cleanup);
1150 
1151     } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
1152         tpmPublic->publicArea.type = TPM2_ALG_ECC;
1153         r = get_ecc_tpm2b_public_from_evp(publicKey, tpmPublic);
1154         goto_if_error(r, "Get public for ECC key.", cleanup);
1155     } else {
1156         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong key_type", cleanup);
1157     }
1158 cleanup:
1159     OSSL_FREE(publicKey, EVP_PKEY);
1160     return r;
1161 }
1162 
1163 /**
1164  * Verifies the signature created by a Quote command.
1165  *
1166  * @param[in] keyObject A FAPI key with which the signature is verified
1167  * @param[in] signature A byte buffer holding the signature
1168  * @param[in] signatureSize The size of signature in bytes
1169  * @param[in] digest The digest of the signature
1170  * @param[in] digestSize The size of digest in bytes
1171  * @param[in] signatureScheme The signature scheme
1172  *
1173  * @retval TSS2_RC_SUCCESS on success
1174  * @retval TSS2_FAPI_RC_BAD_REFERENCE if keyObject, signature, digest
1175  *         or signatureScheme is NULL
1176  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
1177  * @retval TSS2_FAPI_RC_BAD_VALUE if the PEM encoded key could not be decoded
1178  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1179  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the verification of the
1180  *         signature fails
1181  */
1182 TSS2_RC
ifapi_verify_signature_quote(const IFAPI_OBJECT * keyObject,const uint8_t * signature,size_t signatureSize,const uint8_t * digest,size_t digestSize,const TPMT_SIG_SCHEME * signatureScheme)1183 ifapi_verify_signature_quote(
1184     const IFAPI_OBJECT *keyObject,
1185     const uint8_t *signature,
1186     size_t signatureSize,
1187     const uint8_t *digest,
1188     size_t digestSize,
1189     const TPMT_SIG_SCHEME *signatureScheme)
1190 {
1191     /* Check for NULL parameters */
1192     return_if_null(keyObject, "keyObject is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1193     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1194     return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1195     return_if_null(signatureScheme, "signatureScheme is NULL",
1196             TSS2_FAPI_RC_BAD_REFERENCE);
1197 
1198     TSS2_RC r = TSS2_RC_SUCCESS;
1199     char *public_pem_key = NULL;
1200     int pem_size;
1201     EVP_PKEY *publicKey = NULL;
1202     BIO *bufio = NULL;
1203     EVP_PKEY_CTX *pctx = NULL;
1204     EVP_MD_CTX *mdctx = NULL;
1205 
1206     /* Check whether or not the key is valid */
1207     if (keyObject->objectType == IFAPI_KEY_OBJ) {
1208         /* Compute public key */
1209         r = ifapi_pub_pem_key_from_tpm(&keyObject->misc.key.public, &public_pem_key,
1210                                        &pem_size);
1211         goto_if_error(r, "Compute public PEM key.", error_cleanup);
1212     } else if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
1213         public_pem_key = strdup(keyObject->misc.ext_pub_key.pem_ext_public);
1214         check_oom(public_pem_key);
1215     } else {
1216         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong object type",
1217                    error_cleanup);
1218     }
1219 
1220     /* Create an OpenSSL object for the key */
1221     bufio = BIO_new_mem_buf((void *)public_pem_key,
1222                             strlen(public_pem_key));
1223     goto_if_null(bufio, "BIO buffer could not be allocated.",
1224                  TSS2_FAPI_RC_MEMORY, error_cleanup);
1225 
1226     publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
1227     goto_if_null(publicKey, "PEM format could not be decoded.",
1228                  TSS2_FAPI_RC_BAD_VALUE, error_cleanup);
1229 
1230     /* Create the hash engine */
1231     if (!(mdctx = EVP_MD_CTX_create())) {
1232         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EVP_MD_CTX_create",
1233                    error_cleanup);
1234     }
1235 
1236     const EVP_MD *hashAlgorithm = get_hash_md(signatureScheme->details.any.hashAlg);
1237     if (!hashAlgorithm) {
1238         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid hash alg.",
1239                    error_cleanup);
1240     }
1241 
1242     /* Verify the digest of the signature */
1243     if (1 != EVP_DigestVerifyInit(mdctx, &pctx, hashAlgorithm, NULL, publicKey)) {
1244         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "EVP_DigestVerifyInit",
1245                    error_cleanup);
1246     }
1247     goto_if_null(pctx, "Out of memory", TSS2_FAPI_RC_MEMORY, error_cleanup);
1248     if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
1249         int padding = get_sig_scheme(signatureScheme->scheme);
1250         if (!padding) {
1251             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1252                        "Invalid padding scheme.", error_cleanup);
1253         }
1254         if (1 != EVP_PKEY_CTX_set_rsa_padding(pctx, padding)) {
1255             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1256                        "EVP_PKEY_CTX_set_rsa_padding", error_cleanup);
1257         }
1258     }
1259 
1260     if (1 != EVP_DigestVerifyUpdate(mdctx, digest, digestSize)) {
1261         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1262                    "EVP_DigestVerifyUpdate", error_cleanup);
1263     }
1264     if (1 != EVP_DigestVerifyFinal(mdctx, signature, signatureSize)) {
1265         goto_error(r, TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED,
1266                    "EVP_DigestSignFinal", error_cleanup);
1267     }
1268 
1269 error_cleanup:
1270     if (mdctx != NULL) {
1271         EVP_MD_CTX_destroy(mdctx);
1272     }
1273     SAFE_FREE(public_pem_key);
1274     EVP_PKEY_free(publicKey);
1275     BIO_free(bufio);
1276     return r;
1277 }
1278 
1279 /**
1280  * Verifies a signature using a given FAPI public key.
1281  *
1282  * @param[in] keyObject The FAPI public key used for verification
1283  * @param[in] signature The signature to verify
1284  * @param[in] signatureSize The size of signature in bytes
1285  * @param[in] digest The digest of the signature
1286  * @param[in] digestSize The size of digest in bytes
1287  *
1288  * @retval TSS2_RC_SUCCESS In case of success
1289  * @retval TSS2_FAPI_RC_BAD_REFERENCE if keyObject, signature or digest is NULL
1290  * @retval TSS2_FAPI_RC_BAD_VALUE if the type of the key is wrong
1291  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
1292  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1293  * @retval TSS2_FAPI_RC_SIGNATURE_VERIFICATION_FAILED if the verification of the
1294  *         signature fails
1295  *
1296  */
1297 TSS2_RC
ifapi_verify_signature(const IFAPI_OBJECT * keyObject,const uint8_t * signature,size_t signatureSize,const uint8_t * digest,size_t digestSize)1298 ifapi_verify_signature(
1299     const IFAPI_OBJECT *keyObject,
1300     const uint8_t *signature,
1301     size_t signatureSize,
1302     const uint8_t *digest,
1303     size_t digestSize)
1304 {
1305     /* Check for NULL parameters */
1306     return_if_null(keyObject, "keyObject is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1307     return_if_null(signature, "signature is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1308     return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1309 
1310     TSS2_RC r = TSS2_RC_SUCCESS;
1311     char *public_pem_key = NULL;
1312     int pem_size;
1313     EVP_PKEY *publicKey = NULL;
1314     BIO *bufio = NULL;
1315 
1316     /* Check whether or not the key is valid */
1317     if (keyObject->objectType == IFAPI_KEY_OBJ) {
1318         /* Compute public key */
1319         r = ifapi_pub_pem_key_from_tpm(&keyObject->misc.key.public, &public_pem_key,
1320                                        &pem_size);
1321         goto_if_error(r, "Compute public PEM key.", error_cleanup);
1322     } else if (keyObject->objectType == IFAPI_EXT_PUB_KEY_OBJ) {
1323         public_pem_key = strdup(keyObject->misc.ext_pub_key.pem_ext_public);
1324         check_oom(public_pem_key);
1325     } else {
1326         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong object type",
1327                    error_cleanup);
1328     }
1329 
1330     /* Convert the key to an OpenSSL object */
1331     bufio = BIO_new_mem_buf((void *)public_pem_key,
1332                                 strlen(public_pem_key));
1333     goto_if_null(bufio, "Out of memory.", TSS2_FAPI_RC_MEMORY, error_cleanup);
1334     publicKey = PEM_read_bio_PUBKEY(bufio, NULL, NULL, NULL);
1335     goto_if_null(publicKey, "PEM format could not be decoded.",
1336                  TSS2_FAPI_RC_MEMORY, error_cleanup);
1337 
1338     /* Call a suitable local function for the verification */
1339     if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
1340         r = rsa_verify_signature(publicKey, signature, signatureSize, digest,
1341                                      digestSize);
1342         goto_if_error(r, "Verify RSA signature.", error_cleanup);
1343 
1344     } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
1345         r = ecdsa_verify_signature(publicKey, signature, signatureSize,
1346                                    digest, digestSize);
1347         goto_if_error(r, "Verify ECC signature", error_cleanup);
1348 
1349     } else {
1350         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong key type",
1351                        error_cleanup);
1352     }
1353 
1354 error_cleanup:
1355     SAFE_FREE(public_pem_key);
1356     EVP_PKEY_free(publicKey);
1357     if (bufio)
1358         BIO_free(bufio);
1359     return r;
1360 }
1361 
1362 /**
1363  * Returns the digest size of a given hash algorithm.
1364  *
1365  * @param[in] hashAlgorithm The TSS identifier of the hash algorithm
1366  *
1367  * @return The size of the digest produced by the hash algorithm if
1368  * hashAlgorithm is valid
1369  * @retval 0 if hashAlgorithm is invalid
1370  */
1371 size_t
ifapi_hash_get_digest_size(TPM2_ALG_ID hashAlgorithm)1372 ifapi_hash_get_digest_size(TPM2_ALG_ID hashAlgorithm)
1373 {
1374     switch (hashAlgorithm) {
1375     case TPM2_ALG_SHA1:
1376         return TPM2_SHA1_DIGEST_SIZE;
1377         break;
1378     case TPM2_ALG_SHA256:
1379         return TPM2_SHA256_DIGEST_SIZE;
1380         break;
1381     case TPM2_ALG_SHA384:
1382         return TPM2_SHA384_DIGEST_SIZE;
1383         break;
1384     case TPM2_ALG_SHA512:
1385         return TPM2_SHA512_DIGEST_SIZE;
1386         break;
1387     case TPM2_ALG_SM3_256:
1388         return TPM2_SM3_256_DIGEST_SIZE;
1389         break;
1390     default:
1391         return 0;
1392     }
1393 }
1394 
1395 /**
1396  * Converts a TSS hash algorithm identifier into an OpenSSL hash algorithm
1397  * identifier object.
1398  *
1399  * @param[in] hashAlgorithm The TSS hash algorithm identifier to convert
1400  *
1401  * @retval A suitable OpenSSL identifier object if one could be found
1402  * @retval NULL if no suitable identifier object could be found
1403  */
1404 static const EVP_MD *
get_ossl_hash_md(TPM2_ALG_ID hashAlgorithm)1405 get_ossl_hash_md(TPM2_ALG_ID hashAlgorithm)
1406 {
1407     switch (hashAlgorithm) {
1408     case TPM2_ALG_SHA1:
1409         return EVP_sha1();
1410         break;
1411     case TPM2_ALG_SHA256:
1412         return EVP_sha256();
1413         break;
1414     case TPM2_ALG_SHA384:
1415         return EVP_sha384();
1416         break;
1417     case TPM2_ALG_SHA512:
1418         return EVP_sha512();
1419         break;
1420     default:
1421         return NULL;
1422     }
1423 }
1424 
1425 /**
1426  * Starts the computation of a hash digest.
1427  *
1428  * @param[out] context The created hash context (callee-allocated).
1429  * @param[in] hashAlgorithm The TSS hash identifier for the hash algorithm to use.
1430  *
1431  * @retval TSS2_RC_SUCCESS on success.
1432  * @retval TSS2_FAPI_RC_BAD_VALUE if hashAlgorithm is invalid
1433  * @retval TSS2_FAPI_RC_BAD_REFERENCE if context is NULL
1434  * @retval TSS2_FAPI_RC_MEMORY if memory cannot be allocated
1435  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1436  */
1437 TSS2_RC
ifapi_crypto_hash_start(IFAPI_CRYPTO_CONTEXT_BLOB ** context,TPM2_ALG_ID hashAlgorithm)1438 ifapi_crypto_hash_start(IFAPI_CRYPTO_CONTEXT_BLOB **context,
1439                         TPM2_ALG_ID hashAlgorithm)
1440 {
1441     /* Check for NULL parameters */
1442     return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1443 
1444     /* Initialize the hash context */
1445     TSS2_RC r = TSS2_RC_SUCCESS;
1446     LOG_DEBUG("call: context=%p hashAlg=%" PRIu16, context, hashAlgorithm);
1447     IFAPI_CRYPTO_CONTEXT *mycontext = NULL;
1448     mycontext = calloc(1, sizeof(IFAPI_CRYPTO_CONTEXT));
1449     return_if_null(mycontext, "Out of memory", TSS2_FAPI_RC_MEMORY);
1450 
1451     if (!(mycontext->osslHashAlgorithm = get_ossl_hash_md(hashAlgorithm))) {
1452         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
1453                    "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
1454                    hashAlgorithm);
1455     }
1456 
1457     if (!(mycontext->hashSize = ifapi_hash_get_digest_size(hashAlgorithm))) {
1458         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
1459                    "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
1460                    hashAlgorithm);
1461     }
1462 
1463     if (!(mycontext->osslContext = EVP_MD_CTX_create())) {
1464         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Error EVP_MD_CTX_create",
1465                    cleanup);
1466     }
1467 
1468     if (1 != EVP_DigestInit_ex(mycontext->osslContext,
1469                                mycontext->osslHashAlgorithm, get_engine())) {
1470         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Error EVP_DigestInit_ex",
1471                    cleanup);
1472     }
1473 
1474     *context = (IFAPI_CRYPTO_CONTEXT_BLOB *) mycontext;
1475 
1476     return TSS2_RC_SUCCESS;
1477 
1478 cleanup:
1479     if (mycontext->osslContext)
1480         EVP_MD_CTX_destroy(mycontext->osslContext);
1481     SAFE_FREE(mycontext);
1482 
1483     return r;
1484 }
1485 
1486 /**
1487  * Updates the digest value of a hash object with data from a byte buffer.
1488  *
1489  * @param[in,out] context The hash context that will be updated
1490  * @param[in] buffer The data for the update
1491  * @param[in] size The size of data in bytes
1492  *
1493  * @retval TSS2_RC_SUCCESS on success.
1494  * @retval TSS2_FAPI_RC_BAD_REFERENCE for invalid parameters.
1495  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1496  */
1497 TSS2_RC
ifapi_crypto_hash_update(IFAPI_CRYPTO_CONTEXT_BLOB * context,const uint8_t * buffer,size_t size)1498 ifapi_crypto_hash_update(IFAPI_CRYPTO_CONTEXT_BLOB *context,
1499                          const uint8_t *buffer, size_t size)
1500 {
1501     /* Check for NULL parameters */
1502     return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1503     return_if_null(buffer, "buffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1504 
1505     LOG_DEBUG("called for context %p, buffer %p and size %zd", context, buffer,
1506               size);
1507 
1508     /* Update the digest */
1509     IFAPI_CRYPTO_CONTEXT *mycontext = (IFAPI_CRYPTO_CONTEXT *) context;
1510     LOGBLOB_DEBUG(buffer, size, "Updating hash with");
1511 
1512     if (1 != EVP_DigestUpdate(mycontext->osslContext, buffer, size)) {
1513         return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL hash update");
1514     }
1515 
1516     return TSS2_RC_SUCCESS;
1517 }
1518 
1519 /**
1520  * Gets the digest value from a hash context and closes it.
1521  *
1522  * @param[in,out] context The hash context that is released
1523  * @param[out] digest The buffer for the digest value
1524  * @param[out] digestSize The size of digest in bytes. Can be NULL
1525  *
1526  * @retval TSS2_RC_SUCCESS on success
1527  * @retval TSS2_FAPI_RC_BAD_REFERENCE if context or digest is NULL
1528  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1529  */
1530 TSS2_RC
ifapi_crypto_hash_finish(IFAPI_CRYPTO_CONTEXT_BLOB ** context,uint8_t * digest,size_t * digestSize)1531 ifapi_crypto_hash_finish(IFAPI_CRYPTO_CONTEXT_BLOB **context,
1532                          uint8_t *digest, size_t *digestSize)
1533 {
1534     /* Check for NULL parameters */
1535     return_if_null(context, "context is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1536     return_if_null(digest, "digest is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1537 
1538     unsigned int computedDigestSize = 0;
1539 
1540     LOG_TRACE("called for context-pointer %p, digest %p and size-pointer %p",
1541               context, digest, digestSize);
1542     /* Compute the digest */
1543     IFAPI_CRYPTO_CONTEXT *mycontext = *context;
1544     if (1 != EVP_DigestFinal_ex(mycontext->osslContext, digest,
1545                                 &computedDigestSize)) {
1546         return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error.");
1547     }
1548 
1549     if (computedDigestSize != mycontext->hashSize) {
1550         return_error(TSS2_FAPI_RC_GENERAL_FAILURE,
1551                      "Invalid size computed by EVP_DigestFinal_ex");
1552     }
1553 
1554     LOGBLOB_DEBUG(digest, mycontext->hashSize, "finish hash");
1555 
1556     if (digestSize != NULL) {
1557         *digestSize = mycontext->hashSize;
1558     }
1559 
1560     /* Finalize the hash context */
1561     EVP_MD_CTX_destroy(mycontext->osslContext);
1562     free(mycontext);
1563     *context = NULL;
1564 
1565     return TSS2_RC_SUCCESS;
1566 }
1567 
1568 /**
1569  * Aborts a hash operation and finalizes the hash context. It will be set to
1570  * NULL.
1571  *
1572  * @param[in,out] context The context of the digest object.
1573  */
1574 void
ifapi_crypto_hash_abort(IFAPI_CRYPTO_CONTEXT_BLOB ** context)1575 ifapi_crypto_hash_abort(IFAPI_CRYPTO_CONTEXT_BLOB **context)
1576 {
1577     LOG_TRACE("called for context-pointer %p", context);
1578     if (context == NULL || *context == NULL) {
1579         LOG_DEBUG("Null-Pointer passed");
1580         return;
1581     }
1582     IFAPI_CRYPTO_CONTEXT *mycontext = (IFAPI_CRYPTO_CONTEXT *) * context;
1583 
1584     EVP_MD_CTX_destroy(mycontext->osslContext);
1585     free(mycontext);
1586     *context = NULL;
1587 }
1588 
1589 /**
1590  * Get url to download crl from certificate.
1591  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1592  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1593  *         the function.
1594  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1595  * @retval TSS2_FAPI_RC_NO_CERT if an error did occur during certificate downloading.
1596  */
1597 TSS2_RC
get_crl_from_cert(X509 * cert,X509_CRL ** crl)1598 get_crl_from_cert(X509 *cert, X509_CRL **crl)
1599 {
1600     TSS2_RC r = TSS2_RC_SUCCESS;
1601     unsigned char* url = NULL;
1602     unsigned char *crl_buffer = NULL;
1603     size_t crl_buffer_size;
1604     int nid = NID_crl_distribution_points;
1605     STACK_OF(DIST_POINT) * dist_points = (STACK_OF(DIST_POINT) *)X509_get_ext_d2i(cert, nid, NULL, NULL);
1606     int curl_rc;
1607 
1608     *crl = NULL;
1609     for (int i = 0; i < sk_DIST_POINT_num(dist_points); i++)
1610     {
1611         DIST_POINT *dp = sk_DIST_POINT_value(dist_points, i);
1612         DIST_POINT_NAME    *distpoint = dp->distpoint;
1613         if (distpoint->type==0)
1614         {
1615             for (int j = 0; j < sk_GENERAL_NAME_num(distpoint->name.fullname); j++)
1616             {
1617                 GENERAL_NAME *gen_name = sk_GENERAL_NAME_value(distpoint->name.fullname, j);
1618                 ASN1_IA5STRING *asn1_str = gen_name->d.uniformResourceIdentifier;
1619                 SAFE_FREE(url);
1620                 url = (unsigned char *)strdup((char *)asn1_str->data);
1621                 goto_if_null2(url, "Out of memory", r, TSS2_FAPI_RC_MEMORY, cleanup);
1622             }
1623         }
1624     }
1625 
1626     curl_rc = ifapi_get_curl_buffer(url, &crl_buffer, &crl_buffer_size);
1627     if (curl_rc != 0) {
1628         goto_error(r, TSS2_FAPI_RC_NO_CERT, "Get crl.", cleanup);
1629     }
1630 
1631     OpenSSL_add_all_algorithms();
1632 
1633     unsigned const char* tmp_ptr1 = crl_buffer;
1634     unsigned const char** tmp_ptr2 = &tmp_ptr1;
1635 
1636     if (!d2i_X509_CRL(crl, tmp_ptr2, crl_buffer_size)) {
1637         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Can't convert crl.", cleanup);
1638     }
1639 
1640 cleanup:
1641     SAFE_FREE(crl_buffer);
1642     CRL_DIST_POINTS_free(dist_points);
1643     SAFE_FREE(url);
1644     return r;
1645 }
1646 
1647 /**
1648  * Converts a TPM certificate buffer to the PEM format.
1649  *
1650  * @param[in]  certBuffer A byte buffer holding the certificate
1651  * @param[in]  certBufferSize The size of certBuffer in bytes
1652  * @param[out] pemCert A byte buffer where the PEM-formatted certificate is
1653  *             stored
1654  * @param[out] certAlgorithmId The key type of the certified key
1655  * @param[out] tpmPublic The public key of the certificate in TPM format.
1656  *
1657  * @retval TSS2_RC_SUCCESS on success
1658  * @retval TSS2_FAPI_RC_BAD_REFERENCE if certBuffer or pemCert is NULL
1659  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
1660  * @retval TSS2_FAPI_RC_BAD_VALUE, if the certificate is invalid
1661  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
1662  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
1663  *         the function.
1664  */
1665 TSS2_RC
ifapi_cert_to_pem(const uint8_t * certBuffer,size_t certBufferSize,char ** pemCert,TPM2_ALG_ID * certAlgorithmId,TPM2B_PUBLIC * tpmPublic)1666 ifapi_cert_to_pem(
1667     const uint8_t *certBuffer,
1668     size_t certBufferSize,
1669     char **pemCert,
1670     TPM2_ALG_ID *certAlgorithmId,
1671     TPM2B_PUBLIC *tpmPublic)
1672 {
1673     /* Check for NULL parameters */
1674     return_if_null(certBuffer, "certBuffer is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1675     return_if_null(pemCert, "pemCert is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1676 
1677     TSS2_RC r = TSS2_RC_SUCCESS;
1678     X509 *cert = NULL;
1679     BIO *bio = NULL;
1680     EVP_PKEY *publicKey = NULL;
1681     int pemCertSize;
1682 
1683     if (!d2i_X509(&cert, (const unsigned char **)&certBuffer, certBufferSize)) {
1684         LOGBLOB_ERROR(certBuffer, certBufferSize, "Bad certificate data");
1685         return_error(TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid certificate.");
1686     }
1687     *pemCert = NULL;
1688 
1689     /* Memory IO will be used for OSSL key conversion */
1690     bio = BIO_new(BIO_s_mem());
1691     return_if_null(bio, "Out of memory.", TSS2_FAPI_RC_MEMORY);
1692 
1693     if (!PEM_write_bio_X509(bio, cert)) {
1694         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "PEM_write_bio_X509", cleanup);
1695     }
1696     /* Determine the size of the data written */
1697     pemCertSize = BIO_get_mem_data(bio, pemCert);
1698     *pemCert = malloc(pemCertSize + 1);
1699     goto_if_null(pemCert, "Out of memory.", TSS2_FAPI_RC_MEMORY, cleanup);
1700 
1701     /* Get the byte buffer written to the BIO object */
1702     int readSize = BIO_read(bio, *pemCert, pemCertSize);
1703     if (readSize != pemCertSize) {
1704         SAFE_FREE(*pemCert);
1705         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "Invalid BIO_read",
1706                    cleanup);
1707     }
1708     (*pemCert)[pemCertSize] = '\0';
1709 
1710     publicKey = X509_get_pubkey(cert);
1711     goto_if_null(publicKey, "No public key in certificate.",
1712                   TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1713 
1714     if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_RSA) {
1715         tpmPublic->publicArea.type = TPM2_ALG_RSA;
1716         r = get_rsa_tpm2b_public_from_evp(publicKey, tpmPublic);
1717         goto_if_error(r, "Get public for RSA key.", cleanup);
1718 
1719     } else if (EVP_PKEY_type(EVP_PKEY_id(publicKey)) == EVP_PKEY_EC) {
1720         tpmPublic->publicArea.type = TPM2_ALG_ECC;
1721         r = get_ecc_tpm2b_public_from_evp(publicKey, tpmPublic);
1722         goto_if_error(r, "Get public for ECC key.", cleanup);
1723     } else {
1724         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong key_type", cleanup);
1725     }
1726 
1727     if (certAlgorithmId != NULL) {
1728         switch (EVP_PKEY_id(publicKey)) {
1729         case EVP_PKEY_RSA:
1730             *certAlgorithmId = TPM2_ALG_RSA;
1731             break;
1732         case EVP_PKEY_EC:
1733             *certAlgorithmId = TPM2_ALG_ECC;
1734             break;
1735         default:
1736             goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong certificate (key type).",
1737                        cleanup);
1738         }
1739     }
1740 cleanup:
1741     BIO_free(bio);
1742     OSSL_FREE(cert, X509);
1743     OSSL_FREE(publicKey, EVP_PKEY);
1744     return r;
1745 }
1746 
1747 /**
1748  * Returns a suitable hash algorithm for a given digest size.
1749  *
1750  * @param[in]  size The size of the digest
1751  * @param[out] hashAlgorithm A suitable hash algorithm for the digest size
1752  *
1753  * @retval TSS2_RC_SUCCESS on success
1754  * @retval TSS2_FAPI_RC_BAD_REFERENCE if hashAlgorithm is NULL
1755  * @retval TSS2_FAPI_RC_BAD_VALUE if the digest size is invalid
1756  */
1757 TSS2_RC
ifapi_get_hash_alg_for_size(uint16_t size,TPMI_ALG_HASH * hashAlgorithm)1758 ifapi_get_hash_alg_for_size(uint16_t size, TPMI_ALG_HASH *hashAlgorithm)
1759 {
1760     /* Check for NULL parameters */
1761     return_if_null(hashAlgorithm, "hashAlgorithm is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
1762 
1763     /* Determine the hash algorithm */
1764     switch (size) {
1765     case TPM2_SHA1_DIGEST_SIZE:
1766         *hashAlgorithm = TPM2_ALG_SHA1;
1767         return TSS2_RC_SUCCESS;
1768     case TPM2_SHA256_DIGEST_SIZE:
1769         *hashAlgorithm = TPM2_ALG_SHA256;
1770         return TSS2_RC_SUCCESS;
1771     case TPM2_SHA384_DIGEST_SIZE:
1772         *hashAlgorithm = TPM2_ALG_SHA384;
1773         return TSS2_RC_SUCCESS;
1774     case TPM2_SHA512_DIGEST_SIZE:
1775         *hashAlgorithm = TPM2_ALG_SHA512;
1776         return TSS2_RC_SUCCESS;
1777     default:
1778         return TSS2_FAPI_RC_BAD_VALUE;
1779     }
1780 }
1781 
1782 /** Convert PEM certificate to OSSL format.
1783  *
1784  * @param[in] pem_cert Certificate in PEM format.
1785  * @retval X509 OSSL certificate object.
1786  * @retval NULL If the conversion fails.
1787  */
1788 static X509
get_X509_from_pem(const char * pem_cert)1789 *get_X509_from_pem(const char *pem_cert)
1790 {
1791     if (!pem_cert) {
1792         return NULL;
1793     }
1794     BIO *bufio = NULL;
1795     X509 *cert = NULL;
1796 
1797     /* Use BIO for conversion */
1798     size_t pem_length = strlen(pem_cert);
1799     bufio = BIO_new_mem_buf((void *)pem_cert, pem_length);
1800     if (!bufio)
1801         return NULL;
1802     /* Convert the certificate */
1803     cert = PEM_read_bio_X509(bufio, NULL, NULL, NULL);
1804     BIO_free(bufio);
1805     return cert;
1806 }
1807 
1808 /** Get public information for key of a pem certificate.
1809  *
1810  * @param[in]  pem_cert The pem certificate.
1811  * @param[out] tpm_public The public information of the key in TPM format.
1812  *
1813  * @retval TSS2_RC_SUCCESS on success
1814  * @retval TSS2_FAPI_RC_BAD_VALUE if the conversion fails.
1815  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if openssl errors occur.
1816  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
1817  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1818  */
1819 TSS2_RC
ifapi_get_public_from_pem_cert(const char * pem_cert,TPM2B_PUBLIC * tpm_public)1820 ifapi_get_public_from_pem_cert(const char* pem_cert, TPM2B_PUBLIC *tpm_public)
1821 {
1822     TSS2_RC r = TSS2_RC_SUCCESS;
1823     X509 *cert = NULL;
1824     EVP_PKEY *public_key = NULL;
1825 
1826     cert = get_X509_from_pem(pem_cert);
1827     return_if_null(cert, "Invalid certificate.", TSS2_FAPI_RC_BAD_VALUE);
1828 
1829     public_key = X509_get_pubkey(cert);
1830     goto_if_null(public_key, "No public key in certificate.",
1831                  TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1832 
1833     if (EVP_PKEY_type(EVP_PKEY_id(public_key)) == EVP_PKEY_RSA) {
1834         tpm_public->publicArea.type = TPM2_ALG_RSA;
1835         r = get_rsa_tpm2b_public_from_evp(public_key, tpm_public);
1836         goto_if_error(r, "Get public for RSA key.", cleanup);
1837 
1838     } else if (EVP_PKEY_type(EVP_PKEY_id(public_key)) == EVP_PKEY_EC) {
1839         tpm_public->publicArea.type = TPM2_ALG_ECC;
1840         r = get_ecc_tpm2b_public_from_evp(public_key, tpm_public);
1841         goto_if_error(r, "Get public for ECC key.", cleanup);
1842     } else {
1843         goto_error(r, TSS2_FAPI_RC_BAD_VALUE, "Wrong key_type", cleanup);
1844     }
1845 cleanup:
1846     OSSL_FREE(cert, X509);
1847     OSSL_FREE(public_key, EVP_PKEY);
1848     return r;
1849 }
1850 
1851 /** Convert buffer from DER format to X509 certificate.
1852  *
1853  * @param[in] cert_buffer Certificate in DER format.
1854  * @aparm[in] cert_buffer_size Size of DER certificate.
1855  * @retval X509 OSSL certificate object.
1856  * @retval NULL If the conversion fails.
1857  */
1858 static X509
get_cert_from_buffer(unsigned char * cert_buffer,size_t cert_buffer_size)1859 *get_cert_from_buffer(unsigned char *cert_buffer, size_t cert_buffer_size)
1860 {
1861     unsigned char *buffer = cert_buffer;
1862     X509 *cert = NULL;
1863 
1864     unsigned const char* tmp_ptr1 = buffer;
1865     unsigned const char** tmp_ptr2 = &tmp_ptr1;
1866 
1867     if (!d2i_X509(&cert, tmp_ptr2, cert_buffer_size))
1868         return NULL;
1869     return cert;
1870 }
1871 
1872 /**
1873  * Verify EK certificate read from TPM.
1874  *
1875  * @param[in] root_cert_pem The vendor root certificate.
1876  * @param[in] intermed_cert_pem The vendor intermediate certificate.
1877  * @param[in] ek_cert_pem The ek certificate from TPM.
1878  *
1879  * @retval TSS2_RC_SUCCESS on success
1880  * @retval TSS2_FAPI_RC_BAD_VALUE if the verification was no successful.
1881  * @retval TSS2_FAPI_RC_NO_CERT if an error did occur during certificate downloading.
1882  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an internal error occurred.
1883  * @retval TSS2_FAPI_RC_MEMORY if not enough memory can be allocated.
1884  */
1885 TSS2_RC
ifapi_verify_ek_cert(char * root_cert_pem,char * intermed_cert_pem,char * ek_cert_pem)1886 ifapi_verify_ek_cert(
1887     char* root_cert_pem,
1888     char* intermed_cert_pem,
1889     char* ek_cert_pem)
1890 {
1891     TSS2_RC r = TSS2_RC_SUCCESS;
1892     X509 *root_cert = NULL;
1893     X509 *intermed_cert = NULL;
1894     X509 *ek_cert = NULL;
1895     X509_STORE *store = NULL;
1896     X509_STORE_CTX *ctx = NULL;
1897     X509_CRL *crl_intermed = NULL;
1898     X509_CRL *crl_ek = NULL;
1899     int i;
1900     size_t ui;
1901     AUTHORITY_INFO_ACCESS *info = NULL;
1902     ASN1_IA5STRING *uri = NULL;
1903     unsigned char * url;
1904     unsigned char *cert_buffer = NULL;
1905     size_t cert_buffer_size;
1906     int curl_rc;
1907 
1908     ek_cert = get_X509_from_pem(ek_cert_pem);
1909     goto_if_null2(ek_cert, "Failed to convert PEM certificate to DER.",
1910                   r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
1911 
1912     if (intermed_cert_pem) {
1913         intermed_cert = get_X509_from_pem(intermed_cert_pem);
1914         goto_if_null2(intermed_cert, "Failed to convert PEM certificate to DER.",
1915                       r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
1916     } else {
1917         /* Get uri for ek intermediate certificate. */
1918         OpenSSL_add_all_algorithms();
1919         info = X509_get_ext_d2i(ek_cert, NID_info_access, NULL, NULL);
1920 
1921         for (i = 0; i < sk_ACCESS_DESCRIPTION_num(info); i++) {
1922             ACCESS_DESCRIPTION *ad = sk_ACCESS_DESCRIPTION_value(info, i);
1923             if (ad->location->type != GEN_URI) {
1924                 continue;
1925             }
1926             uri = ad->location->d.uniformResourceIdentifier;
1927             url = uri->data;
1928             curl_rc = ifapi_get_curl_buffer(url, &cert_buffer, &cert_buffer_size);
1929             if (curl_rc != 0) {
1930                 goto_error(r, TSS2_FAPI_RC_NO_CERT, "Get certificate.", cleanup);
1931             }
1932             goto_if_null2(cert_buffer, "No certificate downloaded", r,
1933                           TSS2_FAPI_RC_NO_CERT, cleanup);
1934         }
1935         goto_if_null2(cert_buffer, "No certificate downloaded", r,
1936                       TSS2_FAPI_RC_NO_CERT, cleanup);
1937 
1938         OpenSSL_add_all_algorithms();
1939         intermed_cert = get_cert_from_buffer(cert_buffer, cert_buffer_size);
1940 
1941         SAFE_FREE(cert_buffer);
1942         goto_if_null2(intermed_cert, "Failed to create intermediate certificate.",
1943                       r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1944 
1945          /* Get Certificate revocation list for Intermediate certificate */
1946         r = get_crl_from_cert(intermed_cert, &crl_intermed);
1947         goto_if_error(r, "Get crl for intermediate certificate.", cleanup);
1948 
1949         /* Get Certificate revocation list for EK certificate */
1950         r = get_crl_from_cert(ek_cert, &crl_ek);
1951         goto_if_error(r, "Get crl for ek certificate.", cleanup);
1952     }
1953 
1954     /* Prepare X509 certificate store */
1955 
1956     store = X509_STORE_new();
1957 
1958     goto_if_null2(store, "Failed to create X509 store.",
1959                   r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
1960 
1961     /* Add Certificate revocation list for EK certificate if one exists. */
1962     if (crl_ek) {
1963         /* Set the flags of the store to use CRLs. */
1964         X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
1965         if (1 != X509_STORE_add_crl(store, crl_ek)) {
1966             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1967                        "Failed to add intermediate crl.", cleanup);
1968         }
1969     }
1970 
1971     /* Add Certificate revocation list for intermediate certificate if one exists. */
1972     if (crl_intermed) {
1973         /* Set the flags of the store to use CRLs. */
1974         X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL);
1975         if (1 != X509_STORE_add_crl(store, crl_intermed)) {
1976             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1977                        "Failed to add intermediate crl.", cleanup);
1978         }
1979     }
1980 
1981     /* Add stored root certificates */
1982     for (ui = 0; ui < sizeof(root_cert_list) / sizeof(char *); ui++) {
1983          root_cert = get_X509_from_pem(root_cert_list[ui]);
1984          goto_if_null2(root_cert, "Failed to convert PEM certificate to DER.",
1985                        r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
1986          if (1 != X509_STORE_add_cert(store, root_cert)) {
1987              goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
1988                         "Failed to add root certificate", cleanup);
1989         }
1990         OSSL_FREE(root_cert, X509);
1991     }
1992 
1993     /* Create root cert if passed as parameter */
1994     if (root_cert_pem) {
1995         root_cert = get_X509_from_pem(root_cert_pem);
1996         goto_if_null2(root_cert, "Failed to convert PEM certificate to DER.",
1997                       r, TSS2_FAPI_RC_BAD_VALUE, cleanup);
1998 
1999         if (1 != X509_STORE_add_cert(store, root_cert)) {
2000             goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2001                        "Failed to add root certificate", cleanup);
2002         }
2003         OSSL_FREE(root_cert, X509);
2004     }
2005 
2006     /* Verify intermediate certificate */
2007     ctx = X509_STORE_CTX_new();
2008     goto_if_null2(ctx, "Failed to create X509 store context.",
2009                   r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
2010     if (1 != X509_STORE_CTX_init(ctx, store, intermed_cert, NULL)) {
2011         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2012                    "Failed to initialize X509 context.", cleanup);
2013     }
2014     if (1 != X509_verify_cert(ctx)) {
2015         int rc = X509_STORE_CTX_get_error(ctx);
2016         LOG_ERROR("%s", X509_verify_cert_error_string(rc));
2017         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2018                    "Failed to verify EK certificate", cleanup);
2019     }
2020     if (1 != X509_STORE_add_cert(store, intermed_cert)) {
2021         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2022                    "Failed to add intermediate certificate", cleanup);
2023     }
2024 
2025     X509_STORE_CTX_cleanup(ctx);
2026     X509_STORE_CTX_free(ctx);
2027     ctx = NULL;
2028     ctx = X509_STORE_CTX_new();
2029     goto_if_null2(ctx, "Failed to create X509 store context.",
2030                   r, TSS2_FAPI_RC_GENERAL_FAILURE, cleanup);
2031 
2032     if (1 != X509_STORE_CTX_init(ctx, store, ek_cert, NULL)) {
2033         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2034                    "Failed to initialize X509 context.", cleanup);
2035     }
2036     /* Verify the EK certificate. */
2037     if (1 != X509_verify_cert(ctx)) {
2038         int rc = X509_STORE_CTX_get_error(ctx);
2039         LOG_ERROR("%s", X509_verify_cert_error_string(rc));
2040         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE,
2041                    "Failed to verify EK certificate", cleanup);
2042     }
2043 
2044 cleanup:
2045     if (ctx) {
2046         X509_STORE_CTX_cleanup(ctx);
2047         X509_STORE_CTX_free(ctx);
2048     }
2049     if (store)
2050         X509_STORE_free(store);
2051     OSSL_FREE(root_cert, X509);
2052     OSSL_FREE(intermed_cert, X509);
2053     OSSL_FREE(ek_cert, X509);
2054     OSSL_FREE(crl_intermed, X509_CRL);
2055     OSSL_FREE(crl_ek, X509_CRL);
2056     OSSL_FREE(info, AUTHORITY_INFO_ACCESS);
2057     return r;
2058 }
2059 
2060 /** Compute the fingerprint of a TPM public key.
2061  *
2062  * @param[in] tpmPublicKey The public key created by the TPM
2063  * @param[in] hashAlg The hash algorithm used for fingerprint computation.
2064  * @param[out] fingerprint The fingerprint digest.
2065  *
2066  * @retval TSS2_RC_SUCCESS on success
2067  * @retval TSS2_FAPI_RC_GENERAL_FAILURE if an error occurs in the crypto library
2068  * @retval TSS2_FAPI_RC_MEMORY if memory could not be allocated
2069  * @retval TSS2_FAPI_BAD_REFERENCE if tpmPublicKey or pemKeySize are NULL
2070  * @retval TSS2_FAPI_RC_BAD_REFERENCE a invalid null pointer is passed.
2071  * @retval TSS2_FAPI_RC_BAD_VALUE if an invalid value was passed into
2072  *         the function.
2073  */
2074 TSS2_RC
ifapi_get_tpm_key_fingerprint(const TPM2B_PUBLIC * tpmPublicKey,TPMI_ALG_HASH hashAlg,TPM2B_DIGEST * fingerprint)2075 ifapi_get_tpm_key_fingerprint(
2076     const TPM2B_PUBLIC *tpmPublicKey,
2077     TPMI_ALG_HASH hashAlg,
2078     TPM2B_DIGEST *fingerprint)
2079 {
2080     /* Check for NULL parameters */
2081     return_if_null(tpmPublicKey, "tpmPublicKey is NULL", TSS2_FAPI_RC_BAD_REFERENCE);
2082 
2083     EVP_PKEY *evpPublicKey = NULL;
2084     TSS2_RC r = TPM2_RC_SUCCESS;
2085     uint8_t *pubKeyDer = NULL;
2086     int pubKeyDerSize;
2087     IFAPI_CRYPTO_CONTEXT_BLOB *cryptoContext = NULL;
2088     size_t hashSize;
2089     size_t fingerPrintSize;
2090 
2091     if (!(hashSize = ifapi_hash_get_digest_size(hashAlg))) {
2092         goto_error(r, TSS2_FAPI_RC_BAD_VALUE,
2093                    "Unsupported hash algorithm (%" PRIu16 ")", cleanup,
2094                    hashAlg);
2095     }
2096 
2097     evpPublicKey = EVP_PKEY_new();
2098     goto_if_null2(evpPublicKey, "Out of memory.", r, TSS2_FAPI_RC_MEMORY, cleanup);
2099 
2100     if (tpmPublicKey->publicArea.type == TPM2_ALG_RSA) {
2101         r = ossl_rsa_pub_from_tpm(tpmPublicKey, evpPublicKey);
2102     } else if (tpmPublicKey->publicArea.type == TPM2_ALG_ECC)
2103         r = ossl_ecc_pub_from_tpm(tpmPublicKey, evpPublicKey);
2104     else {
2105         goto_error(r,TSS2_FAPI_RC_BAD_VALUE, "Invalid alg id.", cleanup);
2106     }
2107     goto_if_error(r, "Get ossl public key.", cleanup);
2108 
2109     /* Convert the OpenSSL EVP pub key into DEF format */
2110     pubKeyDerSize = i2d_PUBKEY(evpPublicKey, &pubKeyDer);
2111     if (pubKeyDerSize == -1) {
2112         goto_error(r, TSS2_FAPI_RC_GENERAL_FAILURE, "OSSL error", cleanup);
2113     }
2114 
2115     /* Compute the digest of the DER public key */
2116     r = ifapi_crypto_hash_start(&cryptoContext, hashAlg);
2117     goto_if_error(r, "crypto hash start", cleanup);
2118 
2119     HASH_UPDATE_BUFFER(cryptoContext,
2120                        pubKeyDer, pubKeyDerSize, r, cleanup);
2121     r = ifapi_crypto_hash_finish(&cryptoContext,
2122                                  &fingerprint->buffer[0], &fingerPrintSize);
2123     goto_if_error(r, "crypto hash finish", cleanup);
2124 
2125     fingerprint->size = fingerPrintSize;
2126 
2127 cleanup:
2128     EVP_PKEY_free(evpPublicKey);
2129     SAFE_FREE(pubKeyDer);
2130     if (cryptoContext) {
2131         ifapi_crypto_hash_abort(&cryptoContext);
2132     }
2133     return r;
2134 }
2135