1
0
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:
Simon Tatham
2019-01-17 18:06:08 +00:00
parent 20930e7d0c
commit 986508a570
22 changed files with 465 additions and 611 deletions

161
sshdes.c
View File

@ -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
};