]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/ec/ec2_oct.c
Remove /* foo.c */ comments
[thirdparty/openssl.git] / crypto / ec / ec2_oct.c
CommitLineData
84b08eee
DSH
1/* ====================================================================
2 * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
3 *
4 * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
5 * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
6 * to the OpenSSL project.
7 *
8 * The ECC Code is licensed pursuant to the OpenSSL open source
9 * license provided below.
10 *
11 * The software is originally written by Sheueling Chang Shantz and
12 * Douglas Stebila of Sun Microsystems Laboratories.
13 *
14 */
15/* ====================================================================
16 * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
17 *
18 * Redistribution and use in source and binary forms, with or without
19 * modification, are permitted provided that the following conditions
20 * are met:
21 *
22 * 1. Redistributions of source code must retain the above copyright
0f113f3e 23 * notice, this list of conditions and the following disclaimer.
84b08eee
DSH
24 *
25 * 2. Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in
27 * the documentation and/or other materials provided with the
28 * distribution.
29 *
30 * 3. All advertising materials mentioning features or use of this
31 * software must display the following acknowledgment:
32 * "This product includes software developed by the OpenSSL Project
33 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
34 *
35 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
36 * endorse or promote products derived from this software without
37 * prior written permission. For written permission, please contact
38 * openssl-core@openssl.org.
39 *
40 * 5. Products derived from this software may not be called "OpenSSL"
41 * nor may "OpenSSL" appear in their names without prior written
42 * permission of the OpenSSL Project.
43 *
44 * 6. Redistributions of any form whatsoever must retain the following
45 * acknowledgment:
46 * "This product includes software developed by the OpenSSL Project
47 * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
48 *
49 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
50 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
51 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
53 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
54 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
55 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
56 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
58 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
59 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
60 * OF THE POSSIBILITY OF SUCH DAMAGE.
61 * ====================================================================
62 *
63 * This product includes cryptographic software written by Eric Young
64 * (eay@cryptsoft.com). This product includes software written by Tim
65 * Hudson (tjh@cryptsoft.com).
66 *
67 */
68
84b08eee
DSH
69#include <openssl/err.h>
70
71#include "ec_lcl.h"
72
73#ifndef OPENSSL_NO_EC2M
74
3a83462d
MC
75/*-
76 * Calculates and sets the affine coordinates of an EC_POINT from the given
0f113f3e 77 * compressed coordinates. Uses algorithm 2.3.4 of SEC 1.
84b08eee
DSH
78 * Note that the simple implementation only uses affine coordinates.
79 *
80 * The method is from the following publication:
0f113f3e 81 *
84b08eee
DSH
82 * Harper, Menezes, Vanstone:
83 * "Public-Key Cryptosystems with Very Small Key Lengths",
84 * EUROCRYPT '92, Springer-Verlag LNCS 658,
85 * published February 1993
86 *
87 * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
88 * the same method, but claim no priority date earlier than July 29, 1994
89 * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
90 */
0f113f3e
MC
91int ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group,
92 EC_POINT *point,
93 const BIGNUM *x_, int y_bit,
94 BN_CTX *ctx)
95{
96 BN_CTX *new_ctx = NULL;
97 BIGNUM *tmp, *x, *y, *z;
98 int ret = 0, z0;
99
100 /* clear error queue */
101 ERR_clear_error();
102
103 if (ctx == NULL) {
104 ctx = new_ctx = BN_CTX_new();
105 if (ctx == NULL)
106 return 0;
107 }
108
109 y_bit = (y_bit != 0) ? 1 : 0;
110
111 BN_CTX_start(ctx);
112 tmp = BN_CTX_get(ctx);
113 x = BN_CTX_get(ctx);
114 y = BN_CTX_get(ctx);
115 z = BN_CTX_get(ctx);
116 if (z == NULL)
117 goto err;
118
119 if (!BN_GF2m_mod_arr(x, x_, group->poly))
120 goto err;
121 if (BN_is_zero(x)) {
122 if (!BN_GF2m_mod_sqrt_arr(y, group->b, group->poly, ctx))
123 goto err;
124 } else {
125 if (!group->meth->field_sqr(group, tmp, x, ctx))
126 goto err;
127 if (!group->meth->field_div(group, tmp, group->b, tmp, ctx))
128 goto err;
129 if (!BN_GF2m_add(tmp, group->a, tmp))
130 goto err;
131 if (!BN_GF2m_add(tmp, x, tmp))
132 goto err;
133 if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx)) {
134 unsigned long err = ERR_peek_last_error();
135
136 if (ERR_GET_LIB(err) == ERR_LIB_BN
137 && ERR_GET_REASON(err) == BN_R_NO_SOLUTION) {
138 ERR_clear_error();
139 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
140 EC_R_INVALID_COMPRESSED_POINT);
141 } else
142 ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES,
143 ERR_R_BN_LIB);
144 goto err;
145 }
146 z0 = (BN_is_odd(z)) ? 1 : 0;
147 if (!group->meth->field_mul(group, y, x, z, ctx))
148 goto err;
149 if (z0 != y_bit) {
150 if (!BN_GF2m_add(y, y, x))
151 goto err;
152 }
153 }
154
155 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
156 goto err;
157
158 ret = 1;
84b08eee
DSH
159
160 err:
0f113f3e 161 BN_CTX_end(ctx);
23a1d5e9 162 BN_CTX_free(new_ctx);
0f113f3e
MC
163 return ret;
164}
165
166/*
167 * Converts an EC_POINT to an octet string. If buf is NULL, the encoded
168 * length will be returned. If the length len of buf is smaller than required
169 * an error will be returned.
84b08eee 170 */
0f113f3e
MC
171size_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point,
172 point_conversion_form_t form,
173 unsigned char *buf, size_t len, BN_CTX *ctx)
174{
175 size_t ret;
176 BN_CTX *new_ctx = NULL;
177 int used_ctx = 0;
178 BIGNUM *x, *y, *yxi;
179 size_t field_len, i, skip;
180
181 if ((form != POINT_CONVERSION_COMPRESSED)
182 && (form != POINT_CONVERSION_UNCOMPRESSED)
183 && (form != POINT_CONVERSION_HYBRID)) {
184 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
185 goto err;
186 }
187
188 if (EC_POINT_is_at_infinity(group, point)) {
189 /* encodes to a single 0 octet */
190 if (buf != NULL) {
191 if (len < 1) {
192 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
193 return 0;
194 }
195 buf[0] = 0;
196 }
197 return 1;
198 }
199
200 /* ret := required output buffer length */
201 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
202 ret =
203 (form ==
204 POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
205
206 /* if 'buf' is NULL, just return required length */
207 if (buf != NULL) {
208 if (len < ret) {
209 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
210 goto err;
211 }
212
213 if (ctx == NULL) {
214 ctx = new_ctx = BN_CTX_new();
215 if (ctx == NULL)
216 return 0;
217 }
218
219 BN_CTX_start(ctx);
220 used_ctx = 1;
221 x = BN_CTX_get(ctx);
222 y = BN_CTX_get(ctx);
223 yxi = BN_CTX_get(ctx);
224 if (yxi == NULL)
225 goto err;
226
227 if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx))
228 goto err;
229
230 buf[0] = form;
231 if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x)) {
232 if (!group->meth->field_div(group, yxi, y, x, ctx))
233 goto err;
234 if (BN_is_odd(yxi))
235 buf[0]++;
236 }
237
238 i = 1;
239
240 skip = field_len - BN_num_bytes(x);
241 if (skip > field_len) {
242 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
243 goto err;
244 }
245 while (skip > 0) {
246 buf[i++] = 0;
247 skip--;
248 }
249 skip = BN_bn2bin(x, buf + i);
250 i += skip;
251 if (i != 1 + field_len) {
252 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
253 goto err;
254 }
255
256 if (form == POINT_CONVERSION_UNCOMPRESSED
257 || form == POINT_CONVERSION_HYBRID) {
258 skip = field_len - BN_num_bytes(y);
259 if (skip > field_len) {
260 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
261 goto err;
262 }
263 while (skip > 0) {
264 buf[i++] = 0;
265 skip--;
266 }
267 skip = BN_bn2bin(y, buf + i);
268 i += skip;
269 }
270
271 if (i != ret) {
272 ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
273 goto err;
274 }
275 }
276
277 if (used_ctx)
278 BN_CTX_end(ctx);
23a1d5e9 279 BN_CTX_free(new_ctx);
0f113f3e 280 return ret;
84b08eee
DSH
281
282 err:
0f113f3e
MC
283 if (used_ctx)
284 BN_CTX_end(ctx);
23a1d5e9 285 BN_CTX_free(new_ctx);
0f113f3e
MC
286 return 0;
287}
288
289/*
290 * Converts an octet string representation to an EC_POINT. Note that the
291 * simple implementation only uses affine coordinates.
84b08eee
DSH
292 */
293int ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
0f113f3e
MC
294 const unsigned char *buf, size_t len,
295 BN_CTX *ctx)
296{
297 point_conversion_form_t form;
298 int y_bit;
299 BN_CTX *new_ctx = NULL;
300 BIGNUM *x, *y, *yxi;
301 size_t field_len, enc_len;
302 int ret = 0;
303
304 if (len == 0) {
305 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
306 return 0;
307 }
308 form = buf[0];
309 y_bit = form & 1;
310 form = form & ~1U;
311 if ((form != 0) && (form != POINT_CONVERSION_COMPRESSED)
312 && (form != POINT_CONVERSION_UNCOMPRESSED)
313 && (form != POINT_CONVERSION_HYBRID)) {
314 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
315 return 0;
316 }
317 if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit) {
318 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
319 return 0;
320 }
321
322 if (form == 0) {
323 if (len != 1) {
324 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
325 return 0;
326 }
327
328 return EC_POINT_set_to_infinity(group, point);
329 }
330
331 field_len = (EC_GROUP_get_degree(group) + 7) / 8;
332 enc_len =
333 (form ==
334 POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len;
335
336 if (len != enc_len) {
337 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
338 return 0;
339 }
340
341 if (ctx == NULL) {
342 ctx = new_ctx = BN_CTX_new();
343 if (ctx == NULL)
344 return 0;
345 }
346
347 BN_CTX_start(ctx);
348 x = BN_CTX_get(ctx);
349 y = BN_CTX_get(ctx);
350 yxi = BN_CTX_get(ctx);
351 if (yxi == NULL)
352 goto err;
353
354 if (!BN_bin2bn(buf + 1, field_len, x))
355 goto err;
356 if (BN_ucmp(x, group->field) >= 0) {
357 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
358 goto err;
359 }
360
361 if (form == POINT_CONVERSION_COMPRESSED) {
362 if (!EC_POINT_set_compressed_coordinates_GF2m
363 (group, point, x, y_bit, ctx))
364 goto err;
365 } else {
366 if (!BN_bin2bn(buf + 1 + field_len, field_len, y))
367 goto err;
368 if (BN_ucmp(y, group->field) >= 0) {
369 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
370 goto err;
371 }
372 if (form == POINT_CONVERSION_HYBRID) {
373 if (!group->meth->field_div(group, yxi, y, x, ctx))
374 goto err;
375 if (y_bit != BN_is_odd(yxi)) {
376 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
377 goto err;
378 }
379 }
380
381 if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx))
382 goto err;
383 }
384
385 /* test required by X9.62 */
68886be7 386 if (EC_POINT_is_on_curve(group, point, ctx) <= 0) {
0f113f3e
MC
387 ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
388 goto err;
389 }
390
391 ret = 1;
392
84b08eee 393 err:
0f113f3e 394 BN_CTX_end(ctx);
23a1d5e9 395 BN_CTX_free(new_ctx);
0f113f3e
MC
396 return ret;
397}
84b08eee 398#endif