blob: 4c6dc0fcca1db8dfa7bd344b3b3c34afe34bea93 [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>
Madhukar Pappireddy57eaae82020-03-05 18:18:40 -060015#include <mbedtls/x509.h>
Juan Castilloa57a4d52015-04-02 15:44:20 +010016
Antonio Nino Diaze0f90632018-12-14 00:18:21 +000017#include <common/debug.h>
18#include <drivers/auth/crypto_mod.h>
19#include <drivers/auth/mbedtls/mbedtls_common.h>
20#include <drivers/auth/mbedtls/mbedtls_config.h>
21
Juan Castillobae6b2a2015-11-05 09:24:53 +000022#define LIB_NAME "mbed TLS"
Juan Castilloa57a4d52015-04-02 15:44:20 +010023
24/*
25 * AlgorithmIdentifier ::= SEQUENCE {
26 * algorithm OBJECT IDENTIFIER,
27 * parameters ANY DEFINED BY algorithm OPTIONAL
28 * }
29 *
30 * SubjectPublicKeyInfo ::= SEQUENCE {
31 * algorithm AlgorithmIdentifier,
32 * subjectPublicKey BIT STRING
33 * }
34 *
35 * DigestInfo ::= SEQUENCE {
36 * digestAlgorithm AlgorithmIdentifier,
37 * digest OCTET STRING
38 * }
39 */
40
41/*
42 * Initialize the library and export the descriptor
43 */
44static void init(void)
45{
Juan Castillobae6b2a2015-11-05 09:24:53 +000046 /* Initialize mbed TLS */
Juan Castilloa57a4d52015-04-02 15:44:20 +010047 mbedtls_init();
48}
49
50/*
51 * Verify a signature.
52 *
53 * Parameters are passed using the DER encoding format following the ASN.1
54 * structures detailed above.
55 */
56static int verify_signature(void *data_ptr, unsigned int data_len,
57 void *sig_ptr, unsigned int sig_len,
58 void *sig_alg, unsigned int sig_alg_len,
59 void *pk_ptr, unsigned int pk_len)
60{
Juan Castillobae6b2a2015-11-05 09:24:53 +000061 mbedtls_asn1_buf sig_oid, sig_params;
62 mbedtls_asn1_buf signature;
63 mbedtls_md_type_t md_alg;
64 mbedtls_pk_type_t pk_alg;
Soby Mathew0a68d132017-05-31 10:35:27 +010065 mbedtls_pk_context pk = {0};
Juan Castilloa57a4d52015-04-02 15:44:20 +010066 int rc;
67 void *sig_opts = NULL;
Juan Castillobae6b2a2015-11-05 09:24:53 +000068 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +010069 unsigned char *p, *end;
Juan Castillobae6b2a2015-11-05 09:24:53 +000070 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +010071
72 /* Get pointers to signature OID and parameters */
73 p = (unsigned char *)sig_alg;
74 end = (unsigned char *)(p + sig_alg_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000075 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
Juan Castilloa57a4d52015-04-02 15:44:20 +010076 if (rc != 0) {
77 return CRYPTO_ERR_SIGNATURE;
78 }
79
80 /* Get the actual signature algorithm (MD + PK) */
Soby Mathew0a68d132017-05-31 10:35:27 +010081 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +010082 if (rc != 0) {
83 return CRYPTO_ERR_SIGNATURE;
84 }
85
86 /* Parse the public key */
Juan Castillobae6b2a2015-11-05 09:24:53 +000087 mbedtls_pk_init(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010088 p = (unsigned char *)pk_ptr;
89 end = (unsigned char *)(p + pk_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000090 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010091 if (rc != 0) {
Soby Mathew0a68d132017-05-31 10:35:27 +010092 rc = CRYPTO_ERR_SIGNATURE;
93 goto end2;
Juan Castilloa57a4d52015-04-02 15:44:20 +010094 }
95
96 /* Get the signature (bitstring) */
97 p = (unsigned char *)sig_ptr;
98 end = (unsigned char *)(p + sig_len);
99 signature.tag = *p;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000100 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100101 if (rc != 0) {
102 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100103 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100104 }
105 signature.p = p;
106
107 /* Calculate the hash of the data */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000108 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100109 if (md_info == NULL) {
110 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100111 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100112 }
113 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000114 rc = mbedtls_md(md_info, p, data_len, hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100115 if (rc != 0) {
116 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100117 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100118 }
119
120 /* Verify the signature */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000121 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
122 mbedtls_md_get_size(md_info),
123 signature.p, signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100124 if (rc != 0) {
125 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100126 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100127 }
128
129 /* Signature verification success */
130 rc = CRYPTO_SUCCESS;
131
Soby Mathew0a68d132017-05-31 10:35:27 +0100132end1:
Juan Castillobae6b2a2015-11-05 09:24:53 +0000133 mbedtls_pk_free(&pk);
Soby Mathew0a68d132017-05-31 10:35:27 +0100134end2:
135 mbedtls_free(sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100136 return rc;
137}
138
139/*
140 * Match a hash
141 *
142 * Digest info is passed in DER format following the ASN.1 structure detailed
143 * above.
144 */
145static int verify_hash(void *data_ptr, unsigned int data_len,
146 void *digest_info_ptr, unsigned int digest_info_len)
147{
Juan Castillobae6b2a2015-11-05 09:24:53 +0000148 mbedtls_asn1_buf hash_oid, params;
149 mbedtls_md_type_t md_alg;
150 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100151 unsigned char *p, *end, *hash;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000152 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +0100153 size_t len;
154 int rc;
155
Juan Castillobae6b2a2015-11-05 09:24:53 +0000156 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
Juan Castilloa57a4d52015-04-02 15:44:20 +0100157 p = (unsigned char *)digest_info_ptr;
Sandrine Bailleuxdf8de2d2016-01-04 15:49:23 +0000158 end = p + digest_info_len;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000159 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
160 MBEDTLS_ASN1_SEQUENCE);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100161 if (rc != 0) {
162 return CRYPTO_ERR_HASH;
163 }
164
165 /* Get the hash algorithm */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000166 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100167 if (rc != 0) {
168 return CRYPTO_ERR_HASH;
169 }
170
Juan Castillobae6b2a2015-11-05 09:24:53 +0000171 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100172 if (rc != 0) {
173 return CRYPTO_ERR_HASH;
174 }
175
Juan Castillobae6b2a2015-11-05 09:24:53 +0000176 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100177 if (md_info == NULL) {
178 return CRYPTO_ERR_HASH;
179 }
180
181 /* Hash should be octet string type */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000182 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100183 if (rc != 0) {
184 return CRYPTO_ERR_HASH;
185 }
186
187 /* Length of hash must match the algorithm's size */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000188 if (len != mbedtls_md_get_size(md_info)) {
Juan Castilloa57a4d52015-04-02 15:44:20 +0100189 return CRYPTO_ERR_HASH;
190 }
191 hash = p;
192
193 /* Calculate the hash of the data */
194 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000195 rc = mbedtls_md(md_info, p, data_len, data_hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100196 if (rc != 0) {
197 return CRYPTO_ERR_HASH;
198 }
199
200 /* Compare values */
Antonio Nino Diaz0ca1afa2017-02-09 10:26:54 +0000201 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
Juan Castilloa57a4d52015-04-02 15:44:20 +0100202 if (rc != 0) {
203 return CRYPTO_ERR_HASH;
204 }
205
206 return CRYPTO_SUCCESS;
207}
208
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000209#if MEASURED_BOOT
210/*
211 * Calculate a hash
212 *
213 * output points to the computed hash
214 */
215int calc_hash(unsigned int alg, void *data_ptr,
216 unsigned int data_len, unsigned char *output)
217{
218 const mbedtls_md_info_t *md_info;
219
220 md_info = mbedtls_md_info_from_type((mbedtls_md_type_t)alg);
221 if (md_info == NULL) {
222 return CRYPTO_ERR_HASH;
223 }
224
225 /* Calculate the hash of the data */
226 return mbedtls_md(md_info, data_ptr, data_len, output);
227}
228#endif /* MEASURED_BOOT */
229
Juan Castilloa57a4d52015-04-02 15:44:20 +0100230/*
231 * Register crypto library descriptor
232 */
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000233#if MEASURED_BOOT
234REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash);
235#else
Juan Castilloa57a4d52015-04-02 15:44:20 +0100236REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
Alexei Fedorov913cb7e2020-01-23 14:27:38 +0000237#endif /* MEASURED_BOOT */