[PROTOCOL authfile.c cipher.c cipher.h kex.c kex.h monitor_wrap.c]
     [myproposal.h packet.c ssh_config.5 sshd_config.5]
     support AES-GCM as defined in RFC 5647 (but with simpler KEX handling)
     ok and feedback djm@
This commit is contained in:
Damien Miller 2013-01-09 16:12:19 +11:00
parent aa7ad3039c
commit 1d75abfe23
12 changed files with 181 additions and 81 deletions

View File

@ -32,6 +32,11 @@
sftp-server.8: add argument name to -d sftp-server.8: add argument name to -d
sftp-server.c: add -d to usage() sftp-server.c: add -d to usage()
ok djm ok djm
- markus@cvs.openbsd.org 2013/01/08 18:49:04
[PROTOCOL authfile.c cipher.c cipher.h kex.c kex.h monitor_wrap.c]
[myproposal.h packet.c ssh_config.5 sshd_config.5]
support AES-GCM as defined in RFC 5647 (but with simpler KEX handling)
ok and feedback djm@
20121217 20121217
- (dtucker) [Makefile.in] Add some scaffolding so that the new regress - (dtucker) [Makefile.in] Add some scaffolding so that the new regress

View File

@ -79,6 +79,18 @@ contains:
byte[n1] payload; n1 = packet_length - padding_length - 1 byte[n1] payload; n1 = packet_length - padding_length - 1
byte[n2] random padding; n2 = padding_length byte[n2] random padding; n2 = padding_length
1.6 transport: AES-GCM
OpenSSH supports the AES-GCM algorithm as specified in RFC 5647.
Because of problems with the specification of the key exchange
the behaviour of OpenSSH differs from the RFC as follows:
AES-GCM is only negotiated as the cipher algorithms
"aes128-gcm@openssh.com" or "aes256-gcm@openssh.com" and never as
an MAC algorithm. Additionally, if AES-GCM is selected as the cipher
the exchanged MAC algorithms are ignored and there doesn't have to be
a matching MAC.
2. Connection protocol changes 2. Connection protocol changes
2.1. connection: Channel write close extension "eow@openssh.com" 2.1. connection: Channel write close extension "eow@openssh.com"
@ -319,4 +331,4 @@ link(oldpath, newpath) and will respond with a SSH_FXP_STATUS message.
This extension is advertised in the SSH_FXP_VERSION hello with version This extension is advertised in the SSH_FXP_VERSION hello with version
"1". "1".
$OpenBSD: PROTOCOL,v 1.19 2013/01/03 12:49:01 djm Exp $ $OpenBSD: PROTOCOL,v 1.20 2013/01/08 18:49:04 markus Exp $

View File

