Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mRemoteNG/PuTTYNG.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/arcfour.c')
-rw-r--r--crypto/arcfour.c143
1 files changed, 143 insertions, 0 deletions
diff --git a/crypto/arcfour.c b/crypto/arcfour.c
new file mode 100644
index 00000000..87d59022
--- /dev/null
+++ b/crypto/arcfour.c
@@ -0,0 +1,143 @@
+/*
+ * Arcfour (RC4) implementation for PuTTY.
+ *
+ * Coded from Schneier.
+ */
+
+#include <assert.h>
+#include "ssh.h"
+
+typedef struct {
+ unsigned char i, j, s[256];
+ ssh_cipher ciph;
+} ArcfourContext;
+
+static void arcfour_block(void *handle, void *vblk, int len)
+{
+ unsigned char *blk = (unsigned char *)vblk;
+ ArcfourContext *ctx = (ArcfourContext *)handle;
+ unsigned k;
+ unsigned char tmp, i, j, *s;
+
+ s = ctx->s;
+ i = ctx->i; j = ctx->j;
+ for (k = 0; (int)k < len; k++) {
+ i = (i + 1) & 0xff;
+ j = (j + s[i]) & 0xff;
+ tmp = s[i]; s[i] = s[j]; s[j] = tmp;
+ blk[k] ^= s[(s[i]+s[j]) & 0xff];
+ }
+ ctx->i = i; ctx->j = j;
+}
+
+static void arcfour_setkey(ArcfourContext *ctx, unsigned char const *key,
+ unsigned keybytes)
+{
+ unsigned char tmp, k[256], *s;
+ unsigned i, j;
+
+ s = ctx->s;
+ assert(keybytes <= 256);
+ ctx->i = ctx->j = 0;
+ for (i = 0; i < 256; i++) {
+ s[i] = i;
+ k[i] = key[i % keybytes];
+ }
+ j = 0;
+ for (i = 0; i < 256; i++) {
+ j = (j + s[i] + k[i]) & 0xff;
+ tmp = s[i]; s[i] = s[j]; s[j] = tmp;
+ }
+}
+
+/* -- Interface with PuTTY -- */
+
+/*
+ * We don't implement Arcfour in SSH-1 because it's utterly insecure in
+ * several ways. See CERT Vulnerability Notes VU#25309, VU#665372,
+ * and VU#565052.
+ *
+ * We don't implement the "arcfour" algorithm in SSH-2 because it doesn't
+ * stir the cipher state before emitting keystream, and hence is likely
+ * to leak data about the key.
+ */
+
+static ssh_cipher *arcfour_new(const ssh_cipheralg *alg)
+{
+ ArcfourContext *ctx = snew(ArcfourContext);
+ ctx->ciph.vt = alg;
+ return &ctx->ciph;
+}
+
+static void arcfour_free(ssh_cipher *cipher)
+{
+ ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
+ smemclr(ctx, sizeof(*ctx));
+ sfree(ctx);
+}
+
+static void arcfour_stir(ArcfourContext *ctx)
+{
+ unsigned char *junk = snewn(1536, unsigned char);
+ memset(junk, 0, 1536);
+ arcfour_block(ctx, junk, 1536);
+ smemclr(junk, 1536);
+ sfree(junk);
+}
+
+static void arcfour_ssh2_setiv(ssh_cipher *cipher, const void *key)
+{
+ /* As a pure stream cipher, Arcfour has no IV separate from the key */
+}
+
+static void arcfour_ssh2_setkey(ssh_cipher *cipher, const void *key)
+{
+ ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
+ arcfour_setkey(ctx, key, ctx->ciph.vt->padded_keybytes);
+ arcfour_stir(ctx);
+}
+
+static void arcfour_ssh2_block(ssh_cipher *cipher, void *blk, int len)
+{
+ ArcfourContext *ctx = container_of(cipher, ArcfourContext, ciph);
+ arcfour_block(ctx, blk, len);
+}
+
+const ssh_cipheralg ssh_arcfour128_ssh2 = {
+ .new = arcfour_new,
+ .free = arcfour_free,
+ .setiv = arcfour_ssh2_setiv,
+ .setkey = arcfour_ssh2_setkey,
+ .encrypt = arcfour_ssh2_block,
+ .decrypt = arcfour_ssh2_block,
+ .next_message = nullcipher_next_message,
+ .ssh2_id = "arcfour128",
+ .blksize = 1,
+ .real_keybits = 128,
+ .padded_keybytes = 16,
+ .flags = 0,
+ .text_name = "Arcfour-128",
+};
+
+const ssh_cipheralg ssh_arcfour256_ssh2 = {
+ .new = arcfour_new,
+ .free = arcfour_free,
+ .setiv = arcfour_ssh2_setiv,
+ .setkey = arcfour_ssh2_setkey,
+ .encrypt = arcfour_ssh2_block,
+ .decrypt = arcfour_ssh2_block,
+ .next_message = nullcipher_next_message,
+ .ssh2_id = "arcfour256",
+ .blksize = 1,
+ .real_keybits = 256,
+ .padded_keybytes = 32,
+ .flags = 0,
+ .text_name = "Arcfour-256",
+};
+
+static const ssh_cipheralg *const arcfour_list[] = {
+ &ssh_arcfour256_ssh2,
+ &ssh_arcfour128_ssh2,
+};
+
+const ssh2_ciphers ssh2_arcfour = { lenof(arcfour_list), arcfour_list };