1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3  * Copyright (C) 2018, ARM Limited
4  * Copyright (C) 2019, Linaro Limited
5  */
6 
7 #include <assert.h>
8 #include <crypto/crypto.h>
9 #include <mbedtls/ctr_drbg.h>
10 #include <mbedtls/entropy.h>
11 #include <mbedtls/dhm.h>
12 #include <stdlib.h>
13 #include <string.h>
14 
15 #include "mbed_helpers.h"
16 
crypto_acipher_alloc_dh_keypair(struct dh_keypair * s,size_t key_size_bits)17 TEE_Result crypto_acipher_alloc_dh_keypair(struct dh_keypair *s,
18 					   size_t key_size_bits)
19 {
20 	memset(s, 0, sizeof(*s));
21 	s->g = crypto_bignum_allocate(key_size_bits);
22 	if (!s->g)
23 		goto err;
24 	s->p = crypto_bignum_allocate(key_size_bits);
25 	if (!s->p)
26 		goto err;
27 	s->y = crypto_bignum_allocate(key_size_bits);
28 	if (!s->y)
29 		goto err;
30 	s->x = crypto_bignum_allocate(key_size_bits);
31 	if (!s->x)
32 		goto err;
33 	s->q = crypto_bignum_allocate(key_size_bits);
34 	if (!s->q)
35 		goto err;
36 	return TEE_SUCCESS;
37 err:
38 	crypto_bignum_free(s->g);
39 	crypto_bignum_free(s->p);
40 	crypto_bignum_free(s->y);
41 	crypto_bignum_free(s->x);
42 	return TEE_ERROR_OUT_OF_MEMORY;
43 }
44 
crypto_acipher_gen_dh_key(struct dh_keypair * key,struct bignum * q __unused,size_t xbits,size_t key_size)45 TEE_Result crypto_acipher_gen_dh_key(struct dh_keypair *key,
46 				     struct bignum *q __unused,
47 				     size_t xbits, size_t key_size)
48 {
49 	TEE_Result res = TEE_SUCCESS;
50 	int lmd_res = 0;
51 	mbedtls_dhm_context dhm;
52 	unsigned char *buf = NULL;
53 	size_t xbytes = 0;
54 
55 	memset(&dhm, 0, sizeof(dhm));
56 	mbedtls_dhm_init(&dhm);
57 
58 	dhm.G = *(mbedtls_mpi *)key->g;
59 	dhm.P = *(mbedtls_mpi *)key->p;
60 
61 	dhm.len = crypto_bignum_num_bytes(key->p);
62 	if (key_size != 8 * dhm.len) {
63 		res = TEE_ERROR_BAD_PARAMETERS;
64 		goto out;
65 	}
66 
67 	if (xbits == 0)
68 		xbytes = dhm.len;
69 	else
70 		xbytes = xbits / 8;
71 
72 	buf = malloc(dhm.len);
73 	if (!buf) {
74 		res = TEE_ERROR_OUT_OF_MEMORY;
75 		goto out;
76 	}
77 	lmd_res = mbedtls_dhm_make_public(&dhm, (int)xbytes, buf,
78 					  dhm.len, mbd_rand, NULL);
79 	if (lmd_res != 0) {
80 		FMSG("mbedtls_dhm_make_public err, return is 0x%x", -lmd_res);
81 		res = TEE_ERROR_BAD_PARAMETERS;
82 	} else {
83 		crypto_bignum_bin2bn(buf, xbytes, key->y);
84 		crypto_bignum_copy(key->x, (void *)&dhm.X);
85 		res = TEE_SUCCESS;
86 	}
87 out:
88 	free(buf);
89 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
90 	mbedtls_mpi_init(&dhm.G);
91 	mbedtls_mpi_init(&dhm.P);
92 	mbedtls_dhm_free(&dhm);
93 	return res;
94 }
95 
crypto_acipher_dh_shared_secret(struct dh_keypair * private_key,struct bignum * public_key,struct bignum * secret)96 TEE_Result crypto_acipher_dh_shared_secret(struct dh_keypair *private_key,
97 					   struct bignum *public_key,
98 					   struct bignum *secret)
99 {
100 	TEE_Result res = TEE_SUCCESS;
101 	int lmd_res = 0;
102 	mbedtls_dhm_context dhm;
103 	unsigned char *buf = NULL;
104 	size_t olen = 0;
105 
106 	memset(&dhm, 0, sizeof(dhm));
107 	mbedtls_dhm_init(&dhm);
108 
109 	dhm.G = *(mbedtls_mpi *)private_key->g;
110 	dhm.P = *(mbedtls_mpi *)private_key->p;
111 	dhm.GX = *(mbedtls_mpi *)private_key->y;
112 	dhm.X = *(mbedtls_mpi *)private_key->x;
113 	dhm.GY = *(mbedtls_mpi *)public_key;
114 
115 	dhm.len = crypto_bignum_num_bytes(private_key->p);
116 
117 	buf = malloc(dhm.len);
118 	if (!buf) {
119 		res = TEE_ERROR_OUT_OF_MEMORY;
120 		goto out;
121 	}
122 
123 	lmd_res = mbedtls_dhm_calc_secret(&dhm, buf, dhm.len,
124 					  &olen, mbd_rand, NULL);
125 	if (lmd_res != 0) {
126 		FMSG("mbedtls_dhm_calc_secret failed, ret is 0x%x", -lmd_res);
127 		res = TEE_ERROR_BAD_PARAMETERS;
128 	} else {
129 		crypto_bignum_bin2bn(buf, olen, secret);
130 		res = TEE_SUCCESS;
131 	}
132 out:
133 	free(buf);
134 	/* Reset mpi to skip freeing here, those mpis will be freed with key */
135 	mbedtls_mpi_init(&dhm.G);
136 	mbedtls_mpi_init(&dhm.P);
137 	mbedtls_mpi_init(&dhm.GX);
138 	mbedtls_mpi_init(&dhm.X);
139 	mbedtls_mpi_init(&dhm.GY);
140 	mbedtls_dhm_free(&dhm);
141 	return res;
142 }
143