mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-08 08:58:00 +00:00
Turn SSH-2 ciphers into a classoid.
This is more or less the same job as the SSH-1 case, only more extensive, because we have a wider range of ciphers. I'm a bit disappointed about the AES case, in particular, because I feel as if it ought to have been possible to arrange to combine this layer of vtable dispatch with the subsidiary one that selects between hardware and software implementations of the underlying cipher. I may come back later and have another try at that, in fact.
This commit is contained in:
parent
6c5cc49e27
commit
229af2b5bf
2
import.c
2
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);
|
||||
|
4
ssh.c
4
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;
|
||||
|
60
ssh.h
60
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.
|
||||
|
92
ssh2bpp.c
92
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;
|
||||
|
121
sshaes.c
121
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,
|
||||
|
50
ssharcf.c
50
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,
|
||||
};
|
||||
|
104
sshblowf.c
104
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
|
||||
};
|
||||
|
@ -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,
|
||||
|
4
sshbpp.h
4
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);
|
||||
|
||||
|
48
sshccp.c
48
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
|
||||
};
|
||||
|
||||
|
176
sshdes.c
176
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
|
||||
};
|
||||
|
2
sshmd5.c
2
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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user