[BACK]Return to cipher.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

Diff for /src/usr.bin/ssh/cipher.c between version 1.37 and 1.37.2.5

version 1.37, 2000/10/23 19:31:54 version 1.37.2.5, 2001/09/27 00:15:41
Line 11 
Line 11 
  *   *
  *   *
  * Copyright (c) 1999 Niels Provos.  All rights reserved.   * Copyright (c) 1999 Niels Provos.  All rights reserved.
  * Copyright (c) 1999,2000 Markus Friedl.  All rights reserved.   * Copyright (c) 1999, 2000 Markus Friedl.  All rights reserved.
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 37 
Line 37 
 #include "includes.h"  #include "includes.h"
 RCSID("$OpenBSD$");  RCSID("$OpenBSD$");
   
 #include "ssh.h"  
 #include "xmalloc.h"  #include "xmalloc.h"
   #include "log.h"
   #include "cipher.h"
   
 #include <openssl/md5.h>  #include <openssl/md5.h>
   
   
 /* no encryption */  /* no encryption */
 void  static void
 none_setkey(CipherContext *cc, const u_char *key, u_int keylen)  none_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
 }  }
 void  static void
 none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  none_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
 }  }
 void  static void
 none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  none_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         memcpy(dest, src, len);          memcpy(dest, src, len);
 }  }
   
 /* DES */  /* DES */
 void  static void
 des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)  des_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         static int dowarn = 1;          static int dowarn = 1;
Line 70 
Line 70 
         }          }
         des_set_key((void *)key, cc->u.des.key);          des_set_key((void *)key, cc->u.des.key);
 }  }
 void  static void
 des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  des_ssh1_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
         memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));          memset(cc->u.des.iv, 0, sizeof(cc->u.des.iv));
 }  }
 void  static void
 des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  des_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,          des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
             DES_ENCRYPT);              DES_ENCRYPT);
 }  }
 void  static void
 des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  des_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,          des_ncbc_encrypt(src, dest, len, cc->u.des.key, &cc->u.des.iv,
Line 89 
Line 89 
 }  }
   
 /* 3DES */  /* 3DES */
 void  static void
 des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)  des3_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         des_set_key((void *) key, cc->u.des3.key1);          des_set_key((void *) key, cc->u.des3.key1);
         des_set_key((void *) (key+8), cc->u.des3.key2);          des_set_key((void *) (key+8), cc->u.des3.key2);
         des_set_key((void *) (key+16), cc->u.des3.key3);          des_set_key((void *) (key+16), cc->u.des3.key3);
 }  }
 void  static void
 des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  des3_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
           memset(cc->u.des3.iv1, 0, sizeof(cc->u.des3.iv1));
         memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));          memset(cc->u.des3.iv2, 0, sizeof(cc->u.des3.iv2));
         memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));          memset(cc->u.des3.iv3, 0, sizeof(cc->u.des3.iv3));
         if (iv == NULL)          if (iv == NULL)
                 return;                  return;
         memcpy(cc->u.des3.iv3, (char *)iv, 8);          memcpy(cc->u.des3.iv3, (char *)iv, 8);
 }  }
 void  static void
 des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  des3_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         des_ede3_cbc_encrypt(src, dest, len,          des_ede3_cbc_encrypt(src, dest, len,
             cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,              cc->u.des3.key1, cc->u.des3.key2, cc->u.des3.key3,
             &cc->u.des3.iv3, DES_ENCRYPT);              &cc->u.des3.iv3, DES_ENCRYPT);
 }  }
 void  static void
 des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  des3_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         des_ede3_cbc_encrypt(src, dest, len,          des_ede3_cbc_encrypt(src, dest, len,
Line 134 
Line 135 
  * result of that there is no longer any known iv1 to use when   * result of that there is no longer any known iv1 to use when
  * choosing the X block.   * choosing the X block.
  */   */
 void  static void
 des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)  des3_ssh1_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         des_set_key((void *) key, cc->u.des3.key1);          des_set_key((void *) key, cc->u.des3.key1);
Line 144 
Line 145 
         else          else
                 des_set_key((void *) (key+16), cc->u.des3.key3);                  des_set_key((void *) (key+16), cc->u.des3.key3);
 }  }
 void  static void
 des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,  des3_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
         des_cblock iv1;          des_ncbc_encrypt(src,  dest, len, cc->u.des3.key1, &cc->u.des3.iv1,
         des_cblock *iv2 = &cc->u.des3.iv2;              DES_ENCRYPT);
         des_cblock *iv3 = &cc->u.des3.iv3;          des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2,
               DES_DECRYPT);
         memcpy(&iv1, iv2, 8);          des_ncbc_encrypt(dest, dest, len, cc->u.des3.key3, &cc->u.des3.iv3,
               DES_ENCRYPT);
         des_cbc_encrypt(src, dest, len, cc->u.des3.key1, &iv1, DES_ENCRYPT);  
         memcpy(&iv1, dest + len - 8, 8);  
   
         des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_DECRYPT);  
         memcpy(iv2, &iv1, 8);   /* Note how iv1 == iv2 on entry and exit. */  
   
         des_cbc_encrypt(dest, dest, len, cc->u.des3.key3, iv3, DES_ENCRYPT);  
         memcpy(iv3, dest + len - 8, 8);  
 }  }
 void  static void
 des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,  des3_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
         des_cblock iv1;          des_ncbc_encrypt(src,  dest, len, cc->u.des3.key3, &cc->u.des3.iv3,
         des_cblock *iv2 = &cc->u.des3.iv2;              DES_DECRYPT);
         des_cblock *iv3 = &cc->u.des3.iv3;          des_ncbc_encrypt(dest, dest, len, cc->u.des3.key2, &cc->u.des3.iv2,
               DES_ENCRYPT);
         memcpy(&iv1, iv2, 8);          des_ncbc_encrypt(dest, dest, len, cc->u.des3.key1, &cc->u.des3.iv1,
               DES_DECRYPT);
         des_cbc_encrypt(src, dest, len, cc->u.des3.key3, iv3, DES_DECRYPT);  
         memcpy(iv3, src + len - 8, 8);  
   
         des_cbc_encrypt(dest, dest, len, cc->u.des3.key2, iv2, DES_ENCRYPT);  
         memcpy(iv2, dest + len - 8, 8);  
   
         des_cbc_encrypt(dest, dest, len, cc->u.des3.key1, &iv1, DES_DECRYPT);  
         /* memcpy(&iv1, iv2, 8); */  
         /* Note how iv1 == iv2 on entry and exit. */  
 }  }
   
 /* Blowfish */  /* Blowfish */
 void  static void
 blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)  blowfish_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         BF_set_key(&cc->u.bf.key, keylen, (unsigned char *)key);          BF_set_key(&cc->u.bf.key, keylen, (u_char *)key);
 }  }
 void  static void
 blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  blowfish_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
         if (iv == NULL)          if (iv == NULL)
