• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 USE_HISI_MBED
17 #define MBEDTLS_PRIVATE(member) member
18 #endif
19 
20 #ifdef HKS_CONFIG_FILE
21 #include HKS_CONFIG_FILE
22 #else
23 #include "hks_config.h"
24 #endif
25 
26 #ifdef _CUT_AUTHENTICATE_
27 #undef HKS_SUPPORT_X25519_C
28 #endif /* _CUT_AUTHENTICATE_ */
29 
30 #ifdef HKS_SUPPORT_X25519_C
31 
32 #include "hks_mbedtls_x25519.h"
33 
34 #include <mbedtls/bignum.h>
35 #include <mbedtls/ctr_drbg.h>
36 #include <mbedtls/ecdh.h>
37 #include <mbedtls/ecp.h>
38 #include <mbedtls/entropy.h>
39 #include <securec.h>
40 
41 #ifdef HKS_SUPPORT_ED25519_TO_X25519
42 #include "hks_crypto_adapter.h"
43 #endif
44 
45 #include "hks_log.h"
46 #include "hks_mbedtls_common.h"
47 #include "hks_mem.h"
48 #include "hks_template.h"
49 
50 #define HKS_X25519_KEY_BITS 256
51 #define HKS_X25519_KEY_BYTES 32
52 #define HASH512_OUT_SIZE 64
53 
54 struct HksCurveConstPara {
55     mbedtls_mpi mpiP;
56     mbedtls_mpi mpiOne;
57     mbedtls_mpi mpiD;
58     mbedtls_mpi mpiK;
59     mbedtls_mpi mpiCapitalA;
60     mbedtls_mpi mpiMinusA;
61     mbedtls_mpi mpiU;
62     mbedtls_mpi mpiQ;
63 };
64 
65 #ifdef HKS_SUPPORT_ED25519_TO_X25519
66 #define CURVE25519_KEY_BYTE_SIZE HKS_KEY_BYTES(HKS_CURVE25519_KEY_SIZE_256)
67 static const uint8_t g_hksCurveParamP[CURVE25519_KEY_BYTE_SIZE] = {
68     0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xed
70 };
71 
72 /* RFC 8032, one = 1 */
73 static const uint8_t g_hksCurveParamOne[CURVE25519_KEY_BYTE_SIZE] = {
74     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
76 };
77 
78 /* RFC 8032, A non-zero element in the finite field GF(p), not equal to 1 */
79 static const uint8_t g_hksCurveParamD[CURVE25519_KEY_BYTE_SIZE] = {
80     0xa3, 0x78, 0x59, 0x13, 0xca, 0x4d, 0xeb, 0x75, 0xab, 0xd8, 0x41, 0x41, 0x4d, 0x0a, 0x70, 0x00,
81     0x98, 0xe8, 0x79, 0x77, 0x79, 0x40, 0xc7, 0x8c, 0x73, 0xfe, 0x6f, 0x2b, 0xee, 0x6c, 0x03, 0x52
82 };
83 
84 /* RFC 8032, k = (p - 1) / 2 */
85 static const uint8_t g_hksCurveParamK[CURVE25519_KEY_BYTE_SIZE] = {
86     0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
87     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f
88 };
89 
90 /* RFC 8032, A = 486662 */
91 static const uint8_t g_hksCurveParamCapitalA[CURVE25519_KEY_BYTE_SIZE] = {
92     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x6d, 0x06
94 };
95 
96 /* RFC 8032, -A = -486662 */
97 static const uint8_t g_hksCurveParamMinusA[CURVE25519_KEY_BYTE_SIZE] = {
98     0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
99     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x92, 0xe7
100 };
101 
102 /* RFC 8032, u = 2 */
103 static const uint8_t g_hksCurveParamU[CURVE25519_KEY_BYTE_SIZE] = {
104     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02
106 };
107 
108 /* RFC 8032, q = endian_swap(k) */
109 static const uint8_t g_hksCurveParamQ[CURVE25519_KEY_BYTE_SIZE] = {
110     0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
111     0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf6
112 };
113 #endif
114 
X25519CheckKeyMaterialPubPriSize(const struct KeyMaterial25519 * keyMaterial)115 static int32_t X25519CheckKeyMaterialPubPriSize(const struct KeyMaterial25519 *keyMaterial)
116 {
117     if ((keyMaterial->pubKeySize > HKS_X25519_KEY_BYTES) ||
118         (keyMaterial->priKeySize > HKS_X25519_KEY_BYTES)) {
119         HKS_LOG_E("Invalid x25519 keyMaterial! pubKeySize = 0x%" LOG_PUBLIC "X, priKeySize = 0x%" LOG_PUBLIC "X",
120             keyMaterial->pubKeySize, keyMaterial->priKeySize);
121         return HKS_ERROR_INVALID_ARGUMENT;
122     }
123 
124     return HKS_SUCCESS;
125 }
126 
EndianSwap(uint8_t * pData,const int32_t length)127 static int32_t EndianSwap(uint8_t *pData, const int32_t length)
128 {
129     if ((pData == NULL) || (length <= 0)) {
130         HKS_LOG_E("Endian swap invalid input!");
131         return HKS_ERROR_INVALID_ARGUMENT;
132     }
133 
134     const int32_t end = length - 1;
135     const int32_t count = length / 2; /* 2: count is half of length */
136 
137     for (int32_t i = 0; i < count; ++i) {
138         uint8_t tmp = pData[i];
139         pData[i] = pData[end - i];
140         pData[end - i] = tmp;
141     }
142 
143     return HKS_SUCCESS;
144 }
145 
X25519CheckKeySize(const struct HksBlob * key,const struct KeyMaterial25519 * keyMaterial,bool isPubKey)146 static int32_t X25519CheckKeySize(const struct HksBlob *key, const struct KeyMaterial25519 *keyMaterial, bool isPubKey)
147 {
148     if (key->size < (sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize +
149         (isPubKey ? 0 : keyMaterial->priKeySize))) {
150         HKS_LOG_E("X25519 key size too small! key size = 0x%" LOG_PUBLIC "X", key->size);
151         return HKS_ERROR_INVALID_KEY_INFO;
152     }
153 
154     return HKS_SUCCESS;
155 }
156 
X25519CheckKeyMaterialSize(const struct HksBlob * priKey,const struct HksBlob * pubKey)157 static int32_t X25519CheckKeyMaterialSize(const struct HksBlob *priKey, const struct HksBlob *pubKey)
158 {
159     const struct KeyMaterial25519 *priKm = (struct KeyMaterial25519 *)(priKey->data);
160     const struct KeyMaterial25519 *pubKm = (struct KeyMaterial25519 *)(pubKey->data);
161 
162     /* x25519's keySize is fixed at 256, so don't need to check */
163     int32_t ret = X25519CheckKeyMaterialPubPriSize(priKm);
164     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid privateKey size")
165     ret = X25519CheckKeyMaterialPubPriSize(pubKm);
166     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "invalid publicKey size")
167 
168     ret = X25519CheckKeySize(priKey, priKm, false);
169     HKS_IF_NOT_SUCC_RETURN(ret, ret)
170 
171     return X25519CheckKeySize(pubKey, pubKm, true);
172 }
173 
174 #ifdef HKS_SUPPORT_X25519_GENERATE_KEY
X25519SaveKeyMaterial(const mbedtls_ecp_point * pub,const mbedtls_mpi * pri,struct HksBlob * key)175 static int32_t X25519SaveKeyMaterial(const mbedtls_ecp_point *pub,
176     const mbedtls_mpi *pri, struct HksBlob *key)
177 {
178     const uint32_t keyByteLen = HKS_X25519_KEY_BITS / HKS_BITS_PER_BYTE;
179     const uint32_t rawMaterialLen = sizeof(struct KeyMaterial25519) + keyByteLen + keyByteLen;
180     uint8_t *rawMaterial = (uint8_t *)HksMalloc(rawMaterialLen);
181     HKS_IF_NULL_RETURN(rawMaterial, HKS_ERROR_MALLOC_FAIL)
182     (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
183 
184     struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)rawMaterial;
185     keyMaterial->keyAlg = HKS_ALG_X25519;
186     keyMaterial->keySize = HKS_X25519_KEY_BITS;
187     keyMaterial->pubKeySize = keyByteLen;
188     keyMaterial->priKeySize = keyByteLen;
189 
190     /* mbedtls mbedtls_ecp_point.X is x25519's public key */
191     uint32_t offset = sizeof(struct KeyMaterial25519);
192     int32_t ret = mbedtls_mpi_write_binary(&(pub->MBEDTLS_PRIVATE(X)), rawMaterial + offset, keyMaterial->pubKeySize);
193     if (ret != HKS_MBEDTLS_SUCCESS) {
194         HKS_LOG_E("Mbedtls mpi write to x25519 public key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
195         (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
196         HKS_FREE(rawMaterial);
197         return ret;
198     }
199 
200     ret = EndianSwap(rawMaterial + offset, keyMaterial->pubKeySize);
201     if (ret != HKS_SUCCESS) {
202         (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
203         HKS_FREE(rawMaterial);
204         return ret;
205     }
206 
207     offset = offset + keyMaterial->pubKeySize;
208     ret = mbedtls_mpi_write_binary(pri, rawMaterial + offset, keyMaterial->priKeySize);
209     if (ret != HKS_MBEDTLS_SUCCESS) {
210         HKS_LOG_E("Mbedtls mpi write to x25519 private key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
211         (void)memset_s(rawMaterial, rawMaterialLen, 0, rawMaterialLen);
212         HKS_FREE(rawMaterial);
213         return ret;
214     }
215 
216     key->data = rawMaterial;
217     key->size = rawMaterialLen;
218 
219     return HKS_SUCCESS;
220 }
221 
HksMbedtlsX25519GenerateKey(const struct HksKeySpec * spec,struct HksBlob * key)222 int32_t HksMbedtlsX25519GenerateKey(const struct HksKeySpec *spec, struct HksBlob *key)
223 {
224     (void)spec;
225     mbedtls_ecp_group grp;
226     mbedtls_ecp_point pub;
227     mbedtls_mpi pri;
228 
229     mbedtls_ctr_drbg_context ctrDrbg;
230     mbedtls_entropy_context entropy;
231     (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
232     (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
233     int32_t ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
234     HKS_IF_NOT_SUCC_RETURN(ret, ret)
235 
236     mbedtls_ecp_group_init(&grp);
237     mbedtls_ecp_point_init(&pub);
238     mbedtls_mpi_init(&pri);
239 
240     do {
241         ret = mbedtls_ecp_group_load(&grp, MBEDTLS_ECP_DP_CURVE25519);
242         if (ret != HKS_MBEDTLS_SUCCESS) {
243             HKS_LOG_E("Mbedtls load x25519 group failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
244             break;
245         }
246 
247         ret = mbedtls_ecdh_gen_public(&grp, &pri, &pub, mbedtls_ctr_drbg_random, &ctrDrbg);
248         if (ret != HKS_MBEDTLS_SUCCESS) {
249             HKS_LOG_E("Mbedtls generate x25519 key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
250             break;
251         }
252 
253         ret = X25519SaveKeyMaterial(&pub, &pri, key);
254     } while (0);
255 
256     mbedtls_ecp_group_free(&grp);
257     mbedtls_ecp_point_free(&pub);
258     mbedtls_mpi_free(&pri);
259     mbedtls_ctr_drbg_free(&ctrDrbg);
260     mbedtls_entropy_free(&entropy);
261     return ret;
262 }
263 #endif /* HKS_SUPPORT_X25519_GENERATE_KEY */
264 
265 #ifdef HKS_SUPPORT_X25519_AGREE_KEY
X25519KeyMaterialToPub(const struct HksBlob * pubKey,mbedtls_ecp_point * pub)266 static int32_t X25519KeyMaterialToPub(const struct HksBlob *pubKey, mbedtls_ecp_point *pub)
267 {
268     const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(pubKey->data);
269     uint32_t offset = sizeof(struct KeyMaterial25519);
270 
271     uint8_t *tmpPubKey = (uint8_t *)HksMalloc(keyMaterial->pubKeySize);
272     HKS_IF_NULL_RETURN(tmpPubKey, HKS_ERROR_MALLOC_FAIL)
273 
274     int32_t ret;
275     do {
276         if (memcpy_s(tmpPubKey, keyMaterial->pubKeySize, pubKey->data + offset, keyMaterial->pubKeySize) != EOK) {
277             ret = HKS_ERROR_INSUFFICIENT_MEMORY;
278             break;
279         }
280 
281         ret = EndianSwap(tmpPubKey, keyMaterial->pubKeySize);
282         HKS_IF_NOT_SUCC_BREAK(ret)
283 
284         ret = mbedtls_mpi_read_binary(&(pub->MBEDTLS_PRIVATE(X)), tmpPubKey, keyMaterial->pubKeySize);
285         if (ret != HKS_MBEDTLS_SUCCESS) {
286             HKS_LOG_E("Mbedtls mpi read from x25519 public key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
287             break;
288         }
289 
290         /* set initial coordinates. Z = 1, X and Y are its standard(affine) coordinates. */
291         ret = mbedtls_mpi_lset(&(pub->MBEDTLS_PRIVATE(Z)), 1);
292         if (ret != HKS_MBEDTLS_SUCCESS) {
293             HKS_LOG_E("Mbedtls mpi set Z = 1 failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
294         }
295     } while (0);
296 
297     HKS_FREE(tmpPubKey);
298     return ret;
299 }
300 
X25519KeyMaterialToPri(const struct HksBlob * nativeKey,mbedtls_mpi * pri)301 static int32_t X25519KeyMaterialToPri(const struct HksBlob *nativeKey, mbedtls_mpi *pri)
302 {
303     const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(nativeKey->data);
304 
305     uint32_t offset = sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize;
306     int32_t ret = mbedtls_mpi_read_binary(pri, nativeKey->data + offset, keyMaterial->priKeySize);
307     if (ret != HKS_MBEDTLS_SUCCESS) {
308         HKS_LOG_E("Mbedtls mpi read from x25519 private key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
309         return ret;
310     }
311 
312     return HKS_SUCCESS;
313 }
314 
HksMbedtlsX25519KeyAgreement(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)315 int32_t HksMbedtlsX25519KeyAgreement(const struct HksBlob *nativeKey,
316     const struct HksBlob *pubKey, const struct HksKeySpec *spec, struct HksBlob *sharedKey)
317 {
318     (void)spec;
319     int32_t ret = X25519CheckKeyMaterialSize(nativeKey, pubKey);
320     HKS_IF_NOT_SUCC_RETURN(ret, ret)
321 
322     mbedtls_ecdh_context ctx;
323     (void)memset_s(&ctx, sizeof(mbedtls_ecdh_context), 0, sizeof(mbedtls_ecdh_context));
324     mbedtls_ecdh_init(&ctx);
325 
326     mbedtls_ctr_drbg_context ctrDrbg;
327     mbedtls_entropy_context entropy;
328     (void)memset_s(&entropy, sizeof(mbedtls_entropy_context), 0, sizeof(mbedtls_entropy_context));
329     (void)memset_s(&ctrDrbg, sizeof(mbedtls_ctr_drbg_context), 0, sizeof(mbedtls_ctr_drbg_context));
330     ret = HksCtrDrbgSeed(&ctrDrbg, &entropy);
331     if (ret != HKS_SUCCESS) {
332         mbedtls_ecdh_free(&ctx);
333         return ret;
334     }
335 
336     do {
337         ret = mbedtls_ecp_group_load(&(ctx.MBEDTLS_PRIVATE(grp)), MBEDTLS_ECP_DP_CURVE25519);
338         if (ret != HKS_MBEDTLS_SUCCESS) {
339             HKS_LOG_E("Mbedtls load x25519 group failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
340             break;
341         }
342 
343         ret = X25519KeyMaterialToPub(pubKey, &(ctx.MBEDTLS_PRIVATE(Qp)));
344         HKS_IF_NOT_SUCC_BREAK(ret)
345 
346         ret = X25519KeyMaterialToPri(nativeKey, &(ctx.MBEDTLS_PRIVATE(d)));
347         HKS_IF_NOT_SUCC_BREAK(ret)
348 
349         ret = mbedtls_ecdh_compute_shared(&(ctx.MBEDTLS_PRIVATE(grp)), &(ctx.MBEDTLS_PRIVATE(z)),
350             &(ctx.MBEDTLS_PRIVATE(Qp)), &(ctx.MBEDTLS_PRIVATE(d)), mbedtls_ctr_drbg_random, &ctrDrbg);
351         if (ret != HKS_MBEDTLS_SUCCESS) {
352             HKS_LOG_E("Mbedtls x25519 shared key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
353             break;
354         }
355 
356         ret = mbedtls_mpi_write_binary(&(ctx.MBEDTLS_PRIVATE(z)), sharedKey->data, HKS_X25519_KEY_BYTES);
357         if (ret != HKS_MBEDTLS_SUCCESS) {
358             HKS_LOG_E("Mbedtls mpi write to shared key failed! mbedtls ret = 0x%" LOG_PUBLIC "X", ret);
359             (void)memset_s(sharedKey->data, sharedKey->size, 0, sharedKey->size);
360             break;
361         }
362         sharedKey->size = HKS_X25519_KEY_BYTES;
363 
364         ret = EndianSwap(sharedKey->data, sharedKey->size);
365     } while (0);
366 
367     mbedtls_ecdh_free(&ctx);
368     mbedtls_ctr_drbg_free(&ctrDrbg);
369     mbedtls_entropy_free(&entropy);
370     return ret;
371 }
372 #endif /* HKS_SUPPORT_X25519_AGREE_KEY */
373 
374 #ifdef HKS_SUPPORT_X25519_GET_PUBLIC_KEY
GetX25519PubKeyCheckParams(const struct HksBlob * keyIn,const struct HksBlob * keyOut)375 static int32_t GetX25519PubKeyCheckParams(const struct HksBlob *keyIn, const struct HksBlob *keyOut)
376 {
377     const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(keyIn->data);
378     int32_t ret = X25519CheckKeyMaterialPubPriSize(keyMaterial);
379     HKS_IF_NOT_SUCC_RETURN(ret, ret)
380 
381     ret = X25519CheckKeySize(keyIn, keyMaterial, false);
382     HKS_IF_NOT_SUCC_RETURN(ret, ret)
383 
384     /* check keyOut */
385     if (keyOut->size < (sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize)) {
386         HKS_LOG_E("X25519 public keyOut size too small! keyOut size = 0x%" LOG_PUBLIC "X", keyOut->size);
387         return HKS_ERROR_BUFFER_TOO_SMALL;
388     }
389 
390     return HKS_SUCCESS;
391 }
392 
HksMbedtlsGetX25519PubKey(const struct HksBlob * keyIn,struct HksBlob * keyOut)393 int32_t HksMbedtlsGetX25519PubKey(const struct HksBlob *keyIn, struct HksBlob *keyOut)
394 {
395     int32_t ret = GetX25519PubKeyCheckParams(keyIn, keyOut);
396     HKS_IF_NOT_SUCC_RETURN(ret, ret)
397 
398     const struct KeyMaterial25519 *keyMaterial = (struct KeyMaterial25519 *)(keyIn->data);
399     const uint32_t outLen = sizeof(struct KeyMaterial25519) + keyMaterial->pubKeySize;
400     if (memcpy_s(keyOut->data, keyOut->size, (void *)keyMaterial, outLen) != EOK) {
401         HKS_LOG_E("Memcpy x25519 pub key failed!");
402         return HKS_ERROR_INSUFFICIENT_MEMORY;
403     }
404     ((struct KeyMaterial25519 *)(keyOut->data))->priKeySize = 0;
405     keyOut->size = outLen;
406 
407     return HKS_SUCCESS;
408 }
409 #endif /* HKS_SUPPORT_X25519_GET_PUBLIC_KEY */
410 
411 #if defined(HKS_SUPPORT_ED25519_TO_X25519)
HksCurveInitConstPara(struct HksCurveConstPara * para)412 static void HksCurveInitConstPara(struct HksCurveConstPara *para)
413 {
414     mbedtls_mpi_init(&(para->mpiP));
415     mbedtls_mpi_init(&(para->mpiOne));
416     mbedtls_mpi_init(&(para->mpiD));
417     mbedtls_mpi_init(&(para->mpiK));
418     mbedtls_mpi_init(&(para->mpiCapitalA));
419     mbedtls_mpi_init(&(para->mpiMinusA));
420     mbedtls_mpi_init(&(para->mpiU));
421     mbedtls_mpi_init(&(para->mpiQ));
422 }
423 
HksCurveFreeConstPara(struct HksCurveConstPara * para)424 static void HksCurveFreeConstPara(struct HksCurveConstPara *para)
425 {
426     mbedtls_mpi_free(&(para->mpiP));
427     mbedtls_mpi_free(&(para->mpiOne));
428     mbedtls_mpi_free(&(para->mpiD));
429     mbedtls_mpi_free(&(para->mpiK));
430     mbedtls_mpi_free(&(para->mpiCapitalA));
431     mbedtls_mpi_free(&(para->mpiMinusA));
432     mbedtls_mpi_free(&(para->mpiU));
433     mbedtls_mpi_free(&(para->mpiQ));
434 }
435 
HksCurveSetConstPara(struct HksCurveConstPara * para)436 static int32_t HksCurveSetConstPara(struct HksCurveConstPara *para)
437 {
438     int32_t ret = mbedtls_mpi_read_binary(&(para->mpiP), g_hksCurveParamP, CURVE25519_KEY_BYTE_SIZE);
439     if (ret != HKS_MBEDTLS_SUCCESS) {
440         return ret;
441     }
442 
443     ret = mbedtls_mpi_read_binary(&(para->mpiOne), g_hksCurveParamOne, CURVE25519_KEY_BYTE_SIZE);
444     if (ret != HKS_MBEDTLS_SUCCESS) {
445         return ret;
446     }
447 
448     ret = mbedtls_mpi_read_binary(&(para->mpiD), g_hksCurveParamD, CURVE25519_KEY_BYTE_SIZE);
449     if (ret != HKS_MBEDTLS_SUCCESS) {
450         return ret;
451     }
452 
453     ret = mbedtls_mpi_read_binary(&(para->mpiK), g_hksCurveParamK, CURVE25519_KEY_BYTE_SIZE);
454     if (ret != HKS_MBEDTLS_SUCCESS) {
455         return ret;
456     }
457 
458     ret = mbedtls_mpi_read_binary(&(para->mpiCapitalA), g_hksCurveParamCapitalA, CURVE25519_KEY_BYTE_SIZE);
459     if (ret != HKS_MBEDTLS_SUCCESS) {
460         return ret;
461     }
462 
463     ret = mbedtls_mpi_read_binary(&(para->mpiMinusA), g_hksCurveParamMinusA, CURVE25519_KEY_BYTE_SIZE);
464     if (ret != HKS_MBEDTLS_SUCCESS) {
465         return ret;
466     }
467 
468     ret = mbedtls_mpi_read_binary(&(para->mpiU), g_hksCurveParamU, CURVE25519_KEY_BYTE_SIZE);
469     if (ret != HKS_MBEDTLS_SUCCESS) {
470         return ret;
471     }
472 
473     ret = mbedtls_mpi_read_binary(&(para->mpiQ), g_hksCurveParamQ, CURVE25519_KEY_BYTE_SIZE);
474     if (ret != HKS_MBEDTLS_SUCCESS) {
475         return ret;
476     }
477 
478     return HKS_SUCCESS;
479 }
480 #endif /* HKS_SUPPORT_ED25519_TO_X25519 */
481 
482 #ifdef HKS_SUPPORT_ED25519_TO_X25519
483 struct HksEd25519ToX25519Blob {
484     struct HksBlob rawNativeKey;
485     struct HksBlob rawPubKey;
486     struct HksBlob rawX25519NativeKey;
487     struct HksBlob rawX25519PubKey;
488     struct HksBlob kmX25519NativeKey;
489     struct HksBlob kmX25519PubKey;
490 };
491 
HksCurvePskCalcA(const mbedtls_mpi * edwardsY,const struct HksCurveConstPara * curvePara,mbedtls_mpi * mpiA)492 static int32_t HksCurvePskCalcA(const mbedtls_mpi *edwardsY,
493     const struct HksCurveConstPara *curvePara, mbedtls_mpi *mpiA)
494 {
495     mbedtls_mpi mpiE;
496     mbedtls_mpi swap;
497 
498     mbedtls_mpi_init(&mpiE);
499     mbedtls_mpi_init(&swap);
500 
501     int32_t ret = HKS_ERROR_CRYPTO_ENGINE_ERROR;
502     do {
503         /* mpiA := (y ^ 2 - 1) / (1 + d * y ^ 2) */
504         if (mbedtls_mpi_mul_mpi(&mpiE, edwardsY, edwardsY) != HKS_MBEDTLS_SUCCESS) {
505             break;
506         }
507 
508         if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
509             break;
510         }
511 
512         if (mbedtls_mpi_mul_mpi(&swap, &(curvePara->mpiD), &mpiE) != HKS_MBEDTLS_SUCCESS) {
513             break;
514         }
515 
516         if (mbedtls_mpi_add_mpi(&swap, &swap, &(curvePara->mpiOne)) != HKS_MBEDTLS_SUCCESS) {
517             break;
518         }
519 
520         if (mbedtls_mpi_mod_mpi(&swap, &swap, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
521             break;
522         }
523 
524         if (mbedtls_mpi_inv_mod(&swap, &swap, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
525             break;
526         }
527 
528         if (mbedtls_mpi_sub_mpi(&mpiE, &mpiE, &(curvePara->mpiOne)) != HKS_MBEDTLS_SUCCESS) {
529             break;
530         }
531 
532         if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
533             break;
534         }
535 
536         if (mbedtls_mpi_mul_mpi(&mpiE, &mpiE, &swap) != HKS_MBEDTLS_SUCCESS) {
537             break;
538         }
539 
540         if (mbedtls_mpi_mod_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
541             break;
542         }
543 
544         if (mbedtls_mpi_add_mpi(&mpiE, &mpiE, &(curvePara->mpiP)) != HKS_MBEDTLS_SUCCESS) {
545             break;
546         }
547 
548         /* Sliding-window exponentiation: mpiA = e^k mod p */
549         ret = mbedtls_mpi_exp_mod(mpiA, &mpiE, &(curvePara->mpiK), &(curvePara->mpiP), NULL);
550     } while (0);
551 
552     mbedtls_mpi_free(&mpiE);
553     mbedtls_mpi_free(&swap);
554 
555     return ret;
556 }
557 
HksCurvePskCheckA(mbedtls_mpi * mpiA,const uint8_t * ed25519PublicKey,size_t len,const struct HksCurveConstPara * curvePara)558 static int32_t HksCurvePskCheckA(mbedtls_mpi *mpiA, const uint8_t *ed25519PublicKey,
559     size_t len, const struct HksCurveConstPara *curvePara)
560 {
561     /* Check, whether a is a square modulo p (including a = 0) */
562     int32_t ret = mbedtls_mpi_cmp_mpi(&(curvePara->mpiOne), mpiA);
563     if (ret > 0) {
564         HKS_LOG_E("a is not a square modulo p");
565         return HKS_ERROR_INVALID_PUBLIC_KEY;
566     }
567 
568     /* If a == p, the parity bit must be 0 */
569     ret = mbedtls_mpi_cmp_mpi(mpiA, &(curvePara->mpiP));
570     if (ret == 0) {
571         uint32_t value = ed25519PublicKey[len - 1] >> 7; /* 7: RFC8032 */
572         /* The previous check has guaranteed that a must be greater than or equal to one */
573         value = (value & (uint32_t)mbedtls_mpi_sub_mpi(mpiA, mpiA, &(curvePara->mpiOne)));
574         if (value != 0) {
575             HKS_LOG_E("the parity bit not zero");
576             return HKS_ERROR_INVALID_PUBLIC_KEY;
577         }
578     }
579 
580     return HKS_SUCCESS;
581 }
582 
HksCurvePskCheckPoint(const mbedtls_mpi * edwardsY,const uint8_t * ed25519PublicKey,size_t len,const struct HksCurveConstPara * curvePara)583 static int32_t HksCurvePskCheckPoint(const mbedtls_mpi *edwardsY, const uint8_t *ed25519PublicKey,
584     size_t len, const struct HksCurveConstPara *curvePara)
585 {
586     mbedtls_mpi mpiA;
587     mbedtls_mpi_init(&mpiA);
588 
589     int32_t ret;
590     do {
591         /* if y >= p, return error */
592         ret = mbedtls_mpi_cmp_mpi(edwardsY, &(curvePara->mpiP));
593         if (ret >= 0) {
594             HKS_LOG_E("edwardsY is greater than or equal to p, ret is %" LOG_PUBLIC "d", ret);
595             ret = HKS_ERROR_INVALID_PUBLIC_KEY;
596             break;
597         }
598 
599         /* if y == 1, return error */
600         ret = mbedtls_mpi_cmp_mpi(edwardsY, &(curvePara->mpiOne));
601         if (ret == 0) {
602             HKS_LOG_E("edwards_y equals one");
603             ret = HKS_ERROR_INVALID_PUBLIC_KEY;
604             break;
605         }
606 
607         /* a := (y ^ 2 - 1) / (1 + d * y ^ 2) */
608         ret = HksCurvePskCalcA(edwardsY, curvePara, &mpiA);
609         if (ret != HKS_SUCCESS)
610             break;
611 
612         ret = HksCurvePskCheckA(&mpiA, ed25519PublicKey, len, curvePara);
613     } while (0);
614 
615     mbedtls_mpi_free(&mpiA);
616     return ret;
617 }
618 
HksCurvePskCalcC(const mbedtls_mpi * edwardsY,struct HksBlob * x25519Key,const struct HksCurveConstPara * curvePara)619 static int32_t HksCurvePskCalcC(const mbedtls_mpi *edwardsY, struct HksBlob *x25519Key,
620     const struct HksCurveConstPara *curvePara)
621 {
622     mbedtls_mpi curveX;
623     mbedtls_mpi result;
624 
625     mbedtls_mpi_init(&curveX);
626     mbedtls_mpi_init(&result);
627 
628     int32_t ret;
629     do {
630         /* If y != 1, c := (1 + y) / (1 - y), otherwise c := 0 */
631         ret = mbedtls_mpi_sub_mpi(&result, &(curvePara->mpiOne), edwardsY);
632         if (ret != HKS_MBEDTLS_SUCCESS) {
633             break;
634         }
635 
636         ret = mbedtls_mpi_mod_mpi(&result, &result, &(curvePara->mpiP));
637         if (ret != HKS_MBEDTLS_SUCCESS) {
638             break;
639         }
640 
641         ret = mbedtls_mpi_inv_mod(&result, &result, &(curvePara->mpiP));
642         if (ret != HKS_MBEDTLS_SUCCESS) {
643             break;
644         }
645 
646         ret = mbedtls_mpi_add_mpi(&curveX, &(curvePara->mpiOne), edwardsY);
647         if (ret != HKS_MBEDTLS_SUCCESS) {
648             break;
649         }
650 
651         ret = mbedtls_mpi_mul_mpi(&result, &curveX, &result);
652         if (ret != HKS_MBEDTLS_SUCCESS) {
653             break;
654         }
655 
656         ret = mbedtls_mpi_mod_mpi(&result, &result, &(curvePara->mpiP));
657         if (ret != HKS_MBEDTLS_SUCCESS) {
658             break;
659         }
660 
661         ret = mbedtls_mpi_write_binary(&result, x25519Key->data, x25519Key->size);
662     } while (0);
663 
664     mbedtls_mpi_free(&curveX);
665     mbedtls_mpi_free(&result);
666 
667     return ret;
668 }
669 
ConvertPublicKey(const struct HksBlob * publicKeyIn,struct HksBlob * x25519PublicKey)670 static int32_t ConvertPublicKey(const struct HksBlob *publicKeyIn, struct HksBlob *x25519PublicKey)
671 {
672     /* RFC 8032 */
673     publicKeyIn->data[publicKeyIn->size - 1] = publicKeyIn->data[publicKeyIn->size - 1] & 0x7f;
674     int32_t ret = EndianSwap(publicKeyIn->data, publicKeyIn->size);
675     HKS_IF_NOT_SUCC_RETURN(ret, ret)
676 
677     mbedtls_mpi edwardsY;
678     struct HksCurveConstPara curvePara;
679 
680     mbedtls_mpi_init(&edwardsY);
681     HksCurveInitConstPara(&curvePara);
682 
683     do {
684         ret = HksCurveSetConstPara(&curvePara);
685         HKS_IF_NOT_SUCC_BREAK(ret)
686 
687         ret = mbedtls_mpi_read_binary(&edwardsY, publicKeyIn->data, publicKeyIn->size);
688         if (ret != HKS_MBEDTLS_SUCCESS) {
689             break;
690         }
691 
692         ret = HksCurvePskCheckPoint(&edwardsY, publicKeyIn->data, publicKeyIn->size, &curvePara);
693         HKS_IF_NOT_SUCC_BREAK(ret)
694 
695         x25519PublicKey->size = CURVE25519_KEY_BYTE_SIZE;
696         x25519PublicKey->data = (uint8_t *)HksMalloc(x25519PublicKey->size);
697         if (x25519PublicKey->data == NULL) {
698             HKS_LOG_E("malloc failed");
699             ret = HKS_ERROR_MALLOC_FAIL;
700             break;
701         }
702 
703         ret = HksCurvePskCalcC(&edwardsY, x25519PublicKey, &curvePara);
704         HKS_IF_NOT_SUCC_BREAK(ret)
705 
706         ret = EndianSwap(x25519PublicKey->data, x25519PublicKey->size);
707     } while (0);
708 
709     HksCurveFreeConstPara(&curvePara);
710     mbedtls_mpi_free(&edwardsY);
711     if ((ret != HKS_SUCCESS) && (x25519PublicKey->data != NULL)) {
712         (void)memset_s(x25519PublicKey->data, x25519PublicKey->size, 0, x25519PublicKey->size);
713         HKS_FREE_BLOB(*x25519PublicKey);
714     }
715 
716     return ret;
717 }
718 
ConvertPrivateKey(const struct HksBlob * privateKeyIn,struct HksBlob * x25519PrivateKey)719 static int32_t ConvertPrivateKey(const struct HksBlob *privateKeyIn, struct HksBlob *x25519PrivateKey)
720 {
721     uint8_t hash512Data[HASH512_OUT_SIZE] = {0};
722     struct HksBlob hash512 = { HASH512_OUT_SIZE, hash512Data };
723 
724     /* Get 32-bit private key data as the hash input parameter (little endian) */
725     int32_t ret = HksCryptoHalHash(HKS_DIGEST_SHA512, privateKeyIn, &hash512);
726     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret, "convert private key calc hash failed")
727 
728     x25519PrivateKey->size = CURVE25519_KEY_BYTE_SIZE;
729     x25519PrivateKey->data = (uint8_t *)HksMalloc(x25519PrivateKey->size);
730     HKS_IF_NULL_LOGE_RETURN(x25519PrivateKey->data, HKS_ERROR_MALLOC_FAIL, "malloc failed")
731 
732     do {
733         /* Get the first 32 bytes of the hash value (little endian) */
734         if (memcpy_s(x25519PrivateKey->data, x25519PrivateKey->size, hash512.data, CURVE25519_KEY_BYTE_SIZE) != EOK) {
735             ret = HKS_ERROR_INSUFFICIENT_MEMORY;
736             break;
737         }
738 
739         x25519PrivateKey->data[0] &= 248;  /* 248: RFC 8032 */
740         x25519PrivateKey->data[x25519PrivateKey->size - 1] &= 127; /* 127: RFC 8032 */
741         x25519PrivateKey->data[x25519PrivateKey->size - 1] |= 64; /* 64: RFC 8032 */
742 
743         ret = EndianSwap(x25519PrivateKey->data, x25519PrivateKey->size);
744     } while (0);
745 
746     if ((ret != HKS_SUCCESS) && (x25519PrivateKey->data != NULL)) {
747         (void)memset_s(x25519PrivateKey->data, x25519PrivateKey->size, 0, x25519PrivateKey->size);
748         HKS_FREE_BLOB(*x25519PrivateKey);
749     }
750     return ret;
751 }
752 
MbedtlsEd25519KeyToX25519(const struct HksBlob * ed25519NativeKey,const struct HksBlob * ed25519PubKey,struct HksBlob * x25519NativeKey,struct HksBlob * x25519PubKey)753 int32_t MbedtlsEd25519KeyToX25519(const struct HksBlob *ed25519NativeKey,
754     const struct HksBlob *ed25519PubKey, struct HksBlob *x25519NativeKey, struct HksBlob *x25519PubKey)
755 {
756     int32_t ret = ConvertPublicKey(ed25519PubKey, x25519PubKey);
757     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
758         "convert ed25519 public key to x25519 public key failed! ret = %" LOG_PUBLIC "d", ret)
759 
760     HKS_IF_NOT_SUCC_LOGE_RETURN(ret, ret,
761     "convert ed25519 private key to x25519 private key failed! ret = %" LOG_PUBLIC "d", ret)
762 
763     ret = ConvertPrivateKey(ed25519NativeKey, x25519NativeKey);
764 
765     return HKS_SUCCESS;
766 }
767 
HksFreeKeyInfo(struct HksEd25519ToX25519Blob * key)768 void HksFreeKeyInfo(struct HksEd25519ToX25519Blob *key)
769 {
770     if (key->rawNativeKey.data != NULL) {
771         (void)memset_s(key->rawNativeKey.data, key->rawNativeKey.size, 0, key->rawNativeKey.size);
772         HKS_FREE(key->rawNativeKey.data);
773     }
774     if (key->rawPubKey.data != NULL) {
775         (void)memset_s(key->rawPubKey.data, key->rawPubKey.size, 0, key->rawPubKey.size);
776         HKS_FREE(key->rawPubKey.data);
777     }
778     if (key->rawX25519NativeKey.data != NULL) {
779         (void)memset_s(key->rawX25519NativeKey.data, key->rawX25519NativeKey.size, 0, key->rawX25519NativeKey.size);
780         HKS_FREE(key->rawX25519NativeKey.data);
781     }
782     if (key->rawX25519PubKey.data != NULL) {
783         (void)memset_s(key->rawX25519PubKey.data, key->rawX25519PubKey.size, 0, key->rawX25519PubKey.size);
784         HKS_FREE(key->rawX25519PubKey.data);
785     }
786     if (key->kmX25519NativeKey.data != NULL) {
787         (void)memset_s(key->kmX25519NativeKey.data, key->kmX25519NativeKey.size, 0, key->kmX25519NativeKey.size);
788         HKS_FREE(key->kmX25519NativeKey.data);
789     }
790     if (key->kmX25519PubKey.data != NULL) {
791         (void)memset_s(key->kmX25519PubKey.data, key->kmX25519PubKey.size, 0, key->kmX25519PubKey.size);
792         HKS_FREE(key->kmX25519PubKey.data);
793     }
794 }
795 
HksMbedtlsEd25519KeyAgreement(const struct HksBlob * nativeKey,const struct HksBlob * pubKey,const struct HksKeySpec * spec,struct HksBlob * sharedKey)796 int32_t HksMbedtlsEd25519KeyAgreement(const struct HksBlob *nativeKey,
797     const struct HksBlob *pubKey, const struct HksKeySpec *spec, struct HksBlob *sharedKey)
798 {
799     (void)spec;
800     int32_t ret = X25519CheckKeyMaterialSize(nativeKey, pubKey);
801     HKS_IF_NOT_SUCC_RETURN(ret, ret)
802 
803     struct HksEd25519ToX25519Blob key;
804     (void)memset_s(&key, sizeof(key), 0, sizeof(key));
805 
806     do {
807         ret = HksGetKeyFromMaterial(HKS_ALG_ED25519, false, nativeKey, &(key.rawNativeKey));
808         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get private key from material failed, ret = 0x%" LOG_PUBLIC "X", ret)
809         ret = HksGetKeyFromMaterial(HKS_ALG_ED25519, true, pubKey, &(key.rawPubKey));
810         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "get public key from material failed, ret = 0x%" LOG_PUBLIC "X", ret)
811 
812         ret = MbedtlsEd25519KeyToX25519(&(key.rawNativeKey), &(key.rawPubKey),
813             &(key.rawX25519NativeKey), &(key.rawX25519PubKey));
814         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "covert from ed25519 to x25519 failed, ret = 0x%" LOG_PUBLIC "X", ret)
815 
816         ret = HksSetKeyToMaterial(HKS_ALG_X25519, false, &(key.rawX25519NativeKey), &(key.kmX25519NativeKey));
817         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set private key to material failed, ret = 0x%" LOG_PUBLIC "X", ret)
818 
819         ret = HksSetKeyToMaterial(HKS_ALG_X25519, true, &(key.rawX25519PubKey), &(key.kmX25519PubKey));
820         HKS_IF_NOT_SUCC_LOGE_BREAK(ret, "set publicy key to material failed, ret = 0x%" LOG_PUBLIC "X", ret)
821 
822         ret = HksMbedtlsX25519KeyAgreement(&(key.kmX25519NativeKey), &(key.kmX25519PubKey), NULL, sharedKey);
823     } while (0);
824 
825     HksFreeKeyInfo(&key);
826     return ret;
827 }
828 #endif
829 
830 #endif /* HKS_SUPPORT_X25519_C */
831