summaryrefslogtreecommitdiff
path: root/kexc25519.c
diff options
context:
space:
mode:
Diffstat (limited to 'kexc25519.c')
-rw-r--r--kexc25519.c182
1 files changed, 124 insertions, 58 deletions
diff --git a/kexc25519.c b/kexc25519.c
index 0897b8c51..f13d766d7 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,6 +1,6 @@
1/* $OpenBSD: kexc25519.c,v 1.10 2016/05/02 08:49:03 djm Exp $ */ 1/* $OpenBSD: kexc25519.c,v 1.17 2019/01/21 10:40:11 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2019 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
5 * Copyright (c) 2013 Aris Adamantiadis. All rights reserved. 5 * Copyright (c) 2013 Aris Adamantiadis. All rights reserved.
6 * 6 *
@@ -29,20 +29,16 @@
29 29
30#include <sys/types.h> 30#include <sys/types.h>
31 31
32#include <signal.h> 32#include <stdio.h>
33#include <string.h> 33#include <string.h>
34#include <signal.h>
34 35
35#include <openssl/bn.h>
36#include <openssl/evp.h>
37
38#include "sshbuf.h"
39#include "ssh2.h"
40#include "sshkey.h" 36#include "sshkey.h"
41#include "cipher.h"
42#include "kex.h" 37#include "kex.h"
43#include "log.h" 38#include "sshbuf.h"
44#include "digest.h" 39#include "digest.h"
45#include "ssherr.h" 40#include "ssherr.h"
41#include "ssh2.h"
46 42
47extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], 43extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE],
48 const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) 44 const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE])
@@ -60,74 +56,144 @@ kexc25519_keygen(u_char key[CURVE25519_SIZE], u_char pub[CURVE25519_SIZE])
60} 56}
61 57
62int 58int
63kexc25519_shared_key(const u_char key[CURVE25519_SIZE], 59kexc25519_shared_key_ext(const u_char key[CURVE25519_SIZE],
64 const u_char pub[CURVE25519_SIZE], struct sshbuf *out) 60 const u_char pub[CURVE25519_SIZE], struct sshbuf *out, int raw)
65{ 61{
66 u_char shared_key[CURVE25519_SIZE]; 62 u_char shared_key[CURVE25519_SIZE];
63 u_char zero[CURVE25519_SIZE];
67 int r; 64 int r;
68 65
69 /* Check for all-zero public key */ 66 crypto_scalarmult_curve25519(shared_key, key, pub);
70 explicit_bzero(shared_key, CURVE25519_SIZE); 67
71 if (timingsafe_bcmp(pub, shared_key, CURVE25519_SIZE) == 0) 68 /* Check for all-zero shared secret */
69 explicit_bzero(zero, CURVE25519_SIZE);
70 if (timingsafe_bcmp(zero, shared_key, CURVE25519_SIZE) == 0)
72 return SSH_ERR_KEY_INVALID_EC_VALUE; 71 return SSH_ERR_KEY_INVALID_EC_VALUE;
73 72
74 crypto_scalarmult_curve25519(shared_key, key, pub);
75#ifdef DEBUG_KEXECDH 73#ifdef DEBUG_KEXECDH
76 dump_digest("shared secret", shared_key, CURVE25519_SIZE); 74 dump_digest("shared secret", shared_key, CURVE25519_SIZE);
77#endif 75#endif
78 sshbuf_reset(out); 76 if (raw)
79 r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE); 77 r = sshbuf_put(out, shared_key, CURVE25519_SIZE);
78 else
79 r = sshbuf_put_bignum2_bytes(out, shared_key, CURVE25519_SIZE);
80 explicit_bzero(shared_key, CURVE25519_SIZE); 80 explicit_bzero(shared_key, CURVE25519_SIZE);
81 return r; 81 return r;
82} 82}
83 83
84int 84int
85kex_c25519_hash( 85kexc25519_shared_key(const u_char key[CURVE25519_SIZE],
86 int hash_alg, 86 const u_char pub[CURVE25519_SIZE], struct sshbuf *out)
87 const char *client_version_string, 87{
88 const char *server_version_string, 88 return kexc25519_shared_key_ext(key, pub, out, 0);
89 const u_char *ckexinit, size_t ckexinitlen, 89}
90 const u_char *skexinit, size_t skexinitlen, 90
91 const u_char *serverhostkeyblob, size_t sbloblen, 91int
92 const u_char client_dh_pub[CURVE25519_SIZE], 92kex_c25519_keypair(struct kex *kex)
93 const u_char server_dh_pub[CURVE25519_SIZE],
94 const u_char *shared_secret, size_t secretlen,
95 u_char *hash, size_t *hashlen)
96{ 93{
97 struct sshbuf *b; 94 struct sshbuf *buf = NULL;
95 u_char *cp = NULL;
98 int r; 96 int r;
99 97
100 if (*hashlen < ssh_digest_bytes(hash_alg)) 98 if ((buf = sshbuf_new()) == NULL)
101 return SSH_ERR_INVALID_ARGUMENT;
102 if ((b = sshbuf_new()) == NULL)
103 return SSH_ERR_ALLOC_FAIL; 99 return SSH_ERR_ALLOC_FAIL;
104 if ((r = sshbuf_put_cstring(b, client_version_string)) < 0 || 100 if ((r = sshbuf_reserve(buf, CURVE25519_SIZE, &cp)) != 0)
105 (r = sshbuf_put_cstring(b, server_version_string)) < 0 || 101 goto out;
106 /* kexinit messages: fake header: len+SSH2_MSG_KEXINIT */ 102 kexc25519_keygen(kex->c25519_client_key, cp);
107 (r = sshbuf_put_u32(b, ckexinitlen+1)) < 0 || 103#ifdef DEBUG_KEXECDH
108 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || 104 dump_digest("client public key c25519:", cp, CURVE25519_SIZE);
109 (r = sshbuf_put(b, ckexinit, ckexinitlen)) < 0 || 105#endif
110 (r = sshbuf_put_u32(b, skexinitlen+1)) < 0 || 106 kex->client_pub = buf;
111 (r = sshbuf_put_u8(b, SSH2_MSG_KEXINIT)) < 0 || 107 buf = NULL;
112 (r = sshbuf_put(b, skexinit, skexinitlen)) < 0 || 108 out:
113 (r = sshbuf_put_string(b, serverhostkeyblob, sbloblen)) < 0 || 109 sshbuf_free(buf);
114 (r = sshbuf_put_string(b, client_dh_pub, CURVE25519_SIZE)) < 0 || 110 return r;
115 (r = sshbuf_put_string(b, server_dh_pub, CURVE25519_SIZE)) < 0 || 111}
116 (r = sshbuf_put(b, shared_secret, secretlen)) < 0) { 112
117 sshbuf_free(b); 113int
118 return r; 114kex_c25519_enc(struct kex *kex, const struct sshbuf *client_blob,
115 struct sshbuf **server_blobp, struct sshbuf **shared_secretp)
116{
117 struct sshbuf *server_blob = NULL;
118 struct sshbuf *buf = NULL;
119 const u_char *client_pub;
120 u_char *server_pub;
121 u_char server_key[CURVE25519_SIZE];
122 int r;
123
124 *server_blobp = NULL;
125 *shared_secretp = NULL;
126
127 if (sshbuf_len(client_blob) != CURVE25519_SIZE) {
128 r = SSH_ERR_SIGNATURE_INVALID;
129 goto out;
119 } 130 }
120#ifdef DEBUG_KEX 131 client_pub = sshbuf_ptr(client_blob);
121 sshbuf_dump(b, stderr); 132#ifdef DEBUG_KEXECDH
133 dump_digest("client public key 25519:", client_pub, CURVE25519_SIZE);
122#endif 134#endif
123 if (ssh_digest_buffer(hash_alg, b, hash, *hashlen) != 0) { 135 /* allocate space for encrypted KEM key and ECDH pub key */
124 sshbuf_free(b); 136 if ((server_blob = sshbuf_new()) == NULL) {
125 return SSH_ERR_LIBCRYPTO_ERROR; 137 r = SSH_ERR_ALLOC_FAIL;
138 goto out;
126 } 139 }
127 sshbuf_free(b); 140 if ((r = sshbuf_reserve(server_blob, CURVE25519_SIZE, &server_pub)) != 0)
128 *hashlen = ssh_digest_bytes(hash_alg); 141 goto out;
129#ifdef DEBUG_KEX 142 kexc25519_keygen(server_key, server_pub);
130 dump_digest("hash", hash, *hashlen); 143 /* allocate shared secret */
144 if ((buf = sshbuf_new()) == NULL) {
145 r = SSH_ERR_ALLOC_FAIL;
146 goto out;
147 }
148 if ((r = kexc25519_shared_key_ext(server_key, client_pub, buf, 0)) < 0)
149 goto out;
150#ifdef DEBUG_KEXECDH
151 dump_digest("server public key 25519:", server_pub, CURVE25519_SIZE);
152 dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
131#endif 153#endif
132 return 0; 154 *server_blobp = server_blob;
155 *shared_secretp = buf;
156 server_blob = NULL;
157 buf = NULL;
158 out:
159 explicit_bzero(server_key, sizeof(server_key));
160 sshbuf_free(server_blob);
161 sshbuf_free(buf);
162 return r;
163}
164
165int
166kex_c25519_dec(struct kex *kex, const struct sshbuf *server_blob,
167 struct sshbuf **shared_secretp)
168{
169 struct sshbuf *buf = NULL;
170 const u_char *server_pub;
171 int r;
172
173 *shared_secretp = NULL;
174
175 if (sshbuf_len(server_blob) != CURVE25519_SIZE) {
176 r = SSH_ERR_SIGNATURE_INVALID;
177 goto out;
178 }
179 server_pub = sshbuf_ptr(server_blob);
180#ifdef DEBUG_KEXECDH
181 dump_digest("server public key c25519:", server_pub, CURVE25519_SIZE);
182#endif
183 /* shared secret */
184 if ((buf = sshbuf_new()) == NULL) {
185 r = SSH_ERR_ALLOC_FAIL;
186 goto out;
187 }
188 if ((r = kexc25519_shared_key_ext(kex->c25519_client_key, server_pub,
189 buf, 0)) < 0)
190 goto out;
191#ifdef DEBUG_KEXECDH
192 dump_digest("encoded shared secret:", sshbuf_ptr(buf), sshbuf_len(buf));
193#endif
194 *shared_secretp = buf;
195 buf = NULL;
196 out:
197 sshbuf_free(buf);
198 return r;
133} 199}