diff libtomcrypt/src/ciphers/rc2.c @ 1471:6dba84798cd5

Update to libtomcrypt 1.18.1, merged with Dropbear changes
author Matt Johnston <matt@ucc.asn.au>
date Fri, 09 Feb 2018 21:44:05 +0800
parents f849a5ca2efc
children
line wrap: on
line diff
--- a/libtomcrypt/src/ciphers/rc2.c	Thu Feb 08 23:11:40 2018 +0800
+++ b/libtomcrypt/src/ciphers/rc2.c	Fri Feb 09 21:44:05 2018 +0800
@@ -5,8 +5,6 @@
  *
  * The library is free for all purposes without any express
  * guarantee it works.
- *
- * Tom St Denis, [email protected], http://libtom.org
  */
 /**********************************************************************\
 * To commemorate the 1996 RSA Data Security Conference, the following  *
@@ -18,12 +16,12 @@
 * Thanks to CodeView, SoftIce, and D86 for helping bring this code to  *
 * the public.                                                          *
 \**********************************************************************/
-#include <tomcrypt.h>
+#include "tomcrypt.h"
 
 /**
   @file rc2.c
-  Implementation of LTC_RC2
-*/  
+  Implementation of RC2 with fixed effective key length of 64bits
+*/
 
 #ifdef LTC_RC2
 
@@ -36,7 +34,7 @@
    &rc2_test,
    &rc2_done,
    &rc2_keysize,
-   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
 };
 
 /* 256-entry permutation table, probably derived somehow from pi */
@@ -60,68 +58,87 @@
 };
 
  /**
-    Initialize the LTC_RC2 block cipher
+    Initialize the RC2 block cipher
     @param key The symmetric key you wish to pass
     @param keylen The key length in bytes
+    @param bits The effective key length in bits
     @param num_rounds The number of rounds desired (0 for default)
     @param skey The key in as scheduled by this function.
     @return CRYPT_OK if successful
  */
