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