blob: 2c1514870a678e5bf600c74364c5ec9001d29ad5 [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;
63 mbedtls_pk_context pk;
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) */
Juan Castillobae6b2a2015-11-05 09:24:53 +000079 rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
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) {
90 return CRYPTO_ERR_SIGNATURE;
91 }
92
93 /* Get the signature (bitstring) */
94 p = (unsigned char *)sig_ptr;
95 end = (unsigned char *)(p + sig_len);
96 signature.tag = *p;
Juan Castillobae6b2a2015-11-05 09:24:53 +000097 rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +010098 if (rc != 0) {
99 rc = CRYPTO_ERR_SIGNATURE;
100 goto end;
101 }
102 signature.p = p;
103
104 /* Calculate the hash of the data */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000105 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100106 if (md_info == NULL) {
107 rc = CRYPTO_ERR_SIGNATURE;
108 goto end;
109 }
110 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000111 rc = mbedtls_md(md_info, p, data_len, hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100112 if (rc != 0) {
113 rc = CRYPTO_ERR_SIGNATURE;
114 goto end;
115 }
116
117 /* Verify the signature */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000118 rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
119 mbedtls_md_get_size(md_info),
120 signature.p, signature.len);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100121 if (rc != 0) {
122 rc = CRYPTO_ERR_SIGNATURE;
123 goto end;
124 }
125
126 /* Signature verification success */
127 rc = CRYPTO_SUCCESS;
128
129end:
Juan Castillobae6b2a2015-11-05 09:24:53 +0000130 mbedtls_pk_free(&pk);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100131 return rc;
132}
133
134/*
135 * Match a hash
136 *
137 * Digest info is passed in DER format following the ASN.1 structure detailed
138 * above.
139 */
140static int verify_hash(void *data_ptr, unsigned int data_len,
141 void *digest_info_ptr, unsigned int digest_info_len)
142{
Juan Castillobae6b2a2015-11-05 09:24:53 +0000143 mbedtls_asn1_buf hash_oid, params;
144 mbedtls_md_type_t md_alg;
145 const mbedtls_md_info_t *md_info;
Juan Castilloa57a4d52015-04-02 15:44:20 +0100146 unsigned char *p, *end, *hash;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000147 unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
Juan Castilloa57a4d52015-04-02 15:44:20 +0100148 size_t len;
149 int rc;
150
Juan Castillobae6b2a2015-11-05 09:24:53 +0000151 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
Juan Castilloa57a4d52015-04-02 15:44:20 +0100152 p = (unsigned char *)digest_info_ptr;
Sandrine Bailleuxdf8de2d2016-01-04 15:49:23 +0000153 end = p + digest_info_len;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000154 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
155 MBEDTLS_ASN1_SEQUENCE);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100156 if (rc != 0) {
157 return CRYPTO_ERR_HASH;
158 }
159
160 /* Get the hash algorithm */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000161 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100162 if (rc != 0) {
163 return CRYPTO_ERR_HASH;
164 }
165
Juan Castillobae6b2a2015-11-05 09:24:53 +0000166 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
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 md_info = mbedtls_md_info_from_type(md_alg);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100172 if (md_info == NULL) {
173 return CRYPTO_ERR_HASH;
174 }
175
176 /* Hash should be octet string type */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000177 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100178 if (rc != 0) {
179 return CRYPTO_ERR_HASH;
180 }
181
182 /* Length of hash must match the algorithm's size */
Juan Castillobae6b2a2015-11-05 09:24:53 +0000183 if (len != mbedtls_md_get_size(md_info)) {
Juan Castilloa57a4d52015-04-02 15:44:20 +0100184 return CRYPTO_ERR_HASH;
185 }
186 hash = p;
187
188 /* Calculate the hash of the data */
189 p = (unsigned char *)data_ptr;
Juan Castillobae6b2a2015-11-05 09:24:53 +0000190 rc = mbedtls_md(md_info, p, data_len, data_hash);
Juan Castilloa57a4d52015-04-02 15:44:20 +0100191 if (rc != 0) {
192 return CRYPTO_ERR_HASH;
193 }
194
195 /* Compare values */
Antonio Nino Diaz0ca1afa2017-02-09 10:26:54 +0000196 rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
Juan Castilloa57a4d52015-04-02 15:44:20 +0100197 if (rc != 0) {
198 return CRYPTO_ERR_HASH;
199 }
200
201 return CRYPTO_SUCCESS;
202}
203
204/*
205 * Register crypto library descriptor
206 */
207REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);