-int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+int rc2_setup_ex(const unsigned char *key, int keylen, int bits, int num_rounds, symmetric_key *skey)
 {
    unsigned *xkey = skey->rc2.xkey;
    unsigned char tmp[128];
    unsigned T8, TM;
-   int i, bits;
+   int i;
 
    LTC_ARGCHK(key  != NULL);
    LTC_ARGCHK(skey != NULL);
 
-   if (keylen < 8 || keylen > 128) {
+   if (keylen == 0 || keylen > 128 || bits > 1024) {
       return CRYPT_INVALID_KEYSIZE;
    }
+   if (bits == 0) {
+      bits = 1024;
+   }
 
    if (num_rounds != 0 && num_rounds != 16) {
       return CRYPT_INVALID_ROUNDS;
    }
 
    for (i = 0; i < keylen; i++) {
-       tmp[i] = key[i] & 255;
+      tmp[i] = key[i] & 255;
+   }
+
+   /* Phase 1: Expand input key to 128 bytes */
+   if (keylen < 128) {
+      for (i = keylen; i < 128; i++) {
+         tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
+      }
+   }
+
+   /* Phase 2 - reduce effective key size to "bits" */
+   T8   = (unsigned)(bits+7)>>3;
+   TM   = (255 >> (unsigned)(7 & -bits));
+   tmp[128 - T8] = permute[tmp[128 - T8] & TM];
+   for (i = 127 - T8; i >= 0; i--) {
+      tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
    }
 
-    /* Phase 1: Expand input key to 128 bytes */
-    if (keylen < 128) {
-        for (i = keylen; i < 128; i++) {
-            tmp[i] = permute[(tmp[i - 1] + tmp[i - keylen]) & 255];
-        }
-    }
-    
-    /* Phase 2 - reduce effective key size to "bits" */
-    bits = keylen<<3;
-    T8   = (unsigned)(bits+7)>>3;
-    TM   = (255 >> (unsigned)(7 & -bits));
-    tmp[128 - T8] = permute[tmp[128 - T8] & TM];
-    for (i = 127 - T8; i >= 0; i--) {
-        tmp[i] = permute[tmp[i + 1] ^ tmp[i + T8]];
-    }
-
-    /* Phase 3 - copy to xkey in little-endian order */
-    for (i = 0; i < 64; i++) {
-        xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
-    }        
+   /* Phase 3 - copy to xkey in little-endian order */
+   for (i = 0; i < 64; i++) {
+      xkey[i] =  (unsigned)tmp[2*i] + ((unsigned)tmp[2*i+1] << 8);
+   }
 
 #ifdef LTC_CLEAN_STACK
-    zeromem(tmp, sizeof(tmp));
+   zeromem(tmp, sizeof(tmp));
 #endif
-    
-    return CRYPT_OK;
+
+   return CRYPT_OK;
+}
+
+/**
+   Initialize the RC2 block cipher
+
+     The effective key length is here always keylen * 8
+
+   @param key The symmetric key you wish to pass
+   @param keylen The key length in bytes
+   @param num_rounds The number of rounds desired (0 for default)
+   @param skey The key in as scheduled by this function.
+   @return CRYPT_OK if successful
+*/
+int rc2_setup(const unsigned char *key, int keylen, int num_rounds, symmetric_key *skey)
+{
+   return rc2_setup_ex(key, keylen, keylen * 8, num_rounds, skey);
 }
 
 /**********************************************************************\
 * Encrypt an 8-byte block of plaintext using the given key.            *
 \**********************************************************************/
 /**
-  Encrypts a block of text with LTC_RC2
+  Encrypts a block of text with RC2
   @param pt The input plaintext (8 bytes)
   @param ct The output ciphertext (8 bytes)
   @param skey The key as scheduled
@@ -180,7 +197,7 @@
     ct[5] = (unsigned char)(x54 >> 8);
     ct[6] = (unsigned char)x76;
     ct[7] = (unsigned char)(x76 >> 8);
- 
+
     return CRYPT_OK;
 }
 
@@ -199,10 +216,10 @@
 * Decrypt an 8-byte block of ciphertext using the given key.           *
 \**********************************************************************/
 /**
-  Decrypts a block of text with LTC_RC2
+  Decrypts a block of text with RC2
   @param ct The input ciphertext (8 bytes)
   @param pt The output plaintext (8 bytes)
-  @param skey The key as scheduled 
+  @param skey The key as scheduled
   @return CRYPT_OK if successful
 */
 #ifdef LTC_CLEAN_STACK
@@ -275,27 +292,56 @@
 #endif
 
 /**
-  Performs a self-test of the LTC_RC2 block cipher
+  Performs a self-test of the RC2 block cipher
   @return CRYPT_OK if functional, CRYPT_NOP if self-test has been disabled
 */
 int rc2_test(void)
 {
  #ifndef LTC_TEST
     return CRYPT_NOP;
- #else    
+ #else
    static const struct {
-        int keylen;
+        int keylen, bits;
         unsigned char key[16], pt[8], ct[8];
    } tests[] = {
 
-   { 8,
+   { 8, 63,
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0xeb, 0xb7, 0x73, 0xf9, 0x93, 0x27, 0x8e, 0xff }
+   },
+   { 8, 64,
+     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
+     { 0x27, 0x8b, 0x27, 0xe4, 0x2e, 0x2f, 0x0d, 0x49 }
+   },
+   { 8, 64,
      { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
      { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 },
      { 0x30, 0x64, 0x9e, 0xdf, 0x9b, 0xe7, 0xd2, 0xc2 }
-
+   },
+   { 1, 64,
+     { 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x61, 0xa8, 0xa2, 0x44, 0xad, 0xac, 0xcc, 0xf0 }
    },
-   { 16,
+   { 7, 64,
+     { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x00,
+       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x6c, 0xcf, 0x43, 0x08, 0x97, 0x4c, 0x26, 0x7f }
+   },
+   { 16, 64,
+     { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
+       0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
+     { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
+     { 0x1a, 0x80, 0x7d, 0x27, 0x2b, 0xbe, 0x5d, 0xb1 }
+   },
+   { 16, 128,
      { 0x88, 0xbc, 0xa9, 0x0e, 0x90, 0x87, 0x5a, 0x7f,
        0x0f, 0x79, 0xc3, 0x84, 0x62, 0x7b, 0xaf, 0xb2 },
      { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
@@ -308,14 +354,22 @@
 
     for (x = 0; x < (int)(sizeof(tests) / sizeof(tests[0])); x++) {
         zeromem(tmp, sizeof(tmp));
-        if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
-           return err;
+        if (tests[x].bits == (tests[x].keylen * 8)) {
+           if ((err = rc2_setup(tests[x].key, tests[x].keylen, 0, &skey)) != CRYPT_OK) {
+              return err;
+           }
         }
-        
+        else {
+           if ((err = rc2_setup_ex(tests[x].key, tests[x].keylen, tests[x].bits, 0, &skey)) != CRYPT_OK) {
+              return err;
+           }
+        }
+
         rc2_ecb_encrypt(tests[x].pt, tmp[0], &skey);
         rc2_ecb_decrypt(tmp[0], tmp[1], &skey);
-        
-        if (XMEMCMP(tmp[0], tests[x].ct, 8) != 0 || XMEMCMP(tmp[1], tests[x].pt, 8) != 0) {
+
+        if (compare_testvector(tmp[0], 8, tests[x].ct, 8, "RC2 CT", x) ||
+              compare_testvector(tmp[1], 8, tests[x].pt, 8, "RC2 PT", x)) {
            return CRYPT_FAIL_TESTVECTOR;
         }
 
@@ -329,11 +383,12 @@
    #endif
 }
 
-/** Terminate the context 
+/** Terminate the context
    @param skey    The scheduled key
 */
 void rc2_done(symmetric_key *skey)
 {
+  LTC_UNUSED_PARAM(skey);
 }
 
 /**
@@ -344,7 +399,7 @@
 int rc2_keysize(int *keysize)
 {
    LTC_ARGCHK(keysize != NULL);
-   if (*keysize < 8) {
+   if (*keysize < 1) {
        return CRYPT_INVALID_KEYSIZE;
    } else if (*keysize > 128) {
        *keysize = 128;
@@ -357,6 +412,6 @@
 
 
 
-/* $Source$ */
-/* $Revision$ */
-/* $Date$ */
+/* ref:         $Format:%D$ */
+/* git commit:  $Format:%H$ */
+/* commit time: $Format:%ai$ */