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