mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-07-07 06:22:47 -05:00
Merge the ssh1_cipher type into ssh2_cipher.
The aim of this reorganisation is to make it easier to test all the ciphers in PuTTY in a uniform way. It was inconvenient that there were two separate vtable systems for the ciphers used in SSH-1 and SSH-2 with different functionality. Now there's only one type, called ssh_cipher. But really it's the old ssh2_cipher, just renamed: I haven't made any changes to the API on the SSH-2 side. Instead, I've removed ssh1_cipher completely, and adapted the SSH-1 BPP to use the SSH-2 style API. (The relevant differences are that ssh1_cipher encapsulated both the sending and receiving directions in one object - so now ssh1bpp has to make a separate cipher instance per direction - and that ssh1_cipher automatically initialised the IV to all zeroes, which ssh1bpp now has to do by hand.) The previous ssh1_cipher vtable for single-DES has been removed completely, because when converted into the new API it became identical to the SSH-2 single-DES vtable; so now there's just one vtable for DES-CBC which works in both protocols. The other two SSH-1 ciphers each had to stay separate, because 3DES is completely different between SSH-1 and SSH-2 (three layers of CBC structure versus one), and Blowfish varies in endianness and key length between the two. (Actually, while I'm here, I've only just noticed that the SSH-1 Blowfish cipher mis-describes itself in log messages as Blowfish-128. In fact it passes the whole of the input key buffer, which has length SSH1_SESSION_KEY_LENGTH == 32 bytes == 256 bits. So it's actually Blowfish-256, and has been all along!)
This commit is contained in:
161
sshdes.c
161
sshdes.c
@ -774,32 +774,18 @@ static void des_key(DESContext *context, const void *vkey)
|
||||
}
|
||||
|
||||
struct des3_ssh1_ctx {
|
||||
/* 3 cipher context for each direction */
|
||||
DESContext contexts[6];
|
||||
ssh1_cipher ciph;
|
||||
DESContext contexts[3];
|
||||
ssh_cipher ciph;
|
||||
};
|
||||
|
||||
struct des_ssh1_ctx {
|
||||
/* 1 cipher context for each direction */
|
||||
DESContext contexts[2];
|
||||
ssh1_cipher ciph;
|
||||
};
|
||||
|
||||
static ssh1_cipher *des3_ssh1_new(void)
|
||||
static ssh_cipher *des3_ssh1_new(const ssh_cipheralg *alg)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = snew(struct des3_ssh1_ctx);
|
||||
ctx->ciph.vt = &ssh1_3des;
|
||||
ctx->ciph.vt = alg;
|
||||
return &ctx->ciph;
|
||||
}
|
||||
|
||||
static ssh1_cipher *des_ssh1_new(void)
|
||||
{
|
||||
struct des_ssh1_ctx *ctx = snew(struct des_ssh1_ctx);
|
||||
ctx->ciph.vt = &ssh1_des;
|
||||
return &ctx->ciph;
|
||||
}
|
||||
|
||||
static void des3_ssh1_free(ssh1_cipher *cipher)
|
||||
static void des3_ssh1_free(ssh_cipher *cipher)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh1_ctx, ciph);
|
||||
@ -807,83 +793,65 @@ static void des3_ssh1_free(ssh1_cipher *cipher)
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void des_ssh1_free(ssh1_cipher *cipher)
|
||||
{
|
||||
struct des_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh1_ctx, ciph);
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void des3_ssh1_sesskey(ssh1_cipher *cipher, const void *key)
|
||||
static void des3_ssh1_setkey(ssh_cipher *cipher, const void *key)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh1_ctx, ciph);
|
||||
des3_key(ctx->contexts, key);
|
||||
des3_key(ctx->contexts+3, key);
|
||||
}
|
||||
|
||||
static void des3_ssh1_encrypt_blk(ssh1_cipher *cipher, void *blk, int len)
|
||||
static void des3_ssh1_setiv(ssh_cipher *cipher, const void *iv)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh1_ctx, ciph);
|
||||
/* SSH-1's idea of triple-DES CBC is three actual instances of the
|
||||
* whole of DES-CBC, i.e. three separate CBC layers each with
|
||||
* their own IV. So in principle we ought to be able to accept 24
|
||||
* bytes of IV here. However, SSH-1 initialises all IVs to zero
|
||||
* anyway, so we fudge it by just setting them all the same. */
|
||||
for (int i = 0; i < 3; i++)
|
||||
des_iv(&ctx->contexts[i], iv);
|
||||
}
|
||||
|
||||
static void des3_ssh1_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh1_ctx, ciph);
|
||||
des_3cbc_encrypt(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
static void des3_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len)
|
||||
static void des3_ssh1_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des3_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh1_ctx, ciph);
|
||||
des_3cbc_decrypt(blk, len, ctx->contexts+3);
|
||||
}
|
||||
|
||||
static void des_ssh1_sesskey(ssh1_cipher *cipher, const void *key)
|
||||
{
|
||||
struct des_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh1_ctx, ciph);
|
||||
des_key(ctx->contexts, key);
|
||||
des_key(ctx->contexts+1, key);
|
||||
}
|
||||
|
||||
static void des_ssh1_encrypt_blk(ssh1_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh1_ctx, ciph);
|
||||
des_cbc_encrypt(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
static void des_ssh1_decrypt_blk(ssh1_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des_ssh1_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh1_ctx, ciph);
|
||||
des_cbc_decrypt(blk, len, ctx->contexts+1);
|
||||
des_3cbc_decrypt(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
struct des3_ssh2_ctx {
|
||||
DESContext contexts[3];
|
||||
ssh2_cipher ciph;
|
||||
ssh_cipher ciph;
|
||||
};
|
||||
|
||||
struct des_ssh2_ctx {
|
||||
struct des_ctx {
|
||||
DESContext context;
|
||||
ssh2_cipher ciph;
|
||||
ssh_cipher ciph;
|
||||
};
|
||||
|
||||
static ssh2_cipher *des3_ssh2_new(const ssh2_cipheralg *alg)
|
||||
static ssh_cipher *des3_ssh2_new(const ssh_cipheralg *alg)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = snew(struct des3_ssh2_ctx);
|
||||
ctx->ciph.vt = alg;
|
||||
return &ctx->ciph;
|
||||
}
|
||||
|
||||
static ssh2_cipher *des_ssh2_new(const ssh2_cipheralg *alg)
|
||||
static ssh_cipher *des_new(const ssh_cipheralg *alg)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = snew(struct des_ssh2_ctx);
|
||||
struct des_ctx *ctx = snew(struct des_ctx);
|
||||
ctx->ciph.vt = alg;
|
||||
return &ctx->ciph;
|
||||
}
|
||||
|
||||
static void des3_ssh2_free(ssh2_cipher *cipher)
|
||||
static void des3_ssh2_free(ssh_cipher *cipher)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
@ -891,15 +859,14 @@ static void des3_ssh2_free(ssh2_cipher *cipher)
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void des_ssh2_free(ssh2_cipher *cipher)
|
||||
static void des_free(ssh_cipher *cipher)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh2_ctx, ciph);
|
||||
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
|
||||
smemclr(ctx, sizeof(*ctx));
|
||||
sfree(ctx);
|
||||
}
|
||||
|
||||
static void des3_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
|
||||
static void des3_ssh2_setiv(ssh_cipher *cipher, const void *iv)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
@ -908,59 +875,55 @@ static void des3_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
|
||||
* CBC, so there's only one IV required, not three */
|
||||
}
|
||||
|
||||
static void des3_ssh2_setkey(ssh2_cipher *cipher, const void *key)
|
||||
static void des3_ssh2_setkey(ssh_cipher *cipher, const void *key)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
des3_key(ctx->contexts, key);
|
||||
}
|
||||
|
||||
static void des_ssh2_setiv(ssh2_cipher *cipher, const void *iv)
|
||||
static void des_setiv(ssh_cipher *cipher, const void *iv)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh2_ctx, ciph);
|
||||
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
|
||||
des_iv(&ctx->context, iv);
|
||||
}
|
||||
|
||||
static void des_ssh2_setkey(ssh2_cipher *cipher, const void *key)
|
||||
static void des_setkey(ssh_cipher *cipher, const void *key)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh2_ctx, ciph);
|
||||
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
|
||||
des_key(&ctx->context, key);
|
||||
}
|
||||
|
||||
static void des3_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len)
|
||||
static void des3_ssh2_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
des_cbc3_encrypt(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
static void des3_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len)
|
||||
static void des3_ssh2_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
des_cbc3_decrypt(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
static void des3_ssh2_sdctr(ssh2_cipher *cipher, void *blk, int len)
|
||||
static void des3_ssh2_sdctr(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des3_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des3_ssh2_ctx, ciph);
|
||||
des_sdctr3(blk, len, ctx->contexts);
|
||||
}
|
||||
|
||||
static void des_ssh2_encrypt_blk(ssh2_cipher *cipher, void *blk, int len)
|
||||
static void des_encrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh2_ctx, ciph);
|
||||
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
|
||||
des_cbc_encrypt(blk, len, &ctx->context);
|
||||
}
|
||||
|
||||
static void des_ssh2_decrypt_blk(ssh2_cipher *cipher, void *blk, int len)
|
||||
static void des_decrypt_blk(ssh_cipher *cipher, void *blk, int len)
|
||||
{
|
||||
struct des_ssh2_ctx *ctx = container_of(
|
||||
cipher, struct des_ssh2_ctx, ciph);
|
||||
struct des_ctx *ctx = container_of(cipher, struct des_ctx, ciph);
|
||||
des_cbc_decrypt(blk, len, &ctx->context);
|
||||
}
|
||||
|
||||
@ -1070,7 +1033,7 @@ void des_decrypt_xdmauth(const void *keydata, void *blk, int len)
|
||||
des_cbc_decrypt(blk, len, &dc);
|
||||
}
|
||||
|
||||
const ssh2_cipheralg ssh_3des_ssh2 = {
|
||||
const ssh_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",
|
||||
@ -1078,7 +1041,7 @@ const ssh2_cipheralg ssh_3des_ssh2 = {
|
||||
NULL
|
||||
};
|
||||
|
||||
const ssh2_cipheralg ssh_3des_ssh2_ctr = {
|
||||
const ssh_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",
|
||||
@ -1094,44 +1057,38 @@ const ssh2_cipheralg ssh_3des_ssh2_ctr = {
|
||||
* apparently aren't the only people to do so, so we sigh
|
||||
* and implement it anyway.
|
||||
*/
|
||||
const 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,
|
||||
const ssh_cipheralg ssh_des = {
|
||||
des_new, des_free, des_setiv, des_setkey,
|
||||
des_encrypt_blk, des_decrypt_blk, NULL, NULL,
|
||||
"des-cbc",
|
||||
8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC",
|
||||
NULL
|
||||
};
|
||||
|
||||
const 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,
|
||||
const ssh_cipheralg ssh_des_sshcom_ssh2 = {
|
||||
des_new, des_free, des_setiv, des_setkey,
|
||||
des_encrypt_blk, des_decrypt_blk, NULL, NULL,
|
||||
"des-cbc@ssh.com",
|
||||
8, 56, 8, SSH_CIPHER_IS_CBC, "single-DES CBC",
|
||||
NULL
|
||||
};
|
||||
|
||||
static const ssh2_cipheralg *const des3_list[] = {
|
||||
static const ssh_cipheralg *const des3_list[] = {
|
||||
&ssh_3des_ssh2_ctr,
|
||||
&ssh_3des_ssh2
|
||||
};
|
||||
|
||||
const ssh2_ciphers ssh2_3des = { lenof(des3_list), des3_list };
|
||||
|
||||
static const ssh2_cipheralg *const des_list[] = {
|
||||
&ssh_des_ssh2,
|
||||
static const ssh_cipheralg *const des_list[] = {
|
||||
&ssh_des,
|
||||
&ssh_des_sshcom_ssh2
|
||||
};
|
||||
|
||||
const ssh2_ciphers ssh2_des = { lenof(des_list), des_list };
|
||||
|
||||
const ssh1_cipheralg ssh1_3des = {
|
||||
des3_ssh1_new, des3_ssh1_free, des3_ssh1_sesskey,
|
||||
des3_ssh1_encrypt_blk, des3_ssh1_decrypt_blk,
|
||||
8, "triple-DES inner-CBC"
|
||||
};
|
||||
|
||||
const ssh1_cipheralg ssh1_des = {
|
||||
des_ssh1_new, des_ssh1_free, des_ssh1_sesskey,
|
||||
des_ssh1_encrypt_blk, des_ssh1_decrypt_blk,
|
||||
8, "single-DES CBC"
|
||||
const ssh_cipheralg ssh_3des_ssh1 = {
|
||||
des3_ssh1_new, des3_ssh1_free, des3_ssh1_setiv, des3_ssh1_setkey,
|
||||
des3_ssh1_encrypt_blk, des3_ssh1_decrypt_blk, NULL, NULL, NULL,
|
||||
8, 168, 24, SSH_CIPHER_IS_CBC, "triple-DES inner-CBC", NULL
|
||||
};
|
||||
|
Reference in New Issue
Block a user