1 /*
2 * Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 #include "hvb_sm2.h"
16 #include "hvb_sm3.h"
17 #include "hvb_sm2_bn.h"
18 #include "hvb_sysdeps.h"
19 #include "hvb_util.h"
20 #include <stdio.h>
21 #include <stdlib.h>
22
23 #define SM2_POINT_LEN (SM2_KEY_LEN << 1)
24 /* user ID's max bits */
25 #define SM2_MAX_ID_BITS 65535
26 /* user ID's max len */
27 #define SM2_MAX_ID_LENGTH (SM2_MAX_ID_BITS / 8)
28
sm2_verify_check_param(const struct sm2_pubkey * pkey,const uint8_t * pid,uint32_t idlen,const uint8_t * pmsg,uint32_t msglen,const uint8_t * psign,uint32_t signlen)29 static int sm2_verify_check_param(const struct sm2_pubkey *pkey, const uint8_t *pid, uint32_t idlen,
30 const uint8_t *pmsg, uint32_t msglen, const uint8_t *psign, uint32_t signlen)
31 {
32 if (hvb_check(!pkey || !pid || !pmsg || !psign))
33 return SM2_POINTER_NULL;
34
35 if (hvb_check(signlen != SM2_POINT_LEN || idlen == 0 || msglen == 0 || idlen > SM2_MAX_ID_LENGTH))
36 return SM2_PARAM_LEN_ERROR;
37
38 return SM2_VERIFY_OK;
39 }
40
sm2_compute_z(const struct sm2_pubkey * pkey,const uint8_t * pid,uint32_t idlen,uint8_t * pz,uint32_t * pzlen)41 static int sm2_compute_z(const struct sm2_pubkey *pkey, const uint8_t *pid, uint32_t idlen,
42 uint8_t *pz, uint32_t *pzlen)
43 {
44 int ret;
45 uint16_t idx;
46 struct sm3_ctx_t ctx = { 0 };
47
48 ret = hvb_sm3_init(&ctx);
49 if (hvb_check(ret != SM3_OK))
50 return SM2_HASH_INIT_ERROR;
51
52 idx = (uint16_t)byte2bit(idlen);
53 idx = u16_inv(idx);
54 ret = hvb_sm3_update(&ctx, &idx, sizeof(idx));
55 if (hvb_check(ret != SM3_OK))
56 return SM2_HASH_UPDATE_ERROR;
57
58 ret = hvb_sm3_update(&ctx, pid, idlen);
59 if (hvb_check(ret != SM3_OK))
60 return SM2_HASH_UPDATE_ERROR;
61
62 uint8_t *sm2_params[] = {
63 sm2_bn_get_param_a(),
64 sm2_bn_get_param_b(),
65 sm2_bn_get_param_gx(),
66 sm2_bn_get_param_gy(),
67 (uint8_t *)pkey->x,
68 (uint8_t *)pkey->y
69 };
70
71 for (idx = 0; idx < array_size(sm2_params); idx++) {
72 ret = hvb_sm3_update(&ctx, sm2_params[idx], SM2_KEY_LEN);
73 if (hvb_check(ret != SM3_OK))
74 return SM2_HASH_UPDATE_ERROR;
75 }
76
77 ret = hvb_sm3_final(&ctx, pz, pzlen);
78 if (hvb_check(ret != SM3_OK))
79 return SM2_HASH_FINALE_ERROR;
80
81 return SM2_VERIFY_OK;
82 }
83
sm2_compute_digest(const uint8_t * pmsg,uint32_t msglen,const uint8_t * pz,uint32_t pzlen,uint8_t * pdigest,uint32_t * pdigestlen)84 static int sm2_compute_digest(const uint8_t *pmsg, uint32_t msglen, const uint8_t *pz, uint32_t pzlen,
85 uint8_t *pdigest, uint32_t *pdigestlen)
86 {
87 int ret;
88 struct sm3_ctx_t ctx;
89
90 ret = hvb_sm3_init(&ctx);
91 if (hvb_check(ret != SM3_OK))
92 return SM2_HASH_INIT_ERROR;
93
94 ret = hvb_sm3_update(&ctx, pz, pzlen);
95 if (hvb_check(ret != SM3_OK))
96 return SM2_HASH_UPDATE_ERROR;
97
98 ret = hvb_sm3_update(&ctx, pmsg, msglen);
99 if (hvb_check(ret != SM3_OK))
100 return SM2_HASH_UPDATE_ERROR;
101
102 ret = hvb_sm3_final(&ctx, pdigest, pdigestlen);
103 if (hvb_check(ret != SM3_OK))
104 return SM2_HASH_FINALE_ERROR;
105
106 return SM2_VERIFY_OK;
107 }
108
sm2_check_rs(uint64_t r[],uint64_t s[],uint64_t t[])109 static int sm2_check_rs(uint64_t r[], uint64_t s[], uint64_t t[])
110 {
111 int ret;
112
113 ret = sm2_bn_check_indomain_n(r);
114 if (hvb_check(ret != SM2_BN_OK))
115 return SM2_R_NOT_INDOMAIN;
116
117 ret = sm2_bn_check_indomain_n(s);
118 if (hvb_check(ret != SM2_BN_OK))
119 return SM2_S_NOT_INDOMAIN;
120
121 /* t = (r + s) mod n */
122 ret = sm2_bn_add_mod_n(r, s, t);
123 if (hvb_check(ret != SM2_BN_OK))
124 return SM2_MOD_ADD_ERROR;
125
126 ret = sm2_bn_is_valid(t);
127 if (hvb_check(ret != SM2_BN_OK))
128 return SM2_R_ADD_S_ERROR;
129
130 return SM2_VERIFY_OK;
131 }
132
sm2_digest_verify(const struct sm2_pubkey * pkey,const uint8_t * pdigest,uint32_t digestlen,const uint8_t * psign,uint32_t signlen)133 int sm2_digest_verify(const struct sm2_pubkey *pkey, const uint8_t *pdigest, uint32_t digestlen,
134 const uint8_t *psign, uint32_t signlen)
135 {
136 int ret;
137 uint64_t r[SM2_DATA_DWORD_SIZE] = { 0 };
138 uint64_t s[SM2_DATA_DWORD_SIZE] = { 0 };
139 uint64_t t[SM2_DATA_DWORD_SIZE] = { 0 };
140 uint64_t digest_tmp[SM2_DATA_DWORD_SIZE] = { 0 };
141 struct sm2_point_aff tmp_point = { 0 };
142
143 if (hvb_check(digestlen != SM3_OUT_BYTE_SIZE || signlen != SM2_POINT_LEN)) {
144 return SM2_PARAM_LEN_ERROR;
145 }
146
147 invert_copy_byte((uint8_t *)digest_tmp, (uint8_t *)pdigest, digestlen);
148 invert_copy_byte((uint8_t *)r, (uint8_t *)psign, SM2_KEY_LEN);
149 invert_copy_byte((uint8_t *)s, (uint8_t *)psign + SM2_KEY_LEN, SM2_KEY_LEN);
150 invert_copy_byte((uint8_t *)tmp_point.x, (uint8_t *)pkey->x, SM2_KEY_LEN);
151 invert_copy_byte((uint8_t *)tmp_point.y, (uint8_t *)pkey->y, SM2_KEY_LEN);
152 ret = sm2_check_rs(r, s, t);
153 if (hvb_check(ret != SM2_VERIFY_OK))
154 return ret;
155
156 ret = sm2_point_mul_add(s, t, &tmp_point, &tmp_point);
157 if (hvb_check(ret != SM2_BN_OK))
158 return SM2_POINT_MUL_ADD_ERROR;
159
160 ret = sm2_bn_add_mod_n(tmp_point.x, digest_tmp, t);
161 if (hvb_check(ret != SM2_BN_OK))
162 return SM2_MOD_ADD_ERROR;
163
164 int ret_first = sm2_bn_cmp(r, t);
165 int ret_second = sm2_bn_cmp(r, t);
166 if (hvb_check(ret_first != 0 || ret_second != 0))
167 return SM2_VERIFY_ERROR;
168
169 return SM2_VERIFY_OK + ret_first + ret_second;
170 }
171
hvb_sm2_verify(const struct sm2_pubkey * pkey,const uint8_t * pid,uint32_t idlen,const uint8_t * pmsg,uint32_t msglen,const uint8_t * psign,uint32_t signlen)172 int hvb_sm2_verify(const struct sm2_pubkey *pkey, const uint8_t *pid, uint32_t idlen,
173 const uint8_t *pmsg, uint32_t msglen, const uint8_t *psign, uint32_t signlen)
174 {
175 uint8_t pz[SM3_OUT_BYTE_SIZE] = { 0 };
176 uint8_t pdigest[SM3_OUT_BYTE_SIZE] = { 0 };
177 uint32_t zlen = SM3_OUT_BYTE_SIZE;
178 uint32_t digestlen = SM3_OUT_BYTE_SIZE;
179 int ret;
180
181 ret = sm2_verify_check_param(pkey, pid, idlen, pmsg, msglen, psign, signlen);
182 if (hvb_check(ret != SM2_VERIFY_OK))
183 return SM2_PARAM_ERROR;
184
185 ret = sm2_compute_z(pkey, pid, idlen, pz, &zlen);
186 if (hvb_check(ret != SM2_VERIFY_OK))
187 return SM2_COMPUTE_Z_ERROR;
188
189 ret = sm2_compute_digest(pmsg, msglen, pz, zlen, pdigest, &digestlen);
190 if (hvb_check(ret != SM2_VERIFY_OK))
191 return SM2_COMPUTE_DIGEST_ERROR;
192
193 return sm2_digest_verify(pkey, pdigest, digestlen, psign, signlen);
194 }
195