~ubuntu-branches/ubuntu/trusty/rhash/trusty

« back to all changes in this revision

Viewing changes to librhash/md4.c

  • Committer: Bazaar Package Importer
  • Author(s): Alexey S Kravchenko
  • Date: 2011-06-15 01:03:34 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20110615010334-ochayini7ut2djvs
Tags: 1.2.6-1
* New upstream release version 1.2.6
 - ABI changed - now librhash0.0 is librhash0
 - OpenSSL support for faster hash calculation if libssl is installed
   (fully optional) for both rhash and librhash0

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* md4.c - an implementation of MD4 Message-Digest Algorithm
2
 
 * based on RFC 1320.
3
 
 *
4
 
 * Implementation written by Alexei Kravchenko.
5
 
 *
6
 
 * Copyleft:
7
 
 * I hereby release this code into the public domain. This applies worldwide.
8
 
 * I grant any entity the right to use this work for ANY PURPOSE,
9
 
 * without any conditions, unless such conditions are required by law.
 
1
/* md4.c - an implementation of MD4 Message-Digest Algorithm based on RFC 1320.
 
2
 *
 
3
 * Copyright: 2007 Alexey Kravchenko <rhash.admin@gmail.com>
 
4
 *
 
5
 * Permission is hereby granted,  free of charge,  to any person  obtaining a
 
6
 * copy of this software and associated documentation files (the "Software"),
 
7
 * to deal in the Software without restriction,  including without limitation
 
8
 * the rights to  use, copy, modify,  merge, publish, distribute, sublicense,
 
9
 * and/or sell copies  of  the Software,  and to permit  persons  to whom the
 
10
 * Software is furnished to do so.
10
11
 */
11
12
 
12
13
#include <string.h>
18
19
 *
19
20
 * @param ctx context to initalize
20
21
 */
21
 
void md4_init(md4_ctx *ctx)
 
22
void rhash_md4_init(md4_ctx *ctx)
22
23
{
23
 
  ctx->length = 0;
 
24
        ctx->length = 0;
24
25
 
25
 
  /* initialize state */
26
 
  ctx->hash[0] = 0x67452301;
27
 
  ctx->hash[1] = 0xefcdab89;
28
 
  ctx->hash[2] = 0x98badcfe;
29
 
  ctx->hash[3] = 0x10325476;
 
26
        /* initialize state */
 
27
        ctx->hash[0] = 0x67452301;
 
28
        ctx->hash[1] = 0xefcdab89;
 
29
        ctx->hash[2] = 0x98badcfe;
 
30
        ctx->hash[3] = 0x10325476;
30
31
}
31
32
 
32
33
/* First, define three auxiliary functions that each take as input
33
 
   three 32-bit words and returns a 32-bit word.
34
 
    F(x,y,z) = XY v not(X) Z = ((Y xor Z) X) xor Z (the last form is faster)
35
 
    G(X,Y,Z) = XY v XZ v YZ
36
 
    H(X,Y,Z) = X xor Y xor Z */
 
34
 * three 32-bit words and returns a 32-bit word.
 
35
 *  F(x,y,z) = XY v not(X) Z = ((Y xor Z) X) xor Z (the last form is faster)
 
36
 *  G(X,Y,Z) = XY v XZ v YZ
 
37
 *  H(X,Y,Z) = X xor Y xor Z */
37
38
 
38
39
#define MD4_F(x, y, z) ((((y) ^ (z)) & (x)) ^ (z))
39
40
#define MD4_G(x, y, z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
41
42
 
42
43
/* transformations for rounds 1, 2, and 3. */
43
44
#define MD4_ROUND1(a, b, c, d, x, s) { \
44
 
    (a) += MD4_F((b), (c), (d)) + (x); \
45
 
    (a) = ROTL32((a), (s)); \
46
 
  }
 
45
        (a) += MD4_F((b), (c), (d)) + (x); \
 
46
        (a) = ROTL32((a), (s)); \
 
