blob: bf7dff4ac21b9ba0935c22727277777ab268a97b [file] [log] [blame]
Soby Mathew5d708002017-05-10 11:49:58 +01001/*
2 * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#include <arch_helpers.h>
8#include <crypto_mod.h>
9#include <crypto_driver.h>
10#include <debug.h>
11#include <mbedtls_common.h>
12#include <platform_def.h>
13#include <rsa.h>
14#include <sbrom_bsv_api.h>
15#include <secureboot_base_func.h>
16#include <secureboot_gen_defs.h>
17#include <stddef.h>
18#include <string.h>
19#include <utils.h>
20#include <util.h>
21
22#include <mbedtls/oid.h>
23
24#define LIB_NAME "CryptoCell SBROM"
25#define RSA_SALT_LEN 32
26#define RSA_EXPONENT 65537
27
28/*
29 * AlgorithmIdentifier ::= SEQUENCE {
30 * algorithm OBJECT IDENTIFIER,
31 * parameters ANY DEFINED BY algorithm OPTIONAL
32 * }
33 *
34 * SubjectPublicKeyInfo ::= SEQUENCE {
35 * algorithm AlgorithmIdentifier,
36 * subjectPublicKey BIT STRING
37 * }
38 *
39 * DigestInfo ::= SEQUENCE {
40 * digestAlgorithm AlgorithmIdentifier,
41 * digest OCTET STRING
42 * }
43 *
44 * RSASSA-PSS-params ::= SEQUENCE {
45 * hashAlgorithm [0] HashAlgorithm,
46 * maskGenAlgorithm [1] MaskGenAlgorithm,
47 * saltLength [2] INTEGER,
48 * trailerField [3] TrailerField DEFAULT trailerFieldBC
49 * }
50 */
51
52/*
53 * Initialize the library and export the descriptor
54 */
55static void init(void)
56{
57 CCError_t ret;
58
59 /* Initialize CC SBROM */
60 ret = CC_BsvSbromInit((uintptr_t)PLAT_CRYPTOCELL_BASE);
61 if (ret != CC_OK) {
62 ERROR("CryptoCell CC_BsvSbromInit() error %x\n", ret);
63 panic();
64 }
65}
66
67/*
68 * Verify a signature.
69 *
70 * Parameters are passed using the DER encoding format following the ASN.1
71 * structures detailed above.
72 */
73static int verify_signature(void *data_ptr, unsigned int data_len,
74 void *sig_ptr, unsigned int sig_len,
75 void *sig_alg, unsigned int sig_alg_len,
76 void *pk_ptr, unsigned int pk_len)
77{
78 CCError_t error;
79 CCSbNParams_t pk;
80 CCSbSignature_t signature;
81 int rc, exp;
82 mbedtls_asn1_buf sig_oid, alg_oid, params;
83 mbedtls_md_type_t md_alg;
84 mbedtls_pk_type_t pk_alg;
85 mbedtls_pk_rsassa_pss_options pss_opts;
86 size_t len;
87 uint8_t *p, *end;
88 /* Temp buf to store the public key modulo (N) in LE format */
89 uint32_t RevN[SB_RSA_MOD_SIZE_IN_WORDS];
90
91 /* Verify the signature algorithm */
92 /* Get pointers to signature OID and parameters */
93 p = sig_alg;
94 end = p + sig_alg_len;
95 rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &params);
96 if (rc != 0)
97 return CRYPTO_ERR_SIGNATURE;
98
99 /* Get the actual signature algorithm (MD + PK) */
100 rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg);
101 if (rc != 0)
102 return CRYPTO_ERR_SIGNATURE;
103
104 /* The CryptoCell only supports RSASSA-PSS signature */
105 if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE)
106 return CRYPTO_ERR_SIGNATURE;
107
108 /* Verify the RSASSA-PSS params */
109 /* The trailer field is verified to be 0xBC internally by this API */
110 rc = mbedtls_x509_get_rsassa_pss_params(&params, &md_alg,
111 &pss_opts.mgf1_hash_id,
112 &pss_opts.expected_salt_len);
113 if (rc != 0)
114 return CRYPTO_ERR_SIGNATURE;
115
116 /* The CryptoCell only supports SHA256 as hash algorithm */
117 if (md_alg != MBEDTLS_MD_SHA256 || pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256)
118 return CRYPTO_ERR_SIGNATURE;
119
120 if (pss_opts.expected_salt_len != RSA_SALT_LEN)
121 return CRYPTO_ERR_SIGNATURE;
122
123 /* Parse the public key */
124 p = pk_ptr;
125 end = p + pk_len;
126 rc = mbedtls_asn1_get_tag(&p, end, &len,
127 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
128 if (rc != 0)
129 return CRYPTO_ERR_SIGNATURE;
130
131 end = p + len;
132 rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid);
133 if (rc != 0)
134 return CRYPTO_ERR_SIGNATURE;
135
136 if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0)
137 return CRYPTO_ERR_SIGNATURE;
138
139 if (pk_alg != MBEDTLS_PK_RSA)
140 return CRYPTO_ERR_SIGNATURE;
141
142 rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
143 if (rc != 0)
144 return CRYPTO_ERR_SIGNATURE;
145
146 rc = mbedtls_asn1_get_tag(&p, end, &len,
147 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
148 if (rc != 0)
149 return CRYPTO_ERR_SIGNATURE;
150
151 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER);
152 if (rc != 0)
153 return CRYPTO_ERR_SIGNATURE;
154
155 if (*p == 0) {
156 p++; len--;
157 }
158 if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end))
159 return CRYPTO_ERR_SIGNATURE;
160
161 /*
162 * The CCSbVerifySignature() API expects N and Np in BE format and
163 * the signature in LE format. Copy N from certificate.
164 */
165 memcpy(pk.N, p, RSA_MOD_SIZE_IN_BYTES);
166
167 /* Verify the RSA exponent */
168 p += len;
169 rc = mbedtls_asn1_get_int(&p, end, &exp);
170 if (rc != 0)
171 return CRYPTO_ERR_SIGNATURE;
172
173 if (exp != RSA_EXPONENT)
174 return CRYPTO_ERR_SIGNATURE;
175
176 /*
177 * Calculate the Np (Barrett n' value). The RSA_CalcNp() API expects
178 * N in LE format. Hence reverse N into a temporary buffer `RevN`.
179 */
180 UTIL_ReverseMemCopy((uint8_t *)RevN, (uint8_t *)pk.N, sizeof(RevN));
181
182 RSA_CalcNp((uintptr_t)PLAT_CRYPTOCELL_BASE, RevN, pk.Np);
183
184 /* Np is in LE format. Reverse it to BE */
185 UTIL_ReverseBuff((uint8_t *)pk.Np, sizeof(pk.Np));
186
187 /* Get the signature (bitstring) */
188 p = sig_ptr;
189 end = p + sig_len;
190 rc = mbedtls_asn1_get_bitstring_null(&p, end, &len);
191 if (rc != 0)
192 return CRYPTO_ERR_SIGNATURE;
193
194 if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end))
195 return CRYPTO_ERR_SIGNATURE;
196
197 /*
198 * The signature is BE format. Convert it to LE before calling
199 * CCSbVerifySignature().
200 */
201 UTIL_ReverseMemCopy((uint8_t *)signature.sig, p, RSA_MOD_SIZE_IN_BYTES);
202
203 /*
204 * CryptoCell utilises DMA internally to transfer data. Flush the data
205 * from caches.
206 */
207 flush_dcache_range((uintptr_t)data_ptr, data_len);
208
209 /* Verify the signature */
210 error = CCSbVerifySignature((uintptr_t)PLAT_CRYPTOCELL_BASE,
211 (uint32_t *)data_ptr, &pk, &signature,
212 data_len, RSA_PSS_2048);
213 if (error != CC_OK)
214 return CRYPTO_ERR_SIGNATURE;
215
216 /* Signature verification success */
217 return CRYPTO_SUCCESS;
218}
219
220/*
221 * Match a hash
222 *
223 * Digest info is passed in DER format following the ASN.1 structure detailed
224 * above.
225 */
226static int verify_hash(void *data_ptr, unsigned int data_len,
227 void *digest_info_ptr, unsigned int digest_info_len)
228{
229 mbedtls_asn1_buf hash_oid, params;
230 mbedtls_md_type_t md_alg;
231 uint8_t *p, *end, *hash;
232 CCHashResult_t pubKeyHash;
233 size_t len;
234 int rc;
235 CCError_t error;
236
237 /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */
238 p = digest_info_ptr;
239 end = p + digest_info_len;
240 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED |
241 MBEDTLS_ASN1_SEQUENCE);
242 if (rc != 0)
243 return CRYPTO_ERR_HASH;
244
245 /* Get the hash algorithm */
246 rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, &params);
247 if (rc != 0)
248 return CRYPTO_ERR_HASH;
249
250 rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg);
251 if (rc != 0)
252 return CRYPTO_ERR_HASH;
253 /* Verify that hash algorithm is SHA256 */
254 if (md_alg != MBEDTLS_MD_SHA256)
255 return CRYPTO_ERR_HASH;
256
257 /* Hash should be octet string type */
258 rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
259 if (rc != 0)
260 return CRYPTO_ERR_HASH;
261
262 /* Length of hash must match the algorithm's size */
263 if (len != HASH_RESULT_SIZE_IN_BYTES)
264 return CRYPTO_ERR_HASH;
265
266 /*
267 * CryptoCell utilises DMA internally to transfer data. Flush the data
268 * from caches.
269 */
270 flush_dcache_range((uintptr_t)data_ptr, data_len);
271
272 hash = p;
273 error = SBROM_CryptoHash((uintptr_t)PLAT_CRYPTOCELL_BASE,
274 (uintptr_t)data_ptr, data_len, pubKeyHash);
275 if (error != CC_OK)
276 return CRYPTO_ERR_HASH;
277
278 rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES);
279 if (rc != 0)
280 return CRYPTO_ERR_HASH;
281
282 return CRYPTO_SUCCESS;
283}
284
285/*
286 * Register crypto library descriptor
287 */
288REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash);
289
290