1 /*
2 * Copyright (c) 2020-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #ifdef HKS_CONFIG_FILE
17 #include HKS_CONFIG_FILE
18 #else
19 #include "hks_config.h"
20 #endif
21
22 #ifdef HKS_SUPPORT_DH_C
23
24 #include "hks_mbedtls_dh.h"
25
26 #include <mbedtls/dhm.h>
27
28 #include "hks_log.h"
29 #include "hks_mbedtls_common.h"
30 #include "hks_mem.h"
31 #include "hks_template.h"
32
33 #define HKS_DH_KEYPAIR_CNT 2
34
35 #if defined(HKS_SUPPORT_DH_GENERATE_KEY) || defined(HKS_SUPPORT_DH_AGREE_KEY)
36 static uint8_t g_ffdhe2048ParamG[] = MBEDTLS_DHM_RFC7919_FFDHE2048_G_BIN;
37 static uint8_t g_ffdhe2048ParamP[] = MBEDTLS_DHM_RFC7919_FFDHE2048_P_BIN;
38 static uint8_t g_ffdhe3072ParamG[] = MBEDTLS_DHM_RFC7919_FFDHE3072_G_BIN;
39 static uint8_t g_ffdhe3072ParamP[] = MBEDTLS_DHM_RFC7919_FFDHE3072_P_BIN;
40 static uint8_t g_ffdhe4096ParamG[] = MBEDTLS_DHM_RFC7919_FFDHE4096_G_BIN;
41 static uint8_t g_ffdhe4096ParamP[] = MBEDTLS_DHM_RFC7919_FFDHE4096_P_BIN;
42
GetDhParam(uint32_t keySize,struct HksBlob * P,struct HksBlob * G)43 static int32_t GetDhParam(uint32_t keySize, struct HksBlob *P, struct HksBlob *G)
44 {
45 switch (keySize) {
46 case HKS_DH_KEY_SIZE_2048:
47 P->data = g_ffdhe2048ParamP;
48 P->size = sizeof(g_ffdhe2048ParamP);
49 G->data = g_ffdhe2048ParamG;
50 G->size = sizeof(g_ffdhe2048ParamG);
51 return HKS_SUCCESS;
52 case HKS_DH_KEY_SIZE_3072:
53 P->data = g_ffdhe3072ParamP;
54 P->size = sizeof(g_ffdhe3072ParamP);
55 G->data = g_ffdhe3072ParamG;
56 G->size = sizeof(g_ffdhe3072ParamG);
57 return HKS_SUCCESS;
58 case HKS_DH_KEY_SIZE_4096:
59 P->data = g_ffdhe4096ParamP;
60 P->size = sizeof(g_ffdhe4096ParamP);
61 G->data = g_ffdhe4096ParamG;
62 G->size = sizeof(g_ffdhe4096ParamG);
63 return HKS_SUCCESS;
64 default:
65 return HKS_ERROR_INVALID_KEY_SIZE;
66 }
67 }
68 #endif
69
70 #ifdef HKS_SUPPORT_DH_GENERATE_KEY
DhSaveKeyMaterial(const mbedtls_dhm_context * ctx,const uint32_t keySize,struct HksBlob * key)71 static int32_t DhSaveKeyMaterial(const mbedtls_dhm_context *ctx, const uint32_t keySize, struct HksBlob *key)
72 {
73 const uint32_t keyByteLen = HKS_KEY_BYTES(keySize);
74 const uint32_t rawMaterialLen = sizeof(struct KeyMaterialDh) + keyByteLen * HKS_DH_KEYPAIR_CNT;
75 uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
76 HKS_IF_NULL_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL)
77 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
78
79 struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)rawMaterial;
80 keyMaterial->keyAlg = HKS_ALG_DH;
81 keyMaterial->keySize = keySize;
82 keyMaterial->pubKeySize = mbedtls_mpi_size(&ctx->GX);
83 keyMaterial->priKeySize = mbedtls_mpi_size(&ctx->X);
84
85 int32_t ret;
86 do {
87 uint32_t offset = sizeof(*keyMaterial);
88 ret = mbedtls_mpi_write_binary(&(ctx->GX), rawMaterial + offset, keyMaterial->pubKeySize);
89 if (ret != HKS_MBEDTLS_SUCCESS) {
90 HKS_LOG_E("mbedtls_mpi_write_binary failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
91 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
92 HKS_FREE(rawMaterial);
93 break;
94 }
95
96 offset = offset + keyMaterial->pubKeySize;
97 ret = mbedtls_mpi_write_binary(&(ctx->X), rawMaterial + offset, keyMaterial->priKeySize);
98 if (ret != HKS_MBEDTLS_SUCCESS) {
99 HKS_LOG_E("mbedtls_mpi_write_binary failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
100 (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
101 HKS_FREE(rawMaterial);
102 break;
103 }
104
105 key->data = rawMaterial;
106 key->size = rawMaterialLen;
107 } while (0);
108
109 return ret;
110 }
111
HksMbedtlsDhGenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)112 int32_t HksMbedtlsDhGenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
113 {
114 mbedtls_dhm_context ctx;
115 (void)memset_s(&ctx, sizeof(mbedtls_dhm_context), 0, sizeof(mbedtls_dhm_context));
116 mbedtls_dhm_init(&ctx);
117
118 mbedtls_entropy_context entropy;
119 mbedtls_ctr_drbg_context ctrDrbg;
120 (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
121 (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
122 int32_t ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
123 if (ret != HKS_SUCCESS) {
124 mbedtls_dhm_free(&ctx);
125 return ret;
126 }
127
128 do {
129 struct HksBlob paramP;
130 struct HksBlob paramG;
131 ret = GetDhParam(spec->keyLen, ¶mP, ¶mG);
132 HKS_IF_NOT_SUCC_BREAK(ret)
133 uint32_t keyLen = HKS_KEY_BYTES(spec->keyLen);
134
135 if (mbedtls_mpi_read_binary(&ctx.P, paramP.data, paramP.size) != HKS_MBEDTLS_SUCCESS ||
136 mbedtls_mpi_read_binary(&ctx.G, paramG.data, paramG.size) != HKS_MBEDTLS_SUCCESS) {
137 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
138 break;
139 }
140 ctx.len = keyLen;
141
142 uint8_t *output = (uint8_t *)HksMalloc(keyLen);
143 HKS_IF_NULL_BREAK(output)
144 ret = mbedtls_dhm_make_public(&ctx, keyLen, output, keyLen, mbedtls_ctr_drbg_random, &ctrDrbg);
145 if (ret != HKS_SUCCESS) {
146 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
147 } else {
148 ret = DhSaveKeyMaterial(&ctx, spec->keyLen, key);
149 }
150 HKS_FREE(output);
151 } while (0);
152
153 mbedtls_dhm_free(&ctx);
154 mbedtls_ctr_drbg_free(&ctrDrbg);
155 mbedtls_entropy_free(&entropy);
156
157 return ret;
158 }
159 #endif
160
161 #ifdef HKS_SUPPORT_DH_GET_PUBLIC_KEY
HksMbedtlsGetDhPubKey(const struct HksBlob * input,struct HksBlob * output)162 int32_t HksMbedtlsGetDhPubKey(const struct HksBlob *input, struct HksBlob *output)
163 {
164 struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)input->data;
165 if (input->size < sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize) {
166 return HKS_ERROR_INVALID_ARGUMENT;
167 }
168 if (output->size < sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize) {
169 return HKS_ERROR_BUFFER_TOO_SMALL;
170 }
171
172 if (memcpy_s(output->data, output->size, input->data, sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize) !=
173 EOK) {
174 return HKS_ERROR_INSUFFICIENT_MEMORY;
175 }
176 ((struct KeyMaterialDh *)output->data)->priKeySize = 0;
177 ((struct KeyMaterialDh *)output->data)->reserved = 0;
178 output->size = sizeof(struct KeyMaterialDh) + keyMaterial->pubKeySize;
179
180 return HKS_SUCCESS;
181 }
182 #endif
183
184 #ifdef HKS_SUPPORT_DH_AGREE_KEY
DhKeyMaterialToCtx(const struct HksBlob * key,const bool needPrivateExponent,mbedtls_dhm_context * ctx)185 static int32_t DhKeyMaterialToCtx(const struct HksBlob *key, const bool needPrivateExponent, mbedtls_dhm_context *ctx)
186 {
187 const struct KeyMaterialDh *keyMaterial = (struct KeyMaterialDh *)(key->data);
188
189 int32_t ret;
190 do {
191 struct HksBlob paramP;
192 struct HksBlob paramG;
193 ret = GetDhParam(keyMaterial->keySize, ¶mP, ¶mG);
194 HKS_IF_NOT_SUCC_BREAK(ret)
195
196 if (mbedtls_mpi_read_binary(&ctx->P, paramP.data, paramP.size) != HKS_MBEDTLS_SUCCESS ||
197 mbedtls_mpi_read_binary(&ctx->G, paramG.data, paramG.size) != HKS_MBEDTLS_SUCCESS) {
198 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
199 break;
200 }
201 ctx->len = HKS_KEY_BYTES(keyMaterial->keySize);
202
203 uint32_t offset = sizeof(struct KeyMaterialDh);
204 ret = mbedtls_mpi_read_binary(&ctx->GX, key->data + offset, keyMaterial->pubKeySize);
205 if (ret != HKS_MBEDTLS_SUCCESS) {
206 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
207 HKS_LOG_E("mbedtls_mpi_read_binary failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
208 break;
209 }
210
211 if (needPrivateExponent) {
212 offset = offset + keyMaterial->pubKeySize;
213 ret = mbedtls_mpi_read_binary(&ctx->X, key->data + offset, keyMaterial->priKeySize);
214 if (ret != HKS_MBEDTLS_SUCCESS) {
215 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
216 HKS_LOG_E("mbedtls_mpi_read_binary failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
217 break;
218 }
219 }
220
221 ret = HKS_SUCCESS;
222 } while (0);
223
224 return ret;
225 }
226
HksMbedtlsDhAgreeKey(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)227 int32_t HksMbedtlsDhAgreeKey(const struct HksBlob *nativeKey, const struct HksBlob *pubKey,
228 const struct HksKeySpec *spec, struct HksBlob *sharedKey)
229 {
230 if (HKS_KEY_BYTES(spec->keyLen) > sharedKey->size) {
231 return HKS_ERROR_BUFFER_TOO_SMALL;
232 }
233
234 struct KeyMaterialDh *pubKeyMaterial = (struct KeyMaterialDh *)pubKey->data;
235
236 mbedtls_dhm_context ctx;
237 (void)memset_s(&ctx, sizeof(mbedtls_dhm_context), 0, sizeof(mbedtls_dhm_context));
238 mbedtls_dhm_init(&ctx);
239
240 mbedtls_entropy_context entropy;
241 mbedtls_ctr_drbg_context ctrDrbg;
242 (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
243 (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
244 int32_t ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
245 if (ret != HKS_SUCCESS) {
246 mbedtls_dhm_free(&ctx);
247 return ret;
248 }
249
250 do {
251 ret = DhKeyMaterialToCtx(nativeKey, true, &ctx);
252 HKS_IF_NOT_SUCC_BREAK(ret)
253
254 ret = mbedtls_dhm_read_public(&ctx, pubKey->data + sizeof(struct KeyMaterialDh), pubKeyMaterial->pubKeySize);
255 if (ret != HKS_MBEDTLS_SUCCESS) {
256 HKS_LOG_E("mbedtls_dhm_read_public failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
257 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
258 break;
259 }
260
261 size_t keyLen;
262 ret =
263 mbedtls_dhm_calc_secret(&ctx, sharedKey->data, sharedKey->size, &keyLen, mbedtls_ctr_drbg_random, &ctrDrbg);
264 if (ret != HKS_MBEDTLS_SUCCESS) {
265 HKS_LOG_E("mbedtls_dhm_calc_secret failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
266 ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
267 break;
268 }
269 sharedKey->size = keyLen;
270 ret = HKS_SUCCESS;
271 } while (0);
272
273 mbedtls_dhm_free(&ctx);
274 mbedtls_ctr_drbg_free(&ctrDrbg);
275 mbedtls_entropy_free(&entropy);
276
277 return ret;
278 }
279 #endif
280
281 #endif