Annotation of src/usr.bin/ssh/sshbuf-getput-crypto.c, Revision 1.4
1.4 ! djm 1: /* $OpenBSD: sshbuf-getput-crypto.c,v 1.3 2015/01/12 15:18:07 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2011 Damien Miller
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 <sys/types.h>
19: #include <stdlib.h>
20: #include <stdio.h>
21: #include <string.h>
22:
23: #include <openssl/bn.h>
24: #include <openssl/ec.h>
25:
26: #include "ssherr.h"
27: #define SSHBUF_INTERNAL
28: #include "sshbuf.h"
29:
30: int
31: sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v)
32: {
33: const u_char *d;
34: size_t len;
35: int r;
36:
1.4 ! djm 37: if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
1.1 djm 38: return r;
39: if (v != NULL && BN_bin2bn(d, len, v) == NULL)
40: return SSH_ERR_ALLOC_FAIL;
41: return 0;
42: }
43:
44: int
45: sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
46: {
47: const u_char *d = sshbuf_ptr(buf);
48: u_int16_t len_bits;
49: size_t len_bytes;
50:
51: /* Length in bits */
52: if (sshbuf_len(buf) < 2)
53: return SSH_ERR_MESSAGE_INCOMPLETE;
54: len_bits = PEEK_U16(d);
55: len_bytes = (len_bits + 7) >> 3;
1.2 naddy 56: if (len_bytes > SSHBUF_MAX_BIGNUM)
1.1 djm 57: return SSH_ERR_BIGNUM_TOO_LARGE;
58: if (sshbuf_len(buf) < 2 + len_bytes)
59: return SSH_ERR_MESSAGE_INCOMPLETE;
60: if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL)
61: return SSH_ERR_ALLOC_FAIL;
62: if (sshbuf_consume(buf, 2 + len_bytes) != 0) {
63: SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
64: SSHBUF_ABORT();
65: return SSH_ERR_INTERNAL_ERROR;
66: }
67: return 0;
68: }
69:
70: static int
71: get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
72: {
73: /* Refuse overlong bignums */
74: if (len == 0 || len > SSHBUF_MAX_ECPOINT)
75: return SSH_ERR_ECPOINT_TOO_LARGE;
76: /* Only handle uncompressed points */
77: if (*d != POINT_CONVERSION_UNCOMPRESSED)
78: return SSH_ERR_INVALID_FORMAT;
79: if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
80: return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
81: return 0;
82: }
83:
84: int
85: sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
86: {
87: const u_char *d;
88: size_t len;
89: int r;
90:
91: if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
92: return r;
93: if ((r = get_ec(d, len, v, g)) != 0)
94: return r;
95: /* Skip string */
96: if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
97: /* Shouldn't happen */
98: SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
99: SSHBUF_ABORT();
100: return SSH_ERR_INTERNAL_ERROR;
101: }
102: return 0;
103: }
104:
105: int
106: sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
107: {
108: EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
109: int r;
110: const u_char *d;
111: size_t len;
112:
113: if (pt == NULL) {
114: SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
115: return SSH_ERR_ALLOC_FAIL;
116: }
117: if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
118: EC_POINT_free(pt);
119: return r;
120: }
121: if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
122: EC_POINT_free(pt);
123: return r;
124: }
125: if (EC_KEY_set_public_key(v, pt) != 1) {
126: EC_POINT_free(pt);
127: return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
128: }
129: EC_POINT_free(pt);
130: /* Skip string */
131: if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
132: /* Shouldn't happen */
133: SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
134: SSHBUF_ABORT();
135: return SSH_ERR_INTERNAL_ERROR;
136: }
137: return 0;
138: }
139:
140: int
141: sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
142: {
143: u_char d[SSHBUF_MAX_BIGNUM + 1];
144: int len = BN_num_bytes(v), prepend = 0, r;
145:
146: if (len < 0 || len > SSHBUF_MAX_BIGNUM)
147: return SSH_ERR_INVALID_ARGUMENT;
148: *d = '\0';
149: if (BN_bn2bin(v, d + 1) != len)
150: return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
151: /* If MSB is set, prepend a \0 */
152: if (len > 0 && (d[1] & 0x80) != 0)
153: prepend = 1;
154: if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
155: bzero(d, sizeof(d));
156: return r;
157: }
158: bzero(d, sizeof(d));
159: return 0;
160: }
161:
162: int
163: sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v)
164: {
165: int r, len_bits = BN_num_bits(v);
166: size_t len_bytes = (len_bits + 7) / 8;
167: u_char d[SSHBUF_MAX_BIGNUM], *dp;
168:
169: if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM)
170: return SSH_ERR_INVALID_ARGUMENT;
171: if (BN_bn2bin(v, d) != (int)len_bytes)
172: return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
173: if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) {
174: bzero(d, sizeof(d));
175: return r;
176: }
177: POKE_U16(dp, len_bits);
1.3 djm 178: if (len_bytes != 0)
179: memcpy(dp + 2, d, len_bytes);
1.1 djm 180: bzero(d, sizeof(d));
181: return 0;
182: }
183:
184: int
185: sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
186: {
187: u_char d[SSHBUF_MAX_ECPOINT];
188: BN_CTX *bn_ctx;
189: size_t len;
190: int ret;
191:
192: if ((bn_ctx = BN_CTX_new()) == NULL)
193: return SSH_ERR_ALLOC_FAIL;
194: if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
195: NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) {
196: BN_CTX_free(bn_ctx);
197: return SSH_ERR_INVALID_ARGUMENT;
198: }
199: if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
200: d, len, bn_ctx) != len) {
201: BN_CTX_free(bn_ctx);
202: return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
203: }
204: BN_CTX_free(bn_ctx);
205: ret = sshbuf_put_string(buf, d, len);
206: bzero(d, len);
207: return ret;
208: }
209:
210: int
211: sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
212: {
213: return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
214: EC_KEY_get0_group(v));
215: }
216: