blob: 04fbc648b9d9f096e10e684005fca5e925ce6eea [file] [log] [blame]
Juan Castilloa57a4d52015-04-02 15:44:20 +01001/*
Alexei Fedorov913cb7e2020-01-23 14:27:38 +00002 * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved.
Juan Castilloa57a4d52015-04-02 15:44:20 +01003 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castilloa57a4d52015-04-02 15:44:20 +01005 */
6
Juan Castilloa57a4d52015-04-02 15:44:20 +01007#include <stddef.h>
8#include <string.h>
9
Juan Castillobae6b2a2015-11-05 09:24:53 +000010/* mbed TLS headers */
11#include <mbedtls/md.h>
12#include <mbedtls/memory_buffer_alloc.h>
13#include <mbedtls/oid.h>
14#include <mbedtls/platform.h>
Juan Castilloa57a4d52015-04-02 15:44:20 +010015
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000016#include <common/debug.h>
17#include <drivers/auth/crypto_mod.h>
18#include <drivers/auth/mbedtls/mbedtls_common.h>
19#include <drivers/auth/mbedtls/mbedtls_config.h>
20
Juan Castillobae6b2a2015-11-05 09:24:53 +000021#define LIB_NAME "mbed TLS"
Juan Castilloa57a4d52015-04-02 15:44:20 +010022
23/*
24 * AlgorithmIdentifier ::= SEQUENCE {
25 * algorithm OBJECT IDENTIFIER,
26 * parameters ANY DEFINED BY algorithm OPTIONAL
27 * }
28 *
29 * SubjectPublicKeyInfo ::= SEQUENCE {
30 * algorithm AlgorithmIdentifier,
31 * subjectPublicKey BIT STRING
32 * }
33 *
34 * DigestInfo ::= SEQUENCE {
35 * digestAlgorithm AlgorithmIdentifier,
36 * digest OCTET STRING
37 * }
38 */
39
40/*
41 * Initialize the library and export the descriptor
42 */
43static void init(void)
44{
Juan Castillobae6b2a2015-11-05 09:24:53 +000045 /* Initialize mbed TLS */
Juan Castilloa57a4d52015-04-02 15:44:20 +010046 mbedtls_init();
47}
48
49/*
50 * Verify a signature.
51 *
52 * Parameters are passed using the DER encoding format following the ASN.1
53 * structures detailed above.
54 */
55static int verify_signature(void *data_ptr, unsigned int data_len,
56 void *sig_ptr, unsigned int sig_len,
57 void *sig_alg, unsigned int sig_alg_len,
58 void *pk_ptr, unsigned int pk_len)
59{
Juan Castillobae6b2a2015-11-05 09:24:53 +000060 mbedtls_asn1_buf sig_oid, sig_params;
61 mbedtls_asn1_buf signature;
62 mbedtls_md_type_t md_alg;
63 mbedtls_pk_type_t pk_alg;
Soby Mathew0a68d132017-05-31 10:35:27 +010064 mbedtls_pk_context pk = {0};
Juan Castilloa57a4d52015-04-02 15:44:20 +010065 int rc;
66 void *sig_opts = NULL;
Juan Castillobae6b2a2015-11-05 09:24:53 +000067 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +010068 unsigned char *p, *end;
Juan Castillobae6b2a2015-11-05 09:24:53 +000069 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +010070
71 /* Get pointers to signature OID and parameters */
72 p = (unsigned char *)sig_alg;
73 end = (unsigned char *)(p + sig_alg_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000074 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
Juan Castilloa57a4d52015-04-02 15:44:20 +010075 if (rc != 0) {
76 return CRYPTO_ERR_SIGNATURE;
77 }
78
79 /* Get the actual signature algorithm (MD + PK) */
Soby Mathew0a68d132017-05-31 10:35:27 +010080 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +010081 if (rc != 0) {
82 return CRYPTO_ERR_SIGNATURE;
83 }
84
85 /* Parse the public key */
Juan Castillobae6b2a2015-11-05 09:24:53 +000086 mbedtls_pk_init(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010087 p = (unsigned char *)pk_ptr;
88 end = (unsigned char *)(p + pk_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000089 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010090 if (rc != 0) {
Soby Mathew0a68d132017-05-31 10:35:27 +010091 rc = CRYPTO_ERR_SIGNATURE;
92 goto end2;
Juan Castilloa57a4d52015-04-02 15:44:20 +010093 }
94
95 /* Get the signature (bitstring) */
96 p = (unsigned char *)sig_ptr;
97 end = (unsigned char *)(p + sig_len);
98 signature.tag = *p;
Juan Castillobae6b2a2015-11-05 09:24:53 +000099 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100100 if (rc != 0) {
101 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100102 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100103 }
104 signature.p = p;
105
106 /* Calculate the hash of the data */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000107 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100108 if (md_info == NULL) {
109 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100110 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100111 }
112 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000113 rc = mbedtls_md(md_info, p, data_len, hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100114 if (rc != 0) {
115 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100116 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100117 }
118
119 /* Verify the signature */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000120 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
121 mbedtls_md_get_size(md_info),
122 signature.p, signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100123 if (rc != 0) {
124 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100125 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100126 }
127
128 /* Signature verification success */
129 rc = CRYPTO_SUCCESS;
130
Soby Mathew0a68d132017-05-31 10:35:27 +0100131end1:
Juan Castillobae6b2a2015-11-05 09:24:53 +0000132 mbedtls_pk_free(&pk);
Soby Mathew0a68d132017-05-31 10:35:27 +0100133end2:
134 mbedtls_free(sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100135 return rc;
136}
137
138/*
139 * Match a hash
140 *
141 * Digest info is passed in DER format following the ASN.1 structure detailed
142 * above.
143 */
144static int verify_hash(void *data_ptr, unsigned int data_len,
145 void *digest_info_ptr, unsigned int digest_info_len)
146{
Juan Castillobae6b2a2015-11-05 09:24:53 +0000147 mbedtls_asn1_buf hash_oid, params;
148 mbedtls_md_type_t md_alg;
149 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100150 unsigned char *p, *end, *hash;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000151 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +0100152 size_t len;
153 int rc;
154
Juan Castillobae6b2a2015-11-05 09:24:53 +0000155 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
Juan Castilloa57a4d52015-04-02 15:44:20 +0100156 p = (unsigned char *)digest_info_ptr;
Sandrine Bailleuxdf8de2d2016-01-04 15:49:23 +0000157 end = p + digest_info_len;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000158 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
159 MBEDTLS_ASN1_SEQUENCE);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100160 if (rc != 0) {
161 return CRYPTO_ERR_HASH;
162 }
163
164 /* Get the hash algorithm */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000165 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100166 if (rc != 0) {
167 return CRYPTO_ERR_HASH;
168 }
169
Juan Castillobae6b2a2015-11-05 09:24:53 +0000170 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100171 if (rc != 0) {
172 return CRYPTO_ERR_HASH;
173 }
174
Juan Castillobae6b2a2015-11-05 09:24:53 +0000175 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100176 if (md_info == NULL) {
177 return CRYPTO_ERR_HASH;
178 }
179
180 /* Hash should be octet string type */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000181 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100182 if (rc != 0) {
183 return CRYPTO_ERR_HASH;
184 }
185
186 /* Length of hash must match the algorithm's size */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000187 if (len != mbedtls_md_get_size(md_info)) {
Juan Castilloa57a4d52015-04-02 15:44:20 +0100188 return CRYPTO_ERR_HASH;
189 }
190 hash = p;
191
192 /* Calculate the hash of the data */
193 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000194 rc = mbedtls_md(md_info, p, data_len, data_hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100195 if (rc != 0) {
196 return CRYPTO_ERR_HASH;
197 }
198
199 /* Compare values */
Antonio Nino Diaz0ca1afa2017-02-09 10:26:54 +0000200 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
Juan Castilloa57a4d52015-04-02 15:44:20 +0100201 if (rc != 0) {
202 return CRYPTO_ERR_HASH;
203 }
204
205 return CRYPTO_SUCCESS;
206}
207
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000208#if MEASURED_BOOT
209/*
210 * Calculate a hash
211 *
212 * output points to the computed hash
213 */
214int calc_hash(unsigned int alg, void *data_ptr,
215 unsigned int data_len, unsigned char *output)
216{
217 const mbedtls_md_info_t *md_info;
218
219 md_info = mbedtls_md_info_from_type((mbedtls_md_type_t)alg);
220 if (md_info == NULL) {
221 return CRYPTO_ERR_HASH;
222 }
223
224 /* Calculate the hash of the data */
225 return mbedtls_md(md_info, data_ptr, data_len, output);
226}
227#endif /* MEASURED_BOOT */
228
Juan Castilloa57a4d52015-04-02 15:44:20 +0100229/*
230 * Register crypto library descriptor
231 */
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000232#if MEASURED_BOOT
233REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash);
234#else
Juan Castilloa57a4d52015-04-02 15:44:20 +0100235REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000236#endif /* MEASURED_BOOT */