]> git.ipfire.org Git - thirdparty/openssh-portable.git/blame - kexecdh.c
upstream: Factor out PuTTY setup.
[thirdparty/openssh-portable.git] / kexecdh.c
CommitLineData
aaca72d6 1/* $OpenBSD: kexecdh.c,v 1.10 2019/01/21 10:40:11 djm Exp $ */
eb8b60e3 2/*
eb8b60e3 3 * Copyright (c) 2010 Damien Miller. All rights reserved.
92dda34e 4 * Copyright (c) 2019 Markus Friedl. All rights reserved.
eb8b60e3
DM
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
c79ff077
DM
27#include "includes.h"
28
72ef7c14 29#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
6af914a1 30
eb8b60e3
DM
31#include <sys/types.h>
32
92dda34e 33#include <stdio.h>
eb8b60e3 34#include <string.h>
92dda34e 35#include <signal.h>
eb8b60e3 36
eb8b60e3
DM
37#include <openssl/ecdh.h>
38
57d10cbe 39#include "sshkey.h"
eb8b60e3 40#include "kex.h"
57d10cbe 41#include "sshbuf.h"
b3051d01 42#include "digest.h"
57d10cbe 43#include "ssherr.h"
eb8b60e3 44
92dda34e 45static int
71e67fff 46kex_ecdh_dec_key_group(struct kex *, const struct sshbuf *, EC_KEY *key,
92dda34e 47 const EC_GROUP *, struct sshbuf **);
48
57d10cbe 49int
92dda34e 50kex_ecdh_keypair(struct kex *kex)
51{
52 EC_KEY *client_key = NULL;
53 const EC_GROUP *group;
54 const EC_POINT *public_key;
55 struct sshbuf *buf = NULL;
56 int r;
57
58 if ((client_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
59 r = SSH_ERR_ALLOC_FAIL;
60 goto out;
61 }
62 if (EC_KEY_generate_key(client_key) != 1) {
63 r = SSH_ERR_LIBCRYPTO_ERROR;
64 goto out;
65 }
66 group = EC_KEY_get0_group(client_key);
67 public_key = EC_KEY_get0_public_key(client_key);
68
69 if ((buf = sshbuf_new()) == NULL) {
70 r = SSH_ERR_ALLOC_FAIL;
71 goto out;
72 }
73 if ((r = sshbuf_put_ec(buf, public_key, group)) != 0 ||
74 (r = sshbuf_get_u32(buf, NULL)) != 0)
75 goto out;
76#ifdef DEBUG_KEXECDH
77 fputs("client private key:\n", stderr);
78 sshkey_dump_ec_key(client_key);
79#endif
80 kex->ec_client_key = client_key;
81 kex->ec_group = group;
82 client_key = NULL; /* owned by the kex */
aaca72d6 83 kex->client_pub = buf;
92dda34e 84 buf = NULL;
85 out:
86 EC_KEY_free(client_key);
87 sshbuf_free(buf);
88 return r;
89}
90
91int
71e67fff 92kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
92dda34e 93 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
94{
95 const EC_GROUP *group;
96 const EC_POINT *pub_key;
97 EC_KEY *server_key = NULL;
98 struct sshbuf *server_blob = NULL;
99 int r;
100
101 *server_blobp = NULL;
102 *shared_secretp = NULL;
103
104 if ((server_key = EC_KEY_new_by_curve_name(kex->ec_nid)) == NULL) {
105 r = SSH_ERR_ALLOC_FAIL;
106 goto out;
107 }
108 if (EC_KEY_generate_key(server_key) != 1) {
109 r = SSH_ERR_LIBCRYPTO_ERROR;
110 goto out;
111 }
112 group = EC_KEY_get0_group(server_key);
113
114#ifdef DEBUG_KEXECDH
115 fputs("server private key:\n", stderr);
116 sshkey_dump_ec_key(server_key);
117#endif
118 pub_key = EC_KEY_get0_public_key(server_key);
119 if ((server_blob = sshbuf_new()) == NULL) {
120 r = SSH_ERR_ALLOC_FAIL;
121 goto out;
122 }
123 if ((r = sshbuf_put_ec(server_blob, pub_key, group)) != 0 ||
124 (r = sshbuf_get_u32(server_blob, NULL)) != 0)
125 goto out;
71e67fff 126 if ((r = kex_ecdh_dec_key_group(kex, client_blob, server_key, group,
92dda34e 127 shared_secretp)) != 0)
128 goto out;
129 *server_blobp = server_blob;
130 server_blob = NULL;
131 out:
132 EC_KEY_free(server_key);
133 sshbuf_free(server_blob);
134 return r;
135}
136
137static int
71e67fff 138kex_ecdh_dec_key_group(struct kex *kex, const struct sshbuf *ec_blob,
92dda34e 139 EC_KEY *key, const EC_GROUP *group, struct sshbuf **shared_secretp)
eb8b60e3 140{
92dda34e 141 struct sshbuf *buf = NULL;
142 BIGNUM *shared_secret = NULL;
143 EC_POINT *dh_pub = NULL;
144 u_char *kbuf = NULL;
145 size_t klen = 0;
57d10cbe 146 int r;
eb8b60e3 147
92dda34e 148 *shared_secretp = NULL;
149
150 if ((buf = sshbuf_new()) == NULL) {
151 r = SSH_ERR_ALLOC_FAIL;
152 goto out;
153 }
71e67fff 154 if ((r = sshbuf_put_stringb(buf, ec_blob)) != 0)
92dda34e 155 goto out;
92dda34e 156 if ((dh_pub = EC_POINT_new(group)) == NULL) {
157 r = SSH_ERR_ALLOC_FAIL;
158 goto out;
159 }
160 if ((r = sshbuf_get_ec(buf, dh_pub, group)) != 0) {
161 goto out;
57d10cbe 162 }
92dda34e 163 sshbuf_reset(buf);
164
165#ifdef DEBUG_KEXECDH
166 fputs("public key:\n", stderr);
167 sshkey_dump_ec_point(group, dh_pub);
eb8b60e3 168#endif
92dda34e 169 if (sshkey_ec_validate_public(group, dh_pub) != 0) {
170 r = SSH_ERR_MESSAGE_INCOMPLETE;
171 goto out;
172 }
173 klen = (EC_GROUP_get_degree(group) + 7) / 8;
174 if ((kbuf = malloc(klen)) == NULL ||
175 (shared_secret = BN_new()) == NULL) {
176 r = SSH_ERR_ALLOC_FAIL;
177 goto out;
178 }
179 if (ECDH_compute_key(kbuf, klen, dh_pub, key, NULL) != (int)klen ||
180 BN_bin2bn(kbuf, klen, shared_secret) == NULL) {
181 r = SSH_ERR_LIBCRYPTO_ERROR;
182 goto out;
57d10cbe 183 }
92dda34e 184#ifdef DEBUG_KEXECDH
185 dump_digest("shared secret", kbuf, klen);
eb8b60e3 186#endif
92dda34e 187 if ((r = sshbuf_put_bignum2(buf, shared_secret)) != 0)
188 goto out;
189 *shared_secretp = buf;
190 buf = NULL;
191 out:
192 EC_POINT_clear_free(dh_pub);
193 BN_clear_free(shared_secret);
194 freezero(kbuf, klen);
195 sshbuf_free(buf);
196 return r;
197}
198
199int
71e67fff 200kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
92dda34e 201 struct sshbuf **shared_secretp)
202{
203 int r;
204
71e67fff 205 r = kex_ecdh_dec_key_group(kex, server_blob, kex->ec_client_key,
92dda34e 206 kex->ec_group, shared_secretp);
207 EC_KEY_free(kex->ec_client_key);
208 kex->ec_client_key = NULL;
209 return r;
eb8b60e3 210}
97370f6c
DT
211
212#else
213
fa5bd810
DT
214#include "ssherr.h"
215
edd1d3a6
DM
216struct kex;
217struct sshbuf;
218struct sshkey;
97370f6c
DT
219
220int
221kex_ecdh_keypair(struct kex *kex)
222{
223 return SSH_ERR_SIGN_ALG_UNSUPPORTED;
224}
225
226int
227kex_ecdh_enc(struct kex *kex, const struct sshbuf *client_blob,
228 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
229{
230 return SSH_ERR_SIGN_ALG_UNSUPPORTED;
231}
232
233int
234kex_ecdh_dec(struct kex *kex, const struct sshbuf *server_blob,
235 struct sshbuf **shared_secretp)
236{
237 return SSH_ERR_SIGN_ALG_UNSUPPORTED;
238}
72ef7c14 239#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */