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