Support AES-Counter ciphers.

This commit is contained in:
Simon Josefsson 2009-11-16 16:04:00 +01:00
parent b78f854d8b
commit ebbd7c879b
7 changed files with 178 additions and 8 deletions

View File

@ -1,6 +1,7 @@
/* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2004-2007 Sara Golemon <sarag@libssh2.org>
* Copyright (c) 2006-2007 The Written Word, Inc. * Copyright (c) 2006-2007 The Written Word, Inc.
* Copyright (c) 2009 Daniel Stenberg * Copyright (c) 2009 Daniel Stenberg
* Copyright (C) 2008, 2009 Simon Josefsson
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,

4
NEWS
View File

@ -7,6 +7,10 @@ Version 1.2.2 (unreleased)
<http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>. <http://thread.gmane.org/gmane.network.ssh.libssh2.devel/2530>.
By Simon Josefsson. By Simon Josefsson.
o Support for the "aes128-ctr", "aes192-ctr", "aes256-ctr" ciphers
as per RFC 4344 for libgcrypt and OpenSSL. They are now the
preferred ciphers. By Simon Josefsson.
o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt o Support for the "arcfour128" cipher as per RFC 4345 for libgcrypt
and OpenSSL. It is preferred over the normal "arcfour" cipher and OpenSSL. It is preferred over the normal "arcfour" cipher
which is somewhat broken. By Simon Josefsson. which is somewhat broken. By Simon Josefsson.

View File

@ -1,5 +1,5 @@
/* Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org> /* Copyright (c) 2009 Simon Josefsson <simon@josefsson.org>
* Copyright (c) 2009 Simon Josefsson <simon@josefsson.org> * Copyright (c) 2004-2007, Sara Golemon <sarag@libssh2.org>
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@ -115,6 +115,44 @@ crypt_dtor(LIBSSH2_SESSION * session, void **abstract)
return 0; return 0;
} }
#if LIBSSH2_AES_CTR
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_ctr = {
"aes128-ctr",
16, /* blocksize */
16, /* initial value length */
16, /* secret length -- 16*8 == 128bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes128ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes192_ctr = {
"aes192-ctr",
16, /* blocksize */
16, /* initial value length */
24, /* secret length -- 24*8 == 192bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes192ctr
};
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes256_ctr = {
"aes256-ctr",
16, /* blocksize */
16, /* initial value length */
32, /* secret length -- 32*8 == 256bit */
0, /* flags */
&crypt_init,
&crypt_encrypt,
&crypt_dtor,
_libssh2_cipher_aes256ctr
};
#endif
#if LIBSSH2_AES #if LIBSSH2_AES
static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = { static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_aes128_cbc = {
"aes128-cbc", "aes128-cbc",
@ -258,6 +296,11 @@ static const LIBSSH2_CRYPT_METHOD libssh2_crypt_method_3des_cbc = {
#endif #endif
static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = { static const LIBSSH2_CRYPT_METHOD *_libssh2_crypt_methods[] = {
#if LIBSSH2_AES_CTR
&libssh2_crypt_method_aes128_ctr,
&libssh2_crypt_method_aes192_ctr,
&libssh2_crypt_method_aes256_ctr,
#endif /* LIBSSH2_AES */
#if LIBSSH2_AES #if LIBSSH2_AES
&libssh2_crypt_method_aes256_cbc, &libssh2_crypt_method_aes256_cbc,
&libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */ &libssh2_crypt_method_rijndael_cbc_lysator_liu_se, /* == aes256-cbc */

View File

@ -544,8 +544,11 @@ _libssh2_cipher_init(_libssh2_cipher_ctx * h,
if (mode != GCRY_CIPHER_MODE_STREAM) { if (mode != GCRY_CIPHER_MODE_STREAM) {
int blklen = gcry_cipher_get_algo_blklen(cipher); int blklen = gcry_cipher_get_algo_blklen(cipher);
ret = gcry_cipher_setiv(*h, iv, blklen); if (mode == GCRY_CIPHER_MODE_CTR)
if (ret) { ret = gcry_cipher_setctr(*h, iv, blklen);
else
ret = gcry_cipher_setiv(*h, iv, blklen);
if (ret) {
gcry_cipher_close(*h); gcry_cipher_close(*h);
return -1; return -1;
} }

View File

@ -44,6 +44,7 @@
#define LIBSSH2_HMAC_RIPEMD 1 #define LIBSSH2_HMAC_RIPEMD 1
#define LIBSSH2_AES 1 #define LIBSSH2_AES 1
#define LIBSSH2_AES_CTR 1
#define LIBSSH2_BLOWFISH 1 #define LIBSSH2_BLOWFISH 1
#define LIBSSH2_RC4 1 #define LIBSSH2_RC4 1
#define LIBSSH2_CAST 1 #define LIBSSH2_CAST 1
@ -160,7 +161,13 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_gcry_cipher(c) (c >> 8) #define _libssh2_gcry_cipher(c) (c >> 8)
#define _libssh2_gcry_mode(m) (m & 0xFF) #define _libssh2_gcry_mode(m) (m & 0xFF)
#define _libssh2_cipher_aes256 \ #define _libssh2_cipher_aes256ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes192ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes128ctr \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES128, GCRY_CIPHER_MODE_CTR)
#define _libssh2_cipher_aes256 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC) _libssh2_gcry_ciphermode(GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_CBC)
#define _libssh2_cipher_aes192 \ #define _libssh2_cipher_aes192 \
_libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC) _libssh2_gcry_ciphermode(GCRY_CIPHER_AES192, GCRY_CIPHER_MODE_CBC)

View File

@ -1,7 +1,9 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2009 Simon Josefsson
* Author: Simon Josefsson * Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
* Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org> * Copyright (c) 2004-2006, Sara Golemon <sarag@libssh2.org>
* *
* Author: Simon Josefsson
*
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
* with or without modification, are permitted provided * with or without modification, are permitted provided
* that the following conditions are met: * that the following conditions are met:
@ -197,6 +199,106 @@ _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
return ret == 1 ? 0 : 1; return ret == 1 ? 0 : 1;
} }
#include <openssl/aes.h>
typedef struct
{
AES_KEY key;
unsigned char ctr[AES_BLOCK_SIZE];
} aes_ctr_ctx;
static int
aes_ctr_init(EVP_CIPHER_CTX *ctx, const unsigned char *key,
const unsigned char *iv, int enc) /* init key */
{
aes_ctr_ctx *c = malloc(sizeof(*c));
if (c == NULL)
return 0;
AES_set_encrypt_key(key, 8 * ctx->key_len, &c->key);
memcpy(c->ctr, iv, AES_BLOCK_SIZE);
EVP_CIPHER_CTX_set_app_data(ctx, c);
return 1;
}
static int
aes_ctr_do_cipher(EVP_CIPHER_CTX *ctx, unsigned char *out,
const unsigned char *in,
unsigned int inl) /* encrypt/decrypt data */
{
aes_ctr_ctx *c = EVP_CIPHER_CTX_get_app_data(ctx);
unsigned char b1[AES_BLOCK_SIZE];
size_t i;
if (inl != 16) /* libssh2 only ever encrypt one block */
return 0;
/*
To encrypt a packet P=P1||P2||...||Pn (where P1, P2, ..., Pn are each
blocks of length L), the encryptor first encrypts <X> with <cipher>
to obtain a block B1. The block B1 is then XORed with P1 to generate
the ciphertext block C1. The counter X is then incremented
*/
AES_encrypt(c->ctr, b1, &c->key);
for (i = 0; i < 16; i++)
*out++ = *in++ ^ b1[i];
i = 15;
while (c->ctr[i]++ == 0xFF) {
if (i == 0)
break;
i--;
}
return 1;
}
static int
aes_ctr_cleanup(EVP_CIPHER_CTX *ctx) /* cleanup ctx */
{
free(EVP_CIPHER_CTX_get_app_data(ctx));
return 1;
}
static const EVP_CIPHER *
make_ctr_evp (size_t keylen)
{
static EVP_CIPHER aes_ctr_cipher;
memset(&aes_ctr_cipher, 0, sizeof(aes_ctr_cipher));
aes_ctr_cipher.block_size = 16;
aes_ctr_cipher.key_len = keylen;
aes_ctr_cipher.iv_len = 16;
aes_ctr_cipher.init = aes_ctr_init;
aes_ctr_cipher.do_cipher = aes_ctr_do_cipher;
aes_ctr_cipher.cleanup = aes_ctr_cleanup;
return &aes_ctr_cipher;
}
const EVP_CIPHER *
_libssh2_EVP_aes_128_ctr(void)
{
return make_ctr_evp (16);
}
const EVP_CIPHER *
_libssh2_EVP_aes_192_ctr(void)
{
return make_ctr_evp (24);
}
const EVP_CIPHER *
_libssh2_EVP_aes_256_ctr(void)
{
return make_ctr_evp (32);
}
/* TODO: Optionally call a passphrase callback specified by the /* TODO: Optionally call a passphrase callback specified by the
* calling program * calling program
*/ */

View File

@ -1,4 +1,6 @@
/* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved. /* Copyright (C) 2009 Simon Josefsson
* Copyright (C) 2006, 2007 The Written Word, Inc. All rights reserved.
*
* Author: Simon Josefsson * Author: Simon Josefsson
* *
* Redistribution and use in source and binary forms, * Redistribution and use in source and binary forms,
@ -71,6 +73,7 @@
#endif #endif
#if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES) #if OPENSSL_VERSION_NUMBER >= 0x00907000L && !defined(OPENSSL_NO_AES)
# define LIBSSH2_AES_CTR 1
# define LIBSSH2_AES 1 # define LIBSSH2_AES 1
#else #else
# define LIBSSH2_AES 0 # define LIBSSH2_AES 0
@ -194,6 +197,9 @@ int _libssh2_dsa_sha1_sign(libssh2_dsa_ctx * dsactx,
#define _libssh2_cipher_aes256 EVP_aes_256_cbc #define _libssh2_cipher_aes256 EVP_aes_256_cbc
#define _libssh2_cipher_aes192 EVP_aes_192_cbc #define _libssh2_cipher_aes192 EVP_aes_192_cbc
#define _libssh2_cipher_aes128 EVP_aes_128_cbc #define _libssh2_cipher_aes128 EVP_aes_128_cbc
#define _libssh2_cipher_aes128ctr _libssh2_EVP_aes_128_ctr
#define _libssh2_cipher_aes192ctr _libssh2_EVP_aes_192_ctr
#define _libssh2_cipher_aes256ctr _libssh2_EVP_aes_256_ctr
#define _libssh2_cipher_blowfish EVP_bf_cbc #define _libssh2_cipher_blowfish EVP_bf_cbc
#define _libssh2_cipher_arcfour EVP_rc4 #define _libssh2_cipher_arcfour EVP_rc4
#define _libssh2_cipher_cast5 EVP_cast5_cbc #define _libssh2_cipher_cast5 EVP_cast5_cbc
@ -223,3 +229,7 @@ int _libssh2_cipher_crypt(_libssh2_cipher_ctx * ctx,
#define _libssh2_bn_bytes(bn) BN_num_bytes(bn) #define _libssh2_bn_bytes(bn) BN_num_bytes(bn)
#define _libssh2_bn_bits(bn) BN_num_bits(bn) #define _libssh2_bn_bits(bn) BN_num_bits(bn)
#define _libssh2_bn_free(bn) BN_clear_free(bn) #define _libssh2_bn_free(bn) BN_clear_free(bn)
const EVP_CIPHER *_libssh2_EVP_aes_128_ctr(void);
const EVP_CIPHER *_libssh2_EVP_aes_192_ctr(void);
const EVP_CIPHER *_libssh2_EVP_aes_256_ctr(void);