Annotation of src/usr.bin/ssh/kexkemc.c, Revision 1.3
1.3 ! djm 1: /* $OpenBSD: kexkemc.c,v 1.2 2019/01/21 10:24:09 djm Exp $ */
1.1 djm 2: /*
3: * Copyright (c) 2019 Markus Friedl. All rights reserved.
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:
26: #include <sys/types.h>
27:
28: #include <stdio.h>
29: #include <string.h>
30: #include <signal.h>
31:
32: #include "sshkey.h"
33: #include "kex.h"
34: #include "log.h"
35: #include "packet.h"
36: #include "ssh2.h"
37: #include "sshbuf.h"
38: #include "digest.h"
39: #include "ssherr.h"
40:
41: static int
42: input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh);
43:
44: int
45: kex_kem_client(struct ssh *ssh)
46: {
47: struct kex *kex = ssh->kex;
48: int r;
49:
1.2 djm 50: switch (kex->kex_type) {
1.3 ! djm 51: case KEX_DH_GRP1_SHA1:
! 52: case KEX_DH_GRP14_SHA1:
! 53: case KEX_DH_GRP14_SHA256:
! 54: case KEX_DH_GRP16_SHA512:
! 55: case KEX_DH_GRP18_SHA512:
! 56: r = kex_dh_keypair(kex);
! 57: break;
1.2 djm 58: case KEX_C25519_SHA256:
59: r = kex_c25519_keypair(kex);
60: break;
61: case KEX_KEM_SNTRUP4591761X25519_SHA512:
62: r = kex_kem_sntrup4591761x25519_keypair(kex);
63: break;
64: default:
65: r = SSH_ERR_INVALID_ARGUMENT;
66: break;
67: }
68: if (r != 0)
1.1 djm 69: return r;
70: if ((r = sshpkt_start(ssh, SSH2_MSG_KEX_ECDH_INIT)) != 0 ||
71: (r = sshpkt_put_stringb(ssh, kex->kem_client_pub)) != 0 ||
72: (r = sshpkt_send(ssh)) != 0)
73: return r;
74: debug("expecting SSH2_MSG_KEX_ECDH_REPLY");
75: ssh_dispatch_set(ssh, SSH2_MSG_KEX_ECDH_REPLY, &input_kex_kem_reply);
76: return 0;
77: }
78:
79: static int
80: input_kex_kem_reply(int type, u_int32_t seq, struct ssh *ssh)
81: {
82: struct kex *kex = ssh->kex;
83: struct sshkey *server_host_key = NULL;
84: struct sshbuf *shared_secret = NULL;
85: u_char *server_pubkey = NULL;
86: u_char *server_host_key_blob = NULL, *signature = NULL;
87: u_char hash[SSH_DIGEST_MAX_LENGTH];
88: size_t slen, pklen, sbloblen, hashlen;
89: int r;
90:
91: /* hostkey */
92: if ((r = sshpkt_get_string(ssh, &server_host_key_blob,
93: &sbloblen)) != 0 ||
94: (r = sshkey_from_blob(server_host_key_blob, sbloblen,
95: &server_host_key)) != 0)
96: goto out;
97: if ((r = kex_verify_host_key(ssh, server_host_key)) != 0)
98: goto out;
99:
100: /* Q_S, server public key */
101: /* signed H */
102: if ((r = sshpkt_get_string(ssh, &server_pubkey, &pklen)) != 0 ||
103: (r = sshpkt_get_string(ssh, &signature, &slen)) != 0 ||
104: (r = sshpkt_get_end(ssh)) != 0)
105: goto out;
106:
107: /* compute shared secret */
1.2 djm 108: switch (kex->kex_type) {
1.3 ! djm 109: case KEX_DH_GRP1_SHA1:
! 110: case KEX_DH_GRP14_SHA1:
! 111: case KEX_DH_GRP14_SHA256:
! 112: case KEX_DH_GRP16_SHA512:
! 113: case KEX_DH_GRP18_SHA512:
! 114: r = kex_dh_dec(kex, server_pubkey, pklen, &shared_secret);
! 115: break;
1.2 djm 116: case KEX_C25519_SHA256:
117: r = kex_c25519_dec(kex, server_pubkey, pklen, &shared_secret);
118: break;
119: case KEX_KEM_SNTRUP4591761X25519_SHA512:
120: r = kex_kem_sntrup4591761x25519_dec(kex, server_pubkey, pklen,
121: &shared_secret);
122: break;
123: default:
124: r = SSH_ERR_INVALID_ARGUMENT;
125: break;
126: }
127: if (r !=0 )
1.1 djm 128: goto out;
129:
130: /* calc and verify H */
131: hashlen = sizeof(hash);
132: if ((r = kex_c25519_hash(
133: kex->hash_alg,
134: kex->client_version,
135: kex->server_version,
136: sshbuf_ptr(kex->my), sshbuf_len(kex->my),
137: sshbuf_ptr(kex->peer), sshbuf_len(kex->peer),
138: server_host_key_blob, sbloblen,
139: sshbuf_ptr(kex->kem_client_pub), sshbuf_len(kex->kem_client_pub),
140: server_pubkey, pklen,
141: sshbuf_ptr(shared_secret), sshbuf_len(shared_secret),
142: hash, &hashlen)) != 0)
143: goto out;
144:
145: if ((r = sshkey_verify(server_host_key, signature, slen, hash, hashlen,
146: kex->hostkey_alg, ssh->compat)) != 0)
147: goto out;
148:
149: if ((r = kex_derive_keys(ssh, hash, hashlen, shared_secret)) == 0)
150: r = kex_send_newkeys(ssh);
151: out:
152: explicit_bzero(hash, sizeof(hash));
153: explicit_bzero(kex->c25519_client_key, sizeof(kex->c25519_client_key));
154: explicit_bzero(kex->sntrup4591761_client_key,
155: sizeof(kex->sntrup4591761_client_key));
156: free(server_host_key_blob);
157: free(server_pubkey);
158: free(signature);
159: sshkey_free(server_host_key);
160: sshbuf_free(shared_secret);
161: sshbuf_free(kex->kem_client_pub);
162: kex->kem_client_pub = NULL;
163: return r;
164: }