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