1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis
2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic
4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner.
5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express
7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works.
8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *
9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */
11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h"
12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param md4.c
15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   Submitted by Dobes Vandermeer  (dobes@smartt.com)
16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef MD4
19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectconst struct ltc_hash_descriptor md4_desc =
21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    "md4",
23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    6,
24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    16,
25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    64,
26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* OID */
28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   { 1, 2, 840, 113549, 2, 4,  },
29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   6,
30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &md4_init,
32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &md4_process,
33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &md4_done,
34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    &md4_test,
35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    NULL
36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project};
37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S11 3
39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S12 7
40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S13 11
41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S14 19
42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S21 3
43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S22 5
44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S23 9
45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S24 13
46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S31 3
47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S32 9
48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S33 11
49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define S34 15
50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* F, G and H are basic MD4 functions. */
52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define F(x, y, z) (z ^ (x & (y ^ z)))
53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define G(x, y, z) ((x & y) | (z & (x | y)))
54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define H(x, y, z) ((x) ^ (y) ^ (z))
55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* ROTATE_LEFT rotates x left n bits. */
57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define ROTATE_LEFT(x, n) ROLc(x, n)
58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* FF, GG and HH are transformations for rounds 1, 2 and 3 */
60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* Rotation is separate from addition to prevent recomputation */
61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define FF(a, b, c, d, x, s) { \
63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) += F ((b), (c), (d)) + (x); \
64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) = ROTATE_LEFT ((a), (s)); \
65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define GG(a, b, c, d, x, s) { \
67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) += G ((b), (c), (d)) + (x) + 0x5a827999UL; \
68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) = ROTATE_LEFT ((a), (s)); \
69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#define HH(a, b, c, d, x, s) { \
71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) += H ((b), (c), (d)) + (x) + 0x6ed9eba1UL; \
72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    (a) = ROTATE_LEFT ((a), (s)); \
73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  }
74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int _md4_compress(hash_state *md, unsigned char *buf)
77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#else
78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int  md4_compress(hash_state *md, unsigned char *buf)
79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    ulong32 x[16], a, b, c, d;
82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* copy state */
85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    a = md->md4.state[0];
86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    b = md->md4.state[1];
87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    c = md->md4.state[2];
88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    d = md->md4.state[3];
89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* copy the state into 512-bits into W[0..15] */
91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < 16; i++) {
92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        LOAD32L(x[i], buf + (4*i));
93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Round 1 */
96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (a, b, c, d, x[ 0], S11); /* 1 */
97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (d, a, b, c, x[ 1], S12); /* 2 */
98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (c, d, a, b, x[ 2], S13); /* 3 */
99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (b, c, d, a, x[ 3], S14); /* 4 */
100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (a, b, c, d, x[ 4], S11); /* 5 */
101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (d, a, b, c, x[ 5], S12); /* 6 */
102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (c, d, a, b, x[ 6], S13); /* 7 */
103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (b, c, d, a, x[ 7], S14); /* 8 */
104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (a, b, c, d, x[ 8], S11); /* 9 */
105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (d, a, b, c, x[ 9], S12); /* 10 */
106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (c, d, a, b, x[10], S13); /* 11 */
107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (b, c, d, a, x[11], S14); /* 12 */
108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (a, b, c, d, x[12], S11); /* 13 */
109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (d, a, b, c, x[13], S12); /* 14 */
110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (c, d, a, b, x[14], S13); /* 15 */
111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    FF (b, c, d, a, x[15], S14); /* 16 */
112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Round 2 */
114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (a, b, c, d, x[ 0], S21); /* 17 */
115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (d, a, b, c, x[ 4], S22); /* 18 */
116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (c, d, a, b, x[ 8], S23); /* 19 */
117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (b, c, d, a, x[12], S24); /* 20 */
118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (a, b, c, d, x[ 1], S21); /* 21 */
119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (d, a, b, c, x[ 5], S22); /* 22 */
120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (c, d, a, b, x[ 9], S23); /* 23 */
121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (b, c, d, a, x[13], S24); /* 24 */
122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (a, b, c, d, x[ 2], S21); /* 25 */
123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (d, a, b, c, x[ 6], S22); /* 26 */
124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (c, d, a, b, x[10], S23); /* 27 */
125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (b, c, d, a, x[14], S24); /* 28 */
126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (a, b, c, d, x[ 3], S21); /* 29 */
127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (d, a, b, c, x[ 7], S22); /* 30 */
128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (c, d, a, b, x[11], S23); /* 31 */
129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    GG (b, c, d, a, x[15], S24); /* 32 */
130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Round 3 */
132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (a, b, c, d, x[ 0], S31); /* 33 */
133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (d, a, b, c, x[ 8], S32); /* 34 */
134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (c, d, a, b, x[ 4], S33); /* 35 */
135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (b, c, d, a, x[12], S34); /* 36 */
136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (a, b, c, d, x[ 2], S31); /* 37 */
137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (d, a, b, c, x[10], S32); /* 38 */
138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (c, d, a, b, x[ 6], S33); /* 39 */
139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (b, c, d, a, x[14], S34); /* 40 */
140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (a, b, c, d, x[ 1], S31); /* 41 */
141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (d, a, b, c, x[ 9], S32); /* 42 */
142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (c, d, a, b, x[ 5], S33); /* 43 */
143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (b, c, d, a, x[13], S34); /* 44 */
144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (a, b, c, d, x[ 3], S31); /* 45 */
145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (d, a, b, c, x[11], S32); /* 46 */
146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (c, d, a, b, x[ 7], S33); /* 47 */
147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    HH (b, c, d, a, x[15], S34); /* 48 */
148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* Update our state */
151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.state[0] = md->md4.state[0] + a;
152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.state[1] = md->md4.state[1] + b;
153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.state[2] = md->md4.state[2] + c;
154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.state[3] = md->md4.state[3] + d;
155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectstatic int md4_compress(hash_state *md, unsigned char *buf)
161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   int err;
163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   err = _md4_compress(md, buf);
164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   burn_stack(sizeof(ulong32) * 20 + sizeof(int));
165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return err;
166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   Initialize the hash state
171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param md   The hash state you wish to initialize
172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @return CRYPT_OK if successful
173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint md4_init(hash_state * md)
175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   LTC_ARGCHK(md != NULL);
177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.state[0] = 0x67452301UL;
178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.state[1] = 0xefcdab89UL;
179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.state[2] = 0x98badcfeUL;
180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.state[3] = 0x10325476UL;
181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.length  = 0;
182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   md->md4.curlen  = 0;
183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   return CRYPT_OK;
184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   Process a block of memory though the hash
188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param md     The hash state
189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param in     The data to hash
190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param inlen  The length of the data (octets)
191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @return CRYPT_OK if successful
192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source ProjectHASH_PROCESS(md4_process, md4_compress, md4, 64)
194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   Terminate the hash to get the digest
197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param md  The hash state
198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @param out [out] The destination of the hash (16 bytes)
199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project   @return CRYPT_OK if successful
200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint md4_done(hash_state * md, unsigned char *out)
202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(md  != NULL);
206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    LTC_ARGCHK(out != NULL);
207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (md->md4.curlen >= sizeof(md->md4.buf)) {
209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project       return CRYPT_INVALID_ARG;
210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* increase the length of the message */
213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.length += md->md4.curlen * 8;
214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* append the '1' bit */
216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md->md4.buf[md->md4.curlen++] = (unsigned char)0x80;
217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* if the length is currently above 56 bytes we append zeros
219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     * then compress.  Then we can fall back to padding zeros and length
220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     * encoding like normal.
221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project     */
222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    if (md->md4.curlen > 56) {
223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        while (md->md4.curlen < 64) {
224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project            md->md4.buf[md->md4.curlen++] = (unsigned char)0;
225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md4_compress(md, md->md4.buf);
227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md->md4.curlen = 0;
228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* pad upto 56 bytes of zeroes */
231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    while (md->md4.curlen < 56) {
232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md->md4.buf[md->md4.curlen++] = (unsigned char)0;
233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* store length */
236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    STORE64L(md->md4.length, md->md4.buf+56);
237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    md4_compress(md, md->md4.buf);
238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    /* copy output */
240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for (i = 0; i < 4; i++) {
241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        STORE32L(md->md4.state[i], out+(4*i));
242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK
244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    zeromem(md, sizeof(hash_state));
245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/**
250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  Self-test the hash
251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/
253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint md4_test(void)
254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{
255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #ifndef LTC_TEST
256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_NOP;
257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project #else
258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    static const struct md4_test_case {
259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        char *input;
260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        unsigned char digest[16];
261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    } cases[] = {
262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "",
263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0x31, 0xd6, 0xcf, 0xe0, 0xd1, 0x6a, 0xe9, 0x31,
264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0xb7, 0x3c, 0x59, 0xd7, 0xe0, 0xc0, 0x89, 0xc0} },
265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "a",
266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0xbd, 0xe5, 0x2c, 0xb3, 0x1d, 0xe3, 0x3e, 0x46,
267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0x24, 0x5e, 0x05, 0xfb, 0xdb, 0xd6, 0xfb, 0x24} },
268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "abc",
269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0xa4, 0x48, 0x01, 0x7a, 0xaf, 0x21, 0xd8, 0x52,
270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0x5f, 0xc1, 0x0a, 0xe8, 0x7a, 0xa6, 0x72, 0x9d} },
271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "message digest",
272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0xd9, 0x13, 0x0a, 0x81, 0x64, 0x54, 0x9f, 0xe8,
273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0x18, 0x87, 0x48, 0x06, 0xe1, 0xc7, 0x01, 0x4b} },
274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "abcdefghijklmnopqrstuvwxyz",
275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0xd7, 0x9e, 0x1c, 0x30, 0x8a, 0xa5, 0xbb, 0xcd,
276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0xee, 0xa8, 0xed, 0x63, 0xdf, 0x41, 0x2d, 0xa9} },
277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0x04, 0x3f, 0x85, 0x82, 0xf2, 0x41, 0xdb, 0x35,
279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0x1c, 0xe6, 0x27, 0xe1, 0x53, 0xe7, 0xf0, 0xe4} },
280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project          {0xe3, 0x3b, 0x4d, 0xdc, 0x9c, 0x38, 0xf2, 0x19,
282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           0x9c, 0x3e, 0x7b, 0x16, 0x4f, 0xcc, 0x05, 0x36} },
283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    };
284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    int i;
285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    hash_state md;
286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    unsigned char digest[16];
287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    for(i = 0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) {
289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md4_init(&md);
290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md4_process(&md, (unsigned char *)cases[i].input, (unsigned long)strlen(cases[i].input));
291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        md4_done(&md, digest);
292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        if (XMEMCMP(digest, cases[i].digest, 16) != 0) {
293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project           return CRYPT_FAIL_TESTVECTOR;
294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project        }
295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    }
297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project    return CRYPT_OK;
298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project  #endif
299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project}
300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif
302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project
305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md4.c,v $ */
306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.8 $ */
307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/11/01 09:28:17 $ */
308