blob: 11d3ede45abe0211d7279c3079fe9335edb55a6f [file] [log] [blame]
Juan Castilloa57a4d52015-04-02 15:44:20 +01001/*
2 * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * Redistributions of source code must retain the above copyright notice, this
8 * list of conditions and the following disclaimer.
9 *
10 * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * Neither the name of ARM nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without specific
16 * prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31
32#include <crypto_mod.h>
33#include <debug.h>
34#include <mbedtls_common.h>
35#include <stddef.h>
36#include <string.h>
37
Juan Castillobae6b2a2015-11-05 09:24:53 +000038/* mbed TLS headers */
39#include <mbedtls/md.h>
40#include <mbedtls/memory_buffer_alloc.h>
41#include <mbedtls/oid.h>
42#include <mbedtls/platform.h>
Juan Castilloa57a4d52015-04-02 15:44:20 +010043
Juan Castillobae6b2a2015-11-05 09:24:53 +000044#define LIB_NAME "mbed TLS"
Juan Castilloa57a4d52015-04-02 15:44:20 +010045
46/*
47 * AlgorithmIdentifier ::= SEQUENCE {
48 * algorithm OBJECT IDENTIFIER,
49 * parameters ANY DEFINED BY algorithm OPTIONAL
50 * }
51 *
52 * SubjectPublicKeyInfo ::= SEQUENCE {
53 * algorithm AlgorithmIdentifier,
54 * subjectPublicKey BIT STRING
55 * }
56 *
57 * DigestInfo ::= SEQUENCE {
58 * digestAlgorithm AlgorithmIdentifier,
59 * digest OCTET STRING
60 * }
61 */
62
63/*
64 * Initialize the library and export the descriptor
65 */
66static void init(void)
67{
Juan Castillobae6b2a2015-11-05 09:24:53 +000068 /* Initialize mbed TLS */
Juan Castilloa57a4d52015-04-02 15:44:20 +010069 mbedtls_init();
70}
71
72/*
73 * Verify a signature.
74 *
75 * Parameters are passed using the DER encoding format following the ASN.1
76 * structures detailed above.
77 */
78static int verify_signature(void *data_ptr, unsigned int data_len,
79 void *sig_ptr, unsigned int sig_len,
80 void *sig_alg, unsigned int sig_alg_len,
81 void *pk_ptr, unsigned int pk_len)
82{
Juan Castillobae6b2a2015-11-05 09:24:53 +000083 mbedtls_asn1_buf sig_oid, sig_params;
84 mbedtls_asn1_buf signature;
85 mbedtls_md_type_t md_alg;
86 mbedtls_pk_type_t pk_alg;
87 mbedtls_pk_context pk;
Juan Castilloa57a4d52015-04-02 15:44:20 +010088 int rc;
89 void *sig_opts = NULL;
Juan Castillobae6b2a2015-11-05 09:24:53 +000090 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +010091 unsigned char *p, *end;
Juan Castillobae6b2a2015-11-05 09:24:53 +000092 unsigned char hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +010093
94 /* Get pointers to signature OID and parameters */
95 p = (unsigned char *)sig_alg;
96 end = (unsigned char *)(p + sig_alg_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +000097 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
Juan Castilloa57a4d52015-04-02 15:44:20 +010098 if (rc != 0) {
99 return CRYPTO_ERR_SIGNATURE;
100 }
101
102 /* Get the actual signature algorithm (MD + PK) */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000103 rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100104 if (rc != 0) {
105 return CRYPTO_ERR_SIGNATURE;
106 }
107
108 /* Parse the public key */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000109 mbedtls_pk_init(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100110 p = (unsigned char *)pk_ptr;
111 end = (unsigned char *)(p + pk_len);
Juan Castillobae6b2a2015-11-05 09:24:53 +0000112 rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100113 if (rc != 0) {
114 return CRYPTO_ERR_SIGNATURE;
115 }
116
117 /* Get the signature (bitstring) */
118 p = (unsigned char *)sig_ptr;
119 end = (unsigned char *)(p + sig_len);
120 signature.tag = *p;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000121 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100122 if (rc != 0) {
123 rc = CRYPTO_ERR_SIGNATURE;
124 goto end;
125 }
126 signature.p = p;
127
128 /* Calculate the hash of the data */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000129 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100130 if (md_info == NULL) {
131 rc = CRYPTO_ERR_SIGNATURE;
132 goto end;
133 }
134 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000135 rc = mbedtls_md(md_info, p, data_len, hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100136 if (rc != 0) {
137 rc = CRYPTO_ERR_SIGNATURE;
138 goto end;
139 }
140
141 /* Verify the signature */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000142 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
143 mbedtls_md_get_size(md_info),
144 signature.p, signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100145 if (rc != 0) {
146 rc = CRYPTO_ERR_SIGNATURE;
147 goto end;
148 }
149
150 /* Signature verification success */
151 rc = CRYPTO_SUCCESS;
152
153end:
Juan Castillobae6b2a2015-11-05 09:24:53 +0000154 mbedtls_pk_free(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100155 return rc;
156}
157
158/*
159 * Match a hash
160 *
161 * Digest info is passed in DER format following the ASN.1 structure detailed
162 * above.
163 */
164static int verify_hash(void *data_ptr, unsigned int data_len,
165 void *digest_info_ptr, unsigned int digest_info_len)
166{
Juan Castillobae6b2a2015-11-05 09:24:53 +0000167 mbedtls_asn1_buf hash_oid, params;
168 mbedtls_md_type_t md_alg;
169 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100170 unsigned char *p, *end, *hash;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000171 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +0100172 size_t len;
173 int rc;
174
Juan Castillobae6b2a2015-11-05 09:24:53 +0000175 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
Juan Castilloa57a4d52015-04-02 15:44:20 +0100176 p = (unsigned char *)digest_info_ptr;
Sandrine Bailleuxdf8de2d2016-01-04 15:49:23 +0000177 end = p + digest_info_len;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000178 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
179 MBEDTLS_ASN1_SEQUENCE);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100180 if (rc != 0) {
181 return CRYPTO_ERR_HASH;
182 }
183
184 /* Get the hash algorithm */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000185 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100186 if (rc != 0) {
187 return CRYPTO_ERR_HASH;
188 }
189
Juan Castillobae6b2a2015-11-05 09:24:53 +0000190 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100191 if (rc != 0) {
192 return CRYPTO_ERR_HASH;
193 }
194
Juan Castillobae6b2a2015-11-05 09:24:53 +0000195 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100196 if (md_info == NULL) {
197 return CRYPTO_ERR_HASH;
198 }
199
200 /* Hash should be octet string type */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000201 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100202 if (rc != 0) {
203 return CRYPTO_ERR_HASH;
204 }
205
206 /* Length of hash must match the algorithm's size */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000207 if (len != mbedtls_md_get_size(md_info)) {
Juan Castilloa57a4d52015-04-02 15:44:20 +0100208 return CRYPTO_ERR_HASH;
209 }
210 hash = p;
211
212 /* Calculate the hash of the data */
213 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000214 rc = mbedtls_md(md_info, p, data_len, data_hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100215 if (rc != 0) {
216 return CRYPTO_ERR_HASH;
217 }
218
219 /* Compare values */
Antonio Nino Diaz6adeeda2017-01-13 13:53:32 +0000220 rc = timingsafe_bcmp(data_hash, hash, mbedtls_md_get_size(md_info));
Juan Castilloa57a4d52015-04-02 15:44:20 +0100221 if (rc != 0) {
222 return CRYPTO_ERR_HASH;
223 }
224
225 return CRYPTO_SUCCESS;
226}
227
228/*
229 * Register crypto library descriptor
230 */
231REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);