Back to index

lightning-sunbird  0.9+nobinonly
des.c
Go to the documentation of this file.
00001 /*
00002  *  des.c
00003  *
00004  *  core source file for DES-150 library
00005  *  Make key schedule from DES key.
00006  *  Encrypt/Decrypt one 8-byte block.
00007  *
00008  * ***** BEGIN LICENSE BLOCK *****
00009  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00010  *
00011  * The contents of this file are subject to the Mozilla Public License Version
00012  * 1.1 (the "License"); you may not use this file except in compliance with
00013  * the License. You may obtain a copy of the License at
00014  * http://www.mozilla.org/MPL/
00015  *
00016  * Software distributed under the License is distributed on an "AS IS" basis,
00017  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00018  * for the specific language governing rights and limitations under the
00019  * License.
00020  *
00021  * The Original Code is the DES-150 library.
00022  *
00023  * The Initial Developer of the Original Code is
00024  * Nelson B. Bolyard, nelsonb@iname.com.
00025  * Portions created by the Initial Developer are Copyright (C) 1990
00026  * the Initial Developer. All Rights Reserved.
00027  *
00028  * Contributor(s):
00029  *
00030  * Alternatively, the contents of this file may be used under the terms of
00031  * either the GNU General Public License Version 2 or later (the "GPL"), or
00032  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00033  * in which case the provisions of the GPL or the LGPL are applicable instead
00034  * of those above. If you wish to allow use of your version of this file only
00035  * under the terms of either the GPL or the LGPL, and not to allow others to
00036  * use your version of this file under the terms of the MPL, indicate your
00037  * decision by deleting the provisions above and replace them with the notice
00038  * and other provisions required by the GPL or the LGPL. If you do not delete
00039  * the provisions above, a recipient may use your version of this file under
00040  * the terms of any one of the MPL, the GPL or the LGPL.
00041  *
00042  * ***** END LICENSE BLOCK ***** */
00043 
00044 #include "des.h"
00045 #include <stddef.h>  /* for ptrdiff_t */
00046 /* #define USE_INDEXING 1 */
00047 
00048 /*
00049  * The tables below are the 8 sbox functions, with the 6-bit input permutation 
00050  * and the 32-bit output permutation pre-computed.
00051  * They are shifted circularly to the left 3 bits, which removes 2 shifts
00052  * and an or from each round by reducing the number of sboxes whose
00053  * indices cross word broundaries from 2 to 1.  
00054  */
00055 
00056 static const HALF SP[8][64] = {
00057 /* Box S1 */ { 
00058        0x04041000, 0x00000000, 0x00040000, 0x04041010, 
00059        0x04040010, 0x00041010, 0x00000010, 0x00040000, 
00060        0x00001000, 0x04041000, 0x04041010, 0x00001000, 
00061        0x04001010, 0x04040010, 0x04000000, 0x00000010, 
00062        0x00001010, 0x04001000, 0x04001000, 0x00041000, 
00063        0x00041000, 0x04040000, 0x04040000, 0x04001010, 
00064        0x00040010, 0x04000010, 0x04000010, 0x00040010, 
00065        0x00000000, 0x00001010, 0x00041010, 0x04000000, 
00066        0x00040000, 0x04041010, 0x00000010, 0x04040000, 
00067        0x04041000, 0x04000000, 0x04000000, 0x00001000, 
00068        0x04040010, 0x00040000, 0x00041000, 0x04000010, 
00069        0x00001000, 0x00000010, 0x04001010, 0x00041010, 
00070        0x04041010, 0x00040010, 0x04040000, 0x04001010, 
00071        0x04000010, 0x00001010, 0x00041010, 0x04041000, 
00072        0x00001010, 0x04001000, 0x04001000, 0x00000000, 
00073        0x00040010, 0x00041000, 0x00000000, 0x04040010
00074     },
00075 /* Box S2 */ { 
00076        0x00420082, 0x00020002, 0x00020000, 0x00420080, 
00077        0x00400000, 0x00000080, 0x00400082, 0x00020082, 
00078        0x00000082, 0x00420082, 0x00420002, 0x00000002, 
00079        0x00020002, 0x00400000, 0x00000080, 0x00400082, 
00080        0x00420000, 0x00400080, 0x00020082, 0x00000000, 
00081        0x00000002, 0x00020000, 0x00420080, 0x00400002, 
00082        0x00400080, 0x00000082, 0x00000000, 0x00420000, 
00083        0x00020080, 0x00420002, 0x00400002, 0x00020080, 
00084        0x00000000, 0x00420080, 0x00400082, 0x00400000, 
00085        0x00020082, 0x00400002, 0x00420002, 0x00020000, 
00086        0x00400002, 0x00020002, 0x00000080, 0x00420082, 
00087        0x00420080, 0x00000080, 0x00020000, 0x00000002, 
00088        0x00020080, 0x00420002, 0x00400000, 0x00000082, 
00089        0x00400080, 0x00020082, 0x00000082, 0x00400080, 
00090        0x00420000, 0x00000000, 0x00020002, 0x00020080, 
00091        0x00000002, 0x00400082, 0x00420082, 0x00420000 
00092     },
00093 /* Box S3 */ { 
00094        0x00000820, 0x20080800, 0x00000000, 0x20080020, 
00095        0x20000800, 0x00000000, 0x00080820, 0x20000800, 
00096        0x00080020, 0x20000020, 0x20000020, 0x00080000, 
00097        0x20080820, 0x00080020, 0x20080000, 0x00000820, 
00098        0x20000000, 0x00000020, 0x20080800, 0x00000800, 
00099        0x00080800, 0x20080000, 0x20080020, 0x00080820, 
00100        0x20000820, 0x00080800, 0x00080000, 0x20000820, 
00101        0x00000020, 0x20080820, 0x00000800, 0x20000000, 
00102        0x20080800, 0x20000000, 0x00080020, 0x00000820, 
00103        0x00080000, 0x20080800, 0x20000800, 0x00000000, 
00104        0x00000800, 0x00080020, 0x20080820, 0x20000800, 
00105        0x20000020, 0x00000800, 0x00000000, 0x20080020, 
00106        0x20000820, 0x00080000, 0x20000000, 0x20080820, 
00107        0x00000020, 0x00080820, 0x00080800, 0x20000020, 
00108        0x20080000, 0x20000820, 0x00000820, 0x20080000, 
00109        0x00080820, 0x00000020, 0x20080020, 0x00080800 
00110     },
00111 /* Box S4 */ { 
00112        0x02008004, 0x00008204, 0x00008204, 0x00000200, 
00113        0x02008200, 0x02000204, 0x02000004, 0x00008004, 
00114        0x00000000, 0x02008000, 0x02008000, 0x02008204, 
00115        0x00000204, 0x00000000, 0x02000200, 0x02000004, 
00116        0x00000004, 0x00008000, 0x02000000, 0x02008004, 
00117        0x00000200, 0x02000000, 0x00008004, 0x00008200, 
00118        0x02000204, 0x00000004, 0x00008200, 0x02000200, 
00119        0x00008000, 0x02008200, 0x02008204, 0x00000204, 
00120        0x02000200, 0x02000004, 0x02008000, 0x02008204, 
00121        0x00000204, 0x00000000, 0x00000000, 0x02008000, 
00122        0x00008200, 0x02000200, 0x02000204, 0x00000004, 
00123        0x02008004, 0x00008204, 0x00008204, 0x00000200, 
00124        0x02008204, 0x00000204, 0x00000004, 0x00008000, 
00125        0x02000004, 0x00008004, 0x02008200, 0x02000204, 
00126        0x00008004, 0x00008200, 0x02000000, 0x02008004, 
00127        0x00000200, 0x02000000, 0x00008000, 0x02008200 
00128     },
00129 /* Box S5 */ { 
00130        0x00000400, 0x08200400, 0x08200000, 0x08000401, 
00131        0x00200000, 0x00000400, 0x00000001, 0x08200000, 
00132        0x00200401, 0x00200000, 0x08000400, 0x00200401, 
00133        0x08000401, 0x08200001, 0x00200400, 0x00000001, 
00134        0x08000000, 0x00200001, 0x00200001, 0x00000000, 
00135        0x00000401, 0x08200401, 0x08200401, 0x08000400, 
00136        0x08200001, 0x00000401, 0x00000000, 0x08000001, 
00137        0x08200400, 0x08000000, 0x08000001, 0x00200400, 
00138        0x00200000, 0x08000401, 0x00000400, 0x08000000, 
00139        0x00000001, 0x08200000, 0x08000401, 0x00200401, 
00140        0x08000400, 0x00000001, 0x08200001, 0x08200400, 
00141        0x00200401, 0x00000400, 0x08000000, 0x08200001, 
00142        0x08200401, 0x00200400, 0x08000001, 0x08200401, 
00143        0x08200000, 0x00000000, 0x00200001, 0x08000001, 
00144        0x00200400, 0x08000400, 0x00000401, 0x00200000, 
00145        0x00000000, 0x00200001, 0x08200400, 0x00000401
00146     },
00147 /* Box S6 */ { 
00148        0x80000040, 0x81000000, 0x00010000, 0x81010040, 
00149        0x81000000, 0x00000040, 0x81010040, 0x01000000, 
00150        0x80010000, 0x01010040, 0x01000000, 0x80000040, 
00151        0x01000040, 0x80010000, 0x80000000, 0x00010040, 
00152        0x00000000, 0x01000040, 0x80010040, 0x00010000, 
00153        0x01010000, 0x80010040, 0x00000040, 0x81000040, 
00154        0x81000040, 0x00000000, 0x01010040, 0x81010000, 
00155        0x00010040, 0x01010000, 0x81010000, 0x80000000, 
00156        0x80010000, 0x00000040, 0x81000040, 0x01010000, 
00157        0x81010040, 0x01000000, 0x00010040, 0x80000040, 
00158        0x01000000, 0x80010000, 0x80000000, 0x00010040, 
00159        0x80000040, 0x81010040, 0x01010000, 0x81000000, 
00160        0x01010040, 0x81010000, 0x00000000, 0x81000040, 
00161        0x00000040, 0x00010000, 0x81000000, 0x01010040, 
00162        0x00010000, 0x01000040, 0x80010040, 0x00000000, 
00163        0x81010000, 0x80000000, 0x01000040, 0x80010040 
00164     },
00165 /* Box S7 */ { 
00166        0x00800000, 0x10800008, 0x10002008, 0x00000000, 
00167        0x00002000, 0x10002008, 0x00802008, 0x10802000, 
00168        0x10802008, 0x00800000, 0x00000000, 0x10000008, 
00169        0x00000008, 0x10000000, 0x10800008, 0x00002008, 
00170        0x10002000, 0x00802008, 0x00800008, 0x10002000, 
00171        0x10000008, 0x10800000, 0x10802000, 0x00800008, 
00172        0x10800000, 0x00002000, 0x00002008, 0x10802008, 
00173        0x00802000, 0x00000008, 0x10000000, 0x00802000, 
00174        0x10000000, 0x00802000, 0x00800000, 0x10002008, 
00175        0x10002008, 0x10800008, 0x10800008, 0x00000008, 
00176        0x00800008, 0x10000000, 0x10002000, 0x00800000, 
00177        0x10802000, 0x00002008, 0x00802008, 0x10802000, 
00178        0x00002008, 0x10000008, 0x10802008, 0x10800000, 
00179        0x00802000, 0x00000000, 0x00000008, 0x10802008, 
00180        0x00000000, 0x00802008, 0x10800000, 0x00002000, 
00181        0x10000008, 0x10002000, 0x00002000, 0x00800008 
00182     },
00183 /* Box S8 */ { 
00184        0x40004100, 0x00004000, 0x00100000, 0x40104100, 
00185        0x40000000, 0x40004100, 0x00000100, 0x40000000, 
00186        0x00100100, 0x40100000, 0x40104100, 0x00104000, 
00187        0x40104000, 0x00104100, 0x00004000, 0x00000100, 
00188        0x40100000, 0x40000100, 0x40004000, 0x00004100, 
00189        0x00104000, 0x00100100, 0x40100100, 0x40104000, 
00190        0x00004100, 0x00000000, 0x00000000, 0x40100100, 
00191        0x40000100, 0x40004000, 0x00104100, 0x00100000, 
00192        0x00104100, 0x00100000, 0x40104000, 0x00004000, 
00193        0x00000100, 0x40100100, 0x00004000, 0x00104100, 
00194        0x40004000, 0x00000100, 0x40000100, 0x40100000, 
00195        0x40100100, 0x40000000, 0x00100000, 0x40004100, 
00196        0x00000000, 0x40104100, 0x00100100, 0x40000100, 
00197        0x40100000, 0x40004000, 0x40004100, 0x00000000, 
00198        0x40104100, 0x00104000, 0x00104000, 0x00004100, 
00199        0x00004100, 0x00100100, 0x40000000, 0x40104000 
00200     }
00201 };
00202 
00203 static const HALF PC2[8][64] = {
00204 /* table 0 */ {
00205     0x00000000, 0x00001000, 0x04000000, 0x04001000, 
00206     0x00100000, 0x00101000, 0x04100000, 0x04101000, 
00207     0x00008000, 0x00009000, 0x04008000, 0x04009000, 
00208     0x00108000, 0x00109000, 0x04108000, 0x04109000, 
00209     0x00000004, 0x00001004, 0x04000004, 0x04001004, 
00210     0x00100004, 0x00101004, 0x04100004, 0x04101004, 
00211     0x00008004, 0x00009004, 0x04008004, 0x04009004, 
00212     0x00108004, 0x00109004, 0x04108004, 0x04109004, 
00213     0x08000000, 0x08001000, 0x0c000000, 0x0c001000, 
00214     0x08100000, 0x08101000, 0x0c100000, 0x0c101000, 
00215     0x08008000, 0x08009000, 0x0c008000, 0x0c009000, 
00216     0x08108000, 0x08109000, 0x0c108000, 0x0c109000, 
00217     0x08000004, 0x08001004, 0x0c000004, 0x0c001004, 
00218     0x08100004, 0x08101004, 0x0c100004, 0x0c101004, 
00219     0x08008004, 0x08009004, 0x0c008004, 0x0c009004, 
00220     0x08108004, 0x08109004, 0x0c108004, 0x0c109004
00221   },
00222 /* table 1 */ {
00223     0x00000000, 0x00002000, 0x80000000, 0x80002000, 
00224     0x00000008, 0x00002008, 0x80000008, 0x80002008, 
00225     0x00200000, 0x00202000, 0x80200000, 0x80202000, 
00226     0x00200008, 0x00202008, 0x80200008, 0x80202008, 
00227     0x20000000, 0x20002000, 0xa0000000, 0xa0002000, 
00228     0x20000008, 0x20002008, 0xa0000008, 0xa0002008, 
00229     0x20200000, 0x20202000, 0xa0200000, 0xa0202000, 
00230     0x20200008, 0x20202008, 0xa0200008, 0xa0202008, 
00231     0x00000400, 0x00002400, 0x80000400, 0x80002400, 
00232     0x00000408, 0x00002408, 0x80000408, 0x80002408, 
00233     0x00200400, 0x00202400, 0x80200400, 0x80202400, 
00234     0x00200408, 0x00202408, 0x80200408, 0x80202408, 
00235     0x20000400, 0x20002400, 0xa0000400, 0xa0002400, 
00236     0x20000408, 0x20002408, 0xa0000408, 0xa0002408, 
00237     0x20200400, 0x20202400, 0xa0200400, 0xa0202400, 
00238     0x20200408, 0x20202408, 0xa0200408, 0xa0202408
00239   },
00240 /* table 2 */ {
00241     0x00000000, 0x00004000, 0x00000020, 0x00004020, 
00242     0x00080000, 0x00084000, 0x00080020, 0x00084020, 
00243     0x00000800, 0x00004800, 0x00000820, 0x00004820, 
00244     0x00080800, 0x00084800, 0x00080820, 0x00084820, 
00245     0x00000010, 0x00004010, 0x00000030, 0x00004030, 
00246     0x00080010, 0x00084010, 0x00080030, 0x00084030, 
00247     0x00000810, 0x00004810, 0x00000830, 0x00004830, 
00248     0x00080810, 0x00084810, 0x00080830, 0x00084830, 
00249     0x00400000, 0x00404000, 0x00400020, 0x00404020, 
00250     0x00480000, 0x00484000, 0x00480020, 0x00484020, 
00251     0x00400800, 0x00404800, 0x00400820, 0x00404820, 
00252     0x00480800, 0x00484800, 0x00480820, 0x00484820, 
00253     0x00400010, 0x00404010, 0x00400030, 0x00404030, 
00254     0x00480010, 0x00484010, 0x00480030, 0x00484030, 
00255     0x00400810, 0x00404810, 0x00400830, 0x00404830, 
00256     0x00480810, 0x00484810, 0x00480830, 0x00484830 
00257   },
00258 /* table 3 */ {
00259     0x00000000, 0x40000000, 0x00000080, 0x40000080, 
00260     0x00040000, 0x40040000, 0x00040080, 0x40040080, 
00261     0x00000040, 0x40000040, 0x000000c0, 0x400000c0, 
00262     0x00040040, 0x40040040, 0x000400c0, 0x400400c0, 
00263     0x10000000, 0x50000000, 0x10000080, 0x50000080, 
00264     0x10040000, 0x50040000, 0x10040080, 0x50040080, 
00265     0x10000040, 0x50000040, 0x100000c0, 0x500000c0, 
00266     0x10040040, 0x50040040, 0x100400c0, 0x500400c0, 
00267     0x00800000, 0x40800000, 0x00800080, 0x40800080, 
00268     0x00840000, 0x40840000, 0x00840080, 0x40840080, 
00269     0x00800040, 0x40800040, 0x008000c0, 0x408000c0, 
00270     0x00840040, 0x40840040, 0x008400c0, 0x408400c0, 
00271     0x10800000, 0x50800000, 0x10800080, 0x50800080, 
00272     0x10840000, 0x50840000, 0x10840080, 0x50840080, 
00273     0x10800040, 0x50800040, 0x108000c0, 0x508000c0, 
00274     0x10840040, 0x50840040, 0x108400c0, 0x508400c0 
00275   },
00276 /* table 4 */ {
00277     0x00000000, 0x00000008, 0x08000000, 0x08000008, 
00278     0x00040000, 0x00040008, 0x08040000, 0x08040008, 
00279     0x00002000, 0x00002008, 0x08002000, 0x08002008, 
00280     0x00042000, 0x00042008, 0x08042000, 0x08042008, 
00281     0x80000000, 0x80000008, 0x88000000, 0x88000008, 
00282     0x80040000, 0x80040008, 0x88040000, 0x88040008, 
00283     0x80002000, 0x80002008, 0x88002000, 0x88002008, 
00284     0x80042000, 0x80042008, 0x88042000, 0x88042008, 
00285     0x00080000, 0x00080008, 0x08080000, 0x08080008, 
00286     0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008, 
00287     0x00082000, 0x00082008, 0x08082000, 0x08082008, 
00288     0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008, 
00289     0x80080000, 0x80080008, 0x88080000, 0x88080008, 
00290     0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008, 
00291     0x80082000, 0x80082008, 0x88082000, 0x88082008, 
00292     0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008 
00293   },
00294 /* table 5 */ {
00295     0x00000000, 0x00400000, 0x00008000, 0x00408000, 
00296     0x40000000, 0x40400000, 0x40008000, 0x40408000, 
00297     0x00000020, 0x00400020, 0x00008020, 0x00408020, 
00298     0x40000020, 0x40400020, 0x40008020, 0x40408020, 
00299     0x00001000, 0x00401000, 0x00009000, 0x00409000, 
00300     0x40001000, 0x40401000, 0x40009000, 0x40409000, 
00301     0x00001020, 0x00401020, 0x00009020, 0x00409020, 
00302     0x40001020, 0x40401020, 0x40009020, 0x40409020, 
00303     0x00100000, 0x00500000, 0x00108000, 0x00508000, 
00304     0x40100000, 0x40500000, 0x40108000, 0x40508000, 
00305     0x00100020, 0x00500020, 0x00108020, 0x00508020, 
00306     0x40100020, 0x40500020, 0x40108020, 0x40508020, 
00307     0x00101000, 0x00501000, 0x00109000, 0x00509000, 
00308     0x40101000, 0x40501000, 0x40109000, 0x40509000, 
00309     0x00101020, 0x00501020, 0x00109020, 0x00509020, 
00310     0x40101020, 0x40501020, 0x40109020, 0x40509020 
00311   },
00312 /* table 6 */ {
00313     0x00000000, 0x00000040, 0x04000000, 0x04000040, 
00314     0x00000800, 0x00000840, 0x04000800, 0x04000840, 
00315     0x00800000, 0x00800040, 0x04800000, 0x04800040, 
00316     0x00800800, 0x00800840, 0x04800800, 0x04800840, 
00317     0x10000000, 0x10000040, 0x14000000, 0x14000040, 
00318     0x10000800, 0x10000840, 0x14000800, 0x14000840, 
00319     0x10800000, 0x10800040, 0x14800000, 0x14800040, 
00320     0x10800800, 0x10800840, 0x14800800, 0x14800840, 
00321     0x00000080, 0x000000c0, 0x04000080, 0x040000c0, 
00322     0x00000880, 0x000008c0, 0x04000880, 0x040008c0, 
00323     0x00800080, 0x008000c0, 0x04800080, 0x048000c0, 
00324     0x00800880, 0x008008c0, 0x04800880, 0x048008c0, 
00325     0x10000080, 0x100000c0, 0x14000080, 0x140000c0, 
00326     0x10000880, 0x100008c0, 0x14000880, 0x140008c0, 
00327     0x10800080, 0x108000c0, 0x14800080, 0x148000c0, 
00328     0x10800880, 0x108008c0, 0x14800880, 0x148008c0 
00329   },
00330 /* table 7 */ {
00331     0x00000000, 0x00000010, 0x00000400, 0x00000410, 
00332     0x00000004, 0x00000014, 0x00000404, 0x00000414, 
00333     0x00004000, 0x00004010, 0x00004400, 0x00004410, 
00334     0x00004004, 0x00004014, 0x00004404, 0x00004414, 
00335     0x20000000, 0x20000010, 0x20000400, 0x20000410, 
00336     0x20000004, 0x20000014, 0x20000404, 0x20000414, 
00337     0x20004000, 0x20004010, 0x20004400, 0x20004410, 
00338     0x20004004, 0x20004014, 0x20004404, 0x20004414, 
00339     0x00200000, 0x00200010, 0x00200400, 0x00200410, 
00340     0x00200004, 0x00200014, 0x00200404, 0x00200414, 
00341     0x00204000, 0x00204010, 0x00204400, 0x00204410, 
00342     0x00204004, 0x00204014, 0x00204404, 0x00204414, 
00343     0x20200000, 0x20200010, 0x20200400, 0x20200410, 
00344     0x20200004, 0x20200014, 0x20200404, 0x20200414, 
00345     0x20204000, 0x20204010, 0x20204400, 0x20204410, 
00346     0x20204004, 0x20204014, 0x20204404, 0x20204414 
00347   }
00348 };
00349 
00350 /*
00351  * The PC-1 Permutation
00352  * If we number the bits of the 8 bytes of key input like this (in octal):
00353  *     00 01 02 03 04 05 06 07 
00354  *     10 11 12 13 14 15 16 17 
00355  *     20 21 22 23 24 25 26 27 
00356  *     30 31 32 33 34 35 36 37 
00357  *     40 41 42 43 44 45 46 47 
00358  *     50 51 52 53 54 55 56 57 
00359  *     60 61 62 63 64 65 66 67 
00360  *     70 71 72 73 74 75 76 77 
00361  * then after the PC-1 permutation, 
00362  * C0 is
00363  *     70 60 50 40 30 20 10 00 
00364  *     71 61 51 41 31 21 11 01 
00365  *     72 62 52 42 32 22 12 02 
00366  *     73 63 53 43 
00367  * D0 is
00368  *     76 66 56 46 36 26 16 06 
00369  *     75 65 55 45 35 25 15 05 
00370  *     74 64 54 44 34 24 14 04 
00371  *                 33 23 13 03 
00372  * and these parity bits have been discarded:
00373  *     77 67 57 47 37 27 17 07 
00374  * 
00375  * We achieve this by flipping the input matrix about the diagonal from 70-07,
00376  * getting left = 
00377  *     77 67 57 47 37 27 17 07     (these are the parity bits)
00378  *     76 66 56 46 36 26 16 06 
00379  *     75 65 55 45 35 25 15 05 
00380  *     74 64 54 44 34 24 14 04 
00381  * right = 
00382  *     73 63 53 43 33 23 13 03 
00383  *     72 62 52 42 32 22 12 02 
00384  *     71 61 51 41 31 21 11 01 
00385  *     70 60 50 40 30 20 10 00 
00386  * then byte swap right, ala htonl() on a little endian machine.
00387  * right = 
00388  *     70 60 50 40 30 20 10 00 
00389  *     71 67 57 47 37 27 11 07 
00390  *     72 62 52 42 32 22 12 02 
00391  *     73 63 53 43 33 23 13 03 
00392  * then
00393  *     c0 = right >> 4;
00394  *     d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
00395 */
00396 
00397 #define FLIP_RIGHT_DIAGONAL(word, temp) \
00398     temp  = (word ^ (word >> 18)) & 0x00003333; \
00399     word ^=  temp | (temp << 18); \
00400     temp  = (word ^ (word >> 9)) & 0x00550055; \
00401     word ^=  temp | (temp << 9);
00402 
00403 #define BYTESWAP(word, temp) \
00404     word = (word >> 16) | (word << 16); \
00405     temp = 0x00ff00ff; \
00406     word = ((word & temp) << 8) | ((word >> 8) & temp); 
00407 
00408 #define PC1(left, right, c0, d0, temp) \
00409     right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
00410     left  ^= temp << 4; \
00411     FLIP_RIGHT_DIAGONAL(left, temp); \
00412     FLIP_RIGHT_DIAGONAL(right, temp); \
00413     BYTESWAP(right, temp); \
00414     c0 = right >> 4; \
00415     d0 = ((left & 0x00ffffff) << 4) | (right & 0xf); 
00416 
00417 #define LEFT_SHIFT_1( reg ) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
00418 #define LEFT_SHIFT_2( reg ) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
00419 
00420 /*
00421  *   setup key schedules from key
00422  */
00423 
00424 void 
00425 DES_MakeSchedule( HALF * ks, const BYTE * key,   DESDirection direction)
00426 {
00427     register HALF left, right;
00428     register HALF c0, d0;
00429     register HALF temp;
00430     int           delta;
00431     unsigned int  ls;
00432 
00433 #if defined(_X86_)
00434     left  = HALFPTR(key)[0]; 
00435     right = HALFPTR(key)[1]; 
00436     BYTESWAP(left, temp);
00437     BYTESWAP(right, temp);
00438 #else
00439     if (((ptrdiff_t)key & 0x03) == 0) {
00440        left  = HALFPTR(key)[0]; 
00441        right = HALFPTR(key)[1]; 
00442 #if defined(IS_LITTLE_ENDIAN)
00443        BYTESWAP(left, temp);
00444        BYTESWAP(right, temp);
00445 #endif
00446     } else {
00447        left    = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) | 
00448                 ((HALF)key[2] << 8)  | key[3];
00449        right   = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) | 
00450                 ((HALF)key[6] << 8)  | key[7];
00451     }
00452 #endif
00453 
00454     PC1(left, right, c0, d0, temp);
00455 
00456     if (direction == DES_ENCRYPT) {
00457        delta = 2 * (int)sizeof(HALF);
00458     } else {
00459        ks += 30;
00460        delta = (-2) * (int)sizeof(HALF);
00461     }
00462 
00463     for (ls = 0x8103; ls; ls >>= 1) {
00464        if ( ls & 1 ) {
00465            c0 = LEFT_SHIFT_1( c0 );
00466            d0 = LEFT_SHIFT_1( d0 );
00467        } else {
00468            c0 = LEFT_SHIFT_2( c0 );
00469            d0 = LEFT_SHIFT_2( d0 );
00470        }
00471 
00472 #ifdef USE_INDEXING
00473 #define PC2LOOKUP(b,c) PC2[b][c]
00474 
00475        left   = PC2LOOKUP(0, ((c0 >> 22) & 0x3F) );
00476        left  |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F) );
00477        left  |= PC2LOOKUP(2, ((c0 >>  4) & 0x38) | (c0 & 0x7) );
00478        left  |= PC2LOOKUP(3, ((c0>>18)&0xC) | ((c0>>11)&0x3) | (c0&0x30));
00479 
00480        right  = PC2LOOKUP(4, ((d0 >> 22) & 0x3F) );
00481        right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf) );
00482        right |= PC2LOOKUP(6, ((d0 >>  7) & 0x3F) );
00483        right |= PC2LOOKUP(7, ((d0 >>  1) & 0x3C) | (d0 & 0x3));
00484 #else
00485 #define PC2LOOKUP(b,c) *(HALF *)((BYTE *)&PC2[b][0]+(c))
00486 
00487        left   = PC2LOOKUP(0, ((c0 >> 20) & 0xFC) );
00488        left  |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC) );
00489        left  |= PC2LOOKUP(2, ((c0 >>  2) & 0xE0) | ((c0 <<  2) & 0x1C) );
00490        left  |= PC2LOOKUP(3, ((c0>>16)&0x30)|((c0>>9)&0xC)|((c0<<2)&0xC0));
00491 
00492        right  = PC2LOOKUP(4, ((d0 >> 20) & 0xFC) );
00493        right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C) );
00494        right |= PC2LOOKUP(6, ((d0 >>  5) & 0xFC) );
00495        right |= PC2LOOKUP(7, ((d0 <<  1) & 0xF0) | ((d0 << 2) & 0x0C));
00496 #endif
00497        /* left  contains key bits for S1 S3 S2 S4 */
00498        /* right contains key bits for S6 S8 S5 S7 */
00499        temp = (left  << 16)        /* S2 S4 XX XX */
00500             | (right >> 16);       /* XX XX S6 S8 */
00501        ks[0] = temp;
00502 
00503        temp = (left  & 0xffff0000) /* S1 S3 XX XX */
00504             | (right & 0x0000ffff);/* XX XX S5 S7 */
00505        ks[1] = temp;
00506 
00507        ks = (HALF*)((BYTE *)ks + delta);
00508     }
00509 }
00510 
00511 /*
00512  * The DES Initial Permutation
00513  * if we number the bits of the 8 bytes of input like this (in octal):
00514  *     00 01 02 03 04 05 06 07 
00515  *     10 11 12 13 14 15 16 17 
00516  *     20 21 22 23 24 25 26 27 
00517  *     30 31 32 33 34 35 36 37 
00518  *     40 41 42 43 44 45 46 47 
00519  *     50 51 52 53 54 55 56 57 
00520  *     60 61 62 63 64 65 66 67 
00521  *     70 71 72 73 74 75 76 77 
00522  * then after the initial permutation, they will be in this order. 
00523  *     71 61 51 41 31 21 11 01 
00524  *     73 63 53 43 33 23 13 03 
00525  *     75 65 55 45 35 25 15 05 
00526  *     77 67 57 47 37 27 17 07 
00527  *     70 60 50 40 30 20 10 00 
00528  *     72 62 52 42 32 22 12 02 
00529  *     74 64 54 44 34 24 14 04 
00530  *     76 66 56 46 36 26 16 06 
00531  *
00532  * One way to do this is in two steps:
00533  * 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
00534  * 2. Rearrange the bytes (rows in the matrix above) with the following code.
00535  *
00536  * #define swapHiLo(word, temp) \
00537  *   temp  = (word ^ (word >> 24)) & 0x000000ff; \
00538  *   word ^=  temp | (temp << 24); 
00539  *
00540  *   right ^= temp = ((left << 8) ^ right) & 0xff00ff00; 
00541  *   left  ^= temp >> 8; 
00542  *   swapHiLo(left, temp);
00543  *   swapHiLo(right,temp);
00544  *
00545  * However, the two steps can be combined, so that the rows are rearranged
00546  * while the matrix is being flipped, reducing the number of bit exchange
00547  * operations from 8 ot 5.  
00548  *
00549  * Initial Permutation */
00550 #define IP(left, right, temp) \
00551     right ^= temp = ((left >> 4) ^  right) & 0x0f0f0f0f; \
00552     left  ^= temp << 4; \
00553     right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
00554     left  ^= temp << 16; \
00555     right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
00556     left  ^= temp >> 2; \
00557     right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
00558     left  ^= temp >> 8; \
00559     right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
00560     left  ^= temp << 1; 
00561 
00562 /* The Final (Inverse Initial) permutation is done by reversing the 
00563 ** steps of the Initital Permutation 
00564 */
00565 
00566 #define FP(left, right, temp) \
00567     right ^= temp = ((left >> 1) ^ right) & 0x55555555; \
00568     left  ^= temp << 1; \
00569     right ^= temp = ((left << 8) ^ right) & 0xff00ff00; \
00570     left  ^= temp >> 8; \
00571     right ^= temp = ((left << 2) ^ right) & 0xcccccccc; \
00572     left  ^= temp >> 2; \
00573     right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
00574     left  ^= temp << 16; \
00575     right ^= temp = ((left >> 4) ^  right) & 0x0f0f0f0f; \
00576     left  ^= temp << 4; 
00577 
00578 void 
00579 DES_Do1Block(HALF * ks, const BYTE * inbuf, BYTE * outbuf)
00580 {
00581     register HALF left, right;
00582     register HALF temp;
00583 
00584 #if defined(_X86_)
00585     left  = HALFPTR(inbuf)[0]; 
00586     right = HALFPTR(inbuf)[1]; 
00587     BYTESWAP(left, temp);
00588     BYTESWAP(right, temp);
00589 #else
00590     if (((ptrdiff_t)inbuf & 0x03) == 0) {
00591        left  = HALFPTR(inbuf)[0]; 
00592        right = HALFPTR(inbuf)[1]; 
00593 #if defined(IS_LITTLE_ENDIAN)
00594        BYTESWAP(left, temp);
00595        BYTESWAP(right, temp);
00596 #endif
00597     } else {
00598        left    = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) | 
00599                 ((HALF)inbuf[2] << 8)  | inbuf[3];
00600        right   = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) | 
00601                 ((HALF)inbuf[6] << 8)  | inbuf[7];
00602     }
00603 #endif
00604 
00605     IP(left, right, temp);
00606 
00607     /* shift the values left circularly 3 bits. */
00608     left  = (left  << 3) | (left  >> 29);
00609     right = (right << 3) | (right >> 29);
00610 
00611 #ifdef USE_INDEXING
00612 #define KSLOOKUP(s,b) SP[s][((temp >> (b+2)) & 0x3f)]
00613 #else
00614 #define KSLOOKUP(s,b) *(HALF*)((BYTE*)&SP[s][0]+((temp >> b) & 0xFC))
00615 #endif
00616 #define ROUND(out, in, r) \
00617     temp  = in ^ ks[2*r]; \
00618     out ^= KSLOOKUP( 1,  24 ); \
00619     out ^= KSLOOKUP( 3,  16 ); \
00620     out ^= KSLOOKUP( 5,   8 ); \
00621     out ^= KSLOOKUP( 7,   0 ); \
00622     temp  = ((in >> 4) | (in << 28)) ^ ks[2*r+1]; \
00623     out ^= KSLOOKUP( 0,  24 ); \
00624     out ^= KSLOOKUP( 2,  16 ); \
00625     out ^= KSLOOKUP( 4,   8 ); \
00626     out ^= KSLOOKUP( 6,   0 ); 
00627 
00628     /* Do the 16 Feistel rounds */
00629     ROUND(left, right, 0)
00630     ROUND(right, left, 1)
00631     ROUND(left, right, 2)
00632     ROUND(right, left, 3)
00633     ROUND(left, right, 4)
00634     ROUND(right, left, 5)
00635     ROUND(left, right, 6)
00636     ROUND(right, left, 7)
00637     ROUND(left, right, 8)
00638     ROUND(right, left, 9)
00639     ROUND(left, right, 10)
00640     ROUND(right, left, 11)
00641     ROUND(left, right, 12)
00642     ROUND(right, left, 13)
00643     ROUND(left, right, 14)
00644     ROUND(right, left, 15)
00645 
00646     /* now shift circularly right 3 bits to undo the shifting done 
00647     ** above.  switch left and right here. 
00648     */
00649     temp  = (left >> 3) | (left << 29); 
00650     left  = (right >> 3) | (right << 29); 
00651     right = temp;
00652 
00653     FP(left, right, temp);
00654 
00655 #if defined(_X86_)
00656     BYTESWAP(left, temp);
00657     BYTESWAP(right, temp);
00658     HALFPTR(outbuf)[0]  = left; 
00659     HALFPTR(outbuf)[1]  = right; 
00660 #else
00661     if (((ptrdiff_t)outbuf & 0x03) == 0) {
00662 #if defined(IS_LITTLE_ENDIAN)
00663        BYTESWAP(left, temp);
00664        BYTESWAP(right, temp);
00665 #endif
00666        HALFPTR(outbuf)[0]  = left; 
00667        HALFPTR(outbuf)[1]  = right; 
00668     } else {
00669        outbuf[0] = (BYTE)(left >> 24);
00670        outbuf[1] = (BYTE)(left >> 16);
00671        outbuf[2] = (BYTE)(left >>  8);
00672        outbuf[3] = (BYTE)(left      );
00673 
00674        outbuf[4] = (BYTE)(right >> 24);
00675        outbuf[5] = (BYTE)(right >> 16);
00676        outbuf[6] = (BYTE)(right >>  8);
00677        outbuf[7] = (BYTE)(right      );
00678     }
00679 #endif
00680 
00681 }
00682 
00683 /* Ackowledgements:
00684 ** Two ideas used in this implementation were shown to me by Dennis Ferguson 
00685 ** in 1990.  He credits them to Richard Outerbridge and Dan Hoey.  They were:
00686 ** 1. The method of computing the Initial and Final permutations.
00687 ** 2. Circularly rotating the SP tables and the initial values of left and 
00688 **     right to reduce the number of shifts required during the 16 rounds.
00689 */