1c2c66affSColin Finck /*
2c2c66affSColin Finck * RFC 1186/1320 compliant MD4 implementation
3c2c66affSColin Finck *
4218e2596SThomas Faber * Copyright The Mbed TLS Contributors
5e57126f5SThomas Faber * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6e57126f5SThomas Faber *
7e57126f5SThomas Faber * This file is provided under the Apache License 2.0, or the
8e57126f5SThomas Faber * GNU General Public License v2.0 or later.
9e57126f5SThomas Faber *
10e57126f5SThomas Faber * **********
11e57126f5SThomas Faber * Apache License 2.0:
12e57126f5SThomas Faber *
13e57126f5SThomas Faber * Licensed under the Apache License, Version 2.0 (the "License"); you may
14e57126f5SThomas Faber * not use this file except in compliance with the License.
15e57126f5SThomas Faber * You may obtain a copy of the License at
16e57126f5SThomas Faber *
17e57126f5SThomas Faber * http://www.apache.org/licenses/LICENSE-2.0
18e57126f5SThomas Faber *
19e57126f5SThomas Faber * Unless required by applicable law or agreed to in writing, software
20e57126f5SThomas Faber * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
21e57126f5SThomas Faber * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22e57126f5SThomas Faber * See the License for the specific language governing permissions and
23e57126f5SThomas Faber * limitations under the License.
24e57126f5SThomas Faber *
25e57126f5SThomas Faber * **********
26e57126f5SThomas Faber *
27e57126f5SThomas Faber * **********
28e57126f5SThomas Faber * GNU General Public License v2.0 or later:
29c2c66affSColin Finck *
30c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify
31c2c66affSColin Finck * it under the terms of the GNU General Public License as published by
32c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or
33c2c66affSColin Finck * (at your option) any later version.
34c2c66affSColin Finck *
35c2c66affSColin Finck * This program is distributed in the hope that it will be useful,
36c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
37c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
38c2c66affSColin Finck * GNU General Public License for more details.
39c2c66affSColin Finck *
40c2c66affSColin Finck * You should have received a copy of the GNU General Public License along
41c2c66affSColin Finck * with this program; if not, write to the Free Software Foundation, Inc.,
42c2c66affSColin Finck * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
43c2c66affSColin Finck *
44e57126f5SThomas Faber * **********
45c2c66affSColin Finck */
46c2c66affSColin Finck /*
47c2c66affSColin Finck * The MD4 algorithm was designed by Ron Rivest in 1990.
48c2c66affSColin Finck *
49c2c66affSColin Finck * http://www.ietf.org/rfc/rfc1186.txt
50c2c66affSColin Finck * http://www.ietf.org/rfc/rfc1320.txt
51c2c66affSColin Finck */
52c2c66affSColin Finck
53c2c66affSColin Finck #if !defined(MBEDTLS_CONFIG_FILE)
54c2c66affSColin Finck #include "mbedtls/config.h"
55c2c66affSColin Finck #else
56c2c66affSColin Finck #include MBEDTLS_CONFIG_FILE
57c2c66affSColin Finck #endif
58c2c66affSColin Finck
59c2c66affSColin Finck #if defined(MBEDTLS_MD4_C)
60c2c66affSColin Finck
61c2c66affSColin Finck #include "mbedtls/md4.h"
62*cbda039fSThomas Faber #include "mbedtls/platform_util.h"
63c2c66affSColin Finck
64c2c66affSColin Finck #include <string.h>
65c2c66affSColin Finck
66c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
67c2c66affSColin Finck #if defined(MBEDTLS_PLATFORM_C)
68c2c66affSColin Finck #include "mbedtls/platform.h"
69c2c66affSColin Finck #else
70c2c66affSColin Finck #include <stdio.h>
71c2c66affSColin Finck #define mbedtls_printf printf
72c2c66affSColin Finck #endif /* MBEDTLS_PLATFORM_C */
73c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
74c2c66affSColin Finck
75c2c66affSColin Finck #if !defined(MBEDTLS_MD4_ALT)
76c2c66affSColin Finck
77c2c66affSColin Finck /*
78c2c66affSColin Finck * 32-bit integer manipulation macros (little endian)
79c2c66affSColin Finck */
80c2c66affSColin Finck #ifndef GET_UINT32_LE
81c2c66affSColin Finck #define GET_UINT32_LE(n,b,i) \
82c2c66affSColin Finck { \
83c2c66affSColin Finck (n) = ( (uint32_t) (b)[(i) ] ) \
84c2c66affSColin Finck | ( (uint32_t) (b)[(i) + 1] << 8 ) \
85c2c66affSColin Finck | ( (uint32_t) (b)[(i) + 2] << 16 ) \
86c2c66affSColin Finck | ( (uint32_t) (b)[(i) + 3] << 24 ); \
87c2c66affSColin Finck }
88c2c66affSColin Finck #endif
89c2c66affSColin Finck
90c2c66affSColin Finck #ifndef PUT_UINT32_LE
91c2c66affSColin Finck #define PUT_UINT32_LE(n,b,i) \
92c2c66affSColin Finck { \
93c2c66affSColin Finck (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \
94c2c66affSColin Finck (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \
95c2c66affSColin Finck (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \
96c2c66affSColin Finck (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \
97c2c66affSColin Finck }
98c2c66affSColin Finck #endif
99c2c66affSColin Finck
mbedtls_md4_init(mbedtls_md4_context * ctx)100c2c66affSColin Finck void mbedtls_md4_init( mbedtls_md4_context *ctx )
101c2c66affSColin Finck {
102c2c66affSColin Finck memset( ctx, 0, sizeof( mbedtls_md4_context ) );
103c2c66affSColin Finck }
104c2c66affSColin Finck
mbedtls_md4_free(mbedtls_md4_context * ctx)105c2c66affSColin Finck void mbedtls_md4_free( mbedtls_md4_context *ctx )
106c2c66affSColin Finck {
107c2c66affSColin Finck if( ctx == NULL )
108c2c66affSColin Finck return;
109c2c66affSColin Finck
110*cbda039fSThomas Faber mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md4_context ) );
111c2c66affSColin Finck }
112c2c66affSColin Finck
mbedtls_md4_clone(mbedtls_md4_context * dst,const mbedtls_md4_context * src)113c2c66affSColin Finck void mbedtls_md4_clone( mbedtls_md4_context *dst,
114c2c66affSColin Finck const mbedtls_md4_context *src )
115c2c66affSColin Finck {
116c2c66affSColin Finck *dst = *src;
117c2c66affSColin Finck }
118c2c66affSColin Finck
119c2c66affSColin Finck /*
120c2c66affSColin Finck * MD4 context setup
121c2c66affSColin Finck */
mbedtls_md4_starts_ret(mbedtls_md4_context * ctx)122d9e6c9b5SThomas Faber int mbedtls_md4_starts_ret( mbedtls_md4_context *ctx )
123c2c66affSColin Finck {
124c2c66affSColin Finck ctx->total[0] = 0;
125c2c66affSColin Finck ctx->total[1] = 0;
126c2c66affSColin Finck
127c2c66affSColin Finck ctx->state[0] = 0x67452301;
128c2c66affSColin Finck ctx->state[1] = 0xEFCDAB89;
129c2c66affSColin Finck ctx->state[2] = 0x98BADCFE;
130c2c66affSColin Finck ctx->state[3] = 0x10325476;
131d9e6c9b5SThomas Faber
132d9e6c9b5SThomas Faber return( 0 );
133c2c66affSColin Finck }
134c2c66affSColin Finck
135d9e6c9b5SThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_starts(mbedtls_md4_context * ctx)136d9e6c9b5SThomas Faber void mbedtls_md4_starts( mbedtls_md4_context *ctx )
137d9e6c9b5SThomas Faber {
138d9e6c9b5SThomas Faber mbedtls_md4_starts_ret( ctx );
139d9e6c9b5SThomas Faber }
140d9e6c9b5SThomas Faber #endif
141d9e6c9b5SThomas Faber
142c2c66affSColin Finck #if !defined(MBEDTLS_MD4_PROCESS_ALT)
mbedtls_internal_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])143d9e6c9b5SThomas Faber int mbedtls_internal_md4_process( mbedtls_md4_context *ctx,
144d9e6c9b5SThomas Faber const unsigned char data[64] )
145c2c66affSColin Finck {
1462e53fc8eSThomas Faber struct
1472e53fc8eSThomas Faber {
148c2c66affSColin Finck uint32_t X[16], A, B, C, D;
1492e53fc8eSThomas Faber } local;
150c2c66affSColin Finck
1512e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 0], data, 0 );
1522e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 1], data, 4 );
1532e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 2], data, 8 );
1542e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 3], data, 12 );
1552e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 4], data, 16 );
1562e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 5], data, 20 );
1572e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 6], data, 24 );
1582e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 7], data, 28 );
1592e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 8], data, 32 );
1602e53fc8eSThomas Faber GET_UINT32_LE( local.X[ 9], data, 36 );
1612e53fc8eSThomas Faber GET_UINT32_LE( local.X[10], data, 40 );
1622e53fc8eSThomas Faber GET_UINT32_LE( local.X[11], data, 44 );
1632e53fc8eSThomas Faber GET_UINT32_LE( local.X[12], data, 48 );
1642e53fc8eSThomas Faber GET_UINT32_LE( local.X[13], data, 52 );
1652e53fc8eSThomas Faber GET_UINT32_LE( local.X[14], data, 56 );
1662e53fc8eSThomas Faber GET_UINT32_LE( local.X[15], data, 60 );
167c2c66affSColin Finck
168*cbda039fSThomas Faber #define S(x,n) (((x) << (n)) | (((x) & 0xFFFFFFFF) >> (32 - (n))))
169c2c66affSColin Finck
1702e53fc8eSThomas Faber local.A = ctx->state[0];
1712e53fc8eSThomas Faber local.B = ctx->state[1];
1722e53fc8eSThomas Faber local.C = ctx->state[2];
1732e53fc8eSThomas Faber local.D = ctx->state[3];
174c2c66affSColin Finck
175*cbda039fSThomas Faber #define F(x, y, z) (((x) & (y)) | ((~(x)) & (z)))
176*cbda039fSThomas Faber #define P(a,b,c,d,x,s) \
177*cbda039fSThomas Faber do \
178*cbda039fSThomas Faber { \
179*cbda039fSThomas Faber (a) += F((b),(c),(d)) + (x); \
180*cbda039fSThomas Faber (a) = S((a),(s)); \
181*cbda039fSThomas Faber } while( 0 )
182*cbda039fSThomas Faber
183c2c66affSColin Finck
1842e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
1852e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 1], 7 );
1862e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 2], 11 );
1872e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[ 3], 19 );
1882e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 4], 3 );
1892e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 5], 7 );
1902e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
1912e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[ 7], 19 );
1922e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 8], 3 );
1932e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 9], 7 );
1942e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[10], 11 );
1952e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[11], 19 );
1962e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[12], 3 );
1972e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[13], 7 );
1982e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[14], 11 );
1992e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[15], 19 );
200c2c66affSColin Finck
201c2c66affSColin Finck #undef P
202c2c66affSColin Finck #undef F
203c2c66affSColin Finck
204*cbda039fSThomas Faber #define F(x,y,z) (((x) & (y)) | ((x) & (z)) | ((y) & (z)))
205*cbda039fSThomas Faber #define P(a,b,c,d,x,s) \
206*cbda039fSThomas Faber do \
207*cbda039fSThomas Faber { \
208*cbda039fSThomas Faber (a) += F((b),(c),(d)) + (x) + 0x5A827999; \
209*cbda039fSThomas Faber (a) = S((a),(s)); \
210*cbda039fSThomas Faber } while( 0 )
211c2c66affSColin Finck
2122e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
2132e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 4], 5 );
2142e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 8], 9 );
2152e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[12], 13 );
2162e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
2172e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 5], 5 );
2182e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 9], 9 );
2192e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[13], 13 );
2202e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
2212e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 6], 5 );
2222e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[10], 9 );
2232e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[14], 13 );
2242e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
2252e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 7], 5 );
2262e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[11], 9 );
2272e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[15], 13 );
228c2c66affSColin Finck
229c2c66affSColin Finck #undef P
230c2c66affSColin Finck #undef F
231c2c66affSColin Finck
232*cbda039fSThomas Faber #define F(x,y,z) ((x) ^ (y) ^ (z))
233*cbda039fSThomas Faber #define P(a,b,c,d,x,s) \
234*cbda039fSThomas Faber do \
235*cbda039fSThomas Faber { \
236*cbda039fSThomas Faber (a) += F((b),(c),(d)) + (x) + 0x6ED9EBA1; \
237*cbda039fSThomas Faber (a) = S((a),(s)); \
238*cbda039fSThomas Faber } while( 0 )
239c2c66affSColin Finck
2402e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 0], 3 );
2412e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 8], 9 );
2422e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 4], 11 );
2432e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[12], 15 );
2442e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 2], 3 );
2452e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[10], 9 );
2462e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 6], 11 );
2472e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[14], 15 );
2482e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 1], 3 );
2492e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[ 9], 9 );
2502e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 5], 11 );
2512e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[13], 15 );
2522e53fc8eSThomas Faber P( local.A, local.B, local.C, local.D, local.X[ 3], 3 );
2532e53fc8eSThomas Faber P( local.D, local.A, local.B, local.C, local.X[11], 9 );
2542e53fc8eSThomas Faber P( local.C, local.D, local.A, local.B, local.X[ 7], 11 );
2552e53fc8eSThomas Faber P( local.B, local.C, local.D, local.A, local.X[15], 15 );
256c2c66affSColin Finck
257c2c66affSColin Finck #undef F
258c2c66affSColin Finck #undef P
259c2c66affSColin Finck
2602e53fc8eSThomas Faber ctx->state[0] += local.A;
2612e53fc8eSThomas Faber ctx->state[1] += local.B;
2622e53fc8eSThomas Faber ctx->state[2] += local.C;
2632e53fc8eSThomas Faber ctx->state[3] += local.D;
2642e53fc8eSThomas Faber
2652e53fc8eSThomas Faber /* Zeroise variables to clear sensitive data from memory. */
266*cbda039fSThomas Faber mbedtls_platform_zeroize( &local, sizeof( local ) );
267d9e6c9b5SThomas Faber
268d9e6c9b5SThomas Faber return( 0 );
269c2c66affSColin Finck }
270d9e6c9b5SThomas Faber
271d9e6c9b5SThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_process(mbedtls_md4_context * ctx,const unsigned char data[64])272d9e6c9b5SThomas Faber void mbedtls_md4_process( mbedtls_md4_context *ctx,
273d9e6c9b5SThomas Faber const unsigned char data[64] )
274d9e6c9b5SThomas Faber {
275d9e6c9b5SThomas Faber mbedtls_internal_md4_process( ctx, data );
276d9e6c9b5SThomas Faber }
277d9e6c9b5SThomas Faber #endif
278c2c66affSColin Finck #endif /* !MBEDTLS_MD4_PROCESS_ALT */
279c2c66affSColin Finck
280c2c66affSColin Finck /*
281c2c66affSColin Finck * MD4 process buffer
282c2c66affSColin Finck */
mbedtls_md4_update_ret(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)283d9e6c9b5SThomas Faber int mbedtls_md4_update_ret( mbedtls_md4_context *ctx,
284d9e6c9b5SThomas Faber const unsigned char *input,
285d9e6c9b5SThomas Faber size_t ilen )
286c2c66affSColin Finck {
287d9e6c9b5SThomas Faber int ret;
288c2c66affSColin Finck size_t fill;
289c2c66affSColin Finck uint32_t left;
290c2c66affSColin Finck
291c2c66affSColin Finck if( ilen == 0 )
292d9e6c9b5SThomas Faber return( 0 );
293c2c66affSColin Finck
294c2c66affSColin Finck left = ctx->total[0] & 0x3F;
295c2c66affSColin Finck fill = 64 - left;
296c2c66affSColin Finck
297c2c66affSColin Finck ctx->total[0] += (uint32_t) ilen;
298c2c66affSColin Finck ctx->total[0] &= 0xFFFFFFFF;
299c2c66affSColin Finck
300c2c66affSColin Finck if( ctx->total[0] < (uint32_t) ilen )
301c2c66affSColin Finck ctx->total[1]++;
302c2c66affSColin Finck
303c2c66affSColin Finck if( left && ilen >= fill )
304c2c66affSColin Finck {
305c2c66affSColin Finck memcpy( (void *) (ctx->buffer + left),
306c2c66affSColin Finck (void *) input, fill );
307d9e6c9b5SThomas Faber
308d9e6c9b5SThomas Faber if( ( ret = mbedtls_internal_md4_process( ctx, ctx->buffer ) ) != 0 )
309d9e6c9b5SThomas Faber return( ret );
310d9e6c9b5SThomas Faber
311c2c66affSColin Finck input += fill;
312c2c66affSColin Finck ilen -= fill;
313c2c66affSColin Finck left = 0;
314c2c66affSColin Finck }
315c2c66affSColin Finck
316c2c66affSColin Finck while( ilen >= 64 )
317c2c66affSColin Finck {
318d9e6c9b5SThomas Faber if( ( ret = mbedtls_internal_md4_process( ctx, input ) ) != 0 )
319d9e6c9b5SThomas Faber return( ret );
320d9e6c9b5SThomas Faber
321c2c66affSColin Finck input += 64;
322c2c66affSColin Finck ilen -= 64;
323c2c66affSColin Finck }
324c2c66affSColin Finck
325c2c66affSColin Finck if( ilen > 0 )
326c2c66affSColin Finck {
327c2c66affSColin Finck memcpy( (void *) (ctx->buffer + left),
328c2c66affSColin Finck (void *) input, ilen );
329c2c66affSColin Finck }
330d9e6c9b5SThomas Faber
331d9e6c9b5SThomas Faber return( 0 );
332c2c66affSColin Finck }
333c2c66affSColin Finck
334d9e6c9b5SThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_update(mbedtls_md4_context * ctx,const unsigned char * input,size_t ilen)335d9e6c9b5SThomas Faber void mbedtls_md4_update( mbedtls_md4_context *ctx,
336d9e6c9b5SThomas Faber const unsigned char *input,
337d9e6c9b5SThomas Faber size_t ilen )
338d9e6c9b5SThomas Faber {
339d9e6c9b5SThomas Faber mbedtls_md4_update_ret( ctx, input, ilen );
340d9e6c9b5SThomas Faber }
341d9e6c9b5SThomas Faber #endif
342d9e6c9b5SThomas Faber
343c2c66affSColin Finck static const unsigned char md4_padding[64] =
344c2c66affSColin Finck {
345c2c66affSColin Finck 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346c2c66affSColin Finck 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347c2c66affSColin Finck 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348c2c66affSColin Finck 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
349c2c66affSColin Finck };
350c2c66affSColin Finck
351c2c66affSColin Finck /*
352c2c66affSColin Finck * MD4 final digest
353c2c66affSColin Finck */
mbedtls_md4_finish_ret(mbedtls_md4_context * ctx,unsigned char output[16])354d9e6c9b5SThomas Faber int mbedtls_md4_finish_ret( mbedtls_md4_context *ctx,
355d9e6c9b5SThomas Faber unsigned char output[16] )
356c2c66affSColin Finck {
357d9e6c9b5SThomas Faber int ret;
358c2c66affSColin Finck uint32_t last, padn;
359c2c66affSColin Finck uint32_t high, low;
360c2c66affSColin Finck unsigned char msglen[8];
361c2c66affSColin Finck
362c2c66affSColin Finck high = ( ctx->total[0] >> 29 )
363c2c66affSColin Finck | ( ctx->total[1] << 3 );
364c2c66affSColin Finck low = ( ctx->total[0] << 3 );
365c2c66affSColin Finck
366c2c66affSColin Finck PUT_UINT32_LE( low, msglen, 0 );
367c2c66affSColin Finck PUT_UINT32_LE( high, msglen, 4 );
368c2c66affSColin Finck
369c2c66affSColin Finck last = ctx->total[0] & 0x3F;
370c2c66affSColin Finck padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
371c2c66affSColin Finck
372d9e6c9b5SThomas Faber ret = mbedtls_md4_update_ret( ctx, (unsigned char *)md4_padding, padn );
373d9e6c9b5SThomas Faber if( ret != 0 )
374d9e6c9b5SThomas Faber return( ret );
375d9e6c9b5SThomas Faber
376d9e6c9b5SThomas Faber if( ( ret = mbedtls_md4_update_ret( ctx, msglen, 8 ) ) != 0 )
377d9e6c9b5SThomas Faber return( ret );
378d9e6c9b5SThomas Faber
379c2c66affSColin Finck
380c2c66affSColin Finck PUT_UINT32_LE( ctx->state[0], output, 0 );
381c2c66affSColin Finck PUT_UINT32_LE( ctx->state[1], output, 4 );
382c2c66affSColin Finck PUT_UINT32_LE( ctx->state[2], output, 8 );
383c2c66affSColin Finck PUT_UINT32_LE( ctx->state[3], output, 12 );
384d9e6c9b5SThomas Faber
385d9e6c9b5SThomas Faber return( 0 );
386c2c66affSColin Finck }
387c2c66affSColin Finck
388d9e6c9b5SThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4_finish(mbedtls_md4_context * ctx,unsigned char output[16])389d9e6c9b5SThomas Faber void mbedtls_md4_finish( mbedtls_md4_context *ctx,
390d9e6c9b5SThomas Faber unsigned char output[16] )
391d9e6c9b5SThomas Faber {
392d9e6c9b5SThomas Faber mbedtls_md4_finish_ret( ctx, output );
393d9e6c9b5SThomas Faber }
394d9e6c9b5SThomas Faber #endif
395d9e6c9b5SThomas Faber
396c2c66affSColin Finck #endif /* !MBEDTLS_MD4_ALT */
397c2c66affSColin Finck
398c2c66affSColin Finck /*
399c2c66affSColin Finck * output = MD4( input buffer )
400c2c66affSColin Finck */
mbedtls_md4_ret(const unsigned char * input,size_t ilen,unsigned char output[16])401d9e6c9b5SThomas Faber int mbedtls_md4_ret( const unsigned char *input,
402d9e6c9b5SThomas Faber size_t ilen,
403d9e6c9b5SThomas Faber unsigned char output[16] )
404c2c66affSColin Finck {
405d9e6c9b5SThomas Faber int ret;
406c2c66affSColin Finck mbedtls_md4_context ctx;
407c2c66affSColin Finck
408c2c66affSColin Finck mbedtls_md4_init( &ctx );
409d9e6c9b5SThomas Faber
410d9e6c9b5SThomas Faber if( ( ret = mbedtls_md4_starts_ret( &ctx ) ) != 0 )
411d9e6c9b5SThomas Faber goto exit;
412d9e6c9b5SThomas Faber
413d9e6c9b5SThomas Faber if( ( ret = mbedtls_md4_update_ret( &ctx, input, ilen ) ) != 0 )
414d9e6c9b5SThomas Faber goto exit;
415d9e6c9b5SThomas Faber
416d9e6c9b5SThomas Faber if( ( ret = mbedtls_md4_finish_ret( &ctx, output ) ) != 0 )
417d9e6c9b5SThomas Faber goto exit;
418d9e6c9b5SThomas Faber
419d9e6c9b5SThomas Faber exit:
420c2c66affSColin Finck mbedtls_md4_free( &ctx );
421d9e6c9b5SThomas Faber
422d9e6c9b5SThomas Faber return( ret );
423c2c66affSColin Finck }
424c2c66affSColin Finck
425d9e6c9b5SThomas Faber #if !defined(MBEDTLS_DEPRECATED_REMOVED)
mbedtls_md4(const unsigned char * input,size_t ilen,unsigned char output[16])426d9e6c9b5SThomas Faber void mbedtls_md4( const unsigned char *input,
427d9e6c9b5SThomas Faber size_t ilen,
428d9e6c9b5SThomas Faber unsigned char output[16] )
429d9e6c9b5SThomas Faber {
430d9e6c9b5SThomas Faber mbedtls_md4_ret( input, ilen, output );
431d9e6c9b5SThomas Faber }
432d9e6c9b5SThomas Faber #endif
433d9e6c9b5SThomas Faber
434c2c66affSColin Finck #if defined(MBEDTLS_SELF_TEST)
435c2c66affSColin Finck
436c2c66affSColin Finck /*
437c2c66affSColin Finck * RFC 1320 test vectors
438c2c66affSColin Finck */
439d9e6c9b5SThomas Faber static const unsigned char md4_test_str[7][81] =
440c2c66affSColin Finck {
441c2c66affSColin Finck { "" },
442c2c66affSColin Finck { "a" },
443c2c66affSColin Finck { "abc" },
444c2c66affSColin Finck { "message digest" },
445c2c66affSColin Finck { "abcdefghijklmnopqrstuvwxyz" },
446c2c66affSColin Finck { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" },
447d9e6c9b5SThomas Faber { "12345678901234567890123456789012345678901234567890123456789012"
448c2c66affSColin Finck "345678901234567890" }
449c2c66affSColin Finck };
450c2c66affSColin Finck
451d9e6c9b5SThomas Faber static const size_t md4_test_strlen[7] =
452d9e6c9b5SThomas Faber {
453d9e6c9b5SThomas Faber 0, 1, 3, 14, 26, 62, 80
454d9e6c9b5SThomas Faber };
455d9e6c9b5SThomas Faber
456c2c66affSColin Finck static const unsigned char md4_test_sum[7][16] =
457c2c66affSColin Finck {
458c2c66affSColin Finck { 0x31, 0xD6, 0xCF, 0xE0, 0xD1, 0x6A, 0xE9, 0x31,
459c2c66affSColin Finck 0xB7, 0x3C, 0x59, 0xD7, 0xE0, 0xC0, 0x89, 0xC0 },
460c2c66affSColin Finck { 0xBD, 0xE5, 0x2C, 0xB3, 0x1D, 0xE3, 0x3E, 0x46,
461c2c66affSColin Finck 0x24, 0x5E, 0x05, 0xFB, 0xDB, 0xD6, 0xFB, 0x24 },
462c2c66affSColin Finck { 0xA4, 0x48, 0x01, 0x7A, 0xAF, 0x21, 0xD8, 0x52,
463c2c66affSColin Finck 0x5F, 0xC1, 0x0A, 0xE8, 0x7A, 0xA6, 0x72, 0x9D },
464c2c66affSColin Finck { 0xD9, 0x13, 0x0A, 0x81, 0x64, 0x54, 0x9F, 0xE8,
465c2c66affSColin Finck 0x18, 0x87, 0x48, 0x06, 0xE1, 0xC7, 0x01, 0x4B },
466c2c66affSColin Finck { 0xD7, 0x9E, 0x1C, 0x30, 0x8A, 0xA5, 0xBB, 0xCD,
467c2c66affSColin Finck 0xEE, 0xA8, 0xED, 0x63, 0xDF, 0x41, 0x2D, 0xA9 },
468c2c66affSColin Finck { 0x04, 0x3F, 0x85, 0x82, 0xF2, 0x41, 0xDB, 0x35,
469c2c66affSColin Finck 0x1C, 0xE6, 0x27, 0xE1, 0x53, 0xE7, 0xF0, 0xE4 },
470c2c66affSColin Finck { 0xE3, 0x3B, 0x4D, 0xDC, 0x9C, 0x38, 0xF2, 0x19,
471c2c66affSColin Finck 0x9C, 0x3E, 0x7B, 0x16, 0x4F, 0xCC, 0x05, 0x36 }
472c2c66affSColin Finck };
473c2c66affSColin Finck
474c2c66affSColin Finck /*
475c2c66affSColin Finck * Checkup routine
476c2c66affSColin Finck */
mbedtls_md4_self_test(int verbose)477c2c66affSColin Finck int mbedtls_md4_self_test( int verbose )
478c2c66affSColin Finck {
479d9e6c9b5SThomas Faber int i, ret = 0;
480c2c66affSColin Finck unsigned char md4sum[16];
481c2c66affSColin Finck
482c2c66affSColin Finck for( i = 0; i < 7; i++ )
483c2c66affSColin Finck {
484c2c66affSColin Finck if( verbose != 0 )
485c2c66affSColin Finck mbedtls_printf( " MD4 test #%d: ", i + 1 );
486c2c66affSColin Finck
487d9e6c9b5SThomas Faber ret = mbedtls_md4_ret( md4_test_str[i], md4_test_strlen[i], md4sum );
488d9e6c9b5SThomas Faber if( ret != 0 )
489d9e6c9b5SThomas Faber goto fail;
490c2c66affSColin Finck
491c2c66affSColin Finck if( memcmp( md4sum, md4_test_sum[i], 16 ) != 0 )
492c2c66affSColin Finck {
493d9e6c9b5SThomas Faber ret = 1;
494d9e6c9b5SThomas Faber goto fail;
495c2c66affSColin Finck }
496c2c66affSColin Finck
497c2c66affSColin Finck if( verbose != 0 )
498c2c66affSColin Finck mbedtls_printf( "passed\n" );
499c2c66affSColin Finck }
500c2c66affSColin Finck
501c2c66affSColin Finck if( verbose != 0 )
502c2c66affSColin Finck mbedtls_printf( "\n" );
503c2c66affSColin Finck
504c2c66affSColin Finck return( 0 );
505d9e6c9b5SThomas Faber
506d9e6c9b5SThomas Faber fail:
507d9e6c9b5SThomas Faber if( verbose != 0 )
508d9e6c9b5SThomas Faber mbedtls_printf( "failed\n" );
509d9e6c9b5SThomas Faber
510d9e6c9b5SThomas Faber return( ret );
511c2c66affSColin Finck }
512c2c66affSColin Finck
513c2c66affSColin Finck #endif /* MBEDTLS_SELF_TEST */
514c2c66affSColin Finck
515c2c66affSColin Finck #endif /* MBEDTLS_MD4_C */
516