1 /* $OpenBSD: bufec.c,v 1.1 2010/08/31 11:54:45 djm Exp $ */ 2 /* 3 * Copyright (c) 2010 Damien Miller <djm (at) mindrot.org> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "includes.h" 19 20 #ifdef OPENSSL_HAS_ECC 21 22 #include <sys/types.h> 23 24 #include <openssl/bn.h> 25 #include <openssl/ec.h> 26 27 #include <string.h> 28 #include <stdarg.h> 29 30 #include "xmalloc.h" 31 #include "buffer.h" 32 #include "log.h" 33 #include "misc.h" 34 35 /* 36 * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed 37 * encoding represents this as two bitstring points that should each 38 * be no longer than the field length, SEC1 specifies a 1 byte 39 * point type header. 40 * Being paranoid here may insulate us to parsing problems in 41 * EC_POINT_oct2point. 42 */ 43 #define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1) 44 45 /* 46 * Append an EC_POINT to the buffer as a string containing a SEC1 encoded 47 * uncompressed point. Fortunately OpenSSL handles the gory details for us. 48 */ 49 int 50 buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 51 const EC_POINT *point) 52 { 53 u_char *buf = NULL; 54 size_t len; 55 BN_CTX *bnctx; 56 int ret = -1; 57 58 /* Determine length */ 59 if ((bnctx = BN_CTX_new()) == NULL) 60 fatal("%s: BN_CTX_new failed", __func__); 61 len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, 62 NULL, 0, bnctx); 63 if (len > BUFFER_MAX_ECPOINT_LEN) { 64 error("%s: giant EC point: len = %lu (max %u)", 65 __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN); 66 goto out; 67 } 68 /* Convert */ 69 buf = xmalloc(len); 70 if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED, 71 buf, len, bnctx) != len) { 72 error("%s: EC_POINT_point2oct length mismatch", __func__); 73 goto out; 74 } 75 /* Append */ 76 buffer_put_string(buffer, buf, len); 77 ret = 0; 78 out: 79 if (buf != NULL) { 80 bzero(buf, len); 81 xfree(buf); 82 } 83 BN_CTX_free(bnctx); 84 return ret; 85 } 86 87 void 88 buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve, 89 const EC_POINT *point) 90 { 91 if (buffer_put_ecpoint_ret(buffer, curve, point) == -1) 92 fatal("%s: buffer error", __func__); 93 } 94 95 int 96 buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 97 EC_POINT *point) 98 { 99 u_char *buf; 100 u_int len; 101 BN_CTX *bnctx; 102 int ret = -1; 103 104 if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { 105 error("%s: invalid point", __func__); 106 return -1; 107 } 108 if ((bnctx = BN_CTX_new()) == NULL) 109 fatal("%s: BN_CTX_new failed", __func__); 110 if (len > BUFFER_MAX_ECPOINT_LEN) { 111 error("%s: EC_POINT too long: %u > max %u", __func__, 112 len, BUFFER_MAX_ECPOINT_LEN); 113 goto out; 114 } 115 if (len == 0) { 116 error("%s: EC_POINT buffer is empty", __func__); 117 goto out; 118 } 119 if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) { 120 error("%s: EC_POINT is in an incorrect form: " 121 "0x%02x (want 0x%02x)", __func__, buf[0], 122 POINT_CONVERSION_UNCOMPRESSED); 123 goto out; 124 } 125 if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) { 126 error("buffer_get_bignum2_ret: BN_bin2bn failed"); 127 goto out; 128 } 129 /* EC_POINT_oct2point verifies that the point is on the curve for us */ 130 ret = 0; 131 out: 132 BN_CTX_free(bnctx); 133 bzero(buf, len); 134 xfree(buf); 135 return ret; 136 } 137 138 void 139 buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve, 140 EC_POINT *point) 141 { 142 if (buffer_get_ecpoint_ret(buffer, curve, point) == -1) 143 fatal("%s: buffer error", __func__); 144 } 145 146 #endif /* OPENSSL_HAS_ECC */ 147