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