summaryrefslogtreecommitdiff
path: root/cipher.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2014-07-02 15:28:02 +1000
committerDamien Miller <djm@mindrot.org>2014-07-02 15:28:02 +1000
commit8668706d0f52654fe64c0ca41a96113aeab8d2b8 (patch)
tree73e78e1ea3d39206e39870bbe0af17d6c430fb51 /cipher.c
parent2cd7929250cf9e9f658d70dcd452f529ba08c942 (diff)
- djm@cvs.openbsd.org 2014/06/24 01:13:21
[Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c [sshconnect2.c sshd.c sshkey.c sshkey.h [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h] New key API: refactor key-related functions to be more library-like, existing API is offered as a set of wrappers. with and ok markus@ Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew Dempsky and Ron Bowes for a detailed review a few months ago. NB. This commit also removes portable OpenSSH support for OpenSSL <0.9.8e.
Diffstat (limited to 'cipher.c')
-rw-r--r--cipher.c363
1 files changed, 175 insertions, 188 deletions
diff --git a/cipher.c b/cipher.c
index 5569d2455..48ef105ca 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.98 2014/04/29 18:01:49 markus Exp $ */ 1/* $OpenBSD: cipher.c,v 1.99 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -43,23 +43,19 @@
43#include <stdarg.h> 43#include <stdarg.h>
44#include <stdio.h> 44#include <stdio.h>
45 45
46#include "xmalloc.h"
47#include "log.h"
48#include "misc.h"
49#include "cipher.h" 46#include "cipher.h"
50#include "buffer.h" 47#include "misc.h"
48#include "sshbuf.h"
49#include "ssherr.h"
51#include "digest.h" 50#include "digest.h"
52 51
53/* compatibility with old or broken OpenSSL versions */
54#include "openbsd-compat/openssl-compat.h"
55
56#ifdef WITH_SSH1 52#ifdef WITH_SSH1
57extern const EVP_CIPHER *evp_ssh1_bf(void); 53extern const EVP_CIPHER *evp_ssh1_bf(void);
58extern const EVP_CIPHER *evp_ssh1_3des(void); 54extern const EVP_CIPHER *evp_ssh1_3des(void);
59extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); 55extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
60#endif 56#endif
61 57
62struct Cipher { 58struct sshcipher {
63 char *name; 59 char *name;
64 int number; /* for ssh1 only */ 60 int number; /* for ssh1 only */
65 u_int block_size; 61 u_int block_size;
@@ -79,12 +75,12 @@ struct Cipher {
79#endif 75#endif
80}; 76};
81 77
82static const struct Cipher ciphers[] = { 78static const struct sshcipher ciphers[] = {
83#ifdef WITH_SSH1 79#ifdef WITH_SSH1
84 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, 80 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
85 { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, 81 { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
86 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, 82 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
87#endif 83#endif /* WITH_SSH1 */
88#ifdef WITH_OPENSSL 84#ifdef WITH_OPENSSL
89 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, 85 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
90 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, 86 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
@@ -103,12 +99,12 @@ static const struct Cipher ciphers[] = {
103 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, 99 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
104 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, 100 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
105 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, 101 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
106#ifdef OPENSSL_HAVE_EVPGCM 102# ifdef OPENSSL_HAVE_EVPGCM
107 { "aes128-gcm@openssh.com", 103 { "aes128-gcm@openssh.com",
108 SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, 104 SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
109 { "aes256-gcm@openssh.com", 105 { "aes256-gcm@openssh.com",
110 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, 106 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
111#endif 107# endif /* OPENSSL_HAVE_EVPGCM */
112#else /* WITH_OPENSSL */ 108#else /* WITH_OPENSSL */
113 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL }, 109 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
114 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL }, 110 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
@@ -117,18 +113,19 @@ static const struct Cipher ciphers[] = {
117#endif /* WITH_OPENSSL */ 113#endif /* WITH_OPENSSL */
118 { "chacha20-poly1305@openssh.com", 114 { "chacha20-poly1305@openssh.com",
119 SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, 115 SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
116
120 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } 117 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
121}; 118};
122 119
123/*--*/ 120/*--*/
124 121
125/* Returns a list of supported ciphers separated by the specified char. */ 122/* Returns a comma-separated list of supported ciphers. */
126char * 123char *
127cipher_alg_list(char sep, int auth_only) 124cipher_alg_list(char sep, int auth_only)
128{ 125{
129 char *ret = NULL; 126 char *tmp, *ret = NULL;
130 size_t nlen, rlen = 0; 127 size_t nlen, rlen = 0;
131 const Cipher *c; 128 const struct sshcipher *c;
132 129
133 for (c = ciphers; c->name != NULL; c++) { 130 for (c = ciphers; c->name != NULL; c++) {
134 if (c->number != SSH_CIPHER_SSH2) 131 if (c->number != SSH_CIPHER_SSH2)
@@ -138,7 +135,11 @@ cipher_alg_list(char sep, int auth_only)
138 if (ret != NULL) 135 if (ret != NULL)
139 ret[rlen++] = sep; 136 ret[rlen++] = sep;
140 nlen = strlen(c->name); 137 nlen = strlen(c->name);
141 ret = xrealloc(ret, 1, rlen + nlen + 2); 138 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
139 free(ret);
140 return NULL;
141 }
142 ret = tmp;
142 memcpy(ret + rlen, c->name, nlen + 1); 143 memcpy(ret + rlen, c->name, nlen + 1);
143 rlen += nlen; 144 rlen += nlen;
144 } 145 }
@@ -146,19 +147,19 @@ cipher_alg_list(char sep, int auth_only)
146} 147}
147 148
148u_int 149u_int
149cipher_blocksize(const Cipher *c) 150cipher_blocksize(const struct sshcipher *c)
150{ 151{
151 return (c->block_size); 152 return (c->block_size);
152} 153}
153 154
154u_int 155u_int
155cipher_keylen(const Cipher *c) 156cipher_keylen(const struct sshcipher *c)
156{ 157{
157 return (c->key_len); 158 return (c->key_len);
158} 159}
159 160
160u_int 161u_int
161cipher_seclen(const Cipher *c) 162cipher_seclen(const struct sshcipher *c)
162{ 163{
163 if (strcmp("3des-cbc", c->name) == 0) 164 if (strcmp("3des-cbc", c->name) == 0)
164 return 14; 165 return 14;
@@ -166,13 +167,13 @@ cipher_seclen(const Cipher *c)
166} 167}
167 168
168u_int 169u_int
169cipher_authlen(const Cipher *c) 170cipher_authlen(const struct sshcipher *c)
170{ 171{
171 return (c->auth_len); 172 return (c->auth_len);
172} 173}
173 174
174u_int 175u_int
175cipher_ivlen(const Cipher *c) 176cipher_ivlen(const struct sshcipher *c)
176{ 177{
177 /* 178 /*
178 * Default is cipher block size, except for chacha20+poly1305 that 179 * Default is cipher block size, except for chacha20+poly1305 that
@@ -183,13 +184,13 @@ cipher_ivlen(const Cipher *c)
183} 184}
184 185
185u_int 186u_int
186cipher_get_number(const Cipher *c) 187cipher_get_number(const struct sshcipher *c)
187{ 188{
188 return (c->number); 189 return (c->number);
189} 190}
190 191
191u_int 192u_int
192cipher_is_cbc(const Cipher *c) 193cipher_is_cbc(const struct sshcipher *c)
193{ 194{
194 return (c->flags & CFLAG_CBC) != 0; 195 return (c->flags & CFLAG_CBC) != 0;
195} 196}
@@ -206,20 +207,20 @@ cipher_mask_ssh1(int client)
206 return mask; 207 return mask;
207} 208}
208 209
209const Cipher * 210const struct sshcipher *
210cipher_by_name(const char *name) 211cipher_by_name(const char *name)
211{ 212{
212 const Cipher *c; 213 const struct sshcipher *c;
213 for (c = ciphers; c->name != NULL; c++) 214 for (c = ciphers; c->name != NULL; c++)
214 if (strcmp(c->name, name) == 0) 215 if (strcmp(c->name, name) == 0)
215 return c; 216 return c;
216 return NULL; 217 return NULL;
217} 218}
218 219
219const Cipher * 220const struct sshcipher *
220cipher_by_number(int id) 221cipher_by_number(int id)
221{ 222{
222 const Cipher *c; 223 const struct sshcipher *c;
223 for (c = ciphers; c->name != NULL; c++) 224 for (c = ciphers; c->name != NULL; c++)
224 if (c->number == id) 225 if (c->number == id)
225 return c; 226 return c;
@@ -230,23 +231,22 @@ cipher_by_number(int id)
230int 231int
231ciphers_valid(const char *names) 232ciphers_valid(const char *names)
232{ 233{
233 const Cipher *c; 234 const struct sshcipher *c;
234 char *cipher_list, *cp; 235 char *cipher_list, *cp;
235 char *p; 236 char *p;
236 237
237 if (names == NULL || strcmp(names, "") == 0) 238 if (names == NULL || strcmp(names, "") == 0)
238 return 0; 239 return 0;
239 cipher_list = cp = xstrdup(names); 240 if ((cipher_list = cp = strdup(names)) == NULL)
241 return 0;
240 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; 242 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
241 (p = strsep(&cp, CIPHER_SEP))) { 243 (p = strsep(&cp, CIPHER_SEP))) {
242 c = cipher_by_name(p); 244 c = cipher_by_name(p);
243 if (c == NULL || c->number != SSH_CIPHER_SSH2) { 245 if (c == NULL || c->number != SSH_CIPHER_SSH2) {
244 debug("bad cipher %s [%s]", p, names);
245 free(cipher_list); 246 free(cipher_list);
246 return 0; 247 return 0;
247 } 248 }
248 } 249 }
249 debug3("ciphers ok: [%s]", names);
250 free(cipher_list); 250 free(cipher_list);
251 return 1; 251 return 1;
252} 252}
@@ -259,7 +259,7 @@ ciphers_valid(const char *names)
259int 259int
260cipher_number(const char *name) 260cipher_number(const char *name)
261{ 261{
262 const Cipher *c; 262 const struct sshcipher *c;
263 if (name == NULL) 263 if (name == NULL)
264 return -1; 264 return -1;
265 for (c = ciphers; c->name != NULL; c++) 265 for (c = ciphers; c->name != NULL; c++)
@@ -271,31 +271,33 @@ cipher_number(const char *name)
271char * 271char *
272cipher_name(int id) 272cipher_name(int id)
273{ 273{
274 const Cipher *c = cipher_by_number(id); 274 const struct sshcipher *c = cipher_by_number(id);
275 return (c==NULL) ? "<unknown>" : c->name; 275 return (c==NULL) ? "<unknown>" : c->name;
276} 276}
277 277
278void 278const char *
279cipher_init(CipherContext *cc, const Cipher *cipher, 279cipher_warning_message(const struct sshcipher_ctx *cc)
280{
281 if (cc == NULL || cc->cipher == NULL)
282 return NULL;
283 if (cc->cipher->number == SSH_CIPHER_DES)
284 return "use of DES is strongly discouraged due to "
285 "cryptographic weaknesses";
286 return NULL;
287}
288
289int
290cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
280 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, 291 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
281 int do_encrypt) 292 int do_encrypt)
282{ 293{
283#ifdef WITH_OPENSSL 294#ifdef WITH_OPENSSL
284 static int dowarn = 1; 295 int ret = SSH_ERR_INTERNAL_ERROR;
285#ifdef SSH_OLD_EVP
286 EVP_CIPHER *type;
287#else
288 const EVP_CIPHER *type; 296 const EVP_CIPHER *type;
289 int klen; 297 int klen;
290#endif
291 u_char *junk, *discard; 298 u_char *junk, *discard;
292 299
293 if (cipher->number == SSH_CIPHER_DES) { 300 if (cipher->number == SSH_CIPHER_DES) {
294 if (dowarn) {
295 error("Warning: use of DES is strongly discouraged "
296 "due to cryptographic weaknesses");
297 dowarn = 0;
298 }
299 if (keylen > 8) 301 if (keylen > 8)
300 keylen = 8; 302 keylen = 8;
301 } 303 }
@@ -303,71 +305,70 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
303 cc->plaintext = (cipher->number == SSH_CIPHER_NONE); 305 cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
304 cc->encrypt = do_encrypt; 306 cc->encrypt = do_encrypt;
305 307
306 if (keylen < cipher->key_len) 308 if (keylen < cipher->key_len ||
307 fatal("cipher_init: key length %d is insufficient for %s.", 309 (iv != NULL && ivlen < cipher_ivlen(cipher)))
308 keylen, cipher->name); 310 return SSH_ERR_INVALID_ARGUMENT;
309 if (iv != NULL && ivlen < cipher_ivlen(cipher))
310 fatal("cipher_init: iv length %d is insufficient for %s.",
311 ivlen, cipher->name);
312 cc->cipher = cipher;
313 311
312 cc->cipher = cipher;
314 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 313 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
315 chachapoly_init(&cc->cp_ctx, key, keylen); 314 return chachapoly_init(&cc->cp_ctx, key, keylen);
316 return;
317 } 315 }
318#ifndef WITH_OPENSSL 316#ifndef WITH_OPENSSL
319 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { 317 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
320 aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen); 318 aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
321 aesctr_ivsetup(&cc->ac_ctx, iv); 319 aesctr_ivsetup(&cc->ac_ctx, iv);
322 return; 320 return 0;
323 } 321 }
324 if ((cc->cipher->flags & CFLAG_NONE) != 0) 322 if ((cc->cipher->flags & CFLAG_NONE) != 0)
325 return; 323 return 0;
326 fatal("unsupported cipher"); 324 return SSH_ERR_INVALID_ARGUMENT;
327#else 325#else
328 type = (*cipher->evptype)(); 326 type = (*cipher->evptype)();
329 EVP_CIPHER_CTX_init(&cc->evp); 327 EVP_CIPHER_CTX_init(&cc->evp);
330#ifdef SSH_OLD_EVP
331 if (type->key_len > 0 && type->key_len != keylen) {
332 debug("cipher_init: set keylen (%d -> %d)",
333 type->key_len, keylen);
334 type->key_len = keylen;
335 }
336 EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv,
337 (do_encrypt == CIPHER_ENCRYPT));
338#else
339 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, 328 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
340 (do_encrypt == CIPHER_ENCRYPT)) == 0) 329 (do_encrypt == CIPHER_ENCRYPT)) == 0) {
341 fatal("cipher_init: EVP_CipherInit failed for %s", 330 ret = SSH_ERR_LIBCRYPTO_ERROR;
342 cipher->name); 331 goto bad;
332 }
343 if (cipher_authlen(cipher) && 333 if (cipher_authlen(cipher) &&
344 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, 334 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
345 -1, (u_char *)iv)) 335 -1, (u_char *)iv)) {
346 fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", 336 ret = SSH_ERR_LIBCRYPTO_ERROR;
347 cipher->name); 337 goto bad;
338 }
348 klen = EVP_CIPHER_CTX_key_length(&cc->evp); 339 klen = EVP_CIPHER_CTX_key_length(&cc->evp);
349 if (klen > 0 && keylen != (u_int)klen) { 340 if (klen > 0 && keylen != (u_int)klen) {
350 debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); 341 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
351 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) 342 ret = SSH_ERR_LIBCRYPTO_ERROR;
352 fatal("cipher_init: set keylen failed (%d -> %d)", 343 goto bad;
353 klen, keylen); 344 }
345 }
346 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
347 ret = SSH_ERR_LIBCRYPTO_ERROR;
348 goto bad;
354 } 349 }
355 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
356 fatal("cipher_init: EVP_CipherInit: set key failed for %s",
357 cipher->name);
358#endif
359 350
360 if (cipher->discard_len > 0) { 351 if (cipher->discard_len > 0) {
361 junk = xmalloc(cipher->discard_len); 352 if ((junk = malloc(cipher->discard_len)) == NULL ||
362 discard = xmalloc(cipher->discard_len); 353 (discard = malloc(cipher->discard_len)) == NULL) {
363 if (EVP_Cipher(&cc->evp, discard, junk, 354 if (junk != NULL)
364 cipher->discard_len) == 0) 355 free(junk);
365 fatal("evp_crypt: EVP_Cipher failed during discard"); 356 ret = SSH_ERR_ALLOC_FAIL;
357 goto bad;
358 }
359 ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
366 explicit_bzero(discard, cipher->discard_len); 360 explicit_bzero(discard, cipher->discard_len);
367 free(junk); 361 free(junk);
368 free(discard); 362 free(discard);
363 if (ret != 1) {
364 ret = SSH_ERR_LIBCRYPTO_ERROR;
365 bad:
366 EVP_CIPHER_CTX_cleanup(&cc->evp);
367 return ret;
368 }
369 } 369 }
370#endif 370#endif
371 return 0;
371} 372}
372 373
373/* 374/*
@@ -379,16 +380,15 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
379 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. 380 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
380 * This tag is written on encryption and verified on decryption. 381 * This tag is written on encryption and verified on decryption.
381 * Both 'aadlen' and 'authlen' can be set to 0. 382 * Both 'aadlen' and 'authlen' can be set to 0.
382 * cipher_crypt() returns 0 on success and -1 if the decryption integrity
383 * check fails.
384 */ 383 */
385int 384int
386cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, 385cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
387 u_int len, u_int aadlen, u_int authlen) 386 const u_char *src, u_int len, u_int aadlen, u_int authlen)
388{ 387{
389 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 388 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
390 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, 389 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
391 aadlen, authlen, cc->encrypt); 390 len, aadlen, authlen, cc->encrypt);
391 }
392#ifndef WITH_OPENSSL 392#ifndef WITH_OPENSSL
393 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) { 393 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
394 if (aadlen) 394 if (aadlen)
@@ -401,46 +401,43 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
401 memcpy(dest, src, aadlen + len); 401 memcpy(dest, src, aadlen + len);
402 return 0; 402 return 0;
403 } 403 }
404 fatal("unsupported cipher"); 404 return SSH_ERR_INVALID_ARGUMENT;
405#else 405#else
406 if (authlen) { 406 if (authlen) {
407 u_char lastiv[1]; 407 u_char lastiv[1];
408 408
409 if (authlen != cipher_authlen(cc->cipher)) 409 if (authlen != cipher_authlen(cc->cipher))
410 fatal("%s: authlen mismatch %d", __func__, authlen); 410 return SSH_ERR_INVALID_ARGUMENT;
411 /* increment IV */ 411 /* increment IV */
412 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 412 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
413 1, lastiv)) 413 1, lastiv))
414 fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); 414 return SSH_ERR_LIBCRYPTO_ERROR;
415 /* set tag on decyption */ 415 /* set tag on decyption */
416 if (!cc->encrypt && 416 if (!cc->encrypt &&
417 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, 417 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
418 authlen, (u_char *)src + aadlen + len)) 418 authlen, (u_char *)src + aadlen + len))
419 fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); 419 return SSH_ERR_LIBCRYPTO_ERROR;
420 } 420 }
421 if (aadlen) { 421 if (aadlen) {
422 if (authlen && 422 if (authlen &&
423 EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) 423 EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
424 fatal("%s: EVP_Cipher(aad) failed", __func__); 424 return SSH_ERR_LIBCRYPTO_ERROR;
425 memcpy(dest, src, aadlen); 425 memcpy(dest, src, aadlen);
426 } 426 }
427 if (len % cc->cipher->block_size) 427 if (len % cc->cipher->block_size)
428 fatal("%s: bad plaintext length %d", __func__, len); 428 return SSH_ERR_INVALID_ARGUMENT;
429 if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, 429 if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
430 len) < 0) 430 len) < 0)
431 fatal("%s: EVP_Cipher failed", __func__); 431 return SSH_ERR_LIBCRYPTO_ERROR;
432 if (authlen) { 432 if (authlen) {
433 /* compute tag (on encrypt) or verify tag (on decrypt) */ 433 /* compute tag (on encrypt) or verify tag (on decrypt) */
434 if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { 434 if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
435 if (cc->encrypt) 435 return cc->encrypt ?
436 fatal("%s: EVP_Cipher(final) failed", __func__); 436 SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
437 else
438 return -1;
439 }
440 if (cc->encrypt && 437 if (cc->encrypt &&
441 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, 438 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
442 authlen, dest + aadlen + len)) 439 authlen, dest + aadlen + len))
443 fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); 440 return SSH_ERR_LIBCRYPTO_ERROR;
444 } 441 }
445 return 0; 442 return 0;
446#endif 443#endif
@@ -448,61 +445,65 @@ cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src,
448 445
449/* Extract the packet length, including any decryption necessary beforehand */ 446/* Extract the packet length, including any decryption necessary beforehand */
450int 447int
451cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, 448cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
452 const u_char *cp, u_int len) 449 const u_char *cp, u_int len)
453{ 450{
454 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 451 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
455 return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, 452 return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
456 cp, len); 453 cp, len);
457 if (len < 4) 454 if (len < 4)
458 return -1; 455 return SSH_ERR_MESSAGE_INCOMPLETE;
459 *plenp = get_u32(cp); 456 *plenp = get_u32(cp);
460 return 0; 457 return 0;
461} 458}
462 459
463void 460int
464cipher_cleanup(CipherContext *cc) 461cipher_cleanup(struct sshcipher_ctx *cc)
465{ 462{
463 if (cc == NULL || cc->cipher == NULL)
464 return 0;
466 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 465 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
467 explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); 466 explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
468 else if ((cc->cipher->flags & CFLAG_AESCTR) != 0) 467 else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
469 explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx)); 468 explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
470#ifdef WITH_OPENSSL 469#ifdef WITH_OPENSSL
471 else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) 470 else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
472 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); 471 return SSH_ERR_LIBCRYPTO_ERROR;
473#endif 472#endif
473 return 0;
474} 474}
475 475
476/* 476/*
477 * Selects the cipher, and keys if by computing the MD5 checksum of the 477 * Selects the cipher, and keys if by computing the MD5 checksum of the
478 * passphrase and using the resulting 16 bytes as the key. 478 * passphrase and using the resulting 16 bytes as the key.
479 */ 479 */
480 480int
481void 481cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
482cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
483 const char *passphrase, int do_encrypt) 482 const char *passphrase, int do_encrypt)
484{ 483{
485 u_char digest[16]; 484 u_char digest[16];
485 int r = SSH_ERR_INTERNAL_ERROR;
486 486
487 if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), 487 if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
488 digest, sizeof(digest)) < 0) 488 passphrase, strlen(passphrase),
489 fatal("%s: md5 failed", __func__); 489 digest, sizeof(digest))) != 0)
490 490 goto out;
491 cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
492 491
492 r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
493 out:
493 explicit_bzero(digest, sizeof(digest)); 494 explicit_bzero(digest, sizeof(digest));
495 return r;
494} 496}
495 497
496/* 498/*
497 * Exports an IV from the CipherContext required to export the key 499 * Exports an IV from the sshcipher_ctx required to export the key
498 * state back from the unprivileged child to the privileged parent 500 * state back from the unprivileged child to the privileged parent
499 * process. 501 * process.
500 */ 502 */
501
502int 503int
503cipher_get_keyiv_len(const CipherContext *cc) 504cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
504{ 505{
505 const Cipher *c = cc->cipher; 506 const struct sshcipher *c = cc->cipher;
506 int ivlen = 0; 507 int ivlen = 0;
507 508
508 if (c->number == SSH_CIPHER_3DES) 509 if (c->number == SSH_CIPHER_3DES)
@@ -512,25 +513,25 @@ cipher_get_keyiv_len(const CipherContext *cc)
512#ifdef WITH_OPENSSL 513#ifdef WITH_OPENSSL
513 else 514 else
514 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); 515 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
515#endif 516#endif /* WITH_OPENSSL */
516 return (ivlen); 517 return (ivlen);
517} 518}
518 519
519void 520int
520cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) 521cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
521{ 522{
522 const Cipher *c = cc->cipher; 523 const struct sshcipher *c = cc->cipher;
523#ifdef WITH_OPENSSL 524#ifdef WITH_OPENSSL
524 int evplen; 525 int evplen;
525#endif 526#endif
526 527
527 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 528 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
528 if (len != 0) 529 if (len != 0)
529 fatal("%s: wrong iv length %d != %d", __func__, len, 0); 530 return SSH_ERR_INVALID_ARGUMENT;
530 return; 531 return 0;
531 } 532 }
532 if ((cc->cipher->flags & CFLAG_NONE) != 0) 533 if ((cc->cipher->flags & CFLAG_NONE) != 0)
533 return; 534 return 0;
534 535
535 switch (c->number) { 536 switch (c->number) {
536#ifdef WITH_OPENSSL 537#ifdef WITH_OPENSSL
@@ -538,51 +539,42 @@ cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len)
538 case SSH_CIPHER_DES: 539 case SSH_CIPHER_DES:
539 case SSH_CIPHER_BLOWFISH: 540 case SSH_CIPHER_BLOWFISH:
540 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 541 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
541 if (evplen <= 0) 542 if (evplen == 0)
542 return; 543 return 0;
544 else if (evplen < 0)
545 return SSH_ERR_LIBCRYPTO_ERROR;
543 if ((u_int)evplen != len) 546 if ((u_int)evplen != len)
544 fatal("%s: wrong iv length %d != %d", __func__, 547 return SSH_ERR_INVALID_ARGUMENT;
545 evplen, len);
546#ifdef USE_BUILTIN_RIJNDAEL
547 if (c->evptype == evp_rijndael)
548 ssh_rijndael_iv(&cc->evp, 0, iv, len);
549 else
550#endif /* USE_BUILTIN_RIJNDAEL */
551#ifndef OPENSSL_HAVE_EVPCTR
552 if (c->evptype == evp_aes_128_ctr)
553 ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
554 else
555#endif /* OPENSSL_HAVE_EVPCTR */
556 if (cipher_authlen(c)) { 548 if (cipher_authlen(c)) {
557 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 549 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
558 len, iv)) 550 len, iv))
559 fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); 551 return SSH_ERR_LIBCRYPTO_ERROR;
560 } else 552 } else
561 memcpy(iv, cc->evp.iv, len); 553 memcpy(iv, cc->evp.iv, len);
562 break; 554 break;
563#endif /* WITH_OPENSSL */ 555#endif
564#ifdef WITH_SSH1 556#ifdef WITH_SSH1
565 case SSH_CIPHER_3DES: 557 case SSH_CIPHER_3DES:
566 ssh1_3des_iv(&cc->evp, 0, iv, 24); 558 return ssh1_3des_iv(&cc->evp, 0, iv, 24);
567 break; 559#endif
568#endif /* WITH_SSH1 */
569 default: 560 default:
570 fatal("%s: bad cipher %d", __func__, c->number); 561 return SSH_ERR_INVALID_ARGUMENT;
571 } 562 }
563 return 0;
572} 564}
573 565
574void 566int
575cipher_set_keyiv(CipherContext *cc, u_char *iv) 567cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
576{ 568{
577 const Cipher *c = cc->cipher; 569 const struct sshcipher *c = cc->cipher;
578#ifdef WITH_OPENSSL 570#ifdef WITH_OPENSSL
579 int evplen = 0; 571 int evplen = 0;
580#endif 572#endif
581 573
582 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 574 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
583 return; 575 return 0;
584 if ((cc->cipher->flags & CFLAG_NONE) != 0) 576 if ((cc->cipher->flags & CFLAG_NONE) != 0)
585 return; 577 return 0;
586 578
587 switch (c->number) { 579 switch (c->number) {
588#ifdef WITH_OPENSSL 580#ifdef WITH_OPENSSL
@@ -590,42 +582,37 @@ cipher_set_keyiv(CipherContext *cc, u_char *iv)
590 case SSH_CIPHER_DES: 582 case SSH_CIPHER_DES:
591 case SSH_CIPHER_BLOWFISH: 583 case SSH_CIPHER_BLOWFISH:
592 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 584 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
593 if (evplen == 0) 585 if (evplen <= 0)
594 return; 586 return SSH_ERR_LIBCRYPTO_ERROR;
595#ifdef USE_BUILTIN_RIJNDAEL
596 if (c->evptype == evp_rijndael)
597 ssh_rijndael_iv(&cc->evp, 1, iv, evplen);
598 else
599#endif /* USE_BUILTIN_RIJNDAEL */
600#ifndef OPENSSL_HAVE_EVPCTR
601 if (c->evptype == evp_aes_128_ctr)
602 ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
603 else
604#endif /* OPENSSL_HAVE_EVPCTR */
605 if (cipher_authlen(c)) { 587 if (cipher_authlen(c)) {
588 /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
606 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, 589 if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
607 EVP_CTRL_GCM_SET_IV_FIXED, -1, iv)) 590 EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
608 fatal("%s: EVP_CTRL_GCM_SET_IV_FIXED failed", 591 return SSH_ERR_LIBCRYPTO_ERROR;
609 __func__); 592 } else
610 } else 593 memcpy(cc->evp.iv, iv, evplen);
611 memcpy(cc->evp.iv, iv, evplen);
612 break; 594 break;
613#endif /* WITH_OPENSSL */ 595#endif
614#ifdef WITH_SSH1 596#ifdef WITH_SSH1
615 case SSH_CIPHER_3DES: 597 case SSH_CIPHER_3DES:
616 ssh1_3des_iv(&cc->evp, 1, iv, 24); 598 return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24);
617 break; 599#endif
618#endif /* WITH_SSH1 */
619 default: 600 default:
620 fatal("%s: bad cipher %d", __func__, c->number); 601 return SSH_ERR_INVALID_ARGUMENT;
621 } 602 }
603 return 0;
622} 604}
623 605
606#ifdef WITH_OPENSSL
607#define EVP_X_STATE(evp) (evp).cipher_data
608#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
609#endif
610
624int 611int
625cipher_get_keycontext(const CipherContext *cc, u_char *dat) 612cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
626{ 613{
627#ifdef WITH_OPENSSL 614#ifdef WITH_OPENSSL
628 const Cipher *c = cc->cipher; 615 const struct sshcipher *c = cc->cipher;
629 int plen = 0; 616 int plen = 0;
630 617
631 if (c->evptype == EVP_rc4) { 618 if (c->evptype == EVP_rc4) {
@@ -636,15 +623,15 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
636 } 623 }
637 return (plen); 624 return (plen);
638#else 625#else
639 return (0); 626 return 0;
640#endif 627#endif
641} 628}
642 629
643void 630void
644cipher_set_keycontext(CipherContext *cc, u_char *dat) 631cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
645{ 632{
646#ifdef WITH_OPENSSL 633#ifdef WITH_OPENSSL
647 const Cipher *c = cc->cipher; 634 const struct sshcipher *c = cc->cipher;
648 int plen; 635 int plen;
649 636
650 if (c->evptype == EVP_rc4) { 637 if (c->evptype == EVP_rc4) {