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