• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * This file is part of the openHiTLS project.
3  *
4  * openHiTLS is licensed under the Mulan PSL v2.
5  * You can use this software according to the terms and conditions of the Mulan PSL v2.
6  * You may obtain a copy of Mulan PSL v2 at:
7  *
8  *     http://license.coscl.org.cn/MulanPSL2
9  *
10  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13  * See the Mulan PSL v2 for more details.
14  */
15 
16 #include "hitls_build.h"
17 #ifdef HITLS_CRYPTO_CURVE25519
18 
19 #include "securec.h"
20 #include "bsl_sal.h"
21 #include "bsl_err_internal.h"
22 #include "crypt_errno.h"
23 #include "crypt_utils.h"
24 #include "curve25519_local.h"
25 #include "crypt_util_rand.h"
26 #include "crypt_types.h"
27 #include "eal_md_local.h"
28 #include "crypt_params_key.h"
29 
30 #ifdef HITLS_CRYPTO_X25519
CRYPT_X25519_NewCtx(void)31 CRYPT_CURVE25519_Ctx *CRYPT_X25519_NewCtx(void)
32 {
33     CRYPT_CURVE25519_Ctx *ctx = NULL;
34     ctx = (CRYPT_CURVE25519_Ctx *)BSL_SAL_Malloc(sizeof(CRYPT_CURVE25519_Ctx));
35     if (ctx == NULL) {
36         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
37         return NULL;
38     }
39     (void)memset_s(ctx, sizeof(CRYPT_CURVE25519_Ctx), 0, sizeof(CRYPT_CURVE25519_Ctx));
40 
41     ctx->keyType = CURVE25519_NOKEY;
42     ctx->hashMethod = NULL;
43     BSL_SAL_ReferencesInit(&(ctx->references));
44     return ctx;
45 }
46 
CRYPT_X25519_NewCtxEx(void * libCtx)47 CRYPT_CURVE25519_Ctx *CRYPT_X25519_NewCtxEx(void *libCtx)
48 {
49     CRYPT_CURVE25519_Ctx *ctx = CRYPT_X25519_NewCtx();
50     if (ctx == NULL) {
51         return NULL;
52     }
53     ctx->libCtx = libCtx;
54     return ctx;
55 }
56 #endif
57 
58 #ifdef HITLS_CRYPTO_ED25519
CRYPT_ED25519_NewCtx(void)59 CRYPT_CURVE25519_Ctx *CRYPT_ED25519_NewCtx(void)
60 {
61     CRYPT_CURVE25519_Ctx *ctx = NULL;
62     ctx = (CRYPT_CURVE25519_Ctx *)BSL_SAL_Malloc(sizeof(CRYPT_CURVE25519_Ctx));
63     if (ctx == NULL) {
64         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
65         return NULL;
66     }
67     (void)memset_s(ctx, sizeof(CRYPT_CURVE25519_Ctx), 0, sizeof(CRYPT_CURVE25519_Ctx));
68 
69     ctx->hashMethod = EAL_MdFindMethod(CRYPT_MD_SHA512);
70     if (ctx->hashMethod == NULL) {
71         CRYPT_CURVE25519_FreeCtx(ctx);
72         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
73         return NULL;
74     }
75     ctx->keyType = CURVE25519_NOKEY;
76     BSL_SAL_ReferencesInit(&(ctx->references));
77     return ctx;
78 }
79 
CRYPT_ED25519_NewCtxEx(void * libCtx)80 CRYPT_CURVE25519_Ctx *CRYPT_ED25519_NewCtxEx(void *libCtx)
81 {
82     CRYPT_CURVE25519_Ctx *ctx = CRYPT_ED25519_NewCtx();
83     if (ctx == NULL) {
84         return NULL;
85     }
86     ctx->libCtx = libCtx;
87     return ctx;
88 }
89 #endif
90 
CRYPT_CURVE25519_DupCtx(CRYPT_CURVE25519_Ctx * ctx)91 CRYPT_CURVE25519_Ctx *CRYPT_CURVE25519_DupCtx(CRYPT_CURVE25519_Ctx *ctx)
92 {
93     if (ctx == NULL) {
94         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
95         return NULL;
96     }
97 
98     CRYPT_CURVE25519_Ctx *newCtx = NULL;
99     newCtx = (CRYPT_CURVE25519_Ctx *)BSL_SAL_Malloc(sizeof(CRYPT_CURVE25519_Ctx));
100     if (newCtx == NULL) {
101         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
102         return NULL;
103     }
104 
105     (void)memcpy_s(newCtx, sizeof(CRYPT_CURVE25519_Ctx), ctx, sizeof(CRYPT_CURVE25519_Ctx));
106     BSL_SAL_ReferencesInit(&(newCtx->references));
107     return newCtx;
108 }
109 
CRYPT_CURVE25519_GetLen(CRYPT_CURVE25519_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)110 static int32_t CRYPT_CURVE25519_GetLen(CRYPT_CURVE25519_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
111 {
112     if (val == NULL || len != sizeof(int32_t)) {
113         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
114         return CRYPT_NULL_INPUT;
115     }
116 
117     *(int32_t *)val = func(ctx);
118     return CRYPT_SUCCESS;
119 }
120 
CRYPT_CURVE25519_GetKeyLen(const CRYPT_CURVE25519_Ctx * pkey)121 static int32_t CRYPT_CURVE25519_GetKeyLen(const CRYPT_CURVE25519_Ctx *pkey)
122 {
123     (void)pkey;
124     return CRYPT_CURVE25519_KEYLEN;
125 }
126 
CRYPT_CURVE25519_Ctrl(CRYPT_CURVE25519_Ctx * pkey,int32_t opt,void * val,uint32_t len)127 int32_t CRYPT_CURVE25519_Ctrl(CRYPT_CURVE25519_Ctx *pkey, int32_t opt, void *val, uint32_t len)
128 {
129     if (pkey == NULL) {
130         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
131         return CRYPT_NULL_INPUT;
132     }
133     switch (opt) {
134         case CRYPT_CTRL_GET_BITS:
135             return CRYPT_CURVE25519_GetLen(pkey, (GetLenFunc)CRYPT_CURVE25519_GetBits, val, len);
136 #ifdef HITLS_CRYPTO_ED25519
137         case CRYPT_CTRL_GET_SIGNLEN:
138             return CRYPT_CURVE25519_GetLen(pkey, (GetLenFunc)CRYPT_CURVE25519_GetSignLen, val, len);
139 #endif
140         case CRYPT_CTRL_GET_SECBITS:
141             return CRYPT_CURVE25519_GetLen(pkey, (GetLenFunc)CRYPT_CURVE25519_GetSecBits, val, len);
142         case CRYPT_CTRL_GET_PUBKEY_LEN:
143         case CRYPT_CTRL_GET_PRVKEY_LEN:
144         case CRYPT_CTRL_GET_SHARED_KEY_LEN:
145             return GetUintCtrl(pkey, val, len, (GetUintCallBack)CRYPT_CURVE25519_GetKeyLen);
146         case CRYPT_CTRL_UP_REFERENCES:
147             if (val == NULL || len != (uint32_t)sizeof(int)) {
148                 BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
149                 return CRYPT_INVALID_ARG;
150             }
151             return BSL_SAL_AtomicUpReferences(&(pkey->references), (int *)val);
152 #ifdef HITLS_CRYPTO_X25519
153         case CRYPT_CTRL_GEN_X25519_PUBLICKEY:
154             if ((pkey->keyType & CURVE25519_PUBKEY) != 0) {
155                 return CRYPT_SUCCESS;
156             }
157             if ((pkey->keyType & CURVE25519_PRVKEY) == 0) {
158                 BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PRVKEY);
159                 return CRYPT_CURVE25519_NO_PRVKEY;
160             }
161             CRYPT_X25519_PublicFromPrivate(pkey->prvKey, pkey->pubKey);
162             pkey->keyType |= CURVE25519_PUBKEY;
163             return CRYPT_SUCCESS;
164 #endif
165         default:
166             break;
167     }
168     BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_UNSUPPORTED_CTRL_OPTION);
169     return CRYPT_CURVE25519_UNSUPPORTED_CTRL_OPTION;
170 }
171 
CRYPT_CURVE25519_FreeCtx(CRYPT_CURVE25519_Ctx * pkey)172 void CRYPT_CURVE25519_FreeCtx(CRYPT_CURVE25519_Ctx *pkey)
173 {
174     if (pkey == NULL) {
175         return;
176     }
177     int ret = 0;
178     BSL_SAL_AtomicDownReferences(&(pkey->references), &ret);
179     if (ret > 0) {
180         return;
181     }
182     BSL_SAL_ReferencesFree(&(pkey->references));
183     BSL_SAL_CleanseData((void *)(pkey), sizeof(CRYPT_CURVE25519_Ctx));
184     BSL_SAL_FREE(pkey);
185 }
186 
CRYPT_CURVE25519_SetPubKey(CRYPT_CURVE25519_Ctx * pkey,const BSL_Param * para)187 int32_t CRYPT_CURVE25519_SetPubKey(CRYPT_CURVE25519_Ctx *pkey, const BSL_Param *para)
188 {
189     if (pkey == NULL || para == NULL) {
190         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
191         return CRYPT_NULL_INPUT;
192     }
193     // assume that the two scenarios will not coexist.
194     const BSL_Param *pub = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_CURVE25519_PUBKEY);
195     if (pub == NULL) {
196         pub = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
197     }
198 
199     if (pub == NULL || pub->value == NULL) {
200         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
201         return CRYPT_NULL_INPUT;
202     }
203     if (pub->valueLen != CRYPT_CURVE25519_KEYLEN) {
204         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEYLEN_ERROR);
205         return CRYPT_CURVE25519_KEYLEN_ERROR;
206     }
207 
208     /* The keyLen has been checked and does not have the overlong problem.
209        The pkey memory is dynamically allocated and does not overlap with the pubkey memory. */
210     /* There is no failure case for memcpy_s. */
211     (void)memcpy_s(pkey->pubKey, CRYPT_CURVE25519_KEYLEN, pub->value, pub->valueLen);
212     pkey->keyType |= CURVE25519_PUBKEY;
213 
214     return CRYPT_SUCCESS;
215 }
216 
CRYPT_CURVE25519_SetPrvKey(CRYPT_CURVE25519_Ctx * pkey,const BSL_Param * para)217 int32_t CRYPT_CURVE25519_SetPrvKey(CRYPT_CURVE25519_Ctx *pkey, const BSL_Param *para)
218 {
219     if (pkey == NULL || para == NULL) {
220         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
221         return CRYPT_NULL_INPUT;
222     }
223     const BSL_Param *prv = BSL_PARAM_FindConstParam(para, CRYPT_PARAM_CURVE25519_PRVKEY);
224     if (prv == NULL || prv->value == NULL) {
225         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
226         return CRYPT_NULL_INPUT;
227     }
228     if (prv->valueLen != CRYPT_CURVE25519_KEYLEN) {
229         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEYLEN_ERROR);
230         return CRYPT_CURVE25519_KEYLEN_ERROR;
231     }
232 
233     /* The keyLen has been checked and does not have the overlong problem.
234        The pkey memory is dynamically allocated and does not overlap with the pubkey memory. */
235     /* There is no failure case for memcpy_s. */
236     (void)memcpy_s(pkey->prvKey, CRYPT_CURVE25519_KEYLEN, prv->value, prv->valueLen);
237     pkey->keyType |= CURVE25519_PRVKEY;
238 
239     return CRYPT_SUCCESS;
240 }
241 
CRYPT_CURVE25519_GetPubKey(const CRYPT_CURVE25519_Ctx * pkey,BSL_Param * para)242 int32_t CRYPT_CURVE25519_GetPubKey(const CRYPT_CURVE25519_Ctx *pkey, BSL_Param *para)
243 {
244     if (pkey == NULL || para == NULL) {
245         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
246         return CRYPT_NULL_INPUT;
247     }
248     // assume that the two scenarios will not coexist.
249     BSL_Param *pub = BSL_PARAM_FindParam(para, CRYPT_PARAM_CURVE25519_PUBKEY);
250     if (pub == NULL) {
251         pub = BSL_PARAM_FindParam(para, CRYPT_PARAM_PKEY_ENCODE_PUBKEY);
252     }
253     if (pub == NULL || pub->value == NULL) {
254         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
255         return CRYPT_NULL_INPUT;
256     }
257     if (pub->valueLen < CRYPT_CURVE25519_KEYLEN) {
258         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEYLEN_ERROR);
259         return CRYPT_CURVE25519_KEYLEN_ERROR;
260     }
261 
262     if ((pkey->keyType & CURVE25519_PUBKEY) == 0) {
263         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PUBKEY);
264         return CRYPT_CURVE25519_NO_PUBKEY;
265     }
266 
267     /* The keyLen has been checked and does not have the overlong problem.
268        The pkey memory is dynamically allocated and does not overlap with the pubkey memory. */
269     /* There is no failure case for memcpy_s. */
270     (void)memcpy_s(pub->value, pub->valueLen, pkey->pubKey, CRYPT_CURVE25519_KEYLEN);
271 
272     pub->useLen = CRYPT_CURVE25519_KEYLEN;
273     return CRYPT_SUCCESS;
274 }
275 
CRYPT_CURVE25519_GetPrvKey(const CRYPT_CURVE25519_Ctx * pkey,BSL_Param * para)276 int32_t CRYPT_CURVE25519_GetPrvKey(const CRYPT_CURVE25519_Ctx *pkey, BSL_Param *para)
277 {
278     if (pkey == NULL || para == NULL) {
279         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
280         return CRYPT_NULL_INPUT;
281     }
282     BSL_Param *prv = BSL_PARAM_FindParam(para, CRYPT_PARAM_CURVE25519_PRVKEY);
283     if (prv == NULL || prv->value == NULL) {
284         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
285         return CRYPT_NULL_INPUT;
286     }
287     if (prv->valueLen < CRYPT_CURVE25519_KEYLEN) {
288         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEYLEN_ERROR);
289         return CRYPT_CURVE25519_KEYLEN_ERROR;
290     }
291 
292     if ((pkey->keyType & CURVE25519_PRVKEY) == 0) {
293         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PRVKEY);
294         return CRYPT_CURVE25519_NO_PRVKEY;
295     }
296 
297     /* The keyLen has been checked and does not have the overlong problem.
298        The pkey memory is dynamically allocated and does not overlap with the pubkey memory. */
299     /* There is no failure case for memcpy_s. */
300     (void)memcpy_s(prv->value, prv->valueLen, pkey->prvKey, CRYPT_CURVE25519_KEYLEN);
301 
302     prv->useLen = CRYPT_CURVE25519_KEYLEN;
303     return CRYPT_SUCCESS;
304 }
305 
CRYPT_CURVE25519_GetBits(const CRYPT_CURVE25519_Ctx * pkey)306 int32_t CRYPT_CURVE25519_GetBits(const CRYPT_CURVE25519_Ctx *pkey)
307 {
308     (void)pkey;
309     return CRYPT_CURVE25519_KEYLEN * 8; // bits = 8 * bytes
310 }
311 
312 #ifdef HITLS_CRYPTO_ED25519
PrvKeyHash(const uint8_t * prvKey,uint32_t prvKeyLen,uint8_t * prvKeyHash,uint32_t prvHashLen,const EAL_MdMethod * hashMethod)313 static int32_t PrvKeyHash(const uint8_t *prvKey, uint32_t prvKeyLen, uint8_t *prvKeyHash, uint32_t prvHashLen,
314     const EAL_MdMethod *hashMethod)
315 {
316     void *mdCtx = NULL;
317     int32_t ret;
318     uint32_t hashLen = prvHashLen;
319 
320     mdCtx = hashMethod->newCtx();
321     if (mdCtx == NULL) {
322         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
323         return CRYPT_MEM_ALLOC_FAIL;
324     }
325 
326     ret = hashMethod->init(mdCtx, NULL);
327     if (ret != CRYPT_SUCCESS) {
328         BSL_ERR_PUSH_ERROR(ret);
329         goto EXIT;
330     }
331 
332     ret = hashMethod->update(mdCtx, prvKey, prvKeyLen);
333     if (ret != CRYPT_SUCCESS) {
334         BSL_ERR_PUSH_ERROR(ret);
335         goto EXIT;
336     }
337 
338     ret = hashMethod->final(mdCtx, prvKeyHash, &hashLen);
339     if (ret != CRYPT_SUCCESS) {
340         BSL_ERR_PUSH_ERROR(ret);
341     }
342 
343 EXIT:
344     hashMethod->freeCtx(mdCtx);
345     return ret;
346 }
347 
GetRHash(uint8_t r[CRYPT_CURVE25519_SIGNLEN],const uint8_t prefix[CRYPT_CURVE25519_KEYLEN],const uint8_t * msg,uint32_t msgLen,const EAL_MdMethod * hashMethod)348 static int32_t GetRHash(uint8_t r[CRYPT_CURVE25519_SIGNLEN], const uint8_t prefix[CRYPT_CURVE25519_KEYLEN],
349     const uint8_t *msg, uint32_t msgLen, const EAL_MdMethod *hashMethod)
350 {
351     void *mdCtx = NULL;
352     int32_t ret;
353     uint32_t hashLen = CRYPT_CURVE25519_SIGNLEN;
354 
355     mdCtx = hashMethod->newCtx();
356     if (mdCtx == NULL) {
357         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
358         return CRYPT_MEM_ALLOC_FAIL;
359     }
360 
361     ret = hashMethod->init(mdCtx, NULL);
362     if (ret != CRYPT_SUCCESS) {
363         BSL_ERR_PUSH_ERROR(ret);
364         goto EXIT;
365     }
366 
367     ret = hashMethod->update(mdCtx, prefix, CRYPT_CURVE25519_KEYLEN);
368     if (ret != CRYPT_SUCCESS) {
369         BSL_ERR_PUSH_ERROR(ret);
370         goto EXIT;
371     }
372 
373     ret = hashMethod->update(mdCtx, msg, msgLen);
374     if (ret != CRYPT_SUCCESS) {
375         BSL_ERR_PUSH_ERROR(ret);
376         goto EXIT;
377     }
378 
379     ret = hashMethod->final(mdCtx, r, &hashLen);
380     if (ret != CRYPT_SUCCESS) {
381         BSL_ERR_PUSH_ERROR(ret);
382     }
383 
384 EXIT:
385     hashMethod->freeCtx(mdCtx);
386     return ret;
387 }
388 
GetKHash(uint8_t k[CRYPT_CURVE25519_SIGNLEN],const uint8_t r[CRYPT_CURVE25519_KEYLEN],const uint8_t pubKey[CRYPT_CURVE25519_KEYLEN],const uint8_t * msg,uint32_t msgLen,const EAL_MdMethod * hashMethod)389 static int32_t GetKHash(uint8_t k[CRYPT_CURVE25519_SIGNLEN], const uint8_t r[CRYPT_CURVE25519_KEYLEN],
390     const uint8_t pubKey[CRYPT_CURVE25519_KEYLEN], const uint8_t *msg, uint32_t msgLen,
391     const EAL_MdMethod *hashMethod)
392 {
393     void *mdCtx = NULL;
394     uint32_t hashLen = CRYPT_CURVE25519_SIGNLEN;
395 
396     mdCtx = hashMethod->newCtx();
397     if (mdCtx == NULL) {
398         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
399         return CRYPT_MEM_ALLOC_FAIL;
400     }
401 
402     int32_t ret = hashMethod->init(mdCtx, NULL);
403     if (ret != CRYPT_SUCCESS) {
404         BSL_ERR_PUSH_ERROR(ret);
405         goto EXIT;
406     }
407 
408     ret = hashMethod->update(mdCtx, r, CRYPT_CURVE25519_KEYLEN);
409     if (ret != CRYPT_SUCCESS) {
410         BSL_ERR_PUSH_ERROR(ret);
411         goto EXIT;
412     }
413 
414     ret = hashMethod->update(mdCtx, pubKey, CRYPT_CURVE25519_KEYLEN);
415     if (ret != CRYPT_SUCCESS) {
416         BSL_ERR_PUSH_ERROR(ret);
417         goto EXIT;
418     }
419 
420     ret = hashMethod->update(mdCtx, msg, msgLen);
421     if (ret != CRYPT_SUCCESS) {
422         BSL_ERR_PUSH_ERROR(ret);
423         goto EXIT;
424     }
425 
426     ret = hashMethod->final(mdCtx, k, &hashLen);
427     if (ret != CRYPT_SUCCESS) {
428         BSL_ERR_PUSH_ERROR(ret);
429     }
430 
431 EXIT:
432     hashMethod->freeCtx(mdCtx);
433     return ret;
434 }
435 
SignInputCheck(const CRYPT_CURVE25519_Ctx * pkey,const uint8_t * msg,uint32_t msgLen,const uint8_t * sign,const uint32_t * signLen)436 static int32_t SignInputCheck(const CRYPT_CURVE25519_Ctx *pkey, const uint8_t *msg,
437     uint32_t msgLen, const uint8_t *sign, const uint32_t *signLen)
438 {
439     if (pkey == NULL || (msg == NULL && msgLen != 0) || sign == NULL || signLen == NULL) {
440         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
441         return CRYPT_NULL_INPUT;
442     }
443     if ((pkey->keyType & CURVE25519_PRVKEY) == 0) {
444         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PRVKEY);
445         return CRYPT_CURVE25519_NO_PRVKEY;
446     }
447     if (*signLen < CRYPT_CURVE25519_SIGNLEN) {
448         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_SIGNLEN_ERROR);
449         return CRYPT_CURVE25519_SIGNLEN_ERROR;
450     }
451     if (pkey->hashMethod == NULL) {
452         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_HASH_METHOD);
453         return CRYPT_CURVE25519_NO_HASH_METHOD;
454     }
455     return CRYPT_SUCCESS;
456 }
457 
CRYPT_CURVE25519_Sign(CRYPT_CURVE25519_Ctx * pkey,int32_t algId,const uint8_t * msg,uint32_t msgLen,uint8_t * sign,uint32_t * signLen)458 int32_t CRYPT_CURVE25519_Sign(CRYPT_CURVE25519_Ctx *pkey, int32_t algId, const uint8_t *msg,
459     uint32_t msgLen, uint8_t *sign, uint32_t *signLen)
460 {
461     (void)algId;
462     uint8_t prvKeyHash[CRYPT_CURVE25519_SIGNLEN];
463     uint8_t r[CRYPT_CURVE25519_SIGNLEN];
464     uint8_t k[CRYPT_CURVE25519_SIGNLEN];
465     uint8_t outSign[CRYPT_CURVE25519_SIGNLEN];
466     GeE geTmp;
467 
468     int32_t ret = SignInputCheck(pkey, msg, msgLen, sign, signLen);
469     if (ret != CRYPT_SUCCESS) {
470         BSL_ERR_PUSH_ERROR(ret);
471         goto EXIT;
472     }
473 
474     ret = PrvKeyHash(pkey->prvKey, CRYPT_CURVE25519_KEYLEN, prvKeyHash, CRYPT_CURVE25519_SIGNLEN, pkey->hashMethod);
475     if (ret != CRYPT_SUCCESS) {
476         BSL_ERR_PUSH_ERROR(ret);
477         goto EXIT;
478     }
479 
480     prvKeyHash[0] &= 0xf8;
481     // on block 31, clear the highest bit
482     prvKeyHash[31] &= 0x7f;
483     // on block 31, set second highest bit to 1
484     prvKeyHash[31] |= 0x40;
485 
486     // if ctx has no public key, generate public key and store it in ctx
487     if ((pkey->keyType & CURVE25519_PUBKEY) == 0) {
488         ScalarMultiBase(&geTmp, prvKeyHash);
489         PointEncoding(&geTmp, pkey->pubKey, CRYPT_CURVE25519_KEYLEN);
490         pkey->keyType |= CURVE25519_PUBKEY;
491     }
492 
493     ret = GetRHash(r, prvKeyHash + CRYPT_CURVE25519_KEYLEN, msg, msgLen, pkey->hashMethod);
494     if (ret != CRYPT_SUCCESS) {
495         BSL_ERR_PUSH_ERROR(ret);
496         goto EXIT;
497     }
498 
499     ModuloL(r);
500     ScalarMultiBase(&geTmp, r);
501     PointEncoding(&geTmp, outSign, CRYPT_CURVE25519_SIGNLEN);
502 
503     ret = GetKHash(k, outSign, pkey->pubKey, msg, msgLen, pkey->hashMethod);
504     if (ret != CRYPT_SUCCESS) {
505         BSL_ERR_PUSH_ERROR(ret);
506         goto EXIT;
507     }
508 
509     ModuloL(k);
510     ScalarMulAdd(outSign + CRYPT_CURVE25519_KEYLEN, k, prvKeyHash, r);
511 
512     // The value of *signLen has been checked in SignInputCheck to ensure that
513     // the value is greater than or equal to CRYPT_CURVE25519_SIGNLEN.
514     // The sign memory is input from outside the function. The outSign memory is allocated within the function.
515     // Memory overlap does not exist. There is no failure case for memcpy_s.
516     (void)memcpy_s(sign, *signLen, outSign, CRYPT_CURVE25519_SIGNLEN);
517     *signLen = CRYPT_CURVE25519_SIGNLEN;
518 
519 EXIT:
520     BSL_SAL_CleanseData(prvKeyHash, sizeof(prvKeyHash));
521     BSL_SAL_CleanseData(r, sizeof(r));
522     BSL_SAL_CleanseData(k, sizeof(k));
523     return ret;
524 }
525 
CRYPT_CURVE25519_GetSignLen(const CRYPT_CURVE25519_Ctx * pkey)526 int32_t CRYPT_CURVE25519_GetSignLen(const CRYPT_CURVE25519_Ctx *pkey)
527 {
528     (void)pkey;
529     return CRYPT_CURVE25519_SIGNLEN;
530 }
531 
VerifyInputCheck(const CRYPT_CURVE25519_Ctx * pkey,const uint8_t * msg,uint32_t msgLen,const uint8_t * sign,uint32_t signLen)532 static int32_t VerifyInputCheck(const CRYPT_CURVE25519_Ctx *pkey, const uint8_t *msg,
533     uint32_t msgLen, const uint8_t *sign, uint32_t signLen)
534 {
535     if (pkey == NULL || (msg == NULL && msgLen != 0) || sign == NULL) {
536         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
537         return CRYPT_NULL_INPUT;
538     }
539     if ((pkey->keyType & CURVE25519_PUBKEY) == 0) {
540         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PUBKEY);
541         return CRYPT_CURVE25519_NO_PUBKEY;
542     }
543     if (signLen != CRYPT_CURVE25519_SIGNLEN) {
544         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_SIGNLEN_ERROR);
545         return CRYPT_CURVE25519_SIGNLEN_ERROR;
546     }
547     if (pkey->hashMethod == NULL) {
548         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_HASH_METHOD);
549         return CRYPT_CURVE25519_NO_HASH_METHOD;
550     }
551     return CRYPT_SUCCESS;
552 }
553 
554 /* check 0 <= s < l, l = 2^252 + 27742317777372353535851937790883648493 */
VerifyCheckSValid(const uint8_t s[CRYPT_CURVE25519_KEYLEN])555 static bool VerifyCheckSValid(const uint8_t s[CRYPT_CURVE25519_KEYLEN])
556 {
557     const uint8_t l[CRYPT_CURVE25519_KEYLEN] = {
558         0xED, 0xD3, 0xF5, 0x5C, 0x1A, 0x63, 0x12, 0x58, 0xD6, 0x9C, 0xF7, 0xA2, 0xDE, 0xF9, 0xDE, 0x14,
559         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10
560     };
561 
562     int32_t i;
563     // start from highest block 31
564     for (i = 31; i >= 0; i--) {
565         if (s[i] > l[i]) {
566             return false;
567         } else if (s[i] < l[i]) {
568             return true;
569         }
570     }
571     // s = l is invalid
572     return false;
573 }
574 
CRYPT_CURVE25519_Verify(const CRYPT_CURVE25519_Ctx * pkey,int32_t algId,const uint8_t * msg,uint32_t msgLen,const uint8_t * sign,uint32_t signLen)575 int32_t CRYPT_CURVE25519_Verify(const CRYPT_CURVE25519_Ctx *pkey, int32_t algId, const uint8_t *msg,
576     uint32_t msgLen, const uint8_t *sign, uint32_t signLen)
577 {
578     if (algId != CRYPT_MD_SHA512) {
579         BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_ALGID);
580         return CRYPT_EAL_ERR_ALGID;
581     }
582     GeE geA, sG;
583     uint8_t kHash[CRYPT_CURVE25519_SIGNLEN];
584     uint8_t localR[CRYPT_CURVE25519_KEYLEN];
585 
586     const uint8_t *r = NULL;
587     const uint8_t *s = NULL;
588     int32_t ret = VerifyInputCheck(pkey, msg, msgLen, sign, signLen);
589     if (ret != CRYPT_SUCCESS) {
590         BSL_ERR_PUSH_ERROR(ret);
591         return ret;
592     }
593 
594     // r is first half of sign, length 32
595     r = sign;
596     // s is second half of the sign, length 32
597     s = sign + 32;
598 
599     if (!VerifyCheckSValid(s)) {
600         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_VERIFY_FAIL);
601         ret = CRYPT_CURVE25519_VERIFY_FAIL;
602         return ret;
603     }
604 
605     if (PointDecoding(&geA, pkey->pubKey) != 0) {
606         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_VERIFY_FAIL);
607         ret = CRYPT_CURVE25519_INVALID_PUBKEY;
608         return ret;
609     }
610 
611     ret = GetKHash(kHash, r, pkey->pubKey, msg, msgLen, pkey->hashMethod);
612     if (ret != CRYPT_SUCCESS) {
613         BSL_ERR_PUSH_ERROR(ret);
614         return ret;
615     }
616 
617     CURVE25519_FP_NEGATE(geA.x, geA.x);
618     CURVE25519_FP_NEGATE(geA.t, geA.t);
619 
620     ModuloL(kHash);
621     KAMulPlusMulBase(&sG, kHash, &geA, s);
622     PointEncoding(&sG, localR, CRYPT_CURVE25519_KEYLEN);
623 
624     if (memcmp(localR, r, CRYPT_CURVE25519_KEYLEN) != 0) {
625         ret = CRYPT_CURVE25519_VERIFY_FAIL;
626         BSL_ERR_PUSH_ERROR(ret);
627     }
628     return ret;
629 }
630 
CRYPT_ED25519_GenKey(CRYPT_CURVE25519_Ctx * pkey)631 int32_t CRYPT_ED25519_GenKey(CRYPT_CURVE25519_Ctx *pkey)
632 {
633     if (pkey == NULL) {
634         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
635         return CRYPT_NULL_INPUT;
636     }
637     // SHA512 digest size is 64, no other hash has 64 md size
638     if (pkey->hashMethod == NULL) {
639         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_HASH_METHOD);
640         return CRYPT_CURVE25519_NO_HASH_METHOD;
641     }
642     int32_t ret;
643     uint8_t prvKey[CRYPT_CURVE25519_KEYLEN];
644     uint8_t prvKeyHash[CRYPT_CURVE25519_SIGNLEN];
645     GeE tmp;
646 
647     ret = CRYPT_RandEx(pkey->libCtx, prvKey, sizeof(prvKey));
648     if (ret != CRYPT_SUCCESS) {
649         BSL_ERR_PUSH_ERROR(ret);
650         return ret;
651     }
652 
653     ret = PrvKeyHash(prvKey, CRYPT_CURVE25519_KEYLEN, prvKeyHash, CRYPT_CURVE25519_SIGNLEN, pkey->hashMethod);
654     if (ret != CRYPT_SUCCESS) {
655         BSL_ERR_PUSH_ERROR(ret);
656         goto EXIT;
657     }
658 
659     prvKeyHash[0] &= 0xf8;
660     // on block 31, clear the highest bit
661     prvKeyHash[31] &= 0x7f;
662     // on block 31, set second highest bit to 1
663     prvKeyHash[31] |= 0x40;
664 
665     ScalarMultiBase(&tmp, prvKeyHash);
666     PointEncoding(&tmp, pkey->pubKey, CRYPT_CURVE25519_KEYLEN);
667 
668     // The pkey is not empty. The length of the prvKey is CRYPT_CURVE25519_KEYLEN,
669     // which is the same as the length of local prvKey.
670     // The pkey->prvKey memory is input outside the function. The local prvKey memory is allocated within the function.
671     // Memory overlap does not exist. No failure case exists for memcpy_s.
672     (void)memcpy_s(pkey->prvKey, CRYPT_CURVE25519_KEYLEN, prvKey, CRYPT_CURVE25519_KEYLEN);
673     pkey->keyType = CURVE25519_PRVKEY | CURVE25519_PUBKEY;
674 
675 EXIT:
676     BSL_SAL_CleanseData(prvKey, sizeof(prvKey));
677     BSL_SAL_CleanseData(prvKeyHash, sizeof(prvKeyHash));
678     return ret;
679 }
680 #endif /* HITLS_CRYPTO_ED25519 */
681 
682 #ifdef HITLS_CRYPTO_X25519
683 /* Calculate the shared key based on the local private key and peer public key
684  * Shared12 = prv1 * Pub2 = prv1 * (prv2 * G) = prv1 * prv2 * G
685  */
CRYPT_CURVE25519_ComputeSharedKey(CRYPT_CURVE25519_Ctx * prvKey,CRYPT_CURVE25519_Ctx * pubKey,uint8_t * sharedKey,uint32_t * shareKeyLen)686 int32_t CRYPT_CURVE25519_ComputeSharedKey(CRYPT_CURVE25519_Ctx *prvKey, CRYPT_CURVE25519_Ctx *pubKey,
687     uint8_t *sharedKey, uint32_t *shareKeyLen)
688 {
689     if (prvKey == NULL || pubKey == NULL || sharedKey == NULL || shareKeyLen == NULL) {
690         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
691         return CRYPT_NULL_INPUT;
692     }
693     if (*shareKeyLen < CRYPT_CURVE25519_KEYLEN) {
694         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEYLEN_ERROR);
695         return CRYPT_CURVE25519_KEYLEN_ERROR;
696     }
697     if ((prvKey->keyType & CURVE25519_PRVKEY) == 0) {
698         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PRVKEY);
699         return CRYPT_CURVE25519_NO_PRVKEY;
700     }
701     if ((pubKey->keyType & CURVE25519_PUBKEY) == 0) {
702         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_NO_PUBKEY);
703         return CRYPT_CURVE25519_NO_PUBKEY;
704     }
705 
706     uint32_t tmpLen = *shareKeyLen;
707     ScalarMultiPoint(sharedKey, prvKey->prvKey, pubKey->pubKey);
708 
709     int32_t i;
710     uint8_t checkValid = 0;
711     for (i = 0; i < CRYPT_CURVE25519_KEYLEN; i++) {
712         checkValid |= sharedKey[i];
713     }
714     if (checkValid == 0) {
715         *shareKeyLen = tmpLen;
716         BSL_ERR_PUSH_ERROR(CRYPT_CURVE25519_KEY_COMPUTE_FAILED);
717         return CRYPT_CURVE25519_KEY_COMPUTE_FAILED;
718     } else {
719         *shareKeyLen = CRYPT_CURVE25519_KEYLEN;
720         return CRYPT_SUCCESS;
721     }
722 }
723 
724 /**
725  * @brief   x25519 Calculate the public key based on the private key.
726  *
727  * @param privateKey [IN] Private key
728  * @param publicKey [OUT] Public key
729  *
730  */
CRYPT_X25519_PublicFromPrivate(const uint8_t privateKey[CRYPT_CURVE25519_KEYLEN],uint8_t publicKey[CRYPT_CURVE25519_KEYLEN])731 void CRYPT_X25519_PublicFromPrivate(const uint8_t privateKey[CRYPT_CURVE25519_KEYLEN],
732     uint8_t publicKey[CRYPT_CURVE25519_KEYLEN])
733 {
734     uint8_t privateCopy[CRYPT_CURVE25519_KEYLEN];
735     GeE out;
736     Fp25 zPlusY, zMinusY, zMinusYInvert;
737 
738     (void)memcpy_s(privateCopy, sizeof(privateCopy), privateKey, sizeof(privateCopy));
739 
740     privateCopy[0] &= 0xf8;      /* decodeScalar25519(k): k_list[0] &= 0xf8 */
741     privateCopy[31] &= 0x7f;     /* decodeScalar25519(k): k_list[31] &= 0x7f */
742     privateCopy[31] |= 0x40;      /* decodeScalar25519(k): k_list[31] |= 0x40 */
743 
744     ScalarMultiBase(&out, privateCopy);
745 
746     CURVE25519_FP_ADD(zPlusY, out.z, out.y);
747     CURVE25519_FP_SUB(zMinusY, out.z, out.y);
748     FpInvert(zMinusYInvert, zMinusY);
749     FpMul(zPlusY, zPlusY, zMinusYInvert);
750     PolynomialToData(publicKey, zPlusY);
751 
752     /* cleanup tmp private key */
753     BSL_SAL_CleanseData(privateCopy, sizeof(privateCopy));
754 }
755 
CRYPT_X25519_GenKey(CRYPT_CURVE25519_Ctx * pkey)756 int32_t CRYPT_X25519_GenKey(CRYPT_CURVE25519_Ctx *pkey)
757 {
758     if (pkey == NULL) {
759         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
760         return CRYPT_NULL_INPUT;
761     }
762 
763     int32_t ret = CRYPT_RandEx(pkey->libCtx, pkey->prvKey, sizeof(pkey->prvKey));
764     if (ret != CRYPT_SUCCESS) {
765         pkey->keyType = 0;
766         BSL_ERR_PUSH_ERROR(ret);
767         return ret;
768     }
769 
770     CRYPT_X25519_PublicFromPrivate(pkey->prvKey, pkey->pubKey);
771 
772     pkey->keyType = CURVE25519_PRVKEY | CURVE25519_PUBKEY;
773 
774     return CRYPT_SUCCESS;
775 }
776 #endif /* HITLS_CRYPTO_X25519 */
777 
CRYPT_CURVE25519_Cmp(const CRYPT_CURVE25519_Ctx * a,const CRYPT_CURVE25519_Ctx * b)778 int32_t CRYPT_CURVE25519_Cmp(const CRYPT_CURVE25519_Ctx *a, const CRYPT_CURVE25519_Ctx *b)
779 {
780     RETURN_RET_IF(a == NULL || b == NULL, CRYPT_NULL_INPUT);
781 
782     RETURN_RET_IF((a->keyType & CURVE25519_PUBKEY) == 0 || (b->keyType & CURVE25519_PUBKEY) == 0,
783                   CRYPT_CURVE25519_NO_PUBKEY);
784 
785     RETURN_RET_IF(memcmp(a->pubKey, b->pubKey, CRYPT_CURVE25519_KEYLEN) != 0, CRYPT_CURVE25519_PUBKEY_NOT_EQUAL);
786 
787     return CRYPT_SUCCESS;
788 }
789 
CRYPT_CURVE25519_GetSecBits(const CRYPT_CURVE25519_Ctx * ctx)790 int32_t CRYPT_CURVE25519_GetSecBits(const CRYPT_CURVE25519_Ctx *ctx)
791 {
792     (void) ctx;
793     return 128;
794 }
795 
796 #ifdef HITLS_CRYPTO_PROVIDER
797 
CRYPT_CURVE25519_Import(CRYPT_CURVE25519_Ctx * ctx,const BSL_Param * params)798 int32_t CRYPT_CURVE25519_Import(CRYPT_CURVE25519_Ctx *ctx, const BSL_Param *params)
799 {
800     if (ctx == NULL || params == NULL) {
801         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
802         return CRYPT_NULL_INPUT;
803     }
804     int32_t ret = CRYPT_SUCCESS;
805     const BSL_Param *prv = BSL_PARAM_FindConstParam(params, CRYPT_PARAM_CURVE25519_PRVKEY);
806     const BSL_Param *pub = BSL_PARAM_FindConstParam(params, CRYPT_PARAM_CURVE25519_PUBKEY);
807 
808     if (prv != NULL) {
809         ret = CRYPT_CURVE25519_SetPrvKey(ctx, params);
810         if (ret != CRYPT_SUCCESS) {
811             BSL_ERR_PUSH_ERROR(ret);
812             return ret;
813         }
814     }
815     if (pub != NULL) {
816         ret = CRYPT_CURVE25519_SetPubKey(ctx, params);
817         if (ret != CRYPT_SUCCESS) {
818             BSL_ERR_PUSH_ERROR(ret);
819             return ret;
820         }
821     }
822     return ret;
823 }
824 
CRYPT_CURVE25519_Export(const CRYPT_CURVE25519_Ctx * ctx,BSL_Param * params)825 int32_t CRYPT_CURVE25519_Export(const CRYPT_CURVE25519_Ctx *ctx, BSL_Param *params)
826 {
827     if (ctx == NULL || params == NULL) {
828         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
829         return CRYPT_NULL_INPUT;
830     }
831     uint32_t index = 0;
832     uint32_t keyBytes = CRYPT_CURVE25519_KEYLEN;
833     CRYPT_EAL_ProcessFuncCb processCb = NULL;
834     void *args = NULL;
835     BSL_Param ed25519Params[3] = {0}; // 3: pub key + priv key + end marker
836     int32_t ret = CRYPT_GetPkeyProcessParams(params, &processCb, &args);
837     if (ret != CRYPT_SUCCESS) {
838         return ret;
839     }
840 
841     uint8_t *buffer = BSL_SAL_Calloc(1, keyBytes * 2); // For public + private key
842     if (buffer == NULL) {
843         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
844         return CRYPT_MEM_ALLOC_FAIL;
845     }
846     if ((ctx->keyType & CURVE25519_PUBKEY) != 0) {
847         (void)BSL_PARAM_InitValue(&ed25519Params[index], CRYPT_PARAM_CURVE25519_PUBKEY, BSL_PARAM_TYPE_OCTETS,
848             buffer, keyBytes);
849         ret = CRYPT_CURVE25519_GetPubKey(ctx, ed25519Params);
850         if (ret != CRYPT_SUCCESS) {
851             BSL_SAL_Free(buffer);
852             return ret;
853         }
854         ed25519Params[index].valueLen = ed25519Params[index].useLen;
855         index++;
856     }
857     if ((ctx->keyType & CURVE25519_PRVKEY) != 0) {
858         (void)BSL_PARAM_InitValue(&ed25519Params[index], CRYPT_PARAM_CURVE25519_PRVKEY, BSL_PARAM_TYPE_OCTETS,
859             buffer + keyBytes, keyBytes);
860         ret = CRYPT_CURVE25519_GetPrvKey(ctx, ed25519Params);
861         if (ret != CRYPT_SUCCESS) {
862             BSL_SAL_Free(buffer);
863             return ret;
864         }
865         ed25519Params[index].valueLen = ed25519Params[index].useLen;
866         index++;
867     }
868     ret = processCb(ed25519Params, args);
869     BSL_SAL_Free(buffer);
870     if (ret != CRYPT_SUCCESS) {
871         BSL_ERR_PUSH_ERROR(ret);
872     }
873     return ret;
874 }
875 
876 #endif // HITLS_CRYPTO_PROVIDER
877 
878 #endif /* HITLS_CRYPTO_CURVE25519 */
879