Line 198 
Line 182 
         else          else
                 memcpy(cc->u.bf.iv, (char *)iv, 8);                  memcpy(cc->u.bf.iv, (char *)iv, 8);
 }  }
 void  static void
 blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,  blowfish_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
      u_int len)       u_int len)
 {  {
         BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,          BF_cbc_encrypt((void *)src, dest, len, &cc->u.bf.key, cc->u.bf.iv,
             BF_ENCRYPT);              BF_ENCRYPT);
 }  }
 void  static void
 blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,  blowfish_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
      u_int len)       u_int len)
 {  {
Line 218 
Line 202 
  * and after encryption/decryption. Thus the swap_bytes stuff (yuk).   * and after encryption/decryption. Thus the swap_bytes stuff (yuk).
  */   */
 static void  static void
 swap_bytes(const unsigned char *src, unsigned char *dst, int n)  swap_bytes(const u_char *src, u_char *dst, int n)
 {  {
         char c[4];          char c[4];
   
Line 236 
Line 220 
         }          }
 }  }
   
 void  static void
 blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,  blowfish_ssh1_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
Line 245 
Line 229 
             BF_ENCRYPT);              BF_ENCRYPT);
         swap_bytes(dest, dest, len);          swap_bytes(dest, dest, len);
 }  }
 void  static void
 blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,  blowfish_ssh1_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
