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