blob: b157a32ed2dfe7f5e0f8b765d113a4a2f0cd6694 [file] [log] [blame]
Juan Castilloa57a4d52015-04-02 15:44:20 +01001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
dp-armfa3cf0b2017-05-03 09:38:09 +01004 * SPDX-License-Identifier: BSD-3-Clause
Juan Castilloa57a4d52015-04-02 15:44:20 +01005 */
6
7
8#include <crypto_mod.h>
9#include <debug.h>
10#include <mbedtls_common.h>
11#include <stddef.h>
12#include <string.h>
13
Juan Castillobae6b2a2015-11-05 09:24:53 +000014/* mbed TLS headers */
15#include <mbedtls/md.h>
16#include <mbedtls/memory_buffer_alloc.h>
17#include <mbedtls/oid.h>
18#include <mbedtls/platform.h>
Juan Castilloa57a4d52015-04-02 15:44:20 +010019
Juan Castillobae6b2a2015-11-05 09:24:53 +000020#define LIB_NAME "mbed TLS"
Juan Castilloa57a4d52015-04-02 15:44:20 +010021
22/*
23 * AlgorithmIdentifier ::= SEQUENCE {
24 * algorithm OBJECT IDENTIFIER,
25 * parameters ANY DEFINED BY algorithm OPTIONAL
26 * }
27 *
28 * SubjectPublicKeyInfo ::= SEQUENCE {
29 * algorithm AlgorithmIdentifier,
30 * subjectPublicKey BIT STRING
31 * }
32 *
33 * DigestInfo ::= SEQUENCE {
34 * digestAlgorithm AlgorithmIdentifier,
35 * digest OCTET STRING
36 * }
37 */
38
39/*
40 * Initialize the library and export the descriptor
41 */
42static void init(void)
43{
Juan Castillobae6b2a2015-11-05 09:24:53 +000044 /* Initialize mbed TLS */
Juan Castilloa57a4d52015-04-02 15:44:20 +010045 mbedtls_init();
46}
47
48/*
49 * Verify a signature.
50 *
51 * Parameters are passed using the DER encoding format following the ASN.1
52 * structures detailed above.
53 */
54static int verify_signature(void *data_ptr, unsigned int data_len,
55 void *sig_ptr, unsigned int sig_len,
56 void *sig_alg, unsigned int sig_alg_len,
57 void *pk_ptr, unsigned int pk_len)
58{
Juan Castillobae6b2a2015-11-05 09:24:53 +000059 mbedtls_asn1_buf sig_oid, sig_params;
60 mbedtls_asn1_buf signature;
61 mbedtls_md_type_t md_alg;
62 mbedtls_pk_type_t pk_alg;
Soby Mathew0a68d132017-05-31 10:35:27 +010063 mbedtls_pk_context pk = {0};
Juan Castilloa57a4d52015-04-02 15:44:20 +010064 int rc;
65 void *sig_opts = NULL;
Juan Castillobae6b2a2015-11-05 09:24:53 +000066 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +010067 unsigned char *p, *end;
Juan Castillobae6b2a2015-11-05 09:24:53 +000068 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +010069
70 /* Get pointers to signature OID and parameters */
71 p = (unsigned char *)sig_alg;
72 end = (unsigned char *)(p + sig_alg_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000073 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
Juan Castilloa57a4d52015-04-02 15:44:20 +010074 if (rc != 0) {
75 return CRYPTO_ERR_SIGNATURE;
76 }
77
78 /* Get the actual signature algorithm (MD + PK) */
Soby Mathew0a68d132017-05-31 10:35:27 +010079 rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +010080 if (rc != 0) {
81 return CRYPTO_ERR_SIGNATURE;
82 }
83
84 /* Parse the public key */
Juan Castillobae6b2a2015-11-05 09:24:53 +000085 mbedtls_pk_init(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010086 p = (unsigned char *)pk_ptr;
87 end = (unsigned char *)(p + pk_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000088 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +010089 if (rc != 0) {
Soby Mathew0a68d132017-05-31 10:35:27 +010090 rc = CRYPTO_ERR_SIGNATURE;
91 goto end2;
Juan Castilloa57a4d52015-04-02 15:44:20 +010092 }
93
94 /* Get the signature (bitstring) */
95 p = (unsigned char *)sig_ptr;
96 end = (unsigned char *)(p + sig_len);
97 signature.tag = *p;
Juan Castillobae6b2a2015-11-05 09:24:53 +000098 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +010099 if (rc != 0) {
100 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100101 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100102 }
103 signature.p = p;
104
105 /* Calculate the hash of the data */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000106 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100107 if (md_info == NULL) {
108 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100109 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100110 }
111 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000112 rc = mbedtls_md(md_info, p, data_len, hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100113 if (rc != 0) {
114 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100115 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100116 }
117
118 /* Verify the signature */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000119 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
120 mbedtls_md_get_size(md_info),
121 signature.p, signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100122 if (rc != 0) {
123 rc = CRYPTO_ERR_SIGNATURE;
Soby Mathew0a68d132017-05-31 10:35:27 +0100124 goto end1;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100125 }
126
127 /* Signature verification success */
128 rc = CRYPTO_SUCCESS;
129
Soby Mathew0a68d132017-05-31 10:35:27 +0100130end1:
Juan Castillobae6b2a2015-11-05 09:24:53 +0000131 mbedtls_pk_free(&pk);
Soby Mathew0a68d132017-05-31 10:35:27 +0100132end2:
133 mbedtls_free(sig_opts);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100134 return rc;
135}
136
137/*
138 * Match a hash
139 *
140 * Digest info is passed in DER format following the ASN.1 structure detailed
141 * above.
142 */
143static int verify_hash(void *data_ptr, unsigned int data_len,
144 void *digest_info_ptr, unsigned int digest_info_len)
145{
Juan Castillobae6b2a2015-11-05 09:24:53 +0000146 mbedtls_asn1_buf hash_oid, params;
147 mbedtls_md_type_t md_alg;
148 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100149 unsigned char *p, *end, *hash;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000150 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +0100151 size_t len;
152 int rc;
153
Juan Castillobae6b2a2015-11-05 09:24:53 +0000154 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
Juan Castilloa57a4d52015-04-02 15:44:20 +0100155 p = (unsigned char *)digest_info_ptr;
Sandrine Bailleuxdf8de2d2016-01-04 15:49:23 +0000156 end = p + digest_info_len;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000157 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
158 MBEDTLS_ASN1_SEQUENCE);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100159 if (rc != 0) {
160 return CRYPTO_ERR_HASH;
161 }
162
163 /* Get the hash algorithm */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000164 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100165 if (rc != 0) {
166 return CRYPTO_ERR_HASH;
167 }
168
Juan Castillobae6b2a2015-11-05 09:24:53 +0000169 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100170 if (rc != 0) {
171 return CRYPTO_ERR_HASH;
172 }
173
Juan Castillobae6b2a2015-11-05 09:24:53 +0000174 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100175 if (md_info == NULL) {
176 return CRYPTO_ERR_HASH;
177 }
178
179 /* Hash should be octet string type */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000180 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100181 if (rc != 0) {
182 return CRYPTO_ERR_HASH;
183 }
184
185 /* Length of hash must match the algorithm's size */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000186 if (len != mbedtls_md_get_size(md_info)) {
Juan Castilloa57a4d52015-04-02 15:44:20 +0100187 return CRYPTO_ERR_HASH;
188 }
189 hash = p;
190
191 /* Calculate the hash of the data */
192 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000193 rc = mbedtls_md(md_info, p, data_len, data_hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100194 if (rc != 0) {
195 return CRYPTO_ERR_HASH;
196 }
197
198 /* Compare values */
Antonio Nino Diaz0ca1afa2017-02-09 10:26:54 +0000199 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
Juan Castilloa57a4d52015-04-02 15:44:20 +0100200 if (rc != 0) {
201 return CRYPTO_ERR_HASH;
202 }
203
204 return CRYPTO_SUCCESS;
205}
206
207/*
208 * Register crypto library descriptor
209 */
210REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);