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, &paramP, &paramG);
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, &paramP, &paramG);
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