blob: 67133e3394812b7a08d7123a8c40ff553a57bd1f [file] [log] [blame]
djm@openbsd.orgaaca72d2019-01-21 10:40:11 +00001/* $OpenBSD: kexdh.c,v 1.32 2019/01/21 10:40:11 djm Exp $ */
Ben Lindstrom22b19b42001-04-04 17:39:19 +00002/*
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +00003 * Copyright (c) 2019 Markus Friedl. All rights reserved.
Ben Lindstrom22b19b42001-04-04 17:39:19 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "includes.h"
Ben Lindstrom22b19b42001-04-04 17:39:19 +000027
Damien Miller72ef7c12015-01-15 02:21:31 +110028#ifdef WITH_OPENSSL
29
Damien Millerd7834352006-08-05 12:39:39 +100030#include <sys/types.h>
31
32#include <signal.h>
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +000033#include <stdio.h>
34#include <string.h>
Damien Millerd7834352006-08-05 12:39:39 +100035
Damien Miller2de9cec2019-01-22 10:49:52 +110036#include "openbsd-compat/openssl-compat.h"
Damien Millerd5520392019-01-22 10:50:40 +110037#include <openssl/dh.h>
Damien Miller2de9cec2019-01-22 10:49:52 +110038
markus@openbsd.org57d10cb2015-01-19 20:16:15 +000039#include "sshkey.h"
Damien Miller8e7fb332003-02-24 12:03:03 +110040#include "kex.h"
markus@openbsd.org57d10cb2015-01-19 20:16:15 +000041#include "sshbuf.h"
Damien Millerb3051d02014-01-10 10:58:53 +110042#include "digest.h"
Damien Millerb7235722019-01-21 23:11:21 +110043#include "ssherr.h"
djm@openbsd.orgdec5e9d2019-01-21 10:03:37 +000044#include "dh.h"
Ben Lindstrom22b19b42001-04-04 17:39:19 +000045
markus@openbsd.org57d10cb2015-01-19 20:16:15 +000046int
djm@openbsd.orge93bd982019-01-21 10:00:23 +000047kex_dh_keygen(struct kex *kex)
48{
49 switch (kex->kex_type) {
50 case KEX_DH_GRP1_SHA1:
51 kex->dh = dh_new_group1();
52 break;
53 case KEX_DH_GRP14_SHA1:
54 case KEX_DH_GRP14_SHA256:
55 kex->dh = dh_new_group14();
56 break;
57 case KEX_DH_GRP16_SHA512:
58 kex->dh = dh_new_group16();
59 break;
60 case KEX_DH_GRP18_SHA512:
61 kex->dh = dh_new_group18();
62 break;
63 default:
64 return SSH_ERR_INVALID_ARGUMENT;
65 }
66 if (kex->dh == NULL)
67 return SSH_ERR_ALLOC_FAIL;
68 return (dh_gen_key(kex->dh, kex->we_need * 8));
69}
70
71int
djm@openbsd.orgdec5e9d2019-01-21 10:03:37 +000072kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
73{
74 BIGNUM *shared_secret = NULL;
75 u_char *kbuf = NULL;
76 size_t klen = 0;
77 int kout, r;
78
79#ifdef DEBUG_KEXDH
80 fprintf(stderr, "dh_pub= ");
81 BN_print_fp(stderr, dh_pub);
82 fprintf(stderr, "\n");
83 debug("bits %d", BN_num_bits(dh_pub));
84 DHparams_print_fp(stderr, kex->dh);
85 fprintf(stderr, "\n");
86#endif
87
88 if (!dh_pub_is_valid(kex->dh, dh_pub)) {
89 r = SSH_ERR_MESSAGE_INCOMPLETE;
90 goto out;
91 }
92 klen = DH_size(kex->dh);
93 if ((kbuf = malloc(klen)) == NULL ||
94 (shared_secret = BN_new()) == NULL) {
95 r = SSH_ERR_ALLOC_FAIL;
96 goto out;
97 }
98 if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
99 BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
100 r = SSH_ERR_LIBCRYPTO_ERROR;
101 goto out;
102 }
103#ifdef DEBUG_KEXDH
104 dump_digest("shared secret", kbuf, kout);
105#endif
106 r = sshbuf_put_bignum2(out, shared_secret);
107 out:
108 freezero(kbuf, klen);
109 BN_clear_free(shared_secret);
110 return r;
111}
112
113int
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000114kex_dh_keypair(struct kex *kex)
Ben Lindstrom22b19b42001-04-04 17:39:19 +0000115{
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000116 const BIGNUM *pub_key;
117 struct sshbuf *buf = NULL;
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000118 int r;
Ben Lindstrom22b19b42001-04-04 17:39:19 +0000119
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000120 if ((r = kex_dh_keygen(kex)) != 0)
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000121 return r;
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000122 DH_get0_key(kex->dh, &pub_key, NULL);
123 if ((buf = sshbuf_new()) == NULL)
124 return SSH_ERR_ALLOC_FAIL;
125 if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 ||
126 (r = sshbuf_get_u32(buf, NULL)) != 0)
127 goto out;
128#ifdef DEBUG_KEXDH
129 DHparams_print_fp(stderr, kex->dh);
130 fprintf(stderr, "pub= ");
131 BN_print_fp(stderr, pub_key);
132 fprintf(stderr, "\n");
Ben Lindstrom22b19b42001-04-04 17:39:19 +0000133#endif
djm@openbsd.orgaaca72d2019-01-21 10:40:11 +0000134 kex->client_pub = buf;
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000135 buf = NULL;
136 out:
137 sshbuf_free(buf);
138 return r;
139}
140
141int
djm@openbsd.org71e67ff2019-01-21 10:35:09 +0000142kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000143 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
144{
145 const BIGNUM *pub_key;
146 struct sshbuf *server_blob = NULL;
147 int r;
148
149 *server_blobp = NULL;
150 *shared_secretp = NULL;
151
152 if ((r = kex_dh_keygen(kex)) != 0)
153 goto out;
154 DH_get0_key(kex->dh, &pub_key, NULL);
155 if ((server_blob = sshbuf_new()) == NULL) {
156 r = SSH_ERR_ALLOC_FAIL;
157 goto out;
markus@openbsd.org57d10cb2015-01-19 20:16:15 +0000158 }
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000159 if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
160 (r = sshbuf_get_u32(server_blob, NULL)) != 0)
161 goto out;
djm@openbsd.org71e67ff2019-01-21 10:35:09 +0000162 if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000163 goto out;
164 *server_blobp = server_blob;
165 server_blob = NULL;
166 out:
167 DH_free(kex->dh);
168 kex->dh = NULL;
169 sshbuf_free(server_blob);
170 return r;
171}
172
173int
djm@openbsd.org71e67ff2019-01-21 10:35:09 +0000174kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000175 struct sshbuf **shared_secretp)
176{
177 struct sshbuf *buf = NULL;
178 BIGNUM *dh_pub = NULL;
179 int r;
180
181 *shared_secretp = NULL;
182
183 if ((buf = sshbuf_new()) == NULL) {
184 r = SSH_ERR_ALLOC_FAIL;
185 goto out;
186 }
djm@openbsd.org71e67ff2019-01-21 10:35:09 +0000187 if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
188 (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000189 goto out;
djm@openbsd.org9c9c97e2019-01-21 10:28:01 +0000190 sshbuf_reset(buf);
191 if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0)
192 goto out;
193 *shared_secretp = buf;
194 buf = NULL;
195 out:
196 DH_free(kex->dh);
197 kex->dh = NULL;
198 sshbuf_free(buf);
199 return r;
Ben Lindstrom22b19b42001-04-04 17:39:19 +0000200}
Damien Miller72ef7c12015-01-15 02:21:31 +1100201#endif /* WITH_OPENSSL */