Annotation of src/usr.bin/ssh/bufec.c, Revision 1.3
1.3 ! tedu 1: /* $OpenBSD: bufec.c,v 1.2 2013/05/17 00:13:13 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2010 Damien Miller <djm@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: #include <sys/types.h>
18:
19: #include <openssl/bn.h>
20: #include <openssl/ec.h>
21:
22: #include <string.h>
23: #include <stdarg.h>
24:
25: #include "xmalloc.h"
26: #include "buffer.h"
27: #include "log.h"
28: #include "misc.h"
29:
30: /*
31: * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed
32: * encoding represents this as two bitstring points that should each
33: * be no longer than the field length, SEC1 specifies a 1 byte
34: * point type header.
35: * Being paranoid here may insulate us to parsing problems in
36: * EC_POINT_oct2point.
37: */
38: #define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1)
39:
40: /*
41: * Append an EC_POINT to the buffer as a string containing a SEC1 encoded
42: * uncompressed point. Fortunately OpenSSL handles the gory details for us.
43: */
44: int
45: buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
46: const EC_POINT *point)
47: {
48: u_char *buf = NULL;
49: size_t len;
50: BN_CTX *bnctx;
51: int ret = -1;
52:
53: /* Determine length */
54: if ((bnctx = BN_CTX_new()) == NULL)
55: fatal("%s: BN_CTX_new failed", __func__);
56: len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
57: NULL, 0, bnctx);
58: if (len > BUFFER_MAX_ECPOINT_LEN) {
59: error("%s: giant EC point: len = %lu (max %u)",
60: __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
61: goto out;
62: }
63: /* Convert */
64: buf = xmalloc(len);
65: if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
66: buf, len, bnctx) != len) {
67: error("%s: EC_POINT_point2oct length mismatch", __func__);
68: goto out;
69: }
70: /* Append */
71: buffer_put_string(buffer, buf, len);
72: ret = 0;
73: out:
74: if (buf != NULL) {
1.3 ! tedu 75: explicit_bzero(buf, len);
1.2 djm 76: free(buf);
1.1 djm 77: }
78: BN_CTX_free(bnctx);
79: return ret;
80: }
81:
82: void
83: buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
84: const EC_POINT *point)
85: {
86: if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
87: fatal("%s: buffer error", __func__);
88: }
89:
90: int
91: buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
92: EC_POINT *point)
93: {
94: u_char *buf;
95: u_int len;
96: BN_CTX *bnctx;
97: int ret = -1;
98:
99: if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
100: error("%s: invalid point", __func__);
101: return -1;
102: }
103: if ((bnctx = BN_CTX_new()) == NULL)
104: fatal("%s: BN_CTX_new failed", __func__);
105: if (len > BUFFER_MAX_ECPOINT_LEN) {
106: error("%s: EC_POINT too long: %u > max %u", __func__,
107: len, BUFFER_MAX_ECPOINT_LEN);
108: goto out;
109: }
110: if (len == 0) {
111: error("%s: EC_POINT buffer is empty", __func__);
112: goto out;
113: }
114: if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
115: error("%s: EC_POINT is in an incorrect form: "
116: "0x%02x (want 0x%02x)", __func__, buf[0],
117: POINT_CONVERSION_UNCOMPRESSED);
118: goto out;
119: }
120: if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
121: error("buffer_get_bignum2_ret: BN_bin2bn failed");
122: goto out;
123: }
124: /* EC_POINT_oct2point verifies that the point is on the curve for us */
125: ret = 0;
126: out:
127: BN_CTX_free(bnctx);
1.3 ! tedu 128: explicit_bzero(buf, len);
1.2 djm 129: free(buf);
1.1 djm 130: return ret;
131: }
132:
133: void
134: buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
135: EC_POINT *point)
136: {
137: if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
138: fatal("%s: buffer error", __func__);
139: }
140: