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