Line 256 
Line 240 
 }  }
   
 /* alleged rc4 */  /* alleged rc4 */
 void  static void
 arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)  arcfour_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);          RC4_set_key(&cc->u.rc4, keylen, (u_char *)key);
 }  }
 void  static void
 arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  arcfour_crypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         RC4(&cc->u.rc4, len, (u_char *)src, dest);          RC4(&cc->u.rc4, len, (u_char *)src, dest);
 }  }
   
 /* CAST */  /* CAST */
 void  static void
 cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)  cast_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         CAST_set_key(&cc->u.cast.key, keylen, (unsigned char *) key);          CAST_set_key(&cc->u.cast.key, keylen, (u_char *) key);
 }  }
 void  static void
 cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  cast_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
         if (iv == NULL)          if (iv == NULL)
                 fatal("no IV for %s.", cc->cipher->name);                  fatal("no IV for %s.", cc->cipher->name);
         memcpy(cc->u.cast.iv, (char *)iv, 8);          memcpy(cc->u.cast.iv, (char *)iv, 8);
 }  }
 void  static void
 cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  cast_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,          CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
             CAST_ENCRYPT);              CAST_ENCRYPT);
 }  }
 void  static void
 cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)  cast_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src, u_int len)
 {  {
         CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,          CAST_cbc_encrypt(src, dest, len, &cc->u.cast.key, cc->u.cast.iv,
Line 296 
Line 280 
 /* RIJNDAEL */  /* RIJNDAEL */
   
 #define RIJNDAEL_BLOCKSIZE 16  #define RIJNDAEL_BLOCKSIZE 16
 void  static void
 rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)  rijndael_setkey(CipherContext *cc, const u_char *key, u_int keylen)
 {  {
         rijndael_set_key(&cc->u.rijndael.enc, (u4byte *)key, 8*keylen, 1);          rijndael_set_key(&cc->u.rijndael.enc, (char *)key, 8*keylen, 1);
         rijndael_set_key(&cc->u.rijndael.dec, (u4byte *)key, 8*keylen, 0);          rijndael_set_key(&cc->u.rijndael.dec, (char *)key, 8*keylen, 0);
 }  }
 void  static void
 rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)  rijndael_setiv(CipherContext *cc, const u_char *iv, u_int ivlen)
 {  {
         if (iv == NULL)          if (iv == NULL || ivlen != RIJNDAEL_BLOCKSIZE)
                 fatal("no IV for %s.", cc->cipher->name);                  fatal("bad/no IV for %s.", cc->cipher->name);
         memcpy((u_char *)cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);          memcpy(cc->u.rijndael.iv, iv, RIJNDAEL_BLOCKSIZE);
 }  }
 void  static void
 rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,  rijndael_cbc_encrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
         rijndael_ctx *ctx = &cc->u.rijndael.enc;          rijndael_ctx *ctx = &cc->u.rijndael.enc;
         u4byte *iv = cc->u.rijndael.iv;          u_char *iv = cc->u.rijndael.iv;
         u4byte in[4];          u_char in[RIJNDAEL_BLOCKSIZE];
         u4byte *cprev, *cnow, *plain;          u_char *cprev, *cnow, *plain;
         int i, blocks = len / RIJNDAEL_BLOCKSIZE;          int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
   
         if (len == 0)          if (len == 0)
                 return;                  return;
         if (len % RIJNDAEL_BLOCKSIZE)          if (len % RIJNDAEL_BLOCKSIZE)
                 fatal("rijndael_cbc_encrypt: bad len %d", len);                  fatal("rijndael_cbc_encrypt: bad len %d", len);
         cnow  = (u4byte*) dest;          cnow  = dest;
         plain = (u4byte*) src;          plain = (u_char *) src;
         cprev = iv;          cprev = iv;
         for(i = 0; i < blocks; i++, plain+=4, cnow+=4) {          for (i = 0; i < blocks; i++, plain+=RIJNDAEL_BLOCKSIZE,
                 in[0] = plain[0] ^ cprev[0];              cnow+=RIJNDAEL_BLOCKSIZE) {
                 in[1] = plain[1] ^ cprev[1];                  for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
                 in[2] = plain[2] ^ cprev[2];                          in[j] = plain[j] ^ cprev[j];
                 in[3] = plain[3] ^ cprev[3];  
                 rijndael_encrypt(ctx, in, cnow);                  rijndael_encrypt(ctx, in, cnow);
                 cprev = cnow;                  cprev = cnow;
         }          }
         memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE);          memcpy(iv, cprev, RIJNDAEL_BLOCKSIZE);
 }  }
   static void
 void  
 rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,  rijndael_cbc_decrypt(CipherContext *cc, u_char *dest, const u_char *src,
     u_int len)      u_int len)
 {  {
         rijndael_ctx *ctx = &cc->u.rijndael.dec;          rijndael_ctx *ctx = &cc->u.rijndael.dec;
         u4byte *iv = cc->u.rijndael.iv;          u_char *iv = cc->u.rijndael.iv;
         u4byte ivsaved[4];          u_char ivsaved[RIJNDAEL_BLOCKSIZE];
         u4byte *cnow =  (u4byte*) (src+len-RIJNDAEL_BLOCKSIZE);          u_char *cnow  = (u_char *) (src+len-RIJNDAEL_BLOCKSIZE);
         u4byte *plain = (u4byte*) (dest+len-RIJNDAEL_BLOCKSIZE);          u_char *plain = dest+len-RIJNDAEL_BLOCKSIZE;
         u4byte *ivp;          u_char *ivp;
         int i, blocks = len / RIJNDAEL_BLOCKSIZE;          int i, j, blocks = len / RIJNDAEL_BLOCKSIZE;
   
         if (len == 0)          if (len == 0)
                 return;                  return;
         if (len % RIJNDAEL_BLOCKSIZE)          if (len % RIJNDAEL_BLOCKSIZE)
                 fatal("rijndael_cbc_decrypt: bad len %d", len);                  fatal("rijndael_cbc_decrypt: bad len %d", len);
         memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE);          memcpy(ivsaved, cnow, RIJNDAEL_BLOCKSIZE);
         for(i = blocks; i > 0; i--, cnow-=4, plain-=4) {          for (i = blocks; i > 0; i--, cnow-=RIJNDAEL_BLOCKSIZE,
               plain-=RIJNDAEL_BLOCKSIZE) {
                 rijndael_decrypt(ctx, cnow, plain);                  rijndael_decrypt(ctx, cnow, plain);
                 ivp =  (i == 1) ? iv : cnow-4;                  ivp = (i == 1) ? iv : cnow-RIJNDAEL_BLOCKSIZE;
                 plain[0] ^= ivp[0];                  for (j = 0; j < RIJNDAEL_BLOCKSIZE; j++)
                 plain[1] ^= ivp[1];                          plain[j] ^= ivp[j];
                 plain[2] ^= ivp[2];  
                 plain[3] ^= ivp[3];  
         }          }
         memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE);          memcpy(iv, ivsaved, RIJNDAEL_BLOCKSIZE);
 }  }
