1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (c) 2022, Technology Innovation Institute (TII)
4  */
5 
6 #include <crypto/crypto.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <string_ext.h>
10 #include <tee_api_types.h>
11 #include <trace.h>
12 #include <utee_defines.h>
13 
14 #include "acipher_helpers.h"
15 
16 /* X25519 key is an octet string of 32 bytes */
17 #define X25519_KEY_SIZE_BYTES UL(32)
18 
crypto_acipher_alloc_x25519_keypair(struct x25519_keypair * key,size_t key_size)19 TEE_Result crypto_acipher_alloc_x25519_keypair(struct x25519_keypair *key,
20 					       size_t key_size)
21 {
22 	size_t key_size_bytes = key_size / 8;
23 
24 	if (!key)
25 		return TEE_ERROR_BAD_PARAMETERS;
26 
27 	memset(key, 0, sizeof(*key));
28 
29 	if (key_size_bytes != X25519_KEY_SIZE_BYTES)
30 		return TEE_ERROR_BAD_PARAMETERS;
31 
32 	key->priv = calloc(1, key_size_bytes);
33 	key->pub = calloc(1, key_size_bytes);
34 
35 	if (!key->priv || !key->pub) {
36 		free(key->priv);
37 		free(key->pub);
38 		return TEE_ERROR_OUT_OF_MEMORY;
39 	}
40 
41 	return TEE_SUCCESS;
42 }
43 
crypto_acipher_gen_x25519_key(struct x25519_keypair * key,size_t key_size)44 TEE_Result crypto_acipher_gen_x25519_key(struct x25519_keypair *key,
45 					 size_t key_size)
46 {
47 	curve25519_key ltc_tmp_key = { };
48 	size_t key_size_bytes = key_size / 8;
49 
50 	if (key_size_bytes != X25519_KEY_SIZE_BYTES)
51 		return TEE_ERROR_BAD_PARAMETERS;
52 
53 	if (x25519_make_key(NULL, find_prng("prng_crypto"), &ltc_tmp_key) !=
54 	    CRYPT_OK)
55 		return TEE_ERROR_BAD_PARAMETERS;
56 
57 	if (key_size_bytes < sizeof(ltc_tmp_key.pub) ||
58 	    key_size_bytes < sizeof(ltc_tmp_key.priv))
59 		return TEE_ERROR_BAD_PARAMETERS;
60 
61 	memcpy(key->pub, ltc_tmp_key.pub, sizeof(ltc_tmp_key.pub));
62 	memcpy(key->priv, ltc_tmp_key.priv, sizeof(ltc_tmp_key.priv));
63 	memzero_explicit(&ltc_tmp_key, sizeof(ltc_tmp_key));
64 
65 	return TEE_SUCCESS;
66 }
67 
crypto_acipher_x25519_shared_secret(struct x25519_keypair * private_key,void * public_key,void * secret,unsigned long * secret_len)68 TEE_Result crypto_acipher_x25519_shared_secret(struct x25519_keypair
69 					       *private_key,
70 					       void *public_key,
71 					       void *secret,
72 					       unsigned long *secret_len)
73 {
74 	curve25519_key ltc_private_key = {
75 		.type = PK_PRIVATE,
76 		.algo = LTC_OID_X25519,
77 	};
78 	curve25519_key ltc_public_key = {
79 		.type = PK_PUBLIC,
80 		.algo = LTC_OID_X25519,
81 	};
82 
83 	if (!private_key || !public_key || !secret || !secret_len)
84 		return TEE_ERROR_BAD_PARAMETERS;
85 
86 	static_assert(sizeof(ltc_public_key.pub) == X25519_KEY_SIZE_BYTES &&
87 		      sizeof(ltc_public_key.priv) == X25519_KEY_SIZE_BYTES);
88 
89 	memcpy(ltc_public_key.pub, public_key, X25519_KEY_SIZE_BYTES);
90 	memcpy(ltc_private_key.priv, private_key->priv, X25519_KEY_SIZE_BYTES);
91 
92 	if (x25519_shared_secret(&ltc_private_key, &ltc_public_key,
93 				 secret, secret_len) != CRYPT_OK)
94 		return TEE_ERROR_BAD_PARAMETERS;
95 
96 	/* Clear private key from the stack */
97 	memzero_explicit(&ltc_private_key, sizeof(ltc_private_key));
98 
99 	/*
100 	 * RFC 7748, sec 6.1, check for all zero shared secret output to reject
101 	 * input points of low order.
102 	 */
103 	if (*secret_len != X25519_KEY_SIZE_BYTES ||
104 	    !consttime_memcmp(secret, ltc_private_key.pub,
105 			       X25519_KEY_SIZE_BYTES))
106 		return TEE_ERROR_SECURITY;
107 
108 	return TEE_SUCCESS;
109 }
110