xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_crypto.c (revision 7d37aa171158422b5ee7ee6c3cdad58f6aa066b4)
1*7d37aa17SJuan Castillo /*
2*7d37aa17SJuan Castillo  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
3*7d37aa17SJuan Castillo  *
4*7d37aa17SJuan Castillo  * Redistribution and use in source and binary forms, with or without
5*7d37aa17SJuan Castillo  * modification, are permitted provided that the following conditions are met:
6*7d37aa17SJuan Castillo  *
7*7d37aa17SJuan Castillo  * Redistributions of source code must retain the above copyright notice, this
8*7d37aa17SJuan Castillo  * list of conditions and the following disclaimer.
9*7d37aa17SJuan Castillo  *
10*7d37aa17SJuan Castillo  * Redistributions in binary form must reproduce the above copyright notice,
11*7d37aa17SJuan Castillo  * this list of conditions and the following disclaimer in the documentation
12*7d37aa17SJuan Castillo  * and/or other materials provided with the distribution.
13*7d37aa17SJuan Castillo  *
14*7d37aa17SJuan Castillo  * Neither the name of ARM nor the names of its contributors may be used
15*7d37aa17SJuan Castillo  * to endorse or promote products derived from this software without specific
16*7d37aa17SJuan Castillo  * prior written permission.
17*7d37aa17SJuan Castillo  *
18*7d37aa17SJuan Castillo  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19*7d37aa17SJuan Castillo  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20*7d37aa17SJuan Castillo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*7d37aa17SJuan Castillo  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22*7d37aa17SJuan Castillo  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23*7d37aa17SJuan Castillo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24*7d37aa17SJuan Castillo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25*7d37aa17SJuan Castillo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26*7d37aa17SJuan Castillo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27*7d37aa17SJuan Castillo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28*7d37aa17SJuan Castillo  * POSSIBILITY OF SUCH DAMAGE.
29*7d37aa17SJuan Castillo  */
30*7d37aa17SJuan Castillo 
31*7d37aa17SJuan Castillo 
32*7d37aa17SJuan Castillo #include <crypto_mod.h>
33*7d37aa17SJuan Castillo #include <debug.h>
34*7d37aa17SJuan Castillo #include <mbedtls_common.h>
35*7d37aa17SJuan Castillo #include <stddef.h>
36*7d37aa17SJuan Castillo #include <string.h>
37*7d37aa17SJuan Castillo 
38*7d37aa17SJuan Castillo /* mbedTLS headers */
39*7d37aa17SJuan Castillo #include <polarssl/md_wrap.h>
40*7d37aa17SJuan Castillo #include <polarssl/memory_buffer_alloc.h>
41*7d37aa17SJuan Castillo #include <polarssl/oid.h>
42*7d37aa17SJuan Castillo #include <polarssl/platform.h>
43*7d37aa17SJuan Castillo 
44*7d37aa17SJuan Castillo #define LIB_NAME		"mbedTLS"
45*7d37aa17SJuan Castillo 
46*7d37aa17SJuan Castillo /*
47*7d37aa17SJuan Castillo  * AlgorithmIdentifier  ::=  SEQUENCE  {
48*7d37aa17SJuan Castillo  *     algorithm               OBJECT IDENTIFIER,
49*7d37aa17SJuan Castillo  *     parameters              ANY DEFINED BY algorithm OPTIONAL
50*7d37aa17SJuan Castillo  * }
51*7d37aa17SJuan Castillo  *
52*7d37aa17SJuan Castillo  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
53*7d37aa17SJuan Castillo  *     algorithm            AlgorithmIdentifier,
54*7d37aa17SJuan Castillo  *     subjectPublicKey     BIT STRING
55*7d37aa17SJuan Castillo  * }
56*7d37aa17SJuan Castillo  *
57*7d37aa17SJuan Castillo  * DigestInfo ::= SEQUENCE {
58*7d37aa17SJuan Castillo  *     digestAlgorithm AlgorithmIdentifier,
59*7d37aa17SJuan Castillo  *     digest OCTET STRING
60*7d37aa17SJuan Castillo  * }
61*7d37aa17SJuan Castillo  */
62*7d37aa17SJuan Castillo 
63*7d37aa17SJuan Castillo /*
64*7d37aa17SJuan Castillo  * Initialize the library and export the descriptor
65*7d37aa17SJuan Castillo  */
66*7d37aa17SJuan Castillo static void init(void)
67*7d37aa17SJuan Castillo {
68*7d37aa17SJuan Castillo 	/* Initialize mbedTLS */
69*7d37aa17SJuan Castillo 	mbedtls_init();
70*7d37aa17SJuan Castillo }
71*7d37aa17SJuan Castillo 
72*7d37aa17SJuan Castillo /*
73*7d37aa17SJuan Castillo  * Verify a signature.
74*7d37aa17SJuan Castillo  *
75*7d37aa17SJuan Castillo  * Parameters are passed using the DER encoding format following the ASN.1
76*7d37aa17SJuan Castillo  * structures detailed above.
77*7d37aa17SJuan Castillo  */
78*7d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len,
79*7d37aa17SJuan Castillo 			    void *sig_ptr, unsigned int sig_len,
80*7d37aa17SJuan Castillo 			    void *sig_alg, unsigned int sig_alg_len,
81*7d37aa17SJuan Castillo 			    void *pk_ptr, unsigned int pk_len)
82*7d37aa17SJuan Castillo {
83*7d37aa17SJuan Castillo 	asn1_buf sig_oid, sig_params;
84*7d37aa17SJuan Castillo 	asn1_buf signature;
85*7d37aa17SJuan Castillo 	md_type_t md_alg;
86*7d37aa17SJuan Castillo 	pk_type_t pk_alg;
87*7d37aa17SJuan Castillo 	pk_context pk;
88*7d37aa17SJuan Castillo 	int rc;
89*7d37aa17SJuan Castillo 	void *sig_opts = NULL;
90*7d37aa17SJuan Castillo 	const md_info_t *md_info;
91*7d37aa17SJuan Castillo 	unsigned char *p, *end;
92*7d37aa17SJuan Castillo 	unsigned char hash[POLARSSL_MD_MAX_SIZE];
93*7d37aa17SJuan Castillo 
94*7d37aa17SJuan Castillo 	/* Get pointers to signature OID and parameters */
95*7d37aa17SJuan Castillo 	p = (unsigned char *)sig_alg;
96*7d37aa17SJuan Castillo 	end = (unsigned char *)(p + sig_alg_len);
97*7d37aa17SJuan Castillo 	rc = asn1_get_alg(&p, end, &sig_oid, &sig_params);
98*7d37aa17SJuan Castillo 	if (rc != 0) {
99*7d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
100*7d37aa17SJuan Castillo 	}
101*7d37aa17SJuan Castillo 
102*7d37aa17SJuan Castillo 	/* Get the actual signature algorithm (MD + PK) */
103*7d37aa17SJuan Castillo 	rc = oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
104*7d37aa17SJuan Castillo 	if (rc != 0) {
105*7d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
106*7d37aa17SJuan Castillo 	}
107*7d37aa17SJuan Castillo 
108*7d37aa17SJuan Castillo 	/* Parse the public key */
109*7d37aa17SJuan Castillo 	pk_init(&pk);
110*7d37aa17SJuan Castillo 	p = (unsigned char *)pk_ptr;
111*7d37aa17SJuan Castillo 	end = (unsigned char *)(p + pk_len);
112*7d37aa17SJuan Castillo 	rc = pk_parse_subpubkey(&p, end, &pk);
113*7d37aa17SJuan Castillo 	if (rc != 0) {
114*7d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
115*7d37aa17SJuan Castillo 	}
116*7d37aa17SJuan Castillo 
117*7d37aa17SJuan Castillo 	/* Get the signature (bitstring) */
118*7d37aa17SJuan Castillo 	p = (unsigned char *)sig_ptr;
119*7d37aa17SJuan Castillo 	end = (unsigned char *)(p + sig_len);
120*7d37aa17SJuan Castillo 	signature.tag = *p;
121*7d37aa17SJuan Castillo 	rc = asn1_get_bitstring_null(&p, end, &signature.len);
122*7d37aa17SJuan Castillo 	if (rc != 0) {
123*7d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
124*7d37aa17SJuan Castillo 		goto end;
125*7d37aa17SJuan Castillo 	}
126*7d37aa17SJuan Castillo 	signature.p = p;
127*7d37aa17SJuan Castillo 
128*7d37aa17SJuan Castillo 	/* Calculate the hash of the data */
129*7d37aa17SJuan Castillo 	md_info = md_info_from_type(md_alg);
130*7d37aa17SJuan Castillo 	if (md_info == NULL) {
131*7d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
132*7d37aa17SJuan Castillo 		goto end;
133*7d37aa17SJuan Castillo 	}
134*7d37aa17SJuan Castillo 	p = (unsigned char *)data_ptr;
135*7d37aa17SJuan Castillo 	rc = md(md_info, p, data_len, hash);
136*7d37aa17SJuan Castillo 	if (rc != 0) {
137*7d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
138*7d37aa17SJuan Castillo 		goto end;
139*7d37aa17SJuan Castillo 	}
140*7d37aa17SJuan Castillo 
141*7d37aa17SJuan Castillo 	/* Verify the signature */
142*7d37aa17SJuan Castillo 	rc = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
143*7d37aa17SJuan Castillo 			md_info->size, signature.p, signature.len);
144*7d37aa17SJuan Castillo 	if (rc != 0) {
145*7d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
146*7d37aa17SJuan Castillo 		goto end;
147*7d37aa17SJuan Castillo 	}
148*7d37aa17SJuan Castillo 
149*7d37aa17SJuan Castillo 	/* Signature verification success */
150*7d37aa17SJuan Castillo 	rc = CRYPTO_SUCCESS;
151*7d37aa17SJuan Castillo 
152*7d37aa17SJuan Castillo end:
153*7d37aa17SJuan Castillo 	pk_free(&pk);
154*7d37aa17SJuan Castillo 	return rc;
155*7d37aa17SJuan Castillo }
156*7d37aa17SJuan Castillo 
157*7d37aa17SJuan Castillo /*
158*7d37aa17SJuan Castillo  * Match a hash
159*7d37aa17SJuan Castillo  *
160*7d37aa17SJuan Castillo  * Digest info is passed in DER format following the ASN.1 structure detailed
161*7d37aa17SJuan Castillo  * above.
162*7d37aa17SJuan Castillo  */
163*7d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len,
164*7d37aa17SJuan Castillo 		       void *digest_info_ptr, unsigned int digest_info_len)
165*7d37aa17SJuan Castillo {
166*7d37aa17SJuan Castillo 	asn1_buf hash_oid, params;
167*7d37aa17SJuan Castillo 	md_type_t md_alg;
168*7d37aa17SJuan Castillo 	const md_info_t *md_info;
169*7d37aa17SJuan Castillo 	unsigned char *p, *end, *hash;
170*7d37aa17SJuan Castillo 	unsigned char data_hash[POLARSSL_MD_MAX_SIZE];
171*7d37aa17SJuan Castillo 	size_t len;
172*7d37aa17SJuan Castillo 	int rc;
173*7d37aa17SJuan Castillo 
174*7d37aa17SJuan Castillo 	/* Digest info should be an ASN1_SEQUENCE */
175*7d37aa17SJuan Castillo 	p = (unsigned char *)digest_info_ptr;
176*7d37aa17SJuan Castillo 	end = (unsigned char *)(digest_info_ptr + digest_info_len);
177*7d37aa17SJuan Castillo 	rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
178*7d37aa17SJuan Castillo 	if (rc != 0) {
179*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
180*7d37aa17SJuan Castillo 	}
181*7d37aa17SJuan Castillo 
182*7d37aa17SJuan Castillo 	/* Get the hash algorithm */
183*7d37aa17SJuan Castillo 	rc = asn1_get_alg(&p, end, &hash_oid, &params);
184*7d37aa17SJuan Castillo 	if (rc != 0) {
185*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
186*7d37aa17SJuan Castillo 	}
187*7d37aa17SJuan Castillo 
188*7d37aa17SJuan Castillo 	rc = oid_get_md_alg(&hash_oid, &md_alg);
189*7d37aa17SJuan Castillo 	if (rc != 0) {
190*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
191*7d37aa17SJuan Castillo 	}
192*7d37aa17SJuan Castillo 
193*7d37aa17SJuan Castillo 	md_info = md_info_from_type(md_alg);
194*7d37aa17SJuan Castillo 	if (md_info == NULL) {
195*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
196*7d37aa17SJuan Castillo 	}
197*7d37aa17SJuan Castillo 
198*7d37aa17SJuan Castillo 	/* Hash should be octet string type */
199*7d37aa17SJuan Castillo 	rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
200*7d37aa17SJuan Castillo 	if (rc != 0) {
201*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
202*7d37aa17SJuan Castillo 	}
203*7d37aa17SJuan Castillo 
204*7d37aa17SJuan Castillo 	/* Length of hash must match the algorithm's size */
205*7d37aa17SJuan Castillo 	if (len != md_info->size) {
206*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
207*7d37aa17SJuan Castillo 	}
208*7d37aa17SJuan Castillo 	hash = p;
209*7d37aa17SJuan Castillo 
210*7d37aa17SJuan Castillo 	/* Calculate the hash of the data */
211*7d37aa17SJuan Castillo 	p = (unsigned char *)data_ptr;
212*7d37aa17SJuan Castillo 	rc = md(md_info, p, data_len, data_hash);
213*7d37aa17SJuan Castillo 	if (rc != 0) {
214*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
215*7d37aa17SJuan Castillo 	}
216*7d37aa17SJuan Castillo 
217*7d37aa17SJuan Castillo 	/* Compare values */
218*7d37aa17SJuan Castillo 	rc = memcmp(data_hash, hash, md_info->size);
219*7d37aa17SJuan Castillo 	if (rc != 0) {
220*7d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
221*7d37aa17SJuan Castillo 	}
222*7d37aa17SJuan Castillo 
223*7d37aa17SJuan Castillo 	return CRYPTO_SUCCESS;
224*7d37aa17SJuan Castillo }
225*7d37aa17SJuan Castillo 
226*7d37aa17SJuan Castillo /*
227*7d37aa17SJuan Castillo  * Register crypto library descriptor
228*7d37aa17SJuan Castillo  */
229*7d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
230