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