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