diff --git a/common/auth/polarssl/polarssl.c b/common/auth/polarssl/polarssl.c index e099f50..82c8b33 100644 --- a/common/auth/polarssl/polarssl.c +++ b/common/auth/polarssl/polarssl.c @@ -51,8 +51,8 @@ * during the Trusted Boot process. */ -/* SHA256 algorithm */ -#define SHA_BYTES 32 +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 /* * An 8 KB stack has been proven to be enough for the current Trusted Boot @@ -79,6 +79,18 @@ #define RSA_PUB_DER_MAX_BYTES 38 + 2 * POLARSSL_MPI_MAX_SIZE /* + * SHA256: + * DigestInfo ::= SEQUENCE { 1 + 1 + * digestAlgorithm AlgorithmIdentifier, + 1 + 1 (sequence) + * + 1 + 1 + 9 (sha256 oid) + * + 1 + 1 (params null) + * digest OCTET STRING + 1 + 1 + 32 (sha256) + * } + */ +#define SHA256_BYTES 32 +#define SHA256_DER_BYTES (19 + SHA256_BYTES) + +/* * Buffer for storing public keys extracted from certificates while they are * verified */ @@ -89,13 +101,13 @@ /* BL specific variables */ #if IMAGE_BL1 -static unsigned char sha_bl2[SHA_BYTES]; +static unsigned char sha_bl2[SHA256_DER_BYTES]; #elif IMAGE_BL2 /* Buffers to store the hash of BL3-x images */ -static unsigned char sha_bl30[SHA_BYTES]; -static unsigned char sha_bl31[SHA_BYTES]; -static unsigned char sha_bl32[SHA_BYTES]; -static unsigned char sha_bl33[SHA_BYTES]; +static unsigned char sha_bl30[SHA256_DER_BYTES]; +static unsigned char sha_bl31[SHA256_DER_BYTES]; +static unsigned char sha_bl32[SHA256_DER_BYTES]; +static unsigned char sha_bl33[SHA256_DER_BYTES]; /* Buffers to store the Trusted and Non-Trusted world public keys */ static unsigned char tz_world_pk[RSA_PUB_DER_MAX_BYTES]; static unsigned char ntz_world_pk[RSA_PUB_DER_MAX_BYTES]; @@ -111,12 +123,12 @@ x509_crt *crt, const char *oid) { - int ret; + int ret, oid_len; size_t len; unsigned char *end_ext_data, *end_ext_octet; unsigned char *p; const unsigned char *end; - char oid_str[64]; + char oid_str[MAX_OID_STR_LEN]; p = crt->v3_ext.p; end = crt->v3_ext.p + crt->v3_ext.len; @@ -177,8 +189,12 @@ POLARSSL_ERR_ASN1_LENGTH_MISMATCH; /* Detect requested extension */ - oid_get_numeric_string(oid_str, 64, &extn_oid); - if (memcmp(oid, oid_str, sizeof(oid)) == 0) { + oid_len = oid_get_numeric_string(oid_str, + MAX_OID_STR_LEN, &extn_oid); + if (oid_len == POLARSSL_ERR_OID_BUF_TOO_SMALL) + return POLARSSL_ERR_X509_INVALID_EXTENSIONS + + POLARSSL_ERR_ASN1_BUF_TOO_SMALL; + if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { *ext_data = p; *ext_len = len; return 0; @@ -251,11 +267,8 @@ goto error; } - assert(sz == SHA_BYTES + 2); - - /* Skip the tag and length bytes and copy the hash */ - p += 2; - memcpy(sha_bl2, p, SHA_BYTES); + assert(sz == SHA256_DER_BYTES); + memcpy(sha_bl2, p, SHA256_DER_BYTES); error: x509_crt_free(&cert); @@ -433,11 +446,8 @@ goto error; } - assert(sz == SHA_BYTES + 2); - - /* Skip the tag and length bytes and copy the hash */ - p += 2; - memcpy(sha, p, SHA_BYTES); + assert(sz == SHA256_DER_BYTES); + memcpy(sha, p, SHA256_DER_BYTES); error: x509_crt_free(&cert); @@ -460,18 +470,68 @@ static int check_bl_img(unsigned char *buf, size_t len, const unsigned char *sha) { - unsigned char img_sha[SHA_BYTES]; + asn1_buf md_oid, params; + md_type_t md_alg; + int err; + unsigned char *p = NULL; + const unsigned char *end = NULL; + size_t sz; + unsigned char img_sha[SHA256_BYTES]; + + /* + * Extract the image hash from the ASN.1 structure: + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ + + p = (unsigned char *)sha; + end = sha + SHA256_DER_BYTES; + err = asn1_get_tag(&p, end, &sz, ASN1_CONSTRUCTED | ASN1_SEQUENCE); + if (err != 0) { + ERROR("Malformed image hash extension\n"); + goto error; + } + + err = asn1_get_alg(&p, end, &md_oid, ¶ms); + if (err != 0) { + ERROR("Malformed image hash algorithm\n"); + goto error; + } + + err = oid_get_md_alg(&md_oid, &md_alg); + if (err != 0) { + ERROR("Unknown image hash algorithm\n"); + goto error; + } + + /* Only SHA256 is supported */ + if (md_alg != POLARSSL_MD_SHA256) { + ERROR("Only SHA256 is supported as image hash algorithm\n"); + err = 1; + goto error; + } + + /* Get the hash */ + err = asn1_get_tag(&p, end, &sz, ASN1_OCTET_STRING); + if (err != 0) { + ERROR("Image hash not found in extension\n"); + goto error; + } /* Calculate the hash of the image */ sha256(buf, len, img_sha, 0); /* Match the hash with the one extracted from the certificate */ - if (memcmp(img_sha, sha, SHA_BYTES)) { + if (memcmp(img_sha, p, SHA256_BYTES)) { ERROR("Image hash mismatch\n"); return 1; } - return 0; +error: + return err; } /* diff --git a/tools/cert_create/include/ext.h b/tools/cert_create/include/ext.h index d73f573..57bb65f 100644 --- a/tools/cert_create/include/ext.h +++ b/tools/cert_create/include/ext.h @@ -63,7 +63,8 @@ }; int ext_init(ext_t *tbb_ext); -X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len); +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len); X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value); X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k); diff --git a/tools/cert_create/src/ext.c b/tools/cert_create/src/ext.c index 31f84a8..21b90db 100644 --- a/tools/cert_create/src/ext.c +++ b/tools/cert_create/src/ext.c @@ -31,13 +31,29 @@ #include #include #include +#include +#include #include #include #include "ext.h" DECLARE_ASN1_ITEM(ASN1_INTEGER) +DECLARE_ASN1_ITEM(X509_ALGOR) DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) +typedef struct { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *dataHash; +} HASH; + +ASN1_SEQUENCE(HASH) = { + ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR), + ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(HASH) + +DECLARE_ASN1_FUNCTIONS(HASH) +IMPLEMENT_ASN1_FUNCTIONS(HASH) + /* * This function adds the TBB extensions to the internal extension list * maintained by OpenSSL so they can be used later. @@ -123,37 +139,85 @@ } /* - * Creates a x509v3 extension containing a hash encapsulated in an ASN1 Octet - * String + * Creates a x509v3 extension containing a hash + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } * * Parameters: - * pex: OpenSSL extension pointer (output parameter) * nid: extension identifier * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * md: hash algorithm * buf: pointer to the buffer that contains the hash * len: size of the hash in bytes * * Return: Extension address, NULL if error */ -X509_EXTENSION *ext_new_hash(int nid, int crit, unsigned char *buf, size_t len) +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len) { X509_EXTENSION *ex = NULL; - ASN1_OCTET_STRING *hash = NULL; + ASN1_OCTET_STRING *octet = NULL; + HASH *hash = NULL; + ASN1_OBJECT *algorithm = NULL; + X509_ALGOR *x509_algor = NULL; unsigned char *p = NULL; int sz = -1; - /* Encode Hash */ - hash = ASN1_OCTET_STRING_new(); - ASN1_OCTET_STRING_set(hash, buf, len); - sz = i2d_ASN1_OCTET_STRING(hash, NULL); - i2d_ASN1_OCTET_STRING(hash, &p); + /* OBJECT_IDENTIFIER with hash algorithm */ + algorithm = OBJ_nid2obj(md->type); + if (algorithm == NULL) { + return NULL; + } + + /* Create X509_ALGOR */ + x509_algor = X509_ALGOR_new(); + if (x509_algor == NULL) { + return NULL; + } + x509_algor->algorithm = algorithm; + x509_algor->parameter = ASN1_TYPE_new(); + ASN1_TYPE_set(x509_algor->parameter, V_ASN1_NULL, NULL); + + /* OCTET_STRING with the actual hash */ + octet = ASN1_OCTET_STRING_new(); + if (octet == NULL) { + X509_ALGOR_free(x509_algor); + return NULL; + } + ASN1_OCTET_STRING_set(octet, buf, len); + + /* HASH structure containing algorithm + hash */ + hash = HASH_new(); + if (hash == NULL) { + ASN1_OCTET_STRING_free(octet); + X509_ALGOR_free(x509_algor); + return NULL; + } + hash->hashAlgorithm = x509_algor; + hash->dataHash = octet; + + /* DER encoded HASH */ + sz = i2d_HASH(hash, &p); + if ((sz <= 0) || (p == NULL)) { + HASH_free(hash); + X509_ALGOR_free(x509_algor); + return NULL; + } /* Create the extension */ ex = ext_new(nid, crit, p, sz); /* Clean up */ OPENSSL_free(p); - ASN1_OCTET_STRING_free(hash); + HASH_free(hash); return ex; } diff --git a/tools/cert_create/src/main.c b/tools/cert_create/src/main.c index 6df367a..2af5247 100644 --- a/tools/cert_create/src/main.c +++ b/tools/cert_create/src/main.c @@ -277,6 +277,7 @@ int i, tz_nvctr_nid, ntz_nvctr_nid, hash_nid, pk_nid; int c, opt_idx = 0; unsigned char md[SHA256_DIGEST_LENGTH]; + const EVP_MD *md_info; NOTICE("CoT Generation Tool: %s\n", build_msg); NOTICE("Target platform: %s\n", platform_msg); @@ -389,6 +390,10 @@ exit(1); } + /* Indicate SHA256 as image hash algorithm in the certificate + * extension */ + md_info = EVP_sha256(); + /* Get non-volatile counters NIDs */ CHECK_OID(tz_nvctr_nid, TZ_FW_NVCOUNTER_OID); CHECK_OID(ntz_nvctr_nid, NTZ_FW_NVCOUNTER_OID); @@ -430,7 +435,7 @@ exit(1); } CHECK_OID(hash_nid, BL2_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); @@ -509,8 +514,8 @@ exit(1); } CHECK_OID(hash_nid, BL30_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, + md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); if (!cert_new(&certs[BL30_CERT], VAL_DAYS, 0, sk)) { @@ -559,7 +564,7 @@ exit(1); } CHECK_OID(hash_nid, BL31_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); @@ -612,8 +617,8 @@ exit(1); } CHECK_OID(hash_nid, BL32_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, - SHA256_DIGEST_LENGTH)); + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, + md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext); if (!cert_new(&certs[BL32_CERT], VAL_DAYS, 0, sk)) { @@ -662,7 +667,7 @@ exit(1); } CHECK_OID(hash_nid, BL33_HASH_OID); - CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md, + CHECK_NULL(hash_ext, ext_new_hash(hash_nid, EXT_CRIT, md_info, md, SHA256_DIGEST_LENGTH)); sk_X509_EXTENSION_push(sk, hash_ext);