@ -1,4 +1,4 @@
/* $OpenBSD: authfile.c,v 1.94 2012/12/11 22:31:18 markus Exp $ */ /* $OpenBSD: authfile.c,v 1.95 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -150,7 +150,7 @@ key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
cipher_set_key_string(&ciphercontext, cipher, passphrase, cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_ENCRYPT); CIPHER_ENCRYPT);
cipher_crypt(&ciphercontext, cp, cipher_crypt(&ciphercontext, cp,
buffer_ptr(&buffer), buffer_len(&buffer), 0); buffer_ptr(&buffer), buffer_len(&buffer), 0, 0);
cipher_cleanup(&ciphercontext); cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext)); memset(&ciphercontext, 0, sizeof(ciphercontext));
@ -474,7 +474,7 @@ key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp)
cipher_set_key_string(&ciphercontext, cipher, passphrase, cipher_set_key_string(&ciphercontext, cipher, passphrase,
CIPHER_DECRYPT); CIPHER_DECRYPT);
cipher_crypt(&ciphercontext, cp, cipher_crypt(&ciphercontext, cp,
buffer_ptr(&copy), buffer_len(&copy), 0); buffer_ptr(&copy), buffer_len(&copy), 0, 0);
cipher_cleanup(&ciphercontext); cipher_cleanup(&ciphercontext);
memset(&ciphercontext, 0, sizeof(ciphercontext)); memset(&ciphercontext, 0, sizeof(ciphercontext));
buffer_free(&copy); buffer_free(&copy);

109
cipher.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.c,v 1.84 2012/12/12 16:46:10 naddy Exp $ */ /* $OpenBSD: cipher.c,v 1.85 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -71,29 +71,38 @@ struct Cipher {
u_int cbc_mode; u_int cbc_mode;
const EVP_CIPHER *(*evptype)(void); const EVP_CIPHER *(*evptype)(void);
} ciphers[] = { } ciphers[] = {
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 1, evp_ssh1_bf },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_bf_cbc },
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, EVP_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, EVP_aes_192_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, EVP_aes_256_ctr },
#ifdef USE_CIPHER_ACSS
{ "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, 0, 0, EVP_acss },
#endif
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL } { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, NULL }
{ "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
{ "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
{ "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
{ "blowfish-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
{ "cast128-cbc",
SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_cast5_cbc },
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 0, EVP_rc4 },
{ "arcfour128", SSH_CIPHER_SSH2, 8, 16, 0, 0, 1536, 0, EVP_rc4 },
{ "arcfour256", SSH_CIPHER_SSH2, 8, 32, 0, 0, 1536, 0, EVP_rc4 },
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 1, EVP_aes_128_cbc },
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 1, EVP_aes_192_cbc },
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "rijndael-cbc@lysator.liu.se",
SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 1, EVP_aes_256_cbc },
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
{ "aes128-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
{ "aes256-gcm@openssh.com",
SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
#ifdef USE_CIPHER_ACSS
{ "acss@openssh.org",
SSH_CIPHER_SSH2, 16, 5, 0, 0, 0, 0, EVP_acss },
#endif
{ NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
}; };
/*--*/ /*--*/
@ -110,6 +119,18 @@ cipher_keylen(const Cipher *c)
return (c->key_len); return (c->key_len);
} }
u_int
cipher_authlen(const Cipher *c)
{
return (c->auth_len);
}
u_int
cipher_ivlen(const Cipher *c)
{
return (c->iv_len ? c->iv_len : c->block_size);
}
u_int u_int
cipher_get_number(const Cipher *c) cipher_get_number(const Cipher *c)
{ {
@ -229,11 +250,12 @@ cipher_init(CipherContext *cc, Cipher *cipher,
keylen = 8; keylen = 8;
} }
cc->plaintext = (cipher->number == SSH_CIPHER_NONE); cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
cc->encrypt = do_encrypt;
if (keylen < cipher->key_len) if (keylen < cipher->key_len)
fatal("cipher_init: key length %d is insufficient for %s.", fatal("cipher_init: key length %d is insufficient for %s.",
keylen, cipher->name); keylen, cipher->name);
if (iv != NULL && ivlen < cipher->block_size) if (iv != NULL && ivlen < cipher_ivlen(cipher))
fatal("cipher_init: iv length %d is insufficient for %s.", fatal("cipher_init: iv length %d is insufficient for %s.",
ivlen, cipher->name); ivlen, cipher->name);
cc->cipher = cipher; cc->cipher = cipher;
@ -254,6 +276,11 @@ cipher_init(CipherContext *cc, Cipher *cipher,
(do_encrypt == CIPHER_ENCRYPT)) == 0) (do_encrypt == CIPHER_ENCRYPT)) == 0)
fatal("cipher_init: EVP_CipherInit failed for %s", fatal("cipher_init: EVP_CipherInit failed for %s",
cipher->name); cipher->name);
if (cipher_authlen(cipher) &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
-1, (u_char *)iv))
fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s",
cipher->name);
klen = EVP_CIPHER_CTX_key_length(&cc->evp); klen = EVP_CIPHER_CTX_key_length(&cc->evp);
if (klen > 0 && keylen != (u_int)klen) { if (klen > 0 && keylen != (u_int)klen) {
debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); debug2("cipher_init: set keylen (%d -> %d)", klen, keylen);
@ -284,19 +311,49 @@ cipher_init(CipherContext *cc, Cipher *cipher,
* Theses bytes are treated as additional authenticated data for * Theses bytes are treated as additional authenticated data for
* authenticated encryption modes. * authenticated encryption modes.
* En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'. * En/Decrypt 'len' bytes at offset 'aadlen' from 'src' to 'dest'.
* Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
* This tag is written on encryption and verified on decryption.
* Both 'aadlen' and 'authlen' can be set to 0. * Both 'aadlen' and 'authlen' can be set to 0.
*/ */
void void
cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src, cipher_crypt(CipherContext *cc, u_char *dest, const u_char *src,
u_int len, u_int aadlen) u_int len, u_int aadlen, u_int authlen)
{ {
if (aadlen) if (authlen) {
u_char lastiv[1];
if (authlen != cipher_authlen(cc->cipher))
fatal("%s: authlen mismatch %d", __func__, authlen);
/* increment IV */
if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
1, lastiv))
fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__);
/* set tag on decyption */
if (!cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
authlen, (u_char *)src + aadlen + len))
fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__);
}
if (aadlen) {
if (authlen &&
EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
fatal("%s: EVP_Cipher(aad) failed", __func__);
memcpy(dest, src, aadlen); memcpy(dest, src, aadlen);
}
if (len % cc->cipher->block_size) if (len % cc->cipher->block_size)
fatal("%s: bad plaintext length %d", __func__, len); fatal("%s: bad plaintext length %d", __func__, len);
if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
len) < 0) len) < 0)
fatal("%s: EVP_Cipher failed", __func__); fatal("%s: EVP_Cipher failed", __func__);
if (authlen) {
/* compute tag (on encrypt) or verify tag (on decrypt) */
if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
fatal("%s: EVP_Cipher(finish) failed", __func__);
if (cc->encrypt &&
!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
authlen, dest + aadlen + len))
fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__);
}
} }
void void

