1 /*
2  * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #include <assert.h>
8 #include <stddef.h>
9 #include <string.h>
10 
11 #include <drivers/arm/cryptocell/713/bsv_api.h>
12 #include <drivers/arm/cryptocell/713/bsv_crypto_asym_api.h>
13 #include <drivers/auth/crypto_mod.h>
14 
15 #include <mbedtls/oid.h>
16 
17 #define LIB_NAME		"CryptoCell 713 SBROM"
18 #define RSA_SALT_LEN		32
19 #define RSA_EXPONENT		65537
20 
21 /*
22  * AlgorithmIdentifier  ::=  SEQUENCE  {
23  *     algorithm            OBJECT IDENTIFIER,
24  *     parameters           ANY DEFINED BY algorithm OPTIONAL
25  * }
26  *
27  * SubjectPublicKeyInfo  ::=  SEQUENCE  {
28  *     algorithm            AlgorithmIdentifier,
29  *     subjectPublicKey     BIT STRING
30  * }
31  *
32  * DigestInfo ::= SEQUENCE {
33  *     digestAlgorithm      AlgorithmIdentifier,
34  *     digest               OCTET STRING
35  * }
36  *
37  *  RSASSA-PSS-params ::= SEQUENCE {
38  *     hashAlgorithm        [0] HashAlgorithm,
39  *     maskGenAlgorithm     [1] MaskGenAlgorithm,
40  *     saltLength           [2] INTEGER,
41  *     trailerField         [3] TrailerField    DEFAULT trailerFieldBC
42  * }
43  */
44 
45 /*
46  * Initialize the library and export the descriptor
47  */
init(void)48 static void init(void)
49 {
50 	CCError_t ret;
51 	uint32_t lcs;
52 
53 	/* Initialize CC SBROM */
54 	ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE);
55 	if (ret != CC_OK) {
56 		ERROR("CryptoCell CC_BsvInit() error %x\n", ret);
57 		panic();
58 	}
59 
60 	/* Initialize lifecycle state */
61 	ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs);
62 	if (ret != CC_OK) {
63 		ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret);
64 		panic();
65 	}
66 }
67 
68 /*
69  * Verify a signature.
70  *
71  * Parameters are passed using the DER encoding format following the ASN.1
72  * structures detailed above.
73  */
verify_signature(void * data_ptr,unsigned int data_len,void * sig_ptr,unsigned int sig_len,void * sig_alg,unsigned int sig_alg_len,void * pk_ptr,unsigned int pk_len)74 static int verify_signature(void *data_ptr, unsigned int data_len,
75 			    void *sig_ptr, unsigned int sig_len,
76 			    void *sig_alg, unsigned int sig_alg_len,
77 			    void *pk_ptr, unsigned int pk_len)
78 {
79 	CCError_t error;
80 	CCBsvNBuff_t NBuff;
81 	CCBsvSignature_t signature;
82 	int rc, exp;
83 	mbedtls_asn1_buf sig_oid, alg_oid, params;
84 	mbedtls_md_type_t md_alg;
85 	mbedtls_pk_type_t pk_alg;
86 	mbedtls_pk_rsassa_pss_options pss_opts;
87 	size_t len;
88 	uint8_t *p, *end;
89 	CCHashResult_t digest;
90 	CCBool_t is_verified;
91 	/* This is a rather large array, we don't want it on stack */
92 	static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE];
93 
94 	/* Verify the signature algorithm */
95 	/* Get pointers to signature OID and parameters */
96 	p = sig_alg;
97 	end = p + sig_alg_len;
98 	rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &params);
99 	if (rc != 0)
100 		return CRYPTO_ERR_SIGNATURE;
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 	/* The CryptoCell only supports RSASSA-PSS signature */
108 	if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE)
109 		return CRYPTO_ERR_SIGNATURE;
110 
111 	/* Verify the RSASSA-PSS params */
112 	/* The trailer field is verified to be 0xBC internally by this API */
113 	rc = mbedtls_x509_get_rsassa_pss_params(&params, &md_alg,
114 			&pss_opts.mgf1_hash_id,
115 			&pss_opts.expected_salt_len);
116 	if (rc != 0)
117 		return CRYPTO_ERR_SIGNATURE;
118 
119 	/* The CryptoCell only supports SHA256 as hash algorithm */
120 	if (md_alg != MBEDTLS_MD_SHA256 ||
121 	    pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256)
122 		return CRYPTO_ERR_SIGNATURE;
123 
124 	if (pss_opts.expected_salt_len != RSA_SALT_LEN)
125 		return CRYPTO_ERR_SIGNATURE;
126 
127 	/* Parse the public key */
128 	p = pk_ptr;
129 	end = p + pk_len;
130 	rc = mbedtls_asn1_get_tag(&p, end, &len,
131 			MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
132 	if (rc != 0)
133 		return CRYPTO_ERR_SIGNATURE;
134 
135 	end = p + len;
136 	rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid);
137 	if (rc != 0)
138 		return CRYPTO_ERR_SIGNATURE;
139 
140 	if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0)
141 		return CRYPTO_ERR_SIGNATURE;
142 
143 	if (pk_alg != MBEDTLS_PK_RSA)
144 		return CRYPTO_ERR_SIGNATURE;
145 
146 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
147 	if (rc != 0)
148 		return CRYPTO_ERR_SIGNATURE;
149 
150 	rc = mbedtls_asn1_get_tag(&p, end, &len,
151 				MBEDTLS_ASN1_CONSTRUCTED |
152 				MBEDTLS_ASN1_SEQUENCE);
153 	if (rc != 0)
154 		return CRYPTO_ERR_SIGNATURE;
155 
156 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
157 	if (rc != 0)
158 		return CRYPTO_ERR_SIGNATURE;
159 
160 	if (*p == 0) {
161 		p++; len--;
162 	}
163 	if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end))
164 		return CRYPTO_ERR_SIGNATURE;
165 
166 	/*
167 	 * Copy N from certificate.
168 	 */
169 	memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);
170 
171 	/* Verify the RSA exponent */
172 	p += len;
173 	rc = mbedtls_asn1_get_int(&p, end, &exp);
174 	if (rc != 0)
175 		return CRYPTO_ERR_SIGNATURE;
176 
177 	if (exp != RSA_EXPONENT)
178 		return CRYPTO_ERR_SIGNATURE;
179 
180 	/* Get the signature (bitstring) */
181 	p = sig_ptr;
182 	end = p + sig_len;
183 	rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
184 	if (rc != 0)
185 		return CRYPTO_ERR_SIGNATURE;
186 
187 	if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end))
188 		return CRYPTO_ERR_SIGNATURE;
189 
190 	/*
191 	 * Copy the signature (in BE format)
192 	 */
193 	memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES);
194 
195 	error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE,
196 			     data_ptr, data_len, digest);
197 	if (error != CC_OK)
198 		return CRYPTO_ERR_SIGNATURE;
199 
200 	/* Verify the signature */
201 	error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff,
202 				    NULL, signature, digest, workspace,
203 				    BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified);
204 	if ((error != CC_OK) || (is_verified != CC_TRUE))
205 		return CRYPTO_ERR_SIGNATURE;
206 
207 	/* Signature verification success */
208 	return CRYPTO_SUCCESS;
209 }
210 
211 /*
212  * Match a hash
213  *
214  * Digest info is passed in DER format following the ASN.1 structure detailed
215  * above.
216  */
verify_hash(void * data_ptr,unsigned int data_len,void * digest_info_ptr,unsigned int digest_info_len)217 static int verify_hash(void *data_ptr, unsigned int data_len,
218 		       void *digest_info_ptr, unsigned int digest_info_len)
219 {
220 	mbedtls_asn1_buf hash_oid, params;
221 	mbedtls_md_type_t md_alg;
222 	uint8_t *p, *end, *hash;
223 	CCHashResult_t pubKeyHash;
224 	size_t len;
225 	int rc;
226 	CCError_t error;
227 
228 	/* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
229 	p = digest_info_ptr;
230 	end = p + digest_info_len;
231 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
232 				  MBEDTLS_ASN1_SEQUENCE);
233 	if (rc != 0)
234 		return CRYPTO_ERR_HASH;
235 
236 	/* Get the hash algorithm */
237 	rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
238 	if (rc != 0)
239 		return CRYPTO_ERR_HASH;
240 
241 	rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
242 	if (rc != 0)
243 		return CRYPTO_ERR_HASH;
244 	/* Verify that hash algorithm is SHA256 */
245 	if (md_alg != MBEDTLS_MD_SHA256)
246 		return CRYPTO_ERR_HASH;
247 
248 	/* Hash should be octet string type */
249 	rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
250 	if (rc != 0)
251 		return CRYPTO_ERR_HASH;
252 
253 	/* Length of hash must match the algorithm's size */
254 	if (len != HASH_RESULT_SIZE_IN_BYTES)
255 		return CRYPTO_ERR_HASH;
256 
257 	hash = p;
258 	error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr,
259 			     data_len, pubKeyHash);
260 	if (error != CC_OK)
261 		return CRYPTO_ERR_HASH;
262 
263 	rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES);
264 	if (rc != 0)
265 		return CRYPTO_ERR_HASH;
266 
267 	return CRYPTO_SUCCESS;
268 }
269 
270 /*
271  * Register crypto library descriptor
272  */
273 REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL);
274