• 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_SM2_CRYPT
18 #include <limits.h>
19 #include "securec.h"
20 #include "crypt_errno.h"
21 #include "crypt_types.h"
22 #include "crypt_utils.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_local_types.h"
29 #include "sm2_local.h"
30 #include "crypt_sm2.h"
31 #include "crypt_encode_internal.h"
32 
33 #define SM2_POINT_SINGLE_COORDINATE_LEN 32
34 #define SM2_POINT_COORDINATE_LEN 65
35 
EncryptMemFree(ECC_Point * c1,ECC_Point * tmp,BN_BigNum * k,BN_BigNum * order,uint8_t * c2)36 static void EncryptMemFree(ECC_Point *c1, ECC_Point *tmp, BN_BigNum *k,
37     BN_BigNum *order, uint8_t *c2)
38 {
39     ECC_FreePoint(c1);
40     ECC_FreePoint(tmp);
41     BN_Destroy(k);
42     BN_Destroy(order);
43     BSL_SAL_FREE(c2);
44 }
45 
ParaCheckAndCalculate(CRYPT_SM2_Ctx * ctx,ECC_Point * tmp,BN_BigNum * k)46 static int32_t ParaCheckAndCalculate(CRYPT_SM2_Ctx *ctx, ECC_Point *tmp, BN_BigNum *k)
47 {
48     int32_t ret;
49     // Check whether [h]PB is equal to infinity point.
50     GOTO_ERR_IF(ECC_PointCheck(ctx->pkey->pubkey), ret);
51     // Calculate [k] * PB
52     GOTO_ERR_IF(ECC_PointMul(ctx->pkey->para, tmp, k, ctx->pkey->pubkey), ret);
53 ERR:
54     return ret;
55 }
56 
Sm3Hash(const EAL_MdMethod * hashMethod,const uint8_t * pbBuf,const uint8_t * data,uint32_t datalen,uint8_t * c3Buf,uint32_t * c3BufLen)57 static int32_t Sm3Hash(const EAL_MdMethod *hashMethod, const uint8_t *pbBuf, const uint8_t *data, uint32_t datalen,
58     uint8_t *c3Buf, uint32_t *c3BufLen)
59 {
60     int32_t ret;
61     void *mdCtx = hashMethod->newCtx();
62     if (mdCtx == NULL) {
63         ret = CRYPT_MEM_ALLOC_FAIL;
64         BSL_ERR_PUSH_ERROR(ret);
65         return ret;
66     }
67     GOTO_ERR_IF(hashMethod->init(mdCtx, NULL), ret);
68     GOTO_ERR_IF(hashMethod->update(mdCtx, pbBuf + 1,
69         SM2_POINT_SINGLE_COORDINATE_LEN), ret); // Horizontal coordinate x2 of PB
70     GOTO_ERR_IF(hashMethod->update(mdCtx, data, datalen), ret); // M
71     GOTO_ERR_IF(hashMethod->update(mdCtx, pbBuf + SM2_POINT_SINGLE_COORDINATE_LEN + 1,
72         SM2_POINT_SINGLE_COORDINATE_LEN), ret); // Vertical coordinate y2 of PB
73     // Calculated c3, in c3Buf
74     GOTO_ERR_IF(hashMethod->final(mdCtx, c3Buf, c3BufLen), ret);
75 ERR:
76     hashMethod->freeCtx(mdCtx);
77     return ret;
78 }
79 
IsDataZero(const uint8_t * data,uint32_t datalen)80 static int32_t IsDataZero(const uint8_t *data, uint32_t datalen)
81 {
82     uint8_t check = 0;
83     for (uint32_t i = 0; i < datalen; i++) {
84         check |= data[i];
85     }
86     if (check == 0) {
87         BSL_ERR_PUSH_ERROR(CRYPT_SM2_DECRYPT_FAIL);
88         return CRYPT_SM2_DECRYPT_FAIL;
89     }
90     return CRYPT_SUCCESS;
91 }
92 
MemAllocCheck(const BN_BigNum * k,const BN_BigNum * order,const ECC_Point * c1,const ECC_Point * tmp,const uint8_t * c2)93 static int32_t MemAllocCheck(const BN_BigNum *k, const BN_BigNum *order,
94     const ECC_Point *c1, const ECC_Point *tmp, const uint8_t *c2)
95 {
96     if (k == NULL || order == NULL || c1 == NULL || tmp == NULL || c2 == NULL) {
97         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
98         return CRYPT_MEM_ALLOC_FAIL;
99     }
100     return CRYPT_SUCCESS;
101 }
102 
XorCalculate(uint8_t * c2,const uint8_t * data,uint32_t datalen)103 static void XorCalculate(uint8_t *c2, const uint8_t *data, uint32_t datalen)
104 {
105     uint32_t i;
106     for (i = 0; i < datalen; ++i) {
107         c2[i] ^= data[i];
108     }
109     return;
110 }
111 
EncryptInputCheck(const CRYPT_SM2_Ctx * ctx,const uint8_t * data,uint32_t datalen,const uint8_t * out,const uint32_t * outlen)112 static int32_t EncryptInputCheck(const CRYPT_SM2_Ctx *ctx, const uint8_t *data, uint32_t datalen,
113     const uint8_t *out, const uint32_t *outlen)
114 {
115     // 0-length plaintext encryption is not supported.
116     if (ctx == NULL || data == NULL || datalen == 0 || out == NULL || outlen == NULL || *outlen == 0) {
117         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
118         return CRYPT_NULL_INPUT;
119     }
120     uint32_t encodeLen = 0;
121     int32_t ret = CRYPT_EAL_GetSm2EncryptDataEncodeLen(SM2_POINT_SINGLE_COORDINATE_LEN, SM2_POINT_SINGLE_COORDINATE_LEN,
122         SM3_MD_SIZE, datalen, &encodeLen);
123     if (ret != CRYPT_SUCCESS) {
124         BSL_ERR_PUSH_ERROR(ret);
125         return ret;
126     }
127     if (*outlen < encodeLen) {
128         BSL_ERR_PUSH_ERROR(CRYPT_SM2_BUFF_LEN_NOT_ENOUGH);
129         return CRYPT_SM2_BUFF_LEN_NOT_ENOUGH;
130     }
131     if (ctx->pkey == NULL) {
132         BSL_ERR_PUSH_ERROR(CRYPT_SM2_ERR_EMPTY_KEY);
133         return CRYPT_SM2_ERR_EMPTY_KEY;
134     }
135     if (ctx->pkey->pubkey == NULL) {
136         BSL_ERR_PUSH_ERROR(CRYPT_SM2_NO_PUBKEY);
137         return CRYPT_SM2_NO_PUBKEY;
138     }
139     return CRYPT_SUCCESS;
140 }
141 
CRYPT_SM2_Encrypt(CRYPT_SM2_Ctx * ctx,const uint8_t * data,uint32_t datalen,uint8_t * out,uint32_t * outlen)142 int32_t CRYPT_SM2_Encrypt(CRYPT_SM2_Ctx *ctx, const uint8_t *data, uint32_t datalen, uint8_t *out, uint32_t *outlen)
143 {
144     int32_t ret = EncryptInputCheck(ctx, data, datalen, out, outlen);
145     if (ret != CRYPT_SUCCESS) {
146         return ret;
147     }
148     uint32_t i;
149     BN_BigNum *k = BN_Create(CRYPT_SM2_GetBits(ctx));
150     BN_BigNum *order = ECC_GetParaN(ctx->pkey->para);
151     ECC_Point *c1 = ECC_NewPoint(ctx->pkey->para);
152     ECC_Point *tmp = ECC_NewPoint(ctx->pkey->para);
153     uint32_t buflen = SM2_POINT_COORDINATE_LEN;
154     uint8_t c1Buf[SM2_POINT_COORDINATE_LEN];
155     uint8_t tmpBuf[SM2_POINT_COORDINATE_LEN];
156     uint8_t *c2 = BSL_SAL_Malloc(datalen);
157     uint8_t c3Buf[SM3_MD_SIZE];
158     uint32_t c3BufLen = SM3_MD_SIZE;
159     CRYPT_SM2_EncryptData encData = {
160         // +1: Skip one byte for '04'
161         .x = c1Buf + 1,                                   .xLen = SM2_POINT_SINGLE_COORDINATE_LEN,
162         .y = c1Buf + SM2_POINT_SINGLE_COORDINATE_LEN + 1, .yLen = SM2_POINT_SINGLE_COORDINATE_LEN,
163         .hash = c3Buf,                                    .hashLen = c3BufLen,
164         .cipher = c2,                                     .cipherLen = datalen,
165     };
166     GOTO_ERR_IF(MemAllocCheck(k, order, c1, tmp, c2), ret);
167     for (i = 0; i < CRYPT_ECC_TRY_MAX_CNT; i++) {
168         GOTO_ERR_IF(BN_RandRangeEx(ctx->pkey->libCtx, k, order), ret);
169         if (BN_IsZero(k)) {
170             continue;
171         }
172         // c1 = k * G
173         GOTO_ERR_IF(ECC_PointMul(ctx->pkey->para, c1, k, NULL), ret);
174         // Convert the point format into binary data stream and save the data stream in tmpbuf.
175         GOTO_ERR_IF(ECC_EncodePoint(ctx->pkey->para, c1, c1Buf, &buflen, CRYPT_POINT_UNCOMPRESSED), ret);
176         GOTO_ERR_IF(ParaCheckAndCalculate(ctx, tmp, k), ret);
177         GOTO_ERR_IF(ECC_EncodePoint(ctx->pkey->para, tmp, tmpBuf, &buflen, CRYPT_POINT_UNCOMPRESSED), ret);
178         // Calculate the kdf.
179         GOTO_ERR_IF(KdfGmt0032012(c2, &datalen, tmpBuf + 1, buflen - 1, ctx->hashMethod), ret);
180         if (IsDataZero(c2, datalen) == CRYPT_SUCCESS) {
181             break;
182         }
183     }
184     if (i == CRYPT_ECC_TRY_MAX_CNT) {
185         BSL_ERR_PUSH_ERROR(CRYPT_SM2_ERR_TRY_CNT);
186         ret = CRYPT_SM2_ERR_TRY_CNT;
187         goto ERR;
188     }
189     // Bitwise XOR
190     XorCalculate(c2, data, datalen);
191     // x2 || M || y2, calculate the hash value
192     GOTO_ERR_IF(Sm3Hash(ctx->hashMethod, tmpBuf, data, datalen, c3Buf, &c3BufLen), ret);
193 
194     GOTO_ERR_IF(CRYPT_EAL_EncodeSm2EncryptData(&encData, out, outlen), ret);
195 ERR:
196     EncryptMemFree(c1, tmp, k, order, c2);
197     return ret;
198 }
199 
IsUEqualToC3(const uint8_t * data,const uint8_t * sm3Buf,uint32_t sm3BufLen)200 static int32_t IsUEqualToC3(const uint8_t *data, const uint8_t *sm3Buf, uint32_t sm3BufLen)
201 {
202     uint8_t check = 0;
203     for (uint32_t i = 0; i < sm3BufLen; i++) {
204         check |= sm3Buf[i] ^ data[i + SM2_POINT_COORDINATE_LEN];
205     }
206     if (check != 0) {
207         BSL_ERR_PUSH_ERROR(CRYPT_SM2_DECRYPT_FAIL);
208         return CRYPT_SM2_DECRYPT_FAIL;
209     }
210     return CRYPT_SUCCESS;
211 }
212 
DecryptInputCheck(const CRYPT_SM2_Ctx * ctx,const uint8_t * data,uint32_t datalen,const uint8_t * out,const uint32_t * outlen)213 static int32_t DecryptInputCheck(const CRYPT_SM2_Ctx *ctx, const uint8_t *data, uint32_t datalen,
214     const uint8_t *out, const uint32_t *outlen)
215 {
216     // 0-length plaintext decryption is not supported.
217     if (ctx == NULL || data == NULL || datalen == 0 || out == NULL || outlen == NULL || *outlen == 0) {
218         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
219         return CRYPT_NULL_INPUT;
220     }
221     if (ctx->pkey == NULL) {
222         BSL_ERR_PUSH_ERROR(CRYPT_SM2_ERR_EMPTY_KEY);
223         return CRYPT_SM2_ERR_EMPTY_KEY;
224     }
225     if (ctx->pkey->prvkey == NULL) {
226         BSL_ERR_PUSH_ERROR(CRYPT_SM2_NO_PRVKEY);
227         return CRYPT_SM2_NO_PRVKEY;
228     }
229     return CRYPT_SUCCESS;
230 }
231 
DecodeEncryptData(const uint8_t * data,uint32_t datalen,uint8_t ** decode,const uint8_t ** cipher,uint32_t * cipherLen)232 static int32_t DecodeEncryptData(const uint8_t *data, uint32_t datalen, uint8_t **decode,
233     const uint8_t **cipher, uint32_t *cipherLen)
234 {
235     *decode = BSL_SAL_Calloc(1u, datalen);
236     if (*decode == NULL) {
237         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
238         return CRYPT_MEM_ALLOC_FAIL;
239     }
240     // Add uncompressed point identifier
241     (*decode)[0] = 0x04;
242     CRYPT_SM2_EncryptData encData = {
243         .x = *decode + 1,                        // Reserve one byte for '04'
244         .xLen = SM2_POINT_SINGLE_COORDINATE_LEN,
245         .y = *decode + SM2_POINT_SINGLE_COORDINATE_LEN + 1,
246         .yLen = SM2_POINT_SINGLE_COORDINATE_LEN,
247         .hash = *decode + SM2_POINT_COORDINATE_LEN,
248         .hashLen = SM3_MD_SIZE,
249         .cipher = *decode + SM2_POINT_COORDINATE_LEN + SM3_MD_SIZE,
250         .cipherLen = datalen - SM2_POINT_COORDINATE_LEN - SM3_MD_SIZE
251     };
252 
253     int32_t ret = CRYPT_EAL_DecodeSm2EncryptData(data, datalen, &encData);
254     if (ret != CRYPT_SUCCESS) {
255         BSL_SAL_Free(*decode);
256         *decode = NULL;
257         BSL_ERR_PUSH_ERROR(ret);
258         return ret;
259     }
260 
261     // Return cipher related information
262     *cipher = encData.cipher;
263     *cipherLen = encData.cipherLen;
264 
265     return CRYPT_SUCCESS;
266 }
267 
CRYPT_SM2_Decrypt(CRYPT_SM2_Ctx * ctx,const uint8_t * data,uint32_t datalen,uint8_t * out,uint32_t * outlen)268 int32_t CRYPT_SM2_Decrypt(CRYPT_SM2_Ctx *ctx, const uint8_t *data, uint32_t datalen, uint8_t *out, uint32_t *outlen)
269 {
270     // take out the c1
271     int32_t ret = DecryptInputCheck(ctx, data, datalen, out, outlen);
272     if (ret != CRYPT_SUCCESS) {
273         BSL_ERR_PUSH_ERROR(ret);
274         return ret;
275     }
276 
277     uint8_t *decode = NULL;
278     const uint8_t *cipher = NULL;
279     uint32_t cipherLen = 0;
280     ret = DecodeEncryptData(data, datalen, &decode, &cipher, &cipherLen);
281     if (ret != CRYPT_SUCCESS) {
282         return ret;
283     }
284     if (*outlen < cipherLen) {
285         BSL_SAL_Free(decode);
286         BSL_ERR_PUSH_ERROR(CRYPT_SM2_BUFF_LEN_NOT_ENOUGH);
287         return CRYPT_SM2_BUFF_LEN_NOT_ENOUGH;
288     }
289 
290     uint8_t sm3Buf[SM3_MD_SIZE];
291     uint32_t sm3BufLen = SM3_MD_SIZE;
292     uint32_t tmplen = SM2_POINT_COORDINATE_LEN;
293     uint8_t tmpBuf[SM2_POINT_COORDINATE_LEN];
294     ECC_Point *c1 = ECC_NewPoint(ctx->pkey->para);
295     ECC_Point *tmp = ECC_NewPoint(ctx->pkey->para);
296     uint8_t *t = BSL_SAL_Malloc(cipherLen);
297     if (c1 == NULL || tmp == NULL || t == NULL) {
298         ret = CRYPT_MEM_ALLOC_FAIL;
299         BSL_ERR_PUSH_ERROR(ret);
300         goto ERR;
301     }
302 
303     GOTO_ERR_IF(ECC_DecodePoint(ctx->pkey->para, c1, decode, SM2_POINT_COORDINATE_LEN), ret);
304     // Calculate [dB]C1 = (x2, y2) and save it to the point tmp.
305     GOTO_ERR_IF(ECC_PointMul(ctx->pkey->para, tmp, ctx->pkey->prvkey, c1), ret);
306     // Extract x and y of the point tmp and save them to tmpbuf.
307     GOTO_ERR_IF(ECC_EncodePoint(ctx->pkey->para, tmp, tmpBuf, &tmplen, CRYPT_POINT_UNCOMPRESSED), ret);
308     // Calculate the kdf(x2 || y2, cipherLen).
309     GOTO_ERR_IF(KdfGmt0032012(t, &cipherLen, tmpBuf + 1, tmplen - 1, ctx->hashMethod), ret);
310     // Check whether t is all 0s. If yes, report an error and exit.
311     GOTO_ERR_IF(IsDataZero(t, cipherLen), ret);
312 
313     // Calculate M' = C2 ^ t
314     // Bitwise XOR, and the result is still stored in t.
315     for (uint32_t i = 0; i < cipherLen; ++i) {
316         t[i] ^= cipher[i];
317     }
318     // Calculate hash(x2 || t || y2)
319     GOTO_ERR_IF(Sm3Hash(ctx->hashMethod, tmpBuf, t, cipherLen, sm3Buf, &sm3BufLen), ret);
320     // Check whether u is equal to c3.
321     GOTO_ERR_IF(IsUEqualToC3(decode, sm3Buf, sm3BufLen), ret);
322     // The verification is successful. M' is the last plaintext.
323     (void)memcpy_s(out, *outlen, t, cipherLen);
324     *outlen = cipherLen;
325 
326 ERR:
327     BSL_SAL_FREE(decode);
328     ECC_FreePoint(c1);
329     ECC_FreePoint(tmp);
330     BSL_SAL_CleanseData((void*)t, cipherLen);
331     BSL_SAL_FREE(t);
332     return ret;
333 }
334 #endif // HITLS_CRYPTO_SM2_CRYPT
335