Back to index

glibc  2.9
des_impl.c
Go to the documentation of this file.
00001 /* Copyright (C) 1992 Eric Young */
00002 /* Collected from libdes and modified for SECURE RPC by Martin Kuck 1994 */
00003 /* This file is distributed under the terms of the GNU Lesser General */
00004 /* Public License, version 2.1 or later - see the file COPYING.LIB for details.*/
00005 /* If you did not receive a copy of the license with this program, please*/
00006 /* write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,*/
00007 /* Boston, MA 02111, USA to obtain a copy. */
00008 #include <string.h>
00009 #include <stdint.h>
00010 #include "des.h"
00011 
00012 
00013 static const uint32_t des_SPtrans[8][64] =
00014 {
00015   {                         /* nibble 0 */
00016     0x00820200, 0x00020000, 0x80800000, 0x80820200,
00017     0x00800000, 0x80020200, 0x80020000, 0x80800000,
00018     0x80020200, 0x00820200, 0x00820000, 0x80000200,
00019     0x80800200, 0x00800000, 0x00000000, 0x80020000,
00020     0x00020000, 0x80000000, 0x00800200, 0x00020200,
00021     0x80820200, 0x00820000, 0x80000200, 0x00800200,
00022     0x80000000, 0x00000200, 0x00020200, 0x80820000,
00023     0x00000200, 0x80800200, 0x80820000, 0x00000000,
00024     0x00000000, 0x80820200, 0x00800200, 0x80020000,
00025     0x00820200, 0x00020000, 0x80000200, 0x00800200,
00026     0x80820000, 0x00000200, 0x00020200, 0x80800000,
00027     0x80020200, 0x80000000, 0x80800000, 0x00820000,
00028     0x80820200, 0x00020200, 0x00820000, 0x80800200,
00029     0x00800000, 0x80000200, 0x80020000, 0x00000000,
00030     0x00020000, 0x00800000, 0x80800200, 0x00820200,
00031     0x80000000, 0x80820000, 0x00000200, 0x80020200},
00032 
00033   {                         /* nibble 1 */
00034     0x10042004, 0x00000000, 0x00042000, 0x10040000,
00035     0x10000004, 0x00002004, 0x10002000, 0x00042000,
00036     0x00002000, 0x10040004, 0x00000004, 0x10002000,
00037     0x00040004, 0x10042000, 0x10040000, 0x00000004,
00038     0x00040000, 0x10002004, 0x10040004, 0x00002000,
00039     0x00042004, 0x10000000, 0x00000000, 0x00040004,
00040     0x10002004, 0x00042004, 0x10042000, 0x10000004,
00041     0x10000000, 0x00040000, 0x00002004, 0x10042004,
00042     0x00040004, 0x10042000, 0x10002000, 0x00042004,
00043     0x10042004, 0x00040004, 0x10000004, 0x00000000,
00044     0x10000000, 0x00002004, 0x00040000, 0x10040004,
00045     0x00002000, 0x10000000, 0x00042004, 0x10002004,
00046     0x10042000, 0x00002000, 0x00000000, 0x10000004,
00047     0x00000004, 0x10042004, 0x00042000, 0x10040000,
00048     0x10040004, 0x00040000, 0x00002004, 0x10002000,
00049     0x10002004, 0x00000004, 0x10040000, 0x00042000},
00050 
00051   {                         /* nibble 2 */
00052     0x41000000, 0x01010040, 0x00000040, 0x41000040,
00053     0x40010000, 0x01000000, 0x41000040, 0x00010040,
00054     0x01000040, 0x00010000, 0x01010000, 0x40000000,
00055     0x41010040, 0x40000040, 0x40000000, 0x41010000,
00056     0x00000000, 0x40010000, 0x01010040, 0x00000040,
00057     0x40000040, 0x41010040, 0x00010000, 0x41000000,
00058     0x41010000, 0x01000040, 0x40010040, 0x01010000,
00059     0x00010040, 0x00000000, 0x01000000, 0x40010040,
00060     0x01010040, 0x00000040, 0x40000000, 0x00010000,
00061     0x40000040, 0x40010000, 0x01010000, 0x41000040,
00062     0x00000000, 0x01010040, 0x00010040, 0x41010000,
00063     0x40010000, 0x01000000, 0x41010040, 0x40000000,
00064     0x40010040, 0x41000000, 0x01000000, 0x41010040,
00065     0x00010000, 0x01000040, 0x41000040, 0x00010040,
00066     0x01000040, 0x00000000, 0x41010000, 0x40000040,
00067     0x41000000, 0x40010040, 0x00000040, 0x01010000},
00068 
00069   {                         /* nibble 3 */
00070     0x00100402, 0x04000400, 0x00000002, 0x04100402,
00071     0x00000000, 0x04100000, 0x04000402, 0x00100002,
00072     0x04100400, 0x04000002, 0x04000000, 0x00000402,
00073     0x04000002, 0x00100402, 0x00100000, 0x04000000,
00074     0x04100002, 0x00100400, 0x00000400, 0x00000002,
00075     0x00100400, 0x04000402, 0x04100000, 0x00000400,
00076     0x00000402, 0x00000000, 0x00100002, 0x04100400,
00077     0x04000400, 0x04100002, 0x04100402, 0x00100000,
00078     0x04100002, 0x00000402, 0x00100000, 0x04000002,
00079     0x00100400, 0x04000400, 0x00000002, 0x04100000,
00080     0x04000402, 0x00000000, 0x00000400, 0x00100002,
00081     0x00000000, 0x04100002, 0x04100400, 0x00000400,
00082     0x04000000, 0x04100402, 0x00100402, 0x00100000,
00083     0x04100402, 0x00000002, 0x04000400, 0x00100402,
00084     0x00100002, 0x00100400, 0x04100000, 0x04000402,
00085     0x00000402, 0x04000000, 0x04000002, 0x04100400},
00086 
00087   {                         /* nibble 4 */
00088     0x02000000, 0x00004000, 0x00000100, 0x02004108,
00089     0x02004008, 0x02000100, 0x00004108, 0x02004000,
00090     0x00004000, 0x00000008, 0x02000008, 0x00004100,
00091     0x02000108, 0x02004008, 0x02004100, 0x00000000,
00092     0x00004100, 0x02000000, 0x00004008, 0x00000108,
00093     0x02000100, 0x00004108, 0x00000000, 0x02000008,
00094     0x00000008, 0x02000108, 0x02004108, 0x00004008,
00095     0x02004000, 0x00000100, 0x00000108, 0x02004100,
00096     0x02004100, 0x02000108, 0x00004008, 0x02004000,
00097     0x00004000, 0x00000008, 0x02000008, 0x02000100,
00098     0x02000000, 0x00004100, 0x02004108, 0x00000000,
00099     0x00004108, 0x02000000, 0x00000100, 0x00004008,
00100     0x02000108, 0x00000100, 0x00000000, 0x02004108,
00101     0x02004008, 0x02004100, 0x00000108, 0x00004000,
00102     0x00004100, 0x02004008, 0x02000100, 0x00000108,
00103     0x00000008, 0x00004108, 0x02004000, 0x02000008},
00104 
00105   {                         /* nibble 5 */
00106     0x20000010, 0x00080010, 0x00000000, 0x20080800,
00107     0x00080010, 0x00000800, 0x20000810, 0x00080000,
00108     0x00000810, 0x20080810, 0x00080800, 0x20000000,
00109     0x20000800, 0x20000010, 0x20080000, 0x00080810,
00110     0x00080000, 0x20000810, 0x20080010, 0x00000000,
00111     0x00000800, 0x00000010, 0x20080800, 0x20080010,
00112     0x20080810, 0x20080000, 0x20000000, 0x00000810,
00113     0x00000010, 0x00080800, 0x00080810, 0x20000800,
00114     0x00000810, 0x20000000, 0x20000800, 0x00080810,
00115     0x20080800, 0x00080010, 0x00000000, 0x20000800,
00116     0x20000000, 0x00000800, 0x20080010, 0x00080000,
00117     0x00080010, 0x20080810, 0x00080800, 0x00000010,
00118     0x20080810, 0x00080800, 0x00080000, 0x20000810,
00119     0x20000010, 0x20080000, 0x00080810, 0x00000000,
00120     0x00000800, 0x20000010, 0x20000810, 0x20080800,
00121     0x20080000, 0x00000810, 0x00000010, 0x20080010},
00122 
00123   {                         /* nibble 6 */
00124     0x00001000, 0x00000080, 0x00400080, 0x00400001,
00125     0x00401081, 0x00001001, 0x00001080, 0x00000000,
00126     0x00400000, 0x00400081, 0x00000081, 0x00401000,
00127     0x00000001, 0x00401080, 0x00401000, 0x00000081,
00128     0x00400081, 0x00001000, 0x00001001, 0x00401081,
00129     0x00000000, 0x00400080, 0x00400001, 0x00001080,
00130     0x00401001, 0x00001081, 0x00401080, 0x00000001,
00131     0x00001081, 0x00401001, 0x00000080, 0x00400000,
00132     0x00001081, 0x00401000, 0x00401001, 0x00000081,
00133     0x00001000, 0x00000080, 0x00400000, 0x00401001,
00134     0x00400081, 0x00001081, 0x00001080, 0x00000000,
00135     0x00000080, 0x00400001, 0x00000001, 0x00400080,
00136     0x00000000, 0x00400081, 0x00400080, 0x00001080,
00137     0x00000081, 0x00001000, 0x00401081, 0x00400000,
00138     0x00401080, 0x00000001, 0x00001001, 0x00401081,
00139     0x00400001, 0x00401080, 0x00401000, 0x00001001},
00140 
00141   {                         /* nibble 7 */
00142     0x08200020, 0x08208000, 0x00008020, 0x00000000,
00143     0x08008000, 0x00200020, 0x08200000, 0x08208020,
00144     0x00000020, 0x08000000, 0x00208000, 0x00008020,
00145     0x00208020, 0x08008020, 0x08000020, 0x08200000,
00146     0x00008000, 0x00208020, 0x00200020, 0x08008000,
00147     0x08208020, 0x08000020, 0x00000000, 0x00208000,
00148     0x08000000, 0x00200000, 0x08008020, 0x08200020,
00149     0x00200000, 0x00008000, 0x08208000, 0x00000020,
00150     0x00200000, 0x00008000, 0x08000020, 0x08208020,
00151     0x00008020, 0x08000000, 0x00000000, 0x00208000,
00152     0x08200020, 0x08008020, 0x08008000, 0x00200020,
00153     0x08208000, 0x00000020, 0x00200020, 0x08008000,
00154     0x08208020, 0x00200000, 0x08200000, 0x08000020,
00155     0x00208000, 0x00008020, 0x08008020, 0x08200000,
00156     0x00000020, 0x08208000, 0x00208020, 0x00000000,
00157     0x08000000, 0x08200020, 0x00008000, 0x00208020}};
00158 
00159 static const uint32_t des_skb[8][64] =
00160 {
00161   {                         /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
00162     0x00000000, 0x00000010, 0x20000000, 0x20000010,
00163     0x00010000, 0x00010010, 0x20010000, 0x20010010,
00164     0x00000800, 0x00000810, 0x20000800, 0x20000810,
00165     0x00010800, 0x00010810, 0x20010800, 0x20010810,
00166     0x00000020, 0x00000030, 0x20000020, 0x20000030,
00167     0x00010020, 0x00010030, 0x20010020, 0x20010030,
00168     0x00000820, 0x00000830, 0x20000820, 0x20000830,
00169     0x00010820, 0x00010830, 0x20010820, 0x20010830,
00170     0x00080000, 0x00080010, 0x20080000, 0x20080010,
00171     0x00090000, 0x00090010, 0x20090000, 0x20090010,
00172     0x00080800, 0x00080810, 0x20080800, 0x20080810,
00173     0x00090800, 0x00090810, 0x20090800, 0x20090810,
00174     0x00080020, 0x00080030, 0x20080020, 0x20080030,
00175     0x00090020, 0x00090030, 0x20090020, 0x20090030,
00176     0x00080820, 0x00080830, 0x20080820, 0x20080830,
00177     0x00090820, 0x00090830, 0x20090820, 0x20090830},
00178   {                         /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */
00179     0x00000000, 0x02000000, 0x00002000, 0x02002000,
00180     0x00200000, 0x02200000, 0x00202000, 0x02202000,
00181     0x00000004, 0x02000004, 0x00002004, 0x02002004,
00182     0x00200004, 0x02200004, 0x00202004, 0x02202004,
00183     0x00000400, 0x02000400, 0x00002400, 0x02002400,
00184     0x00200400, 0x02200400, 0x00202400, 0x02202400,
00185     0x00000404, 0x02000404, 0x00002404, 0x02002404,
00186     0x00200404, 0x02200404, 0x00202404, 0x02202404,
00187     0x10000000, 0x12000000, 0x10002000, 0x12002000,
00188     0x10200000, 0x12200000, 0x10202000, 0x12202000,
00189     0x10000004, 0x12000004, 0x10002004, 0x12002004,
00190     0x10200004, 0x12200004, 0x10202004, 0x12202004,
00191     0x10000400, 0x12000400, 0x10002400, 0x12002400,
00192     0x10200400, 0x12200400, 0x10202400, 0x12202400,
00193     0x10000404, 0x12000404, 0x10002404, 0x12002404,
00194     0x10200404, 0x12200404, 0x10202404, 0x12202404},
00195   {                         /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */
00196     0x00000000, 0x00000001, 0x00040000, 0x00040001,
00197     0x01000000, 0x01000001, 0x01040000, 0x01040001,
00198     0x00000002, 0x00000003, 0x00040002, 0x00040003,
00199     0x01000002, 0x01000003, 0x01040002, 0x01040003,
00200     0x00000200, 0x00000201, 0x00040200, 0x00040201,
00201     0x01000200, 0x01000201, 0x01040200, 0x01040201,
00202     0x00000202, 0x00000203, 0x00040202, 0x00040203,
00203     0x01000202, 0x01000203, 0x01040202, 0x01040203,
00204     0x08000000, 0x08000001, 0x08040000, 0x08040001,
00205     0x09000000, 0x09000001, 0x09040000, 0x09040001,
00206     0x08000002, 0x08000003, 0x08040002, 0x08040003,
00207     0x09000002, 0x09000003, 0x09040002, 0x09040003,
00208     0x08000200, 0x08000201, 0x08040200, 0x08040201,
00209     0x09000200, 0x09000201, 0x09040200, 0x09040201,
00210     0x08000202, 0x08000203, 0x08040202, 0x08040203,
00211     0x09000202, 0x09000203, 0x09040202, 0x09040203},
00212   {                         /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */
00213     0x00000000, 0x00100000, 0x00000100, 0x00100100,
00214     0x00000008, 0x00100008, 0x00000108, 0x00100108,
00215     0x00001000, 0x00101000, 0x00001100, 0x00101100,
00216     0x00001008, 0x00101008, 0x00001108, 0x00101108,
00217     0x04000000, 0x04100000, 0x04000100, 0x04100100,
00218     0x04000008, 0x04100008, 0x04000108, 0x04100108,
00219     0x04001000, 0x04101000, 0x04001100, 0x04101100,
00220     0x04001008, 0x04101008, 0x04001108, 0x04101108,
00221     0x00020000, 0x00120000, 0x00020100, 0x00120100,
00222     0x00020008, 0x00120008, 0x00020108, 0x00120108,
00223     0x00021000, 0x00121000, 0x00021100, 0x00121100,
00224     0x00021008, 0x00121008, 0x00021108, 0x00121108,
00225     0x04020000, 0x04120000, 0x04020100, 0x04120100,
00226     0x04020008, 0x04120008, 0x04020108, 0x04120108,
00227     0x04021000, 0x04121000, 0x04021100, 0x04121100,
00228     0x04021008, 0x04121008, 0x04021108, 0x04121108},
00229   {                         /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */
00230     0x00000000, 0x10000000, 0x00010000, 0x10010000,
00231     0x00000004, 0x10000004, 0x00010004, 0x10010004,
00232     0x20000000, 0x30000000, 0x20010000, 0x30010000,
00233     0x20000004, 0x30000004, 0x20010004, 0x30010004,
00234     0x00100000, 0x10100000, 0x00110000, 0x10110000,
00235     0x00100004, 0x10100004, 0x00110004, 0x10110004,
00236     0x20100000, 0x30100000, 0x20110000, 0x30110000,
00237     0x20100004, 0x30100004, 0x20110004, 0x30110004,
00238     0x00001000, 0x10001000, 0x00011000, 0x10011000,
00239     0x00001004, 0x10001004, 0x00011004, 0x10011004,
00240     0x20001000, 0x30001000, 0x20011000, 0x30011000,
00241     0x20001004, 0x30001004, 0x20011004, 0x30011004,
00242     0x00101000, 0x10101000, 0x00111000, 0x10111000,
00243     0x00101004, 0x10101004, 0x00111004, 0x10111004,
00244     0x20101000, 0x30101000, 0x20111000, 0x30111000,
00245     0x20101004, 0x30101004, 0x20111004, 0x30111004},
00246   {                         /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */
00247     0x00000000, 0x08000000, 0x00000008, 0x08000008,
00248     0x00000400, 0x08000400, 0x00000408, 0x08000408,
00249     0x00020000, 0x08020000, 0x00020008, 0x08020008,
00250     0x00020400, 0x08020400, 0x00020408, 0x08020408,
00251     0x00000001, 0x08000001, 0x00000009, 0x08000009,
00252     0x00000401, 0x08000401, 0x00000409, 0x08000409,
00253     0x00020001, 0x08020001, 0x00020009, 0x08020009,
00254     0x00020401, 0x08020401, 0x00020409, 0x08020409,
00255     0x02000000, 0x0A000000, 0x02000008, 0x0A000008,
00256     0x02000400, 0x0A000400, 0x02000408, 0x0A000408,
00257     0x02020000, 0x0A020000, 0x02020008, 0x0A020008,
00258     0x02020400, 0x0A020400, 0x02020408, 0x0A020408,
00259     0x02000001, 0x0A000001, 0x02000009, 0x0A000009,
00260     0x02000401, 0x0A000401, 0x02000409, 0x0A000409,
00261     0x02020001, 0x0A020001, 0x02020009, 0x0A020009,
00262     0x02020401, 0x0A020401, 0x02020409, 0x0A020409},
00263   {                         /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */
00264     0x00000000, 0x00000100, 0x00080000, 0x00080100,
00265     0x01000000, 0x01000100, 0x01080000, 0x01080100,
00266     0x00000010, 0x00000110, 0x00080010, 0x00080110,
00267     0x01000010, 0x01000110, 0x01080010, 0x01080110,
00268     0x00200000, 0x00200100, 0x00280000, 0x00280100,
00269     0x01200000, 0x01200100, 0x01280000, 0x01280100,
00270     0x00200010, 0x00200110, 0x00280010, 0x00280110,
00271     0x01200010, 0x01200110, 0x01280010, 0x01280110,
00272     0x00000200, 0x00000300, 0x00080200, 0x00080300,
00273     0x01000200, 0x01000300, 0x01080200, 0x01080300,
00274     0x00000210, 0x00000310, 0x00080210, 0x00080310,
00275     0x01000210, 0x01000310, 0x01080210, 0x01080310,
00276     0x00200200, 0x00200300, 0x00280200, 0x00280300,
00277     0x01200200, 0x01200300, 0x01280200, 0x01280300,
00278     0x00200210, 0x00200310, 0x00280210, 0x00280310,
00279     0x01200210, 0x01200310, 0x01280210, 0x01280310},
00280   {                         /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */
00281     0x00000000, 0x04000000, 0x00040000, 0x04040000,
00282     0x00000002, 0x04000002, 0x00040002, 0x04040002,
00283     0x00002000, 0x04002000, 0x00042000, 0x04042000,
00284     0x00002002, 0x04002002, 0x00042002, 0x04042002,
00285     0x00000020, 0x04000020, 0x00040020, 0x04040020,
00286     0x00000022, 0x04000022, 0x00040022, 0x04040022,
00287     0x00002020, 0x04002020, 0x00042020, 0x04042020,
00288     0x00002022, 0x04002022, 0x00042022, 0x04042022,
00289     0x00000800, 0x04000800, 0x00040800, 0x04040800,
00290     0x00000802, 0x04000802, 0x00040802, 0x04040802,
00291     0x00002800, 0x04002800, 0x00042800, 0x04042800,
00292     0x00002802, 0x04002802, 0x00042802, 0x04042802,
00293     0x00000820, 0x04000820, 0x00040820, 0x04040820,
00294     0x00000822, 0x04000822, 0x00040822, 0x04040822,
00295     0x00002820, 0x04002820, 0x00042820, 0x04042820,
00296     0x00002822, 0x04002822, 0x00042822, 0x04042822},
00297 };
00298 
00299 #define c2l(c,l)     (l =((unsigned long)(*((c)++)))    , \
00300                       l|=((unsigned long)(*((c)++)))<< 8, \
00301                       l|=((unsigned long)(*((c)++)))<<16, \
00302                       l|=((unsigned long)(*((c)++)))<<24)
00303 
00304 #define l2c(l,c)     (*((c)++)=(unsigned char)(((l)    )&0xff), \
00305                       *((c)++)=(unsigned char)(((l)>> 8)&0xff), \
00306                       *((c)++)=(unsigned char)(((l)>>16)&0xff), \
00307                       *((c)++)=(unsigned char)(((l)>>24)&0xff))
00308 
00309 /*
00310  * IP and FP
00311  * The problem is more of a geometric problem that random bit fiddling.
00312  *  0  1  2  3  4  5  6  7      62 54 46 38 30 22 14  6
00313  *  8  9 10 11 12 13 14 15      60 52 44 36 28 20 12  4
00314  * 16 17 18 19 20 21 22 23      58 50 42 34 26 18 10  2
00315  * 24 25 26 27 28 29 30 31  to  56 48 40 32 24 16  8  0
00316  *
00317  * 32 33 34 35 36 37 38 39      63 55 47 39 31 23 15  7
00318  * 40 41 42 43 44 45 46 47      61 53 45 37 29 21 13  5
00319  * 48 49 50 51 52 53 54 55      59 51 43 35 27 19 11  3
00320  * 56 57 58 59 60 61 62 63      57 49 41 33 25 17  9  1
00321  *
00322  * The output has been subject to swaps of the form
00323  * 0 1 -> 3 1 but the odd and even bits have been put into
00324  * 2 3    2 0
00325  * different words.  The main trick is to remember that
00326  * t=((l>>size)^r)&(mask);
00327  * r^=t;
00328  * l^=(t<<size);
00329  * can be used to swap and move bits between words.
00330  *
00331  * So l =  0  1  2  3  r = 16 17 18 19
00332  *         4  5  6  7      20 21 22 23
00333  *         8  9 10 11      24 25 26 27
00334  *        12 13 14 15      28 29 30 31
00335  * becomes (for size == 2 and mask == 0x3333)
00336  * t =   2^16  3^17 -- --   l =  0  1 16 17  r =  2  3 18 19
00337  *       6^20  7^21 -- --        4  5 20 21       6  7 22 23
00338  *      10^24 11^25 -- --        8  9 24 25      10 11 24 25
00339  *      14^28 15^29 -- --       12 13 28 29      14 15 28 29
00340  *
00341  * Thanks for hints from Richard Outerbridge - he told me IP&FP
00342  * could be done in 15 xor, 10 shifts and 5 ands.
00343  * When I finally started to think of the problem in 2D
00344  * I first got ~42 operations without xors.  When I remembered
00345  * how to use xors :-) I got it to its final state.
00346  */
00347 
00348 #define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\
00349        (b)^=(t),\
00350        (a)^=((t)<<(n)))
00351 
00352 #define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\
00353        (a)=(a)^(t)^(t>>(16-(n))))
00354 
00355 
00356 #define D_ENCRYPT(L,R,S)    \
00357        u=(R^s[S  ]); \
00358        t=R^s[S+1]; \
00359        t=((t>>4)+(t<<28)); \
00360        L^=    des_SPtrans[1][(t    )&0x3f]| \
00361               des_SPtrans[3][(t>> 8)&0x3f]| \
00362               des_SPtrans[5][(t>>16)&0x3f]| \
00363               des_SPtrans[7][(t>>24)&0x3f]| \
00364               des_SPtrans[0][(u    )&0x3f]| \
00365               des_SPtrans[2][(u>> 8)&0x3f]| \
00366               des_SPtrans[4][(u>>16)&0x3f]| \
00367               des_SPtrans[6][(u>>24)&0x3f];
00368 
00369 #define ITERATIONS 16
00370 
00371 static const char shifts2[16] =
00372 {0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0};
00373 
00374 static void des_set_key (unsigned char *, unsigned long *) internal_function;
00375 static void des_encrypt (unsigned long *, unsigned long *, int)
00376      internal_function;
00377 int _des_crypt (char *, unsigned, struct desparams *);
00378 
00379 static void
00380 internal_function
00381 des_set_key (unsigned char *key, unsigned long *schedule)
00382 {
00383   register unsigned long c, d, t, s;
00384   register unsigned char *in;
00385   register unsigned long *k;
00386   register int i;
00387 
00388   k = (unsigned long *) schedule;
00389   in = key;
00390 
00391   c2l (in, c);
00392   c2l (in, d);
00393 
00394   /* I now do it in 47 simple operations :-)
00395    * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov)
00396    * for the inspiration. :-) */
00397   PERM_OP (d, c, t, 4, 0x0f0f0f0f);
00398   HPERM_OP (c, t, -2, 0xcccc0000);
00399   HPERM_OP (d, t, -2, 0xcccc0000);
00400   PERM_OP (d, c, t, 1, 0x55555555);
00401   PERM_OP (c, d, t, 8, 0x00ff00ff);
00402   PERM_OP (d, c, t, 1, 0x55555555);
00403   d = (((d & 0x000000ff) << 16) | (d & 0x0000ff00) |
00404        ((d & 0x00ff0000) >> 16) | ((c & 0xf0000000) >> 4));
00405   c &= 0x0fffffff;
00406 
00407   for (i = 0; i < ITERATIONS; i++)
00408     {
00409       if (shifts2[i])
00410        {
00411          c = ((c >> 2) | (c << 26));
00412          d = ((d >> 2) | (d << 26));
00413        }
00414       else
00415        {
00416          c = ((c >> 1) | (c << 27));
00417          d = ((d >> 1) | (d << 27));
00418        }
00419       c &= 0x0fffffff;
00420       d &= 0x0fffffff;
00421       /* could be a few less shifts but I am to lazy at this
00422        * point in time to investigate */
00423       s = des_skb[0][(c) & 0x3f] |
00424        des_skb[1][((c >> 6) & 0x03) | ((c >> 7) & 0x3c)] |
00425        des_skb[2][((c >> 13) & 0x0f) | ((c >> 14) & 0x30)] |
00426        des_skb[3][((c >> 20) & 0x01) | ((c >> 21) & 0x06) | ((c >> 22) & 0x38)];
00427       t = des_skb[4][(d) & 0x3f] |
00428        des_skb[5][((d >> 7) & 0x03) | ((d >> 8) & 0x3c)] |
00429        des_skb[6][(d >> 15) & 0x3f] |
00430        des_skb[7][((d >> 21) & 0x0f) | ((d >> 22) & 0x30)];
00431 
00432       /* table contained 0213 4657 */
00433       *(k++) = ((t << 16) | (s & 0x0000ffff)) & 0xffffffff;
00434       s = ((s >> 16) | (t & 0xffff0000));
00435 
00436       s = (s << 4) | (s >> 28);
00437       *(k++) = s & 0xffffffff;
00438     }
00439 }
00440 
00441 
00442 static void
00443 internal_function
00444 des_encrypt (unsigned long *buf, unsigned long *schedule, int encrypt)
00445 {
00446   register unsigned long l, r, t, u;
00447   register int i;
00448   register unsigned long *s;
00449 
00450   l = buf[0];
00451   r = buf[1];
00452 
00453   /* do IP */
00454   PERM_OP (r, l, t, 4, 0x0f0f0f0f);
00455   PERM_OP (l, r, t, 16, 0x0000ffff);
00456   PERM_OP (r, l, t, 2, 0x33333333);
00457   PERM_OP (l, r, t, 8, 0x00ff00ff);
00458   PERM_OP (r, l, t, 1, 0x55555555);
00459   /* r and l are reversed - remember that :-) - fix
00460    * it in the next step */
00461 
00462   /* Things have been modified so that the initial rotate is
00463    * done outside the loop.  This required the
00464    * des_SPtrans values in sp.h to be rotated 1 bit to the right.
00465    * One perl script later and things have a 5% speed up on a sparc2.
00466    * Thanks to Richard Outerbridge <71755.204@CompuServe.COM>
00467    * for pointing this out. */
00468   t = (r << 1) | (r >> 31);
00469   r = (l << 1) | (l >> 31);
00470   l = t;
00471 
00472   /* clear the top bits on machines with 8byte longs */
00473   l &= 0xffffffff;
00474   r &= 0xffffffff;
00475 
00476   s = (unsigned long *) schedule;
00477   /* I don't know if it is worth the effort of loop unrolling the
00478    * inner loop */
00479   if (encrypt)
00480     {
00481       for (i = 0; i < 32; i += 4)
00482        {
00483          D_ENCRYPT (l, r, i + 0);  /*  1 */
00484          D_ENCRYPT (r, l, i + 2);  /*  2 */
00485        }
00486     }
00487   else
00488     {
00489       for (i = 30; i > 0; i -= 4)
00490        {
00491          D_ENCRYPT (l, r, i - 0);  /* 16 */
00492          D_ENCRYPT (r, l, i - 2);  /* 15 */
00493        }
00494     }
00495   l = (l >> 1) | (l << 31);
00496   r = (r >> 1) | (r << 31);
00497   /* clear the top bits on machines with 8byte longs */
00498   l &= 0xffffffff;
00499   r &= 0xffffffff;
00500 
00501   /* swap l and r
00502    * we will not do the swap so just remember they are
00503    * reversed for the rest of the subroutine
00504    * luckily FP fixes this problem :-) */
00505 
00506   PERM_OP (r, l, t, 1, 0x55555555);
00507   PERM_OP (l, r, t, 8, 0x00ff00ff);
00508   PERM_OP (r, l, t, 2, 0x33333333);
00509   PERM_OP (l, r, t, 16, 0x0000ffff);
00510   PERM_OP (r, l, t, 4, 0x0f0f0f0f);
00511 
00512   buf[0] = l;
00513   buf[1] = r;
00514 
00515   l = r = t = u = 0;
00516 }
00517 
00518 
00519 int
00520 _des_crypt (char *buf, unsigned len, struct desparams *desp)
00521 {
00522   unsigned long schedule[32];
00523   register unsigned long tin0, tin1;
00524   register unsigned long tout0, tout1, xor0, xor1;
00525   register unsigned char *in, *out;
00526   unsigned long tbuf[2];
00527   unsigned char *iv, *oiv;
00528   int cbc_mode;
00529 
00530   cbc_mode = (desp->des_mode == CBC) ? 1 : 0;
00531 
00532   in = (unsigned char *) buf;
00533   out = (unsigned char *) buf;
00534   oiv = iv = (unsigned char *) desp->des_ivec;
00535 
00536   des_set_key (desp->des_key, schedule);
00537 
00538   tin0 = tin1 = 0;          /* For GCC */
00539   if (desp->des_dir == ENCRYPT)
00540     {
00541       c2l (iv, tout0);
00542       c2l (iv, tout1);
00543       for (; len > 0; len -= 8)
00544        {
00545          c2l (in, tin0);
00546          c2l (in, tin1);
00547          if (cbc_mode)
00548            {
00549              tin0 ^= tout0;
00550              tin1 ^= tout1;
00551            }
00552          tbuf[0] = tin0;
00553          tbuf[1] = tin1;
00554          des_encrypt (tbuf, schedule, 1);
00555          tout0 = tbuf[0];
00556          tout1 = tbuf[1];
00557          l2c (tout0, out);
00558          l2c (tout1, out);
00559        }
00560       l2c (tout0, oiv);
00561       l2c (tout1, oiv);
00562     }
00563   else
00564     {
00565       c2l (iv, xor0);
00566       c2l (iv, xor1);
00567       for (; len > 0; len -= 8)
00568        {
00569          c2l (in, tin0);
00570          c2l (in, tin1);
00571          tbuf[0] = tin0;
00572          tbuf[1] = tin1;
00573          des_encrypt (tbuf, schedule, 0);
00574          if (cbc_mode)
00575            {
00576              tout0 = tbuf[0] ^ xor0;
00577              tout1 = tbuf[1] ^ xor1;
00578              xor0 = tin0;
00579              xor1 = tin1;
00580            }
00581          else
00582            {
00583              tout0 = tbuf[0];
00584              tout1 = tbuf[1];
00585            }
00586          l2c (tout0, out);
00587          l2c (tout1, out);
00588        }
00589       l2c (tin0, oiv);
00590       l2c (tin1, oiv);
00591     }
00592   tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0;
00593   tbuf[0] = tbuf[1] = 0;
00594   __bzero (schedule, sizeof (schedule));
00595 
00596   return (1);
00597 }