Line data Source code
1 : /* crypto/ecdsa/ecs_lib.c */
2 : /* ====================================================================
3 : * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
4 : *
5 : * Redistribution and use in source and binary forms, with or without
6 : * modification, are permitted provided that the following conditions
7 : * are met:
8 : *
9 : * 1. Redistributions of source code must retain the above copyright
10 : * notice, this list of conditions and the following disclaimer.
11 : *
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in
14 : * the documentation and/or other materials provided with the
15 : * distribution.
16 : *
17 : * 3. All advertising materials mentioning features or use of this
18 : * software must display the following acknowledgment:
19 : * "This product includes software developed by the OpenSSL Project
20 : * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
21 : *
22 : * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
23 : * endorse or promote products derived from this software without
24 : * prior written permission. For written permission, please contact
25 : * openssl-core@OpenSSL.org.
26 : *
27 : * 5. Products derived from this software may not be called "OpenSSL"
28 : * nor may "OpenSSL" appear in their names without prior written
29 : * permission of the OpenSSL Project.
30 : *
31 : * 6. Redistributions of any form whatsoever must retain the following
32 : * acknowledgment:
33 : * "This product includes software developed by the OpenSSL Project
34 : * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
35 : *
36 : * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
37 : * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
38 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
39 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
40 : * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41 : * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
42 : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
43 : * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 : * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
45 : * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
46 : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
47 : * OF THE POSSIBILITY OF SUCH DAMAGE.
48 : * ====================================================================
49 : *
50 : * This product includes cryptographic software written by Eric Young
51 : * (eay@cryptsoft.com). This product includes software written by Tim
52 : * Hudson (tjh@cryptsoft.com).
53 : *
54 : */
55 :
56 : #include <string.h>
57 : #include "ecs_locl.h"
58 : #ifndef OPENSSL_NO_ENGINE
59 : # include <openssl/engine.h>
60 : #endif
61 : #include <openssl/err.h>
62 : #include <openssl/bn.h>
63 : #ifdef OPENSSL_FIPS
64 : # include <openssl/fips.h>
65 : #endif
66 :
67 : const char ECDSA_version[] = "ECDSA" OPENSSL_VERSION_PTEXT;
68 :
69 : static const ECDSA_METHOD *default_ECDSA_method = NULL;
70 :
71 : static void *ecdsa_data_new(void);
72 : static void *ecdsa_data_dup(void *);
73 : static void ecdsa_data_free(void *);
74 :
75 0 : void ECDSA_set_default_method(const ECDSA_METHOD *meth)
76 : {
77 0 : default_ECDSA_method = meth;
78 0 : }
79 :
80 0 : const ECDSA_METHOD *ECDSA_get_default_method(void)
81 : {
82 0 : if (!default_ECDSA_method) {
83 : #ifdef OPENSSL_FIPS
84 : if (FIPS_mode())
85 : return FIPS_ecdsa_openssl();
86 : else
87 : return ECDSA_OpenSSL();
88 : #else
89 0 : default_ECDSA_method = ECDSA_OpenSSL();
90 : #endif
91 : }
92 0 : return default_ECDSA_method;
93 : }
94 :
95 0 : int ECDSA_set_method(EC_KEY *eckey, const ECDSA_METHOD *meth)
96 : {
97 : ECDSA_DATA *ecdsa;
98 :
99 0 : ecdsa = ecdsa_check(eckey);
100 :
101 0 : if (ecdsa == NULL)
102 : return 0;
103 :
104 : #ifndef OPENSSL_NO_ENGINE
105 0 : if (ecdsa->engine) {
106 0 : ENGINE_finish(ecdsa->engine);
107 0 : ecdsa->engine = NULL;
108 : }
109 : #endif
110 0 : ecdsa->meth = meth;
111 :
112 0 : return 1;
113 : }
114 :
115 0 : static ECDSA_DATA *ECDSA_DATA_new_method(ENGINE *engine)
116 : {
117 : ECDSA_DATA *ret;
118 :
119 0 : ret = (ECDSA_DATA *)OPENSSL_malloc(sizeof(ECDSA_DATA));
120 0 : if (ret == NULL) {
121 0 : ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
122 0 : return (NULL);
123 : }
124 :
125 0 : ret->init = NULL;
126 :
127 0 : ret->meth = ECDSA_get_default_method();
128 0 : ret->engine = engine;
129 : #ifndef OPENSSL_NO_ENGINE
130 0 : if (!ret->engine)
131 0 : ret->engine = ENGINE_get_default_ECDSA();
132 0 : if (ret->engine) {
133 0 : ret->meth = ENGINE_get_ECDSA(ret->engine);
134 0 : if (!ret->meth) {
135 0 : ECDSAerr(ECDSA_F_ECDSA_DATA_NEW_METHOD, ERR_R_ENGINE_LIB);
136 0 : ENGINE_finish(ret->engine);
137 0 : OPENSSL_free(ret);
138 0 : return NULL;
139 : }
140 : }
141 : #endif
142 :
143 0 : ret->flags = ret->meth->flags;
144 0 : CRYPTO_new_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data);
145 : #if 0
146 : if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
147 : CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, ret, &ret->ex_data);
148 : OPENSSL_free(ret);
149 : ret = NULL;
150 : }
151 : #endif
152 0 : return (ret);
153 : }
154 :
155 : static void *ecdsa_data_new(void)
156 : {
157 0 : return (void *)ECDSA_DATA_new_method(NULL);
158 : }
159 :
160 0 : static void *ecdsa_data_dup(void *data)
161 : {
162 : ECDSA_DATA *r = (ECDSA_DATA *)data;
163 :
164 : /* XXX: dummy operation */
165 0 : if (r == NULL)
166 : return NULL;
167 :
168 0 : return ecdsa_data_new();
169 : }
170 :
171 0 : static void ecdsa_data_free(void *data)
172 : {
173 : ECDSA_DATA *r = (ECDSA_DATA *)data;
174 :
175 : #ifndef OPENSSL_NO_ENGINE
176 0 : if (r->engine)
177 0 : ENGINE_finish(r->engine);
178 : #endif
179 0 : CRYPTO_free_ex_data(CRYPTO_EX_INDEX_ECDSA, r, &r->ex_data);
180 :
181 0 : OPENSSL_cleanse((void *)r, sizeof(ECDSA_DATA));
182 :
183 0 : OPENSSL_free(r);
184 0 : }
185 :
186 0 : ECDSA_DATA *ecdsa_check(EC_KEY *key)
187 : {
188 : ECDSA_DATA *ecdsa_data;
189 :
190 0 : void *data = EC_KEY_get_key_method_data(key, ecdsa_data_dup,
191 : ecdsa_data_free, ecdsa_data_free);
192 0 : if (data == NULL) {
193 : ecdsa_data = (ECDSA_DATA *)ecdsa_data_new();
194 0 : if (ecdsa_data == NULL)
195 : return NULL;
196 0 : data = EC_KEY_insert_key_method_data(key, (void *)ecdsa_data,
197 : ecdsa_data_dup, ecdsa_data_free,
198 : ecdsa_data_free);
199 0 : if (data != NULL) {
200 : /*
201 : * Another thread raced us to install the key_method data and
202 : * won.
203 : */
204 0 : ecdsa_data_free(ecdsa_data);
205 : ecdsa_data = (ECDSA_DATA *)data;
206 : }
207 : } else
208 : ecdsa_data = (ECDSA_DATA *)data;
209 : #ifdef OPENSSL_FIPS
210 : if (FIPS_mode() && !(ecdsa_data->flags & ECDSA_FLAG_FIPS_METHOD)
211 : && !(EC_KEY_get_flags(key) & EC_FLAG_NON_FIPS_ALLOW)) {
212 : ECDSAerr(ECDSA_F_ECDSA_CHECK, ECDSA_R_NON_FIPS_METHOD);
213 : return NULL;
214 : }
215 : #endif
216 :
217 0 : return ecdsa_data;
218 : }
219 :
220 0 : int ECDSA_size(const EC_KEY *r)
221 : {
222 : int ret, i;
223 : ASN1_INTEGER bs;
224 : BIGNUM *order = NULL;
225 : unsigned char buf[4];
226 : const EC_GROUP *group;
227 :
228 0 : if (r == NULL)
229 : return 0;
230 0 : group = EC_KEY_get0_group(r);
231 0 : if (group == NULL)
232 : return 0;
233 :
234 0 : if ((order = BN_new()) == NULL)
235 : return 0;
236 0 : if (!EC_GROUP_get_order(group, order, NULL)) {
237 0 : BN_clear_free(order);
238 0 : return 0;
239 : }
240 0 : i = BN_num_bits(order);
241 0 : bs.length = (i + 7) / 8;
242 0 : bs.data = buf;
243 0 : bs.type = V_ASN1_INTEGER;
244 : /* If the top bit is set the asn1 encoding is 1 larger. */
245 0 : buf[0] = 0xff;
246 :
247 0 : i = i2d_ASN1_INTEGER(&bs, NULL);
248 0 : i += i; /* r and s */
249 0 : ret = ASN1_object_size(1, i, V_ASN1_SEQUENCE);
250 0 : BN_clear_free(order);
251 0 : return (ret);
252 : }
253 :
254 0 : int ECDSA_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func,
255 : CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func)
256 : {
257 0 : return CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_ECDSA, argl, argp,
258 : new_func, dup_func, free_func);
259 : }
260 :
261 0 : int ECDSA_set_ex_data(EC_KEY *d, int idx, void *arg)
262 : {
263 : ECDSA_DATA *ecdsa;
264 0 : ecdsa = ecdsa_check(d);
265 0 : if (ecdsa == NULL)
266 : return 0;
267 0 : return (CRYPTO_set_ex_data(&ecdsa->ex_data, idx, arg));
268 : }
269 :
270 0 : void *ECDSA_get_ex_data(EC_KEY *d, int idx)
271 : {
272 : ECDSA_DATA *ecdsa;
273 0 : ecdsa = ecdsa_check(d);
274 0 : if (ecdsa == NULL)
275 : return NULL;
276 0 : return (CRYPTO_get_ex_data(&ecdsa->ex_data, idx));
277 : }
278 :
279 0 : ECDSA_METHOD *ECDSA_METHOD_new(ECDSA_METHOD *ecdsa_meth)
280 : {
281 : ECDSA_METHOD *ret;
282 :
283 0 : ret = OPENSSL_malloc(sizeof(ECDSA_METHOD));
284 0 : if (ret == NULL) {
285 0 : ECDSAerr(ECDSA_F_ECDSA_METHOD_NEW, ERR_R_MALLOC_FAILURE);
286 0 : return NULL;
287 : }
288 :
289 0 : if (ecdsa_meth)
290 0 : *ret = *ecdsa_meth;
291 : else {
292 0 : ret->ecdsa_sign_setup = 0;
293 0 : ret->ecdsa_do_sign = 0;
294 0 : ret->ecdsa_do_verify = 0;
295 0 : ret->name = NULL;
296 0 : ret->flags = 0;
297 : }
298 0 : ret->flags |= ECDSA_METHOD_FLAG_ALLOCATED;
299 0 : return ret;
300 : }
301 :
302 0 : void ECDSA_METHOD_set_sign(ECDSA_METHOD *ecdsa_method,
303 : ECDSA_SIG *(*ecdsa_do_sign) (const unsigned char
304 : *dgst, int dgst_len,
305 : const BIGNUM *inv,
306 : const BIGNUM *rp,
307 : EC_KEY *eckey))
308 : {
309 0 : ecdsa_method->ecdsa_do_sign = ecdsa_do_sign;
310 0 : }
311 :
312 0 : void ECDSA_METHOD_set_sign_setup(ECDSA_METHOD *ecdsa_method,
313 : int (*ecdsa_sign_setup) (EC_KEY *eckey,
314 : BN_CTX *ctx,
315 : BIGNUM **kinv,
316 : BIGNUM **r))
317 : {
318 0 : ecdsa_method->ecdsa_sign_setup = ecdsa_sign_setup;
319 0 : }
320 :
321 0 : void ECDSA_METHOD_set_verify(ECDSA_METHOD *ecdsa_method,
322 : int (*ecdsa_do_verify) (const unsigned char
323 : *dgst, int dgst_len,
324 : const ECDSA_SIG *sig,
325 : EC_KEY *eckey))
326 : {
327 0 : ecdsa_method->ecdsa_do_verify = ecdsa_do_verify;
328 0 : }
329 :
330 0 : void ECDSA_METHOD_set_flags(ECDSA_METHOD *ecdsa_method, int flags)
331 : {
332 0 : ecdsa_method->flags = flags | ECDSA_METHOD_FLAG_ALLOCATED;
333 0 : }
334 :
335 0 : void ECDSA_METHOD_set_name(ECDSA_METHOD *ecdsa_method, char *name)
336 : {
337 0 : ecdsa_method->name = name;
338 0 : }
339 :
340 0 : void ECDSA_METHOD_free(ECDSA_METHOD *ecdsa_method)
341 : {
342 0 : if (ecdsa_method->flags & ECDSA_METHOD_FLAG_ALLOCATED)
343 0 : OPENSSL_free(ecdsa_method);
344 0 : }
345 :
346 0 : void ECDSA_METHOD_set_app_data(ECDSA_METHOD *ecdsa_method, void *app)
347 : {
348 0 : ecdsa_method->app_data = app;
349 0 : }
350 :
351 0 : void *ECDSA_METHOD_get_app_data(ECDSA_METHOD *ecdsa_method)
352 : {
353 0 : return ecdsa_method->app_data;
354 : }
|