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