* 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
*/
#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
/* 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];
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;
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;
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);
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);
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;
}
/*
};
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);
#include <stddef.h>
#include <stdio.h>
#include <string.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
#include <openssl/err.h>
#include <openssl/x509v3.h>
#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.
}
/*
- * 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;
}
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);
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);
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);
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)) {
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);
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)) {
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);