xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_crypto.c (revision 7d37aa171158422b5ee7ee6c3cdad58f6aa066b4)
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 /* mbedTLS headers */
39 #include <polarssl/md_wrap.h>
40 #include <polarssl/memory_buffer_alloc.h>
41 #include <polarssl/oid.h>
42 #include <polarssl/platform.h>
43 
44 #define LIB_NAME		"mbedTLS"
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 mbedTLS */
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 	asn1_buf sig_oid, sig_params;
84 	asn1_buf signature;
85 	md_type_t md_alg;
86 	pk_type_t pk_alg;
87 	pk_context pk;
88 	int rc;
89 	void *sig_opts = NULL;
90 	const md_info_t *md_info;
91 	unsigned char *p, *end;
92 	unsigned char hash[POLARSSL_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 = 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 = 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 	pk_init(&pk);
110 	p = (unsigned char *)pk_ptr;
111 	end = (unsigned char *)(p + pk_len);
112 	rc = 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 = 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 = 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 = 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 = pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
143 			md_info->size, signature.p, signature.len);
144 	if (rc != 0) {
145 		rc = CRYPTO_ERR_SIGNATURE;
146 		goto end;
147 	}
148 
149 	/* Signature verification success */
150 	rc = CRYPTO_SUCCESS;
151 
152 end:
153 	pk_free(&pk);
154 	return rc;
155 }
156 
157 /*
158  * Match a hash
159  *
160  * Digest info is passed in DER format following the ASN.1 structure detailed
161  * above.
162  */
163 static int verify_hash(void *data_ptr, unsigned int data_len,
164 		       void *digest_info_ptr, unsigned int digest_info_len)
165 {
166 	asn1_buf hash_oid, params;
167 	md_type_t md_alg;
168 	const md_info_t *md_info;
169 	unsigned char *p, *end, *hash;
170 	unsigned char data_hash[POLARSSL_MD_MAX_SIZE];
171 	size_t len;
172 	int rc;
173 
174 	/* Digest info should be an ASN1_SEQUENCE */
175 	p = (unsigned char *)digest_info_ptr;
176 	end = (unsigned char *)(digest_info_ptr + digest_info_len);
177 	rc = asn1_get_tag(&p, end, &len, ASN1_CONSTRUCTED | ASN1_SEQUENCE);
178 	if (rc != 0) {
179 		return CRYPTO_ERR_HASH;
180 	}
181 
182 	/* Get the hash algorithm */
183 	rc = asn1_get_alg(&p, end, &hash_oid, &params);
184 	if (rc != 0) {
185 		return CRYPTO_ERR_HASH;
186 	}
187 
188 	rc = oid_get_md_alg(&hash_oid, &md_alg);
189 	if (rc != 0) {
190 		return CRYPTO_ERR_HASH;
191 	}
192 
193 	md_info = md_info_from_type(md_alg);
194 	if (md_info == NULL) {
195 		return CRYPTO_ERR_HASH;
196 	}
197 
198 	/* Hash should be octet string type */
199 	rc = asn1_get_tag(&p, end, &len, ASN1_OCTET_STRING);
200 	if (rc != 0) {
201 		return CRYPTO_ERR_HASH;
202 	}
203 
204 	/* Length of hash must match the algorithm's size */
205 	if (len != md_info->size) {
206 		return CRYPTO_ERR_HASH;
207 	}
208 	hash = p;
209 
210 	/* Calculate the hash of the data */
211 	p = (unsigned char *)data_ptr;
212 	rc = md(md_info, p, data_len, data_hash);
213 	if (rc != 0) {
214 		return CRYPTO_ERR_HASH;
215 	}
216 
217 	/* Compare values */
218 	rc = memcmp(data_hash, hash, md_info->size);
219 	if (rc != 0) {
220 		return CRYPTO_ERR_HASH;
221 	}
222 
223 	return CRYPTO_SUCCESS;
224 }
225 
226 /*
227  * Register crypto library descriptor
228  */
229 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
230