summaryrefslogtreecommitdiff
path: root/src/lib/libcrypto/sm2/sm2_pmeth.c
diff options
context:
space:
mode:
authortb <>2021-08-18 16:04:32 +0000
committertb <>2021-08-18 16:04:32 +0000
commit27a4a421da356671ca87fff69b8b7340d284659c (patch)
treeff95b8757df3a4b8d97a0f3f19a7c9962ba1076f /src/lib/libcrypto/sm2/sm2_pmeth.c
parente9cfb6e09338ad2081dfa06cdae4acc1dc0c78d9 (diff)
downloadopenbsd-27a4a421da356671ca87fff69b8b7340d284659c.tar.gz
openbsd-27a4a421da356671ca87fff69b8b7340d284659c.tar.bz2
openbsd-27a4a421da356671ca87fff69b8b7340d284659c.zip
Import initial code for the SM2 cipher
This adds the SM2 algorithm defined in the Chinese standards GB/T 32918.1-2016, GB/T 32918.2-2016, GB/T 32918.3-2016, GB/T 32918.4-2016 and GB/T 32918.5-2017. This is an ISC licensed implementation contributed by Ribose.inc, based on the same code that was contributed to OpenSSL by Jack Lloyd. The port to LibreSSL was done by Ronald Tse and Nickolay Olshevsky. Github PR #105 I made quite a few cleanup passes on this, but more is needed, some of which will happen in-tree before this is linked to the build. ok deraadt inoguchi (a long time ago), jsing
Diffstat (limited to 'src/lib/libcrypto/sm2/sm2_pmeth.c')
-rw-r--r--src/lib/libcrypto/sm2/sm2_pmeth.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/src/lib/libcrypto/sm2/sm2_pmeth.c b/src/lib/libcrypto/sm2/sm2_pmeth.c
new file mode 100644
index 0000000000..af6e180a70
--- /dev/null
+++ b/src/lib/libcrypto/sm2/sm2_pmeth.c
@@ -0,0 +1,316 @@
1/* $OpenBSD: sm2_pmeth.c,v 1.1.1.1 2021/08/18 16:04:32 tb Exp $ */
2/*
3 * Copyright (c) 2017, 2019 Ribose Inc
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef OPENSSL_NO_SM2
19
20#include <string.h>
21
22#include <openssl/sm2.h>
23#include <openssl/asn1t.h>
24#include <openssl/x509.h>
25#include <openssl/err.h>
26#include <openssl/evp.h>
27
28#include "evp_locl.h"
29#include "sm2_locl.h"
30
31/* SM2 pkey context structure */
32
33typedef struct {
34 /* key and paramgen group */
35 EC_GROUP *gen_group;
36 /* message digest */
37 const EVP_MD *md;
38 EVP_MD_CTX *md_ctx;
39 /* personalization string */
40 uint8_t* uid;
41 size_t uid_len;
42} SM2_PKEY_CTX;
43
44static int
45pkey_sm2_init(EVP_PKEY_CTX *ctx)
46{
47 SM2_PKEY_CTX *dctx;
48
49 if ((dctx = calloc(1, sizeof(*dctx))) == NULL) {
50 SM2error(ERR_R_MALLOC_FAILURE);
51 return 0;
52 }
53 ctx->data = dctx;
54 return 1;
55}
56
57static void
58pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
59{
60 SM2_PKEY_CTX *dctx = ctx->data;
61
62 if (ctx == NULL || ctx->data == NULL)
63 return;
64
65 EC_GROUP_free(dctx->gen_group);
66 free(dctx->uid);
67 free(dctx);
68 ctx->data = NULL;
69}
70
71static int
72pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
73{
74 SM2_PKEY_CTX *dctx, *sctx;
75
76 if (!pkey_sm2_init(dst))
77 return 0;
78 sctx = src->data;
79 dctx = dst->data;
80 if (sctx->gen_group) {
81 if ((dctx->gen_group = EC_GROUP_dup(sctx->gen_group)) == NULL) {
82 SM2error(ERR_R_MALLOC_FAILURE);
83 goto err;
84 }
85 }
86
87 if (sctx->uid != NULL) {
88 if ((dctx->uid = malloc(sctx->uid_len)) == NULL) {
89 SM2error(ERR_R_MALLOC_FAILURE);
90 goto err;
91 }
92 memcpy(dctx->uid, sctx->uid, sctx->uid_len);
93 dctx->uid_len = sctx->uid_len;
94 }
95
96 dctx->md = sctx->md;
97
98 if (!EVP_MD_CTX_copy(dctx->md_ctx, sctx->md_ctx))
99 goto err;
100
101 return 1;
102
103 err:
104 pkey_sm2_cleanup(dst);
105 return 0;
106}
107
108static int
109pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
110 const unsigned char *tbs, size_t tbslen)
111{
112 unsigned int sltmp;
113 int ret, sig_sz;
114
115 if ((sig_sz = ECDSA_size(ctx->pkey->pkey.ec)) <= 0)
116 return 0;
117
118 if (sig == NULL) {
119 *siglen = sig_sz;
120 return 1;
121 }
122
123 if (*siglen < (size_t)sig_sz) {
124 SM2error(SM2_R_BUFFER_TOO_SMALL);
125 return 0;
126 }
127
128 if ((ret = SM2_sign(tbs, tbslen, sig, &sltmp, ctx->pkey->pkey.ec)) <= 0)
129 return ret;
130
131 *siglen = (size_t)sltmp;
132 return 1;
133}
134
135static int
136pkey_sm2_verify(EVP_PKEY_CTX *ctx, const unsigned char *sig, size_t siglen,
137 const unsigned char *tbs, size_t tbslen)
138{
139 return SM2_verify(tbs, tbslen, sig, siglen, ctx->pkey->pkey.ec);
140}
141
142static int
143pkey_sm2_encrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
144 const unsigned char *in, size_t inlen)
145{
146 SM2_PKEY_CTX *dctx = ctx->data;
147 const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
148
149 if (out == NULL) {
150 if (!SM2_ciphertext_size(ctx->pkey->pkey.ec, md, inlen, outlen))
151 return -1;
152 else
153 return 1;
154 }
155
156 return SM2_encrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen);
157}
158
159static int
160pkey_sm2_decrypt(EVP_PKEY_CTX *ctx, unsigned char *out, size_t *outlen,
161 const unsigned char *in, size_t inlen)
162{
163 SM2_PKEY_CTX *dctx = ctx->data;
164 const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
165
166 if (out == NULL) {
167 if (!SM2_plaintext_size(ctx->pkey->pkey.ec, md, inlen, outlen))
168 return -1;
169 else
170 return 1;
171 }
172
173 return SM2_decrypt(ctx->pkey->pkey.ec, md, in, inlen, out, outlen);
174}
175
176static int
177pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
178{
179 SM2_PKEY_CTX *dctx = ctx->data;
180 EC_GROUP *group = NULL;
181
182 switch (type) {
183 case EVP_PKEY_CTRL_DIGESTINIT:
184 dctx->md_ctx = p2;
185 return 1;
186
187 case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
188 if ((group = EC_GROUP_new_by_curve_name(p1)) == NULL) {
189 SM2error(SM2_R_INVALID_CURVE);
190 return 0;
191 }
192 EC_GROUP_free(dctx->gen_group);
193 dctx->gen_group = group;
194 return 1;
195
196 case EVP_PKEY_CTRL_SM2_SET_UID:
197 if ((p1 < 0) || ((p1 == 0) && (p2 != NULL))) {
198 SM2error(SM2_R_INVALID_ARGUMENT);
199 return 0;
200 }
201 if ((p1 > 0) && (p2 == NULL)) {
202 SM2error(ERR_R_PASSED_NULL_PARAMETER);
203 return 0;
204 }
205 free(dctx->uid);
206 if (p2 == NULL) {
207 dctx->uid = NULL;
208 dctx->uid_len = 0;
209 return 1;
210 }
211
212 if ((dctx->uid = malloc(p1)) == NULL) {
213 SM2error(ERR_R_MALLOC_FAILURE);
214 return 1;
215 }
216 memcpy(dctx->uid, p2, p1);
217 dctx->uid_len = p1;
218 return 1;
219
220 case EVP_PKEY_CTRL_SM2_HASH_UID:
221 {
222 const EVP_MD* md;
223 uint8_t za[EVP_MAX_MD_SIZE] = {0};
224 int md_len;
225
226 if (dctx->uid == NULL) {
227 SM2error(SM2_R_INVALID_ARGUMENT);
228 return 0;
229 }
230
231 if ((md = EVP_MD_CTX_md(dctx->md_ctx)) == NULL) {
232 SM2error(ERR_R_EVP_LIB);
233 return 0;
234 }
235
236 if ((md_len = EVP_MD_size(md)) < 0) {
237 SM2error(SM2_R_INVALID_DIGEST);
238 return 0;
239 }
240
241 if (sm2_compute_userid_digest(za, md, dctx->uid, dctx->uid_len,
242 ctx->pkey->pkey.ec) != 1) {
243 SM2error(SM2_R_DIGEST_FAILURE);
244 return 0;
245 }
246 return EVP_DigestUpdate(dctx->md_ctx, za, md_len);
247 }
248
249 case EVP_PKEY_CTRL_SM2_GET_UID_LEN:
250 if (p2 == NULL) {
251 SM2error(ERR_R_PASSED_NULL_PARAMETER);
252 return 0;
253 }
254 *(size_t *)p2 = dctx->uid_len;
255 return 1;
256
257 case EVP_PKEY_CTRL_SM2_GET_UID:
258 if (p2 == NULL) {
259 SM2error(ERR_R_PASSED_NULL_PARAMETER);
260 return 0;
261 }
262 if (dctx->uid_len == 0) {
263 return 1;
264 }
265 memcpy(p2, dctx->uid, dctx->uid_len);
266 return 1;
267
268 case EVP_PKEY_CTRL_MD:
269 dctx->md = p2;
270 return 1;
271
272 default:
273 return -2;
274 }
275}
276
277static int
278pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx, const char *type, const char *value)
279{
280 int nid;
281
282 if (strcmp(type, "ec_paramgen_curve") == 0) {
283 if (((nid = EC_curve_nist2nid(value)) == NID_undef) &&
284 ((nid = OBJ_sn2nid(value)) == NID_undef) &&
285 ((nid = OBJ_ln2nid(value)) == NID_undef)) {
286 SM2error(SM2_R_INVALID_CURVE);
287 return 0;
288 }
289 return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
290 } else if (strcmp(type, "sm2_uid") == 0) {
291 return EVP_PKEY_CTX_set_sm2_uid(ctx, (void*) value,
292 (int)strlen(value));
293 }
294
295 return -2;
296}
297
298const EVP_PKEY_METHOD sm2_pkey_meth = {
299 .pkey_id = EVP_PKEY_SM2,
300 .init = pkey_sm2_init,
301 .copy = pkey_sm2_copy,
302 .cleanup = pkey_sm2_cleanup,
303
304 .sign = pkey_sm2_sign,
305
306 .verify = pkey_sm2_verify,
307
308 .encrypt = pkey_sm2_encrypt,
309
310 .decrypt = pkey_sm2_decrypt,
311
312 .ctrl = pkey_sm2_ctrl,
313 .ctrl_str = pkey_sm2_ctrl_str
314};
315
316#endif /* OPENSSL_NO_SM2 */