xref: /rk3399_ARM-atf/drivers/auth/mbedtls/mbedtls_crypto.c (revision aa856917abecafc371dd7e02405957e9d63007b9)
17d37aa17SJuan Castillo /*
27d37aa17SJuan Castillo  * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved.
37d37aa17SJuan Castillo  *
47d37aa17SJuan Castillo  * Redistribution and use in source and binary forms, with or without
57d37aa17SJuan Castillo  * modification, are permitted provided that the following conditions are met:
67d37aa17SJuan Castillo  *
77d37aa17SJuan Castillo  * Redistributions of source code must retain the above copyright notice, this
87d37aa17SJuan Castillo  * list of conditions and the following disclaimer.
97d37aa17SJuan Castillo  *
107d37aa17SJuan Castillo  * Redistributions in binary form must reproduce the above copyright notice,
117d37aa17SJuan Castillo  * this list of conditions and the following disclaimer in the documentation
127d37aa17SJuan Castillo  * and/or other materials provided with the distribution.
137d37aa17SJuan Castillo  *
147d37aa17SJuan Castillo  * Neither the name of ARM nor the names of its contributors may be used
157d37aa17SJuan Castillo  * to endorse or promote products derived from this software without specific
167d37aa17SJuan Castillo  * prior written permission.
177d37aa17SJuan Castillo  *
187d37aa17SJuan Castillo  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
197d37aa17SJuan Castillo  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
207d37aa17SJuan Castillo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
217d37aa17SJuan Castillo  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
227d37aa17SJuan Castillo  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
237d37aa17SJuan Castillo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
247d37aa17SJuan Castillo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
257d37aa17SJuan Castillo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
267d37aa17SJuan Castillo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
277d37aa17SJuan Castillo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
287d37aa17SJuan Castillo  * POSSIBILITY OF SUCH DAMAGE.
297d37aa17SJuan Castillo  */
307d37aa17SJuan Castillo 
317d37aa17SJuan Castillo 
327d37aa17SJuan Castillo #include <crypto_mod.h>
337d37aa17SJuan Castillo #include <debug.h>
347d37aa17SJuan Castillo #include <mbedtls_common.h>
357d37aa17SJuan Castillo #include <stddef.h>
367d37aa17SJuan Castillo #include <string.h>
377d37aa17SJuan Castillo 
387d37aa17SJuan Castillo /* mbed TLS headers */
39649dbf6fSJuan Castillo #include <mbedtls/md.h>
40649dbf6fSJuan Castillo #include <mbedtls/memory_buffer_alloc.h>
41649dbf6fSJuan Castillo #include <mbedtls/oid.h>
42649dbf6fSJuan Castillo #include <mbedtls/platform.h>
437d37aa17SJuan Castillo 
447d37aa17SJuan Castillo #define LIB_NAME		"mbed TLS"
457d37aa17SJuan Castillo 
467d37aa17SJuan Castillo /*
477d37aa17SJuan Castillo  * AlgorithmIdentifier  ::=  SEQUENCE  {
487d37aa17SJuan Castillo  *     algorithm               OBJECT IDENTIFIER,
497d37aa17SJuan Castillo  *     parameters              ANY DEFINED BY algorithm OPTIONAL
507d37aa17SJuan Castillo  * }
517d37aa17SJuan Castillo  *
527d37aa17SJuan Castillo  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
537d37aa17SJuan Castillo  *     algorithm            AlgorithmIdentifier,
547d37aa17SJuan Castillo  *     subjectPublicKey     BIT STRING
557d37aa17SJuan Castillo  * }
567d37aa17SJuan Castillo  *
577d37aa17SJuan Castillo  * DigestInfo ::= SEQUENCE {
587d37aa17SJuan Castillo  *     digestAlgorithm AlgorithmIdentifier,
597d37aa17SJuan Castillo  *     digest OCTET STRING
607d37aa17SJuan Castillo  * }
617d37aa17SJuan Castillo  */
627d37aa17SJuan Castillo 
637d37aa17SJuan Castillo /*
647d37aa17SJuan Castillo  * Initialize the library and export the descriptor
657d37aa17SJuan Castillo  */
667d37aa17SJuan Castillo static void init(void)
677d37aa17SJuan Castillo {
687d37aa17SJuan Castillo 	/* Initialize mbed TLS */
697d37aa17SJuan Castillo 	mbedtls_init();
707d37aa17SJuan Castillo }
717d37aa17SJuan Castillo 
727d37aa17SJuan Castillo /*
737d37aa17SJuan Castillo  * Verify a signature.
747d37aa17SJuan Castillo  *
757d37aa17SJuan Castillo  * Parameters are passed using the DER encoding format following the ASN.1
767d37aa17SJuan Castillo  * structures detailed above.
777d37aa17SJuan Castillo  */
787d37aa17SJuan Castillo static int verify_signature(void *data_ptr, unsigned int data_len,
797d37aa17SJuan Castillo 			    void *sig_ptr, unsigned int sig_len,
807d37aa17SJuan Castillo 			    void *sig_alg, unsigned int sig_alg_len,
817d37aa17SJuan Castillo 			    void *pk_ptr, unsigned int pk_len)
827d37aa17SJuan Castillo {
83649dbf6fSJuan Castillo 	mbedtls_asn1_buf sig_oid, sig_params;
84649dbf6fSJuan Castillo 	mbedtls_asn1_buf signature;
85649dbf6fSJuan Castillo 	mbedtls_md_type_t md_alg;
86649dbf6fSJuan Castillo 	mbedtls_pk_type_t pk_alg;
87649dbf6fSJuan Castillo 	mbedtls_pk_context pk;
887d37aa17SJuan Castillo 	int rc;
897d37aa17SJuan Castillo 	void *sig_opts = NULL;
90649dbf6fSJuan Castillo 	const mbedtls_md_info_t *md_info;
917d37aa17SJuan Castillo 	unsigned char *p, *end;
92649dbf6fSJuan Castillo 	unsigned char hash[MBEDTLS_MD_MAX_SIZE];
937d37aa17SJuan Castillo 
947d37aa17SJuan Castillo 	/* Get pointers to signature OID and parameters */
957d37aa17SJuan Castillo 	p = (unsigned char *)sig_alg;
967d37aa17SJuan Castillo 	end = (unsigned char *)(p + sig_alg_len);
97649dbf6fSJuan Castillo 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params);
987d37aa17SJuan Castillo 	if (rc != 0) {
997d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
1007d37aa17SJuan Castillo 	}
1017d37aa17SJuan Castillo 
1027d37aa17SJuan Castillo 	/* Get the actual signature algorithm (MD + PK) */
103649dbf6fSJuan Castillo 	rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
1047d37aa17SJuan Castillo 	if (rc != 0) {
1057d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
1067d37aa17SJuan Castillo 	}
1077d37aa17SJuan Castillo 
1087d37aa17SJuan Castillo 	/* Parse the public key */
109649dbf6fSJuan Castillo 	mbedtls_pk_init(&pk);
1107d37aa17SJuan Castillo 	p = (unsigned char *)pk_ptr;
1117d37aa17SJuan Castillo 	end = (unsigned char *)(p + pk_len);
112649dbf6fSJuan Castillo 	rc = mbedtls_pk_parse_subpubkey(&p, end, &pk);
1137d37aa17SJuan Castillo 	if (rc != 0) {
1147d37aa17SJuan Castillo 		return CRYPTO_ERR_SIGNATURE;
1157d37aa17SJuan Castillo 	}
1167d37aa17SJuan Castillo 
1177d37aa17SJuan Castillo 	/* Get the signature (bitstring) */
1187d37aa17SJuan Castillo 	p = (unsigned char *)sig_ptr;
1197d37aa17SJuan Castillo 	end = (unsigned char *)(p + sig_len);
1207d37aa17SJuan Castillo 	signature.tag = *p;
121649dbf6fSJuan Castillo 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len);
1227d37aa17SJuan Castillo 	if (rc != 0) {
1237d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
1247d37aa17SJuan Castillo 		goto end;
1257d37aa17SJuan Castillo 	}
1267d37aa17SJuan Castillo 	signature.p = p;
1277d37aa17SJuan Castillo 
1287d37aa17SJuan Castillo 	/* Calculate the hash of the data */
129649dbf6fSJuan Castillo 	md_info = mbedtls_md_info_from_type(md_alg);
1307d37aa17SJuan Castillo 	if (md_info == NULL) {
1317d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
1327d37aa17SJuan Castillo 		goto end;
1337d37aa17SJuan Castillo 	}
1347d37aa17SJuan Castillo 	p = (unsigned char *)data_ptr;
135649dbf6fSJuan Castillo 	rc = mbedtls_md(md_info, p, data_len, hash);
1367d37aa17SJuan Castillo 	if (rc != 0) {
1377d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
1387d37aa17SJuan Castillo 		goto end;
1397d37aa17SJuan Castillo 	}
1407d37aa17SJuan Castillo 
1417d37aa17SJuan Castillo 	/* Verify the signature */
142649dbf6fSJuan Castillo 	rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash,
143649dbf6fSJuan Castillo 			mbedtls_md_get_size(md_info),
144649dbf6fSJuan Castillo 			signature.p, signature.len);
1457d37aa17SJuan Castillo 	if (rc != 0) {
1467d37aa17SJuan Castillo 		rc = CRYPTO_ERR_SIGNATURE;
1477d37aa17SJuan Castillo 		goto end;
1487d37aa17SJuan Castillo 	}
1497d37aa17SJuan Castillo 
1507d37aa17SJuan Castillo 	/* Signature verification success */
1517d37aa17SJuan Castillo 	rc = CRYPTO_SUCCESS;
1527d37aa17SJuan Castillo 
1537d37aa17SJuan Castillo end:
154649dbf6fSJuan Castillo 	mbedtls_pk_free(&pk);
1557d37aa17SJuan Castillo 	return rc;
1567d37aa17SJuan Castillo }
1577d37aa17SJuan Castillo 
1587d37aa17SJuan Castillo /*
1597d37aa17SJuan Castillo  * Match a hash
1607d37aa17SJuan Castillo  *
1617d37aa17SJuan Castillo  * Digest info is passed in DER format following the ASN.1 structure detailed
1627d37aa17SJuan Castillo  * above.
1637d37aa17SJuan Castillo  */
1647d37aa17SJuan Castillo static int verify_hash(void *data_ptr, unsigned int data_len,
1657d37aa17SJuan Castillo 		       void *digest_info_ptr, unsigned int digest_info_len)
1667d37aa17SJuan Castillo {
167649dbf6fSJuan Castillo 	mbedtls_asn1_buf hash_oid, params;
168649dbf6fSJuan Castillo 	mbedtls_md_type_t md_alg;
169649dbf6fSJuan Castillo 	const mbedtls_md_info_t *md_info;
1707d37aa17SJuan Castillo 	unsigned char *p, *end, *hash;
171649dbf6fSJuan Castillo 	unsigned char data_hash[MBEDTLS_MD_MAX_SIZE];
1727d37aa17SJuan Castillo 	size_t len;
1737d37aa17SJuan Castillo 	int rc;
1747d37aa17SJuan Castillo 
175649dbf6fSJuan Castillo 	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
1767d37aa17SJuan Castillo 	p = (unsigned char *)digest_info_ptr;
177*aa856917SSandrine Bailleux 	end = p + digest_info_len;
178649dbf6fSJuan Castillo 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
179649dbf6fSJuan Castillo 				  MBEDTLS_ASN1_SEQUENCE);
1807d37aa17SJuan Castillo 	if (rc != 0) {
1817d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
1827d37aa17SJuan Castillo 	}
1837d37aa17SJuan Castillo 
1847d37aa17SJuan Castillo 	/* Get the hash algorithm */
185649dbf6fSJuan Castillo 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
1867d37aa17SJuan Castillo 	if (rc != 0) {
1877d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
1887d37aa17SJuan Castillo 	}
1897d37aa17SJuan Castillo 
190649dbf6fSJuan Castillo 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
1917d37aa17SJuan Castillo 	if (rc != 0) {
1927d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
1937d37aa17SJuan Castillo 	}
1947d37aa17SJuan Castillo 
195649dbf6fSJuan Castillo 	md_info = mbedtls_md_info_from_type(md_alg);
1967d37aa17SJuan Castillo 	if (md_info == NULL) {
1977d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
1987d37aa17SJuan Castillo 	}
1997d37aa17SJuan Castillo 
2007d37aa17SJuan Castillo 	/* Hash should be octet string type */
201649dbf6fSJuan Castillo 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
2027d37aa17SJuan Castillo 	if (rc != 0) {
2037d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
2047d37aa17SJuan Castillo 	}
2057d37aa17SJuan Castillo 
2067d37aa17SJuan Castillo 	/* Length of hash must match the algorithm's size */
207649dbf6fSJuan Castillo 	if (len != mbedtls_md_get_size(md_info)) {
2087d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
2097d37aa17SJuan Castillo 	}
2107d37aa17SJuan Castillo 	hash = p;
2117d37aa17SJuan Castillo 
2127d37aa17SJuan Castillo 	/* Calculate the hash of the data */
2137d37aa17SJuan Castillo 	p = (unsigned char *)data_ptr;
214649dbf6fSJuan Castillo 	rc = mbedtls_md(md_info, p, data_len, data_hash);
2157d37aa17SJuan Castillo 	if (rc != 0) {
2167d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
2177d37aa17SJuan Castillo 	}
2187d37aa17SJuan Castillo 
2197d37aa17SJuan Castillo 	/* Compare values */
220649dbf6fSJuan Castillo 	rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info));
2217d37aa17SJuan Castillo 	if (rc != 0) {
2227d37aa17SJuan Castillo 		return CRYPTO_ERR_HASH;
2237d37aa17SJuan Castillo 	}
2247d37aa17SJuan Castillo 
2257d37aa17SJuan Castillo 	return CRYPTO_SUCCESS;
2267d37aa17SJuan Castillo }
2277d37aa17SJuan Castillo 
2287d37aa17SJuan Castillo /*
2297d37aa17SJuan Castillo  * Register crypto library descriptor
2307d37aa17SJuan Castillo  */
2317d37aa17SJuan Castillo REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
232