47
}
47
48
#define MD4_ROUND2(a, b, c, d, x, s) { \
48
 
    (a) += MD4_G((b), (c), (d)) + (x) + 0x5a827999; \
49
 
    (a) = ROTL32((a), (s)); \
50
 
  }
 
49
        (a) += MD4_G((b), (c), (d)) + (x) + 0x5a827999; \
 
50
        (a) = ROTL32((a), (s)); \
 
51
}
51
52
#define MD4_ROUND3(a, b, c, d, x, s) { \
52
 
    (a) += MD4_H((b), (c), (d)) + (x) + 0x6ed9eba1; \
53
 
    (a) = ROTL32((a), (s)); \
54
 
  }
 
53
        (a) += MD4_H((b), (c), (d)) + (x) + 0x6ed9eba1; \
 
54
        (a) = ROTL32((a), (s)); \
 
55
}
55
56
 
56
57
/**
57
58
 * The core transformation. Process a 512-bit block.
60
61
 * @param state algorithm state
61
62
 * @param x the message block to process
62
63
 */
63
 
static void md4_process_block(unsigned state[4], const unsigned* x)
 
64
static void rhash_md4_process_block(unsigned state[4], const unsigned* x)
64
65
{
65
 
  register unsigned a, b, c, d;
66
 
  a = state[0];
67
 
  b = state[1];
68
 
  c = state[2];
69
 
  d = state[3];
70
 
 
71
 
  MD4_ROUND1(a, b, c, d, x[ 0],  3);
72
 
  MD4_ROUND1(d, a, b, c, x[ 1],  7);
73
 
  MD4_ROUND1(c, d, a, b, x[ 2], 11);
74
 
  MD4_ROUND1(b, c, d, a, x[ 3], 19);
75
 
  MD4_ROUND1(a, b, c, d, x[ 4],  3);
76
 
  MD4_ROUND1(d, a, b, c, x[ 5],  7);
77
 
  MD4_ROUND1(c, d, a, b, x[ 6], 11);
78
 
  MD4_ROUND1(b, c, d, a, x[ 7], 19);
79
 
  MD4_ROUND1(a, b, c, d, x[ 8],  3);
80
 
  MD4_ROUND1(d, a, b, c, x[ 9],  7);
81
 
  MD4_ROUND1(c, d, a, b, x[10], 11);
82
 
  MD4_ROUND1(b, c, d, a, x[11], 19);
83
 
  MD4_ROUND1(a, b, c, d, x[12],  3);
84
 
  MD4_ROUND1(d, a, b, c, x[13],  7);
85
 
  MD4_ROUND1(c, d, a, b, x[14], 11);
86
 
  MD4_ROUND1(b, c, d, a, x[15], 19);
87
 
  
88
 
  MD4_ROUND2(a, b, c, d, x[ 0],  3);
89
 
  MD4_ROUND2(d, a, b, c, x[ 4],  5);
90
 
  MD4_ROUND2(c, d, a, b, x[ 8],  9);
91
 
  MD4_ROUND2(b, c, d, a, x[12], 13);
92
 
  MD4_ROUND2(a, b, c, d, x[ 1],  3);
93
 
  MD4_ROUND2(d, a, b, c, x[ 5],  5);
94
 
  MD4_ROUND2(c, d, a, b, x[ 9],  9);
95
 
  MD4_ROUND2(b, c, d, a, x[13], 13);
96
 
  MD4_ROUND2(a, b, c, d, x[ 2],  3);
97
 
  MD4_ROUND2(d, a, b, c, x[ 6],  5);
98
 
  MD4_ROUND2(c, d, a, b, x[10],  9);
99
 
  MD4_ROUND2(b, c, d, a, x[14], 13);
100
 
  MD4_ROUND2(a, b, c, d, x[ 3],  3);
101
 
  MD4_ROUND2(d, a, b, c, x[ 7],  5);
102
 
  MD4_ROUND2(c, d, a, b, x[11],  9);
103
 
  MD4_ROUND2(b, c, d, a, x[15], 13);
104
 
 
105
 
  MD4_ROUND3(a, b, c, d, x[ 0],  3);
106
 
  MD4_ROUND3(d, a, b, c, x[ 8],  9);
107
 
  MD4_ROUND3(c, d, a, b, x[ 4], 11);
108
 
  MD4_ROUND3(b, c, d, a, x[12], 15);
109
 
  MD4_ROUND3(a, b, c, d, x[ 2],  3);
110
 
  MD4_ROUND3(d, a, b, c, x[10],  9);
111
 
  MD4_ROUND3(c, d, a, b, x[ 6], 11);
112
 
  MD4_ROUND3(b, c, d, a, x[14], 15);
113
 
  MD4_ROUND3(a, b, c, d, x[ 1],  3);
114
 
  MD4_ROUND3(d, a, b, c, x[ 9],  9);
115
 
  MD4_ROUND3(c, d, a, b, x[ 5], 11);
116
 
  MD4_ROUND3(b, c, d, a, x[13], 15);
117
 
  MD4_ROUND3(a, b, c, d, x[ 3],  3);
118
 
  MD4_ROUND3(d, a, b, c, x[11],  9);
119
 
  MD4_ROUND3(c, d, a, b, x[ 7], 11);
120
 
  MD4_ROUND3(b, c, d, a, x[15], 15);
121
 
  
122
 
  state[0] += a;
123
 
  state[1] += b;
124
 
  state[2] += c;
125
 
  state[3] += d;
 
66
        register unsigned a, b, c, d;
 
67
        a = state[0], b = state[1], c = state[2], d = state[3];
 
68
 
 
69
        MD4_ROUND1(a, b, c, d, x[ 0],  3);
 
70
        MD4_ROUND1(d, a, b, c, x[ 1],  7);
 
71
        MD4_ROUND1(c, d, a, b, x[ 2], 11);
 
72
        MD4_ROUND1(b, c, d, a, x[ 3], 19);
 
73
        MD4_ROUND1(a, b, c, d, x[ 4],  3);
 
74
        MD4_ROUND1(d, a, b, c, x[ 5],  7);
 
75
        MD4_ROUND1(c, d, a, b, x[ 6], 11);
 
76
        MD4_ROUND1(b, c, d, a, x[ 7], 19);
 
77
        MD4_ROUND1(a, b, c, d, x[ 8],  3);
 
78
        MD4_ROUND1(d, a, b, c, x[ 9],  7);
 
79
        MD4_ROUND1(c, d, a, b, x[10], 11);
 
80
        MD4_ROUND1(b, c, d, a, x[11], 19);
 
81
        MD4_ROUND1(a, b, c, d, x[12],  3);
 
82
        MD4_ROUND1(d, a, b, c, x[13],  7);
 
83
        MD4_ROUND1(c, d, a, b, x[14], 11);
 
84
        MD4_ROUND1(b, c, d, a, x[15], 19);
 
85
 
 
86
        MD4_ROUND2(a, b, c, d, x[ 0],  3);
 
87
        MD4_ROUND2(d, a, b, c, x[ 4],  5);
 
88
        MD4_ROUND2(c, d, a, b, x[ 8],  9);
 
89
        MD4_ROUND2(b, c, d, a, x[12], 13);
 
90
        MD4_ROUND2(a, b, c, d, x[ 1],  3);
 
91
        MD4_ROUND2(d, a, b, c, x[ 5],  5);
 
92
        MD4_ROUND2(c, d, a, b, x[ 9],  9);
 
93
        MD4_ROUND2(b, c, d, a, x[13], 13);
 
94
        MD4_ROUND2(a, b, c, d, x[ 2],  3);
 
95
        MD4_ROUND2(d, a, b, c, x[ 6],  5);
 
96
        MD4_ROUND2(c, d, a, b, x[10],  9);
 
97
        MD4_ROUND2(b, c, d, a, x[14], 13);
 
98
        MD4_ROUND2(a, b, c, d, x[ 3],  3);
 
99
        MD4_ROUND2(d, a, b, c, x[ 7],  5);
 
100
        MD4_ROUND2(c, d, a, b, x[11],  9);
 
101
        MD4_ROUND2(b, c, d, a, x[15], 13);
 
102
 
 
103
        MD4_ROUND3(a, b, c, d, x[ 0],  3);
 
104
        MD4_ROUND3(d, a, b, c, x[ 8],  9);
 
105
        MD4_ROUND3(c, d, a, b, x[ 4], 11);
 
106
        MD4_ROUND3(b, c, d, a, x[12], 15);
 
107
        MD4_ROUND3(a, b, c, d, x[ 2],  3);
 
108
        MD4_ROUND3(d, a, b, c, x[10],  9);
 
109
        MD4_ROUND3(c, d, a, b, x[ 6], 11);
 
110
        MD4_ROUND3(b, c, d, a, x[14], 15);
 
111
        MD4_ROUND3(a, b, c, d, x[ 1],  3);
 
112
        MD4_ROUND3(d, a, b, c, x[ 9],  9);
 
113
        MD4_ROUND3(c, d, a, b, x[ 5], 11);
 
114
        MD4_ROUND3(b, c, d, a, x[13], 15);
 
115
        MD4_ROUND3(a, b, c, d, x[ 3],  3);
 
116
        MD4_ROUND3(d, a, b, c, x[11],  9);
 
117
        MD4_ROUND3(c, d, a, b, x[ 7], 11);
 
118
        MD4_ROUND3(b, c, d, a, x[15], 15);
 
119
 
 
120
        state[0] += a, state[1] += b, state[2] += c, state[3] += d;
126
121
}
127
122
 
