ice_key.cpp

Go to the documentation of this file.
00001 #ifndef ICE_KEY_IMPLEMENTATION_FILE
00002 #define ICE_KEY_IMPLEMENTATION_FILE
00003 
00004 /*****************************************************************************\
00005 *                                                                             *
00006 *  Name   : ice_key                                                           *
00007 *  Author : Matthew Kwan                                                      *
00008 *  Mods   : Chris Koeritz                                                     *
00009 *                                                                             *
00010 *******************************************************************************
00011 * Copyright (c) 1996-$now By Author.  This program is free software; you can  *
00012 * redistribute it and/or modify it under the terms of the GNU General Public  *
00013 * License as published by the Free Software Foundation; either version 2 of   *
00014 * the License or (at your option) any later version.  This is online at:      *
00015 *     http://www.fsf.org/copyleft/gpl.html                                    *
00016 * Please send any updates to: fred@gruntose.com                               *
00017 \*****************************************************************************/
00018 
00019 #include "ice_key.h"
00020 
00021 #include <basis/byte_array.h>
00022 #include <basis/chaos.h>
00023 #include <basis/function.h>
00024 #include <basis/log_base.h>
00025 #include <basis/mutex.h>
00026 #include <data_struct/static_memory_gremlin.h>
00027 
00028 #include <string.h>
00029 
00030 #undef LOG
00031 #define LOG(s) CLASS_EMERGENCY_LOG(program_wide_logger(), s)
00032 
00033 SAFE_STATIC(mutex, __ice_box_init_lock, )
00034 
00035 /* Structure of a single round subkey */
00036 class ice_subkey
00037 {
00038 public:
00039   unsigned int val[3];
00040 };
00041 
00042 /* The S-boxes. */
00043 static unsigned int ice_sbox[4][1024];
00044 
00045 /* Modulo values for the S-boxes. */
00046 static const int ice_smod[4][4] = 
00047 {
00048   {333, 313, 505, 369},
00049   {379, 375, 319, 391},
00050   {361, 445, 451, 397},
00051   {397, 425, 395, 505}
00052 };
00053 
00054 /* XOR values for the S-boxes. */
00055 static const int ice_sxor[4][4] = 
00056 {
00057   {0x83, 0x85, 0x9b, 0xcd},
00058   {0xcc, 0xa7, 0xad, 0x41},
00059   {0x4b, 0x2e, 0xd4, 0x33},
00060   {0xea, 0xcb, 0x2e, 0x04}
00061 };
00062 
00063 /* Permutation values for the P-box */
00064 static const unsigned int ice_pbox[32] = {
00065     0x00000001, 0x00000080, 0x00000400, 0x00002000,
00066     0x00080000, 0x00200000, 0x01000000, 0x40000000,
00067     0x00000008, 0x00000020, 0x00000100, 0x00004000,
00068     0x00010000, 0x00800000, 0x04000000, 0x20000000,
00069     0x00000004, 0x00000010, 0x00000200, 0x00008000,
00070     0x00020000, 0x00400000, 0x08000000, 0x10000000,
00071     0x00000002, 0x00000040, 0x00000800, 0x00001000,
00072     0x00040000, 0x00100000, 0x02000000, 0x80000000};
00073 
00074 /* The key rotation schedule */
00075 static const int ice_keyrot[16] =
00076 {
00077   0, 1, 2, 3, 2, 1, 3, 0,
00078   1, 3, 2, 0, 3, 1, 0, 2
00079 };
00080 
00081 ice_key::ice_key(int n, bool randomize)
00082 : _key_set(false),
00083   _randomizer(new chaos),
00084   _randomize(randomize)
00085 {
00086   initialize_ice_sboxes();
00087   if (n < 1) n = 1;  // minimum "n" is one, so reset if it's too low.
00088   _size = n;
00089   _rounds = n * 16;
00090   _keysched = new ice_subkey[_rounds];
00091 }
00092 
00093 ice_key::~ice_key()
00094 {
00095   int i, j;
00096 
00097   for (i = 0; i < _rounds; i++)
00098     for (j = 0; j < 3; j++)
00099       _keysched[i].val[j] = 0;
00100 
00101   _rounds = _size = 0;
00102 
00103   delete [] _keysched;
00104 
00105   WHACK(_randomizer);
00106 }
00107 
00108 // 8-bit Galois Field multiplication of a by b, modulo m.  Just like arithmetic
00109 // multiplication, except that additions and subtractions are replaced by XOR.
00110 static int gf_mult(register int a, register int b, register int m)
00111 {
00112   register int res = 0;
00113 
00114   while (b) {
00115     if (b & 1) res ^= a;
00116 
00117     a <<= 1;
00118     b >>= 1;
00119 
00120     if (a >= 256) a ^= m;
00121   }
00122 
00123   return res;
00124 }
00125 
00126 // Galois Field exponentiation.  Raise the base to the power of 7, modulo m.
00127 static int gf_exp7(register int b, int m)
00128 {
00129   register int x;
00130 
00131   if (b == 0) return 0;
00132 
00133   x = gf_mult(b, b, m);
00134   x = gf_mult(b, x, m);
00135   x = gf_mult(x, x, m);
00136   return gf_mult(b, x, m);
00137 }
00138 
00139 // Carry out the ICE 32-bit P-box permutation.
00140 static unsigned int ice_perm32(register unsigned int x)
00141 {
00142   register unsigned int res = 0;
00143   register const unsigned int *pbox = ice_pbox;
00144 
00145   while (x) {
00146     if (x & 1) res |= *pbox;
00147     pbox++;
00148     x >>= 1;
00149   }
00150 
00151   return res;
00152 }
00153 
00154 void ice_key::initialize_ice_sboxes()
00155 {
00156   auto_synchronizer l(__ice_box_init_lock());
00157     // ensure that we don't allow our static blobs to be scrambled by
00158     // multiple threads hitting the following code at the same time.
00159   static bool ice_sboxes_initialized = false;
00160     // if we haven't done it before, then we need to do it.  otherwise we do
00161     // nothing.
00162   if (ice_sboxes_initialized) return;  // get out if we already did it.
00163 
00164   register int i;
00165   for (i = 0; i < 1024; i++) {
00166     int col = (i >> 1) & 0xff;
00167     int row = (i & 0x1) | ((i & 0x200) >> 8);
00168     unsigned int x;
00169 
00170     x = gf_exp7(col ^ ice_sxor[0][row], ice_smod[0][row]) << 24;
00171     ice_sbox[0][i] = ice_perm32(x);
00172 
00173     x = gf_exp7(col ^ ice_sxor[1][row], ice_smod[1][row]) << 16;
00174     ice_sbox[1][i] = ice_perm32(x);
00175 
00176     x = gf_exp7(col ^ ice_sxor[2][row], ice_smod[2][row]) << 8;
00177     ice_sbox[2][i] = ice_perm32(x);
00178 
00179     x = gf_exp7(col ^ ice_sxor[3][row], ice_smod[3][row]);
00180     ice_sbox[3][i] = ice_perm32(x);
00181   }
00182 
00183   ice_sboxes_initialized = true;  // now record we've done it.
00184 }
00185 
00186 // The single round ICE f function.
00187 static unsigned int ice_f(register unsigned int p, const ice_subkey *sk)
00188 {
00189   unsigned int tl, tr;    /* Expanded 40-bit values */
00190   unsigned int al, ar;    /* Salted expanded 40-bit values */
00191 
00192   /* Left half expansion */
00193   tl = ((p >> 16) & 0x3ff) | (((p >> 14) | (p << 18)) & 0xffc00);
00194 
00195   /* Right half expansion */
00196   tr = (p & 0x3ff) | ((p << 2) & 0xffc00);
00197 
00198   /* Perform the salt permutation */
00199   // al = (tr & sk->val[2]) | (tl & ~sk->val[2]);
00200   // ar = (tl & sk->val[2]) | (tr & ~sk->val[2]);
00201   al = sk->val[2] & (tl ^ tr);
00202   ar = al ^ tr;
00203   al ^= tl;
00204 
00205   al ^= sk->val[0];    /* XOR with the subkey */
00206   ar ^= sk->val[1];
00207 
00208   /* S-box lookup and permutation */
00209   return ice_sbox[0][al >> 10] | ice_sbox[1][al & 0x3ff]
00210       | ice_sbox[2][ar >> 10] | ice_sbox[3][ar & 0x3ff];
00211 }
00212 
00213 byte_array ice_key::int_to_bytes(u_int to_encode) const
00214 {
00215   byte_array to_return;
00216   for (int i = 0; i < 4; i++) {
00217     to_return += to_encode % 0x100;
00218     to_encode = to_encode >> 8;
00219   }
00220   return to_return;
00221 }
00222 
00223 u_int ice_key::bytes_to_int(const byte_array &to_decode) const
00224 {
00225   u_int to_return = 0;
00226   for (int i = 3; i >= 0; i--) {
00227     to_return = to_return << 8;
00228     to_return += to_decode[i];
00229   }
00230   return to_return;
00231 }
00232 
00233 bool ice_key::encrypt(const byte_array &ptext, byte_array &ctext) const
00234 {
00235   ctext.reset();
00236   if (!_key_set) return false;
00237   if (!ptext.length()) return false;
00238   byte_array to_encode(int_to_bytes(u_int(ptext.length())));
00239   to_encode += ptext;
00240   // check whether the length is divisible by eight.  if not, pad the array.
00241   int leftover = to_encode.length() % 8;
00242   if (leftover) {
00243     for (int i = 0; i < 8 - leftover; i++) {
00244       if (_randomize)
00245         to_encode += byte(_randomizer->inclusive(0, 255));
00246       else
00247         to_encode += 0;
00248     }
00249   }
00250   ctext.reset(to_encode.length());
00251   for (int i = 0; i < to_encode.length(); i += 8) {
00252     code_granule eight_in;
00253     code_granule eight_out;
00254     memory_assign(eight_in, &to_encode[i], 8);
00255     encrypt_eight(eight_in, eight_out);
00256     ctext.overwrite(i, byte_array(8, eight_out), 8);
00257   }
00258   return true;
00259 }
00260 
00261 bool ice_key::decrypt(const byte_array &ctext, byte_array &ptext) const
00262 {
00263   ptext.reset();
00264   if (!_key_set) return false;
00265   if (!ctext.length()) return false;
00266   byte_array decoded(ctext.length());
00267   for (int i = 0; i < ctext.length(); i += 8) {
00268     code_granule eight_in;
00269     code_granule eight_out;
00270     int j;
00271     for (j = 0; j < 8; j++) {
00272       eight_in[j] = (i + j < ctext.length())? ctext[i + j] : 0;
00273     }
00274 
00275     decrypt_eight(eight_in, eight_out);
00276     decoded.overwrite(i, byte_array(8, eight_out), 8);
00277   }
00278 
00279   // now reclaim the original length.
00280   byte_array length_bytes = decoded.subarray(0, 3);
00281   decoded.zap(0, 3);
00282   int original_length = int(bytes_to_int(length_bytes));
00283   if (original_length != decoded.length())
00284     decoded.zap(original_length, decoded.length() - 1);
00285   ptext = decoded;
00286   return true;
00287 }
00288 
00289 void ice_key::encrypt_eight(const code_granule &ptext,
00290     code_granule &ctext) const
00291 {
00292   register int i;
00293   register unsigned int l, r;
00294 
00295   l = (ptext[0] << 24) | (ptext[1] << 16) | (ptext[2] << 8) | ptext[3];
00296   r = (ptext[4] << 24) | (ptext[5] << 16) | (ptext[6] << 8) | ptext[7];
00297 
00298   for (i = 0; i < _rounds; i += 2) {
00299     l ^= ice_f(r, &_keysched[i]);
00300     r ^= ice_f(l, &_keysched[i + 1]);
00301   }
00302 
00303   for (i = 0; i < 4; i++) {
00304     ctext[3 - i] = byte(r & 0xff);
00305     ctext[7 - i] = byte(l & 0xff);
00306 
00307     r >>= 8;
00308     l >>= 8;
00309   }
00310 }
00311 
00312 void ice_key::decrypt_eight(const code_granule &ctext,
00313     code_granule &ptext) const
00314 {
00315   register int i;
00316   register unsigned int l, r;
00317 
00318   l = (ctext[0] << 24) | (ctext[1] << 16) | (ctext[2] << 8) | ctext[3];
00319   r = (ctext[4] << 24) | (ctext[5] << 16) | (ctext[6] << 8) | ctext[7];
00320 
00321   for (i = _rounds - 1; i > 0; i -= 2) {
00322     l ^= ice_f(r, &_keysched[i]);
00323     r ^= ice_f(l, &_keysched[i - 1]);
00324   }
00325 
00326   for (i = 0; i < 4; i++) {
00327     ptext[3 - i] = byte(r & 0xff);
00328     ptext[7 - i] = byte(l & 0xff);
00329 
00330     r >>= 8;
00331     l >>= 8;
00332   }
00333 }
00334 
00335 void ice_key::schedule_build(u_short *kb, int n, const int *keyrot)
00336 {
00337   int i;
00338 
00339   for (i = 0; i < 8; i++) {
00340     register int j;
00341     register int kr = keyrot[i];
00342     ice_subkey *isk = &_keysched[n + i];
00343 
00344     for (j = 0; j < 3; j++) isk->val[j] = 0;
00345 
00346     for (j = 0; j < 15; j++) {
00347       register int k;
00348       unsigned int *curr_sk = &isk->val[j % 3];
00349 
00350       for (k = 0; k < 4; k++) {
00351         unsigned short *curr_kb = &kb[(kr + k) & 3];
00352         register int bit = *curr_kb & 1;
00353 
00354         *curr_sk = (*curr_sk << 1) | bit;
00355         *curr_kb = (*curr_kb >> 1) | ((bit ^ 1) << 15);
00356       }
00357     }
00358   }
00359 }
00360 
00361 bool ice_key::set(const byte_array &key)
00362 {
00363   FUNCDEF("set");
00364   int i;
00365   if (key.length() != _size * 8) {
00366     LOG("failure in key size; it is not the block size times 8.");
00367     return false;
00368   }
00369 
00370   _key_set = true;
00371 
00372   if (_rounds == 8) {
00373     unsigned short kb[4];
00374 
00375     for (i = 0; i < 4; i++)
00376       kb[3 - i] = (key[i*2] << 8) | key[i*2 + 1];
00377 
00378     schedule_build(kb, 0, ice_keyrot);
00379     return true;
00380   }
00381 
00382   for (i = 0; i < _size; i++) {
00383     int j;
00384     unsigned short kb[4];
00385 
00386     for (j = 0; j < 4; j++)
00387       kb[3 - j] = (key[i*8 + j*2] << 8) | key[i*8 + j*2 + 1];
00388 
00389     schedule_build(kb, i*8, ice_keyrot);
00390     schedule_build(kb, _rounds - 8 - i*8, &ice_keyrot[8]);
00391   }
00392   return true;
00393 }
00394 
00395 
00396 #endif //ICE_KEY_IMPLEMENTATION_FILE
00397 

Generated on Sat Aug 30 04:31:43 2008 for HOOPLE Libraries by  doxygen 1.5.1