View File

@ -1,4 +1,4 @@
/* $OpenBSD: cipher.h,v 1.38 2012/12/11 22:31:18 markus Exp $ */ /* $OpenBSD: cipher.h,v 1.39 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
@ -64,6 +64,7 @@ typedef struct CipherContext CipherContext;
struct Cipher; struct Cipher;
struct CipherContext { struct CipherContext {
int plaintext; int plaintext;
int encrypt;
EVP_CIPHER_CTX evp; EVP_CIPHER_CTX evp;
Cipher *cipher; Cipher *cipher;
}; };
@ -76,11 +77,14 @@ char *cipher_name(int);
int ciphers_valid(const char *); int ciphers_valid(const char *);
void cipher_init(CipherContext *, Cipher *, const u_char *, u_int, void cipher_init(CipherContext *, Cipher *, const u_char *, u_int,
const u_char *, u_int, int); const u_char *, u_int, int);
void cipher_crypt(CipherContext *, u_char *, const u_char *, u_int, u_int); void cipher_crypt(CipherContext *, u_char *, const u_char *,
u_int, u_int, u_int);
void cipher_cleanup(CipherContext *); void cipher_cleanup(CipherContext *);
void cipher_set_key_string(CipherContext *, Cipher *, const char *, int); void cipher_set_key_string(CipherContext *, Cipher *, const char *, int);
u_int cipher_blocksize(const Cipher *); u_int cipher_blocksize(const Cipher *);
u_int cipher_keylen(const Cipher *); u_int cipher_keylen(const Cipher *);
u_int cipher_authlen(const Cipher *);
u_int cipher_ivlen(const Cipher *);
u_int cipher_is_cbc(const Cipher *); u_int cipher_is_cbc(const Cipher *);
u_int cipher_get_number(const Cipher *); u_int cipher_get_number(const Cipher *);

16
kex.c
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.c,v 1.87 2012/08/17 01:22:56 djm Exp $ */ /* $OpenBSD: kex.c,v 1.88 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
* *
@ -304,6 +304,7 @@ choose_enc(Enc *enc, char *client, char *server)
enc->name = name; enc->name = name;
enc->enabled = 0; enc->enabled = 0;
enc->iv = NULL; enc->iv = NULL;
enc->iv_len = cipher_ivlen(enc->cipher);
enc->key = NULL; enc->key = NULL;
enc->key_len = cipher_keylen(enc->cipher); enc->key_len = cipher_keylen(enc->cipher);
enc->block_size = cipher_blocksize(enc->cipher); enc->block_size = cipher_blocksize(enc->cipher);
@ -415,7 +416,7 @@ kex_choose_conf(Kex *kex)
char **my, **peer; char **my, **peer;
char **cprop, **sprop; char **cprop, **sprop;
int nenc, nmac, ncomp; int nenc, nmac, ncomp;
u_int mode, ctos, need; u_int mode, ctos, need, authlen;
int first_kex_follows, type; int first_kex_follows, type;
my = kex_buf2prop(&kex->my, NULL); my = kex_buf2prop(&kex->my, NULL);
@ -448,13 +449,16 @@ kex_choose_conf(Kex *kex)
nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC; nenc = ctos ? PROPOSAL_ENC_ALGS_CTOS : PROPOSAL_ENC_ALGS_STOC;
nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC; nmac = ctos ? PROPOSAL_MAC_ALGS_CTOS : PROPOSAL_MAC_ALGS_STOC;
ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC; ncomp = ctos ? PROPOSAL_COMP_ALGS_CTOS : PROPOSAL_COMP_ALGS_STOC;
choose_enc (&newkeys->enc, cprop[nenc], sprop[nenc]); choose_enc(&newkeys->enc, cprop[nenc], sprop[nenc]);
choose_mac (&newkeys->mac, cprop[nmac], sprop[nmac]); /* ignore mac for authenticated encryption */
authlen = cipher_authlen(newkeys->enc.cipher);
if (authlen == 0)
choose_mac(&newkeys->mac, cprop[nmac], sprop[nmac]);
choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]); choose_comp(&newkeys->comp, cprop[ncomp], sprop[ncomp]);
debug("kex: %s %s %s %s", debug("kex: %s %s %s %s",
ctos ? "client->server" : "server->client", ctos ? "client->server" : "server->client",
newkeys->enc.name, newkeys->enc.name,
newkeys->mac.name, authlen == 0 ? newkeys->mac.name : "<implicit>",
newkeys->comp.name); newkeys->comp.name);
} }
choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]); choose_kex(kex, cprop[PROPOSAL_KEX_ALGS], sprop[PROPOSAL_KEX_ALGS]);
@ -467,6 +471,8 @@ kex_choose_conf(Kex *kex)
need = newkeys->enc.key_len; need = newkeys->enc.key_len;
if (need < newkeys->enc.block_size) if (need < newkeys->enc.block_size)
need = newkeys->enc.block_size; need = newkeys->enc.block_size;
if (need < newkeys->enc.iv_len)
need = newkeys->enc.iv_len;
if (need < newkeys->mac.key_len) if (need < newkeys->mac.key_len)
need = newkeys->mac.key_len; need = newkeys->mac.key_len;
} }

