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"), <c_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(<c_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(<c_private_key, <c_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(<c_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