tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

des.c (27537B)


      1 /*
      2 *  des.c
      3 *
      4 *  core source file for DES-150 library
      5 *  Make key schedule from DES key.
      6 *  Encrypt/Decrypt one 8-byte block.
      7 *
      8 * This Source Code Form is subject to the terms of the Mozilla Public
      9 * License, v. 2.0. If a copy of the MPL was not distributed with this
     10 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     11 
     12 #include "des.h"
     13 #include "blapii.h"
     14 #include <stddef.h> /* for ptrdiff_t */
     15 /* #define USE_INDEXING 1 */
     16 
     17 /*
     18 * The tables below are the 8 sbox functions, with the 6-bit input permutation
     19 * and the 32-bit output permutation pre-computed.
     20 * They are shifted circularly to the left 3 bits, which removes 2 shifts
     21 * and an or from each round by reducing the number of sboxes whose
     22 * indices cross word broundaries from 2 to 1.
     23 */
     24 
     25 static const HALF SP[8][64] = {
     26    /* Box S1 */
     27    { 0x04041000, 0x00000000, 0x00040000, 0x04041010,
     28      0x04040010, 0x00041010, 0x00000010, 0x00040000,
     29      0x00001000, 0x04041000, 0x04041010, 0x00001000,
     30      0x04001010, 0x04040010, 0x04000000, 0x00000010,
     31      0x00001010, 0x04001000, 0x04001000, 0x00041000,
     32      0x00041000, 0x04040000, 0x04040000, 0x04001010,
     33      0x00040010, 0x04000010, 0x04000010, 0x00040010,
     34      0x00000000, 0x00001010, 0x00041010, 0x04000000,
     35      0x00040000, 0x04041010, 0x00000010, 0x04040000,
     36      0x04041000, 0x04000000, 0x04000000, 0x00001000,
     37      0x04040010, 0x00040000, 0x00041000, 0x04000010,
     38      0x00001000, 0x00000010, 0x04001010, 0x00041010,
     39      0x04041010, 0x00040010, 0x04040000, 0x04001010,
     40      0x04000010, 0x00001010, 0x00041010, 0x04041000,
     41      0x00001010, 0x04001000, 0x04001000, 0x00000000,
     42      0x00040010, 0x00041000, 0x00000000, 0x04040010 },
     43    /* Box S2 */
     44    { 0x00420082, 0x00020002, 0x00020000, 0x00420080,
     45      0x00400000, 0x00000080, 0x00400082, 0x00020082,
     46      0x00000082, 0x00420082, 0x00420002, 0x00000002,
     47      0x00020002, 0x00400000, 0x00000080, 0x00400082,
     48      0x00420000, 0x00400080, 0x00020082, 0x00000000,
     49      0x00000002, 0x00020000, 0x00420080, 0x00400002,
     50      0x00400080, 0x00000082, 0x00000000, 0x00420000,
     51      0x00020080, 0x00420002, 0x00400002, 0x00020080,
     52      0x00000000, 0x00420080, 0x00400082, 0x00400000,
     53      0x00020082, 0x00400002, 0x00420002, 0x00020000,
     54      0x00400002, 0x00020002, 0x00000080, 0x00420082,
     55      0x00420080, 0x00000080, 0x00020000, 0x00000002,
     56      0x00020080, 0x00420002, 0x00400000, 0x00000082,
     57      0x00400080, 0x00020082, 0x00000082, 0x00400080,
     58      0x00420000, 0x00000000, 0x00020002, 0x00020080,
     59      0x00000002, 0x00400082, 0x00420082, 0x00420000 },
     60    /* Box S3 */
     61    { 0x00000820, 0x20080800, 0x00000000, 0x20080020,
     62      0x20000800, 0x00000000, 0x00080820, 0x20000800,
     63      0x00080020, 0x20000020, 0x20000020, 0x00080000,
     64      0x20080820, 0x00080020, 0x20080000, 0x00000820,
     65      0x20000000, 0x00000020, 0x20080800, 0x00000800,
     66      0x00080800, 0x20080000, 0x20080020, 0x00080820,
     67      0x20000820, 0x00080800, 0x00080000, 0x20000820,
     68      0x00000020, 0x20080820, 0x00000800, 0x20000000,
     69      0x20080800, 0x20000000, 0x00080020, 0x00000820,
     70      0x00080000, 0x20080800, 0x20000800, 0x00000000,
     71      0x00000800, 0x00080020, 0x20080820, 0x20000800,
     72      0x20000020, 0x00000800, 0x00000000, 0x20080020,
     73      0x20000820, 0x00080000, 0x20000000, 0x20080820,
     74      0x00000020, 0x00080820, 0x00080800, 0x20000020,
     75      0x20080000, 0x20000820, 0x00000820, 0x20080000,
     76      0x00080820, 0x00000020, 0x20080020, 0x00080800 },
     77    /* Box S4 */
     78    { 0x02008004, 0x00008204, 0x00008204, 0x00000200,
     79      0x02008200, 0x02000204, 0x02000004, 0x00008004,
     80      0x00000000, 0x02008000, 0x02008000, 0x02008204,
     81      0x00000204, 0x00000000, 0x02000200, 0x02000004,
     82      0x00000004, 0x00008000, 0x02000000, 0x02008004,
     83      0x00000200, 0x02000000, 0x00008004, 0x00008200,
     84      0x02000204, 0x00000004, 0x00008200, 0x02000200,
     85      0x00008000, 0x02008200, 0x02008204, 0x00000204,
     86      0x02000200, 0x02000004, 0x02008000, 0x02008204,
     87      0x00000204, 0x00000000, 0x00000000, 0x02008000,
     88      0x00008200, 0x02000200, 0x02000204, 0x00000004,
     89      0x02008004, 0x00008204, 0x00008204, 0x00000200,
     90      0x02008204, 0x00000204, 0x00000004, 0x00008000,
     91      0x02000004, 0x00008004, 0x02008200, 0x02000204,
     92      0x00008004, 0x00008200, 0x02000000, 0x02008004,
     93      0x00000200, 0x02000000, 0x00008000, 0x02008200 },
     94    /* Box S5 */
     95    { 0x00000400, 0x08200400, 0x08200000, 0x08000401,
     96      0x00200000, 0x00000400, 0x00000001, 0x08200000,
     97      0x00200401, 0x00200000, 0x08000400, 0x00200401,
     98      0x08000401, 0x08200001, 0x00200400, 0x00000001,
     99      0x08000000, 0x00200001, 0x00200001, 0x00000000,
    100      0x00000401, 0x08200401, 0x08200401, 0x08000400,
    101      0x08200001, 0x00000401, 0x00000000, 0x08000001,
    102      0x08200400, 0x08000000, 0x08000001, 0x00200400,
    103      0x00200000, 0x08000401, 0x00000400, 0x08000000,
    104      0x00000001, 0x08200000, 0x08000401, 0x00200401,
    105      0x08000400, 0x00000001, 0x08200001, 0x08200400,
    106      0x00200401, 0x00000400, 0x08000000, 0x08200001,
    107      0x08200401, 0x00200400, 0x08000001, 0x08200401,
    108      0x08200000, 0x00000000, 0x00200001, 0x08000001,
    109      0x00200400, 0x08000400, 0x00000401, 0x00200000,
    110      0x00000000, 0x00200001, 0x08200400, 0x00000401 },
    111    /* Box S6 */
    112    { 0x80000040, 0x81000000, 0x00010000, 0x81010040,
    113      0x81000000, 0x00000040, 0x81010040, 0x01000000,
    114      0x80010000, 0x01010040, 0x01000000, 0x80000040,
    115      0x01000040, 0x80010000, 0x80000000, 0x00010040,
    116      0x00000000, 0x01000040, 0x80010040, 0x00010000,
    117      0x01010000, 0x80010040, 0x00000040, 0x81000040,
    118      0x81000040, 0x00000000, 0x01010040, 0x81010000,
    119      0x00010040, 0x01010000, 0x81010000, 0x80000000,
    120      0x80010000, 0x00000040, 0x81000040, 0x01010000,
    121      0x81010040, 0x01000000, 0x00010040, 0x80000040,
    122      0x01000000, 0x80010000, 0x80000000, 0x00010040,
    123      0x80000040, 0x81010040, 0x01010000, 0x81000000,
    124      0x01010040, 0x81010000, 0x00000000, 0x81000040,
    125      0x00000040, 0x00010000, 0x81000000, 0x01010040,
    126      0x00010000, 0x01000040, 0x80010040, 0x00000000,
    127      0x81010000, 0x80000000, 0x01000040, 0x80010040 },
    128    /* Box S7 */
    129    { 0x00800000, 0x10800008, 0x10002008, 0x00000000,
    130      0x00002000, 0x10002008, 0x00802008, 0x10802000,
    131      0x10802008, 0x00800000, 0x00000000, 0x10000008,
    132      0x00000008, 0x10000000, 0x10800008, 0x00002008,
    133      0x10002000, 0x00802008, 0x00800008, 0x10002000,
    134      0x10000008, 0x10800000, 0x10802000, 0x00800008,
    135      0x10800000, 0x00002000, 0x00002008, 0x10802008,
    136      0x00802000, 0x00000008, 0x10000000, 0x00802000,
    137      0x10000000, 0x00802000, 0x00800000, 0x10002008,
    138      0x10002008, 0x10800008, 0x10800008, 0x00000008,
    139      0x00800008, 0x10000000, 0x10002000, 0x00800000,
    140      0x10802000, 0x00002008, 0x00802008, 0x10802000,
    141      0x00002008, 0x10000008, 0x10802008, 0x10800000,
    142      0x00802000, 0x00000000, 0x00000008, 0x10802008,
    143      0x00000000, 0x00802008, 0x10800000, 0x00002000,
    144      0x10000008, 0x10002000, 0x00002000, 0x00800008 },
    145    /* Box S8 */
    146    { 0x40004100, 0x00004000, 0x00100000, 0x40104100,
    147      0x40000000, 0x40004100, 0x00000100, 0x40000000,
    148      0x00100100, 0x40100000, 0x40104100, 0x00104000,
    149      0x40104000, 0x00104100, 0x00004000, 0x00000100,
    150      0x40100000, 0x40000100, 0x40004000, 0x00004100,
    151      0x00104000, 0x00100100, 0x40100100, 0x40104000,
    152      0x00004100, 0x00000000, 0x00000000, 0x40100100,
    153      0x40000100, 0x40004000, 0x00104100, 0x00100000,
    154      0x00104100, 0x00100000, 0x40104000, 0x00004000,
    155      0x00000100, 0x40100100, 0x00004000, 0x00104100,
    156      0x40004000, 0x00000100, 0x40000100, 0x40100000,
    157      0x40100100, 0x40000000, 0x00100000, 0x40004100,
    158      0x00000000, 0x40104100, 0x00100100, 0x40000100,
    159      0x40100000, 0x40004000, 0x40004100, 0x00000000,
    160      0x40104100, 0x00104000, 0x00104000, 0x00004100,
    161      0x00004100, 0x00100100, 0x40000000, 0x40104000 }
    162 };
    163 
    164 static const HALF PC2[8][64] = {
    165    /* table 0 */
    166    { 0x00000000, 0x00001000, 0x04000000, 0x04001000,
    167      0x00100000, 0x00101000, 0x04100000, 0x04101000,
    168      0x00008000, 0x00009000, 0x04008000, 0x04009000,
    169      0x00108000, 0x00109000, 0x04108000, 0x04109000,
    170      0x00000004, 0x00001004, 0x04000004, 0x04001004,
    171      0x00100004, 0x00101004, 0x04100004, 0x04101004,
    172      0x00008004, 0x00009004, 0x04008004, 0x04009004,
    173      0x00108004, 0x00109004, 0x04108004, 0x04109004,
    174      0x08000000, 0x08001000, 0x0c000000, 0x0c001000,
    175      0x08100000, 0x08101000, 0x0c100000, 0x0c101000,
    176      0x08008000, 0x08009000, 0x0c008000, 0x0c009000,
    177      0x08108000, 0x08109000, 0x0c108000, 0x0c109000,
    178      0x08000004, 0x08001004, 0x0c000004, 0x0c001004,
    179      0x08100004, 0x08101004, 0x0c100004, 0x0c101004,
    180      0x08008004, 0x08009004, 0x0c008004, 0x0c009004,
    181      0x08108004, 0x08109004, 0x0c108004, 0x0c109004 },
    182    /* table 1 */
    183    { 0x00000000, 0x00002000, 0x80000000, 0x80002000,
    184      0x00000008, 0x00002008, 0x80000008, 0x80002008,
    185      0x00200000, 0x00202000, 0x80200000, 0x80202000,
    186      0x00200008, 0x00202008, 0x80200008, 0x80202008,
    187      0x20000000, 0x20002000, 0xa0000000, 0xa0002000,
    188      0x20000008, 0x20002008, 0xa0000008, 0xa0002008,
    189      0x20200000, 0x20202000, 0xa0200000, 0xa0202000,
    190      0x20200008, 0x20202008, 0xa0200008, 0xa0202008,
    191      0x00000400, 0x00002400, 0x80000400, 0x80002400,
    192      0x00000408, 0x00002408, 0x80000408, 0x80002408,
    193      0x00200400, 0x00202400, 0x80200400, 0x80202400,
    194      0x00200408, 0x00202408, 0x80200408, 0x80202408,
    195      0x20000400, 0x20002400, 0xa0000400, 0xa0002400,
    196      0x20000408, 0x20002408, 0xa0000408, 0xa0002408,
    197      0x20200400, 0x20202400, 0xa0200400, 0xa0202400,
    198      0x20200408, 0x20202408, 0xa0200408, 0xa0202408 },
    199    /* table 2 */
    200    { 0x00000000, 0x00004000, 0x00000020, 0x00004020,
    201      0x00080000, 0x00084000, 0x00080020, 0x00084020,
    202      0x00000800, 0x00004800, 0x00000820, 0x00004820,
    203      0x00080800, 0x00084800, 0x00080820, 0x00084820,
    204      0x00000010, 0x00004010, 0x00000030, 0x00004030,
    205      0x00080010, 0x00084010, 0x00080030, 0x00084030,
    206      0x00000810, 0x00004810, 0x00000830, 0x00004830,
    207      0x00080810, 0x00084810, 0x00080830, 0x00084830,
    208      0x00400000, 0x00404000, 0x00400020, 0x00404020,
    209      0x00480000, 0x00484000, 0x00480020, 0x00484020,
    210      0x00400800, 0x00404800, 0x00400820, 0x00404820,
    211      0x00480800, 0x00484800, 0x00480820, 0x00484820,
    212      0x00400010, 0x00404010, 0x00400030, 0x00404030,
    213      0x00480010, 0x00484010, 0x00480030, 0x00484030,
    214      0x00400810, 0x00404810, 0x00400830, 0x00404830,
    215      0x00480810, 0x00484810, 0x00480830, 0x00484830 },
    216    /* table 3 */
    217    { 0x00000000, 0x40000000, 0x00000080, 0x40000080,
    218      0x00040000, 0x40040000, 0x00040080, 0x40040080,
    219      0x00000040, 0x40000040, 0x000000c0, 0x400000c0,
    220      0x00040040, 0x40040040, 0x000400c0, 0x400400c0,
    221      0x10000000, 0x50000000, 0x10000080, 0x50000080,
    222      0x10040000, 0x50040000, 0x10040080, 0x50040080,
    223      0x10000040, 0x50000040, 0x100000c0, 0x500000c0,
    224      0x10040040, 0x50040040, 0x100400c0, 0x500400c0,
    225      0x00800000, 0x40800000, 0x00800080, 0x40800080,
    226      0x00840000, 0x40840000, 0x00840080, 0x40840080,
    227      0x00800040, 0x40800040, 0x008000c0, 0x408000c0,
    228      0x00840040, 0x40840040, 0x008400c0, 0x408400c0,
    229      0x10800000, 0x50800000, 0x10800080, 0x50800080,
    230      0x10840000, 0x50840000, 0x10840080, 0x50840080,
    231      0x10800040, 0x50800040, 0x108000c0, 0x508000c0,
    232      0x10840040, 0x50840040, 0x108400c0, 0x508400c0 },
    233    /* table 4 */
    234    { 0x00000000, 0x00000008, 0x08000000, 0x08000008,
    235      0x00040000, 0x00040008, 0x08040000, 0x08040008,
    236      0x00002000, 0x00002008, 0x08002000, 0x08002008,
    237      0x00042000, 0x00042008, 0x08042000, 0x08042008,
    238      0x80000000, 0x80000008, 0x88000000, 0x88000008,
    239      0x80040000, 0x80040008, 0x88040000, 0x88040008,
    240      0x80002000, 0x80002008, 0x88002000, 0x88002008,
    241      0x80042000, 0x80042008, 0x88042000, 0x88042008,
    242      0x00080000, 0x00080008, 0x08080000, 0x08080008,
    243      0x000c0000, 0x000c0008, 0x080c0000, 0x080c0008,
    244      0x00082000, 0x00082008, 0x08082000, 0x08082008,
    245      0x000c2000, 0x000c2008, 0x080c2000, 0x080c2008,
    246      0x80080000, 0x80080008, 0x88080000, 0x88080008,
    247      0x800c0000, 0x800c0008, 0x880c0000, 0x880c0008,
    248      0x80082000, 0x80082008, 0x88082000, 0x88082008,
    249      0x800c2000, 0x800c2008, 0x880c2000, 0x880c2008 },
    250    /* table 5 */
    251    { 0x00000000, 0x00400000, 0x00008000, 0x00408000,
    252      0x40000000, 0x40400000, 0x40008000, 0x40408000,
    253      0x00000020, 0x00400020, 0x00008020, 0x00408020,
    254      0x40000020, 0x40400020, 0x40008020, 0x40408020,
    255      0x00001000, 0x00401000, 0x00009000, 0x00409000,
    256      0x40001000, 0x40401000, 0x40009000, 0x40409000,
    257      0x00001020, 0x00401020, 0x00009020, 0x00409020,
    258      0x40001020, 0x40401020, 0x40009020, 0x40409020,
    259      0x00100000, 0x00500000, 0x00108000, 0x00508000,
    260      0x40100000, 0x40500000, 0x40108000, 0x40508000,
    261      0x00100020, 0x00500020, 0x00108020, 0x00508020,
    262      0x40100020, 0x40500020, 0x40108020, 0x40508020,
    263      0x00101000, 0x00501000, 0x00109000, 0x00509000,
    264      0x40101000, 0x40501000, 0x40109000, 0x40509000,
    265      0x00101020, 0x00501020, 0x00109020, 0x00509020,
    266      0x40101020, 0x40501020, 0x40109020, 0x40509020 },
    267    /* table 6 */
    268    { 0x00000000, 0x00000040, 0x04000000, 0x04000040,
    269      0x00000800, 0x00000840, 0x04000800, 0x04000840,
    270      0x00800000, 0x00800040, 0x04800000, 0x04800040,
    271      0x00800800, 0x00800840, 0x04800800, 0x04800840,
    272      0x10000000, 0x10000040, 0x14000000, 0x14000040,
    273      0x10000800, 0x10000840, 0x14000800, 0x14000840,
    274      0x10800000, 0x10800040, 0x14800000, 0x14800040,
    275      0x10800800, 0x10800840, 0x14800800, 0x14800840,
    276      0x00000080, 0x000000c0, 0x04000080, 0x040000c0,
    277      0x00000880, 0x000008c0, 0x04000880, 0x040008c0,
    278      0x00800080, 0x008000c0, 0x04800080, 0x048000c0,
    279      0x00800880, 0x008008c0, 0x04800880, 0x048008c0,
    280      0x10000080, 0x100000c0, 0x14000080, 0x140000c0,
    281      0x10000880, 0x100008c0, 0x14000880, 0x140008c0,
    282      0x10800080, 0x108000c0, 0x14800080, 0x148000c0,
    283      0x10800880, 0x108008c0, 0x14800880, 0x148008c0 },
    284    /* table 7 */
    285    { 0x00000000, 0x00000010, 0x00000400, 0x00000410,
    286      0x00000004, 0x00000014, 0x00000404, 0x00000414,
    287      0x00004000, 0x00004010, 0x00004400, 0x00004410,
    288      0x00004004, 0x00004014, 0x00004404, 0x00004414,
    289      0x20000000, 0x20000010, 0x20000400, 0x20000410,
    290      0x20000004, 0x20000014, 0x20000404, 0x20000414,
    291      0x20004000, 0x20004010, 0x20004400, 0x20004410,
    292      0x20004004, 0x20004014, 0x20004404, 0x20004414,
    293      0x00200000, 0x00200010, 0x00200400, 0x00200410,
    294      0x00200004, 0x00200014, 0x00200404, 0x00200414,
    295      0x00204000, 0x00204010, 0x00204400, 0x00204410,
    296      0x00204004, 0x00204014, 0x00204404, 0x00204414,
    297      0x20200000, 0x20200010, 0x20200400, 0x20200410,
    298      0x20200004, 0x20200014, 0x20200404, 0x20200414,
    299      0x20204000, 0x20204010, 0x20204400, 0x20204410,
    300      0x20204004, 0x20204014, 0x20204404, 0x20204414 }
    301 };
    302 
    303 /*
    304 * The PC-1 Permutation
    305 * If we number the bits of the 8 bytes of key input like this (in octal):
    306 *     00 01 02 03 04 05 06 07
    307 *     10 11 12 13 14 15 16 17
    308 *     20 21 22 23 24 25 26 27
    309 *     30 31 32 33 34 35 36 37
    310 *     40 41 42 43 44 45 46 47
    311 *     50 51 52 53 54 55 56 57
    312 *     60 61 62 63 64 65 66 67
    313 *     70 71 72 73 74 75 76 77
    314 * then after the PC-1 permutation,
    315 * C0 is
    316 *     70 60 50 40 30 20 10 00
    317 *     71 61 51 41 31 21 11 01
    318 *     72 62 52 42 32 22 12 02
    319 *     73 63 53 43
    320 * D0 is
    321 *     76 66 56 46 36 26 16 06
    322 *     75 65 55 45 35 25 15 05
    323 *     74 64 54 44 34 24 14 04
    324 *                 33 23 13 03
    325 * and these parity bits have been discarded:
    326 *     77 67 57 47 37 27 17 07
    327 *
    328 * We achieve this by flipping the input matrix about the diagonal from 70-07,
    329 * getting left =
    330 *     77 67 57 47 37 27 17 07  (these are the parity bits)
    331 *     76 66 56 46 36 26 16 06
    332 *     75 65 55 45 35 25 15 05
    333 *     74 64 54 44 34 24 14 04
    334 * right =
    335 *     73 63 53 43 33 23 13 03
    336 *     72 62 52 42 32 22 12 02
    337 *     71 61 51 41 31 21 11 01
    338 *     70 60 50 40 30 20 10 00
    339 * then byte swap right, ala htonl() on a little endian machine.
    340 * right =
    341 *     70 60 50 40 30 20 10 00
    342 *     71 67 57 47 37 27 11 07
    343 *     72 62 52 42 32 22 12 02
    344 *     73 63 53 43 33 23 13 03
    345 * then
    346 *     c0 = right >> 4;
    347 *     d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
    348 */
    349 
    350 #define FLIP_RIGHT_DIAGONAL(word, temp)        \
    351    temp = (word ^ (word >> 18)) & 0x00003333; \
    352    word ^= temp | (temp << 18);               \
    353    temp = (word ^ (word >> 9)) & 0x00550055;  \
    354    word ^= temp | (temp << 9);
    355 
    356 #if defined(__GNUC__) && defined(NSS_X86_OR_X64)
    357 #define BYTESWAP(word, temp) \
    358    __asm("bswap  %0"        \
    359          : "+r"(word));
    360 #elif (_MSC_VER >= 1300) && defined(NSS_X86_OR_X64)
    361 #include <stdlib.h>
    362 #pragma intrinsic(_byteswap_ulong)
    363 #define BYTESWAP(word, temp) \
    364    word = _byteswap_ulong(word);
    365 #elif defined(__GNUC__) && (defined(__thumb2__) ||         \
    366                            (!defined(__thumb__) &&        \
    367                             (defined(__ARM_ARCH_6__) ||   \
    368                              defined(__ARM_ARCH_6J__) ||  \
    369                              defined(__ARM_ARCH_6K__) ||  \
    370                              defined(__ARM_ARCH_6Z__) ||  \
    371                              defined(__ARM_ARCH_6ZK__) || \
    372                              defined(__ARM_ARCH_6T2__) || \
    373                              defined(__ARM_ARCH_7__) ||   \
    374                              defined(__ARM_ARCH_7A__) ||  \
    375                              defined(__ARM_ARCH_7R__))))
    376 #define BYTESWAP(word, temp) \
    377    __asm("rev %0, %0"       \
    378          : "+r"(word));
    379 #else
    380 #define BYTESWAP(word, temp)            \
    381    word = (word >> 16) | (word << 16); \
    382    temp = 0x00ff00ff;                  \
    383    word = ((word & temp) << 8) | ((word >> 8) & temp);
    384 #endif
    385 
    386 #define PC1(left, right, c0, d0, temp)                  \
    387    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f; \
    388    left ^= temp << 4;                                  \
    389    FLIP_RIGHT_DIAGONAL(left, temp);                    \
    390    FLIP_RIGHT_DIAGONAL(right, temp);                   \
    391    BYTESWAP(right, temp);                              \
    392    c0 = right >> 4;                                    \
    393    d0 = ((left & 0x00ffffff) << 4) | (right & 0xf);
    394 
    395 #define LEFT_SHIFT_1(reg) (((reg << 1) | (reg >> 27)) & 0x0FFFFFFF)
    396 #define LEFT_SHIFT_2(reg) (((reg << 2) | (reg >> 26)) & 0x0FFFFFFF)
    397 
    398 /*
    399 *   setup key schedules from key
    400 */
    401 
    402 void
    403 DES_MakeSchedule(HALF *ks, const BYTE *key, DESDirection direction)
    404 {
    405    register HALF left, right;
    406    register HALF c0, d0;
    407    register HALF temp;
    408    int delta;
    409    unsigned int ls;
    410 
    411 #if defined(HAVE_UNALIGNED_ACCESS)
    412    left = HALFPTR(key)[0];
    413    right = HALFPTR(key)[1];
    414 #if defined(IS_LITTLE_ENDIAN)
    415    BYTESWAP(left, temp);
    416    BYTESWAP(right, temp);
    417 #endif
    418 #else
    419    if (((ptrdiff_t)key & 0x03) == 0) {
    420        left = HALFPTR(key)[0];
    421        right = HALFPTR(key)[1];
    422 #if defined(IS_LITTLE_ENDIAN)
    423        BYTESWAP(left, temp);
    424        BYTESWAP(right, temp);
    425 #endif
    426    } else {
    427        left = ((HALF)key[0] << 24) | ((HALF)key[1] << 16) |
    428               ((HALF)key[2] << 8) | key[3];
    429        right = ((HALF)key[4] << 24) | ((HALF)key[5] << 16) |
    430                ((HALF)key[6] << 8) | key[7];
    431    }
    432 #endif
    433 
    434    PC1(left, right, c0, d0, temp);
    435 
    436    if (direction == DES_ENCRYPT) {
    437        delta = 2 * (int)sizeof(HALF);
    438    } else {
    439        ks += 30;
    440        delta = (-2) * (int)sizeof(HALF);
    441    }
    442 
    443    for (ls = 0x8103; ls; ls >>= 1) {
    444        if (ls & 1) {
    445            c0 = LEFT_SHIFT_1(c0);
    446            d0 = LEFT_SHIFT_1(d0);
    447        } else {
    448            c0 = LEFT_SHIFT_2(c0);
    449            d0 = LEFT_SHIFT_2(d0);
    450        }
    451 
    452 #ifdef USE_INDEXING
    453 #define PC2LOOKUP(b, c) PC2[b][c]
    454 
    455        left = PC2LOOKUP(0, ((c0 >> 22) & 0x3F));
    456        left |= PC2LOOKUP(1, ((c0 >> 13) & 0x3F));
    457        left |= PC2LOOKUP(2, ((c0 >> 4) & 0x38) | (c0 & 0x7));
    458        left |= PC2LOOKUP(3, ((c0 >> 18) & 0xC) | ((c0 >> 11) & 0x3) | (c0 & 0x30));
    459 
    460        right = PC2LOOKUP(4, ((d0 >> 22) & 0x3F));
    461        right |= PC2LOOKUP(5, ((d0 >> 15) & 0x30) | ((d0 >> 14) & 0xf));
    462        right |= PC2LOOKUP(6, ((d0 >> 7) & 0x3F));
    463        right |= PC2LOOKUP(7, ((d0 >> 1) & 0x3C) | (d0 & 0x3));
    464 #else
    465 #define PC2LOOKUP(b, c) *(HALF *)((BYTE *)&PC2[b][0] + (c))
    466 
    467        left = PC2LOOKUP(0, ((c0 >> 20) & 0xFC));
    468        left |= PC2LOOKUP(1, ((c0 >> 11) & 0xFC));
    469        left |= PC2LOOKUP(2, ((c0 >> 2) & 0xE0) | ((c0 << 2) & 0x1C));
    470        left |= PC2LOOKUP(3, ((c0 >> 16) & 0x30) | ((c0 >> 9) & 0xC) | ((c0 << 2) & 0xC0));
    471 
    472        right = PC2LOOKUP(4, ((d0 >> 20) & 0xFC));
    473        right |= PC2LOOKUP(5, ((d0 >> 13) & 0xC0) | ((d0 >> 12) & 0x3C));
    474        right |= PC2LOOKUP(6, ((d0 >> 5) & 0xFC));
    475        right |= PC2LOOKUP(7, ((d0 << 1) & 0xF0) | ((d0 << 2) & 0x0C));
    476 #endif
    477        /* left  contains key bits for S1 S3 S2 S4 */
    478        /* right contains key bits for S6 S8 S5 S7 */
    479        temp = (left << 16)     /* S2 S4 XX XX */
    480               | (right >> 16); /* XX XX S6 S8 */
    481        ks[0] = temp;
    482 
    483        temp = (left & 0xffff0000)     /* S1 S3 XX XX */
    484               | (right & 0x0000ffff); /* XX XX S5 S7 */
    485        ks[1] = temp;
    486 
    487        ks = (HALF *)((BYTE *)ks + delta);
    488    }
    489 }
    490 
    491 /*
    492 * The DES Initial Permutation
    493 * if we number the bits of the 8 bytes of input like this (in octal):
    494 *     00 01 02 03 04 05 06 07
    495 *     10 11 12 13 14 15 16 17
    496 *     20 21 22 23 24 25 26 27
    497 *     30 31 32 33 34 35 36 37
    498 *     40 41 42 43 44 45 46 47
    499 *     50 51 52 53 54 55 56 57
    500 *     60 61 62 63 64 65 66 67
    501 *     70 71 72 73 74 75 76 77
    502 * then after the initial permutation, they will be in this order.
    503 *     71 61 51 41 31 21 11 01
    504 *     73 63 53 43 33 23 13 03
    505 *     75 65 55 45 35 25 15 05
    506 *     77 67 57 47 37 27 17 07
    507 *     70 60 50 40 30 20 10 00
    508 *     72 62 52 42 32 22 12 02
    509 *     74 64 54 44 34 24 14 04
    510 *     76 66 56 46 36 26 16 06
    511 *
    512 * One way to do this is in two steps:
    513 * 1. Flip this matrix about the diagonal from 70-07 as done for PC1.
    514 * 2. Rearrange the bytes (rows in the matrix above) with the following code.
    515 *
    516 * #define swapHiLo(word, temp) \
    517 *   temp  = (word ^ (word >> 24)) & 0x000000ff; \
    518 *   word ^=  temp | (temp << 24);
    519 *
    520 *   right ^= temp = ((left << 8) ^ right) & 0xff00ff00;
    521 *   left  ^= temp >> 8;
    522 *   swapHiLo(left, temp);
    523 *   swapHiLo(right,temp);
    524 *
    525 * However, the two steps can be combined, so that the rows are rearranged
    526 * while the matrix is being flipped, reducing the number of bit exchange
    527 * operations from 8 ot 5.
    528 *
    529 * Initial Permutation */
    530 #define IP(left, right, temp)                            \
    531    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f;  \
    532    left ^= temp << 4;                                   \
    533    right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
    534    left ^= temp << 16;                                  \
    535    right ^= temp = ((left << 2) ^ right) & 0xcccccccc;  \
    536    left ^= temp >> 2;                                   \
    537    right ^= temp = ((left << 8) ^ right) & 0xff00ff00;  \
    538    left ^= temp >> 8;                                   \
    539    right ^= temp = ((left >> 1) ^ right) & 0x55555555;  \
    540    left ^= temp << 1;
    541 
    542 /* The Final (Inverse Initial) permutation is done by reversing the
    543 ** steps of the Initital Permutation
    544 */
    545 
    546 #define FP(left, right, temp)                            \
    547    right ^= temp = ((left >> 1) ^ right) & 0x55555555;  \
    548    left ^= temp << 1;                                   \
    549    right ^= temp = ((left << 8) ^ right) & 0xff00ff00;  \
    550    left ^= temp >> 8;                                   \
    551    right ^= temp = ((left << 2) ^ right) & 0xcccccccc;  \
    552    left ^= temp >> 2;                                   \
    553    right ^= temp = ((left >> 16) ^ right) & 0x0000ffff; \
    554    left ^= temp << 16;                                  \
    555    right ^= temp = ((left >> 4) ^ right) & 0x0f0f0f0f;  \
    556    left ^= temp << 4;
    557 
    558 void NO_SANITIZE_ALIGNMENT
    559 DES_Do1Block(HALF *ks, const BYTE *inbuf, BYTE *outbuf)
    560 {
    561    register HALF left, right;
    562    register HALF temp;
    563 
    564 #if defined(HAVE_UNALIGNED_ACCESS)
    565    left = HALFPTR(inbuf)[0];
    566    right = HALFPTR(inbuf)[1];
    567 #if defined(IS_LITTLE_ENDIAN)
    568    BYTESWAP(left, temp);
    569    BYTESWAP(right, temp);
    570 #endif
    571 #else
    572    if (((ptrdiff_t)inbuf & 0x03) == 0) {
    573        left = HALFPTR(inbuf)[0];
    574        right = HALFPTR(inbuf)[1];
    575 #if defined(IS_LITTLE_ENDIAN)
    576        BYTESWAP(left, temp);
    577        BYTESWAP(right, temp);
    578 #endif
    579    } else {
    580        left = ((HALF)inbuf[0] << 24) | ((HALF)inbuf[1] << 16) |
    581               ((HALF)inbuf[2] << 8) | inbuf[3];
    582        right = ((HALF)inbuf[4] << 24) | ((HALF)inbuf[5] << 16) |
    583                ((HALF)inbuf[6] << 8) | inbuf[7];
    584    }
    585 #endif
    586 
    587    IP(left, right, temp);
    588 
    589    /* shift the values left circularly 3 bits. */
    590    left = (left << 3) | (left >> 29);
    591    right = (right << 3) | (right >> 29);
    592 
    593 #ifdef USE_INDEXING
    594 #define KSLOOKUP(s, b) SP[s][((temp >> (b + 2)) & 0x3f)]
    595 #else
    596 #define KSLOOKUP(s, b) *(HALF *)((BYTE *)&SP[s][0] + ((temp >> b) & 0xFC))
    597 #endif
    598 #define ROUND(out, in, r)                            \
    599    temp = in ^ ks[2 * r];                           \
    600    out ^= KSLOOKUP(1, 24);                          \
    601    out ^= KSLOOKUP(3, 16);                          \
    602    out ^= KSLOOKUP(5, 8);                           \
    603    out ^= KSLOOKUP(7, 0);                           \
    604    temp = ((in >> 4) | (in << 28)) ^ ks[2 * r + 1]; \
    605    out ^= KSLOOKUP(0, 24);                          \
    606    out ^= KSLOOKUP(2, 16);                          \
    607    out ^= KSLOOKUP(4, 8);                           \
    608    out ^= KSLOOKUP(6, 0);
    609 
    610    /* Do the 16 Feistel rounds */
    611    ROUND(left, right, 0)
    612    ROUND(right, left, 1)
    613    ROUND(left, right, 2)
    614    ROUND(right, left, 3)
    615    ROUND(left, right, 4)
    616    ROUND(right, left, 5)
    617    ROUND(left, right, 6)
    618    ROUND(right, left, 7)
    619    ROUND(left, right, 8)
    620    ROUND(right, left, 9)
    621    ROUND(left, right, 10)
    622    ROUND(right, left, 11)
    623    ROUND(left, right, 12)
    624    ROUND(right, left, 13)
    625    ROUND(left, right, 14)
    626    ROUND(right, left, 15)
    627 
    628    /* now shift circularly right 3 bits to undo the shifting done
    629    ** above.  switch left and right here.
    630    */
    631    temp = (left >> 3) | (left << 29);
    632    left = (right >> 3) | (right << 29);
    633    right = temp;
    634 
    635    FP(left, right, temp);
    636 
    637 #if defined(HAVE_UNALIGNED_ACCESS)
    638 #if defined(IS_LITTLE_ENDIAN)
    639    BYTESWAP(left, temp);
    640    BYTESWAP(right, temp);
    641 #endif
    642    HALFPTR(outbuf)
    643    [0] = left;
    644    HALFPTR(outbuf)
    645    [1] = right;
    646 #else
    647    if (((ptrdiff_t)outbuf & 0x03) == 0) {
    648 #if defined(IS_LITTLE_ENDIAN)
    649        BYTESWAP(left, temp);
    650        BYTESWAP(right, temp);
    651 #endif
    652        HALFPTR(outbuf)
    653        [0] = left;
    654        HALFPTR(outbuf)
    655        [1] = right;
    656    } else {
    657        outbuf[0] = (BYTE)(left >> 24);
    658        outbuf[1] = (BYTE)(left >> 16);
    659        outbuf[2] = (BYTE)(left >> 8);
    660        outbuf[3] = (BYTE)(left);
    661 
    662        outbuf[4] = (BYTE)(right >> 24);
    663        outbuf[5] = (BYTE)(right >> 16);
    664        outbuf[6] = (BYTE)(right >> 8);
    665        outbuf[7] = (BYTE)(right);
    666    }
    667 #endif
    668 }
    669 
    670 /* Ackowledgements:
    671 ** Two ideas used in this implementation were shown to me by Dennis Ferguson
    672 ** in 1990.  He credits them to Richard Outerbridge and Dan Hoey.  They were:
    673 ** 1. The method of computing the Initial and Final permutations.
    674 ** 2. Circularly rotating the SP tables and the initial values of left and
    675 **  right to reduce the number of shifts required during the 16 rounds.
    676 */