• 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_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