xref: /reactos/dll/3rdparty/mbedtls/md4.c (revision cbda039f)
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