Branch data Line data Source code
1 : : /* $OpenBSD: bufec.c,v 1.3 2014/01/31 16:39:19 tedu Exp $ */
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 : :
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 : 1153 : buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
51 : : const EC_POINT *point)
52 : : {
53 : 1153 : u_char *buf = NULL;
54 : : size_t len;
55 : : BN_CTX *bnctx;
56 : 1153 : int ret = -1;
57 : :
58 : : /* Determine length */
59 [ - + ]: 1153 : if ((bnctx = BN_CTX_new()) == NULL)
60 : 0 : fatal("%s: BN_CTX_new failed", __func__);
61 : 1153 : len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
62 : : NULL, 0, bnctx);
63 [ - + ]: 1153 : if (len > BUFFER_MAX_ECPOINT_LEN) {
64 : 0 : error("%s: giant EC point: len = %lu (max %u)",
65 : : __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
66 : 0 : goto out;
67 : : }
68 : : /* Convert */
69 : 1153 : buf = xmalloc(len);
70 [ - + ]: 1153 : if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
71 : : buf, len, bnctx) != len) {
72 : 0 : error("%s: EC_POINT_point2oct length mismatch", __func__);
73 : 0 : goto out;
74 : : }
75 : : /* Append */
76 : 1153 : buffer_put_string(buffer, buf, len);
77 : 1153 : ret = 0;
78 : : out:
79 [ + - ]: 1153 : if (buf != NULL) {
80 : 1153 : explicit_bzero(buf, len);
81 : 1153 : free(buf);
82 : : }
83 : 1153 : BN_CTX_free(bnctx);
84 : 1153 : return ret;
85 : : }
86 : :
87 : : void
88 : 1153 : buffer_put_ecpoint(Buffer *buffer, const EC_GROUP *curve,
89 : : const EC_POINT *point)
90 : : {
91 [ - + ]: 1153 : if (buffer_put_ecpoint_ret(buffer, curve, point) == -1)
92 : 0 : fatal("%s: buffer error", __func__);
93 : 1153 : }
94 : :
95 : : int
96 : 1399 : 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 : 1399 : int ret = -1;
103 : :
104 [ - + ]: 1399 : if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) {
105 : 0 : error("%s: invalid point", __func__);
106 : 0 : return -1;
107 : : }
108 [ - + ]: 1399 : if ((bnctx = BN_CTX_new()) == NULL)
109 : 0 : fatal("%s: BN_CTX_new failed", __func__);
110 [ - + ]: 1399 : if (len > BUFFER_MAX_ECPOINT_LEN) {
111 : 0 : error("%s: EC_POINT too long: %u > max %u", __func__,
112 : : len, BUFFER_MAX_ECPOINT_LEN);
113 : 0 : goto out;
114 : : }
115 [ - + ]: 1399 : if (len == 0) {
116 : 0 : error("%s: EC_POINT buffer is empty", __func__);
117 : 0 : goto out;
118 : : }
119 [ - + ]: 1399 : if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
120 : 0 : error("%s: EC_POINT is in an incorrect form: "
121 : : "0x%02x (want 0x%02x)", __func__, buf[0],
122 : : POINT_CONVERSION_UNCOMPRESSED);
123 : 0 : goto out;
124 : : }
125 [ - + ]: 1399 : if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
126 : 0 : error("buffer_get_bignum2_ret: BN_bin2bn failed");
127 : 0 : goto out;
128 : : }
129 : : /* EC_POINT_oct2point verifies that the point is on the curve for us */
130 : : ret = 0;
131 : : out:
132 : 1399 : BN_CTX_free(bnctx);
133 : 1399 : explicit_bzero(buf, len);
134 : 1399 : free(buf);
135 : 1399 : return ret;
136 : : }
137 : :
138 : : void
139 : 96 : buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
140 : : EC_POINT *point)
141 : : {
142 [ - + ]: 96 : if (buffer_get_ecpoint_ret(buffer, curve, point) == -1)
143 : 0 : fatal("%s: buffer error", __func__);
144 : 96 : }
145 : :
146 : : #endif /* OPENSSL_HAS_ECC */
|