~ubuntu-branches/ubuntu/utopic/dropbear/utopic-proposed

« back to all changes in this revision

Viewing changes to libtomcrypt/src/hashes/md2.c

  • Committer: Bazaar Package Importer
  • Author(s): Matt Johnston
  • Date: 2005-12-08 19:20:21 UTC
  • mfrom: (1.2.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20051208192021-nyp9rwnt77nsg6ty
Tags: 0.47-1
* New upstream release.
* SECURITY: Fix incorrect buffer sizing.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
 
2
 *
 
3
 * LibTomCrypt is a library that provides various cryptographic
 
4
 * algorithms in a highly modular and flexible manner.
 
5
 *
 
6
 * The library is free for all purposes without any express
 
7
 * guarantee it works.
 
8
 *
 
9
 * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.org
 
10
 */
 
11
#include "tomcrypt.h"
 
12
 
 
13
/**
 
14
   @param md2.c
 
15
   MD2 (RFC 1319) hash function implementation by Tom St Denis 
 
16
*/
 
17
 
 
18
#ifdef MD2
 
19
 
 
20
const struct ltc_hash_descriptor md2_desc =
 
21
{
 
22
    "md2",
 
23
    7,
 
24
    16,
 
25
    16,
 
26
 
 
27
    /* OID */
 
28
   { 1, 2, 840, 113549, 2, 2,  },
 
29
   6,
 
30
 
 
31
    &md2_init,
 
32
    &md2_process,
 
33
    &md2_done,
 
34
    &md2_test
 
35
};
 
36
 
 
37
static const unsigned char PI_SUBST[256] = {
 
38
  41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
 
39
  19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
 
40
  76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
 
41
  138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
 
42
  245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
 
43
  148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
 
44
  39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
 
45
  181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
 
46
  150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
 
47
  112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
 
48
  96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
 
49
  85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
 
50
  234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
 
51
  129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
 
52
  8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
 
53
  203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
 
54
  166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
 
55
  31, 26, 219, 153, 141, 51, 159, 17, 131, 20
 
56
};
 
57
 
 
58
/* adds 16 bytes to the checksum */
 
59
static void md2_update_chksum(hash_state *md)
 
60
{
 
61
   int j;
 
62
   unsigned char L;
 
63
   L = md->md2.chksum[15];
 
64
   for (j = 0; j < 16; j++) {
 
65
 
 
66
/* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say 
 
67
   otherwise.
 
68
*/
 
69
       L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255);
 
70
   }
 
71
}
 
72
 
 
73
static void md2_compress(hash_state *md)
 
74
{
 
75
   int j, k;
 
76
   unsigned char t;
 
77
   
 
78
   /* copy block */
 
79
   for (j = 0; j < 16; j++) {
 
80
       md->md2.X[16+j] = md->md2.buf[j];
 
81
       md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j];
 
82
   }
 
83
 
 
84
   t = (unsigned char)0;
 
85
 
 
86
   /* do 18 rounds */
 
87
   for (j = 0; j < 18; j++) {
 
88
       for (k = 0; k < 48; k++) {
 
89
           t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
 
90
       }
 
91
       t = (t + (unsigned char)j) & 255;
 
92
   }
 
93
}
 
94
 
 
95
/**
 
96
   Initialize the hash state
 
97
   @param md   The hash state you wish to initialize
 
98
   @return CRYPT_OK if successful
 
99
*/
 
100
int md2_init(hash_state *md)
 
101
{
 
102
   LTC_ARGCHK(md != NULL);
 
103
 
 
104
   /* MD2 uses a zero'ed state... */
 
105
   zeromem(md->md2.X, sizeof(md->md2.X));
 
106
   zeromem(md->md2.chksum, sizeof(md->md2.chksum));
 
107
   zeromem(md->md2.buf, sizeof(md->md2.buf));
 
108
   md->md2.curlen = 0;
 
109
   return CRYPT_OK;
 
110
}
 
111
 
 
112
/**
 
113
   Process a block of memory though the hash
 
114
   @param md     The hash state
 
115
   @param in     The data to hash
 
116
   @param inlen  The length of the data (octets)
 
117
   @return CRYPT_OK if successful
 
118
*/
 
119
int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen)
 