3
kex.h
View File

@ -1,4 +1,4 @@
/* $OpenBSD: kex.h,v 1.53 2012/12/11 22:31:18 markus Exp $ */ /* $OpenBSD: kex.h,v 1.54 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@ -89,6 +89,7 @@ struct Enc {
Cipher *cipher; Cipher *cipher;
int enabled; int enabled;
u_int key_len; u_int key_len;
u_int iv_len;
u_int block_size; u_int block_size;
u_char *key; u_char *key;
u_char *iv; u_char *iv;

View File

@ -1,4 +1,4 @@
/* $OpenBSD: monitor_wrap.c,v 1.74 2012/10/01 13:59:51 naddy Exp $ */ /* $OpenBSD: monitor_wrap.c,v 1.75 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Copyright 2002 Niels Provos <provos@citi.umich.edu> * Copyright 2002 Niels Provos <provos@citi.umich.edu>
* Copyright 2002 Markus Friedl <markus@openbsd.org> * Copyright 2002 Markus Friedl <markus@openbsd.org>
@ -491,16 +491,14 @@ mm_newkeys_from_blob(u_char *blob, int blen)
enc->enabled = buffer_get_int(&b); enc->enabled = buffer_get_int(&b);
enc->block_size = buffer_get_int(&b); enc->block_size = buffer_get_int(&b);
enc->key = buffer_get_string(&b, &enc->key_len); enc->key = buffer_get_string(&b, &enc->key_len);
enc->iv = buffer_get_string(&b, &len); enc->iv = buffer_get_string(&b, &enc->iv_len);
if (len != enc->block_size)
fatal("%s: bad ivlen: expected %u != %u", __func__,
enc->block_size, len);
if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher) if (enc->name == NULL || cipher_by_name(enc->name) != enc->cipher)
fatal("%s: bad cipher name %s or pointer %p", __func__, fatal("%s: bad cipher name %s or pointer %p", __func__,
enc->name, enc->cipher); enc->name, enc->cipher);
/* Mac structure */ /* Mac structure */
if (cipher_authlen(enc->cipher) == 0) {
mac->name = buffer_get_string(&b, NULL); mac->name = buffer_get_string(&b, NULL);
if (mac->name == NULL || mac_setup(mac, mac->name) == -1) if (mac->name == NULL || mac_setup(mac, mac->name) == -1)
fatal("%s: can not setup mac %s", __func__, mac->name); fatal("%s: can not setup mac %s", __func__, mac->name);
@ -510,6 +508,7 @@ mm_newkeys_from_blob(u_char *blob, int blen)
fatal("%s: bad mac key length: %u > %d", __func__, len, fatal("%s: bad mac key length: %u > %d", __func__, len,
mac->key_len); mac->key_len);
mac->key_len = len; mac->key_len = len;
}
/* Comp structure */ /* Comp structure */
comp->type = buffer_get_int(&b); comp->type = buffer_get_int(&b);
@ -551,13 +550,15 @@ mm_newkeys_to_blob(int mode, u_char **blobp, u_int *lenp)
buffer_put_int(&b, enc->enabled); buffer_put_int(&b, enc->enabled);
buffer_put_int(&b, enc->block_size); buffer_put_int(&b, enc->block_size);
buffer_put_string(&b, enc->key, enc->key_len); buffer_put_string(&b, enc->key, enc->key_len);
packet_get_keyiv(mode, enc->iv, enc->block_size); packet_get_keyiv(mode, enc->iv, enc->iv_len);
buffer_put_string(&b, enc->iv, enc->block_size); buffer_put_string(&b, enc->iv, enc->iv_len);
/* Mac structure */ /* Mac structure */
if (cipher_authlen(enc->cipher) == 0) {
buffer_put_cstring(&b, mac->name); buffer_put_cstring(&b, mac->name);
buffer_put_int(&b, mac->enabled); buffer_put_int(&b, mac->enabled);
buffer_put_string(&b, mac->key, mac->key_len); buffer_put_string(&b, mac->key, mac->key_len);
}
/* Comp structure */ /* Comp structure */
buffer_put_int(&b, comp->type); buffer_put_int(&b, comp->type);

