1 /*
2 * RFC 1115/1319 compliant MD2 implementation
3 *
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6 *
7 * This file is provided under the Apache License 2.0, or the
8 * GNU General Public License v2.0 or later.
9 *
10 * **********
11 * Apache License 2.0:
12 *
13 * Licensed under the Apache License, Version 2.0 (the "License"); you may
14 * not use this file except in compliance with the License.
15 * You may obtain a copy of the License at
16 *
17 * http://www.apache.org/licenses/LICENSE-2.0
18 *
19 * Unless required by applicable law or agreed to in writing, software
20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 * See the License for the specific language governing permissions and
23 * limitations under the License.
24 *
25 * **********
26 *
27 * **********
28 * GNU General Public License v2.0 or later:
29 *
30 * This program is free software; you can redistribute it and/or modify
31 * it under the terms of the GNU General Public License as published by
32 * the Free Software Foundation; either version 2 of the License, or
33 * (at your option) any later version.
34 *
35 * This program is distributed in the hope that it will be useful,
36 * but WITHOUT ANY WARRANTY; without even the implied warranty of
37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38 * GNU General Public License for more details.
39 *
40 * You should have received a copy of the GNU General Public License along
41 * with this program; if not, write to the Free Software Foundation, Inc.,
42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43 *
44 * **********
45 */
46 /*
47 * The MD2 algorithm was designed by Ron Rivest in 1989.
48 *
49 * http://www.ietf.org/rfc/rfc1115.txt
50 * http://www.ietf.org/rfc/rfc1319.txt
51 */
52
53 #if !defined(MBEDTLS_CONFIG_FILE)
54 #include "mbedtls/config.h"
55 #else
56 #include MBEDTLS_CONFIG_FILE
57 #endif
58
59 #if defined(MBEDTLS_MD2_C)
60
61 #include "mbedtls/md2.h"
62 #include "mbedtls/platform_util.h"
63
64 #include <string.h>
65
66 #if defined(MBEDTLS_SELF_TEST)
67 #if defined(MBEDTLS_PLATFORM_C)
68 #include "mbedtls/platform.h"
69 #else
70 #include <stdio.h>
71 #define mbedtls_printf printf
72 #endif /* MBEDTLS_PLATFORM_C */
73 #endif /* MBEDTLS_SELF_TEST */
74
75 #if !defined(MBEDTLS_MD2_ALT)
76
77 static const unsigned char PI_SUBST[256] =
78 {
79 0x29, 0x2E, 0x43, 0xC9, 0xA2, 0xD8, 0x7C, 0x01, 0x3D, 0x36,
80 0x54, 0xA1, 0xEC, 0xF0, 0x06, 0x13, 0x62, 0xA7, 0x05, 0xF3,
81 0xC0, 0xC7, 0x73, 0x8C, 0x98, 0x93, 0x2B, 0xD9, 0xBC, 0x4C,
82 0x82, 0xCA, 0x1E, 0x9B, 0x57, 0x3C, 0xFD, 0xD4, 0xE0, 0x16,
83 0x67, 0x42, 0x6F, 0x18, 0x8A, 0x17, 0xE5, 0x12, 0xBE, 0x4E,
84 0xC4, 0xD6, 0xDA, 0x9E, 0xDE, 0x49, 0xA0, 0xFB, 0xF5, 0x8E,
85 0xBB, 0x2F, 0xEE, 0x7A, 0xA9, 0x68, 0x79, 0x91, 0x15, 0xB2,
86 0x07, 0x3F, 0x94, 0xC2, 0x10, 0x89, 0x0B, 0x22, 0x5F, 0x21,
87 0x80, 0x7F, 0x5D, 0x9A, 0x5A, 0x90, 0x32, 0x27, 0x35, 0x3E,
88 0xCC, 0xE7, 0xBF, 0xF7, 0x97, 0x03, 0xFF, 0x19, 0x30, 0xB3,
89 0x48, 0xA5, 0xB5, 0xD1, 0xD7, 0x5E, 0x92, 0x2A, 0xAC, 0x56,
90 0xAA, 0xC6, 0x4F, 0xB8, 0x38, 0xD2, 0x96, 0xA4, 0x7D, 0xB6,
91 0x76, 0xFC, 0x6B, 0xE2, 0x9C, 0x74, 0x04, 0xF1, 0x45, 0x9D,
92 0x70, 0x59, 0x64, 0x71, 0x87, 0x20, 0x86, 0x5B, 0xCF, 0x65,
93 0xE6, 0x2D, 0xA8, 0x02, 0x1B, 0x60, 0x25, 0xAD, 0xAE, 0xB0,
94 0xB9, 0xF6, 0x1C, 0x46, 0x61, 0x69, 0x34, 0x40, 0x7E, 0x0F,
95 0x55, 0x47, 0xA3, 0x23, 0xDD, 0x51, 0xAF, 0x3A, 0xC3, 0x5C,
96 0xF9, 0xCE, 0xBA, 0xC5, 0xEA, 0x26, 0x2C, 0x53, 0x0D, 0x6E,
97 0x85, 0x28, 0x84, 0x09, 0xD3, 0xDF, 0xCD, 0xF4, 0x41, 0x81,
98 0x4D, 0x52, 0x6A, 0xDC, 0x37, 0xC8, 0x6C, 0xC1, 0xAB, 0xFA,
99 0x24, 0xE1, 0x7B, 0x08, 0x0C, 0xBD, 0xB1, 0x4A, 0x78, 0x88,
100 0x95, 0x8B, 0xE3, 0x63, 0xE8, 0x6D, 0xE9, 0xCB, 0xD5, 0xFE,
101 0x3B, 0x00, 0x1D, 0x39, 0xF2, 0xEF, 0xB7, 0x0E, 0x66, 0x58,
102 0xD0, 0xE4, 0xA6, 0x77, 0x72, 0xF8, 0xEB, 0x75, 0x4B, 0x0A,
103 0x31, 0x44, 0x50, 0xB4, 0x8F, 0xED, 0x1F, 0x1A, 0xDB, 0x99,
104 0x8D, 0x33, 0x9F, 0x11, 0x83, 0x14
105 };
106
mbedtls_md2_init(mbedtls_md2_context * ctx)107 void mbedtls_md2_init( mbedtls_md2_context *ctx )
108 {
109 memset( ctx, 0, sizeof( mbedtls_md2_context ) );
110 }
111
mbedtls_md2_free(mbedtls_md2_context * ctx)112 void mbedtls_md2_free( mbedtls_md2_context *ctx )
113 {
114 if( ctx == NULL )
115 return;
116
117 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md2_context ) );
118 }
119
mbedtls_md2_clone(mbedtls_md2_context * dst,const mbedtls_md2_context * src)120 void mbedtls_md2_clone( mbedtls_md2_context *dst,
121 const mbedtls_md2_context *src )
122 {
123 *dst = *src;
124 }
125
126 /*
127 * MD2 context setup
128 */
mbedtls_md2_starts_ret(mbedtls_md2_context * ctx)129 int mbedtls_md2_starts_ret( mbedtls_md2_context *ctx )
130 {
131 memset( ctx->cksum, 0, 16 );
132 memset( ctx->state, 0, 46 );
133 memset( ctx->buffer, 0, 16 );
134 ctx->left = 0;
135
136 return( 0 );
137 }
138
139 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md2_starts(mbedtls_md2_context * ctx)140 void mbedtls_md2_starts( mbedtls_md2_context *ctx )
141 {
142 mbedtls_md2_starts_ret( ctx );
143 }
144 #endif
145
146 #if !defined(MBEDTLS_MD2_PROCESS_ALT)
mbedtls_internal_md2_process(mbedtls_md2_context * ctx)147 int mbedtls_internal_md2_process( mbedtls_md2_context *ctx )
148 {
149 int i, j;
150 unsigned char t = 0;
151
152 for( i = 0; i < 16; i++ )
153 {
154 ctx->state[i + 16] = ctx->buffer[i];
155 ctx->state[i + 32] =
156 (unsigned char)( ctx->buffer[i] ^ ctx->state[i]);
157 }
158
159 for( i = 0; i < 18; i++ )
160 {
161 for( j = 0; j < 48; j++ )
162 {
163 ctx->state[j] = (unsigned char)
164 ( ctx->state[j] ^ PI_SUBST[t] );
165 t = ctx->state[j];
166 }
167
168 t = (unsigned char)( t + i );
169 }
170
171 t = ctx->cksum[15];
172
173 for( i = 0; i < 16; i++ )
174 {
175 ctx->cksum[i] = (unsigned char)
176 ( ctx->cksum[i] ^ PI_SUBST[ctx->buffer[i] ^ t] );
177 t = ctx->cksum[i];
178 }
179
180 /* Zeroise variables to clear sensitive data from memory. */
181 mbedtls_platform_zeroize( &t, sizeof( t ) );
182
183 return( 0 );
184 }
185
186 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md2_process(mbedtls_md2_context * ctx)187 void mbedtls_md2_process( mbedtls_md2_context *ctx )
188 {
189 mbedtls_internal_md2_process( ctx );
190 }
191 #endif
192 #endif /* !MBEDTLS_MD2_PROCESS_ALT */
193
194 /*
195 * MD2 process buffer
196 */
mbedtls_md2_update_ret(mbedtls_md2_context * ctx,const unsigned char * input,size_t ilen)197 int mbedtls_md2_update_ret( mbedtls_md2_context *ctx,
198 const unsigned char *input,
199 size_t ilen )
200 {
201 int ret;
202 size_t fill;
203
204 while( ilen > 0 )
205 {
206 if( ilen > 16 - ctx->left )
207 fill = 16 - ctx->left;
208 else
209 fill = ilen;
210
211 memcpy( ctx->buffer + ctx->left, input, fill );
212
213 ctx->left += fill;
214 input += fill;
215 ilen -= fill;
216
217 if( ctx->left == 16 )
218 {
219 ctx->left = 0;
220 if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
221 return( ret );
222 }
223 }
224
225 return( 0 );
226 }
227
228 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md2_update(mbedtls_md2_context * ctx,const unsigned char * input,size_t ilen)229 void mbedtls_md2_update( mbedtls_md2_context *ctx,
230 const unsigned char *input,
231 size_t ilen )
232 {
233 mbedtls_md2_update_ret( ctx, input, ilen );
234 }
235 #endif
236
237 /*
238 * MD2 final digest
239 */
mbedtls_md2_finish_ret(mbedtls_md2_context * ctx,unsigned char output[16])240 int mbedtls_md2_finish_ret( mbedtls_md2_context *ctx,
241 unsigned char output[16] )
242 {
243 int ret;
244 size_t i;
245 unsigned char x;
246
247 x = (unsigned char)( 16 - ctx->left );
248
249 for( i = ctx->left; i < 16; i++ )
250 ctx->buffer[i] = x;
251
252 if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
253 return( ret );
254
255 memcpy( ctx->buffer, ctx->cksum, 16 );
256 if( ( ret = mbedtls_internal_md2_process( ctx ) ) != 0 )
257 return( ret );
258
259 memcpy( output, ctx->state, 16 );
260
261 return( 0 );
262 }
263
264 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md2_finish(mbedtls_md2_context * ctx,unsigned char output[16])265 void mbedtls_md2_finish( mbedtls_md2_context *ctx,
266 unsigned char output[16] )
267 {
268 mbedtls_md2_finish_ret( ctx, output );
269 }
270 #endif
271
272 #endif /* !MBEDTLS_MD2_ALT */
273
274 /*
275 * output = MD2( input buffer )
276 */
mbedtls_md2_ret(const unsigned char * input,size_t ilen,unsigned char output[16])277 int mbedtls_md2_ret( const unsigned char *input,
278 size_t ilen,
279 unsigned char output[16] )
280 {
281 int ret;
282 mbedtls_md2_context ctx;
283
284 mbedtls_md2_init( &ctx );
285
286 if( ( ret = mbedtls_md2_starts_ret( &ctx ) ) != 0 )
287 goto exit;
288
289 if( ( ret = mbedtls_md2_update_ret( &ctx, input, ilen ) ) != 0 )
290 goto exit;
291
292 if( ( ret = mbedtls_md2_finish_ret( &ctx, output ) ) != 0 )
293 goto exit;
294
295 exit:
296 mbedtls_md2_free( &ctx );
297
298 return( ret );
299 }
300
301 #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md2(const unsigned char * input,size_t ilen,unsigned char output[16])302 void mbedtls_md2( const unsigned char *input,
303 size_t ilen,
304 unsigned char output[16] )
305 {
306 mbedtls_md2_ret( input, ilen, output );
307 }
308 #endif
309
310 #if defined(MBEDTLS_SELF_TEST)
311
312 /*
313 * RFC 1319 test vectors
314 */
315 static const unsigned char md2_test_str[7][81] =
316 {
317 { "" },
318 { "a" },
319 { "abc" },
320 { "message digest" },
321 { "abcdefghijklmnopqrstuvwxyz" },
322 { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
323 { "12345678901234567890123456789012345678901234567890123456789012"
324 "345678901234567890" }
325 };
326
327 static const size_t md2_test_strlen[7] =
328 {
329 0, 1, 3, 14, 26, 62, 80
330 };
331
332 static const unsigned char md2_test_sum[7][16] =
333 {
334 { 0x83, 0x50, 0xE5, 0xA3, 0xE2, 0x4C, 0x15, 0x3D,
335 0xF2, 0x27, 0x5C, 0x9F, 0x80, 0x69, 0x27, 0x73 },
336 { 0x32, 0xEC, 0x01, 0xEC, 0x4A, 0x6D, 0xAC, 0x72,
337 0xC0, 0xAB, 0x96, 0xFB, 0x34, 0xC0, 0xB5, 0xD1 },
338 { 0xDA, 0x85, 0x3B, 0x0D, 0x3F, 0x88, 0xD9, 0x9B,
339 0x30, 0x28, 0x3A, 0x69, 0xE6, 0xDE, 0xD6, 0xBB },
340 { 0xAB, 0x4F, 0x49, 0x6B, 0xFB, 0x2A, 0x53, 0x0B,
341 0x21, 0x9F, 0xF3, 0x30, 0x31, 0xFE, 0x06, 0xB0 },
342 { 0x4E, 0x8D, 0xDF, 0xF3, 0x65, 0x02, 0x92, 0xAB,
343 0x5A, 0x41, 0x08, 0xC3, 0xAA, 0x47, 0x94, 0x0B },
344 { 0xDA, 0x33, 0xDE, 0xF2, 0xA4, 0x2D, 0xF1, 0x39,
345 0x75, 0x35, 0x28, 0x46, 0xC3, 0x03, 0x38, 0xCD },
346 { 0xD5, 0x97, 0x6F, 0x79, 0xD8, 0x3D, 0x3A, 0x0D,
347 0xC9, 0x80, 0x6C, 0x3C, 0x66, 0xF3, 0xEF, 0xD8 }
348 };
349
350 /*
351 * Checkup routine
352 */
mbedtls_md2_self_test(int verbose)353 int mbedtls_md2_self_test( int verbose )
354 {
355 int i, ret = 0;
356 unsigned char md2sum[16];
357
358 for( i = 0; i < 7; i++ )
359 {
360 if( verbose != 0 )
361 mbedtls_printf( " MD2 test #%d: ", i + 1 );
362
363 ret = mbedtls_md2_ret( md2_test_str[i], md2_test_strlen[i], md2sum );
364 if( ret != 0 )
365 goto fail;
366
367 if( memcmp( md2sum, md2_test_sum[i], 16 ) != 0 )
368 {
369 ret = 1;
370 goto fail;
371 }
372
373 if( verbose != 0 )
374 mbedtls_printf( "passed\n" );
375 }
376
377 if( verbose != 0 )
378 mbedtls_printf( "\n" );
379
380 return( 0 );
381
382 fail:
383 if( verbose != 0 )
384 mbedtls_printf( "failed\n" );
385
386 return( ret );
387 }
388
389 #endif /* MBEDTLS_SELF_TEST */
390
391 #endif /* MBEDTLS_MD2_C */
392