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, ¶ms);
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(¶ms, &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, ¶ms);
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