View File

@ -1,4 +1,4 @@
/* $OpenBSD: myproposal.h,v 1.31 2012/12/11 22:31:18 markus Exp $ */ /* $OpenBSD: myproposal.h,v 1.32 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Copyright (c) 2000 Markus Friedl. All rights reserved. * Copyright (c) 2000 Markus Friedl. All rights reserved.
@ -73,6 +73,7 @@
#define KEX_DEFAULT_ENCRYPT \ #define KEX_DEFAULT_ENCRYPT \
"aes128-ctr,aes192-ctr,aes256-ctr," \ "aes128-ctr,aes192-ctr,aes256-ctr," \
"arcfour256,arcfour128," \ "arcfour256,arcfour128," \
"aes128-gcm@openssh.com,aes256-gcm@openssh.com," \
"aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
"aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
#ifdef HAVE_EVP_SHA256 #ifdef HAVE_EVP_SHA256

View File

@ -1,4 +1,4 @@
/* $OpenBSD: packet.c,v 1.179 2012/12/12 16:45:52 markus Exp $ */ /* $OpenBSD: packet.c,v 1.180 2013/01/08 18:49:04 markus Exp $ */
/* /*
* Author: Tatu Ylonen <ylo@cs.hut.fi> * Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@ -709,7 +709,7 @@ packet_send1(void)
buffer_len(&active_state->outgoing_packet)); buffer_len(&active_state->outgoing_packet));
cipher_crypt(&active_state->send_context, cp, cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet), buffer_ptr(&active_state->outgoing_packet),
buffer_len(&active_state->outgoing_packet), 0); buffer_len(&active_state->outgoing_packet), 0, 0);
#ifdef PACKET_DEBUG #ifdef PACKET_DEBUG
fprintf(stderr, "encrypted: "); fprintf(stderr, "encrypted: ");
@ -757,7 +757,7 @@ set_newkeys(int mode)
mac = &active_state->newkeys[mode]->mac; mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp; comp = &active_state->newkeys[mode]->comp;
mac_clear(mac); mac_clear(mac);
memset(enc->iv, 0, enc->block_size); memset(enc->iv, 0, enc->iv_len);
memset(enc->key, 0, enc->key_len); memset(enc->key, 0, enc->key_len);
memset(mac->key, 0, mac->key_len); memset(mac->key, 0, mac->key_len);
xfree(enc->name); xfree(enc->name);
@ -774,11 +774,11 @@ set_newkeys(int mode)
enc = &active_state->newkeys[mode]->enc; enc = &active_state->newkeys[mode]->enc;
mac = &active_state->newkeys[mode]->mac; mac = &active_state->newkeys[mode]->mac;
comp = &active_state->newkeys[mode]->comp; comp = &active_state->newkeys[mode]->comp;
if (mac_init(mac) == 0) if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0)
mac->enabled = 1; mac->enabled = 1;
DBG(debug("cipher_init_context: %d", mode)); DBG(debug("cipher_init_context: %d", mode));
cipher_init(cc, enc->cipher, enc->key, enc->key_len, cipher_init(cc, enc->cipher, enc->key, enc->key_len,
enc->iv, enc->block_size, crypt_type); enc->iv, enc->iv_len, crypt_type);
/* Deleting the keys does not gain extra security */ /* Deleting the keys does not gain extra security */
/* memset(enc->iv, 0, enc->block_size); /* memset(enc->iv, 0, enc->block_size);
memset(enc->key, 0, enc->key_len); memset(enc->key, 0, enc->key_len);
@ -846,7 +846,7 @@ packet_send2_wrapped(void)
{ {
u_char type, *cp, *macbuf = NULL; u_char type, *cp, *macbuf = NULL;
u_char padlen, pad = 0; u_char padlen, pad = 0;
u_int i, len, aadlen = 0; u_int i, len, authlen = 0, aadlen = 0;
u_int32_t rnd = 0; u_int32_t rnd = 0;
Enc *enc = NULL; Enc *enc = NULL;
Mac *mac = NULL; Mac *mac = NULL;
@ -857,9 +857,12 @@ packet_send2_wrapped(void)
enc = &active_state->newkeys[MODE_OUT]->enc; enc = &active_state->newkeys[MODE_OUT]->enc;
mac = &active_state->newkeys[MODE_OUT]->mac; mac = &active_state->newkeys[MODE_OUT]->mac;
comp = &active_state->newkeys[MODE_OUT]->comp; comp = &active_state->newkeys[MODE_OUT]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
} }
block_size = enc ? enc->block_size : 8; block_size = enc ? enc->block_size : 8;
aadlen = mac && mac->enabled && mac->etm ? 4 : 0; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
cp = buffer_ptr(&active_state->outgoing_packet); cp = buffer_ptr(&active_state->outgoing_packet);
type = cp[5]; type = cp[5];
@ -936,10 +939,10 @@ packet_send2_wrapped(void)
DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr)); DBG(debug("done calc MAC out #%d", active_state->p_send.seqnr));
} }
/* encrypt packet and append to output buffer. */ /* encrypt packet and append to output buffer. */
cp = buffer_append_space(&active_state->output, len); cp = buffer_append_space(&active_state->output, len + authlen);
cipher_crypt(&active_state->send_context, cp, cipher_crypt(&active_state->send_context, cp,
buffer_ptr(&active_state->outgoing_packet), buffer_ptr(&active_state->outgoing_packet),
len - aadlen, aadlen); len - aadlen, aadlen, authlen);
/* append unencrypted MAC */ /* append unencrypted MAC */
if (mac && mac->enabled) { if (mac && mac->enabled) {
if (mac->etm) { if (mac->etm) {
@ -1199,7 +1202,7 @@ packet_read_poll1(void)
buffer_clear(&active_state->incoming_packet); buffer_clear(&active_state->incoming_packet);
cp = buffer_append_space(&active_state->incoming_packet, padded_len); cp = buffer_append_space(&active_state->incoming_packet, padded_len);
cipher_crypt(&active_state->receive_context, cp, cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), padded_len, 0); buffer_ptr(&active_state->input), padded_len, 0, 0);
buffer_consume(&active_state->input, padded_len); buffer_consume(&active_state->input, padded_len);
@ -1248,7 +1251,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
{ {
u_int padlen, need; u_int padlen, need;
u_char *macbuf = NULL, *cp, type; u_char *macbuf = NULL, *cp, type;
u_int maclen, aadlen = 0, block_size; u_int maclen, authlen = 0, aadlen = 0, block_size;
Enc *enc = NULL; Enc *enc = NULL;
Mac *mac = NULL; Mac *mac = NULL;
Comp *comp = NULL; Comp *comp = NULL;
@ -1260,10 +1263,13 @@ packet_read_poll2(u_int32_t *seqnr_p)
enc = &active_state->newkeys[MODE_IN]->enc; enc = &active_state->newkeys[MODE_IN]->enc;
mac = &active_state->newkeys[MODE_IN]->mac; mac = &active_state->newkeys[MODE_IN]->mac;
comp = &active_state->newkeys[MODE_IN]->comp; comp = &active_state->newkeys[MODE_IN]->comp;
/* disable mac for authenticated encryption */
if ((authlen = cipher_authlen(enc->cipher)) != 0)
mac = NULL;
} }
maclen = mac && mac->enabled ? mac->mac_len : 0; maclen = mac && mac->enabled ? mac->mac_len : 0;
block_size = enc ? enc->block_size : 8; block_size = enc ? enc->block_size : 8;
aadlen = mac && mac->enabled && mac->etm ? 4 : 0; aadlen = (mac && mac->enabled && mac->etm) || authlen ? 4 : 0;
if (aadlen && active_state->packlen == 0) { if (aadlen && active_state->packlen == 0) {
if (buffer_len(&active_state->input) < 4) if (buffer_len(&active_state->input) < 4)
@ -1290,7 +1296,7 @@ packet_read_poll2(u_int32_t *seqnr_p)
cp = buffer_append_space(&active_state->incoming_packet, cp = buffer_append_space(&active_state->incoming_packet,
block_size); block_size);
cipher_crypt(&active_state->receive_context, cp, cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), block_size, 0); buffer_ptr(&active_state->input), block_size, 0, 0);
cp = buffer_ptr(&active_state->incoming_packet); cp = buffer_ptr(&active_state->incoming_packet);
active_state->packlen = get_u32(cp); active_state->packlen = get_u32(cp);
if (active_state->packlen < 1 + 4 || if (active_state->packlen < 1 + 4 ||
@ -1316,8 +1322,8 @@ packet_read_poll2(u_int32_t *seqnr_p)
*/ */
need = 4 + active_state->packlen - block_size; need = 4 + active_state->packlen - block_size;
} }
DBG(debug("partial packet: block %d, need %d, maclen %d, aadlen %d", DBG(debug("partial packet: block %d, need %d, maclen %d, authlen %d,"
block_size, need, maclen, aadlen)); " aadlen %d", block_size, need, maclen, authlen, aadlen));
if (need % block_size != 0) { if (need % block_size != 0) {
logit("padding error: need %d block %d mod %d", logit("padding error: need %d block %d mod %d",
need, block_size, need % block_size); need, block_size, need % block_size);
@ -1329,10 +1335,11 @@ packet_read_poll2(u_int32_t *seqnr_p)
* check if the entire packet has been received and * check if the entire packet has been received and
* decrypt into incoming_packet: * decrypt into incoming_packet:
* 'aadlen' bytes are unencrypted, but authenticated. * 'aadlen' bytes are unencrypted, but authenticated.
* 'need' bytes are encrypted, followed by * 'need' bytes are encrypted, followed by either
* 'authlen' bytes of authentication tag or
* 'maclen' bytes of message authentication code. * 'maclen' bytes of message authentication code.
*/ */
if (buffer_len(&active_state->input) < aadlen + need + maclen) if (buffer_len(&active_state->input) < aadlen + need + authlen + maclen)
return SSH_MSG_NONE; return SSH_MSG_NONE;
#ifdef PACKET_DEBUG #ifdef PACKET_DEBUG
fprintf(stderr, "read_poll enc/full: "); fprintf(stderr, "read_poll enc/full: ");
@ -1344,8 +1351,8 @@ packet_read_poll2(u_int32_t *seqnr_p)
buffer_ptr(&active_state->input), aadlen + need); buffer_ptr(&active_state->input), aadlen + need);
cp = buffer_append_space(&active_state->incoming_packet, aadlen + need); cp = buffer_append_space(&active_state->incoming_packet, aadlen + need);
cipher_crypt(&active_state->receive_context, cp, cipher_crypt(&active_state->receive_context, cp,
buffer_ptr(&active_state->input), need, aadlen); buffer_ptr(&active_state->input), need, aadlen, authlen);
buffer_consume(&active_state->input, aadlen + need); buffer_consume(&active_state->input, aadlen + need + authlen);
/* /*
* compute MAC over seqnr and packet, * compute MAC over seqnr and packet,
* increment sequence number for incoming packet * increment sequence number for incoming packet

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: ssh_config.5,v 1.160 2012/12/11 22:31:18 markus Exp $ .\" $OpenBSD: ssh_config.5,v 1.161 2013/01/08 18:49:04 markus Exp $
.Dd $Mdocdate: December 11 2012 $ .Dd $Mdocdate: January 8 2013 $
.Dt SSH_CONFIG 5 .Dt SSH_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -204,6 +204,8 @@ The supported ciphers are
.Dq aes128-ctr , .Dq aes128-ctr ,
.Dq aes192-ctr , .Dq aes192-ctr ,
.Dq aes256-ctr , .Dq aes256-ctr ,
.Dq aes128-gcm@openssh.com ,
.Dq aes256-gcm@openssh.com ,
.Dq arcfour128 , .Dq arcfour128 ,
.Dq arcfour256 , .Dq arcfour256 ,
.Dq arcfour , .Dq arcfour ,
@ -213,6 +215,7 @@ and
The default is: The default is:
.Bd -literal -offset 3n .Bd -literal -offset 3n
aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
aes128-gcm@openssh.com,aes256-gcm@openssh.com,
aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
aes256-cbc,arcfour aes256-cbc,arcfour
.Ed .Ed

View File

@ -33,8 +33,8 @@
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF .\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. .\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\" .\"
.\" $OpenBSD: sshd_config.5,v 1.152 2012/12/11 22:31:18 markus Exp $ .\" $OpenBSD: sshd_config.5,v 1.153 2013/01/08 18:49:04 markus Exp $
.Dd $Mdocdate: December 11 2012 $ .Dd $Mdocdate: January 8 2013 $
.Dt SSHD_CONFIG 5 .Dt SSHD_CONFIG 5
.Os .Os
.Sh NAME .Sh NAME
@ -336,6 +336,8 @@ The supported ciphers are
.Dq aes128-ctr , .Dq aes128-ctr ,
.Dq aes192-ctr , .Dq aes192-ctr ,
.Dq aes256-ctr , .Dq aes256-ctr ,
.Dq aes128-gcm@openssh.com ,
.Dq aes256-gcm@openssh.com ,
.Dq arcfour128 , .Dq arcfour128 ,
.Dq arcfour256 , .Dq arcfour256 ,
.Dq arcfour , .Dq arcfour ,
@ -345,6 +347,7 @@ and
The default is: The default is:
.Bd -literal -offset 3n .Bd -literal -offset 3n
aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128,
aes128-gcm@openssh.com,aes256-gcm@openssh.com,
aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
aes256-cbc,arcfour aes256-cbc,arcfour
.Ed .Ed