diff --git a/import.c b/import.c index e95883a0..98cf8010 100644 --- a/import.c +++ b/import.c @@ -549,7 +549,7 @@ struct ssh2_userkey *openssh_pem_read(const Filename *filename, des3_decrypt_pubkey_ossh(keybuf, key->iv, key->keyblob->u, key->keyblob->len); else { - void *ctx; + AESContext *ctx; assert(key->encryption == OP_E_AES); ctx = aes_make_context(); aes128_key(ctx, keybuf); diff --git a/ssh.c b/ssh.c index 3d4baf47..1ece7488 100644 --- a/ssh.c +++ b/ssh.c @@ -4850,7 +4850,7 @@ struct kexinit_algorithm { int warn; } hk; struct { - const struct ssh2_cipher *cipher; + const struct ssh2_cipheralg *cipher; int warn; } cipher; struct { @@ -5026,7 +5026,7 @@ static void do_ssh2_transport(void *vctx) const struct ssh_mac *const *maclist; int nmacs; struct { - const struct ssh2_cipher *cipher; + const struct ssh2_cipheralg *cipher; const struct ssh_mac *mac; int etm_mode; const struct ssh_compress *comp; diff --git a/ssh.h b/ssh.h index c10d6fb1..a856aa9e 100644 --- a/ssh.h +++ b/ssh.h @@ -355,6 +355,9 @@ Bignum ssh_ecdhkex_getkey(struct ec_key *key, Bignum *dss_gen_k(const char *id_string, Bignum modulus, Bignum private_key, unsigned char *digest, int digest_len); +struct ssh2_cipheralg; +typedef const struct ssh2_cipheralg *ssh2_cipher; + typedef struct { uint32 h[4]; } MD5_Core_State; @@ -371,7 +374,7 @@ void MD5Init(struct MD5Context *context); void MD5Final(unsigned char digest[16], struct MD5Context *context); void MD5Simple(void const *p, unsigned len, unsigned char output[16]); -void *hmacmd5_make_context(void *); +void *hmacmd5_make_context(ssh2_cipher *); void hmacmd5_free_context(void *handle); void hmacmd5_key(void *handle, void const *key, int len); void hmacmd5_do_hmac(void *handle, unsigned char const *blk, int len, @@ -441,16 +444,18 @@ struct ssh1_cipheralg { #define ssh1_cipher_encrypt(ctx, blk, len) ((*(ctx))->encrypt(ctx, blk, len)) #define ssh1_cipher_decrypt(ctx, blk, len) ((*(ctx))->decrypt(ctx, blk, len)) -struct ssh2_cipher { - void *(*make_context)(void); - void (*free_context)(void *); - void (*setiv) (void *, const void *iv); /* for SSH-2 */ - void (*setkey) (void *, const void *key);/* for SSH-2 */ - void (*encrypt) (void *, void *blk, int len); - void (*decrypt) (void *, void *blk, int len); +struct ssh2_cipheralg { + ssh2_cipher *(*new)(const struct ssh2_cipheralg *alg); + void (*free)(ssh2_cipher *); + void (*setiv)(ssh2_cipher *, const void *iv); + void (*setkey)(ssh2_cipher *, const void *key); + void (*encrypt)(ssh2_cipher *, void *blk, int len); + void (*decrypt)(ssh2_cipher *, void *blk, int len); /* Ignored unless SSH_CIPHER_SEPARATE_LENGTH flag set */ - void (*encrypt_length) (void *, void *blk, int len, unsigned long seq); - void (*decrypt_length) (void *, void *blk, int len, unsigned long seq); + void (*encrypt_length)(ssh2_cipher *, void *blk, int len, + unsigned long seq); + void (*decrypt_length)(ssh2_cipher *, void *blk, int len, + unsigned long seq); const char *name; int blksize; /* real_keybits is the number of bits of entropy genuinely used by @@ -474,14 +479,26 @@ struct ssh2_cipher { const struct ssh_mac *required_mac; }; +#define ssh2_cipher_new(alg) ((alg)->new(alg)) +#define ssh2_cipher_free(ctx) ((*(ctx))->free(ctx)) +#define ssh2_cipher_setiv(ctx, iv) ((*(ctx))->setiv(ctx, iv)) +#define ssh2_cipher_setkey(ctx, key) ((*(ctx))->setkey(ctx, key)) +#define ssh2_cipher_encrypt(ctx, blk, len) ((*(ctx))->encrypt(ctx, blk, len)) +#define ssh2_cipher_decrypt(ctx, blk, len) ((*(ctx))->decrypt(ctx, blk, len)) +#define ssh2_cipher_encrypt_length(ctx, blk, len, seq) \ + ((*(ctx))->encrypt_length(ctx, blk, len, seq)) +#define ssh2_cipher_decrypt_length(ctx, blk, len, seq) \ + ((*(ctx))->decrypt_length(ctx, blk, len, seq)) +#define ssh2_cipher_alg(ctx) (*(ctx)) + struct ssh2_ciphers { int nciphers; - const struct ssh2_cipher *const *list; + const struct ssh2_cipheralg *const *list; }; struct ssh_mac { /* Passes in the cipher context */ - void *(*make_context)(void *); + void *(*make_context)(ssh2_cipher *); void (*free_context)(void *); void (*setkey) (void *, const void *key); /* whole-packet operations */ @@ -618,15 +635,16 @@ extern const struct ssh_mac ssh_hmac_sha1_96; extern const struct ssh_mac ssh_hmac_sha1_96_buggy; extern const struct ssh_mac ssh_hmac_sha256; -void *aes_make_context(void); -void aes_free_context(void *handle); -void aes128_key(void *handle, const void *key); -void aes192_key(void *handle, const void *key); -void aes256_key(void *handle, const void *key); -void aes_iv(void *handle, const void *iv); -void aes_ssh2_encrypt_blk(void *handle, void *blk, int len); -void aes_ssh2_decrypt_blk(void *handle, void *blk, int len); -void aes_ssh2_sdctr(void *handle, void *blk, int len); +typedef struct AESContext AESContext; +AESContext *aes_make_context(void); +void aes_free_context(AESContext *ctx); +void aes128_key(AESContext *ctx, const void *key); +void aes192_key(AESContext *ctx, const void *key); +void aes256_key(AESContext *ctx, const void *key); +void aes_iv(AESContext *ctx, const void *iv); +void aes_ssh2_encrypt_blk(AESContext *ctx, void *blk, int len); +void aes_ssh2_decrypt_blk(AESContext *ctx, void *blk, int len); +void aes_ssh2_sdctr(AESContext *ctx, void *blk, int len); /* * PuTTY version number formatted as an SSH version string. diff --git a/ssh2bpp.c b/ssh2bpp.c index 007ab735..510e21a5 100644 --- a/ssh2bpp.c +++ b/ssh2bpp.c @@ -11,8 +11,7 @@ struct ssh2_bpp_direction { unsigned long sequence; - const struct ssh2_cipher *cipher; - void *cipher_ctx; + ssh2_cipher *cipher; const struct ssh_mac *mac; int etm_mode; void *mac_ctx; @@ -60,14 +59,14 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp) { struct ssh2_bpp_state *s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp); sfree(s->buf); - if (s->out.cipher_ctx) - s->out.cipher->free_context(s->out.cipher_ctx); + if (s->out.cipher) + ssh2_cipher_free(s->out.cipher); if (s->out.mac_ctx) s->out.mac->free_context(s->out.mac_ctx); if (s->out.comp_ctx) s->out.comp->compress_cleanup(s->out.comp_ctx); - if (s->in.cipher_ctx) - s->in.cipher->free_context(s->in.cipher_ctx); + if (s->in.cipher) + ssh2_cipher_free(s->in.cipher); if (s->in.mac_ctx) s->in.mac->free_context(s->in.mac_ctx); if (s->in.comp_ctx) @@ -79,7 +78,7 @@ static void ssh2_bpp_free(BinaryPacketProtocol *bpp) void ssh2_bpp_new_outgoing_crypto( BinaryPacketProtocol *bpp, - const struct ssh2_cipher *cipher, const void *ckey, const void *iv, + const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh_mac *mac, int etm_mode, const void *mac_key, const struct ssh_compress *compression) { @@ -87,23 +86,24 @@ void ssh2_bpp_new_outgoing_crypto( assert(bpp->vt == &ssh2_bpp_vtable); s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp); - if (s->out.cipher_ctx) - s->out.cipher->free_context(s->out.cipher_ctx); + if (s->out.cipher) + ssh2_cipher_free(s->out.cipher); if (s->out.mac_ctx) s->out.mac->free_context(s->out.mac_ctx); if (s->out.comp_ctx) s->out.comp->compress_cleanup(s->out.comp_ctx); - s->out.cipher = cipher; if (cipher) { - s->out.cipher_ctx = cipher->make_context(); - cipher->setkey(s->out.cipher_ctx, ckey); - cipher->setiv(s->out.cipher_ctx, iv); + s->out.cipher = ssh2_cipher_new(cipher); + ssh2_cipher_setkey(s->out.cipher, ckey); + ssh2_cipher_setiv(s->out.cipher, iv); + } else { + s->out.cipher = NULL; } s->out.mac = mac; s->out.etm_mode = etm_mode; if (mac) { - s->out.mac_ctx = mac->make_context(s->out.cipher_ctx); + s->out.mac_ctx = mac->make_context(s->out.cipher); mac->setkey(s->out.mac_ctx, mac_key); } @@ -116,7 +116,7 @@ void ssh2_bpp_new_outgoing_crypto( void ssh2_bpp_new_incoming_crypto( BinaryPacketProtocol *bpp, - const struct ssh2_cipher *cipher, const void *ckey, const void *iv, + const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh_mac *mac, int etm_mode, const void *mac_key, const struct ssh_compress *compression) { @@ -124,23 +124,24 @@ void ssh2_bpp_new_incoming_crypto( assert(bpp->vt == &ssh2_bpp_vtable); s = FROMFIELD(bpp, struct ssh2_bpp_state, bpp); - if (s->in.cipher_ctx) - s->in.cipher->free_context(s->in.cipher_ctx); + if (s->in.cipher) + ssh2_cipher_free(s->in.cipher); if (s->in.mac_ctx) s->in.mac->free_context(s->in.mac_ctx); if (s->in.comp_ctx) s->in.comp->decompress_cleanup(s->in.comp_ctx); - s->in.cipher = cipher; if (cipher) { - s->in.cipher_ctx = cipher->make_context(); - cipher->setkey(s->in.cipher_ctx, ckey); - cipher->setiv(s->in.cipher_ctx, iv); + s->in.cipher = ssh2_cipher_new(cipher); + ssh2_cipher_setkey(s->in.cipher, ckey); + ssh2_cipher_setiv(s->in.cipher, iv); + } else { + s->in.cipher = NULL; } s->in.mac = mac; s->in.etm_mode = etm_mode; if (mac) { - s->in.mac_ctx = mac->make_context(s->in.cipher_ctx); + s->in.mac_ctx = mac->make_context(s->in.cipher); mac->setkey(s->in.mac_ctx, mac_key); } @@ -165,14 +166,15 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) s->maxlen = 0; s->length = 0; if (s->in.cipher) - s->cipherblk = s->in.cipher->blksize; + s->cipherblk = ssh2_cipher_alg(s->in.cipher)->blksize; else s->cipherblk = 8; if (s->cipherblk < 8) s->cipherblk = 8; s->maclen = s->in.mac ? s->in.mac->len : 0; - if (s->in.cipher && (s->in.cipher->flags & SSH_CIPHER_IS_CBC) && + if (s->in.cipher && + (ssh2_cipher_alg(s->in.cipher)->flags & SSH_CIPHER_IS_CBC) && s->in.mac && !s->in.etm_mode) { /* * When dealing with a CBC-mode cipher, we want to avoid the @@ -219,9 +221,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) s->cipherblk)); /* Decrypt one more block (a little further back in * the stream). */ - s->in.cipher->decrypt( - s->in.cipher_ctx, - s->buf + s->packetlen, s->cipherblk); + ssh2_cipher_decrypt(s->in.cipher, + s->buf + s->packetlen, s->cipherblk); /* Feed that block to the MAC. */ put_data(s->sc_mac_bs, @@ -265,13 +266,13 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) s->bpp.in_raw, s->buf, 4)); /* Cipher supports length decryption, so do it */ - if (s->in.cipher && - (s->in.cipher->flags & SSH_CIPHER_SEPARATE_LENGTH)) { + if (s->in.cipher && (ssh2_cipher_alg(s->in.cipher)->flags & + SSH_CIPHER_SEPARATE_LENGTH)) { /* Keep the packet the same though, so the MAC passes */ unsigned char len[4]; memcpy(len, s->buf, 4); - s->in.cipher->decrypt_length( - s->in.cipher_ctx, len, 4, s->in.sequence); + ssh2_cipher_decrypt_length( + s->in.cipher, len, 4, s->in.sequence); s->len = toint(GET_32BIT(len)); } else { s->len = toint(GET_32BIT(s->buf)); @@ -321,8 +322,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) /* Decrypt everything between the length field and the MAC. */ if (s->in.cipher) - s->in.cipher->decrypt( - s->in.cipher_ctx, s->data + 4, s->packetlen - 4); + ssh2_cipher_decrypt( + s->in.cipher, s->data + 4, s->packetlen - 4); } else { if (s->bufsize < s->cipherblk) { s->bufsize = s->cipherblk; @@ -337,8 +338,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) s->bpp.in_raw, s->buf, s->cipherblk)); if (s->in.cipher) - s->in.cipher->decrypt( - s->in.cipher_ctx, s->buf, s->cipherblk); + ssh2_cipher_decrypt( + s->in.cipher, s->buf, s->cipherblk); /* * Now get the length figure. @@ -381,8 +382,8 @@ static void ssh2_bpp_handle_input(BinaryPacketProtocol *bpp) /* Decrypt everything _except_ the MAC. */ if (s->in.cipher) - s->in.cipher->decrypt( - s->in.cipher_ctx, + ssh2_cipher_decrypt( + s->in.cipher, s->data + s->cipherblk, s->packetlen - s->cipherblk); /* @@ -524,7 +525,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt) pkt->downstream_id, pkt->additional_log_text); } - cipherblk = s->out.cipher ? s->out.cipher->blksize : 8; + cipherblk = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 8; cipherblk = cipherblk < 8 ? 8 : cipherblk; /* or 8 if blksize < 8 */ if (s->out.comp && s->out.comp_ctx) { @@ -573,9 +574,9 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt) /* Encrypt length if the scheme requires it */ if (s->out.cipher && - (s->out.cipher->flags & SSH_CIPHER_SEPARATE_LENGTH)) { - s->out.cipher->encrypt_length(s->out.cipher_ctx, pkt->data, 4, - s->out.sequence); + (ssh2_cipher_alg(s->out.cipher)->flags & SSH_CIPHER_SEPARATE_LENGTH)) { + ssh2_cipher_encrypt_length(s->out.cipher, pkt->data, 4, + s->out.sequence); } put_padding(pkt, maclen, 0); @@ -585,8 +586,8 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt) * OpenSSH-defined encrypt-then-MAC protocol. */ if (s->out.cipher) - s->out.cipher->encrypt(s->out.cipher_ctx, - pkt->data + 4, origlen + padding - 4); + ssh2_cipher_encrypt(s->out.cipher, + pkt->data + 4, origlen + padding - 4); s->out.mac->generate(s->out.mac_ctx, pkt->data, origlen + padding, s->out.sequence); } else { @@ -598,8 +599,7 @@ static void ssh2_bpp_format_packet_inner(struct ssh2_bpp_state *s, PktOut *pkt) s->out.mac_ctx, pkt->data, origlen + padding, s->out.sequence); if (s->out.cipher) - s->out.cipher->encrypt(s->out.cipher_ctx, - pkt->data, origlen + padding); + ssh2_cipher_encrypt(s->out.cipher, pkt->data, origlen + padding); } s->out.sequence++; /* whether or not we MACed */ @@ -634,7 +634,7 @@ static void ssh2_bpp_format_packet(BinaryPacketProtocol *bpp, PktOut *pkt) int block, length; PktOut *ignore_pkt; - block = s->out.cipher ? s->out.cipher->blksize : 0; + block = s->out.cipher ? ssh2_cipher_alg(s->out.cipher)->blksize : 0; if (block < 8) block = 8; length = pkt->length; diff --git a/sshaes.c b/sshaes.c index 0b09a6a6..5259396f 100644 --- a/sshaes.c +++ b/sshaes.c @@ -970,38 +970,35 @@ static void aes_decrypt_cbc_sw(unsigned char *blk, int len, AESContext * ctx) memcpy(ctx->iv, iv, sizeof(iv)); } -void *aes_make_context(void) +AESContext *aes_make_context(void) { return snew(AESContext); } -void aes_free_context(void *handle) +void aes_free_context(AESContext *ctx) { - sfree(handle); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); } -void aes128_key(void *handle, const void *key) +void aes128_key(AESContext *ctx, const void *key) { - AESContext *ctx = (AESContext *)handle; aes_setup(ctx, key, 16); } -void aes192_key(void *handle, const void *key) +void aes192_key(AESContext *ctx, const void *key) { - AESContext *ctx = (AESContext *)handle; aes_setup(ctx, key, 24); } -void aes256_key(void *handle, const void *key) +void aes256_key(AESContext *ctx, const void *key) { - AESContext *ctx = (AESContext *)handle; aes_setup(ctx, key, 32); } -void aes_iv(void *handle, const void *viv) +void aes_iv(AESContext *ctx, const void *viv) { const unsigned char *iv = (const unsigned char *)viv; - AESContext *ctx = (AESContext *)handle; if (ctx->isNI) { memcpy(ctx->iv, iv, sizeof(ctx->iv)); } @@ -1012,21 +1009,18 @@ void aes_iv(void *handle, const void *viv) } } -void aes_ssh2_encrypt_blk(void *handle, void *blk, int len) +void aes_ssh2_encrypt_blk(AESContext *ctx, void *blk, int len) { - AESContext *ctx = (AESContext *)handle; aes_encrypt_cbc(blk, len, ctx); } -void aes_ssh2_decrypt_blk(void *handle, void *blk, int len) +void aes_ssh2_decrypt_blk(AESContext *ctx, void *blk, int len) { - AESContext *ctx = (AESContext *)handle; aes_decrypt_cbc(blk, len, ctx); } -void aes_ssh2_sdctr(void *handle, void *blk, int len) +void aes_ssh2_sdctr(AESContext *ctx, void *blk, int len) { - AESContext *ctx = (AESContext *)handle; aes_sdctr(blk, len, ctx); } @@ -1048,63 +1042,112 @@ void aes256_decrypt_pubkey(const void *key, void *blk, int len) smemclr(&ctx, 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, NULL, NULL, +struct aes_ssh2_ctx { + AESContext context; + ssh2_cipher vt; +}; + +ssh2_cipher *aes_ssh2_new(const struct ssh2_cipheralg *alg) +{ + struct aes_ssh2_ctx *ctx = snew(struct aes_ssh2_ctx); + ctx->vt = alg; + return &ctx->vt; +} + +static void aes_ssh2_free(ssh2_cipher *cipher) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); +} + +static void aes_ssh2_setiv(ssh2_cipher *cipher, const void *iv) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + aes_iv(&ctx->context, iv); +} + +static void aes_ssh2_setkey(ssh2_cipher *cipher, const void *key) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + aes_setup(&ctx->context, key, ctx->vt->padded_keybytes); +} + +static void aes_ssh2_encrypt(ssh2_cipher *cipher, void *blk, int len) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + aes_encrypt_cbc(blk, len, &ctx->context); +} + +static void aes_ssh2_decrypt(ssh2_cipher *cipher, void *blk, int len) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + aes_decrypt_cbc(blk, len, &ctx->context); +} + +static void aes_ssh2_sdctr_method(ssh2_cipher *cipher, void *blk, int len) +{ + struct aes_ssh2_ctx *ctx = FROMFIELD(cipher, struct aes_ssh2_ctx, vt); + aes_sdctr(blk, len, &ctx->context); +} + +static const struct ssh2_cipheralg ssh_aes128_ctr = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_sdctr_method, aes_ssh2_sdctr_method, NULL, NULL, "aes128-ctr", 16, 128, 16, 0, "AES-128 SDCTR", NULL }; -static const struct ssh2_cipher ssh_aes192_ctr = { - aes_make_context, aes_free_context, aes_iv, aes192_key, - aes_ssh2_sdctr, aes_ssh2_sdctr, NULL, NULL, +static const struct ssh2_cipheralg ssh_aes192_ctr = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_sdctr_method, aes_ssh2_sdctr_method, NULL, NULL, "aes192-ctr", 16, 192, 24, 0, "AES-192 SDCTR", NULL }; -static const struct ssh2_cipher ssh_aes256_ctr = { - aes_make_context, aes_free_context, aes_iv, aes256_key, - aes_ssh2_sdctr, aes_ssh2_sdctr, NULL, NULL, +static const struct ssh2_cipheralg ssh_aes256_ctr = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_sdctr_method, aes_ssh2_sdctr_method, NULL, NULL, "aes256-ctr", 16, 256, 32, 0, "AES-256 SDCTR", NULL }; -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, NULL, NULL, +static const struct ssh2_cipheralg ssh_aes128 = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_encrypt, aes_ssh2_decrypt, NULL, NULL, "aes128-cbc", 16, 128, 16, SSH_CIPHER_IS_CBC, "AES-128 CBC", NULL }; -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, NULL, NULL, +static const struct ssh2_cipheralg ssh_aes192 = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_encrypt, aes_ssh2_decrypt, NULL, NULL, "aes192-cbc", 16, 192, 24, SSH_CIPHER_IS_CBC, "AES-192 CBC", NULL }; -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, NULL, NULL, +static const struct ssh2_cipheralg ssh_aes256 = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_encrypt, aes_ssh2_decrypt, NULL, NULL, "aes256-cbc", 16, 256, 32, SSH_CIPHER_IS_CBC, "AES-256 CBC", NULL }; -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, NULL, NULL, +static const struct ssh2_cipheralg ssh_rijndael_lysator = { + aes_ssh2_new, aes_ssh2_free, aes_ssh2_setiv, aes_ssh2_setkey, + aes_ssh2_encrypt, aes_ssh2_decrypt, NULL, NULL, "rijndael-cbc@lysator.liu.se", 16, 256, 32, SSH_CIPHER_IS_CBC, "AES-256 CBC", NULL }; -static const struct ssh2_cipher *const aes_list[] = { +static const struct ssh2_cipheralg *const aes_list[] = { &ssh_aes256_ctr, &ssh_aes256, &ssh_rijndael_lysator, diff --git a/ssharcf.c b/ssharcf.c index 336e4d06..3434459c 100644 --- a/ssharcf.c +++ b/ssharcf.c @@ -9,6 +9,7 @@ typedef struct { unsigned char i, j, s[256]; + ssh2_cipher vt; } ArcfourContext; static void arcfour_block(void *handle, void *vblk, int len) @@ -61,14 +62,18 @@ static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key, * to leak data about the key. */ -static void *arcfour_make_context(void) +static ssh2_cipher *arcfour_new(const struct ssh2_cipheralg *alg) { - return snew(ArcfourContext); + ArcfourContext *ctx = snew(ArcfourContext); + ctx->vt = alg; + return &ctx->vt; } -static void arcfour_free_context(void *handle) +static void arcfour_free(ssh2_cipher *cipher) { - sfree(handle); + ArcfourContext *ctx = FROMFIELD(cipher, ArcfourContext, vt); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); } static void arcfour_stir(ArcfourContext *ctx) @@ -80,42 +85,41 @@ static void arcfour_stir(ArcfourContext *ctx) sfree(junk); } -static void arcfour128_key(void *handle, const void *key) +static void arcfour_ssh2_setiv(ssh2_cipher *cipher, const void *key) { - ArcfourContext *ctx = (ArcfourContext *)handle; - arcfour_setkey(ctx, key, 16); + /* As a pure stream cipher, Arcfour has no IV separate from the key */ +} + +static void arcfour_ssh2_setkey(ssh2_cipher *cipher, const void *key) +{ + ArcfourContext *ctx = FROMFIELD(cipher, ArcfourContext, vt); + arcfour_setkey(ctx, key, ctx->vt->padded_keybytes); arcfour_stir(ctx); } -static void arcfour256_key(void *handle, const void *key) +static void arcfour_ssh2_block(ssh2_cipher *cipher, void *blk, int len) { - ArcfourContext *ctx = (ArcfourContext *)handle; - arcfour_setkey(ctx, key, 32); - arcfour_stir(ctx); + ArcfourContext *ctx = FROMFIELD(cipher, ArcfourContext, vt); + arcfour_block(ctx, blk, len); } -static void arcfour_iv(void *handle, const void *iv) -{ - -} - -const struct ssh2_cipher ssh_arcfour128_ssh2 = { - arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour128_key, - arcfour_block, arcfour_block, NULL, NULL, +const struct ssh2_cipheralg ssh_arcfour128_ssh2 = { + arcfour_new, arcfour_free, arcfour_ssh2_setiv, arcfour_ssh2_setkey, + arcfour_ssh2_block, arcfour_ssh2_block, NULL, NULL, "arcfour128", 1, 128, 16, 0, "Arcfour-128", NULL }; -const struct ssh2_cipher ssh_arcfour256_ssh2 = { - arcfour_make_context, arcfour_free_context, arcfour_iv, arcfour256_key, - arcfour_block, arcfour_block, NULL, NULL, +const struct ssh2_cipheralg ssh_arcfour256_ssh2 = { + arcfour_new, arcfour_free, arcfour_ssh2_setiv, arcfour_ssh2_setkey, + arcfour_ssh2_block, arcfour_ssh2_block, NULL, NULL, "arcfour256", 1, 256, 32, 0, "Arcfour-256", NULL }; -static const struct ssh2_cipher *const arcfour_list[] = { +static const struct ssh2_cipheralg *const arcfour_list[] = { &ssh_arcfour256_ssh2, &ssh_arcfour128_ssh2, }; diff --git a/sshblowf.c b/sshblowf.c index 764f3f65..f5460518 100644 --- a/sshblowf.c +++ b/sshblowf.c @@ -554,16 +554,23 @@ static void blowfish_setkey(BlowfishContext *ctx, /* -- Interface with PuTTY -- */ -#define SSH_SESSION_KEY_LENGTH 32 +#define SSH1_SESSION_KEY_LENGTH 32 -void *blowfish_make_context(void) +BlowfishContext *blowfish_make_context(void) { return snew(BlowfishContext); } -void blowfish_free_context(void *handle) +void blowfish_free_context(BlowfishContext *ctx) { - sfree(handle); + sfree(ctx); +} + +static void blowfish_iv(BlowfishContext *ctx, const void *viv) +{ + const unsigned char *iv = (const unsigned char *)viv; + ctx->iv0 = GET_32BIT_MSB_FIRST(iv); + ctx->iv1 = GET_32BIT_MSB_FIRST(iv + 4); } struct blowfish_ssh1_ctx { @@ -587,31 +594,11 @@ static void blowfish_ssh1_free(ssh1_cipher *cipher) sfree(ctx); } -static void blowfish_key(void *handle, const void *key) -{ - BlowfishContext *ctx = (BlowfishContext *)handle; - blowfish_setkey(ctx, key, 16); -} - -static void blowfish256_key(void *handle, const void *key) -{ - BlowfishContext *ctx = (BlowfishContext *)handle; - blowfish_setkey(ctx, key, 32); -} - -static void blowfish_iv(void *handle, const void *viv) -{ - const unsigned char *iv = (const unsigned char *)viv; - BlowfishContext *ctx = (BlowfishContext *)handle; - ctx->iv0 = GET_32BIT_MSB_FIRST(iv); - ctx->iv1 = GET_32BIT_MSB_FIRST(iv + 4); -} - static void blowfish_ssh1_sesskey(ssh1_cipher *cipher, const void *key) { struct blowfish_ssh1_ctx *ctx = FROMFIELD(cipher, struct blowfish_ssh1_ctx, vt); - blowfish_setkey(&ctx->contexts[0], key, SSH_SESSION_KEY_LENGTH); + blowfish_setkey(&ctx->contexts[0], key, SSH1_SESSION_KEY_LENGTH); ctx->contexts[0].iv0 = ctx->contexts[0].iv1 = 0; ctx->contexts[1] = ctx->contexts[0]; /* structure copy */ } @@ -630,22 +617,59 @@ static void blowfish_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len) blowfish_lsb_decrypt_cbc(blk, len, ctx->contexts+1); } -static void blowfish_ssh2_encrypt_blk(void *handle, void *blk, int len) +struct blowfish_ssh2_ctx { + BlowfishContext context; + ssh2_cipher vt; +}; + +static ssh2_cipher *blowfish_ssh2_new(const struct ssh2_cipheralg *alg) { - BlowfishContext *ctx = (BlowfishContext *)handle; - blowfish_msb_encrypt_cbc(blk, len, ctx); + struct blowfish_ssh2_ctx *ctx = snew(struct blowfish_ssh2_ctx); + ctx->vt = alg; + return &ctx->vt; } -static void blowfish_ssh2_decrypt_blk(void *handle, void *blk, int len) +static void blowfish_ssh2_free(ssh2_cipher *cipher) { - BlowfishContext *ctx = (BlowfishContext *)handle; - blowfish_msb_decrypt_cbc(blk, len, ctx); + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); } -static void blowfish_ssh2_sdctr(void *handle, void *blk, int len) +static void blowfish_ssh2_setiv(ssh2_cipher *cipher, const void *iv) { - BlowfishContext *ctx = (BlowfishContext *)handle; - blowfish_msb_sdctr(blk, len, ctx); + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + blowfish_iv(&ctx->context, iv); +} + +static void blowfish_ssh2_setkey(ssh2_cipher *cipher, const void *key) +{ + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + blowfish_setkey(&ctx->context, key, ctx->vt->padded_keybytes); +} + +static void blowfish_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + blowfish_msb_encrypt_cbc(blk, len, &ctx->context); +} + +static void blowfish_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + blowfish_msb_decrypt_cbc(blk, len, &ctx->context); +} + +static void blowfish_ssh2_sdctr(ssh2_cipher *cipher, void *blk, int len) +{ + struct blowfish_ssh2_ctx *ctx = + FROMFIELD(cipher, struct blowfish_ssh2_ctx, vt); + blowfish_msb_sdctr(blk, len, &ctx->context); } const struct ssh1_cipheralg ssh1_blowfish = { @@ -655,23 +679,25 @@ const struct ssh1_cipheralg ssh1_blowfish = { 8, "Blowfish-128 CBC" }; -static const struct ssh2_cipher ssh_blowfish_ssh2 = { - blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish_key, +static const struct ssh2_cipheralg ssh_blowfish_ssh2 = { + blowfish_ssh2_new, blowfish_ssh2_free, + blowfish_ssh2_setiv, blowfish_ssh2_setkey, blowfish_ssh2_encrypt_blk, blowfish_ssh2_decrypt_blk, NULL, NULL, "blowfish-cbc", 8, 128, 16, SSH_CIPHER_IS_CBC, "Blowfish-128 CBC", NULL }; -static const struct ssh2_cipher ssh_blowfish_ssh2_ctr = { - blowfish_make_context, blowfish_free_context, blowfish_iv, blowfish256_key, +static const struct ssh2_cipheralg ssh_blowfish_ssh2_ctr = { + blowfish_ssh2_new, blowfish_ssh2_free, + blowfish_ssh2_setiv, blowfish_ssh2_setkey, blowfish_ssh2_sdctr, blowfish_ssh2_sdctr, NULL, NULL, "blowfish-ctr", 8, 256, 32, 0, "Blowfish-256 SDCTR", NULL }; -static const struct ssh2_cipher *const blowfish_list[] = { +static const struct ssh2_cipheralg *const blowfish_list[] = { &ssh_blowfish_ssh2_ctr, &ssh_blowfish_ssh2 }; diff --git a/sshblowf.h b/sshblowf.h index e2364521..a9efe3da 100644 --- a/sshblowf.h +++ b/sshblowf.h @@ -5,8 +5,8 @@ typedef struct BlowfishContext BlowfishContext; -void *blowfish_make_context(void); -void blowfish_free_context(void *handle); +BlowfishContext *blowfish_make_context(void); +void blowfish_free_context(BlowfishContext *ctx); void blowfish_initkey(BlowfishContext *ctx); void blowfish_expandkey(BlowfishContext *ctx, const void *key, short keybytes, diff --git a/sshbpp.h b/sshbpp.h index de11e69d..41683410 100644 --- a/sshbpp.h +++ b/sshbpp.h @@ -39,12 +39,12 @@ void ssh1_bpp_start_compression(BinaryPacketProtocol *bpp); BinaryPacketProtocol *ssh2_bpp_new(void); void ssh2_bpp_new_outgoing_crypto( BinaryPacketProtocol *bpp, - const struct ssh2_cipher *cipher, const void *ckey, const void *iv, + const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh_mac *mac, int etm_mode, const void *mac_key, const struct ssh_compress *compression); void ssh2_bpp_new_incoming_crypto( BinaryPacketProtocol *bpp, - const struct ssh2_cipher *cipher, const void *ckey, const void *iv, + const struct ssh2_cipheralg *cipher, const void *ckey, const void *iv, const struct ssh_mac *mac, int etm_mode, const void *mac_key, const struct ssh_compress *compression); diff --git a/sshccp.c b/sshccp.c index 04f1cc16..9919ced2 100644 --- a/sshccp.c +++ b/sshccp.c @@ -20,7 +20,7 @@ * This has an intricate link between the cipher and the MAC. The * keying of both is done in by the cipher and setting of the IV is * done by the MAC. One cannot operate without the other. The - * configuration of the ssh2_cipher structure ensures that the MAC is + * configuration of the ssh2_cipheralg structure ensures that the MAC is * set (and others ignored) if this cipher is chosen. * * This cipher also encrypts the length using a different @@ -866,11 +866,12 @@ struct ccp_context { struct poly1305 mac; BinarySink_IMPLEMENTATION; + ssh2_cipher vt; }; -static void *poly_make_context(void *ctx) +static void *poly_make_context(ssh2_cipher *cipher) { - return ctx; + return FROMFIELD(cipher, struct ccp_context, vt); } static void poly_free_context(void *ctx) @@ -987,48 +988,49 @@ static const struct ssh_mac ssh2_poly1305 = { 16, 0, "Poly1305" }; -static void *ccp_make_context(void) +static ssh2_cipher *ccp_new(const struct ssh2_cipheralg *alg) { struct ccp_context *ctx = snew(struct ccp_context); BinarySink_INIT(ctx, poly_BinarySink_write); poly1305_init(&ctx->mac); - return ctx; + ctx->vt = alg; + return &ctx->vt; } -static void ccp_free_context(void *vctx) +static void ccp_free(ssh2_cipher *cipher) { - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); smemclr(&ctx->a_cipher, sizeof(ctx->a_cipher)); smemclr(&ctx->b_cipher, sizeof(ctx->b_cipher)); smemclr(&ctx->mac, sizeof(ctx->mac)); sfree(ctx); } -static void ccp_iv(void *vctx, const void *iv) +static void ccp_iv(ssh2_cipher *cipher, const void *iv) { - /* struct ccp_context *ctx = (struct ccp_context *)vctx; */ + /* struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); */ /* IV is set based on the sequence number */ } -static void ccp_key(void *vctx, const void *vkey) +static void ccp_key(ssh2_cipher *cipher, const void *vkey) { const unsigned char *key = (const unsigned char *)vkey; - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); /* Initialise the a_cipher (for decrypting lengths) with the first 256 bits */ chacha20_key(&ctx->a_cipher, key + 32); /* Initialise the b_cipher (for content and MAC) with the second 256 bits */ chacha20_key(&ctx->b_cipher, key); } -static void ccp_encrypt(void *vctx, void *blk, int len) +static void ccp_encrypt(ssh2_cipher *cipher, void *blk, int len) { - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); chacha20_encrypt(&ctx->b_cipher, blk, len); } -static void ccp_decrypt(void *vctx, void *blk, int len) +static void ccp_decrypt(ssh2_cipher *cipher, void *blk, int len) { - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); chacha20_decrypt(&ctx->b_cipher, blk, len); } @@ -1049,26 +1051,26 @@ static void ccp_length_op(struct ccp_context *ctx, void *blk, int len, smemclr(iv, sizeof(iv)); } -static void ccp_encrypt_length(void *vctx, void *blk, int len, +static void ccp_encrypt_length(ssh2_cipher *cipher, void *blk, int len, unsigned long seq) { - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); ccp_length_op(ctx, blk, len, seq); chacha20_encrypt(&ctx->a_cipher, blk, len); } -static void ccp_decrypt_length(void *vctx, void *blk, int len, +static void ccp_decrypt_length(ssh2_cipher *cipher, void *blk, int len, unsigned long seq) { - struct ccp_context *ctx = (struct ccp_context *)vctx; + struct ccp_context *ctx = FROMFIELD(cipher, struct ccp_context, vt); ccp_length_op(ctx, blk, len, seq); chacha20_decrypt(&ctx->a_cipher, blk, len); } -static const struct ssh2_cipher ssh2_chacha20_poly1305 = { +static const struct ssh2_cipheralg ssh2_chacha20_poly1305 = { - ccp_make_context, - ccp_free_context, + ccp_new, + ccp_free, ccp_iv, ccp_key, ccp_encrypt, @@ -1082,7 +1084,7 @@ static const struct ssh2_cipher ssh2_chacha20_poly1305 = { &ssh2_poly1305 }; -static const struct ssh2_cipher *const ccp_list[] = { +static const struct ssh2_cipheralg *const ccp_list[] = { &ssh2_chacha20_poly1305 }; diff --git a/sshdes.c b/sshdes.c index 6cc1ce67..c3afe3eb 100644 --- a/sshdes.c +++ b/sshdes.c @@ -747,9 +747,29 @@ static void des_sdctr3(unsigned char *blk, scheds->iv1 = iv1; } -static void *des3_make_context(void) +static void des3_key(DESContext *contexts, const void *vkey) { - return snewn(3, DESContext); + const unsigned char *key = (const unsigned char *)vkey; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), &contexts[0]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 8), + GET_32BIT_MSB_FIRST(key + 12), &contexts[1]); + des_key_setup(GET_32BIT_MSB_FIRST(key + 16), + GET_32BIT_MSB_FIRST(key + 20), &contexts[2]); +} + +static void des_iv(DESContext *context, const void *viv) +{ + const unsigned char *iv = (const unsigned char *)viv; + context->iv0 = GET_32BIT_MSB_FIRST(iv); + context->iv1 = GET_32BIT_MSB_FIRST(iv + 4); +} + +static void des_key(DESContext *context, const void *vkey) +{ + const unsigned char *key = (const unsigned char *)vkey; + des_key_setup(GET_32BIT_MSB_FIRST(key), + GET_32BIT_MSB_FIRST(key + 4), context); } struct des3_ssh1_ctx { @@ -771,11 +791,6 @@ static ssh1_cipher *des3_ssh1_new(void) return &ctx->vt; } -static void *des_make_context(void) -{ - return snew(DESContext); -} - static ssh1_cipher *des_ssh1_new(void) { struct des_ssh1_ctx *ctx = snew(struct des_ssh1_ctx); @@ -797,39 +812,6 @@ static void des_ssh1_free(ssh1_cipher *cipher) sfree(ctx); } -static void des3_free_context(void *handle) /* used for both 3DES and DES */ -{ - sfree(handle); -} - -static void des3_key(void *handle, const void *vkey) -{ - const unsigned char *key = (const unsigned char *)vkey; - DESContext *keys = (DESContext *) handle; - des_key_setup(GET_32BIT_MSB_FIRST(key), - GET_32BIT_MSB_FIRST(key + 4), &keys[0]); - des_key_setup(GET_32BIT_MSB_FIRST(key + 8), - GET_32BIT_MSB_FIRST(key + 12), &keys[1]); - des_key_setup(GET_32BIT_MSB_FIRST(key + 16), - GET_32BIT_MSB_FIRST(key + 20), &keys[2]); -} - -static void des3_iv(void *handle, const void *viv) -{ - const unsigned char *iv = (const unsigned char *)viv; - DESContext *keys = (DESContext *) handle; - keys[0].iv0 = GET_32BIT_MSB_FIRST(iv); - keys[0].iv1 = GET_32BIT_MSB_FIRST(iv + 4); -} - -static void des_key(void *handle, const void *vkey) -{ - const unsigned char *key = (const unsigned char *)vkey; - DESContext *keys = (DESContext *) handle; - des_key_setup(GET_32BIT_MSB_FIRST(key), - GET_32BIT_MSB_FIRST(key + 4), &keys[0]); -} - static void des3_ssh1_sesskey(ssh1_cipher *cipher, const void *key) { struct des3_ssh1_ctx *ctx = FROMFIELD(cipher, struct des3_ssh1_ctx, vt); @@ -868,34 +850,98 @@ static void des_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len) des_cbc_decrypt(blk, len, ctx->contexts+1); } -static void des3_ssh2_encrypt_blk(void *handle, void *blk, int len) +struct des3_ssh2_ctx { + DESContext contexts[3]; + ssh2_cipher vt; +}; + +struct des_ssh2_ctx { + DESContext context; + ssh2_cipher vt; +}; + +static ssh2_cipher *des3_ssh2_new(const struct ssh2_cipheralg *alg) { - DESContext *keys = (DESContext *) handle; - des_cbc3_encrypt(blk, len, keys); + struct des3_ssh2_ctx *ctx = snew(struct des3_ssh2_ctx); + ctx->vt = alg; + return &ctx->vt; } -static void des3_ssh2_decrypt_blk(void *handle, void *blk, int len) +static ssh2_cipher *des_ssh2_new(const struct ssh2_cipheralg *alg) { - DESContext *keys = (DESContext *) handle; - des_cbc3_decrypt(blk, len, keys); + struct des_ssh2_ctx *ctx = snew(struct des_ssh2_ctx); + ctx->vt = alg; + return &ctx->vt; } -static void des3_ssh2_sdctr(void *handle, void *blk, int len) +static void des3_ssh2_free(ssh2_cipher *cipher) { - DESContext *keys = (DESContext *) handle; - des_sdctr3(blk, len, keys); + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); } -static void des_ssh2_encrypt_blk(void *handle, void *blk, int len) +static void des_ssh2_free(ssh2_cipher *cipher) { - DESContext *keys = (DESContext *) handle; - des_cbc_encrypt(blk, len, keys); + struct des_ssh2_ctx *ctx = FROMFIELD(cipher, struct des_ssh2_ctx, vt); + smemclr(ctx, sizeof(*ctx)); + sfree(ctx); } -static void des_ssh2_decrypt_blk(void *handle, void *blk, int len) +static void des3_ssh2_setiv(ssh2_cipher *cipher, const void *iv) { - DESContext *keys = (DESContext *) handle; - des_cbc_decrypt(blk, len, keys); + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + des_iv(&ctx->contexts[0], iv); + /* SSH-2 treats triple-DES as a single block cipher to wrap in + * CBC, so there's only one IV required, not three */ +} + +static void des3_ssh2_setkey(ssh2_cipher *cipher, const void *key) +{ + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + des3_key(ctx->contexts, key); +} + +static void des_ssh2_setiv(ssh2_cipher *cipher, const void *iv) +{ + struct des_ssh2_ctx *ctx = FROMFIELD(cipher, struct des_ssh2_ctx, vt); + des_iv(&ctx->context, iv); +} + +static void des_ssh2_setkey(ssh2_cipher *cipher, const void *key) +{ + struct des_ssh2_ctx *ctx = FROMFIELD(cipher, struct des_ssh2_ctx, vt); + des_key(&ctx->context, key); +} + +static void des3_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + des_cbc3_encrypt(blk, len, ctx->contexts); +} + +static void des3_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + des_cbc3_decrypt(blk, len, ctx->contexts); +} + +static void des3_ssh2_sdctr(ssh2_cipher *cipher, void *blk, int len) +{ + struct des3_ssh2_ctx *ctx = FROMFIELD(cipher, struct des3_ssh2_ctx, vt); + des_sdctr3(blk, len, ctx->contexts); +} + +static void des_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct des_ssh2_ctx *ctx = FROMFIELD(cipher, struct des_ssh2_ctx, vt); + des_cbc_encrypt(blk, len, &ctx->context); +} + +static void des_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len) +{ + struct des_ssh2_ctx *ctx = FROMFIELD(cipher, struct des_ssh2_ctx, vt); + des_cbc_decrypt(blk, len, &ctx->context); } void des3_decrypt_pubkey(const void *vkey, void *vblk, int len) @@ -1004,16 +1050,16 @@ void des_decrypt_xdmauth(const void *keydata, void *blk, int len) des_cbc_decrypt(blk, len, &dc); } -static const struct ssh2_cipher ssh_3des_ssh2 = { - des3_make_context, des3_free_context, des3_iv, des3_key, +static const struct ssh2_cipheralg ssh_3des_ssh2 = { + des3_ssh2_new, des3_ssh2_free, des3_ssh2_setiv, des3_ssh2_setkey, des3_ssh2_encrypt_blk, des3_ssh2_decrypt_blk, NULL, NULL, "3des-cbc", 8, 168, 24, SSH_CIPHER_IS_CBC, "triple-DES CBC", NULL }; -static const struct ssh2_cipher ssh_3des_ssh2_ctr = { - des3_make_context, des3_free_context, des3_iv, des3_key, +static const struct ssh2_cipheralg ssh_3des_ssh2_ctr = { + des3_ssh2_new, des3_ssh2_free, des3_ssh2_setiv, des3_ssh2_setkey, des3_ssh2_sdctr, des3_ssh2_sdctr, NULL, NULL, "3des-ctr", 8, 168, 24, 0, "triple-DES SDCTR", @@ -1028,23 +1074,23 @@ static const struct ssh2_cipher ssh_3des_ssh2_ctr = { * apparently aren't the only people to do so, so we sigh * and implement it anyway. */ -static const struct ssh2_cipher ssh_des_ssh2 = { - des_make_context, des3_free_context, des3_iv, des_key, +static const struct ssh2_cipheralg ssh_des_ssh2 = { + des_ssh2_new, des_ssh2_free, des_ssh2_setiv, des_ssh2_setkey, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL, "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, +static const struct ssh2_cipheralg ssh_des_sshcom_ssh2 = { + des_ssh2_new, des_ssh2_free, des_ssh2_setiv, des_ssh2_setkey, des_ssh2_encrypt_blk, des_ssh2_decrypt_blk, NULL, NULL, "des-cbc@ssh.com", 8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC", NULL }; -static const struct ssh2_cipher *const des3_list[] = { +static const struct ssh2_cipheralg *const des3_list[] = { &ssh_3des_ssh2_ctr, &ssh_3des_ssh2 }; @@ -1054,7 +1100,7 @@ const struct ssh2_ciphers ssh2_3des = { des3_list }; -static const struct ssh2_cipher *const des_list[] = { +static const struct ssh2_cipheralg *const des_list[] = { &ssh_des_ssh2, &ssh_des_sshcom_ssh2 }; diff --git a/sshmd5.c b/sshmd5.c index 05f00d0b..be3b96cf 100644 --- a/sshmd5.c +++ b/sshmd5.c @@ -228,7 +228,7 @@ void MD5Simple(void const *p, unsigned len, unsigned char output[16]) * useful elsewhere (SOCKS5 CHAP authentication uses HMAC-MD5). */ -void *hmacmd5_make_context(void *cipher_ctx) +void *hmacmd5_make_context(ssh2_cipher *cipher) { return snewn(3, struct MD5Context); } diff --git a/sshsh256.c b/sshsh256.c index 66752326..51788679 100644 --- a/sshsh256.c +++ b/sshsh256.c @@ -256,7 +256,7 @@ const struct ssh_hash ssh_sha256 = { * HMAC wrapper on it. */ -static void *sha256_make_context(void *cipher_ctx) +static void *sha256_make_context(ssh2_cipher *cipher) { return snewn(3, SHA256_State); } diff --git a/sshsha.c b/sshsha.c index 4b9d002f..e2f2a860 100644 --- a/sshsha.c +++ b/sshsha.c @@ -283,7 +283,7 @@ const struct ssh_hash ssh_sha1 = { * HMAC wrapper on it. */ -static void *sha1_make_context(void *cipher_ctx) +static void *sha1_make_context(ssh2_cipher *cipher) { return snewn(3, SHA_State); }