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