From c2e3a6c92d062f019a60fa97d339db80fa0d88a3 Mon Sep 17 00:00:00 2001 From: ben Date: Wed, 6 Apr 2005 23:27:08 +0000 Subject: [PATCH] Implement SDCTR modes, as defined in the newmodes draft. This adds aes128-ctr, aes192-ctr, and aes256-ctr. blowfish-ctr and 3des-ctr are present but disabled, since I haven't tested them yet. In addition, change the user-visible names of ciphers (as displayed in the Event Log) to include the mode name and, in Blowfish's case, the key size. git-svn-id: svn://svn.tartarus.org/sgt/putty@5605 cda61777-01e9-0310-a592-d414129be87e --- sshaes.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++------- sshblowf.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++-- sshdes.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 172 insertions(+), 14 deletions(-) diff --git a/sshaes.c b/sshaes.c index 09f5b397..bc62b985 100644 --- a/sshaes.c +++ b/sshaes.c @@ -1083,6 +1083,32 @@ static void aes_decrypt_cbc(unsigned char *blk, int len, AESContext * ctx) memcpy(ctx->iv, iv, sizeof(iv)); } +static void aes_sdctr(unsigned char *blk, int len, AESContext *ctx) +{ + word32 iv[4], b[4], tmp; + int i; + + assert((len & 15) == 0); + + memcpy(iv, ctx->iv, sizeof(iv)); + + while (len > 0) { + memcpy(b, iv, sizeof(b)); + aes_encrypt(ctx, b); + for (i = 0; i < 4; i++) { + tmp = GET_32BIT_MSB_FIRST(blk + 4 * i); + PUT_32BIT_MSB_FIRST(blk + 4 * i, tmp ^ b[i]); + } + for (i = 3; i >= 0; i--) + if ((iv[i] = (iv[i] + 1) & 0xffffffff) != 0) + break; + blk += 16; + len -= 16; + } + + memcpy(ctx->iv, iv, sizeof(iv)); +} + static void *aes_make_context(void) { return snew(AESContext); @@ -1131,6 +1157,12 @@ static void aes_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) aes_decrypt_cbc(blk, len, ctx); } +static void aes_ssh2_sdctr(void *handle, unsigned char *blk, int len) +{ + AESContext *ctx = (AESContext *)handle; + aes_sdctr(blk, len, ctx); +} + void aes256_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) { AESContext ctx; @@ -1149,61 +1181,85 @@ void aes256_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) memset(&ctx, 0, sizeof(ctx)); } +static const struct ssh2_cipher ssh_aes128_ctr = { + aes_make_context, aes_free_context, aes_iv, aes128_key, + aes_ssh2_sdctr, aes_ssh2_sdctr, + "aes128-ctr", + 16, 128, "AES-128 SDCTR" +}; + +static const struct ssh2_cipher ssh_aes192_ctr = { + aes_make_context, aes_free_context, aes_iv, aes192_key, + aes_ssh2_sdctr, aes_ssh2_sdctr, + "aes192-ctr", + 16, 192, "AES-192 SDCTR" +}; + +static const struct ssh2_cipher ssh_aes256_ctr = { + aes_make_context, aes_free_context, aes_iv, aes256_key, + aes_ssh2_sdctr, aes_ssh2_sdctr, + "aes256-ctr", + 16, 256, "AES-256 SDCTR" +}; + static const struct ssh2_cipher ssh_aes128 = { aes_make_context, aes_free_context, aes_iv, aes128_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "aes128-cbc", - 16, 128, "AES-128" + 16, 128, "AES-128 CBC" }; static const struct ssh2_cipher ssh_aes192 = { aes_make_context, aes_free_context, aes_iv, aes192_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "aes192-cbc", - 16, 192, "AES-192" + 16, 192, "AES-192 CBC" }; static const struct ssh2_cipher ssh_aes256 = { aes_make_context, aes_free_context, aes_iv, aes256_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "aes256-cbc", - 16, 256, "AES-256" + 16, 256, "AES-256 CBC" }; static const struct ssh2_cipher ssh_rijndael128 = { aes_make_context, aes_free_context, aes_iv, aes128_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "rijndael128-cbc", - 16, 128, "AES-128" + 16, 128, "AES-128 CBC" }; static const struct ssh2_cipher ssh_rijndael192 = { aes_make_context, aes_free_context, aes_iv, aes192_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "rijndael192-cbc", - 16, 192, "AES-192" + 16, 192, "AES-192 CBC" }; static const struct ssh2_cipher ssh_rijndael256 = { aes_make_context, aes_free_context, aes_iv, aes256_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "rijndael256-cbc", - 16, 256, "AES-256" + 16, 256, "AES-256 CBC" }; static const struct ssh2_cipher ssh_rijndael_lysator = { aes_make_context, aes_free_context, aes_iv, aes256_key, aes_ssh2_encrypt_blk, aes_ssh2_decrypt_blk, "rijndael-cbc@lysator.liu.se", - 16, 256, "AES-256" + 16, 256, "AES-256 CBC" }; static const struct ssh2_cipher *const aes_list[] = { + &ssh_aes256_ctr, &ssh_aes256, &ssh_rijndael256, &ssh_rijndael_lysator, + &ssh_aes192_ctr, &ssh_aes192, &ssh_rijndael192, + &ssh_aes128_ctr, &ssh_aes128, &ssh_rijndael128, }; diff --git a/sshblowf.c b/sshblowf.c index 9cbeed4f..650f9b9f 100644 --- a/sshblowf.c +++ b/sshblowf.c @@ -413,6 +413,32 @@ static void blowfish_msb_decrypt_cbc(unsigned char *blk, int len, ctx->iv1 = iv1; } +static void blowfish_msb_sdctr(unsigned char *blk, int len, + BlowfishContext * ctx) +{ + word32 b[2], iv0, iv1, tmp; + + assert((len & 7) == 0); + + iv0 = ctx->iv0; + iv1 = ctx->iv1; + + while (len > 0) { + blowfish_encrypt(iv0, iv1, b, ctx); + tmp = GET_32BIT_MSB_FIRST(blk); + PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]); + tmp = GET_32BIT_MSB_FIRST(blk + 4); + PUT_32BIT_MSB_FIRST(blk + 4, tmp ^ b[1]); + if ((iv0 = (iv0 + 1) & 0xffffffff) == 0) + iv1 = (iv1 + 1) & 0xffffffff; + blk += 8; + len -= 8; + } + + ctx->iv0 = iv0; + ctx->iv1 = iv1; +} + static void blowfish_setkey(BlowfishContext * ctx, const unsigned char *key, short keybytes) { @@ -498,6 +524,12 @@ static void blowfish_key(void *handle, unsigned char *key) blowfish_setkey(ctx, key, 16); } +static void blowfish256_key(void *handle, unsigned char *key) +{ + BlowfishContext *ctx = (BlowfishContext *)handle; + blowfish_setkey(ctx, key, 32); +} + static void blowfish_iv(void *handle, unsigned char *key) { BlowfishContext *ctx = (BlowfishContext *)handle; @@ -542,20 +574,41 @@ static void blowfish_ssh2_decrypt_blk(void *handle, unsigned char *blk, blowfish_msb_decrypt_cbc(blk, len, ctx); } +static void blowfish_ssh2_sdctr(void *handle, unsigned char *blk, + int len) +{ + BlowfishContext *ctx = (BlowfishContext *)handle; + blowfish_msb_sdctr(blk, len, ctx); +} + const struct ssh_cipher ssh_blowfish_ssh1 = { blowfish_ssh1_make_context, blowfish_free_context, blowfish_sesskey, blowfish_ssh1_encrypt_blk, blowfish_ssh1_decrypt_blk, - 8, "Blowfish" + 8, "Blowfish-128 CBC" }; static const struct ssh2_cipher ssh_blowfish_ssh2 = { blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish_key, blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk, "blowfish-cbc", - 8, 128, "Blowfish" + 8, 128, "Blowfish-128 CBC" }; +static const struct ssh2_cipher ssh_blowfish_ssh2_ctr = { + blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish256_key, + blowfish_ssh2_sdctr, blowfish_ssh2_sdctr, + "blowfish-ctr", + 8, 256, "Blowfish-256 SDCTR" +}; + +/* + * "blowfish-ctr" is disabled because it hasn't had any interoperability + * testing, which is in turn because I couldn't find another implementation + * to test against. Once it's been tested, it can be enabled in standard + * builds. + */ static const struct ssh2_cipher *const blowfish_list[] = { +/* &ssh_blowfish_ssh2_ctr, */ &ssh_blowfish_ssh2 }; diff --git a/sshdes.c b/sshdes.c index 65231c8f..14ac7f68 100644 --- a/sshdes.c +++ b/sshdes.c @@ -744,6 +744,35 @@ static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src, scheds->iv1 = iv1; } +static void des_sdctr3(unsigned char *dest, const unsigned char *src, + unsigned int len, DESContext * scheds) +{ + word32 b[2], iv0, iv1, tmp; + unsigned int i; + + assert((len & 7) == 0); + + iv0 = scheds->iv0; + iv1 = scheds->iv1; + for (i = 0; i < len; i += 8) { + des_encipher(b, iv0, iv1, &scheds[2]); + des_decipher(b, b[0], b[1], &scheds[1]); + des_encipher(b, b[0], b[1], &scheds[0]); + tmp = GET_32BIT_MSB_FIRST(src); + PUT_32BIT_MSB_FIRST(dest, tmp ^ b[0]); + src += 4; + dest += 4; + tmp = GET_32BIT_MSB_FIRST(src); + PUT_32BIT_MSB_FIRST(dest, tmp ^ b[0]); + src += 4; + dest += 4; + if ((iv0 = (iv0 + 1) & 0xffffffff) == 0) + iv1 = (iv1 + 1) & 0xffffffff; + } + scheds->iv0 = iv0; + scheds->iv1 = iv1; +} + static void *des3_make_context(void) { return snewn(3, DESContext); @@ -827,6 +856,12 @@ static void des3_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) des_cbc3_decrypt(blk, blk, len, keys); } +static void des3_ssh2_sdctr(void *handle, unsigned char *blk, int len) +{ + DESContext *keys = (DESContext *) handle; + des_sdctr3(blk, blk, len, keys); +} + static void des_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; @@ -938,7 +973,14 @@ static const struct ssh2_cipher ssh_3des_ssh2 = { des3_make_context, des3_free_context, des3_iv, des3_key, des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, "3des-cbc", - 8, 168, "triple-DES" + 8, 168, "triple-DES CBC" +}; + +static const struct ssh2_cipher ssh_3des_ssh2_ctr = { + des3_make_context, des3_free_context, des3_iv, des3_key, + des3_ssh2_sdctr, des3_ssh2_sdctr, + "3des-ctr", + 8, 168, "triple-DES SDCTR" }; /* @@ -953,17 +995,24 @@ static const struct ssh2_cipher ssh_des_ssh2 = { des_make_context, des3_free_context, des3_iv, des_key, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, "des-cbc", - 8, 56, "single-DES" + 8, 56, "single-DES CBC" }; static const struct ssh2_cipher ssh_des_sshcom_ssh2 = { des_make_context, des3_free_context, des3_iv, des_key, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, "des-cbc@ssh.com", - 8, 56, "single-DES" + 8, 56, "single-DES CBC" }; +/* + * "3des-ctr" is disabled because it hasn't had any interoperability + * testing, which is in turn because I couldn't find another implementation + * to test against. Once it's been tested, it can be enabled in standard + * builds. + */ static const struct ssh2_cipher *const des3_list[] = { +/* &ssh_3des_ssh2_ctr, */ &ssh_3des_ssh2 }; @@ -985,7 +1034,7 @@ const struct ssh2_ciphers ssh2_des = { const struct ssh_cipher ssh_3des = { des3_ssh1_make_context, des3_free_context, des3_sesskey, des3_encrypt_blk, des3_decrypt_blk, - 8, "triple-DES" + 8, "triple-DES inner-CBC" }; static void des_sesskey(void *handle, unsigned char *key) @@ -1010,5 +1059,5 @@ static void des_decrypt_blk(void *handle, unsigned char *blk, int len) const struct ssh_cipher ssh_des = { des_ssh1_make_context, des3_free_context, des_sesskey, des_encrypt_blk, des_decrypt_blk, - 8, "single-DES" + 8, "single-DES CBC" }; -- 2.11.0