128
123
/**
133
128
 * @param msg message chunk
134
129
 * @param size length of the message chunk
135
130
 */
136
 
void md4_update(md4_ctx *ctx, const unsigned char* msg, size_t size)
 
131
void rhash_md4_update(md4_ctx *ctx, const unsigned char* msg, size_t size)
137
132
{
138
 
  unsigned index = (unsigned)ctx->length & 63;
139
 
  ctx->length += size;
140
 
 
141
 
  /* fill partial block */
142
 
  if(index) {
143
 
    unsigned left = md4_block_size - index;
144
 
    le32_copy((char*)ctx->message + index, msg, (size < left ? size : left));
145
 
    if(size < left) return;
146
 
 
147
 
    /* process partial block */
148
 
    md4_process_block(ctx->hash, ctx->message);
149
 
    msg  += left;
150
 
    size -= left;
151
 
  }
152
 
  while(size >= md4_block_size) {
153
 
    unsigned* aligned_message_block;
154
 
    if( IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg) ) {
155
 
      /* the most common case is processing a 32-bit aligned message 
156
 
         on a little-endian CPU without copying it */
157
 
      aligned_message_block = (unsigned*)msg;
158
 
    } else {
159
 
      le32_copy(ctx->message, msg, md4_block_size);
160
 
      aligned_message_block = ctx->message;
161
 
    }
162
 
 
163
 
    md4_process_block(ctx->hash, aligned_message_block);
164
 
    msg  += md4_block_size;
165
 
    size -= md4_block_size;
166
 
  }
