md4.c - vx32 - Local 9vx git repository for patches.
 (HTM) git clone git://r-36.net/vx32
 (DIR) Log
 (DIR) Files
 (DIR) Refs
       ---
       md4.c (4260B)
       ---
            1 #include "os.h"
            2 #include "libsec.h"
            3 
            4 /*
            5  *  This MD4 is implemented from the description in Stinson's Cryptography,
            6  *  theory and practice. -- presotto
            7  */
            8 
            9 /*
           10  *        Rotate ammounts used in the algorithm
           11  */
           12 enum
           13 {
           14         S11=        3,
           15         S12=        7,
           16         S13=        11,
           17         S14=        19,
           18 
           19         S21=        3,
           20         S22=        5,
           21         S23=        9,
           22         S24=        13,
           23 
           24         S31=        3,
           25         S32=        9,
           26         S33=        11,
           27         S34=        15,
           28 };
           29 
           30 typedef struct MD4Table MD4Table;
           31 struct MD4Table
           32 {
           33         uchar        x;        /* index into data block */
           34         uchar        rot;        /* amount to rotate left by */
           35 };
           36 
           37 static MD4Table tab[] =
           38 {
           39         /* round 1 */
           40 /*[0]*/        { 0,        S11},        
           41         { 1,        S12},        
           42         { 2,        S13},        
           43         { 3,        S14},        
           44         { 4,        S11},        
           45         { 5,        S12},        
           46         { 6,        S13},        
           47         { 7,        S14},        
           48         { 8,        S11},        
           49         { 9,        S12},        
           50         { 10,        S13},        
           51         { 11,        S14},        
           52         { 12,        S11},        
           53         { 13,        S12},        
           54         { 14,        S13},        
           55         { 15,        S14},
           56 
           57         /* round 2 */
           58 /*[16]*/{ 0,        S21},        
           59         { 4,        S22},        
           60         { 8,        S23},        
           61         { 12,        S24},        
           62         { 1,        S21},        
           63         { 5,        S22},        
           64         { 9,        S23},        
           65         { 13,        S24},        
           66         { 2,        S21},        
           67         { 6,        S22},        
           68         { 10,        S23},        
           69         { 14,        S24},        
           70         { 3,        S21},        
           71         { 7,        S22},        
           72         { 11,        S23},        
           73         { 15,        S24},
           74 
           75         /* round 3 */
           76 /*[32]*/{ 0,        S31},        
           77         { 8,        S32},        
           78         { 4,        S33},        
           79         { 12,        S34},        
           80         { 2,        S31},        
           81         { 10,        S32},        
           82         { 6,        S33},        
           83         { 14,        S34},        
           84         { 1,        S31},        
           85         { 9,        S32},        
           86         { 5,        S33},        
           87         { 13,        S34},        
           88         { 3,        S31},        
           89         { 11,        S32},        
           90         { 7,        S33},        
           91         { 15,        S34},        
           92 };
           93 
           94 static void encode(uchar*, uint32*, ulong);
           95 static void decode(uint32*, uchar*, ulong);
           96 
           97 static void
           98 md4block(uchar *p, ulong len, MD4state *s)
           99 {
          100         int i;
          101         uint32 a, b, c, d, tmp;
          102         MD4Table *t;
          103         uchar *end;
          104         uint32 x[16];
          105 
          106         for(end = p+len; p < end; p += 64){
          107                 a = s->state[0];
          108                 b = s->state[1];
          109                 c = s->state[2];
          110                 d = s->state[3];
          111 
          112                 decode(x, p, 64);
          113         
          114                 for(i = 0; i < 48; i++){
          115                         t = tab + i;
          116                         switch(i>>4){
          117                         case 0:
          118                                 a += (b & c) | (~b & d);
          119                                 break;
          120                         case 1:
          121                                 a += ((b & c) | (b & d) | (c & d)) + 0x5A827999;
          122                                 break;
          123                         case 2:
          124                                 a += (b ^ c ^ d) + 0x6ED9EBA1;
          125                                 break;
          126                         }
          127                         a += x[t->x];
          128                         a = (a << t->rot) | (a >> (32 - t->rot));
          129         
          130                         /* rotate variables */
          131                         tmp = d;
          132                         d = c;
          133                         c = b;
          134                         b = a;
          135                         a = tmp;
          136                 }
          137 
          138                 s->state[0] += a;
          139                 s->state[1] += b;
          140                 s->state[2] += c;
          141                 s->state[3] += d;
          142 
          143                 s->len += 64;
          144         }
          145 }
          146 
          147 MD4state*
          148 md4(uchar *p, ulong len, uchar *digest, MD4state *s)
          149 {
          150         uint32 x[16];
          151         uchar buf[128];
          152         int i;
          153         uchar *e;
          154 
          155         if(s == nil){
          156                 s = malloc(sizeof(*s));
          157                 if(s == nil)
          158                         return nil;
          159                 memset(s, 0, sizeof(*s));
          160                 s->malloced = 1;
          161         }
          162 
          163         if(s->seeded == 0){
          164                 /* seed the state, these constants would look nicer big-endian */
          165                 s->state[0] = 0x67452301;
          166                 s->state[1] = 0xefcdab89;
          167                 s->state[2] = 0x98badcfe;
          168                 s->state[3] = 0x10325476;
          169                 s->seeded = 1;
          170         }
          171 
          172         /* fill out the partial 64 byte block from previous calls */
          173         if(s->blen){
          174                 i = 64 - s->blen;
          175                 if(len < i)
          176                         i = len;
          177                 memmove(s->buf + s->blen, p, i);
          178                 len -= i;
          179                 s->blen += i;
          180                 p += i;
          181                 if(s->blen == 64){
          182                         md4block(s->buf, s->blen, s);
          183                         s->blen = 0;
          184                 }
          185         }
          186 
          187         /* do 64 byte blocks */
          188         i = len & ~0x3f;
          189         if(i){
          190                 md4block(p, i, s);
          191                 len -= i;
          192                 p += i;
          193         }
          194 
          195         /* save the left overs if not last call */
          196         if(digest == 0){
          197                 if(len){
          198                         memmove(s->buf, p, len);
          199                         s->blen += len;
          200                 }
          201                 return s;
          202         }
          203 
          204         /*
          205          *  this is the last time through, pad what's left with 0x80,
          206          *  0's, and the input count to create a multiple of 64 bytes
          207          */
          208         if(s->blen){
          209                 p = s->buf;
          210                 len = s->blen;
          211         } else {
          212                 memmove(buf, p, len);
          213                 p = buf;
          214         }
          215         s->len += len;
          216         e = p + len;
          217         if(len < 56)
          218                 i = 56 - len;
          219         else
          220                 i = 120 - len;
          221         memset(e, 0, i);
          222         *e = 0x80;
          223         len += i;
          224 
          225         /* append the count */
          226         x[0] = s->len<<3;
          227         x[1] = s->len>>29;
          228         encode(p+len, x, 8);
          229 
          230         /* digest the last part */
          231         md4block(p, len+8, s);
          232 
          233         /* return result and free state */
          234         encode(digest, s->state, MD4dlen);
          235         if(s->malloced == 1)
          236                 free(s);
          237         return nil;
          238 }
          239 
          240 /*
          241  *        encodes input (uint32) into output (uchar). Assumes len is
          242  *        a multiple of 4.
          243  */
          244 static void
          245 encode(uchar *output, uint32 *input, ulong len)
          246 {
          247         uint32 x;
          248         uchar *e;
          249 
          250         for(e = output + len; output < e;) {
          251                 x = *input++;
          252                 *output++ = x;
          253                 *output++ = x >> 8;
          254                 *output++ = x >> 16;
          255                 *output++ = x >> 24;
          256         }
          257 }
          258 
          259 /*
          260  *        decodes input (uchar) into output (uint32). Assumes len is
          261  *        a multiple of 4.
          262  */
          263 static void
          264 decode(uint32 *output, uchar *input, ulong len)
          265 {
          266         uchar *e;
          267 
          268         for(e = input+len; input < e; input += 4)
          269                 *output++ = input[0] | (input[1] << 8) |
          270                         (input[2] << 16) | (input[3] << 24);
          271 }