Annotation of src/usr.bin/ssh/sshbuf-getput-crypto.c, Revision 1.7
1.7 ! djm 1: /* $OpenBSD: sshbuf-getput-crypto.c,v 1.6 2019/01/21 09:52:25 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
1.7 ! djm 31: sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM **valp)
1.1 djm 32: {
1.7 ! djm 33: BIGNUM *v;
1.1 djm 34: const u_char *d;
35: size_t len;
36: int r;
37:
1.7 ! djm 38: if (valp != NULL)
! 39: *valp = NULL;
1.4 djm 40: if ((r = sshbuf_get_bignum2_bytes_direct(buf, &d, &len)) != 0)
1.1 djm 41: return r;
1.7 ! djm 42: if (valp != NULL) {
! 43: if ((v = BN_new()) == NULL ||
! 44: BN_bin2bn(d, len, v) == NULL) {
! 45: BN_clear_free(v);
! 46: return SSH_ERR_ALLOC_FAIL;
! 47: }
! 48: *valp = v;
! 49: }
1.1 djm 50: return 0;
51: }
52:
53: static int
54: get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
55: {
56: /* Refuse overlong bignums */
57: if (len == 0 || len > SSHBUF_MAX_ECPOINT)
58: return SSH_ERR_ECPOINT_TOO_LARGE;
59: /* Only handle uncompressed points */
60: if (*d != POINT_CONVERSION_UNCOMPRESSED)
61: return SSH_ERR_INVALID_FORMAT;
62: if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
63: return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
64: return 0;
65: }
66:
67: int
68: sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
69: {
70: const u_char *d;
71: size_t len;
72: int r;
73:
74: if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
75: return r;
76: if ((r = get_ec(d, len, v, g)) != 0)
77: return r;
78: /* Skip string */
79: if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
80: /* Shouldn't happen */
81: SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
82: SSHBUF_ABORT();
83: return SSH_ERR_INTERNAL_ERROR;
84: }
85: return 0;
86: }
87:
88: int
89: sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
90: {
91: EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
92: int r;
93: const u_char *d;
94: size_t len;
95:
96: if (pt == NULL) {
97: SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
98: return SSH_ERR_ALLOC_FAIL;
99: }
100: if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
101: EC_POINT_free(pt);
102: return r;
103: }
104: if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
105: EC_POINT_free(pt);
106: return r;
107: }
108: if (EC_KEY_set_public_key(v, pt) != 1) {
109: EC_POINT_free(pt);
110: return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
111: }
112: EC_POINT_free(pt);
113: /* Skip string */
114: if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
115: /* Shouldn't happen */
116: SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
117: SSHBUF_ABORT();
118: return SSH_ERR_INTERNAL_ERROR;
119: }
120: return 0;
121: }
122:
123: int
124: sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
125: {
126: u_char d[SSHBUF_MAX_BIGNUM + 1];
127: int len = BN_num_bytes(v), prepend = 0, r;
128:
129: if (len < 0 || len > SSHBUF_MAX_BIGNUM)
130: return SSH_ERR_INVALID_ARGUMENT;
131: *d = '\0';
132: if (BN_bn2bin(v, d + 1) != len)
133: return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
134: /* If MSB is set, prepend a \0 */
135: if (len > 0 && (d[1] & 0x80) != 0)
136: prepend = 1;
137: if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
1.5 djm 138: explicit_bzero(d, sizeof(d));
1.1 djm 139: return r;
140: }
1.5 djm 141: explicit_bzero(d, sizeof(d));
1.1 djm 142: return 0;
143: }
144:
145: int
146: sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
147: {
148: u_char d[SSHBUF_MAX_ECPOINT];
149: BN_CTX *bn_ctx;
150: size_t len;
151: int ret;
152:
153: if ((bn_ctx = BN_CTX_new()) == NULL)
154: return SSH_ERR_ALLOC_FAIL;
155: if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
156: NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) {
157: BN_CTX_free(bn_ctx);
158: return SSH_ERR_INVALID_ARGUMENT;
159: }
160: if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
161: d, len, bn_ctx) != len) {
162: BN_CTX_free(bn_ctx);
163: return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
164: }
165: BN_CTX_free(bn_ctx);
166: ret = sshbuf_put_string(buf, d, len);
1.5 djm 167: explicit_bzero(d, len);
1.1 djm 168: return ret;
169: }
170:
171: int
172: sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
173: {
174: return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
175: EC_KEY_get0_group(v));
176: }
177: