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