167
 
  if(size) {
168
 
    /* save leftovers */
169
 
    le32_copy(ctx->message, msg, size);
170
 
  }
 
133
        unsigned index = (unsigned)ctx->length & 63;
 
134
        ctx->length += size;
 
135
 
 
136
        /* fill partial block */
 
137
        if(index) {
 
138
                unsigned left = md4_block_size - index;
 
139
                le32_copy((char*)ctx->message, index, msg, (size < left ? size : left));
 
140
                if(size < left) return;
 
141
 
 
142
                /* process partial block */
 
143
                rhash_md4_process_block(ctx->hash, ctx->message);
 
144
                msg  += left;
 
145
                size -= left;
 
146
        }
 
147
        while(size >= md4_block_size) {
 
148
                unsigned* aligned_message_block;
 
149
                if(IS_LITTLE_ENDIAN && IS_ALIGNED_32(msg)) {
 
150
                        /* the most common case is processing a 32-bit aligned message 
 
151
                        on a little-endian CPU without copying it */
 
152
                        aligned_message_block = (unsigned*)msg;
 
153
                } else {
 
154
                        le32_copy(ctx->message, 0, msg, md4_block_size);
 
155
                        aligned_message_block = ctx->message;
 
156
                }
 
157
 
 
158
                rhash_md4_process_block(ctx->hash, aligned_message_block);
 
159
                msg  += md4_block_size;
 
160
                size -= md4_block_size;
 
161
        }
 
