X-Git-Url: https://asedeno.scripts.mit.edu/gitweb/?a=blobdiff_plain;f=sshdes.c;h=13487fcd79bdb704451eb2f296af77dc6b2f126e;hb=72c3c23ebd2149ea326ad4fe7b71ac7bdefaa514;hp=f926fca3774cbe4bd36fa6ad11460364d714b159;hpb=024781b3ed53a728f5ea331fe429f9e7edd4257d;p=PuTTY.git diff --git a/sshdes.c b/sshdes.c index f926fca3..13487fcd 100644 --- a/sshdes.c +++ b/sshdes.c @@ -600,7 +600,7 @@ static void des_decipher(word32 * output, word32 L, word32 R, output[1] = R; } -static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src, +static void des_cbc_encrypt(unsigned char *blk, unsigned int len, DESContext * sched) { word32 out[2], iv0, iv1; @@ -611,23 +611,20 @@ static void des_cbc_encrypt(unsigned char *dest, const unsigned char *src, iv0 = sched->iv0; iv1 = sched->iv1; for (i = 0; i < len; i += 8) { - iv0 ^= GET_32BIT_MSB_FIRST(src); - src += 4; - iv1 ^= GET_32BIT_MSB_FIRST(src); - src += 4; + iv0 ^= GET_32BIT_MSB_FIRST(blk); + iv1 ^= GET_32BIT_MSB_FIRST(blk + 4); des_encipher(out, iv0, iv1, sched); iv0 = out[0]; iv1 = out[1]; - PUT_32BIT_MSB_FIRST(dest, iv0); - dest += 4; - PUT_32BIT_MSB_FIRST(dest, iv1); - dest += 4; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; } sched->iv0 = iv0; sched->iv1 = iv1; } -static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src, +static void des_cbc_decrypt(unsigned char *blk, unsigned int len, DESContext * sched) { word32 out[2], iv0, iv1, xL, xR; @@ -638,17 +635,14 @@ static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src, iv0 = sched->iv0; iv1 = sched->iv1; for (i = 0; i < len; i += 8) { - xL = GET_32BIT_MSB_FIRST(src); - src += 4; - xR = GET_32BIT_MSB_FIRST(src); - src += 4; + xL = GET_32BIT_MSB_FIRST(blk); + xR = GET_32BIT_MSB_FIRST(blk + 4); des_decipher(out, xL, xR, sched); iv0 ^= out[0]; iv1 ^= out[1]; - PUT_32BIT_MSB_FIRST(dest, iv0); - dest += 4; - PUT_32BIT_MSB_FIRST(dest, iv1); - dest += 4; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; iv0 = xL; iv1 = xR; } @@ -656,15 +650,15 @@ static void des_cbc_decrypt(unsigned char *dest, const unsigned char *src, sched->iv1 = iv1; } -static void des_3cbc_encrypt(unsigned char *dest, const unsigned char *src, +static void des_3cbc_encrypt(unsigned char *blk, unsigned int len, DESContext * scheds) { - des_cbc_encrypt(dest, src, len, &scheds[0]); - des_cbc_decrypt(dest, src, len, &scheds[1]); - des_cbc_encrypt(dest, src, len, &scheds[2]); + des_cbc_encrypt(blk, len, &scheds[0]); + des_cbc_decrypt(blk, len, &scheds[1]); + des_cbc_encrypt(blk, len, &scheds[2]); } -static void des_cbc3_encrypt(unsigned char *dest, const unsigned char *src, +static void des_cbc3_encrypt(unsigned char *blk, unsigned int len, DESContext * scheds) { word32 out[2], iv0, iv1; @@ -675,33 +669,30 @@ static void des_cbc3_encrypt(unsigned char *dest, const unsigned char *src, iv0 = scheds->iv0; iv1 = scheds->iv1; for (i = 0; i < len; i += 8) { - iv0 ^= GET_32BIT_MSB_FIRST(src); - src += 4; - iv1 ^= GET_32BIT_MSB_FIRST(src); - src += 4; + iv0 ^= GET_32BIT_MSB_FIRST(blk); + iv1 ^= GET_32BIT_MSB_FIRST(blk + 4); des_encipher(out, iv0, iv1, &scheds[0]); des_decipher(out, out[0], out[1], &scheds[1]); des_encipher(out, out[0], out[1], &scheds[2]); iv0 = out[0]; iv1 = out[1]; - PUT_32BIT_MSB_FIRST(dest, iv0); - dest += 4; - PUT_32BIT_MSB_FIRST(dest, iv1); - dest += 4; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; } scheds->iv0 = iv0; scheds->iv1 = iv1; } -static void des_3cbc_decrypt(unsigned char *dest, const unsigned char *src, +static void des_3cbc_decrypt(unsigned char *blk, unsigned int len, DESContext * scheds) { - des_cbc_decrypt(dest, src, len, &scheds[2]); - des_cbc_encrypt(dest, src, len, &scheds[1]); - des_cbc_decrypt(dest, src, len, &scheds[0]); + des_cbc_decrypt(blk, len, &scheds[2]); + des_cbc_encrypt(blk, len, &scheds[1]); + des_cbc_decrypt(blk, len, &scheds[0]); } -static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src, +static void des_cbc3_decrypt(unsigned char *blk, unsigned int len, DESContext * scheds) { word32 out[2], iv0, iv1, xL, xR; @@ -712,19 +703,16 @@ static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src, iv0 = scheds->iv0; iv1 = scheds->iv1; for (i = 0; i < len; i += 8) { - xL = GET_32BIT_MSB_FIRST(src); - src += 4; - xR = GET_32BIT_MSB_FIRST(src); - src += 4; + xL = GET_32BIT_MSB_FIRST(blk); + xR = GET_32BIT_MSB_FIRST(blk + 4); des_decipher(out, xL, xR, &scheds[2]); des_encipher(out, out[0], out[1], &scheds[1]); des_decipher(out, out[0], out[1], &scheds[0]); iv0 ^= out[0]; iv1 ^= out[1]; - PUT_32BIT_MSB_FIRST(dest, iv0); - dest += 4; - PUT_32BIT_MSB_FIRST(dest, iv1); - dest += 4; + PUT_32BIT_MSB_FIRST(blk, iv0); + PUT_32BIT_MSB_FIRST(blk + 4, iv1); + blk += 8; iv0 = xL; iv1 = xR; } @@ -732,8 +720,7 @@ static void des_cbc3_decrypt(unsigned char *dest, const unsigned char *src, scheds->iv1 = iv1; } -#ifdef ENABLE_3DES_SSH2_CTR -static void des_sdctr3(unsigned char *dest, const unsigned char *src, +static void des_sdctr3(unsigned char *blk, unsigned int len, DESContext * scheds) { word32 b[2], iv0, iv1, tmp; @@ -747,21 +734,18 @@ static void des_sdctr3(unsigned char *dest, const unsigned char *src, des_encipher(b, iv0, iv1, &scheds[0]); des_decipher(b, b[0], b[1], &scheds[1]); des_encipher(b, b[0], b[1], &scheds[2]); - 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; + tmp = GET_32BIT_MSB_FIRST(blk); + PUT_32BIT_MSB_FIRST(blk, tmp ^ b[0]); + blk += 4; + tmp = GET_32BIT_MSB_FIRST(blk); + PUT_32BIT_MSB_FIRST(blk, tmp ^ b[1]); + blk += 4; + if ((iv1 = (iv1 + 1) & 0xffffffff) == 0) + iv0 = (iv0 + 1) & 0xffffffff; } scheds->iv0 = iv0; scheds->iv1 = iv1; } -#endif static void *des3_make_context(void) { @@ -825,45 +809,43 @@ static void des3_sesskey(void *handle, unsigned char *key) static void des3_encrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_3cbc_encrypt(blk, blk, len, keys); + des_3cbc_encrypt(blk, len, keys); } static void des3_decrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_3cbc_decrypt(blk, blk, len, keys+3); + des_3cbc_decrypt(blk, len, keys+3); } static void des3_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc3_encrypt(blk, blk, len, keys); + des_cbc3_encrypt(blk, len, keys); } static void des3_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc3_decrypt(blk, blk, len, keys); + des_cbc3_decrypt(blk, len, keys); } -#ifdef ENABLE_3DES_SSH2_CTR static void des3_ssh2_sdctr(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_sdctr3(blk, blk, len, keys); + des_sdctr3(blk, len, keys); } -#endif static void des_ssh2_encrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc_encrypt(blk, blk, len, keys); + des_cbc_encrypt(blk, len, keys); } static void des_ssh2_decrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc_decrypt(blk, blk, len, keys); + des_cbc_decrypt(blk, len, keys); } void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) @@ -875,8 +857,8 @@ void des3_decrypt_pubkey(unsigned char *key, unsigned char *blk, int len) GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]); - des_3cbc_decrypt(blk, blk, len, ourkeys); - memset(ourkeys, 0, sizeof(ourkeys)); + des_3cbc_decrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); } void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) @@ -888,8 +870,8 @@ void des3_encrypt_pubkey(unsigned char *key, unsigned char *blk, int len) GET_32BIT_MSB_FIRST(key + 12), &ourkeys[1]); des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4), &ourkeys[2]); - des_3cbc_encrypt(blk, blk, len, ourkeys); - memset(ourkeys, 0, sizeof(ourkeys)); + des_3cbc_encrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); } void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, @@ -904,8 +886,8 @@ void des3_decrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]); ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv); ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4); - des_cbc3_decrypt(blk, blk, len, ourkeys); - memset(ourkeys, 0, sizeof(ourkeys)); + des_cbc3_decrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); } void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, @@ -920,11 +902,11 @@ void des3_encrypt_pubkey_ossh(unsigned char *key, unsigned char *iv, GET_32BIT_MSB_FIRST(key + 20), &ourkeys[2]); ourkeys[0].iv0 = GET_32BIT_MSB_FIRST(iv); ourkeys[0].iv1 = GET_32BIT_MSB_FIRST(iv+4); - des_cbc3_encrypt(blk, blk, len, ourkeys); - memset(ourkeys, 0, sizeof(ourkeys)); + des_cbc3_encrypt(blk, len, ourkeys); + smemclr(ourkeys, sizeof(ourkeys)); } -static void des_keysetup_xdmauth(unsigned char *keydata, DESContext *dc) +static void des_keysetup_xdmauth(const unsigned char *keydata, DESContext *dc) { unsigned char key[8]; int i, nbits, j; @@ -947,39 +929,41 @@ static void des_keysetup_xdmauth(unsigned char *keydata, DESContext *dc) des_key_setup(GET_32BIT_MSB_FIRST(key), GET_32BIT_MSB_FIRST(key + 4), dc); } -void des_encrypt_xdmauth(unsigned char *keydata, unsigned char *blk, int len) +void des_encrypt_xdmauth(const unsigned char *keydata, + unsigned char *blk, int len) { DESContext dc; des_keysetup_xdmauth(keydata, &dc); - des_cbc_encrypt(blk, blk, 24, &dc); + des_cbc_encrypt(blk, len, &dc); } -void des_decrypt_xdmauth(unsigned char *keydata, unsigned char *blk, int len) +void des_decrypt_xdmauth(const unsigned char *keydata, + unsigned char *blk, int len) { DESContext dc; des_keysetup_xdmauth(keydata, &dc); - des_cbc_decrypt(blk, blk, 24, &dc); + des_cbc_decrypt(blk, len, &dc); } 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, + des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, NULL, NULL, "3des-cbc", - 8, 168, SSH_CIPHER_IS_CBC, "triple-DES CBC" + 8, 168, 24, SSH_CIPHER_IS_CBC, "triple-DES CBC", + NULL }; -#ifdef ENABLE_3DES_SSH2_CTR 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, + des3_ssh2_sdctr, des3_ssh2_sdctr, NULL, NULL, "3des-ctr", - 8, 168, 0, "triple-DES SDCTR" + 8, 168, 24, 0, "triple-DES SDCTR", + NULL }; -#endif /* * Single DES in SSH-2. "des-cbc" is marked as HISTORIC in - * draft-ietf-secsh-assignednumbers-04.txt, referring to + * RFC 4250, referring to * FIPS-46-3. ("Single DES (i.e., DES) will be permitted * for legacy systems only.") , but ssh.com support it and * apparently aren't the only people to do so, so we sigh @@ -987,28 +971,22 @@ static const struct ssh2_cipher ssh_3des_ssh2_ctr = { */ 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_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL, "des-cbc", - 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC" + 8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC", + NULL }; 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_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL, "des-cbc@ssh.com", - 8, 56, SSH_CIPHER_IS_CBC, "single-DES CBC" + 8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC", + NULL }; -/* - * "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[] = { -#ifdef ENABLE_3DES_SSH2_CTR &ssh_3des_ssh2_ctr, -#endif &ssh_3des_ssh2 }; @@ -1043,13 +1021,13 @@ static void des_sesskey(void *handle, unsigned char *key) static void des_encrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc_encrypt(blk, blk, len, keys); + des_cbc_encrypt(blk, len, keys); } static void des_decrypt_blk(void *handle, unsigned char *blk, int len) { DESContext *keys = (DESContext *) handle; - des_cbc_decrypt(blk, blk, len, keys+1); + des_cbc_decrypt(blk, len, keys+1); } const struct ssh_cipher ssh_des = { @@ -1057,3 +1035,58 @@ const struct ssh_cipher ssh_des = { des_encrypt_blk, des_decrypt_blk, 8, "single-DES CBC" }; + +#ifdef TEST_XDM_AUTH + +/* + * Small standalone utility which allows encryption and decryption of + * single cipher blocks in the XDM-AUTHORIZATION-1 style. Written + * during the rework of X authorisation for connection sharing, to + * check the corner case when xa1_firstblock matches but the rest of + * the authorisation is bogus. + * + * Just compile this file on its own with the above ifdef symbol + * predefined: + +gcc -DTEST_XDM_AUTH -o sshdes sshdes.c + + */ + +#include +void *safemalloc(size_t n, size_t size) { return calloc(n, size); } +void safefree(void *p) { return free(p); } +void smemclr(void *p, size_t size) { memset(p, 0, size); } +int main(int argc, char **argv) +{ + unsigned char words[2][8]; + unsigned char out[8]; + int i, j; + + memset(words, 0, sizeof(words)); + + for (i = 0; i < 2; i++) { + for (j = 0; j < 8 && argv[i+1][2*j]; j++) { + char x[3]; + unsigned u; + x[0] = argv[i+1][2*j]; + x[1] = argv[i+1][2*j+1]; + x[2] = 0; + sscanf(x, "%02x", &u); + words[i][j] = u; + } + } + + memcpy(out, words[0], 8); + des_decrypt_xdmauth(words[1], out, 8); + printf("decrypt(%s,%s) = ", argv[1], argv[2]); + for (i = 0; i < 8; i++) printf("%02x", out[i]); + printf("\n"); + + memcpy(out, words[0], 8); + des_encrypt_xdmauth(words[1], out, 8); + printf("encrypt(%s,%s) = ", argv[1], argv[2]); + for (i = 0; i < 8; i++) printf("%02x", out[i]); + printf("\n"); +} + +#endif