120
{
 
121
    unsigned long n;
 
122
    LTC_ARGCHK(md != NULL);
 
123
    LTC_ARGCHK(in != NULL);
 
124
    if (md-> md2 .curlen > sizeof(md-> md2 .buf)) {                            
 
125
       return CRYPT_INVALID_ARG;                                                           
 
126
    }                                                                                       
 
127
    while (inlen > 0) {
 
128
        n = MIN(inlen, (16 - md->md2.curlen));
 
129
        XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n);
 
130
        md->md2.curlen += n;
 
131
        in             += n;
 
132
        inlen          -= n;
 
133
 
 
134
        /* is 16 bytes full? */
 
135
        if (md->md2.curlen == 16) {
 
136
            md2_compress(md);
 
137
            md2_update_chksum(md);
 
138
            md->md2.curlen = 0;
 
139
        }
 
140
    }
 
141
    return CRYPT_OK;
 
142
}
 
143
 
 
144
/**
 
145
   Terminate the hash to get the digest
 
146
   @param md  The hash state
 
147
   @param out [out] The destination of the hash (16 bytes)
 
148
   @return CRYPT_OK if successful
 
149
*/
 
150
int md2_done(hash_state * md, unsigned char *out)
 
151
{
 
152
    unsigned long i, k;
 
153
 
 
154
    LTC_ARGCHK(md  != NULL);
 
155
    LTC_ARGCHK(out != NULL);
 
156
 
 
157
    if (md->md2.curlen >= sizeof(md->md2.buf)) {
 
158
       return CRYPT_INVALID_ARG;
 
159
    }
 
160
 
 
161
 
 
162
    /* pad the message */
 
163
    k = 16 - md->md2.curlen;
 
164
    for (i = md->md2.curlen; i < 16; i++) {
 
165
        md->md2.buf[i] = (unsigned char)k;
 
166
    }
 
167
 
 
168
    /* hash and update */
 
169
    md2_compress(md);
 
170
    md2_update_chksum(md);
 
171
 
 
172
    /* hash checksum */
 
173
    XMEMCPY(md->md2.buf, md->md2.chksum, 16);
 
174
    md2_compress(md);
 
175
 
 
176
    /* output is lower 16 bytes of X */
 
177
    XMEMCPY(out, md->md2.X, 16);
 
178
 
 
179
#ifdef LTC_CLEAN_STACK
 
180
    zeromem(md, sizeof(hash_state));
 
181
#endif
 
182
    return CRYPT_OK;
 
183
}
 
184
 
 
185
/**
 
186
  Self-test the hash
 
187
  @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
 
188
*/  
 
189
int md2_test(void)
 
190
{
 
191
 #ifndef LTC_TEST
 
192
    return CRYPT_NOP;
 
193
 #else    
 
194
   static const struct {
 
195
        char *msg;
 
196
        unsigned char md[16];
 
197
   } tests[] = {
 
198
      { "",
 
199
        {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
 
200
         0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73
 
201
        }
 
202
      },
 
203
      { "a",
 
204
        {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
 
205
         0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1
 
206
        }
 
207
      },
 
208
      { "message digest",
 
209
        {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
 
210
         0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0
 
211
        }
 
212
      },
 
213
      { "abcdefghijklmnopqrstuvwxyz",
 
214
        {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
 
215
         0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b
 
216
        }
 
217
      },
 
218
      { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
 
219
        {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
 
220
         0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd
 
221
        }
 
222
      },
 
223
      { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
 
224
        {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
 
225
         0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8
 
226
        }
 
227
      }
 
228
   };
 
229
   int i;
 
230
   hash_state md;
 
231
   unsigned char buf[16];
 
232
 
 
233
   for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
 
234
       md2_init(&md);
 
235
       md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)strlen(tests[i].msg));
 
236
       md2_done(&md, buf);
 
237
       if (memcmp(buf, tests[i].md, 16) != 0) {
 
238
          return CRYPT_FAIL_TESTVECTOR;
 
239
       }
 
240
   }
 
241
   return CRYPT_OK;        
 
242
  #endif
 
243
}
 
244
 
 
245
#endif
 
246
 
 
247
 
 
248
/* $Source: /cvs/libtom/libtomcrypt/src/hashes/md2.c,v $ */
 
249
/* $Revision: 1.5 $ */
 
250
/* $Date: 2005/05/23 02:42:07 $ */