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