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_ECDH
18
19 #include <stdbool.h>
20 #include "crypt_errno.h"
21 #include "crypt_types.h"
22 #include "securec.h"
23 #include "bsl_sal.h"
24 #include "bsl_err_internal.h"
25 #include "crypt_bn.h"
26 #include "crypt_ecc.h"
27 #include "crypt_ecc_pkey.h"
28 #include "crypt_ecdh.h"
29 #include "sal_atomic.h"
30 #include "crypt_local_types.h"
31 #include "crypt_params_key.h"
32
CRYPT_ECDH_NewCtx(void)33 CRYPT_ECDH_Ctx *CRYPT_ECDH_NewCtx(void)
34 {
35 ECC_Pkey *ctx = BSL_SAL_Calloc(1u, sizeof(ECC_Pkey));
36 if (ctx == NULL) {
37 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
38 return NULL;
39 }
40 ctx->useCofactorMode = true;
41 ctx->pointFormat = CRYPT_POINT_UNCOMPRESSED; // the point format is uncompressed by default
42 BSL_SAL_ReferencesInit(&(ctx->references));
43 return ctx;
44 }
45
CRYPT_ECDH_NewCtxEx(void * libCtx)46 CRYPT_ECDH_Ctx *CRYPT_ECDH_NewCtxEx(void *libCtx)
47 {
48 CRYPT_ECDH_Ctx *ctx = CRYPT_ECDH_NewCtx();
49 if (ctx == NULL) {
50 return NULL;
51 }
52 ctx->libCtx = libCtx;
53 return ctx;
54 }
55
CRYPT_ECDH_DupCtx(CRYPT_ECDH_Ctx * ctx)56 CRYPT_ECDH_Ctx *CRYPT_ECDH_DupCtx(CRYPT_ECDH_Ctx *ctx)
57 {
58 return ECC_DupCtx(ctx);
59 }
60
CRYPT_ECDH_FreeCtx(CRYPT_ECDH_Ctx * ctx)61 void CRYPT_ECDH_FreeCtx(CRYPT_ECDH_Ctx *ctx)
62 {
63 if (ctx == NULL) {
64 return;
65 }
66 ECC_FreeCtx(ctx);
67 return;
68 }
69
CRYPT_ECDH_NewParaById(CRYPT_PKEY_ParaId id)70 CRYPT_EcdhPara *CRYPT_ECDH_NewParaById(CRYPT_PKEY_ParaId id)
71 {
72 return ECC_NewPara(id);
73 }
74
CRYPT_ECDH_NewPara(const BSL_Param * eccPara)75 CRYPT_EcdhPara *CRYPT_ECDH_NewPara(const BSL_Param *eccPara)
76 {
77 if (eccPara == NULL) {
78 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
79 return NULL;
80 }
81 CRYPT_PKEY_ParaId id = ECC_GetCurveId(eccPara);
82 if (id == CRYPT_PKEY_PARAID_MAX) {
83 BSL_ERR_PUSH_ERROR(CRYPT_ECC_ERR_PARA);
84 return NULL;
85 }
86 return CRYPT_ECDH_NewParaById(id);
87 }
88
CRYPT_ECDH_GetParaId(const CRYPT_ECDH_Ctx * ctx)89 CRYPT_PKEY_ParaId CRYPT_ECDH_GetParaId(const CRYPT_ECDH_Ctx *ctx)
90 {
91 if (ctx == NULL) {
92 return CRYPT_PKEY_PARAID_MAX;
93 }
94 return ECC_GetParaId(ctx->para);
95 }
96
CRYPT_ECDH_FreePara(CRYPT_EcdhPara * para)97 void CRYPT_ECDH_FreePara(CRYPT_EcdhPara *para)
98 {
99 ECC_FreePara(para);
100 }
101
CRYPT_ECDH_GetPara(const CRYPT_ECDH_Ctx * ctx,BSL_Param * param)102 int32_t CRYPT_ECDH_GetPara(const CRYPT_ECDH_Ctx *ctx, BSL_Param *param)
103 {
104 return ECC_GetPara(ctx, param);
105 }
106
CRYPT_ECDH_SetParaEx(CRYPT_ECDH_Ctx * ctx,CRYPT_EcdhPara * para)107 int32_t CRYPT_ECDH_SetParaEx(CRYPT_ECDH_Ctx *ctx, CRYPT_EcdhPara *para)
108 {
109 return ECC_SetPara(ctx, para);
110 }
111
CRYPT_ECDH_SetPara(CRYPT_ECDH_Ctx * ctx,const BSL_Param * para)112 int32_t CRYPT_ECDH_SetPara(CRYPT_ECDH_Ctx *ctx, const BSL_Param *para)
113 {
114 if (ctx == NULL) {
115 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
116 return CRYPT_NULL_INPUT;
117 }
118 CRYPT_EcdhPara *ecdhPara = CRYPT_ECDH_NewPara(para);
119 if (ecdhPara == NULL) {
120 BSL_ERR_PUSH_ERROR(CRYPT_EAL_ERR_NEW_PARA_FAIL);
121 return CRYPT_EAL_ERR_NEW_PARA_FAIL;
122 }
123 // updating public and private keys
124 BN_Destroy(ctx->prvkey);
125 ECC_FreePoint(ctx->pubkey);
126 ctx->prvkey = NULL;
127 ctx->pubkey = NULL;
128
129 ECC_FreePara(ctx->para);
130 ctx->para = ecdhPara;
131 ECC_SetLibCtx(ctx->libCtx, ctx->para);
132
133 return CRYPT_SUCCESS;
134 }
135
CRYPT_ECDH_GetBits(const CRYPT_ECDH_Ctx * ctx)136 uint32_t CRYPT_ECDH_GetBits(const CRYPT_ECDH_Ctx *ctx)
137 {
138 return ECC_PkeyGetBits(ctx);
139 }
140
CRYPT_ECDH_SetPrvKey(CRYPT_ECDH_Ctx * ctx,const BSL_Param * para)141 int32_t CRYPT_ECDH_SetPrvKey(CRYPT_ECDH_Ctx *ctx, const BSL_Param *para)
142 {
143 return ECC_PkeySetPrvKey(ctx, para);
144 }
145
CRYPT_ECDH_SetPubKey(CRYPT_ECDH_Ctx * ctx,const BSL_Param * para)146 int32_t CRYPT_ECDH_SetPubKey(CRYPT_ECDH_Ctx *ctx, const BSL_Param *para)
147 {
148 return ECC_PkeySetPubKey(ctx, para);
149 }
150
CRYPT_ECDH_GetPrvKey(const CRYPT_ECDH_Ctx * ctx,BSL_Param * para)151 int32_t CRYPT_ECDH_GetPrvKey(const CRYPT_ECDH_Ctx *ctx, BSL_Param *para)
152 {
153 return ECC_PkeyGetPrvKey(ctx, para);
154 }
155
CRYPT_ECDH_GetPubKey(const CRYPT_ECDH_Ctx * ctx,BSL_Param * para)156 int32_t CRYPT_ECDH_GetPubKey(const CRYPT_ECDH_Ctx *ctx, BSL_Param *para)
157 {
158 return ECC_PkeyGetPubKey(ctx, para);
159 }
160
CRYPT_ECDH_Gen(CRYPT_ECDH_Ctx * ctx)161 int32_t CRYPT_ECDH_Gen(CRYPT_ECDH_Ctx *ctx)
162 {
163 return ECC_PkeyGen(ctx);
164 }
165
ComputeShareKeyInputCheck(const CRYPT_ECDH_Ctx * ctx,const CRYPT_ECDH_Ctx * pubKey,const uint8_t * shareKey,const uint32_t * shareKeyLen)166 static int32_t ComputeShareKeyInputCheck(const CRYPT_ECDH_Ctx *ctx, const CRYPT_ECDH_Ctx *pubKey,
167 const uint8_t *shareKey, const uint32_t *shareKeyLen)
168 {
169 if ((ctx == NULL) || (pubKey == NULL) || (shareKey == NULL) || (shareKeyLen == NULL)) {
170 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
171 return CRYPT_NULL_INPUT;
172 }
173
174 if ((ctx->prvkey == NULL) || (pubKey->pubkey == NULL)) {
175 BSL_ERR_PUSH_ERROR(CRYPT_ECDH_ERR_EMPTY_KEY);
176 return CRYPT_ECDH_ERR_EMPTY_KEY;
177 }
178
179 // only the cofactor which value is 1 is supported currently
180 BN_BigNum *paraH = ECC_GetParaH(ctx->para);
181 if (paraH == NULL) {
182 BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
183 return CRYPT_MEM_ALLOC_FAIL;
184 }
185 if (BN_IsOne(paraH) != true) {
186 BN_Destroy(paraH);
187 BSL_ERR_PUSH_ERROR(CRYPT_ECDH_ERR_INVALID_COFACTOR);
188 return CRYPT_ECDH_ERR_INVALID_COFACTOR;
189 }
190 BN_Destroy(paraH);
191
192 return CRYPT_SUCCESS;
193 }
194
CRYPT_ECDH_ComputeShareKey(const CRYPT_ECDH_Ctx * ctx,const CRYPT_ECDH_Ctx * pubKey,uint8_t * shareKey,uint32_t * shareKeyLen)195 int32_t CRYPT_ECDH_ComputeShareKey(const CRYPT_ECDH_Ctx *ctx, const CRYPT_ECDH_Ctx *pubKey,
196 uint8_t *shareKey, uint32_t *shareKeyLen)
197 {
198 int32_t ret = ComputeShareKeyInputCheck(ctx, pubKey, shareKey, shareKeyLen);
199 if (ret != CRYPT_SUCCESS) {
200 return ret;
201 }
202
203 ECC_Point *sharePoint = NULL;
204 CRYPT_Data shareKeyX = {shareKey, *shareKeyLen};
205 BN_BigNum *tmpPrvkey = BN_Dup(ctx->prvkey);
206 sharePoint = ECC_NewPoint(ctx->para);
207 if ((tmpPrvkey == NULL) || (sharePoint == NULL)) {
208 ret = CRYPT_MEM_ALLOC_FAIL;
209 BSL_ERR_PUSH_ERROR(ret);
210 goto EXIT;
211 }
212
213 /** When the cofactor mode is enabled, pubkey = prvkey * h * G. When h is 1, no calculation is required.
214 * Currently, the cofactor of the prime curve is only 1, and no related calculation is required.
215 */
216 ret = ECC_PointMul(ctx->para, sharePoint, ctx->prvkey, pubKey->pubkey);
217 if (ret != CRYPT_SUCCESS) {
218 BSL_ERR_PUSH_ERROR(ret);
219 goto EXIT;
220 }
221
222 ret = ECC_PointCheck(sharePoint);
223 if (ret != CRYPT_SUCCESS) {
224 BSL_ERR_PUSH_ERROR(ret);
225 goto EXIT;
226 }
227
228 ret = ECC_GetPoint(ctx->para, sharePoint, &shareKeyX, NULL);
229 if (ret != CRYPT_SUCCESS) {
230 BSL_ERR_PUSH_ERROR(ret);
231 goto EXIT;
232 }
233 *shareKeyLen = shareKeyX.len;
234
235 EXIT:
236 ECC_FreePoint(sharePoint);
237 BN_Destroy(tmpPrvkey);
238 return ret;
239 }
240
CRYPT_ECDH_GetLen(const CRYPT_ECDH_Ctx * ctx,GetLenFunc func,void * val,uint32_t len)241 static int32_t CRYPT_ECDH_GetLen(const CRYPT_ECDH_Ctx *ctx, GetLenFunc func, void *val, uint32_t len)
242 {
243 if (val == NULL || len != sizeof(int32_t)) {
244 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
245 return CRYPT_NULL_INPUT;
246 }
247
248 *(int32_t *)val = func(ctx);
249 return CRYPT_SUCCESS;
250 }
251
CRYPT_ECDH_Ctrl(CRYPT_ECDH_Ctx * ctx,int32_t opt,void * val,uint32_t len)252 int32_t CRYPT_ECDH_Ctrl(CRYPT_ECDH_Ctx *ctx, int32_t opt, void *val, uint32_t len)
253 {
254 if (ctx == NULL) {
255 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
256 return CRYPT_NULL_INPUT;
257 }
258 switch (opt) {
259 case CRYPT_CTRL_GET_PARAID:
260 return CRYPT_ECDH_GetLen(ctx, (GetLenFunc)CRYPT_ECDH_GetParaId, val, len);
261 case CRYPT_CTRL_GET_BITS:
262 return CRYPT_ECDH_GetLen(ctx, (GetLenFunc)CRYPT_ECDH_GetBits, val, len);
263 case CRYPT_CTRL_GET_SECBITS:
264 return CRYPT_ECDH_GetLen(ctx, (GetLenFunc)CRYPT_ECDH_GetSecBits, val, len);
265 case CRYPT_CTRL_SET_PARA_BY_ID:
266 return CRYPT_ECDH_SetParaEx(ctx, CRYPT_ECDH_NewParaById(*(CRYPT_PKEY_ParaId *)val));
267 default:
268 break;
269 }
270 return ECC_PkeyCtrl(ctx, opt, val, len);
271 }
272
CRYPT_ECDH_Cmp(const CRYPT_ECDH_Ctx * a,const CRYPT_ECDH_Ctx * b)273 int32_t CRYPT_ECDH_Cmp(const CRYPT_ECDH_Ctx *a, const CRYPT_ECDH_Ctx *b)
274 {
275 return ECC_PkeyCmp(a, b);
276 }
277
CRYPT_ECDH_GetSecBits(const CRYPT_ECDH_Ctx * ctx)278 int32_t CRYPT_ECDH_GetSecBits(const CRYPT_ECDH_Ctx *ctx)
279 {
280 if (ctx == NULL) {
281 BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
282 return 0;
283 }
284 return ECC_GetSecBits(ctx->para);
285 }
286 #endif /* HITLS_CRYPTO_ECDH */
287