CyaSSL is an SSL library for devices like mbed.

Dependents:   cyassl-client Sync

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers des3.c Source File

des3.c

00001 /* des3.c
00002  *
00003  * Copyright (C) 2006-2009 Sawtooth Consulting Ltd.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00020  */
00021 
00022 
00023 #ifndef NO_DES3
00024 
00025 #include "des3.h"
00026 #ifdef NO_INLINE
00027     #include "misc.h"
00028 #else
00029     #include "misc.c"
00030 #endif
00031 
00032 
00033 /* permuted choice table (key) */
00034 static const byte pc1[] = {
00035        57, 49, 41, 33, 25, 17,  9,
00036         1, 58, 50, 42, 34, 26, 18,
00037        10,  2, 59, 51, 43, 35, 27,
00038        19, 11,  3, 60, 52, 44, 36,
00039 
00040        63, 55, 47, 39, 31, 23, 15,
00041         7, 62, 54, 46, 38, 30, 22,
00042        14,  6, 61, 53, 45, 37, 29,
00043        21, 13,  5, 28, 20, 12,  4
00044 };
00045 
00046 /* number left rotations of pc1 */
00047 static const byte totrot[] = {
00048        1,2,4,6,8,10,12,14,15,17,19,21,23,25,27,28
00049 };
00050 
00051 /* permuted choice key (table) */
00052 static const byte pc2[] = {
00053        14, 17, 11, 24,  1,  5,
00054         3, 28, 15,  6, 21, 10,
00055        23, 19, 12,  4, 26,  8,
00056        16,  7, 27, 20, 13,  2,
00057        41, 52, 31, 37, 47, 55,
00058        30, 40, 51, 45, 33, 48,
00059        44, 49, 39, 56, 34, 53,
00060        46, 42, 50, 36, 29, 32
00061 };
00062 
00063 /* End of DES-defined tables */
00064 
00065 /* bit 0 is left-most in byte */
00066 static const int bytebit[] = {
00067        0200,0100,040,020,010,04,02,01
00068 };
00069 
00070 const word32 Spbox[8][64] = {
00071 {
00072 0x01010400,0x00000000,0x00010000,0x01010404,
00073 0x01010004,0x00010404,0x00000004,0x00010000,
00074 0x00000400,0x01010400,0x01010404,0x00000400,
00075 0x01000404,0x01010004,0x01000000,0x00000004,
00076 0x00000404,0x01000400,0x01000400,0x00010400,
00077 0x00010400,0x01010000,0x01010000,0x01000404,
00078 0x00010004,0x01000004,0x01000004,0x00010004,
00079 0x00000000,0x00000404,0x00010404,0x01000000,
00080 0x00010000,0x01010404,0x00000004,0x01010000,
00081 0x01010400,0x01000000,0x01000000,0x00000400,
00082 0x01010004,0x00010000,0x00010400,0x01000004,
00083 0x00000400,0x00000004,0x01000404,0x00010404,
00084 0x01010404,0x00010004,0x01010000,0x01000404,
00085 0x01000004,0x00000404,0x00010404,0x01010400,
00086 0x00000404,0x01000400,0x01000400,0x00000000,
00087 0x00010004,0x00010400,0x00000000,0x01010004},
00088 {
00089 0x80108020,0x80008000,0x00008000,0x00108020,
00090 0x00100000,0x00000020,0x80100020,0x80008020,
00091 0x80000020,0x80108020,0x80108000,0x80000000,
00092 0x80008000,0x00100000,0x00000020,0x80100020,
00093 0x00108000,0x00100020,0x80008020,0x00000000,
00094 0x80000000,0x00008000,0x00108020,0x80100000,
00095 0x00100020,0x80000020,0x00000000,0x00108000,
00096 0x00008020,0x80108000,0x80100000,0x00008020,
00097 0x00000000,0x00108020,0x80100020,0x00100000,
00098 0x80008020,0x80100000,0x80108000,0x00008000,
00099 0x80100000,0x80008000,0x00000020,0x80108020,
00100 0x00108020,0x00000020,0x00008000,0x80000000,
00101 0x00008020,0x80108000,0x00100000,0x80000020,
00102 0x00100020,0x80008020,0x80000020,0x00100020,
00103 0x00108000,0x00000000,0x80008000,0x00008020,
00104 0x80000000,0x80100020,0x80108020,0x00108000},
00105 {
00106 0x00000208,0x08020200,0x00000000,0x08020008,
00107 0x08000200,0x00000000,0x00020208,0x08000200,
00108 0x00020008,0x08000008,0x08000008,0x00020000,
00109 0x08020208,0x00020008,0x08020000,0x00000208,
00110 0x08000000,0x00000008,0x08020200,0x00000200,
00111 0x00020200,0x08020000,0x08020008,0x00020208,
00112 0x08000208,0x00020200,0x00020000,0x08000208,
00113 0x00000008,0x08020208,0x00000200,0x08000000,
00114 0x08020200,0x08000000,0x00020008,0x00000208,
00115 0x00020000,0x08020200,0x08000200,0x00000000,
00116 0x00000200,0x00020008,0x08020208,0x08000200,
00117 0x08000008,0x00000200,0x00000000,0x08020008,
00118 0x08000208,0x00020000,0x08000000,0x08020208,
00119 0x00000008,0x00020208,0x00020200,0x08000008,
00120 0x08020000,0x08000208,0x00000208,0x08020000,
00121 0x00020208,0x00000008,0x08020008,0x00020200},
00122 {
00123 0x00802001,0x00002081,0x00002081,0x00000080,
00124 0x00802080,0x00800081,0x00800001,0x00002001,
00125 0x00000000,0x00802000,0x00802000,0x00802081,
00126 0x00000081,0x00000000,0x00800080,0x00800001,
00127 0x00000001,0x00002000,0x00800000,0x00802001,
00128 0x00000080,0x00800000,0x00002001,0x00002080,
00129 0x00800081,0x00000001,0x00002080,0x00800080,
00130 0x00002000,0x00802080,0x00802081,0x00000081,
00131 0x00800080,0x00800001,0x00802000,0x00802081,
00132 0x00000081,0x00000000,0x00000000,0x00802000,
00133 0x00002080,0x00800080,0x00800081,0x00000001,
00134 0x00802001,0x00002081,0x00002081,0x00000080,
00135 0x00802081,0x00000081,0x00000001,0x00002000,
00136 0x00800001,0x00002001,0x00802080,0x00800081,
00137 0x00002001,0x00002080,0x00800000,0x00802001,
00138 0x00000080,0x00800000,0x00002000,0x00802080},
00139 {
00140 0x00000100,0x02080100,0x02080000,0x42000100,
00141 0x00080000,0x00000100,0x40000000,0x02080000,
00142 0x40080100,0x00080000,0x02000100,0x40080100,
00143 0x42000100,0x42080000,0x00080100,0x40000000,
00144 0x02000000,0x40080000,0x40080000,0x00000000,
00145 0x40000100,0x42080100,0x42080100,0x02000100,
00146 0x42080000,0x40000100,0x00000000,0x42000000,
00147 0x02080100,0x02000000,0x42000000,0x00080100,
00148 0x00080000,0x42000100,0x00000100,0x02000000,
00149 0x40000000,0x02080000,0x42000100,0x40080100,
00150 0x02000100,0x40000000,0x42080000,0x02080100,
00151 0x40080100,0x00000100,0x02000000,0x42080000,
00152 0x42080100,0x00080100,0x42000000,0x42080100,
00153 0x02080000,0x00000000,0x40080000,0x42000000,
00154 0x00080100,0x02000100,0x40000100,0x00080000,
00155 0x00000000,0x40080000,0x02080100,0x40000100},
00156 {
00157 0x20000010,0x20400000,0x00004000,0x20404010,
00158 0x20400000,0x00000010,0x20404010,0x00400000,
00159 0x20004000,0x00404010,0x00400000,0x20000010,
00160 0x00400010,0x20004000,0x20000000,0x00004010,
00161 0x00000000,0x00400010,0x20004010,0x00004000,
00162 0x00404000,0x20004010,0x00000010,0x20400010,
00163 0x20400010,0x00000000,0x00404010,0x20404000,
00164 0x00004010,0x00404000,0x20404000,0x20000000,
00165 0x20004000,0x00000010,0x20400010,0x00404000,
00166 0x20404010,0x00400000,0x00004010,0x20000010,
00167 0x00400000,0x20004000,0x20000000,0x00004010,
00168 0x20000010,0x20404010,0x00404000,0x20400000,
00169 0x00404010,0x20404000,0x00000000,0x20400010,
00170 0x00000010,0x00004000,0x20400000,0x00404010,
00171 0x00004000,0x00400010,0x20004010,0x00000000,
00172 0x20404000,0x20000000,0x00400010,0x20004010},
00173 {
00174 0x00200000,0x04200002,0x04000802,0x00000000,
00175 0x00000800,0x04000802,0x00200802,0x04200800,
00176 0x04200802,0x00200000,0x00000000,0x04000002,
00177 0x00000002,0x04000000,0x04200002,0x00000802,
00178 0x04000800,0x00200802,0x00200002,0x04000800,
00179 0x04000002,0x04200000,0x04200800,0x00200002,
00180 0x04200000,0x00000800,0x00000802,0x04200802,
00181 0x00200800,0x00000002,0x04000000,0x00200800,
00182 0x04000000,0x00200800,0x00200000,0x04000802,
00183 0x04000802,0x04200002,0x04200002,0x00000002,
00184 0x00200002,0x04000000,0x04000800,0x00200000,
00185 0x04200800,0x00000802,0x00200802,0x04200800,
00186 0x00000802,0x04000002,0x04200802,0x04200000,
00187 0x00200800,0x00000000,0x00000002,0x04200802,
00188 0x00000000,0x00200802,0x04200000,0x00000800,
00189 0x04000002,0x04000800,0x00000800,0x00200002},
00190 {
00191 0x10001040,0x00001000,0x00040000,0x10041040,
00192 0x10000000,0x10001040,0x00000040,0x10000000,
00193 0x00040040,0x10040000,0x10041040,0x00041000,
00194 0x10041000,0x00041040,0x00001000,0x00000040,
00195 0x10040000,0x10000040,0x10001000,0x00001040,
00196 0x00041000,0x00040040,0x10040040,0x10041000,
00197 0x00001040,0x00000000,0x00000000,0x10040040,
00198 0x10000040,0x10001000,0x00041040,0x00040000,
00199 0x00041040,0x00040000,0x10041000,0x00001000,
00200 0x00000040,0x10040040,0x00001000,0x00041040,
00201 0x10001000,0x00000040,0x10000040,0x10040000,
00202 0x10040040,0x10000000,0x00040000,0x10001040,
00203 0x00000000,0x10041040,0x00040040,0x10000040,
00204 0x10040000,0x10001000,0x10001040,0x00000000,
00205 0x10041040,0x00041000,0x00041000,0x00001040,
00206 0x00001040,0x00040040,0x10000000,0x10041000}
00207 };
00208 
00209 
00210 static INLINE void IPERM(word32* left, word32* right)
00211 {
00212     word32 work;
00213 
00214     *right = rotlFixed(*right, 4U);
00215     work = (*left ^ *right) & 0xf0f0f0f0;
00216     *left ^= work;
00217 
00218     *right = rotrFixed(*right^work, 20U);
00219     work = (*left ^ *right) & 0xffff0000;
00220     *left ^= work;
00221 
00222     *right = rotrFixed(*right^work, 18U);
00223     work = (*left ^ *right) & 0x33333333;
00224     *left ^= work;
00225 
00226     *right = rotrFixed(*right^work, 6U);
00227     work = (*left ^ *right) & 0x00ff00ff;
00228     *left ^= work;
00229 
00230     *right = rotlFixed(*right^work, 9U);
00231     work = (*left ^ *right) & 0xaaaaaaaa;
00232     *left = rotlFixed(*left^work, 1U);
00233     *right ^= work;
00234 }
00235 
00236 
00237 static INLINE void FPERM(word32* left, word32* right)
00238 {
00239     word32 work;
00240 
00241     *right = rotrFixed(*right, 1U);
00242     work = (*left ^ *right) & 0xaaaaaaaa;
00243     *right ^= work;
00244 
00245     *left = rotrFixed(*left^work, 9U);
00246     work = (*left ^ *right) & 0x00ff00ff;
00247     *right ^= work;
00248 
00249     *left = rotlFixed(*left^work, 6U);
00250     work = (*left ^ *right) & 0x33333333;
00251     *right ^= work;
00252 
00253     *left = rotlFixed(*left^work, 18U);
00254     work = (*left ^ *right) & 0xffff0000;
00255     *right ^= work;
00256 
00257     *left = rotlFixed(*left^work, 20U);
00258     work = (*left ^ *right) & 0xf0f0f0f0;
00259     *right ^= work;
00260 
00261     *left = rotrFixed(*left^work, 4U);
00262 }
00263 
00264 
00265 static void DesSetKey(const byte* key, int dir, word32* out)
00266 {
00267     byte buffer[56+56+8];
00268     byte *const pc1m = buffer;                 /* place to modify pc1 into */
00269     byte *const pcr = pc1m + 56;               /* place to rotate pc1 into */
00270     byte *const ks = pcr + 56;
00271     register int i,j,l;
00272     int m;
00273 
00274     for (j = 0; j < 56; j++) {          /* convert pc1 to bits of key */
00275         l = pc1[j] - 1;                 /* integer bit location  */
00276         m = l & 07;                     /* find bit              */
00277         pc1m[j] = (key[l >> 3] &        /* find which key byte l is in */
00278             bytebit[m])                 /* and which bit of that byte */
00279             ? 1 : 0;                    /* and store 1-bit result */
00280     }
00281     for (i = 0; i < 16; i++) {          /* key chunk for each iteration */
00282         XMEMSET(ks, 0, 8);               /* Clear key schedule */
00283         for (j = 0; j < 56; j++)        /* rotate pc1 the right amount */
00284             pcr[j] = pc1m[(l = j + totrot[i]) < (j < 28 ? 28 : 56) ? l: l-28];
00285         /* rotate left and right halves independently */
00286         for (j = 0; j < 48; j++){   /* select bits individually */
00287             /* check bit that goes to ks[j] */
00288             if (pcr[pc2[j] - 1]){
00289                 /* mask it in if it's there */
00290                 l= j % 6;
00291                 ks[j/6] |= bytebit[l] >> 2;
00292             }
00293         }
00294         /* Now convert to odd/even interleaved form for use in F */
00295         out[2*i] = ((word32)ks[0] << 24)
00296             | ((word32)ks[2] << 16)
00297             | ((word32)ks[4] << 8)
00298             | ((word32)ks[6]);
00299         out[2*i + 1] = ((word32)ks[1] << 24)
00300             | ((word32)ks[3] << 16)
00301             | ((word32)ks[5] << 8)
00302             | ((word32)ks[7]);
00303     }
00304     
00305     /* reverse key schedule order */
00306     if (dir == DES_DECRYPTION)
00307         for (i = 0; i < 16; i += 2) {
00308             word32 swap = out[i];
00309             out[i] = out[DES_KS_SIZE - 2 - i];
00310             out[DES_KS_SIZE - 2 - i] = swap;
00311 
00312             swap = out[i + 1];
00313             out[i + 1] = out[DES_KS_SIZE - 1 - i];
00314             out[DES_KS_SIZE - 1 - i] = swap;
00315         }
00316    
00317 }
00318 
00319 
00320 static INLINE int Reverse(int dir)
00321 {
00322     return !dir;
00323 }
00324 
00325 
00326 void Des_SetKey(Des* des, const byte* key, const byte* iv, int dir)
00327 {
00328     DesSetKey(key, dir, des->key);
00329     
00330     XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
00331 }
00332 
00333 
00334 void Des3_SetKey(Des3* des, const byte* key, const byte* iv, int dir)
00335 {
00336     DesSetKey(key + (dir == DES_ENCRYPTION ? 0 : 16), dir, des->key[0]);
00337     DesSetKey(key + 8, Reverse(dir), des->key[1]);
00338     DesSetKey(key + (dir == DES_DECRYPTION ? 0 : 16), dir, des->key[2]);
00339     
00340     XMEMCPY(des->reg, iv, DES_BLOCK_SIZE);
00341 }
00342 
00343 
00344 void DesRawProcessBlock(word32* lIn, word32* rIn, const word32* kptr)
00345 {
00346     word32 l = *lIn, r = *rIn, i;
00347 
00348     for (i=0; i<8; i++)
00349     {
00350         word32 work = rotrFixed(r, 4U) ^ kptr[4*i+0];
00351         l ^= Spbox[6][(work) & 0x3f]
00352           ^  Spbox[4][(work >> 8) & 0x3f]
00353           ^  Spbox[2][(work >> 16) & 0x3f]
00354           ^  Spbox[0][(work >> 24) & 0x3f];
00355         work = r ^ kptr[4*i+1];
00356         l ^= Spbox[7][(work) & 0x3f]
00357           ^  Spbox[5][(work >> 8) & 0x3f]
00358           ^  Spbox[3][(work >> 16) & 0x3f]
00359           ^  Spbox[1][(work >> 24) & 0x3f];
00360 
00361         work = rotrFixed(l, 4U) ^ kptr[4*i+2];
00362         r ^= Spbox[6][(work) & 0x3f]
00363           ^  Spbox[4][(work >> 8) & 0x3f]
00364           ^  Spbox[2][(work >> 16) & 0x3f]
00365           ^  Spbox[0][(work >> 24) & 0x3f];
00366         work = l ^ kptr[4*i+3];
00367         r ^= Spbox[7][(work) & 0x3f]
00368           ^  Spbox[5][(work >> 8) & 0x3f]
00369           ^  Spbox[3][(work >> 16) & 0x3f]
00370           ^  Spbox[1][(work >> 24) & 0x3f];
00371     }
00372 
00373     *lIn = l; *rIn = r;
00374 }
00375 
00376 
00377 static void DesProcessBlock(Des* des, const byte* in, byte* out)
00378 {
00379     word32 l, r;
00380 
00381     XMEMCPY(&l, in, sizeof(l));
00382     XMEMCPY(&r, in + sizeof(l), sizeof(r));
00383     #ifdef LITTLE_ENDIAN_ORDER
00384         l = ByteReverseWord32(l);
00385         r = ByteReverseWord32(r);
00386     #endif
00387     IPERM(&l,&r);
00388     
00389     DesRawProcessBlock(&l, &r, des->key);   
00390 
00391     FPERM(&l,&r);
00392     #ifdef LITTLE_ENDIAN_ORDER
00393         l = ByteReverseWord32(l);
00394         r = ByteReverseWord32(r);
00395     #endif
00396     XMEMCPY(out, &r, sizeof(r));
00397     XMEMCPY(out + sizeof(r), &l, sizeof(l));
00398 }
00399 
00400 
00401 static void Des3ProcessBlock(Des3* des, const byte* in, byte* out)
00402 {
00403     word32 l, r;
00404 
00405     XMEMCPY(&l, in, sizeof(l));
00406     XMEMCPY(&r, in + sizeof(l), sizeof(r));
00407     #ifdef LITTLE_ENDIAN_ORDER
00408         l = ByteReverseWord32(l);
00409         r = ByteReverseWord32(r);
00410     #endif
00411     IPERM(&l,&r);
00412     
00413     DesRawProcessBlock(&l, &r, des->key[0]);   
00414     DesRawProcessBlock(&r, &l, des->key[1]);   
00415     DesRawProcessBlock(&l, &r, des->key[2]);   
00416 
00417     FPERM(&l,&r);
00418     #ifdef LITTLE_ENDIAN_ORDER
00419         l = ByteReverseWord32(l);
00420         r = ByteReverseWord32(r);
00421     #endif
00422     XMEMCPY(out, &r, sizeof(r));
00423     XMEMCPY(out + sizeof(r), &l, sizeof(l));
00424 }
00425 
00426 
00427 void Des_CbcEncrypt(Des* des, byte* out, const byte* in, word32 sz)
00428 {
00429     word32 blocks = sz / DES_BLOCK_SIZE;
00430 
00431     while (blocks--) {
00432         xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
00433         DesProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
00434         XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
00435 
00436         out += DES_BLOCK_SIZE;
00437         in  += DES_BLOCK_SIZE; 
00438     }
00439 }
00440 
00441 
00442 void Des_CbcDecrypt(Des* des, byte* out, const byte* in, word32 sz)
00443 {
00444     word32 blocks = sz / DES_BLOCK_SIZE;
00445     byte   hold[16];
00446 
00447     while (blocks--) {
00448         XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
00449         DesProcessBlock(des, (byte*)des->tmp, out);
00450         xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
00451 
00452         XMEMCPY(hold, des->reg, DES_BLOCK_SIZE);
00453         XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
00454         XMEMCPY(des->tmp, hold, DES_BLOCK_SIZE);
00455 
00456         out += DES_BLOCK_SIZE;
00457         in  += DES_BLOCK_SIZE; 
00458     }
00459 }
00460 
00461 
00462 void Des3_CbcEncrypt(Des3* des, byte* out, const byte* in, word32 sz)
00463 {
00464     word32 blocks = sz / DES_BLOCK_SIZE;
00465 
00466     while (blocks--) {
00467         xorbuf((byte*)des->reg, in, DES_BLOCK_SIZE);
00468         Des3ProcessBlock(des, (byte*)des->reg, (byte*)des->reg);
00469         XMEMCPY(out, des->reg, DES_BLOCK_SIZE);
00470 
00471         out += DES_BLOCK_SIZE;
00472         in  += DES_BLOCK_SIZE; 
00473     }
00474 }
00475 
00476 
00477 void Des3_CbcDecrypt(Des3* des, byte* out, const byte* in, word32 sz)
00478 {
00479     word32 blocks = sz / DES_BLOCK_SIZE;
00480 
00481     while (blocks--) {
00482         XMEMCPY(des->tmp, in, DES_BLOCK_SIZE);
00483         Des3ProcessBlock(des, (byte*)des->tmp, out);
00484         xorbuf(out, (byte*)des->reg, DES_BLOCK_SIZE);
00485         XMEMCPY(des->reg, des->tmp, DES_BLOCK_SIZE);
00486 
00487         out += DES_BLOCK_SIZE;
00488         in  += DES_BLOCK_SIZE; 
00489     }
00490 }
00491 
00492 
00493 #endif /* NO_DES3 */