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 107 void mbedtls_md2_init( mbedtls_md2_context *ctx ) 108 { 109 memset( ctx, 0, sizeof( mbedtls_md2_context ) ); 110 } 111 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 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 */ 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) 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) 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) 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 */ 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) 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 */ 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) 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 */ 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) 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 */ 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