mirror of
				https://git.proxmox.com/git/mirror_edk2
				synced 2025-10-27 18:45:25 +00:00 
			
		
		
		
	 e5eed7d364
			
		
	
	
		e5eed7d364
		
	
	
	
	
		
			
			git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10418 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			351 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			351 lines
		
	
	
		
			9.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   Implementation of MD5 algorithm.
 | |
| 
 | |
| Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
 | |
| This program and the accompanying materials
 | |
| are licensed and made available under the terms and conditions of the BSD License
 | |
| which accompanies this distribution.  The full text of the license may be found at
 | |
| http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
| THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
| WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "Md5.h"
 | |
| 
 | |
| CONST UINT32  Md5_Data[][2] = {
 | |
|   { 0, 1 },
 | |
|   { 1, 5 },
 | |
|   { 5, 3 },
 | |
|   { 0, 7 }
 | |
| };
 | |
| 
 | |
| CONST UINT32  Md5_S[][4] = {
 | |
|   { 7, 22, 17, 12 },
 | |
|   { 5, 20, 14, 9 },
 | |
|   { 4, 23, 16 ,11 },
 | |
|   { 6, 21, 15, 10 },
 | |
| };
 | |
| 
 | |
| CONST UINT32  Md5_T[] = {
 | |
|   0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
 | |
|   0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
 | |
|   0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
 | |
|   0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
 | |
|   0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
 | |
|   0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
 | |
|   0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
 | |
|   0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
 | |
|   0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
 | |
|   0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
 | |
|   0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
 | |
|   0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
 | |
|   0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
 | |
|   0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
 | |
|   0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
 | |
|   0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
 | |
| };
 | |
| 
 | |
| CONST UINT8 Md5HashPadding[] =
 | |
| {
 | |
|   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 | |
|   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 
 | |
| };
 | |
| 
 | |
| //
 | |
| // ROTATE_LEFT rotates x left n bits.
 | |
| //
 | |
| #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
 | |
| 
 | |
| #define SA            MedStates[Index2 & 3]
 | |
| #define SB            MedStates[(Index2 + 1) & 3]
 | |
| #define SC            MedStates[(Index2 + 2) & 3]
 | |
| #define SD            MedStates[(Index2 + 3) & 3]
 | |
| 
 | |
| /**
 | |
|   Tf1 is one basic MD5 transform function.
 | |
|   
 | |
|   @param[in]  A      A  32-bit quantity.
 | |
|   @param[in]  B      A  32-bit quantity. 
 | |
|   @param[in]  C      A  32-bit quantity.
 | |
| 
 | |
|   @return             Output was produced as a 32-bit quantity based on the
 | |
|                       three 32-bit input quantity.   
 | |
| **/
 | |
| UINT32 
 | |
| Tf1 (
 | |
|   IN UINT32 A, 
 | |
|   IN UINT32 B, 
 | |
|   IN UINT32 C
 | |
|   )
 | |
