projects/linux/asn1/dice/x509_extension_builder_openssl_dice_tcbinfo.c (182 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. #include <stdlib.h> #include <stddef.h> #include <string.h> #include <openssl/asn1t.h> #include <openssl/err.h> #include <openssl/evp.h> #include <openssl/x509v3.h> #include "platform_api.h" #include "x509_extension_builder_openssl_dice_tcbinfo.h" #include "asn1/dice/x509_extension_builder_dice_tcbinfo.h" #include "common/unused.h" /** * Structure of the DICE FWID. */ typedef struct dice_fwid_st { ASN1_OBJECT *hash_alg; /**< The algorithm used to generate the FWID. */ ASN1_OCTET_STRING *digest; /**< The FWID hash data. */ ASN1_ENCODING enc; /**< ASN1 encoding. */ } DICE_FWID; DEFINE_STACK_OF (DICE_FWID) typedef STACK_OF (DICE_FWID) DICE_FWIDS; /** * Structure of the DICE TcbInfo extension. */ typedef struct dice_tcbinfo_st { GENERAL_NAMES *vendor; /**< Device vendor information. */ ASN1_IA5STRING *model; /**< Model identifier. */ ASN1_IA5STRING *version; /**< The firmware version. */ ASN1_INTEGER *svn; /**< The security state. */ ASN1_INTEGER *layer; /**< Firmware state information. */ ASN1_INTEGER *index; /**< Firmware state information. */ DICE_FWIDS *digests; /**< The FWID information. */ ASN1_ENCODING enc; /**< ASN1 encoding. */ } DICE_TCBINFO; ASN1_SEQUENCE_enc (DICE_FWID, enc, 0) = { ASN1_SIMPLE (DICE_FWID, hash_alg, ASN1_OBJECT), ASN1_SIMPLE (DICE_FWID, digest, ASN1_OCTET_STRING) } ASN1_SEQUENCE_END_enc (DICE_FWID, DICE_FWID) IMPLEMENT_ASN1_FUNCTIONS (DICE_FWID) ASN1_SEQUENCE_enc (DICE_TCBINFO, enc, 0) = { ASN1_IMP_SEQUENCE_OF_OPT (DICE_TCBINFO, vendor, GENERAL_NAME, 0), ASN1_IMP_OPT (DICE_TCBINFO, model, ASN1_IA5STRING, 1), ASN1_IMP_OPT (DICE_TCBINFO, version, ASN1_IA5STRING, 2), ASN1_IMP_OPT (DICE_TCBINFO, svn, ASN1_INTEGER, 3), ASN1_IMP_OPT (DICE_TCBINFO, layer, ASN1_INTEGER, 4), ASN1_IMP_OPT (DICE_TCBINFO, index, ASN1_INTEGER, 5), ASN1_IMP_SEQUENCE_OF_OPT (DICE_TCBINFO, digests, DICE_FWID, 6) } ASN1_SEQUENCE_END_enc (DICE_TCBINFO, DICE_TCBINFO) IMPLEMENT_ASN1_FUNCTIONS (DICE_TCBINFO) int x509_extension_builder_openssl_dice_tcbinfo_build (const struct x509_extension_builder *builder, struct x509_extension *extension) { const struct x509_extension_builder_openssl_dice_tcbinfo *dice = (const struct x509_extension_builder_openssl_dice_tcbinfo*) builder; DICE_TCBINFO *tcbinfo; BIGNUM *svn; DICE_FWID *fwid; ASN1_OBJECT *fwid_oid; int fwid_len; int status; uint8_t *tcb_der = NULL; int tcb_der_len; if ((dice == NULL) || (extension == NULL)) { return DICE_TCBINFO_EXTENSION_INVALID_ARGUMENT; } if (dice->tcb == NULL) { return DICE_TCBINFO_EXTENSION_INVALID_ARGUMENT; } if (dice->tcb->version == NULL) { return DICE_TCBINFO_EXTENSION_NO_VERSION; } if ((dice->tcb->svn == NULL) || (dice->tcb->svn_length == 0)) { return DICE_TCBINFO_EXTENSION_NO_SVN; } if (dice->tcb->fwid == NULL) { return DICE_TCBINFO_EXTENSION_NO_FWID; } switch (dice->tcb->fwid_hash) { case HASH_TYPE_SHA1: fwid_len = SHA1_HASH_LENGTH; fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha1 ())); break; case HASH_TYPE_SHA256: fwid_len = SHA256_HASH_LENGTH; fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha256 ())); break; case HASH_TYPE_SHA384: fwid_len = SHA384_HASH_LENGTH; fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha384 ())); break; case HASH_TYPE_SHA512: fwid_len = SHA512_HASH_LENGTH; fwid_oid = OBJ_nid2obj (EVP_MD_type (EVP_sha512 ())); break; default: return DICE_TCBINFO_EXTENSION_UNKNOWN_FWID; } if (fwid_oid == NULL) { return -ERR_get_error (); } tcbinfo = DICE_TCBINFO_new (); if (tcbinfo == NULL) { status = -ERR_get_error (); goto err_tcb; } tcbinfo->version = ASN1_IA5STRING_new (); if (tcbinfo->version == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } tcbinfo->version->length = strlen (dice->tcb->version); tcbinfo->version->data = (unsigned char*) strdup (dice->tcb->version); if (tcbinfo->version->data == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } svn = BN_bin2bn (dice->tcb->svn, dice->tcb->svn_length, NULL); if (svn == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } tcbinfo->svn = BN_to_ASN1_INTEGER (svn, NULL); BN_free (svn); if (tcbinfo->svn == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } tcbinfo->digests = sk_DICE_FWID_new_null (); if (tcbinfo->digests == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } fwid = DICE_FWID_new (); if (fwid == NULL) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_build; } ASN1_OBJECT_free (fwid->hash_alg); fwid->hash_alg = fwid_oid; if (ASN1_OCTET_STRING_set (fwid->digest, dice->tcb->fwid, fwid_len) == 0) { status = -ERR_get_error (); goto err_fwid; } status = sk_DICE_FWID_push (tcbinfo->digests, fwid); if (status == 0) { status = DICE_TCBINFO_EXTENSION_NO_MEMORY; goto err_fwid; } tcb_der_len = i2d_DICE_TCBINFO (tcbinfo, &tcb_der); if (tcb_der_len < 0) { status = -ERR_get_error (); goto err_build; } x509_extension_builder_init_extension_descriptor (extension, false, X509_EXTENSION_BUILDER_DICE_TCBINFO_OID, X509_EXTENSION_BUILDER_DICE_TCBINFO_OID_LENGTH, tcb_der, tcb_der_len); DICE_TCBINFO_free (tcbinfo); return 0; err_fwid: DICE_FWID_free (fwid); err_build: DICE_TCBINFO_free (tcbinfo); err_tcb: return status; } void x509_extension_builder_openssl_dice_tcbinfo_free (const struct x509_extension_builder *builder, struct x509_extension *extension) { UNUSED (builder); platform_free ((void*) extension->data); } /** * Initialize an extension builder for a TCG DICE TcbInfo extension. * * @param builder The extension builder to initialize. * @param tcb The firmware TCB to encode in the extension. This does not need to be constant. The * contents can be externally modified after initialization to change what will be encoded in the * extension. * * @return 0 if the extension builder was initialized successfully or an error code. */ int x509_extension_builder_openssl_dice_tcbinfo_init ( struct x509_extension_builder_openssl_dice_tcbinfo *builder, const struct tcg_dice_tcbinfo *tcb) { if ((builder == NULL) || (tcb == NULL)) { return DICE_TCBINFO_EXTENSION_INVALID_ARGUMENT; } memset (builder, 0, sizeof (struct x509_extension_builder_openssl_dice_tcbinfo)); builder->base.build = x509_extension_builder_openssl_dice_tcbinfo_build; builder->base.free = x509_extension_builder_openssl_dice_tcbinfo_free; builder->tcb = tcb; return 0; } /** * Release the resources used by a TCG DICE TcbInfo extension builder. * * @param builder The extension builder to release. */ void x509_extension_builder_openssl_dice_tcbinfo_release ( const struct x509_extension_builder_openssl_dice_tcbinfo *builder) { UNUSED (builder); }