162
        if(size) {
 
163
                /* save leftovers */
 
164
                le32_copy(ctx->message, 0, msg, size);
 
165
        }
171
166
}
172
167
 
173
168
/**
176
171
 * @param ctx the algorithm context containing current hashing state
177
172
 * @param result calculated hash in binary form
178
173
 */
179
 
void md4_final(md4_ctx *ctx, unsigned char result[16])
 
174
void rhash_md4_final(md4_ctx *ctx, unsigned char result[16])
180
175
{
181
 
  unsigned index = ((unsigned)ctx->length & 63) >> 2;
182
 
  unsigned shift = ((unsigned)ctx->length & 3) * 8;
183
 
 
184
 
  /* pad message and run for last block */
185
 
 
186
 
  /* append the byte 0x80 to the message */
187
 
  ctx->message[index]   &= ~(0xFFFFFFFF << shift);
188
 
  ctx->message[index++] ^= 0x80 << shift;
189
 
 
190
 
  /* if no room left in the message to store 64-bit message length */
191
 
  if(index>14) {
192
 
    /* then fill the rest with zeros and process it */
193
 
    while(index < 16) {
194
 
      ctx->message[index++] = 0;
195
 
    }
196
 
    md4_process_block(ctx->hash, ctx->message);
197
 
    index = 0;
198
 
  }
199
 
  while(index < 14) {
200
 
    ctx->message[index++] = 0;
201
 
  }
202
 
  ctx->message[14] = (unsigned)(ctx->length << 3);
203
 
  ctx->message[15] = (unsigned)(ctx->length >> 29);
204
 
  md4_process_block(ctx->hash, ctx->message);
205
 
 
206
 
  if(result) le32_copy(result, &ctx->hash, 16);
 
176
        unsigned index = ((unsigned)ctx->length & 63) >> 2;
 
177
        unsigned shift = ((unsigned)ctx->length & 3) * 8;
 
178
 
 
179
        /* pad message and run for last block */
 
180
 
 
181
        /* append the byte 0x80 to the message */
 
182
        ctx->message[index]   &= ~(0xFFFFFFFF << shift);
 
183
        ctx->message[index++] ^= 0x80 << shift;
 
184
 
 
185
        /* if no room left in the message to store 64-bit message length */
 
186
        if(index>14) {
 
187
                /* then fill the rest with zeros and process it */
 
188
                while(index < 16) {
 
189
                        ctx->message[index++] = 0;
 
190
                }
 
191
                rhash_md4_process_block(ctx->hash, ctx->message);
 
192
                index = 0;
 
193
        }
 
194
        while(index < 14) {
 
195
                ctx->message[index++] = 0;
 
196
        }
 
197
        ctx->message[14] = (unsigned)(ctx->length << 3);
 
198
        ctx->message[15] = (unsigned)(ctx->length >> 29);
 
199
        rhash_md4_process_block(ctx->hash, ctx->message);
 
200
 
 
201
        if(result) le32_copy(result, 0, &ctx->hash, 16);
207
202
}