37e6fe042f7a6c1aeb608454cc1c17fc767ef1be
[openssl.git] / crypto / ec / ec_lib.c
1 /* crypto/ec/ec_lib.c */
2 /* ====================================================================
3  * Copyright (c) 1998-2001 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
58 #include <openssl/err.h>
59
60 #include "ec_lcl.h"
61
62
63 /* functions for EC_GROUP objects */
64
65 EC_GROUP *EC_GROUP_new(const EC_METHOD *meth)
66         {
67         EC_GROUP *ret;
68
69         if (meth == NULL)
70                 {
71                 ECerr(EC_F_EC_GROUP_NEW, ERR_R_PASSED_NULL_PARAMETER);
72                 return NULL;
73                 }
74         if (meth->group_init == 0)
75                 {
76                 ECerr(EC_F_EC_GROUP_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
77                 return NULL;
78                 }
79
80         ret = OPENSSL_malloc(sizeof *ret);
81         if (ret == NULL)
82                 {
83                 ECerr(EC_F_EC_GROUP_NEW, ERR_R_MALLOC_FAILURE);
84                 return NULL;
85                 }
86
87         ret->meth = meth;
88         
89         if (!meth->group_init(ret))
90                 {
91                 OPENSSL_free(ret);
92                 return NULL;
93                 }
94         
95         return ret;
96         }
97
98
99 int EC_GROUP_set_curve_GFp(EC_GROUP *group, const BIGNUM *p, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
100         {
101         if (group->meth->group_set_curve_GFp == 0)
102                 {
103                 ECerr(EC_F_EC_GROUP_SET_CURVE_GFP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
104                 return 0;
105                 }
106         
107         return group->meth->group_set_curve_GFp(group, p, a, b, ctx);
108         }
109
110
111 void EC_GROUP_free(EC_GROUP *group)
112         {
113         if (group->meth->group_finish != 0)
114                 group->meth->group_finish(group);
115         OPENSSL_free(group);
116         }
117  
118
119 void EC_GROUP_clear_free(EC_GROUP *group)
120         {
121         if (group->meth->group_clear_finish != 0)
122                 group->meth->group_clear_finish(group);
123         else if (group->meth != NULL && group->meth->group_finish != 0)
124                 group->meth->group_finish(group);
125         memset(group, 0, sizeof *group);
126         OPENSSL_free(group);
127         }
128
129
130 int EC_GROUP_copy(EC_GROUP *dest, const EC_GROUP *src)
131         {
132         if (dest->meth->group_copy == 0)
133                 {
134                 ECerr(EC_F_EC_GROUP_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
135                 return 0;
136                 }
137         if (dest->meth != src->meth)
138                 {
139                 ECerr(EC_F_EC_GROUP_COPY, EC_R_INCOMPATIBLE_OBJECTS);
140                 return 0;
141                 }
142         
143         return dest->meth->group_copy(dest, src);
144         }
145
146
147 int EC_GROUP_set_generator(EC_GROUP *group, const EC_POINT *generator, const BIGNUM *order, const BIGNUM *cofactor)
148         {
149         if (group->meth->group_set_generator == 0)
150                 {
151                 ECerr(EC_F_EC_GROUP_SET_GENERATOR, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
152                 return 0;
153                 }
154         return group->meth->group_set_generator(group, generator, order, cofactor);
155         }
156
157
158 /* TODO: 'get' functions for EC_GROUPs */
159
160
161
162 /* functions for EC_POINT objects */
163
164 EC_POINT *EC_POINT_new(const EC_GROUP *group)
165         {
166         EC_POINT *ret;
167
168         if (group == NULL)
169                 {
170                 ECerr(EC_F_EC_POINT_NEW, ERR_R_PASSED_NULL_PARAMETER);
171                 return NULL;
172                 }
173         if (group->meth->point_init == 0)
174                 {
175                 ECerr(EC_F_EC_POINT_NEW, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
176                 return NULL;
177                 }
178
179         ret = OPENSSL_malloc(sizeof *ret);
180         if (ret == NULL)
181                 {
182                 ECerr(EC_F_EC_POINT_NEW, ERR_R_MALLOC_FAILURE);
183                 return NULL;
184                 }
185
186         ret->meth = group->meth;
187         
188         if (!ret->meth->point_init(ret))
189                 {
190                 OPENSSL_free(ret);
191                 return NULL;
192                 }
193         
194         return ret;
195         }
196
197
198 void EC_POINT_free(EC_POINT *point)
199         {
200         if (point->meth->point_finish != 0)
201                 point->meth->point_finish(point);
202         OPENSSL_free(point);
203         }
204  
205
206 void EC_POINT_clear_free(EC_POINT *point)
207         {
208         if (point->meth->point_clear_finish != 0)
209                 point->meth->point_clear_finish(point);
210         else if (point->meth != NULL && point->meth->point_finish != 0)
211                 point->meth->point_finish(point);
212         memset(point, 0, sizeof *point);
213         OPENSSL_free(point);
214         }
215
216
217 int EC_POINT_copy(EC_POINT *dest, const EC_POINT *src)
218         {
219         if (dest->meth->point_copy == 0)
220                 {
221                 ECerr(EC_F_EC_POINT_COPY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
222                 return 0;
223                 }
224         if (dest->meth != src->meth)
225                 {
226                 ECerr(EC_F_EC_POINT_COPY, EC_R_INCOMPATIBLE_OBJECTS);
227                 return 0;
228                 }
229         
230         return dest->meth->point_copy(dest, src);
231         }
232
233
234 /* TODO: 'set' and 'get' functions for EC_POINTs */
235
236
237 size_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
238         unsigned char *buf, size_t len, BN_CTX *ctx)
239         {
240         if (group->meth->point2oct == 0)
241                 {
242                 ECerr(EC_F_EC_POINT_POINT2OCT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
243                 return 0;
244                 }
245         if (group->meth != point->meth)
246                 {
247                 ECerr(EC_F_EC_POINT_POINT2OCT, EC_R_INCOMPATIBLE_OBJECTS);
248                 return 0;
249                 }
250         return group->meth->point2oct(group, point, form, buf, len, ctx);
251         }
252
253
254 int EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point,
255         const unsigned char *buf, size_t len, BN_CTX *ctx)
256         {
257         if (group->meth->oct2point == 0)
258                 {
259                 ECerr(EC_F_EC_POINT_OCT2POINT, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
260                 return 0;
261                 }
262         if (group->meth != point->meth)
263                 {
264                 ECerr(EC_F_EC_POINT_OCT2POINT, EC_R_INCOMPATIBLE_OBJECTS);
265                 return 0;
266                 }
267         return group->meth->oct2point(group, point, buf, len, ctx);
268         }
269
270
271 int EC_POINT_add(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, const EC_POINT *b, BN_CTX *ctx)
272         {
273         if (group->meth->add == 0)
274                 {
275                 ECerr(EC_F_EC_POINT_ADD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
276                 return 0;
277                 }
278         if ((group->meth != r->meth) || (r->meth != a->meth) || (a->meth != b->meth))
279                 {
280                 ECerr(EC_F_EC_POINT_ADD, EC_R_INCOMPATIBLE_OBJECTS);
281                 return 0;
282                 }
283         return group->meth->add(group, r, a, b, ctx);
284         }
285
286
287 int EC_POINT_dbl(const EC_GROUP *group, EC_POINT *r, const EC_POINT *a, BN_CTX *ctx)
288         {
289         if (group->meth->dbl == 0)
290                 {
291                 ECerr(EC_F_EC_POINT_DBL, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
292                 return 0;
293                 }
294         if ((group->meth != r->meth) || (r->meth != a->meth))
295                 {
296                 ECerr(EC_F_EC_POINT_DBL, EC_R_INCOMPATIBLE_OBJECTS);
297                 return 0;
298                 }
299         return group->meth->dbl(group, r, a, ctx);
300         }
301
302
303 int EC_POINT_is_at_infinity(const EC_GROUP *group, const EC_POINT *point)
304         {
305         if (group->meth->is_at_infinity == 0)
306                 {
307                 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
308                 return 0;
309                 }
310         if (group->meth != point->meth)
311                 {
312                 ECerr(EC_F_EC_POINT_IS_AT_INFINITY, EC_R_INCOMPATIBLE_OBJECTS);
313                 return 0;
314                 }
315         return group->meth->is_at_infinity(group, point);
316         }
317
318
319 int EC_POINT_is_on_curve(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
320         {
321         if (group->meth->is_on_curve == 0)
322                 {
323                 ECerr(EC_F_EC_POINT_IS_ON_CURVE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
324                 return 0;
325                 }
326         if (group->meth != point->meth)
327                 {
328                 ECerr(EC_F_EC_POINT_IS_ON_CURVE, EC_R_INCOMPATIBLE_OBJECTS);
329                 return 0;
330                 }
331         return group->meth->is_on_curve(group, point, ctx);
332         }
333
334
335 int EC_POINT_make_affine(const EC_GROUP *group, const EC_POINT *point, BN_CTX *ctx)
336         {
337         if (group->meth->make_affine == 0)
338                 {
339                 ECerr(EC_F_EC_POINT_MAKE_AFFINE, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
340                 return 0;
341                 }
342         if (group->meth != point->meth)
343                 {
344                 ECerr(EC_F_EC_POINT_MAKE_AFFINE, EC_R_INCOMPATIBLE_OBJECTS);
345                 return 0;
346                 }
347         return group->meth->make_affine(group, point, ctx);
348         }