1392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* crypto/ec/ec2_oct.c */
2392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* ====================================================================
3392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED.
4392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
5392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * The Elliptic Curve Public-Key Crypto Library (ECC Code) included
6392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * herein is developed by SUN MICROSYSTEMS, INC., and is contributed
7392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * to the OpenSSL project.
8392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
9392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * The ECC Code is licensed pursuant to the OpenSSL open source
10392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * license provided below.
11392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
12392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * The software is originally written by Sheueling Chang Shantz and
13392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Douglas Stebila of Sun Microsystems Laboratories.
14392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
15392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
16392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* ====================================================================
17392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Copyright (c) 1998-2005 The OpenSSL Project.  All rights reserved.
18392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
19392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Redistribution and use in source and binary forms, with or without
20392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * modification, are permitted provided that the following conditions
21392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * are met:
22392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
23392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 1. Redistributions of source code must retain the above copyright
24392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    notice, this list of conditions and the following disclaimer.
25392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
26392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 2. Redistributions in binary form must reproduce the above copyright
27392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    notice, this list of conditions and the following disclaimer in
28392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    the documentation and/or other materials provided with the
29392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    distribution.
30392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
31392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 3. All advertising materials mentioning features or use of this
32392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    software must display the following acknowledgment:
33392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
34392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
35392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
36392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
37392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    endorse or promote products derived from this software without
38392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    prior written permission. For written permission, please contact
39392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    openssl-core@openssl.org.
40392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
41392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 5. Products derived from this software may not be called "OpenSSL"
42392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    nor may "OpenSSL" appear in their names without prior written
43392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    permission of the OpenSSL Project.
44392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
45392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * 6. Redistributions of any form whatsoever must retain the following
46392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    acknowledgment:
47392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    "This product includes software developed by the OpenSSL Project
48392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
49392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
50392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
51392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
52392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
53392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
54392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
55392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
56392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
57392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
59392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
61392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * OF THE POSSIBILITY OF SUCH DAMAGE.
62392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * ====================================================================
63392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
64392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * This product includes cryptographic software written by Eric Young
65392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * (eay@cryptsoft.com).  This product includes software written by Tim
66392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Hudson (tjh@cryptsoft.com).
67392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
68392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
69392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
70392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include <openssl/err.h>
71392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
72392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#include "ec_lcl.h"
73392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
74392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#ifndef OPENSSL_NO_EC2M
75392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
76392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Calculates and sets the affine coordinates of an EC_POINT from the given
77392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * compressed coordinates.  Uses algorithm 2.3.4 of SEC 1.
78392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Note that the simple implementation only uses affine coordinates.
79392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
80392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * The method is from the following publication:
81392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
82392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *     Harper, Menezes, Vanstone:
83392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *     "Public-Key Cryptosystems with Very Small Key Lengths",
84392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *     EUROCRYPT '92, Springer-Verlag LNCS 658,
85392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *     published February 1993
86392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom *
87392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * US Patents 6,141,420 and 6,618,483 (Vanstone, Mullin, Agnew) describe
88392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * the same method, but claim no priority date earlier than July 29, 1994
89392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * (and additionally fail to cite the EUROCRYPT '92 publication as prior art).
90392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
91392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint ec_GF2m_simple_set_compressed_coordinates(const EC_GROUP *group, EC_POINT *point,
92392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const BIGNUM *x_, int y_bit, BN_CTX *ctx)
93392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
94392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX *new_ctx = NULL;
95392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIGNUM *tmp, *x, *y, *z;
96392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret = 0, z0;
97392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
98392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* clear error queue */
99392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ERR_clear_error();
100392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
101392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx == NULL)
102392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
103392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx = new_ctx = BN_CTX_new();
104392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ctx == NULL)
105392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
106392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
107392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
108392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	y_bit = (y_bit != 0) ? 1 : 0;
109392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
110392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX_start(ctx);
111392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	tmp = BN_CTX_get(ctx);
112392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	x = BN_CTX_get(ctx);
113392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	y = BN_CTX_get(ctx);
114392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	z = BN_CTX_get(ctx);
115392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (z == NULL) goto err;
116392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
117392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (!BN_GF2m_mod_arr(x, x_, group->poly)) goto err;
118392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (BN_is_zero(x))
119392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
120392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!BN_GF2m_mod_sqrt_arr(y, &group->b, group->poly, ctx)) goto err;
121392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
122392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
123392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
124392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!group->meth->field_sqr(group, tmp, x, ctx)) goto err;
125392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!group->meth->field_div(group, tmp, &group->b, tmp, ctx)) goto err;
126392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!BN_GF2m_add(tmp, &group->a, tmp)) goto err;
127392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!BN_GF2m_add(tmp, x, tmp)) goto err;
128392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!BN_GF2m_mod_solve_quad_arr(z, tmp, group->poly, ctx))
129392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
130392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			unsigned long err = ERR_peek_last_error();
131392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
132392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ERR_GET_LIB(err) == ERR_LIB_BN && ERR_GET_REASON(err) == BN_R_NO_SOLUTION)
133392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
134392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ERR_clear_error();
135392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, EC_R_INVALID_COMPRESSED_POINT);
136392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
137392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			else
138392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ECerr(EC_F_EC_GF2M_SIMPLE_SET_COMPRESSED_COORDINATES, ERR_R_BN_LIB);
139392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
140392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
141392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		z0 = (BN_is_odd(z)) ? 1 : 0;
142392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!group->meth->field_mul(group, y, x, z, ctx)) goto err;
143392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (z0 != y_bit)
144392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
145392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (!BN_GF2m_add(y, y, x)) goto err;
146392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
147392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
148392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
149392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
150392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
151392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = 1;
152392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
153392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom err:
154392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX_end(ctx);
155392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (new_ctx != NULL)
156392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_free(new_ctx);
157392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
158392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
159392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
160392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
161392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Converts an EC_POINT to an octet string.
162392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * If buf is NULL, the encoded length will be returned.
163392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * If the length len of buf is smaller than required an error will be returned.
164392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
165392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromsize_t ec_GF2m_simple_point2oct(const EC_GROUP *group, const EC_POINT *point, point_conversion_form_t form,
166392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	unsigned char *buf, size_t len, BN_CTX *ctx)
167392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
168392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t ret;
169392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX *new_ctx = NULL;
170392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int used_ctx = 0;
171392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIGNUM *x, *y, *yxi;
172392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t field_len, i, skip;
173392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
174392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((form != POINT_CONVERSION_COMPRESSED)
175392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		&& (form != POINT_CONVERSION_UNCOMPRESSED)
176392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		&& (form != POINT_CONVERSION_HYBRID))
177392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
178392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_INVALID_FORM);
179392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		goto err;
180392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
181392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
182392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (EC_POINT_is_at_infinity(group, point))
183392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
184392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		/* encodes to a single 0 octet */
185392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (buf != NULL)
186392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
187392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (len < 1)
188392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
189392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
190392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
191392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
192392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			buf[0] = 0;
193392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
194392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 1;
195392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
196392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
197392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
198392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* ret := required output buffer length */
199392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
200392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
201392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
202392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	/* if 'buf' is NULL, just return required length */
203392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (buf != NULL)
204392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
205392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len < ret)
206392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
207392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, EC_R_BUFFER_TOO_SMALL);
208392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
209392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
210392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
211392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ctx == NULL)
212392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
213392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ctx = new_ctx = BN_CTX_new();
214392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (ctx == NULL)
215392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				return 0;
216392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
217392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
218392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_start(ctx);
219392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		used_ctx = 1;
220392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		x = BN_CTX_get(ctx);
221392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		y = BN_CTX_get(ctx);
222392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		yxi = BN_CTX_get(ctx);
223392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (yxi == NULL) goto err;
224392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
225392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!EC_POINT_get_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
226392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
227392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		buf[0] = form;
228392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if ((form != POINT_CONVERSION_UNCOMPRESSED) && !BN_is_zero(x))
229392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
230392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
231392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (BN_is_odd(yxi)) buf[0]++;
232392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
233392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
234392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		i = 1;
235392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
236392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		skip = field_len - BN_num_bytes(x);
237392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (skip > field_len)
238392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
239392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
240392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
241392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
242392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		while (skip > 0)
243392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
244392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			buf[i++] = 0;
245392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			skip--;
246392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
247392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		skip = BN_bn2bin(x, buf + i);
248392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		i += skip;
249392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (i != 1 + field_len)
250392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
251392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
252392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
253392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
254392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
255392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (form == POINT_CONVERSION_UNCOMPRESSED || form == POINT_CONVERSION_HYBRID)
256392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
257392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			skip = field_len - BN_num_bytes(y);
258392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (skip > field_len)
259392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
260392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
261392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				goto err;
262392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
263392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			while (skip > 0)
264392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
265392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				buf[i++] = 0;
266392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				skip--;
267392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
268392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			skip = BN_bn2bin(y, buf + i);
269392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			i += skip;
270392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
271392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
272392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (i != ret)
273392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
274392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_POINT2OCT, ERR_R_INTERNAL_ERROR);
275392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
276392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
277392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
278392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
279392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (used_ctx)
280392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_end(ctx);
281392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (new_ctx != NULL)
282392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_free(new_ctx);
283392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
284392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
285392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom err:
286392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (used_ctx)
287392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_end(ctx);
288392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (new_ctx != NULL)
289392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_free(new_ctx);
290392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return 0;
291392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
292392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
293392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
294392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom/* Converts an octet string representation to an EC_POINT.
295392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom * Note that the simple implementation only uses affine coordinates.
296392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom */
297392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstromint ec_GF2m_simple_oct2point(const EC_GROUP *group, EC_POINT *point,
298392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	const unsigned char *buf, size_t len, BN_CTX *ctx)
299392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	{
300392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	point_conversion_form_t form;
301392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int y_bit;
302392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX *new_ctx = NULL;
303392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BIGNUM *x, *y, *yxi;
304392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	size_t field_len, enc_len;
305392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	int ret = 0;
306392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
307392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len == 0)
308392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
309392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_BUFFER_TOO_SMALL);
310392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
311392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
312392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	form = buf[0];
313392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	y_bit = form & 1;
314392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	form = form & ~1U;
315392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((form != 0)	&& (form != POINT_CONVERSION_COMPRESSED)
316392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		&& (form != POINT_CONVERSION_UNCOMPRESSED)
317392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		&& (form != POINT_CONVERSION_HYBRID))
318392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
319392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
320392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
321392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
322392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if ((form == 0 || form == POINT_CONVERSION_UNCOMPRESSED) && y_bit)
323392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
324392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
325392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
326392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
327392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
328392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (form == 0)
329392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
330392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (len != 1)
331392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
332392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
333392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
334392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
335392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
336392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return EC_POINT_set_to_infinity(group, point);
337392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
338392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
339392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	field_len = (EC_GROUP_get_degree(group) + 7) / 8;
340392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	enc_len = (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2*field_len;
341392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
342392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (len != enc_len)
343392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
344392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
345392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		return 0;
346392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
347392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
348392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (ctx == NULL)
349392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
350392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ctx = new_ctx = BN_CTX_new();
351392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (ctx == NULL)
352392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			return 0;
353392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
354392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
355392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX_start(ctx);
356392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	x = BN_CTX_get(ctx);
357392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	y = BN_CTX_get(ctx);
358392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	yxi = BN_CTX_get(ctx);
359392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (yxi == NULL) goto err;
360392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
361392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (!BN_bin2bn(buf + 1, field_len, x)) goto err;
362392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (BN_ucmp(x, &group->field) >= 0)
363392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
364392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
365392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		goto err;
366392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
367392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
368392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (form == POINT_CONVERSION_COMPRESSED)
369392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
370392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!EC_POINT_set_compressed_coordinates_GF2m(group, point, x, y_bit, ctx)) goto err;
371392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
372392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	else
373392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
374392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) goto err;
375392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (BN_ucmp(y, &group->field) >= 0)
376392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
377392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
378392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			goto err;
379392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
380392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (form == POINT_CONVERSION_HYBRID)
381392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			{
382392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (!group->meth->field_div(group, yxi, y, x, ctx)) goto err;
383392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			if (y_bit != BN_is_odd(yxi))
384392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				{
385392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_INVALID_ENCODING);
386392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				goto err;
387392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom				}
388392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom			}
389392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
390392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		if (!EC_POINT_set_affine_coordinates_GF2m(group, point, x, y, ctx)) goto err;
391392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
392392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
393392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (!EC_POINT_is_on_curve(group, point, ctx)) /* test required by X9.62 */
394392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		{
395392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		ECerr(EC_F_EC_GF2M_SIMPLE_OCT2POINT, EC_R_POINT_IS_NOT_ON_CURVE);
396392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		goto err;
397392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		}
398392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
399392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	ret = 1;
400392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom
401392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom err:
402392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	BN_CTX_end(ctx);
403392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	if (new_ctx != NULL)
404392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom		BN_CTX_free(new_ctx);
405392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	return ret;
406392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom	}
407392aa7cc7d2b122614c5393c3e357da07fd07af3Brian Carlstrom#endif
408