1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2018-2021 NXP
4 *
5 * Crypto ECC interface implementation to enable HW driver.
6 */
7 #include <crypto/crypto_impl.h>
8 #include <drvcrypt.h>
9 #include <drvcrypt_acipher.h>
10 #include <tee/tee_cryp_utl.h>
11 #include <utee_defines.h>
12
13 /*
14 * Returns the key size in bytes for the given ECC curve
15 *
16 * @curve ECC Curve ID
17 */
get_ecc_key_size_bytes(uint32_t curve)18 static size_t get_ecc_key_size_bytes(uint32_t curve)
19 {
20 switch (curve) {
21 case TEE_ECC_CURVE_NIST_P192:
22 return 24;
23
24 case TEE_ECC_CURVE_NIST_P224:
25 return 28;
26
27 case TEE_ECC_CURVE_NIST_P256:
28 return 32;
29
30 case TEE_ECC_CURVE_NIST_P384:
31 return 48;
32
33 case TEE_ECC_CURVE_NIST_P521:
34 return 66;
35
36 default:
37 return 0;
38 }
39 }
40
41 /*
42 * Verify if the cryptographic algorithm @algo is valid for
43 * the ECC curve
44 *
45 * @curve ECC curve
46 * @algo Cryptographic algorithm
47 */
algo_is_valid(uint32_t curve,uint32_t algo)48 static bool algo_is_valid(uint32_t curve, uint32_t algo)
49 {
50 unsigned int algo_op = TEE_ALG_GET_CLASS(algo);
51 unsigned int algo_id = TEE_ALG_GET_MAIN_ALG(algo);
52 unsigned int algo_curve = TEE_ALG_GET_DIGEST_HASH(algo);
53
54 /* Check first the algo operation and id */
55 if ((algo_op == TEE_OPERATION_ASYMMETRIC_SIGNATURE &&
56 algo_id == TEE_MAIN_ALGO_ECDSA) ||
57 (algo_op == TEE_OPERATION_KEY_DERIVATION &&
58 algo_id == TEE_MAIN_ALGO_ECDH)) {
59 if (curve == algo_curve) {
60 CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32
61 " is valid", algo, curve);
62 return true;
63 }
64 }
65
66 CRYPTO_TRACE("Algo 0x%" PRIx32 " curve 0x%" PRIx32 " is not valid",
67 algo, curve);
68
69 return false;
70 }
71
72 /*
73 * Free an ECC public key
74 *
75 * @key Public Key
76 */
ecc_free_public_key(struct ecc_public_key * key)77 static void ecc_free_public_key(struct ecc_public_key *key)
78 {
79 struct drvcrypt_ecc *ecc = NULL;
80
81 if (key) {
82 ecc = drvcrypt_get_ops(CRYPTO_ECC);
83 if (ecc) {
84 CRYPTO_TRACE("ECC Public Key free");
85 ecc->free_publickey(key);
86 }
87 }
88 }
89
90 /*
91 * Generates an ECC keypair
92 *
93 * @key Keypair
94 * @size_bits Key size in bits
95 */
ecc_generate_keypair(struct ecc_keypair * key,size_t size_bits __maybe_unused)96 static TEE_Result ecc_generate_keypair(struct ecc_keypair *key,
97 size_t size_bits __maybe_unused)
98 {
99 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
100 struct drvcrypt_ecc *ecc = NULL;
101 size_t key_size_bits = 0;
102
103 /* Check input parameters */
104 if (!key) {
105 CRYPTO_TRACE("Parameters error key is NULL");
106 return TEE_ERROR_BAD_PARAMETERS;
107 }
108
109 key_size_bits = get_ecc_key_size_bytes(key->curve) * 8;
110
111 ecc = drvcrypt_get_ops(CRYPTO_ECC);
112 if (ecc)
113 ret = ecc->gen_keypair(key, key_size_bits);
114
115 CRYPTO_TRACE("ECC Keypair (%zu bits) generate ret = 0x%" PRIx32,
116 key_size_bits, ret);
117
118 return ret;
119 }
120
121 /*
122 * Sign the message with the ECC Key given by the Keypair
123 *
124 * @algo ECC algorithm
125 * @key ECC Keypair
126 * @msg Message to sign
127 * @msg_len Length of the message (bytes)
128 * @sig Signature
129 * @sig_len [in/out] Length of the signature (bytes)
130 */
ecc_sign(uint32_t algo,struct ecc_keypair * key,const uint8_t * msg,size_t msg_len,uint8_t * sig,size_t * sig_len)131 static TEE_Result ecc_sign(uint32_t algo, struct ecc_keypair *key,
132 const uint8_t *msg, size_t msg_len, uint8_t *sig,
133 size_t *sig_len)
134 {
135 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
136 struct drvcrypt_ecc *ecc = NULL;
137 struct drvcrypt_sign_data sdata = { };
138 size_t size_bytes = 0;
139
140 /* Verify first the input parameters */
141 if (!key || !msg || !sig_len) {
142 CRYPTO_TRACE("Input parameters reference error");
143 return ret;
144 }
145
146 if (!algo_is_valid(key->curve, algo))
147 return ret;
148
149 size_bytes = get_ecc_key_size_bytes(key->curve);
150 if (!size_bytes)
151 return TEE_ERROR_BAD_PARAMETERS;
152
153 /* Verify the signature length function of the key size */
154 if (*sig_len < 2 * size_bytes) {
155 CRYPTO_TRACE("Length (%zu) too short expected %zu bytes",
156 *sig_len, 2 * size_bytes);
157 *sig_len = 2 * size_bytes;
158 return TEE_ERROR_SHORT_BUFFER;
159 }
160
161 if (!sig) {
162 CRYPTO_TRACE("Parameter \"sig\" reference error");
163 return TEE_ERROR_BAD_PARAMETERS;
164 }
165
166 ecc = drvcrypt_get_ops(CRYPTO_ECC);
167 if (ecc) {
168 /*
169 * Prepare the Signature structure data
170 */
171 sdata.algo = algo;
172 sdata.key = key;
173 sdata.size_sec = size_bytes;
174 sdata.message.data = (uint8_t *)msg;
175 sdata.message.length = msg_len;
176 sdata.signature.data = (uint8_t *)sig;
177 sdata.signature.length = *sig_len;
178
179 ret = ecc->sign(&sdata);
180
181 /* Set the signature length */
182 *sig_len = sdata.signature.length;
183 } else {
184 ret = TEE_ERROR_NOT_IMPLEMENTED;
185 }
186
187 CRYPTO_TRACE("Sign algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo,
188 ret);
189
190 return ret;
191 }
192
193 /*
194 * Verify if signature is signed with the given public key.
195 *
196 * @algo ECC algorithm
197 * @key ECC Public key
198 * @msg Message to sign
199 * @msg_len Length of the message (bytes)
200 * @sig Signature
201 * @sig_len Length of the signature (bytes)
202 */
ecc_verify(uint32_t algo,struct ecc_public_key * key,const uint8_t * msg,size_t msg_len,const uint8_t * sig,size_t sig_len)203 static TEE_Result ecc_verify(uint32_t algo, struct ecc_public_key *key,
204 const uint8_t *msg, size_t msg_len,
205 const uint8_t *sig, size_t sig_len)
206 {
207 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
208 struct drvcrypt_ecc *ecc = NULL;
209 struct drvcrypt_sign_data sdata = { };
210 size_t size_bytes = 0;
211
212 /* Verify first the input parameters */
213 if (!key || !msg || !sig) {
214 CRYPTO_TRACE("Input parameters reference error");
215 return ret;
216 }
217
218 if (!algo_is_valid(key->curve, algo))
219 return ret;
220
221 size_bytes = get_ecc_key_size_bytes(key->curve);
222 if (!size_bytes)
223 return TEE_ERROR_BAD_PARAMETERS;
224
225 /* Verify the signature length against key size */
226 if (sig_len != 2 * size_bytes) {
227 CRYPTO_TRACE("Length (%zu) is invalid expected %zu bytes",
228 sig_len, 2 * size_bytes);
229 return TEE_ERROR_SIGNATURE_INVALID;
230 }
231
232 ecc = drvcrypt_get_ops(CRYPTO_ECC);
233 if (ecc) {
234 sdata.algo = algo;
235 sdata.key = key;
236 sdata.size_sec = size_bytes;
237 sdata.message.data = (uint8_t *)msg;
238 sdata.message.length = msg_len;
239 sdata.signature.data = (uint8_t *)sig;
240 sdata.signature.length = sig_len;
241
242 ret = ecc->verify(&sdata);
243 } else {
244 ret = TEE_ERROR_NOT_IMPLEMENTED;
245 }
246
247 CRYPTO_TRACE("Verify algo (0x%" PRIx32 ") returned 0x%" PRIx32, algo,
248 ret);
249
250 return ret;
251 }
252
253 /*
254 * Compute the shared secret data from ECC Private key and Public Key
255 *
256 * @private_key ECC Private key
257 * @public_key ECC Public key
258 * @secret Secret
259 * @secret_len Length of the secret (bytes)
260 */
ecc_shared_secret(struct ecc_keypair * private_key,struct ecc_public_key * public_key,void * secret,unsigned long * secret_len)261 static TEE_Result ecc_shared_secret(struct ecc_keypair *private_key,
262 struct ecc_public_key *public_key,
263 void *secret, unsigned long *secret_len)
264 {
265 TEE_Result ret = TEE_ERROR_BAD_PARAMETERS;
266 struct drvcrypt_ecc *ecc = NULL;
267 struct drvcrypt_secret_data sdata = { };
268 size_t size_bytes = 0;
269
270 /* Verify first the input parameters */
271 if (!private_key || !public_key || !secret_len) {
272 CRYPTO_TRACE("Input parameters reference error");
273 return ret;
274 }
275
276 if (private_key->curve != public_key->curve) {
277 CRYPTO_TRACE("Private Key curve (%d) != Public Key curve (%d)",
278 private_key->curve, public_key->curve);
279 return ret;
280 }
281
282 size_bytes = get_ecc_key_size_bytes(public_key->curve);
283 if (!size_bytes)
284 return ret;
285
286 if (*secret_len < size_bytes) {
287 *secret_len = size_bytes;
288 return TEE_ERROR_SHORT_BUFFER;
289 }
290
291 if (!secret) {
292 CRYPTO_TRACE("Parameter \"secret\" reference error");
293 return ret;
294 }
295
296 ecc = drvcrypt_get_ops(CRYPTO_ECC);
297 if (ecc) {
298 /*
299 * Prepare the Secret structure data
300 */
301 sdata.key_priv = private_key;
302 sdata.key_pub = public_key;
303 sdata.size_sec = size_bytes;
304 sdata.secret.data = secret;
305 sdata.secret.length = *secret_len;
306
307 ret = ecc->shared_secret(&sdata);
308
309 /* Set the secret length */
310 *secret_len = sdata.secret.length;
311 } else {
312 ret = TEE_ERROR_NOT_IMPLEMENTED;
313 }
314
315 CRYPTO_TRACE("Shared Secret returned 0x%" PRIx32, ret);
316
317 return ret;
318 }
319
320 static const struct crypto_ecc_keypair_ops ecc_keypair_ops = {
321 .generate = ecc_generate_keypair,
322 .sign = ecc_sign,
323 .shared_secret = ecc_shared_secret,
324 };
325
drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair * key,uint32_t type,size_t size_bits)326 TEE_Result drvcrypt_asym_alloc_ecc_keypair(struct ecc_keypair *key,
327 uint32_t type, size_t size_bits)
328 {
329 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
330 struct drvcrypt_ecc *ecc = NULL;
331
332 if (!key || !size_bits) {
333 CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key,
334 size_bits);
335 return TEE_ERROR_BAD_PARAMETERS;
336 }
337
338 switch (type) {
339 case TEE_TYPE_ECDSA_KEYPAIR:
340 case TEE_TYPE_ECDH_KEYPAIR:
341 ecc = drvcrypt_get_ops(CRYPTO_ECC);
342 break;
343 default:
344 break;
345 }
346
347 if (ecc)
348 ret = ecc->alloc_keypair(key, size_bits);
349
350 if (!ret)
351 key->ops = &ecc_keypair_ops;
352
353 CRYPTO_TRACE("ECC Keypair (%zu bits) alloc ret = 0x%" PRIx32, size_bits,
354 ret);
355 return ret;
356 }
357
358 static const struct crypto_ecc_public_ops ecc_public_key_ops = {
359 .free = ecc_free_public_key,
360 .verify = ecc_verify,
361 };
362
drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key * key,uint32_t type,size_t size_bits)363 TEE_Result drvcrypt_asym_alloc_ecc_public_key(struct ecc_public_key *key,
364 uint32_t type, size_t size_bits)
365 {
366 TEE_Result ret = TEE_ERROR_NOT_IMPLEMENTED;
367 struct drvcrypt_ecc *ecc = NULL;
368
369 if (!key || !size_bits) {
370 CRYPTO_TRACE("Bad parameters (key @%p)(size %zu bits)", key,
371 size_bits);
372 return TEE_ERROR_BAD_PARAMETERS;
373 }
374
375 switch (type) {
376 case TEE_TYPE_ECDSA_PUBLIC_KEY:
377 case TEE_TYPE_ECDH_PUBLIC_KEY:
378 ecc = drvcrypt_get_ops(CRYPTO_ECC);
379 break;
380 default:
381 break;
382 }
383
384 if (ecc)
385 ret = ecc->alloc_publickey(key, size_bits);
386
387 if (!ret)
388 key->ops = &ecc_public_key_ops;
389
390 CRYPTO_TRACE("ECC Public Key (%zu bits) alloc ret = 0x%" PRIx32,
391 size_bits, ret);
392 return ret;
393 }
394