diff --git a/crypto/aes.h b/crypto/aes.h index 1960713a..433306ab 100644 --- a/crypto/aes.h +++ b/crypto/aes.h @@ -52,6 +52,7 @@ static inline bool check_availability(const struct aes_extra *extra) .setkey = aes ## impl_c ## _setkey, \ .encrypt = aes ## bits ## impl_c ## _cbc_encrypt, \ .decrypt = aes ## bits ## impl_c ## _cbc_decrypt, \ + .next_message = nullcipher_next_message, \ .ssh2_id = "aes" #bits "-cbc", \ .blksize = 16, \ .real_keybits = bits, \ @@ -69,6 +70,7 @@ static inline bool check_availability(const struct aes_extra *extra) .setkey = aes ## impl_c ## _setkey, \ .encrypt = aes ## bits ## impl_c ## _sdctr, \ .decrypt = aes ## bits ## impl_c ## _sdctr, \ + .next_message = nullcipher_next_message, \ .ssh2_id = "aes" #bits "-ctr", \ .blksize = 16, \ .real_keybits = bits, \ diff --git a/crypto/arcfour.c b/crypto/arcfour.c index 53821473..87d59022 100644 --- a/crypto/arcfour.c +++ b/crypto/arcfour.c @@ -110,6 +110,7 @@ const ssh_cipheralg ssh_arcfour128_ssh2 = { .setkey = arcfour_ssh2_setkey, .encrypt = arcfour_ssh2_block, .decrypt = arcfour_ssh2_block, + .next_message = nullcipher_next_message, .ssh2_id = "arcfour128", .blksize = 1, .real_keybits = 128, @@ -125,6 +126,7 @@ const ssh_cipheralg ssh_arcfour256_ssh2 = { .setkey = arcfour_ssh2_setkey, .encrypt = arcfour_ssh2_block, .decrypt = arcfour_ssh2_block, + .next_message = nullcipher_next_message, .ssh2_id = "arcfour256", .blksize = 1, .real_keybits = 256, diff --git a/crypto/blowfish.c b/crypto/blowfish.c index 07b989ed..a4e44652 100644 --- a/crypto/blowfish.c +++ b/crypto/blowfish.c @@ -654,6 +654,7 @@ const ssh_cipheralg ssh_blowfish_ssh1 = { .setkey = blowfish_ssh_setkey, .encrypt = blowfish_ssh1_encrypt_blk, .decrypt = blowfish_ssh1_decrypt_blk, + .next_message = nullcipher_next_message, .blksize = 8, .real_keybits = 128, .padded_keybytes = SSH1_SESSION_KEY_LENGTH, @@ -668,6 +669,7 @@ const ssh_cipheralg ssh_blowfish_ssh2 = { .setkey = blowfish_ssh_setkey, .encrypt = blowfish_ssh2_encrypt_blk, .decrypt = blowfish_ssh2_decrypt_blk, + .next_message = nullcipher_next_message, .ssh2_id = "blowfish-cbc", .blksize = 8, .real_keybits = 128, @@ -683,6 +685,7 @@ const ssh_cipheralg ssh_blowfish_ssh2_ctr = { .setkey = blowfish_ssh_setkey, .encrypt = blowfish_ssh2_sdctr, .decrypt = blowfish_ssh2_sdctr, + .next_message = nullcipher_next_message, .ssh2_id = "blowfish-ctr", .blksize = 8, .real_keybits = 256, diff --git a/crypto/chacha20-poly1305.c b/crypto/chacha20-poly1305.c index f06f7dfe..d765e7fc 100644 --- a/crypto/chacha20-poly1305.c +++ b/crypto/chacha20-poly1305.c @@ -964,6 +964,7 @@ const ssh2_macalg ssh2_poly1305 = { .setkey = poly_setkey, .start = poly_start, .genresult = poly_genresult, + .next_message = nullmac_next_message, .text_name = poly_text_name, .name = "", .etm_name = "", /* Not selectable individually, just part of @@ -1061,6 +1062,7 @@ const ssh_cipheralg ssh2_chacha20_poly1305 = { .decrypt = ccp_decrypt, .encrypt_length = ccp_encrypt_length, .decrypt_length = ccp_decrypt_length, + .next_message = nullcipher_next_message, // FIXME: can we use this? .ssh2_id = "chacha20-poly1305@openssh.com", .blksize = 1, .real_keybits = 512, diff --git a/crypto/des.c b/crypto/des.c index 045b00c0..1cbec8fa 100644 --- a/crypto/des.c +++ b/crypto/des.c @@ -689,6 +689,7 @@ const ssh_cipheralg ssh_des = { .setkey = des_cbc_setkey, .encrypt = des_cbc_encrypt, .decrypt = des_cbc_decrypt, + .next_message = nullcipher_next_message, .ssh2_id = "des-cbc", .blksize = 8, .real_keybits = 56, @@ -705,6 +706,7 @@ const ssh_cipheralg ssh_des_sshcom_ssh2 = { .setkey = des_cbc_setkey, .encrypt = des_cbc_encrypt, .decrypt = des_cbc_decrypt, + .next_message = nullcipher_next_message, .ssh2_id = "des-cbc@ssh.com", .blksize = 8, .real_keybits = 56, @@ -808,6 +810,7 @@ const ssh_cipheralg ssh_3des_ssh2 = { .setkey = des3_cbc1_setkey, .encrypt = des3_cbc1_cbc_encrypt, .decrypt = des3_cbc1_cbc_decrypt, + .next_message = nullcipher_next_message, .ssh2_id = "3des-cbc", .blksize = 8, .real_keybits = 168, @@ -905,6 +908,7 @@ const ssh_cipheralg ssh_3des_ssh2_ctr = { .setkey = des3_sdctr_setkey, .encrypt = des3_sdctr_encrypt_decrypt, .decrypt = des3_sdctr_encrypt_decrypt, + .next_message = nullcipher_next_message, .ssh2_id = "3des-ctr", .blksize = 8, .real_keybits = 168, @@ -1040,6 +1044,7 @@ const ssh_cipheralg ssh_3des_ssh1 = { .setkey = des3_cbc3_setkey, .encrypt = des3_cbc3_cbc_encrypt, .decrypt = des3_cbc3_cbc_decrypt, + .next_message = nullcipher_next_message, .blksize = 8, .real_keybits = 168, .padded_keybytes = 24, diff --git a/crypto/hmac.c b/crypto/hmac.c index f04d74b5..adeccd29 100644 --- a/crypto/hmac.c +++ b/crypto/hmac.c @@ -167,6 +167,7 @@ const ssh2_macalg ssh_hmac_sha256 = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-sha2-256", .etm_name = "hmac-sha2-256-etm@openssh.com", @@ -182,6 +183,7 @@ const ssh2_macalg ssh_hmac_md5 = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-md5", .etm_name = "hmac-md5-etm@openssh.com", @@ -198,6 +200,7 @@ const ssh2_macalg ssh_hmac_sha1 = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-sha1", .etm_name = "hmac-sha1-etm@openssh.com", @@ -214,6 +217,7 @@ const ssh2_macalg ssh_hmac_sha1_96 = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-sha1-96", .etm_name = "hmac-sha1-96-etm@openssh.com", @@ -232,6 +236,7 @@ const ssh2_macalg ssh_hmac_sha1_buggy = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-sha1", .len = 20, @@ -249,6 +254,7 @@ const ssh2_macalg ssh_hmac_sha1_96_buggy = { .setkey = hmac_key, .start = hmac_start, .genresult = hmac_genresult, + .next_message = nullmac_next_message, .text_name = hmac_text_name, .name = "hmac-sha1-96", .len = 12, diff --git a/ssh.h b/ssh.h index 56eb7049..e14b44c6 100644 --- a/ssh.h +++ b/ssh.h @@ -651,6 +651,9 @@ struct ssh_cipheralg { unsigned long seq); void (*decrypt_length)(ssh_cipher *, void *blk, int len, unsigned long seq); + /* For ciphers that update their state per logical message + * (typically, per unit independently MACed) */ + void (*next_message)(ssh_cipher *); const char *ssh2_id; int blksize; /* real_keybits is the number of bits of entropy genuinely used by @@ -695,9 +698,13 @@ static inline void ssh_cipher_encrypt_length( static inline void ssh_cipher_decrypt_length( ssh_cipher *c, void *blk, int len, unsigned long seq) { c->vt->decrypt_length(c, blk, len, seq); } +static inline void ssh_cipher_next_message(ssh_cipher *c) +{ c->vt->next_message(c); } static inline const struct ssh_cipheralg *ssh_cipher_alg(ssh_cipher *c) { return c->vt; } +void nullcipher_next_message(ssh_cipher *); + struct ssh2_ciphers { int nciphers; const ssh_cipheralg *const *list; @@ -715,6 +722,7 @@ struct ssh2_macalg { void (*setkey)(ssh2_mac *, ptrlen key); void (*start)(ssh2_mac *); void (*genresult)(ssh2_mac *, unsigned char *); + void (*next_message)(ssh2_mac *); const char *(*text_name)(ssh2_mac *); const char *name, *etm_name; int len, keylen; @@ -734,6 +742,8 @@ static inline void ssh2_mac_start(ssh2_mac *m) { m->vt->start(m); } static inline void ssh2_mac_genresult(ssh2_mac *m, unsigned char *out) { m->vt->genresult(m, out); } +static inline void ssh2_mac_next_message(ssh2_mac *m) +{ m->vt->next_message(m); } static inline const char *ssh2_mac_text_name(ssh2_mac *m) { return m->vt->text_name(m); } static inline const ssh2_macalg *ssh2_mac_alg(ssh2_mac *m) @@ -746,6 +756,8 @@ bool ssh2_mac_verresult(ssh2_mac *, const void *); void ssh2_mac_generate(ssh2_mac *, void *, int, unsigned long seq); bool ssh2_mac_verify(ssh2_mac *, const void *, int, unsigned long seq); +void nullmac_next_message(ssh2_mac *m); + /* Use a MAC in its raw form, outside SSH-2 context, to MAC a given * string with a given key in the most obvious way. */ void mac_simple(const ssh2_macalg *alg, ptrlen key, ptrlen data, void *output); diff --git a/ssh/bpp2.c b/ssh/bpp2.c index 240101e3..a3ab99f9 100644 --- a/ssh/bpp2.c +++ b/ssh/bpp2.c @@ -513,6 +513,10 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) dts_consume(&s->stats->in, s->packetlen); s->pktin->sequence = s->in.sequence++; + if (s->in.cipher) + ssh_cipher_next_message(s->in.cipher); + if (s->in.mac) + ssh2_mac_next_message(s->in.mac); s->length = s->packetlen - s->pad; assert(s->length >= 0); @@ -819,6 +823,10 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt) } s->out.sequence++; /* whether or not we MACed */ + if (s->out.cipher) + ssh_cipher_next_message(s->out.cipher); + if (s->out.mac) + ssh2_mac_next_message(s->out.mac); dts_consume(&s->stats->out, origlen + padding); } diff --git a/test/testcrypt-func.h b/test/testcrypt-func.h index 02b2eb4d..f79c966e 100644 --- a/test/testcrypt-func.h +++ b/test/testcrypt-func.h @@ -273,6 +273,7 @@ FUNC(val_mac, ssh2_mac_new, ARG(macalg, alg), ARG(opt_val_cipher, cipher)) FUNC(void, ssh2_mac_setkey, ARG(val_mac, m), ARG(val_string_ptrlen, key)) FUNC(void, ssh2_mac_start, ARG(val_mac, m)) FUNC(void, ssh2_mac_update, ARG(val_mac, m), ARG(val_string_ptrlen, data)) +FUNC(void, ssh2_mac_next_message, ARG(val_mac, m)) FUNC_WRAPPED(val_string, ssh2_mac_genresult, ARG(val_mac, m)) FUNC(val_string_asciz_const, ssh2_mac_text_name, ARG(val_mac, m)) @@ -341,6 +342,7 @@ FUNC_WRAPPED(val_string, ssh_cipher_encrypt_length, ARG(val_cipher, c), ARG(val_string_ptrlen, blk), ARG(uint, seq)) FUNC_WRAPPED(val_string, ssh_cipher_decrypt_length, ARG(val_cipher, c), ARG(val_string_ptrlen, blk), ARG(uint, seq)) +FUNC(void, ssh_cipher_next_message, ARG(val_cipher, c)) /* * Integer Diffie-Hellman. diff --git a/utils/CMakeLists.txt b/utils/CMakeLists.txt index e717af49..19cbc737 100644 --- a/utils/CMakeLists.txt +++ b/utils/CMakeLists.txt @@ -42,7 +42,9 @@ add_sources_from_current_dir(utils memory.c memxor.c null_lp.c + nullcipher.c nullkey.c + nullmac.c nullseat.c nullstrcmp.c out_of_memory.c diff --git a/utils/nullcipher.c b/utils/nullcipher.c new file mode 100644 index 00000000..e11c7bbc --- /dev/null +++ b/utils/nullcipher.c @@ -0,0 +1,11 @@ +/* + * Implementation of shared trivial routines that ssh_cipher + * implementations might use. + */ + +#include "ssh.h" + +void nullcipher_next_message(ssh_cipher *cipher) +{ + /* Most ciphers don't do anything at all with this */ +} diff --git a/utils/nullmac.c b/utils/nullmac.c new file mode 100644 index 00000000..4d836704 --- /dev/null +++ b/utils/nullmac.c @@ -0,0 +1,11 @@ +/* + * Implementation of shared trivial routines that ssh2_mac + * implementations might use. + */ + +#include "ssh.h" + +void nullmac_next_message(ssh2_mac *m) +{ + /* Most MACs don't do anything at all with this */ +}