11305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* $OpenBSD: bufec.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ 21305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 31305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Copyright (c) 2010 Damien Miller <djm@mindrot.org> 41305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 51305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Permission to use, copy, modify, and distribute this software for any 61305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * purpose with or without fee is hereby granted, provided that the above 71305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * copyright notice and this permission notice appear in all copies. 81305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * 91305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "includes.h" 191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#ifdef OPENSSL_HAS_ECC 211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <sys/types.h> 231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/bn.h> 251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <openssl/ec.h> 261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <string.h> 281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include <stdarg.h> 291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "xmalloc.h" 311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "buffer.h" 321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "log.h" 331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#include "misc.h" 341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed 371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * encoding represents this as two bitstring points that should each 381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * be no longer than the field length, SEC1 specifies a 1 byte 391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * point type header. 401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Being paranoid here may insulate us to parsing problems in 411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * EC_POINT_oct2point. 421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1) 441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood/* 461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * Append an EC_POINT to the buffer as a string containing a SEC1 encoded 471305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood * uncompressed point. Fortunately OpenSSL handles the gory details for us. 481305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood */ 491305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 501305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbuffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 511305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EC_POINT *point) 521305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 531305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *buf = NULL; 541305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood size_t len; 551305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_CTX *bnctx; 561305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ret = -1; 571305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 581305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Determine length */ 591305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((bnctx = BN_CTX_new()) == NULL) 601305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: BN_CTX_new failed", __func__); 611305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, 621305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood NULL, 0, bnctx); 631305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > BUFFER_MAX_ECPOINT_LEN) { 641305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: giant EC point: len = %lu (max %u)", 651305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN); 661305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 671305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 681305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Convert */ 691305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf = xmalloc(len); 701305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, 711305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buf, len, bnctx) != len) { 721305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: EC_POINT_point2oct length mismatch", __func__); 731305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 741305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 751305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* Append */ 761305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood buffer_put_string(buffer, buf, len); 771305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = 0; 781305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out: 791305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buf != NULL) { 801305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood bzero(buf, len); 811305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(buf); 821305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 831305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_CTX_free(bnctx); 841305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 851305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 861305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 871305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 881305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbuffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve, 891305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood const EC_POINT *point) 901305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 911305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_put_ecpoint_ret(buffer, curve, point) == -1) 921305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: buffer error", __func__); 931305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 941305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 951305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodint 961305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbuffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 971305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EC_POINT *point) 981305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 991305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_char *buf; 1001305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood u_int len; 1011305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_CTX *bnctx; 1021305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood int ret = -1; 1031305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1041305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { 1051305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: invalid point", __func__); 1061305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return -1; 1071305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1081305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if ((bnctx = BN_CTX_new()) == NULL) 1091305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: BN_CTX_new failed", __func__); 1101305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len > BUFFER_MAX_ECPOINT_LEN) { 1111305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: EC_POINT too long: %u > max %u", __func__, 1121305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood len, BUFFER_MAX_ECPOINT_LEN); 1131305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 1141305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1151305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (len == 0) { 1161305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: EC_POINT buffer is empty", __func__); 1171305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 1181305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1191305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) { 1201305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("%s: EC_POINT is in an incorrect form: " 1211305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood "0x%02x (want 0x%02x)", __func__, buf[0], 1221305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood POINT_CONVERSION_UNCOMPRESSED); 1231305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 1241305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1251305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) { 1261305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood error("buffer_get_bignum2_ret: BN_bin2bn failed"); 1271305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood goto out; 1281305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood } 1291305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood /* EC_POINT_oct2point verifies that the point is on the curve for us */ 1301305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood ret = 0; 1311305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood out: 1321305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood BN_CTX_free(bnctx); 1331305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood bzero(buf, len); 1341305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood xfree(buf); 1351305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood return ret; 1361305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1371305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1381305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodvoid 1391305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwoodbuffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve, 1401305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood EC_POINT *point) 1411305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood{ 1421305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood if (buffer_get_ecpoint_ret(buffer, curve, point) == -1) 1431305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood fatal("%s: buffer error", __func__); 1441305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood} 1451305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood 1461305e95ba6ff9fa202d0818caf10405df4b0f648Mike Lockwood#endif /* OPENSSL_HAS_ECC */ 147