int nopty;
int compression;
int agentfwd;
- enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES } cipher;
+ enum { CIPHER_3DES, CIPHER_BLOWFISH, CIPHER_DES, CIPHER_AES } cipher;
char keyfile[FILENAME_MAX];
int sshprot; /* use v1 or v2 when both available */
int buggymac; /* MAC bug commmercial <=v2.3.x SSH2 */
write_setting_i (sesskey, "Compression", cfg->compression);
write_setting_i (sesskey, "AgentFwd", cfg->agentfwd);
write_setting_s (sesskey, "RemoteCmd", cfg->remote_cmd);
- write_setting_s (sesskey, "Cipher", cfg->cipher == CIPHER_BLOWFISH ? "blowfish" :
- cfg->cipher == CIPHER_DES ? "des" : "3des");
+ write_setting_s (sesskey, "Cipher",
+ cfg->cipher == CIPHER_BLOWFISH ? "blowfish" :
+ cfg->cipher == CIPHER_DES ? "des" :
+ cfg->cipher == CIPHER_AES ? "aes" :
+ "3des");
write_setting_i (sesskey, "AuthTIS", cfg->try_tis_auth);
write_setting_i (sesskey, "SshProt", cfg->sshprot);
write_setting_i (sesskey, "BuggyMAC", cfg->buggymac);
cfg->cipher = CIPHER_BLOWFISH;
else if (!strcmp(cipher, "des"))
cfg->cipher = CIPHER_DES;
+ else if (!strcmp(cipher, "aes"))
+ cfg->cipher = CIPHER_AES;
else
cfg->cipher = CIPHER_3DES;
}
#define crWaitUntilV(c) do { crReturnV; } while (!(c))
extern const struct ssh_cipher ssh_3des;
-extern const struct ssh_cipher ssh_3des_ssh2;
+extern const struct ssh2_ciphers ssh2_3des;
extern const struct ssh_cipher ssh_des;
-extern const struct ssh_cipher ssh_aes128_ssh2;
-extern const struct ssh_cipher ssh_aes192_ssh2;
-extern const struct ssh_cipher ssh_aes256_ssh2;
+extern const struct ssh2_ciphers ssh2_aes;
extern const struct ssh_cipher ssh_blowfish_ssh1;
-extern const struct ssh_cipher ssh_blowfish_ssh2;
+extern const struct ssh2_ciphers ssh2_blowfish;
extern char *x11_init (Socket *, char *, void *);
extern void x11_close (Socket);
* SSH1. (3DES uses outer chaining; Blowfish has the opposite
* endianness and different-sized keys.)
*/
-const static struct ssh_cipher *ciphers[] = {
- &ssh_aes256_ssh2,
- &ssh_aes192_ssh2,
- &ssh_aes128_ssh2,
- &ssh_blowfish_ssh2,
- &ssh_3des_ssh2
+const static struct ssh2_ciphers *ciphers[] = {
+ &ssh2_aes,
+ &ssh2_blowfish,
+ &ssh2_3des,
};
extern const struct ssh_kex ssh_diffiehellman;
static int ssh_agentfwd_enabled;
static int ssh_X11_fwd_enabled;
static const struct ssh_cipher *cipher = NULL;
-static const struct ssh_cipher *cscipher = NULL;
-static const struct ssh_cipher *sccipher = NULL;
+static const struct ssh2_cipher *cscipher = NULL;
+static const struct ssh2_cipher *sccipher = NULL;
static const struct ssh_mac *csmac = NULL;
static const struct ssh_mac *scmac = NULL;
static const struct ssh_compress *cscomp = NULL;
logevent("Encrypted session key");
- cipher_type = cfg.cipher == CIPHER_BLOWFISH ? SSH_CIPHER_BLOWFISH :
- cfg.cipher == CIPHER_DES ? SSH_CIPHER_DES :
- SSH_CIPHER_3DES;
+ switch (cfg.cipher) {
+ case CIPHER_BLOWFISH: cipher_type = SSH_CIPHER_BLOWFISH; break;
+ case CIPHER_DES: cipher_type = SSH_CIPHER_DES; break;
+ case CIPHER_3DES: cipher_type = SSH_CIPHER_3DES; break;
+ case CIPHER_AES:
+ c_write("AES not supported in SSH1, falling back to 3DES\r\n", 49);
+ cipher_type = SSH_CIPHER_3DES;
+ break;
+ }
if ((supported_ciphers_mask & (1 << cipher_type)) == 0) {
c_write("Selected cipher not supported, falling back to 3DES\r\n", 53);
cipher_type = SSH_CIPHER_3DES;
*/
static int do_ssh2_transport(unsigned char *in, int inlen, int ispkt)
{
- static int i, len, nbits;
+ static int i, j, len, nbits;
static char *str;
static Bignum p, g, e, f, K;
static int kex_init_value, kex_reply_value;
static const struct ssh_mac **maclist;
static int nmacs;
- static const struct ssh_cipher *cscipher_tobe = NULL;
- static const struct ssh_cipher *sccipher_tobe = NULL;
+ static const struct ssh2_cipher *cscipher_tobe = NULL;
+ static const struct ssh2_cipher *sccipher_tobe = NULL;
static const struct ssh_mac *csmac_tobe = NULL;
static const struct ssh_mac *scmac_tobe = NULL;
static const struct ssh_compress *cscomp_tobe = NULL;
static unsigned char exchange_hash[20];
static unsigned char first_exchange_hash[20];
static unsigned char keyspace[40];
- static const struct ssh_cipher *preferred_cipher;
+ static const struct ssh2_ciphers *preferred_cipher;
static const struct ssh_compress *preferred_comp;
static int first_kex;
* Set up the preferred cipher and compression.
*/
if (cfg.cipher == CIPHER_BLOWFISH) {
- preferred_cipher = &ssh_blowfish_ssh2;
+ preferred_cipher = &ssh2_blowfish;
} else if (cfg.cipher == CIPHER_DES) {
logevent("Single DES not supported in SSH2; using 3DES");
- preferred_cipher = &ssh_3des_ssh2;
+ preferred_cipher = &ssh2_3des;
} else if (cfg.cipher == CIPHER_3DES) {
- preferred_cipher = &ssh_3des_ssh2;
+ preferred_cipher = &ssh2_3des;
+ } else if (cfg.cipher == CIPHER_AES) {
+ preferred_cipher = &ssh2_aes;
} else {
/* Shouldn't happen, but we do want to initialise to _something_. */
- preferred_cipher = &ssh_3des_ssh2;
+ preferred_cipher = &ssh2_3des;
}
if (cfg.compression)
preferred_comp = &ssh_zlib;
/* List client->server encryption algorithms. */
ssh2_pkt_addstring_start();
for (i = 0; i < lenof(ciphers)+1; i++) {
- const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1];
- ssh2_pkt_addstring_str(c->name);
- if (i < lenof(ciphers))
- ssh2_pkt_addstring_str(",");
+ const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];
+ for (j = 0; j < c->nciphers; j++) {
+ ssh2_pkt_addstring_str(c->list[j]->name);
+ if (i < lenof(ciphers) || j < c->nciphers-1)
+ ssh2_pkt_addstring_str(",");
+ }
}
/* List server->client encryption algorithms. */
ssh2_pkt_addstring_start();
for (i = 0; i < lenof(ciphers)+1; i++) {
- const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1];
- ssh2_pkt_addstring_str(c->name);
- if (i < lenof(ciphers))
- ssh2_pkt_addstring_str(",");
+ const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];
+ for (j = 0; j < c->nciphers; j++) {
+ ssh2_pkt_addstring_str(c->list[j]->name);
+ if (i < lenof(ciphers) || j < c->nciphers-1)
+ ssh2_pkt_addstring_str(",");
+ }
}
/* List client->server MAC algorithms. */
ssh2_pkt_addstring_start();
}
ssh2_pkt_getstring(&str, &len); /* client->server cipher */
for (i = 0; i < lenof(ciphers)+1; i++) {
- const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1];
- if (in_commasep_string(c->name, str, len)) {
- cscipher_tobe = c;
- break;
+ const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];
+ for (j = 0; j < c->nciphers; j++) {
+ if (in_commasep_string(c->list[j]->name, str, len)) {
+ cscipher_tobe = c->list[j];
+ break;
+ }
}
+ if (cscipher_tobe)
+ break;
}
ssh2_pkt_getstring(&str, &len); /* server->client cipher */
for (i = 0; i < lenof(ciphers)+1; i++) {
- const struct ssh_cipher *c = i==0 ? preferred_cipher : ciphers[i-1];
- if (in_commasep_string(c->name, str, len)) {
- sccipher_tobe = c;
- break;
+ const struct ssh2_ciphers *c = i==0 ? preferred_cipher : ciphers[i-1];
+ for (j = 0; j < c->nciphers; j++) {
+ if (in_commasep_string(c->list[j]->name, str, len)) {
+ sccipher_tobe = c->list[j];
+ break;
+ }
}
+ if (sccipher_tobe)
+ break;
}
ssh2_pkt_getstring(&str, &len); /* client->server mac */
for (i = 0; i < nmacs; i++) {
struct ssh_cipher {
void (*sesskey)(unsigned char *key); /* for ssh 1 */
+ void (*encrypt)(unsigned char *blk, int len);
+ void (*decrypt)(unsigned char *blk, int len);
+ int blksize;
+};
+
+struct ssh2_cipher {
void (*setcsiv)(unsigned char *key); /* for ssh 2 */
void (*setcskey)(unsigned char *key); /* for ssh 2 */
void (*setsciv)(unsigned char *key); /* for ssh 2 */
int keylen;
};
+struct ssh2_ciphers {
+ int nciphers;
+ struct ssh2_cipher **list;
+};
+
struct ssh_mac {
void (*setcskey)(unsigned char *key);
void (*setsckey)(unsigned char *key);
aes_decrypt_cbc(blk, len, &scctx);
}
-struct ssh_cipher ssh_aes128_ssh2 = {
- NULL,
+static struct ssh2_cipher ssh_aes128 = {
aes_csiv, aes128_cskey,
aes_sciv, aes128_sckey,
aes_ssh2_encrypt_blk,
16, 128
};
-struct ssh_cipher ssh_aes192_ssh2 = {
- NULL,
+static struct ssh2_cipher ssh_aes192 = {
aes_csiv, aes192_cskey,
aes_sciv, aes192_sckey,
aes_ssh2_encrypt_blk,
16, 192
};
-struct ssh_cipher ssh_aes256_ssh2 = {
- NULL,
+static struct ssh2_cipher ssh_aes256 = {
aes_csiv, aes256_cskey,
aes_sciv, aes256_sckey,
aes_ssh2_encrypt_blk,
16, 256
};
-#ifdef TESTMODE
+static struct ssh2_cipher ssh_rijndael128 = {
+ aes_csiv, aes128_cskey,
+ aes_sciv, aes128_sckey,
+ aes_ssh2_encrypt_blk,
+ aes_ssh2_decrypt_blk,
+ "rijndael128-cbc",
+ 16, 128
+};
-#include <stdio.h>
+static struct ssh2_cipher ssh_rijndael192 = {
+ aes_csiv, aes192_cskey,
+ aes_sciv, aes192_sckey,
+ aes_ssh2_encrypt_blk,
+ aes_ssh2_decrypt_blk,
+ "rijndael192-cbc",
+ 16, 192
+};
-int main(void) {
- AESContext c;
- static unsigned char key[32] = {};
- word32 block[32];
- int i, j, k;
+static struct ssh2_cipher ssh_rijndael256 = {
+ aes_csiv, aes256_cskey,
+ aes_sciv, aes256_sckey,
+ aes_ssh2_encrypt_blk,
+ aes_ssh2_decrypt_blk,
+ "rijndael256-cbc",
+ 16, 256
+};
- for (i = 16; i <= 32; i += 8) {
- for (j = 16; j <= 32; j += 8) {
- printf("b%d, k%d: ", i, j);
- fflush(stdout);
- aes_setup(&c, i, key, j);
- memset(block, 0, sizeof(block));
- aes_encrypt(&c, block);
- aes_decrypt(&c, block);
- for (k = 0; k < i/4; k++)
- printf("%08x ", block[k]);
- printf("\n");
- }
- }
+static struct ssh2_cipher ssh_rijndael_lysator = {
+ aes_csiv, aes256_cskey,
+ aes_sciv, aes256_sckey,
+ aes_ssh2_encrypt_blk,
+ aes_ssh2_decrypt_blk,
+ "rijndael-cbc@lysator.liu.se",
+ 16, 256
+};
- return 0;
-}
+static struct ssh2_cipher *aes_list[] = {
+ &ssh_aes256,
+ &ssh_rijndael256,
+ &ssh_rijndael_lysator,
+ &ssh_aes192,
+ &ssh_rijndael192,
+ &ssh_aes128,
+ &ssh_rijndael128,
+};
-#endif
+struct ssh2_ciphers ssh2_aes = {
+ sizeof(aes_list) / sizeof(*aes_list),
+ aes_list
+};
struct ssh_cipher ssh_blowfish_ssh1 = {
blowfish_sesskey,
- blowfish_csiv, blowfish_cskey,
- blowfish_sciv, blowfish_sckey,
blowfish_ssh1_encrypt_blk,
blowfish_ssh1_decrypt_blk,
- "blowfish-cbc",
- 8, 256
+ 8
};
-struct ssh_cipher ssh_blowfish_ssh2 = {
- blowfish_sesskey,
+static struct ssh2_cipher ssh_blowfish_ssh2 = {
blowfish_csiv, blowfish_cskey,
blowfish_sciv, blowfish_sckey,
blowfish_ssh2_encrypt_blk,
"blowfish-cbc",
8, 128
};
+
+static struct ssh2_cipher *blowfish_list[] = {
+ &ssh_blowfish_ssh2
+};
+
+struct ssh2_ciphers ssh2_blowfish = {
+ sizeof(blowfish_list) / sizeof(*blowfish_list),
+ blowfish_list
+};
des_3cbc_encrypt(blk, blk, len, ourkeys);
}
-struct ssh_cipher ssh_3des_ssh2 = {
- NULL,
+static struct ssh2_cipher ssh_3des_ssh2 = {
des3_csiv, des3_cskey,
des3_sciv, des3_sckey,
des3_ssh2_encrypt_blk,
8, 168
};
+static struct ssh2_cipher *des3_list[] = {
+ &ssh_3des_ssh2
+};
+
+struct ssh2_ciphers ssh2_3des = {
+ sizeof(des3_list) / sizeof(*des3_list),
+ des3_list
+};
+
struct ssh_cipher ssh_3des = {
des3_sesskey,
- NULL, NULL, NULL, NULL,
des3_encrypt_blk,
des3_decrypt_blk,
- "3des-cbc",
- 8, 168
+ 8
};
static void des_sesskey(unsigned char *key) {
struct ssh_cipher ssh_des = {
des_sesskey,
- NULL, NULL, NULL, NULL, /* SSH 2 bits - unused */
des_encrypt_blk,
des_decrypt_blk,
- "des-cbc", /* should never be used - not a valid cipher in ssh2 */
- 8, 56
+ 8
};
IDC_CIPHER3DES,
IDC_CIPHERBLOWF,
IDC_CIPHERDES,
+ IDC_CIPHERAES,
IDC_BUGGYMAC,
IDC_AUTHTIS,
IDC_PKSTATIC,
CheckDlgButton (hwnd, IDC_COMPRESS, cfg.compression);
CheckDlgButton (hwnd, IDC_BUGGYMAC, cfg.buggymac);
CheckDlgButton (hwnd, IDC_AGENTFWD, cfg.agentfwd);
- CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERDES,
+ CheckRadioButton (hwnd, IDC_CIPHER3DES, IDC_CIPHERAES,
cfg.cipher == CIPHER_BLOWFISH ? IDC_CIPHERBLOWF :
cfg.cipher == CIPHER_DES ? IDC_CIPHERDES :
+ cfg.cipher == CIPHER_AES ? IDC_CIPHERAES :
IDC_CIPHER3DES);
CheckRadioButton (hwnd, IDC_SSHPROT1, IDC_SSHPROT2,
cfg.sshprot == 1 ? IDC_SSHPROT1 : IDC_SSHPROT2);
radioline(&cp, "Preferred SSH protocol version:",
IDC_SSHPROTSTATIC, 2,
"&1", IDC_SSHPROT1, "&2", IDC_SSHPROT2, NULL);
- radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 3,
+ radioline(&cp, "Preferred encryption algorithm:", IDC_CIPHERSTATIC, 4,
"&3DES", IDC_CIPHER3DES,
"&Blowfish", IDC_CIPHERBLOWF,
- "&DES", IDC_CIPHERDES, NULL);
+ "&DES", IDC_CIPHERDES,
+ "&AES", IDC_CIPHERAES,
+ NULL);
checkbox(&cp, "&Imitate SSH 2 MAC bug in commercial <= v2.3.x",
IDC_BUGGYMAC);
endbox(&cp);
case IDC_CIPHER3DES:
case IDC_CIPHERBLOWF:
case IDC_CIPHERDES:
+ case IDC_CIPHERAES:
if (HIWORD(wParam) == BN_CLICKED ||
HIWORD(wParam) == BN_DOUBLECLICKED) {
if (IsDlgButtonChecked (hwnd, IDC_CIPHER3DES))
cfg.cipher = CIPHER_BLOWFISH;
else if (IsDlgButtonChecked (hwnd, IDC_CIPHERDES))
cfg.cipher = CIPHER_DES;
+ else if (IsDlgButtonChecked (hwnd, IDC_CIPHERAES))
+ cfg.cipher = CIPHER_AES;
}
break;
case IDC_SSHPROT1: