1d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* Originally written by Bodo Moeller for the OpenSSL project. 2d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 3d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved. 4d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Redistribution and use in source and binary forms, with or without 6d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * modification, are permitted provided that the following conditions 7d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * are met: 8d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 9d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 1. Redistributions of source code must retain the above copyright 10d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer. 11d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 12d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 2. Redistributions in binary form must reproduce the above copyright 13d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * notice, this list of conditions and the following disclaimer in 14d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * the documentation and/or other materials provided with the 15d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * distribution. 16d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 17d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 3. All advertising materials mentioning features or use of this 18d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * software must display the following acknowledgment: 19d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 20d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 21d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 22d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 23d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * endorse or promote products derived from this software without 24d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * prior written permission. For written permission, please contact 25d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * openssl-core@openssl.org. 26d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 27d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 5. Products derived from this software may not be called "OpenSSL" 28d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * nor may "OpenSSL" appear in their names without prior written 29d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * permission of the OpenSSL Project. 30d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 31d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 6. Redistributions of any form whatsoever must retain the following 32d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * acknowledgment: 33d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * "This product includes software developed by the OpenSSL Project 34d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 35d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 36d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 37d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 38d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 39d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 40d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 41d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 42d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 43d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 44d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 45d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 46d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 47d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * OF THE POSSIBILITY OF SUCH DAMAGE. 48d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * ==================================================================== 49d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 50d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * This product includes cryptographic software written by Eric Young 51d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * (eay@cryptsoft.com). This product includes software written by Tim 52d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Hudson (tjh@cryptsoft.com). 53d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 54d9e397b599b13d642138480a28c14db7a136bf0Adam Langley */ 55d9e397b599b13d642138480a28c14db7a136bf0Adam Langley/* ==================================================================== 56d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Copyright 2002 Sun Microsystems, Inc. ALL RIGHTS RESERVED. 57d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 58d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Portions of the attached software ("Contribution") are developed by 59d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * SUN MICROSYSTEMS, INC., and are contributed to the OpenSSL project. 60d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 61d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The Contribution is licensed pursuant to the OpenSSL open source 62d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * license provided above. 63d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * 64d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * The elliptic curve binary polynomial software is originally written by 65d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Sheueling Chang Shantz and Douglas Stebila of Sun Microsystems 66d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * Laboratories. */ 67d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 68d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/ec.h> 69d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 70d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/bn.h> 71d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include <openssl/err.h> 72d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 73d9e397b599b13d642138480a28c14db7a136bf0Adam Langley#include "internal.h" 74d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 75d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 76d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic size_t ec_GFp_simple_point2oct(const EC_GROUP *group, 77d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const EC_POINT *point, 78d9e397b599b13d642138480a28c14db7a136bf0Adam Langley point_conversion_form_t form, 79d9e397b599b13d642138480a28c14db7a136bf0Adam Langley uint8_t *buf, size_t len, BN_CTX *ctx) { 80d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t ret; 81d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *new_ctx = NULL; 82d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int used_ctx = 0; 83d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *x, *y; 84d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t field_len, i; 85d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 86d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((form != POINT_CONVERSION_COMPRESSED) && 87d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (form != POINT_CONVERSION_UNCOMPRESSED)) { 88b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_FORM); 89d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 90d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 91d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 92d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (EC_POINT_is_at_infinity(group, point)) { 934139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley OPENSSL_PUT_ERROR(EC, EC_R_POINT_AT_INFINITY); 944139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley goto err; 95d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 96d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 97d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* ret := required output buffer length */ 98d9e397b599b13d642138480a28c14db7a136bf0Adam Langley field_len = BN_num_bytes(&group->field); 99d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 100d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 101d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 102d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* if 'buf' is NULL, just return required length */ 103d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (buf != NULL) { 104d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len < ret) { 105b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); 106d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 107d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 108d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 109d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 110d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = new_ctx = BN_CTX_new(); 111d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 1124139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley goto err; 113d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 114d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 115d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 116d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_start(ctx); 117d9e397b599b13d642138480a28c14db7a136bf0Adam Langley used_ctx = 1; 118d9e397b599b13d642138480a28c14db7a136bf0Adam Langley x = BN_CTX_get(ctx); 119d9e397b599b13d642138480a28c14db7a136bf0Adam Langley y = BN_CTX_get(ctx); 120d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (y == NULL) { 121d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 122d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 123d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 124d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!EC_POINT_get_affine_coordinates_GFp(group, point, x, y, ctx)) { 125d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 126d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 127d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 128d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if ((form == POINT_CONVERSION_COMPRESSED) && 129d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_is_odd(y)) { 130d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf[0] = form + 1; 131d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 132d9e397b599b13d642138480a28c14db7a136bf0Adam Langley buf[0] = form; 133d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 134d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i = 1; 135d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 136d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_bn2bin_padded(buf + i, field_len, x)) { 137b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 138d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 139d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 140d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i += field_len; 141d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 142d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (form == POINT_CONVERSION_UNCOMPRESSED) { 143d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_bn2bin_padded(buf + i, field_len, y)) { 144b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 145d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 146d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 147d9e397b599b13d642138480a28c14db7a136bf0Adam Langley i += field_len; 148d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 149d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 150d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (i != ret) { 151b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 152d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 153d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 154d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 155d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 156d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (used_ctx) { 157d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_end(ctx); 158d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 159e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(new_ctx); 160d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 161d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 162d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 163d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (used_ctx) { 164d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_end(ctx); 165d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 166e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(new_ctx); 167d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 168d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 169d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 170d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 171d9e397b599b13d642138480a28c14db7a136bf0Adam Langleystatic int ec_GFp_simple_oct2point(const EC_GROUP *group, EC_POINT *point, 172d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *buf, size_t len, 173d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *ctx) { 174d9e397b599b13d642138480a28c14db7a136bf0Adam Langley point_conversion_form_t form; 175d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int y_bit; 176d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *new_ctx = NULL; 177d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *x, *y; 178d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t field_len, enc_len; 179d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 180d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 181d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len == 0) { 182b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_BUFFER_TOO_SMALL); 183d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 184d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 185d9e397b599b13d642138480a28c14db7a136bf0Adam Langley form = buf[0]; 186d9e397b599b13d642138480a28c14db7a136bf0Adam Langley y_bit = form & 1; 187d9e397b599b13d642138480a28c14db7a136bf0Adam Langley form = form & ~1U; 1884139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley if ((form != POINT_CONVERSION_COMPRESSED && 1894139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley form != POINT_CONVERSION_UNCOMPRESSED) || 1904139edb02e59e7ad48e0a8f4c02e45923bc8a344Adam Langley (form == POINT_CONVERSION_UNCOMPRESSED && y_bit)) { 191b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); 192d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 193d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 194d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 195d9e397b599b13d642138480a28c14db7a136bf0Adam Langley field_len = BN_num_bytes(&group->field); 196d9e397b599b13d642138480a28c14db7a136bf0Adam Langley enc_len = 197d9e397b599b13d642138480a28c14db7a136bf0Adam Langley (form == POINT_CONVERSION_COMPRESSED) ? 1 + field_len : 1 + 2 * field_len; 198d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 199d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (len != enc_len) { 200b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); 201d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 202d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 203d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 204d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 205d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = new_ctx = BN_CTX_new(); 206e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (ctx == NULL) { 207d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 208e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 209d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 210d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 211d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_start(ctx); 212d9e397b599b13d642138480a28c14db7a136bf0Adam Langley x = BN_CTX_get(ctx); 213d9e397b599b13d642138480a28c14db7a136bf0Adam Langley y = BN_CTX_get(ctx); 214b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root if (x == NULL || y == NULL) { 215d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 216e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 217d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 218e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!BN_bin2bn(buf + 1, field_len, x)) { 219d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 220e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 221d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_ucmp(x, &group->field) >= 0) { 222b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); 223d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 224d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 225d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 226d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (form == POINT_CONVERSION_COMPRESSED) { 227e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_set_compressed_coordinates_GFp(group, point, x, y_bit, ctx)) { 228d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 229e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 230d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 231e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!BN_bin2bn(buf + 1 + field_len, field_len, y)) { 232d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 233e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 234d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_ucmp(y, &group->field) >= 0) { 235b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_ENCODING); 236d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 237d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 238d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 239e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { 240d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 241e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 242d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 243d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 244d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 245d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 246d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 247d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_end(ctx); 248e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(new_ctx); 249d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 250d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 251d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 252d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_POINT_oct2point(const EC_GROUP *group, EC_POINT *point, 253d9e397b599b13d642138480a28c14db7a136bf0Adam Langley const uint8_t *buf, size_t len, BN_CTX *ctx) { 254d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth != point->meth) { 255b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 256d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 257d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 258e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return ec_GFp_simple_oct2point(group, point, buf, len, ctx); 259d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 260d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 261d9e397b599b13d642138480a28c14db7a136bf0Adam Langleysize_t EC_POINT_point2oct(const EC_GROUP *group, const EC_POINT *point, 262d9e397b599b13d642138480a28c14db7a136bf0Adam Langley point_conversion_form_t form, uint8_t *buf, 263d9e397b599b13d642138480a28c14db7a136bf0Adam Langley size_t len, BN_CTX *ctx) { 264d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth != point->meth) { 265b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 266d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 267d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 268e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return ec_GFp_simple_point2oct(group, point, form, buf, len, ctx); 269d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 270d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 271d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint ec_GFp_simple_set_compressed_coordinates(const EC_GROUP *group, 272d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *point, const BIGNUM *x_, 273d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int y_bit, BN_CTX *ctx) { 274d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX *new_ctx = NULL; 275d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BIGNUM *tmp1, *tmp2, *x, *y; 276d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int ret = 0; 277d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 278d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_clear_error(); 279d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 280d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 281d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ctx = new_ctx = BN_CTX_new(); 282d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ctx == NULL) { 283d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 284d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 285d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 286d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 287d9e397b599b13d642138480a28c14db7a136bf0Adam Langley y_bit = (y_bit != 0); 288d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 289d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_start(ctx); 290d9e397b599b13d642138480a28c14db7a136bf0Adam Langley tmp1 = BN_CTX_get(ctx); 291d9e397b599b13d642138480a28c14db7a136bf0Adam Langley tmp2 = BN_CTX_get(ctx); 292d9e397b599b13d642138480a28c14db7a136bf0Adam Langley x = BN_CTX_get(ctx); 293d9e397b599b13d642138480a28c14db7a136bf0Adam Langley y = BN_CTX_get(ctx); 294d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (y == NULL) { 295d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 296d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 297d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 298d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* Recover y. We have a Weierstrass equation 299d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * y^2 = x^3 + a*x + b, 300d9e397b599b13d642138480a28c14db7a136bf0Adam Langley * so y is one of the square roots of x^3 + a*x + b. */ 301d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 302d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* tmp1 := x^3 */ 303d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_nnmod(x, x_, &group->field, ctx)) { 304d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 305d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 306d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 307d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth->field_decode == 0) { 308d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* field_{sqr,mul} work on standard representation */ 309d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!group->meth->field_sqr(group, tmp2, x_, ctx) || 310d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !group->meth->field_mul(group, tmp1, tmp2, x_, ctx)) { 311d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 312d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 313d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 314d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_sqr(tmp2, x_, &group->field, ctx) || 315d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_mod_mul(tmp1, tmp2, x_, &group->field, ctx)) { 316d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 317d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 318d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 319d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 320d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* tmp1 := tmp1 + a*x */ 321d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->a_is_minus3) { 322d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_lshift1_quick(tmp2, x, &group->field) || 323d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_mod_add_quick(tmp2, tmp2, x, &group->field) || 324d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_mod_sub_quick(tmp1, tmp1, tmp2, &group->field)) { 325d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 326d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 327d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 328d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth->field_decode) { 329d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!group->meth->field_decode(group, tmp2, &group->a, ctx) || 330d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_mod_mul(tmp2, tmp2, x, &group->field, ctx)) { 331d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 332d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 333d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 334d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* field_mul works on standard representation */ 335d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!group->meth->field_mul(group, tmp2, &group->a, x, ctx)) { 336d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 337d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 338d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 339d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 340d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { 341d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 342d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 343d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 344d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 345d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* tmp1 := tmp1 + b */ 346d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth->field_decode) { 347d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!group->meth->field_decode(group, tmp2, &group->b, ctx) || 348d9e397b599b13d642138480a28c14db7a136bf0Adam Langley !BN_mod_add_quick(tmp1, tmp1, tmp2, &group->field)) { 349d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 350d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 351d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 352d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_add_quick(tmp1, tmp1, &group->b, &group->field)) { 353d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 354d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 355d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 356d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 357d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_mod_sqrt(y, tmp1, &group->field, ctx)) { 358d9e397b599b13d642138480a28c14db7a136bf0Adam Langley unsigned long err = ERR_peek_last_error(); 359d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 360d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (ERR_GET_LIB(err) == ERR_LIB_BN && 361d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_GET_REASON(err) == BN_R_NOT_A_SQUARE) { 362d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ERR_clear_error(); 363b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); 364d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 365b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_BN_LIB); 366d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 367d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 368d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 369d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 370d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (y_bit != BN_is_odd(y)) { 371d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (BN_is_zero(y)) { 372d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int kron; 373d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 374d9e397b599b13d642138480a28c14db7a136bf0Adam Langley kron = BN_kronecker(x, &group->field, ctx); 375d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (kron == -2) { 376d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 377d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 378d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 379d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (kron == 1) { 380b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSION_BIT); 381d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } else { 382d9e397b599b13d642138480a28c14db7a136bf0Adam Langley /* BN_mod_sqrt() should have cought this error (not a square) */ 383b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INVALID_COMPRESSED_POINT); 384d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 385d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 386d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 387d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (!BN_usub(y, &group->field, y)) { 388d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 389d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 390d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 391d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (y_bit != BN_is_odd(y)) { 392b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, ERR_R_INTERNAL_ERROR); 393d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 394d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 395d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 396e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley if (!EC_POINT_set_affine_coordinates_GFp(group, point, x, y, ctx)) { 397d9e397b599b13d642138480a28c14db7a136bf0Adam Langley goto err; 398e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley } 399d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 400d9e397b599b13d642138480a28c14db7a136bf0Adam Langley ret = 1; 401d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 402d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyerr: 403d9e397b599b13d642138480a28c14db7a136bf0Adam Langley BN_CTX_end(ctx); 404e9ada863a7b3e81f5d2b1e3bdd2305da902a87f5Adam Langley BN_CTX_free(new_ctx); 405d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return ret; 406d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 407d9e397b599b13d642138480a28c14db7a136bf0Adam Langley 408d9e397b599b13d642138480a28c14db7a136bf0Adam Langleyint EC_POINT_set_compressed_coordinates_GFp(const EC_GROUP *group, 409d9e397b599b13d642138480a28c14db7a136bf0Adam Langley EC_POINT *point, const BIGNUM *x, 410d9e397b599b13d642138480a28c14db7a136bf0Adam Langley int y_bit, BN_CTX *ctx) { 411d9e397b599b13d642138480a28c14db7a136bf0Adam Langley if (group->meth != point->meth) { 412b8494591d1b1a143f3b192d845c238bbf3bc629dKenny Root OPENSSL_PUT_ERROR(EC, EC_R_INCOMPATIBLE_OBJECTS); 413d9e397b599b13d642138480a28c14db7a136bf0Adam Langley return 0; 414d9e397b599b13d642138480a28c14db7a136bf0Adam Langley } 415e99801b603dea8893dcc61c70b327ef2d00b652cKenny Root return ec_GFp_simple_set_compressed_coordinates(group, point, x, y_bit, ctx); 416d9e397b599b13d642138480a28c14db7a136bf0Adam Langley} 417