| {
 | |
|   return (A & B) | (~A & C);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Tf2 is one basic MD5 transform function.
 | |
|   
 | |
|   @param[in]  A      A  32-bit quantity.
 | |
|   @param[in]  B      A  32-bit quantity. 
 | |
|   @param[in]  C      A  32-bit quantity.
 | |
| 
 | |
|   @return             Output was produced as a 32-bit quantity based on the
 | |
|                       three 32-bit input quantity.   
 | |
| **/
 | |
| UINT32 
 | |
| Tf2 (
 | |
|   IN UINT32 A, 
 | |
|   IN UINT32 B, 
 | |
|   IN UINT32 C
 | |
|   )
 | |
| {
 | |
|   return (A & C) | (B & ~C);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Tf3 is one basic MD5 transform function.
 | |
|   
 | |
|   @param[in]  A      A  32-bit quantity.
 | |
|   @param[in]  B      A  32-bit quantity. 
 | |
|   @param[in]  C      A  32-bit quantity.
 | |
| 
 | |
|   @return             Output was produced as a 32-bit quantity based on the
 | |
|                       three 32-bit input quantity.   
 | |
| **/
 | |
| UINT32 
 | |
| Tf3 (
 | |
|   IN UINT32 A, 
 | |
|   IN UINT32 B, 
 | |
|   IN UINT32 C
 | |
|   )
 | |
| {
 | |
|   return A ^ B ^ C;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Tf4 is one basic MD5 transform function.
 | |
|   
 | |
|   @param[in]  A      A  32-bit quantity.
 | |
|   @param[in]  B      A  32-bit quantity. 
 | |
|   @param[in]  C      A  32-bit quantity.
 | |
| 
 | |
|   @return             Output was produced as a 32-bit quantity based on the
 | |
|                       three 32-bit input quantity.   
 | |
| **/
 | |
| UINT32 
 | |
| Tf4 (
 | |
|   IN UINT32 A, 
 | |
|   IN UINT32 B, 
 | |
|   IN UINT32 C
 | |
|   )
 | |
| {
 | |
|   return B ^ (A | ~C);
 | |
| }
 | |
| 
 | |
| typedef
 | |
| UINT32
 | |
| (*MD5_TRANSFORM_FUNC) (
 | |
|   IN UINT32  A,
 | |
|   IN UINT32  B,
 | |
|   IN UINT32  C
 | |
|   );
 | |
| 
 | |
| CONST MD5_TRANSFORM_FUNC Md5_F[] = {
 | |
|   Tf1,
 | |
|   Tf2,
 | |
|   Tf3,
 | |
|   Tf4
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Perform the MD5 transform on 64 bytes data segment.
 | |
| 
 | |
|   @param[in, out]  Md5Ctx  It includes the data segment for Md5 transform.
 | |
| **/
 | |
| VOID
 | |
| MD5Transform (
 | |
|   IN OUT MD5_CTX  *Md5Ctx
 | |
|   )
 | |
| {
 | |
|   UINT32  Index1;
 | |
|   UINT32  Index2;
 | |
|   UINT32  MedStates[MD5_HASHSIZE >> 2];
 | |
|   UINT32  *Data;
 | |
|   UINT32  IndexD;
 | |
|   UINT32  IndexT;
 | |
| 
 | |
|   Data = (UINT32 *) Md5Ctx->M;
 | |
| 
 | |
|   //
 | |
|   // Copy MD5 states to MedStates
 | |
|   //
 | |
|   CopyMem (MedStates, Md5Ctx->States, MD5_HASHSIZE);
 | |
| 
 | |
|   IndexT = 0;
 | |
|   for (Index1 = 0; Index1 < 4; Index1++) {
 | |
|     IndexD = Md5_Data[Index1][0];
 | |
|     for (Index2 = 16; Index2 > 0; Index2--) {
 | |
|       SA += (*Md5_F[Index1]) (SB, SC, SD) + Data[IndexD] + Md5_T[IndexT];
 | |
|       SA  = ROTATE_LEFT (SA, Md5_S[Index1][Index2 & 3]);
 | |
|       SA += SB;
 | |
| 
 | |
|       IndexD += Md5_Data[Index1][1];
 | |
|       IndexD &= 15;
 | |
| 
 | |
|       IndexT++;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   for (Index1 = 0; Index1 < 4; Index1++) {
 | |
|     Md5Ctx->States[Index1] += MedStates[Index1];
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Copy data segment into the M field of MD5_CTX structure for later transform.
 | |
|   If the length of data segment is larger than 64 bytes, then does the transform
 | |
|   immediately and the generated Md5 code is stored in the States field of MD5_CTX
 | |
|   data struct for later accumulation. 
 | |
|   All of Md5 code generated for the sequential 64-bytes data segaments are be
 | |
|   accumulated in MD5Final() function.
 | |
| 
 | |
|   @param[in, out]  Md5Ctx  The data structure of storing the original data
 | |
|                            segment and the final result.
 | |
|   @param[in]       Data    The data wanted to be transformed.
 | |
|   @param[in]       DataLen The length of data.
 | |
| **/
 | |
| VOID
 | |
| MD5UpdateBlock (
 | |
|   IN OUT MD5_CTX  *Md5Ctx,
 | |
|   IN CONST UINT8  *Data,
 | |
|   IN       UINTN  DataLen
 | |
|   )
 | |
| {
 | |
|   UINTN Limit;
 | |
| 
 | |
|   for (Limit = 64 - Md5Ctx->Count; DataLen >= 64 - Md5Ctx->Count; Limit = 64) {
 | |
|     CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, Limit);
 | |
|     MD5Transform (Md5Ctx);
 | |
|     
 | |
|     Md5Ctx->Count = 0;
 | |
|     Data         += Limit;
 | |
|     DataLen      -= Limit;
 | |
|   }
 | |
| 
 | |
|   CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, DataLen);
 | |
|   Md5Ctx->Count += DataLen;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Initialize four 32-bits chaining variables and use them to do the Md5 transform.
 | |
| 
 | |
|   @param[out]  Md5Ctx The data structure of Md5.
 | |
| 
 | |
|   @retval EFI_SUCCESS Initialization is ok.
 | |
| **/
 | |
| EFI_STATUS
 | |
| MD5Init (
 | |
|   OUT MD5_CTX  *Md5Ctx
 | |
|   )
 | |
| {
 | |
|   ZeroMem (Md5Ctx, sizeof (*Md5Ctx));
 | |
| 
 | |
|   //
 | |
|   // Set magic initialization constants.
 | |
|   //
 | |
|   Md5Ctx->States[0] = 0x67452301;
 | |
|   Md5Ctx->States[1] = 0xefcdab89;
 | |
|   Md5Ctx->States[2] = 0x98badcfe;
 | |
|   Md5Ctx->States[3] = 0x10325476;  
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   the external interface of Md5 algorithm
 | |
| 
 | |
|   @param[in, out]  Md5Ctx  The data structure of storing the original data
 | |
|                            segment and the final result.
 | |
|   @param[in]       Data    The data wanted to be transformed.
 | |
|   @param[in]       DataLen The length of data.
 | |
| 
 | |
|   @retval EFI_SUCCESS The transform is ok.
 | |
|   @retval Others      Other errors as indicated.
 | |
| **/
 | |
| EFI_STATUS
 | |
| MD5Update (
 | |
|   IN  OUT MD5_CTX  *Md5Ctx,
 | |
|   IN  VOID         *Data,
 | |
|   IN  UINTN        DataLen
 | |
|   )
 | |
| {
 | |
|   if (EFI_ERROR (Md5Ctx->Status)) {
 | |
|     return Md5Ctx->Status;
 | |
|   }
 | |
| 
 | |
|   MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) Data, DataLen);
 | |
|   Md5Ctx->Length += DataLen;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Accumulate the MD5 value of every data segment and generate the finial
 | |
|   result according to MD5 algorithm.
 | |
| 
 | |
|   @param[in, out]   Md5Ctx  The data structure of storing the original data
 | |
|                             segment and the final result.
 | |
|   @param[out]      HashVal  The final 128-bits output.
 | |
| 
 | |
|   @retval EFI_SUCCESS  The transform is ok.
 | |
|   @retval Others       Other errors as indicated.
 | |
| **/
 | |
| EFI_STATUS
 | |
| MD5Final (
 | |
|   IN  OUT MD5_CTX  *Md5Ctx,
 | |
|   OUT UINT8        *HashVal
 | |
|   )
 | |
| {
 | |
|   UINTN PadLength;
 | |
| 
 | |
|   if (Md5Ctx->Status == EFI_ALREADY_STARTED) {
 | |
|     //
 | |
|     // Store Hashed value & Zeroize sensitive context information.
 | |
|     //
 | |
|     CopyMem (HashVal, (UINT8 *) Md5Ctx->States, MD5_HASHSIZE);
 | |
|     ZeroMem ((UINT8 *)Md5Ctx, sizeof (*Md5Ctx));
 | |
|     
 | |
|     return EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (EFI_ERROR (Md5Ctx->Status)) {
 | |
|     return Md5Ctx->Status;
 | |
|   }
 | |
| 
 | |
|   PadLength  = Md5Ctx->Count >= 56 ? 120 : 56;
 | |
|   PadLength -= Md5Ctx->Count;
 | |
|   MD5UpdateBlock (Md5Ctx, Md5HashPadding, PadLength);
 | |
|   Md5Ctx->Length = LShiftU64 (Md5Ctx->Length, 3);
 | |
|   MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) &Md5Ctx->Length, 8);
 | |
| 
 | |
|   ZeroMem (Md5Ctx->M, sizeof (Md5Ctx->M));
 | |
|   Md5Ctx->Length  = 0;
 | |
|   Md5Ctx->Status  = EFI_ALREADY_STARTED;
 | |
|   return MD5Final (Md5Ctx, HashVal);
 | |
| }
 | |
| 
 |