Check md_size isn't negative before we use it
[openssl.git] / crypto / sm2 / sm2_pmeth.c
1 /*
2  * Copyright 2006-2018 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "internal/cryptlib.h"
11 #include <openssl/asn1t.h>
12 #include <openssl/ec.h>
13 #include <openssl/evp.h>
14 #include "internal/evp_int.h"
15 #include "internal/sm2.h"
16 #include "internal/sm2err.h"
17
18 /* EC pkey context structure */
19
20 typedef struct {
21     /* Key and paramgen group */
22     EC_GROUP *gen_group;
23     /* message digest */
24     const EVP_MD *md;
25 } SM2_PKEY_CTX;
26
27 static int pkey_sm2_init(EVP_PKEY_CTX *ctx)
28 {
29     SM2_PKEY_CTX *dctx;
30
31     if ((dctx = OPENSSL_zalloc(sizeof(*dctx))) == NULL) {
32         SM2err(SM2_F_PKEY_SM2_INIT, ERR_R_MALLOC_FAILURE);
33         return 0;
34     }
35
36     ctx->data = dctx;
37     return 1;
38 }
39
40 static void pkey_sm2_cleanup(EVP_PKEY_CTX *ctx)
41 {
42     SM2_PKEY_CTX *dctx = ctx->data;
43
44     if (dctx != NULL) {
45         EC_GROUP_free(dctx->gen_group);
46         OPENSSL_free(dctx);
47         ctx->data = NULL;
48     }
49 }
50
51 static int pkey_sm2_copy(EVP_PKEY_CTX *dst, EVP_PKEY_CTX *src)
52 {
53     SM2_PKEY_CTX *dctx, *sctx;
54
55     if (!pkey_sm2_init(dst))
56         return 0;
57     sctx = src->data;
58     dctx = dst->data;
59     if (sctx->gen_group != NULL) {
60         dctx->gen_group = EC_GROUP_dup(sctx->gen_group);
61         if (dctx->gen_group == NULL) {
62             pkey_sm2_cleanup(dst);
63             return 0;
64         }
65     }
66     dctx->md = sctx->md;
67
68     return 1;
69 }
70
71 static int pkey_sm2_sign(EVP_PKEY_CTX *ctx, unsigned char *sig, size_t *siglen,
72                          const unsigned char *tbs, size_t tbslen)
73 {
74     int ret;
75     unsigned int sltmp;
76     EC_KEY *ec = ctx->pkey->pkey.ec;
77     const int sig_sz = ECDSA_size(ctx->pkey->pkey.ec);
78
79     if (sig_sz <= 0) {
80         return 0;
81     }
82
83     if (sig == NULL) {
84         *siglen = (size_t)sig_sz;
85         return 1;
86     }
87
88     if (*siglen < (size_t)sig_sz) {
89         SM2err(SM2_F_PKEY_SM2_SIGN, SM2_R_BUFFER_TOO_SMALL);
90         return 0;
91     }
92
93     ret = sm2_sign(tbs, tbslen, sig, &sltmp, ec);
94
95     if (ret <= 0)
96         return ret;
97     *siglen = (size_t)sltmp;
98     return 1;
99 }
100
101 static int pkey_sm2_verify(EVP_PKEY_CTX *ctx,
102                            const unsigned char *sig, size_t siglen,
103                            const unsigned char *tbs, size_t tbslen)
104 {
105     EC_KEY *ec = ctx->pkey->pkey.ec;
106
107     return sm2_verify(tbs, tbslen, sig, siglen, ec);
108 }
109
110 static int pkey_sm2_encrypt(EVP_PKEY_CTX *ctx,
111                             unsigned char *out, size_t *outlen,
112                             const unsigned char *in, size_t inlen)
113 {
114     EC_KEY *ec = ctx->pkey->pkey.ec;
115     SM2_PKEY_CTX *dctx = ctx->data;
116     const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
117
118     if (out == NULL) {
119         if (!sm2_ciphertext_size(ec, md, inlen, outlen))
120             return -1;
121         else
122             return 1;
123     }
124
125     return sm2_encrypt(ec, md, in, inlen, out, outlen);
126 }
127
128 static int pkey_sm2_decrypt(EVP_PKEY_CTX *ctx,
129                             unsigned char *out, size_t *outlen,
130                             const unsigned char *in, size_t inlen)
131 {
132     EC_KEY *ec = ctx->pkey->pkey.ec;
133     SM2_PKEY_CTX *dctx = ctx->data;
134     const EVP_MD *md = (dctx->md == NULL) ? EVP_sm3() : dctx->md;
135
136     if (out == NULL) {
137         if (!sm2_plaintext_size(ec, md, inlen, outlen))
138             return -1;
139         else
140             return 1;
141     }
142
143     return sm2_decrypt(ec, md, in, inlen, out, outlen);
144 }
145
146 static int pkey_sm2_ctrl(EVP_PKEY_CTX *ctx, int type, int p1, void *p2)
147 {
148     SM2_PKEY_CTX *dctx = ctx->data;
149     EC_GROUP *group;
150
151     switch (type) {
152     case EVP_PKEY_CTRL_EC_PARAMGEN_CURVE_NID:
153         group = EC_GROUP_new_by_curve_name(p1);
154         if (group == NULL) {
155             SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_INVALID_CURVE);
156             return 0;
157         }
158         EC_GROUP_free(dctx->gen_group);
159         dctx->gen_group = group;
160         return 1;
161
162     case EVP_PKEY_CTRL_EC_PARAM_ENC:
163         if (dctx->gen_group == NULL) {
164             SM2err(SM2_F_PKEY_SM2_CTRL, SM2_R_NO_PARAMETERS_SET);
165             return 0;
166         }
167         EC_GROUP_set_asn1_flag(dctx->gen_group, p1);
168         return 1;
169
170     case EVP_PKEY_CTRL_MD:
171         dctx->md = p2;
172         return 1;
173
174     case EVP_PKEY_CTRL_GET_MD:
175         *(const EVP_MD **)p2 = dctx->md;
176         return 1;
177
178     default:
179         return -2;
180
181     }
182 }
183
184 static int pkey_sm2_ctrl_str(EVP_PKEY_CTX *ctx,
185                              const char *type, const char *value)
186 {
187     if (strcmp(type, "ec_paramgen_curve") == 0) {
188         int nid = NID_undef;
189
190         if (((nid = EC_curve_nist2nid(value)) == NID_undef)
191             && ((nid = OBJ_sn2nid(value)) == NID_undef)
192             && ((nid = OBJ_ln2nid(value)) == NID_undef)) {
193             SM2err(SM2_F_PKEY_SM2_CTRL_STR, SM2_R_INVALID_CURVE);
194             return 0;
195         }
196         return EVP_PKEY_CTX_set_ec_paramgen_curve_nid(ctx, nid);
197     } else if (strcmp(type, "ec_param_enc") == 0) {
198         int param_enc;
199
200         if (strcmp(value, "explicit") == 0)
201             param_enc = 0;
202         else if (strcmp(value, "named_curve") == 0)
203             param_enc = OPENSSL_EC_NAMED_CURVE;
204         else
205             return -2;
206         return EVP_PKEY_CTX_set_ec_param_enc(ctx, param_enc);
207     }
208
209     return -2;
210 }
211
212 const EVP_PKEY_METHOD sm2_pkey_meth = {
213     EVP_PKEY_SM2,
214     0,
215     pkey_sm2_init,
216     pkey_sm2_copy,
217     pkey_sm2_cleanup,
218
219     0,
220     0,
221
222     0,
223     0,
224
225     0,
226     pkey_sm2_sign,
227
228     0,
229     pkey_sm2_verify,
230
231     0, 0,
232
233     0, 0, 0, 0,
234
235     0,
236     pkey_sm2_encrypt,
237
238     0,
239     pkey_sm2_decrypt,
240
241     0,
242     0,
243     pkey_sm2_ctrl,
244     pkey_sm2_ctrl_str
245 };