xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_crypto.c (revision 93f398205a8ebd2c1cef780251a0d24576ab1b28)
1 /*
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 
38 /* 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>
43 
44 #define LIB_NAME		"mbed TLS"
45 
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  */
66 static void init(void)
67 {
68 	/* Initialize mbed TLS */
69 	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  */
78 static 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 {
83 	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;
88 	int rc;
89 	void *sig_opts = NULL;
90 	const mbedtls_md_info_t *md_info;
91 	unsigned char *p, *end;
92 	unsigned char hash[MBEDTLS_MD_MAX_SIZE];
93 
94 	/* Get pointers to signature OID and parameters */
95 	p = (unsigned char *)sig_alg;
96 	end = (unsigned char *)(p + sig_alg_len);
97 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
98 	if (rc != 0) {
99 		return CRYPTO_ERR_SIGNATURE;
100 	}
101 
102 	/* Get the actual signature algorithm (MD + PK) */
103 	rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
104 	if (rc != 0) {
105 		return CRYPTO_ERR_SIGNATURE;
106 	}
107 
108 	/* Parse the public key */
109 	mbedtls_pk_init(&pk);
110 	p = (unsigned char *)pk_ptr;
111 	end = (unsigned char *)(p + pk_len);
112 	rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
113 	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;
121 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
122 	if (rc != 0) {
123 		rc = CRYPTO_ERR_SIGNATURE;
124 		goto end;
125 	}
126 	signature.p = p;
127 
128 	/* Calculate the hash of the data */
129 	md_info = mbedtls_md_info_from_type(md_alg);
130 	if (md_info == NULL) {
131 		rc = CRYPTO_ERR_SIGNATURE;
132 		goto end;
133 	}
134 	p = (unsigned char *)data_ptr;
135 	rc = mbedtls_md(md_info, p, data_len, hash);
136 	if (rc != 0) {
137 		rc = CRYPTO_ERR_SIGNATURE;
138 		goto end;
139 	}
140 
141 	/* Verify the signature */
142 	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);
145 	if (rc != 0) {
146 		rc = CRYPTO_ERR_SIGNATURE;
147 		goto end;
148 	}
149 
150 	/* Signature verification success */
151 	rc = CRYPTO_SUCCESS;
152 
153 end:
154 	mbedtls_pk_free(&pk);
155 	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  */
164 static int verify_hash(void *data_ptr, unsigned int data_len,
165 		       void *digest_info_ptr, unsigned int digest_info_len)
166 {
167 	mbedtls_asn1_buf hash_oid, params;
168 	mbedtls_md_type_t md_alg;
169 	const mbedtls_md_info_t *md_info;
170 	unsigned char *p, *end, *hash;
171 	unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
172 	size_t len;
173 	int rc;
174 
175 	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
176 	p = (unsigned char *)digest_info_ptr;
177 	end = p + digest_info_len;
178 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
179 				  MBEDTLS_ASN1_SEQUENCE);
180 	if (rc != 0) {
181 		return CRYPTO_ERR_HASH;
182 	}
183 
184 	/* Get the hash algorithm */
185 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
186 	if (rc != 0) {
187 		return CRYPTO_ERR_HASH;
188 	}
189 
190 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
191 	if (rc != 0) {
192 		return CRYPTO_ERR_HASH;
193 	}
194 
195 	md_info = mbedtls_md_info_from_type(md_alg);
196 	if (md_info == NULL) {
197 		return CRYPTO_ERR_HASH;
198 	}
199 
200 	/* Hash should be octet string type */
201 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
202 	if (rc != 0) {
203 		return CRYPTO_ERR_HASH;
204 	}
205 
206 	/* Length of hash must match the algorithm's size */
207 	if (len != mbedtls_md_get_size(md_info)) {
208 		return CRYPTO_ERR_HASH;
209 	}
210 	hash = p;
211 
212 	/* Calculate the hash of the data */
213 	p = (unsigned char *)data_ptr;
214 	rc = mbedtls_md(md_info, p, data_len, data_hash);
215 	if (rc != 0) {
216 		return CRYPTO_ERR_HASH;
217 	}
218 
219 	/* Compare values */
220 	rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
221 	if (rc != 0) {
222 		return CRYPTO_ERR_HASH;
223 	}
224 
225 	return CRYPTO_SUCCESS;
226 }
227 
228 /*
229  * Register crypto library descriptor
230  */
231 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
232