version 1.65, 2003/05/17 04:27:52 |
version 1.65.2.2, 2004/08/19 22:37:31 |
|
|
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); |
extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); |
extern const EVP_CIPHER *evp_aes_128_ctr(void); |
extern const EVP_CIPHER *evp_aes_128_ctr(void); |
extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); |
extern void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, u_int); |
|
#define EVP_acss NULL |
|
|
struct Cipher { |
struct Cipher { |
char *name; |
char *name; |
|
|
u_int key_len; |
u_int key_len; |
const EVP_CIPHER *(*evptype)(void); |
const EVP_CIPHER *(*evptype)(void); |
} ciphers[] = { |
} ciphers[] = { |
{ "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null }, |
{ "none", SSH_CIPHER_NONE, 8, 0, EVP_enc_null }, |
{ "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc }, |
{ "des", SSH_CIPHER_DES, 8, 8, EVP_des_cbc }, |
{ "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des }, |
{ "3des", SSH_CIPHER_3DES, 8, 16, evp_ssh1_3des }, |
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf }, |
{ "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, evp_ssh1_bf }, |
|
|
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc }, |
{ "3des-cbc", SSH_CIPHER_SSH2, 8, 24, EVP_des_ede3_cbc }, |
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }, |
{ "blowfish-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_bf_cbc }, |
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc }, |
{ "cast128-cbc", SSH_CIPHER_SSH2, 8, 16, EVP_cast5_cbc }, |
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 }, |
{ "arcfour", SSH_CIPHER_SSH2, 8, 16, EVP_rc4 }, |
#if OPENSSL_VERSION_NUMBER < 0x00907000L |
#if OPENSSL_VERSION_NUMBER < 0x00907000L |
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael }, |
{ "aes128-cbc", SSH_CIPHER_SSH2, 16, 16, evp_rijndael }, |
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael }, |
{ "aes192-cbc", SSH_CIPHER_SSH2, 16, 24, evp_rijndael }, |
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, |
{ "aes256-cbc", SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, |
{ "rijndael-cbc@lysator.liu.se", |
{ "rijndael-cbc@lysator.liu.se", |
SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, |
SSH_CIPHER_SSH2, 16, 32, evp_rijndael }, |
#else |
#else |
|
|
{ "rijndael-cbc@lysator.liu.se", |
{ "rijndael-cbc@lysator.liu.se", |
SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, |
SSH_CIPHER_SSH2, 16, 32, EVP_aes_256_cbc }, |
#endif |
#endif |
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, |
{ "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, evp_aes_128_ctr }, |
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, |
{ "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, evp_aes_128_ctr }, |
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, |
{ "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, evp_aes_128_ctr }, |
|
{ "acss@openssh.org", SSH_CIPHER_SSH2, 16, 5, EVP_acss }, |
|
|
{ NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL } |
{ NULL, SSH_CIPHER_INVALID, 0, 0, NULL } |
}; |
}; |
|
|
/*--*/ |
/*--*/ |
|
|
u_int |
u_int |
cipher_blocksize(Cipher *c) |
cipher_blocksize(const Cipher *c) |
{ |
{ |
return (c->block_size); |
return (c->block_size); |
} |
} |
|
|
u_int |
u_int |
cipher_keylen(Cipher *c) |
cipher_keylen(const Cipher *c) |
{ |
{ |
return (c->key_len); |
return (c->key_len); |
} |
} |
|
|
u_int |
u_int |
cipher_get_number(Cipher *c) |
cipher_get_number(const Cipher *c) |
{ |
{ |
return (c->number); |
return (c->number); |
} |
} |
|
|
ciphers_valid(const char *names) |
ciphers_valid(const char *names) |
{ |
{ |
Cipher *c; |
Cipher *c; |
char *ciphers, *cp; |
char *cipher_list, *cp; |
char *p; |
char *p; |
|
|
if (names == NULL || strcmp(names, "") == 0) |
if (names == NULL || strcmp(names, "") == 0) |
return 0; |
return 0; |
ciphers = cp = xstrdup(names); |
cipher_list = cp = xstrdup(names); |
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; |
for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; |
(p = strsep(&cp, CIPHER_SEP))) { |
(p = strsep(&cp, CIPHER_SEP))) { |
c = cipher_by_name(p); |
c = cipher_by_name(p); |
if (c == NULL || c->number != SSH_CIPHER_SSH2) { |
if (c == NULL || c->number != SSH_CIPHER_SSH2) { |
debug("bad cipher %s [%s]", p, names); |
debug("bad cipher %s [%s]", p, names); |
xfree(ciphers); |
xfree(cipher_list); |
return 0; |
return 0; |
} else { |
} else { |
debug3("cipher ok: %s [%s]", p, names); |
debug3("cipher ok: %s [%s]", p, names); |
} |
} |
} |
} |
debug3("ciphers ok: [%s]", names); |
debug3("ciphers ok: [%s]", names); |
xfree(ciphers); |
xfree(cipher_list); |
return 1; |
return 1; |
} |
} |
|
|
|
|
void |
void |
cipher_init(CipherContext *cc, Cipher *cipher, |
cipher_init(CipherContext *cc, Cipher *cipher, |
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, |
const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, |
int encrypt) |
int do_encrypt) |
{ |
{ |
static int dowarn = 1; |
static int dowarn = 1; |
const EVP_CIPHER *type; |
const EVP_CIPHER *type; |
|
|
|
|
EVP_CIPHER_CTX_init(&cc->evp); |
EVP_CIPHER_CTX_init(&cc->evp); |
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, |
if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, |
(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); |
klen = EVP_CIPHER_CTX_key_length(&cc->evp); |
klen = EVP_CIPHER_CTX_key_length(&cc->evp); |
|
|
|
|
void |
void |
cipher_set_key_string(CipherContext *cc, Cipher *cipher, |
cipher_set_key_string(CipherContext *cc, Cipher *cipher, |
const char *passphrase, int encrypt) |
const char *passphrase, int do_encrypt) |
{ |
{ |
MD5_CTX md; |
MD5_CTX md; |
u_char digest[16]; |
u_char digest[16]; |
|
|
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); |
MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase)); |
MD5_Final(digest, &md); |
MD5_Final(digest, &md); |
|
|
cipher_init(cc, cipher, digest, 16, NULL, 0, encrypt); |
cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt); |
|
|
memset(digest, 0, sizeof(digest)); |
memset(digest, 0, sizeof(digest)); |
memset(&md, 0, sizeof(md)); |
memset(&md, 0, sizeof(md)); |
|
|
*/ |
*/ |
|
|
int |
int |
cipher_get_keyiv_len(CipherContext *cc) |
cipher_get_keyiv_len(const CipherContext *cc) |
{ |
{ |
Cipher *c = cc->cipher; |
Cipher *c = cc->cipher; |
int ivlen; |
int ivlen; |
|
|
#endif |
#endif |
|
|
int |
int |
cipher_get_keycontext(CipherContext *cc, u_char *dat) |
cipher_get_keycontext(const CipherContext *cc, u_char *dat) |
{ |
{ |
Cipher *c = cc->cipher; |
Cipher *c = cc->cipher; |
int plen = 0; |
int plen = 0; |
|
|
if (c->evptype == EVP_rc4) { |
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) { |
plen = EVP_X_STATE_LEN(cc->evp); |
plen = EVP_X_STATE_LEN(cc->evp); |
if (dat == NULL) |
if (dat == NULL) |
return (plen); |
return (plen); |
|
|
Cipher *c = cc->cipher; |
Cipher *c = cc->cipher; |
int plen; |
int plen; |
|
|
if (c->evptype == EVP_rc4) { |
if (c->evptype == EVP_rc4 || c->evptype == EVP_acss) { |
plen = EVP_X_STATE_LEN(cc->evp); |
plen = EVP_X_STATE_LEN(cc->evp); |
memcpy(EVP_X_STATE(cc->evp), dat, plen); |
memcpy(EVP_X_STATE(cc->evp), dat, plen); |
} |
} |