Line 425 
Line 408 
                 SSH_CIPHER_SSH2, 16, 32,                  SSH_CIPHER_SSH2, 16, 32,
                 rijndael_setkey, rijndael_setiv,                  rijndael_setkey, rijndael_setiv,
                 rijndael_cbc_encrypt, rijndael_cbc_decrypt },                  rijndael_cbc_encrypt, rijndael_cbc_decrypt },
         { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }          { NULL, SSH_CIPHER_ILLEGAL, 0, 0, NULL, NULL, NULL, NULL }
 };  };
   
 /*--*/  /*--*/
   
 unsigned int  u_int
 cipher_mask_ssh1(int client)  cipher_mask_ssh1(int client)
 {  {
         unsigned int mask = 0;          u_int mask = 0;
         mask |= 1 << SSH_CIPHER_3DES;           /* Mandatory */          mask |= 1 << SSH_CIPHER_3DES;           /* Mandatory */
         mask |= 1 << SSH_CIPHER_BLOWFISH;          mask |= 1 << SSH_CIPHER_BLOWFISH;
         if (client) {          if (client) {
Line 552 
Line 535 
     const char *passphrase)      const char *passphrase)
 {  {
         MD5_CTX md;          MD5_CTX md;
         unsigned char digest[16];          u_char digest[16];
   
         MD5_Init(&md);          MD5_Init(&md);
         MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));          MD5_Update(&md, (const u_char *)passphrase, strlen(passphrase));

Legend:
Removed from v.1.37  
changed lines
  Added in v.1.37.2.5