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