Annotation of src/usr.bin/ssh/kexdh.c, Revision 1.34
1.34 ! djm 1: /* $OpenBSD: kexdh.c,v 1.33 2020/05/08 05:13:14 djm Exp $ */
1.1 markus 2: /*
1.30 djm 3: * Copyright (c) 2019 Markus Friedl. All rights reserved.
1.1 markus 4: *
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:
1.23 deraadt 26: #include <sys/types.h>
27:
1.30 djm 28: #include <stdio.h>
29: #include <string.h>
1.23 deraadt 30: #include <signal.h>
1.1 markus 31:
1.25 markus 32: #include "sshkey.h"
1.1 markus 33: #include "kex.h"
1.25 markus 34: #include "sshbuf.h"
1.24 djm 35: #include "digest.h"
1.30 djm 36: #include "ssherr.h"
1.29 djm 37: #include "dh.h"
1.33 djm 38: #include "log.h"
1.28 djm 39:
40: int
41: kex_dh_keygen(struct kex *kex)
42: {
43: switch (kex->kex_type) {
44: case KEX_DH_GRP1_SHA1:
45: kex->dh = dh_new_group1();
46: break;
47: case KEX_DH_GRP14_SHA1:
48: case KEX_DH_GRP14_SHA256:
49: kex->dh = dh_new_group14();
50: break;
51: case KEX_DH_GRP16_SHA512:
52: kex->dh = dh_new_group16();
53: break;
54: case KEX_DH_GRP18_SHA512:
55: kex->dh = dh_new_group18();
56: break;
57: default:
58: return SSH_ERR_INVALID_ARGUMENT;
59: }
60: if (kex->dh == NULL)
61: return SSH_ERR_ALLOC_FAIL;
62: return (dh_gen_key(kex->dh, kex->we_need * 8));
63: }
1.1 markus 64:
1.25 markus 65: int
1.29 djm 66: kex_dh_compute_key(struct kex *kex, BIGNUM *dh_pub, struct sshbuf *out)
67: {
68: BIGNUM *shared_secret = NULL;
69: u_char *kbuf = NULL;
70: size_t klen = 0;
71: int kout, r;
72:
73: #ifdef DEBUG_KEXDH
74: fprintf(stderr, "dh_pub= ");
75: BN_print_fp(stderr, dh_pub);
76: fprintf(stderr, "\n");
77: debug("bits %d", BN_num_bits(dh_pub));
78: DHparams_print_fp(stderr, kex->dh);
79: fprintf(stderr, "\n");
80: #endif
81:
82: if (!dh_pub_is_valid(kex->dh, dh_pub)) {
83: r = SSH_ERR_MESSAGE_INCOMPLETE;
84: goto out;
85: }
86: klen = DH_size(kex->dh);
87: if ((kbuf = malloc(klen)) == NULL ||
88: (shared_secret = BN_new()) == NULL) {
89: r = SSH_ERR_ALLOC_FAIL;
90: goto out;
91: }
92: if ((kout = DH_compute_key(kbuf, dh_pub, kex->dh)) < 0 ||
93: BN_bin2bn(kbuf, kout, shared_secret) == NULL) {
94: r = SSH_ERR_LIBCRYPTO_ERROR;
95: goto out;
96: }
97: #ifdef DEBUG_KEXDH
98: dump_digest("shared secret", kbuf, kout);
99: #endif
100: r = sshbuf_put_bignum2(out, shared_secret);
101: out:
102: freezero(kbuf, klen);
103: BN_clear_free(shared_secret);
104: return r;
105: }
106:
107: int
1.30 djm 108: kex_dh_keypair(struct kex *kex)
1.1 markus 109: {
1.30 djm 110: const BIGNUM *pub_key;
111: struct sshbuf *buf = NULL;
1.25 markus 112: int r;
1.1 markus 113:
1.30 djm 114: if ((r = kex_dh_keygen(kex)) != 0)
115: return r;
116: DH_get0_key(kex->dh, &pub_key, NULL);
117: if ((buf = sshbuf_new()) == NULL)
1.25 markus 118: return SSH_ERR_ALLOC_FAIL;
1.30 djm 119: if ((r = sshbuf_put_bignum2(buf, pub_key)) != 0 ||
120: (r = sshbuf_get_u32(buf, NULL)) != 0)
121: goto out;
122: #ifdef DEBUG_KEXDH
123: DHparams_print_fp(stderr, kex->dh);
124: fprintf(stderr, "pub= ");
125: BN_print_fp(stderr, pub_key);
126: fprintf(stderr, "\n");
127: #endif
1.32 djm 128: kex->client_pub = buf;
1.30 djm 129: buf = NULL;
130: out:
131: sshbuf_free(buf);
132: return r;
133: }
134:
135: int
1.31 djm 136: kex_dh_enc(struct kex *kex, const struct sshbuf *client_blob,
1.30 djm 137: struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
138: {
139: const BIGNUM *pub_key;
140: struct sshbuf *server_blob = NULL;
141: int r;
142:
143: *server_blobp = NULL;
144: *shared_secretp = NULL;
145:
146: if ((r = kex_dh_keygen(kex)) != 0)
147: goto out;
148: DH_get0_key(kex->dh, &pub_key, NULL);
149: if ((server_blob = sshbuf_new()) == NULL) {
150: r = SSH_ERR_ALLOC_FAIL;
151: goto out;
152: }
153: if ((r = sshbuf_put_bignum2(server_blob, pub_key)) != 0 ||
154: (r = sshbuf_get_u32(server_blob, NULL)) != 0)
155: goto out;
1.31 djm 156: if ((r = kex_dh_dec(kex, client_blob, shared_secretp)) != 0)
1.30 djm 157: goto out;
158: *server_blobp = server_blob;
159: server_blob = NULL;
160: out:
161: DH_free(kex->dh);
162: kex->dh = NULL;
163: sshbuf_free(server_blob);
164: return r;
165: }
166:
167: int
1.31 djm 168: kex_dh_dec(struct kex *kex, const struct sshbuf *dh_blob,
1.30 djm 169: struct sshbuf **shared_secretp)
170: {
171: struct sshbuf *buf = NULL;
172: BIGNUM *dh_pub = NULL;
173: int r;
174:
175: *shared_secretp = NULL;
176:
177: if ((buf = sshbuf_new()) == NULL) {
178: r = SSH_ERR_ALLOC_FAIL;
179: goto out;
180: }
1.31 djm 181: if ((r = sshbuf_put_stringb(buf, dh_blob)) != 0 ||
182: (r = sshbuf_get_bignum2(buf, &dh_pub)) != 0)
1.30 djm 183: goto out;
184: sshbuf_reset(buf);
185: if ((r = kex_dh_compute_key(kex, dh_pub, buf)) != 0)
186: goto out;
187: *shared_secretp = buf;
188: buf = NULL;
189: out:
1.34 ! djm 190: BN_free(dh_pub);
1.30 djm 191: DH_free(kex->dh);
192: kex->dh = NULL;
193: sshbuf_free(buf);
194: return r;
1.1 markus 195: }