• 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 #if defined(HITLS_CRYPTO_SM2_SIGN) || defined(HITLS_CRYPTO_DSA) || defined(HITLS_CRYPTO_ECDSA) || \
18     defined(HITLS_CRYPTO_SM2_CRYPT)
19 #include "securec.h"
20 #include "crypt_errno.h"
21 #include "bsl_err_internal.h"
22 #include "bsl_obj_internal.h"
23 #include "crypt_encode_internal.h"
24 #include "bsl_asn1.h"
25 
26 /**
27  * Common function to encode ASN.1 template and copy result
28  */
EncodeAsn1Template(BSL_ASN1_Template * templ,BSL_ASN1_Buffer * asnArr,uint32_t asnArrLen,uint8_t * encode,uint32_t * encodeLen)29 static int32_t EncodeAsn1Template(BSL_ASN1_Template *templ, BSL_ASN1_Buffer *asnArr, uint32_t asnArrLen,
30     uint8_t *encode, uint32_t *encodeLen)
31 {
32     uint8_t *outBuf = NULL;
33     uint32_t outLen = 0;
34 
35     int32_t ret = BSL_ASN1_EncodeTemplate(templ, asnArr, asnArrLen, &outBuf, &outLen);
36     if (ret != CRYPT_SUCCESS) {
37         BSL_ERR_PUSH_ERROR(ret);
38         return ret;
39     }
40 
41     if (outLen > *encodeLen) {
42         BSL_SAL_Free(outBuf);
43         BSL_ERR_PUSH_ERROR(CRYPT_ENCODE_BUFF_NOT_ENOUGH);
44         return CRYPT_ENCODE_BUFF_NOT_ENOUGH;
45     }
46 
47     (void)memcpy_s(encode, *encodeLen, outBuf, outLen);
48     BSL_SAL_Free(outBuf);
49     *encodeLen = outLen;
50 
51     return CRYPT_SUCCESS;
52 }
53 
54 /**
55  * Common function to decode ASN.1 template and check remaining length
56  */
DecodeAsn1Template(const uint8_t * encode,uint32_t encodeLen,BSL_ASN1_Template * templ,BSL_ASN1_Buffer * asnArr,uint32_t asnArrLen)57 static int32_t DecodeAsn1Template(const uint8_t *encode, uint32_t encodeLen, BSL_ASN1_Template *templ,
58     BSL_ASN1_Buffer *asnArr, uint32_t asnArrLen)
59 {
60     uint8_t *tmpEnc = (uint8_t *)(uintptr_t)encode;
61     uint32_t tmpEncLen = encodeLen;
62 
63     int32_t ret = BSL_ASN1_DecodeTemplate(templ, NULL, &tmpEnc, &tmpEncLen, asnArr, asnArrLen);
64     if (ret != CRYPT_SUCCESS) {
65         BSL_ERR_PUSH_ERROR(ret);
66         return ret;
67     }
68 
69     if (tmpEncLen != 0) {
70         BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ASN1_BUFF_FAILED);
71         return CRYPT_DECODE_ASN1_BUFF_FAILED;
72     }
73 
74     for (uint32_t i = 0; i < asnArrLen; i++) {
75         if (asnArr[i].len == 0) {
76             BSL_ERR_PUSH_ERROR(CRYPT_DECODE_ASN1_BUFF_LEN_ZERO);
77             return CRYPT_DECODE_ASN1_BUFF_LEN_ZERO;
78         }
79     }
80 
81     return CRYPT_SUCCESS;
82 }
83 
84 #if defined(HITLS_CRYPTO_SM2_SIGN) || defined(HITLS_CRYPTO_DSA) || defined(HITLS_CRYPTO_ECDSA)
CRYPT_EAL_GetSignEncodeLen(uint32_t rLen,uint32_t sLen,uint32_t * maxLen)85 int32_t CRYPT_EAL_GetSignEncodeLen(uint32_t rLen, uint32_t sLen, uint32_t *maxLen)
86 {
87     /**
88      * https://docs.microsoft.com/en-us/windows/win32/seccertenroll/about-integer
89      * If the integer is positive but the high order bit is set to 1,
90      * a leading 0x00 is added to the content to indicate that the number is not negative
91      */
92     if (rLen == 0 || rLen > UINT32_MAX - 1 || sLen == 0 || sLen > UINT32_MAX - 1 || maxLen == NULL) {
93         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
94         return CRYPT_INVALID_ARG;
95     }
96     uint32_t rEncodeLen = 0;
97     uint32_t sEncodeLen = 0;
98     int32_t ret = BSL_ASN1_GetEncodeLen(rLen + 1, &rEncodeLen); // + 1: if high bit is 1, should add a leading 0x00
99     if (ret != CRYPT_SUCCESS) {
100         BSL_ERR_PUSH_ERROR(ret);
101         return ret;
102     }
103     ret = BSL_ASN1_GetEncodeLen(sLen + 1, &sEncodeLen); // + 1: if high bit is 1, should add a leading 0x00
104     if (ret != CRYPT_SUCCESS) {
105         BSL_ERR_PUSH_ERROR(ret);
106         return ret;
107     }
108 
109     if (rEncodeLen > UINT32_MAX - sEncodeLen) {
110         BSL_ERR_PUSH_ERROR(CRYPT_ENCODE_ERR_SIGN_LEN_OVERFLOW);
111         return CRYPT_ENCODE_ERR_SIGN_LEN_OVERFLOW;
112     }
113     ret = BSL_ASN1_GetEncodeLen(rEncodeLen + sEncodeLen, maxLen);
114     if (ret != CRYPT_SUCCESS) {
115         BSL_ERR_PUSH_ERROR(ret);
116     }
117     return ret;
118 }
119 
120 static BSL_ASN1_TemplateItem g_signTempl[] = {
121     {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SEQUENCE, 0, 0},
122         {BSL_ASN1_TAG_INTEGER, 0, 1},
123         {BSL_ASN1_TAG_INTEGER, 0, 1},
124 };
125 
CheckSignBnParams(const BN_BigNum * r,const BN_BigNum * s,uint8_t * encode,uint32_t * encodeLen)126 static int32_t CheckSignBnParams(const BN_BigNum *r, const BN_BigNum *s, uint8_t *encode, uint32_t *encodeLen)
127 {
128     if (r == NULL || s == NULL || encode == NULL || encodeLen == NULL) {
129         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
130         return CRYPT_NULL_INPUT;
131     }
132 
133     // The big number must be non-negative.
134     if (BN_IsNegative(r) || BN_IsNegative(s)) {
135         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
136         return CRYPT_INVALID_ARG;
137     }
138 
139     // The big number must be non-zero.
140     if (BN_IsZero(r) || BN_IsZero(s)) {
141         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
142         return CRYPT_INVALID_ARG;
143     }
144 
145     return CRYPT_SUCCESS;
146 }
147 
ConvertBNToBuffer(const BN_BigNum * bn,uint8_t ** outBuf,uint32_t * outLen)148 static int32_t ConvertBNToBuffer(const BN_BigNum *bn, uint8_t **outBuf, uint32_t *outLen)
149 {
150     uint32_t len = BN_Bytes(bn);
151     uint8_t *buf = (uint8_t *)BSL_SAL_Malloc(len);
152     if (buf == NULL) {
153         BSL_ERR_PUSH_ERROR(CRYPT_MEM_ALLOC_FAIL);
154         return CRYPT_MEM_ALLOC_FAIL;
155     }
156 
157     int32_t ret = BN_Bn2Bin(bn, buf, &len);
158     if (ret != CRYPT_SUCCESS) {
159         BSL_SAL_Free(buf);
160         BSL_ERR_PUSH_ERROR(ret);
161         return ret;
162     }
163 
164     *outBuf = buf;
165     *outLen = len;
166     return CRYPT_SUCCESS;
167 }
168 
CRYPT_EAL_EncodeSign(const BN_BigNum * r,const BN_BigNum * s,uint8_t * encode,uint32_t * encodeLen)169 int32_t CRYPT_EAL_EncodeSign(const BN_BigNum *r, const BN_BigNum *s, uint8_t *encode, uint32_t *encodeLen)
170 {
171     int32_t ret = CheckSignBnParams(r, s, encode, encodeLen);
172     if (ret != CRYPT_SUCCESS) {
173         return ret;
174     }
175 
176     uint8_t *rBuf = NULL;
177     uint8_t *sBuf = NULL;
178     uint32_t rLen = 0;
179     uint32_t sLen = 0;
180 
181     // Prepare the buffer for r.
182     ret = ConvertBNToBuffer(r, &rBuf, &rLen);
183     if (ret != CRYPT_SUCCESS) {
184         return ret; // no need to push err
185     }
186 
187     // Prepare the buffer for s.
188     ret = ConvertBNToBuffer(s, &sBuf, &sLen);
189     if (ret != CRYPT_SUCCESS) {
190         BSL_SAL_Free(rBuf);
191         return ret; // no need to push err
192     }
193 
194     BSL_ASN1_Buffer asnArr[2] = {
195         {BSL_ASN1_TAG_INTEGER, rLen, rBuf},
196         {BSL_ASN1_TAG_INTEGER, sLen, sBuf}
197     };
198     BSL_ASN1_Template templ = {g_signTempl, sizeof(g_signTempl) / sizeof(g_signTempl[0])};
199     ret = EncodeAsn1Template(&templ, asnArr, 2, encode, encodeLen);
200 
201     BSL_SAL_Free(rBuf);
202     BSL_SAL_Free(sBuf);
203 
204     return ret;
205 }
206 
CRYPT_EAL_DecodeSign(const uint8_t * encode,uint32_t encodeLen,BN_BigNum * r,BN_BigNum * s)207 int32_t CRYPT_EAL_DecodeSign(const uint8_t *encode, uint32_t encodeLen, BN_BigNum *r, BN_BigNum *s)
208 {
209     if (encode == NULL || encodeLen == 0 || r == NULL || s == NULL) {
210         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
211         return CRYPT_NULL_INPUT;
212     }
213 
214     // Decode ASN.1 sequence to get r and s components
215     BSL_ASN1_Buffer asnArr[2] = {0};  // 2: r and s
216     BSL_ASN1_Template templ = {g_signTempl, sizeof(g_signTempl) / sizeof(g_signTempl[0])};
217     int32_t ret = DecodeAsn1Template(encode, encodeLen, &templ, asnArr, 2);  // 2: r and s
218     if (ret != CRYPT_SUCCESS) {
219         BSL_ERR_PUSH_ERROR(ret);
220         return ret;
221     }
222 
223     // Convert decoded buffers to big numbers
224     ret = BN_Bin2Bn(r, asnArr[0].buff, asnArr[0].len);
225     if (ret != CRYPT_SUCCESS) {
226         BSL_ERR_PUSH_ERROR(ret);
227         return ret;
228     }
229 
230     ret = BN_Bin2Bn(s, asnArr[1].buff, asnArr[1].len);
231     if (ret != CRYPT_SUCCESS) {
232         BSL_ERR_PUSH_ERROR(ret);
233     }
234 
235     return ret;
236 }
237 #endif
238 
239 #ifdef HITLS_CRYPTO_SM2_CRYPT
CRYPT_EAL_GetSm2EncryptDataEncodeLen(uint32_t xLen,uint32_t yLen,uint32_t hashLen,uint32_t dataLen,uint32_t * maxLen)240 int32_t CRYPT_EAL_GetSm2EncryptDataEncodeLen(uint32_t xLen, uint32_t yLen, uint32_t hashLen, uint32_t dataLen,
241     uint32_t *maxLen)
242 {
243     if (maxLen == NULL || xLen > UINT32_MAX - 1 || yLen > UINT32_MAX - 1) {
244         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
245         return CRYPT_INVALID_ARG;
246     }
247     uint32_t xEncodeLen = 0;
248     uint32_t yEncodeLen = 0;
249     uint32_t hashEncodeLen = 0;
250     uint32_t cipherEncodeLen = 0;
251 
252     int32_t ret = BSL_ASN1_GetEncodeLen(xLen + 1, &xEncodeLen); // + 1: if high bit is 1, should add a leading 0x00
253     if (ret != CRYPT_SUCCESS) {
254         BSL_ERR_PUSH_ERROR(ret);
255         return ret;
256     }
257 
258     ret = BSL_ASN1_GetEncodeLen(yLen + 1, &yEncodeLen); // + 1: if high bit is 1, should add a leading 0x00
259     if (ret != CRYPT_SUCCESS) {
260         BSL_ERR_PUSH_ERROR(ret);
261         return ret;
262     }
263 
264     ret = BSL_ASN1_GetEncodeLen(hashLen, &hashEncodeLen);
265     if (ret != CRYPT_SUCCESS) {
266         BSL_ERR_PUSH_ERROR(ret);
267         return ret;
268     }
269 
270     ret = BSL_ASN1_GetEncodeLen(dataLen, &cipherEncodeLen);
271     if (ret != CRYPT_SUCCESS) {
272         BSL_ERR_PUSH_ERROR(ret);
273         return ret;
274     }
275 
276     if (xEncodeLen > UINT32_MAX - yEncodeLen ||
277         (xEncodeLen + yEncodeLen) > UINT32_MAX - hashEncodeLen ||
278         (xEncodeLen + yEncodeLen + hashEncodeLen) > UINT32_MAX - cipherEncodeLen) {
279         BSL_ERR_PUSH_ERROR(CRYPT_ENCODE_ERR_SM2_ENCRYPT_DATA_LEN_OVERFLOW);
280         return CRYPT_ENCODE_ERR_SM2_ENCRYPT_DATA_LEN_OVERFLOW;
281     }
282 
283     // Calculate the total length of the encoded data
284     ret = BSL_ASN1_GetEncodeLen(xEncodeLen + yEncodeLen + hashEncodeLen + cipherEncodeLen, maxLen);
285     if (ret != CRYPT_SUCCESS) {
286         BSL_ERR_PUSH_ERROR(ret);
287     }
288     return ret;
289 }
290 
291 /**
292  * Reference: GM/T 0009-2012 7.2
293  * Define template for SM2 encryption data structure:
294  * SM2Cipher ::= SEQUENCE {
295  *     XCoordinate          INTEGER,
296  *     YCoordinate          INTEGER,
297  *     HASH                 OCTET STRING SIZE(32),
298  *     CipherText           OCTET STRING
299  * }
300  */
301 static BSL_ASN1_TemplateItem g_sm2EncryptTempl[] = {
302     {BSL_ASN1_TAG_CONSTRUCTED | BSL_ASN1_TAG_SEQUENCE, 0, 0},
303         {BSL_ASN1_TAG_INTEGER, 0, 1},           // x coordinate
304         {BSL_ASN1_TAG_INTEGER, 0, 1},           // y coordinate
305         {BSL_ASN1_TAG_OCTETSTRING, 0, 1},      // hash (c3)
306         {BSL_ASN1_TAG_OCTETSTRING, 0, 1}       // ciphertext (c2)
307 };
308 #define SM2_ENCRYPT_DATA_ITEM_NUM 4
309 
CheckSm2EncryptData(const CRYPT_SM2_EncryptData * data)310 int32_t CheckSm2EncryptData(const CRYPT_SM2_EncryptData *data)
311 {
312     if (data == NULL) {
313         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
314         return CRYPT_NULL_INPUT;
315     }
316 
317     // Check x and y coordinate
318     if (data->x == NULL || data->xLen == 0 || data->y == NULL || data->yLen == 0) {
319         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
320         return CRYPT_INVALID_ARG;
321     }
322 
323     // Check hash
324     if (data->hash == NULL || data->hashLen == 0) {
325         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
326         return CRYPT_INVALID_ARG;
327     }
328 
329     // Check cipher
330     if (data->cipher == NULL || data->cipherLen == 0) {
331         BSL_ERR_PUSH_ERROR(CRYPT_INVALID_ARG);
332         return CRYPT_INVALID_ARG;
333     }
334 
335     return CRYPT_SUCCESS;
336 }
337 
CRYPT_EAL_EncodeSm2EncryptData(const CRYPT_SM2_EncryptData * data,uint8_t * encode,uint32_t * encodeLen)338 int32_t CRYPT_EAL_EncodeSm2EncryptData(const CRYPT_SM2_EncryptData *data, uint8_t *encode, uint32_t *encodeLen)
339 {
340     int32_t ret = CheckSm2EncryptData(data);
341     if (ret != CRYPT_SUCCESS) {
342         BSL_ERR_PUSH_ERROR(ret);
343         return ret;
344     }
345     if (encode == NULL || encodeLen == NULL) {
346         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
347         return CRYPT_NULL_INPUT;
348     }
349 
350     BSL_ASN1_Buffer asnArr[SM2_ENCRYPT_DATA_ITEM_NUM] = {
351         {BSL_ASN1_TAG_INTEGER, data->xLen, data->x},        // x coordinate
352         {BSL_ASN1_TAG_INTEGER, data->yLen, data->y},        // y coordinate
353         {BSL_ASN1_TAG_OCTETSTRING, data->hashLen, data->hash},       // hash
354         {BSL_ASN1_TAG_OCTETSTRING, data->cipherLen, data->cipher}    // ciphertext
355     };
356     BSL_ASN1_Template templ = {g_sm2EncryptTempl, sizeof(g_sm2EncryptTempl) / sizeof(g_sm2EncryptTempl[0])};
357 
358     return EncodeAsn1Template(&templ, asnArr, SM2_ENCRYPT_DATA_ITEM_NUM, encode, encodeLen);
359 }
360 
CRYPT_EAL_DecodeSm2EncryptData(const uint8_t * encode,uint32_t encodeLen,CRYPT_SM2_EncryptData * data)361 int32_t CRYPT_EAL_DecodeSm2EncryptData(const uint8_t *encode, uint32_t encodeLen, CRYPT_SM2_EncryptData *data)
362 {
363     int32_t ret = CheckSm2EncryptData(data);
364     if (ret != CRYPT_SUCCESS) {
365         BSL_ERR_PUSH_ERROR(ret);
366         return ret;
367     }
368     if (encode == NULL || encodeLen == 0) {
369         BSL_ERR_PUSH_ERROR(CRYPT_NULL_INPUT);
370         return CRYPT_NULL_INPUT;
371     }
372 
373     BSL_ASN1_Buffer asnArr[SM2_ENCRYPT_DATA_ITEM_NUM] = {0};
374     BSL_ASN1_Template templ = {g_sm2EncryptTempl, sizeof(g_sm2EncryptTempl) / sizeof(g_sm2EncryptTempl[0])};
375     ret = DecodeAsn1Template(encode, encodeLen, &templ, asnArr, SM2_ENCRYPT_DATA_ITEM_NUM);
376     if (ret != CRYPT_SUCCESS) {
377         BSL_ERR_PUSH_ERROR(ret);
378         return ret;
379     }
380 
381     // Validate lengths
382     if (asnArr[0].len > data->xLen || asnArr[1].len > data->yLen ||
383         asnArr[2].len > data->hashLen ||   // 2: hash
384         asnArr[3].len > data->cipherLen) { // 3: cipher
385         BSL_ERR_PUSH_ERROR(CRYPT_DECODE_BUFF_NOT_ENOUGH);
386         return CRYPT_DECODE_BUFF_NOT_ENOUGH;
387     }
388     // 1: point xy
389     (void)memcpy_s(data->x + (data->xLen - asnArr[0].len), asnArr[0].len, asnArr[0].buff, asnArr[0].len);
390     (void)memcpy_s(data->y + (data->yLen - asnArr[1].len), asnArr[1].len, asnArr[1].buff, asnArr[1].len);
391     (void)memcpy_s(data->hash, data->hashLen, asnArr[2].buff, asnArr[2].len);     // 2: hash
392     (void)memcpy_s(data->cipher, data->cipherLen, asnArr[3].buff, asnArr[3].len); // 3: cipher
393     data->hashLen = asnArr[2].len;   // 2: hash
394     data->cipherLen = asnArr[3].len; // 3: cipher
395 
396     return CRYPT_SUCCESS;
397 }
398 #endif // HITLS_CRYPTO_SM2_CRYPT
399 
400 #endif
401