+static void des_sdctr3(unsigned char *dest, const unsigned char *src,
+ unsigned int len, DESContext * scheds)
+{
+ word32 b[2], iv0, iv1, tmp;
+ unsigned int i;
+
+ assert((len & 7) == 0);
+
+ iv0 = scheds->iv0;
+ iv1 = scheds->iv1;
+ for (i = 0; i < len; i += 8) {
+ des_encipher(b, iv0, iv1, &scheds[2]);
+ des_decipher(b, b[0], b[1], &scheds[1]);
+ des_encipher(b, b[0], b[1], &scheds[0]);
+ tmp = GET_32BIT_MSB_FIRST(src);
+ PUT_32BIT_MSB_FIRST(dest, tmp ^ b[0]);
+ src += 4;
+ dest += 4;
+ tmp = GET_32BIT_MSB_FIRST(src);
+ PUT_32BIT_MSB_FIRST(dest, tmp ^ b[0]);
+ src += 4;
+ dest += 4;
+ if ((iv0 = (iv0 + 1) & 0xffffffff) == 0)
+ iv1 = (iv1 + 1) & 0xffffffff;
+ }
+ scheds->iv0 = iv0;
+ scheds->iv1 = iv1;
+}
+
+static void *des3_make_context(void)
+{
+ return snewn(3, DESContext);
+}
+
+static void *des3_ssh1_make_context(void)
+{
+ /* Need 3 keys for each direction, in SSH-1 */
+ return snewn(6, DESContext);
+}
+
+static void *des_make_context(void)
+{
+ return snew(DESContext);
+}
+
+static void *des_ssh1_make_context(void)
+{
+ /* Need one key for each direction, in SSH-1 */
+ return snewn(2, DESContext);
+}
+
+static void des3_free_context(void *handle) /* used for both 3DES and DES */
+{
+ sfree(handle);
+}
+
+static void des3_key(void *handle, unsigned char *key)
+{
+ 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]);
+}