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