Home | History | Annotate | Download | only in IScsiDxe
      1 /** @file
      2   Implementation of MD5 algorithm.
      3 
      4 Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "Md5.h"
     16 
     17 CONST UINT32  Md5_Data[][2] = {
     18   { 0, 1 },
     19   { 1, 5 },
     20   { 5, 3 },
     21   { 0, 7 }
     22 };
     23 
     24 CONST UINT32  Md5_S[][4] = {
     25   { 7, 22, 17, 12 },
     26   { 5, 20, 14, 9 },
     27   { 4, 23, 16 ,11 },
     28   { 6, 21, 15, 10 },
     29 };
     30 
     31 CONST UINT32  Md5_T[] = {
     32   0xD76AA478, 0xE8C7B756, 0x242070DB, 0xC1BDCEEE,
     33   0xF57C0FAF, 0x4787C62A, 0xA8304613, 0xFD469501,
     34   0x698098D8, 0x8B44F7AF, 0xFFFF5BB1, 0x895CD7BE,
     35   0x6B901122, 0xFD987193, 0xA679438E, 0x49B40821,
     36   0xF61E2562, 0xC040B340, 0x265E5A51, 0xE9B6C7AA,
     37   0xD62F105D, 0x02441453, 0xD8A1E681, 0xE7D3FBC8,
     38   0x21E1CDE6, 0xC33707D6, 0xF4D50D87, 0x455A14ED,
     39   0xA9E3E905, 0xFCEFA3F8, 0x676F02D9, 0x8D2A4C8A,
     40   0xFFFA3942, 0x8771F681, 0x6D9D6122, 0xFDE5380C,
     41   0xA4BEEA44, 0x4BDECFA9, 0xF6BB4B60, 0xBEBFBC70,
     42   0x289B7EC6, 0xEAA127FA, 0xD4EF3085, 0x04881D05,
     43   0xD9D4D039, 0xE6DB99E5, 0x1FA27CF8, 0xC4AC5665,
     44   0xF4292244, 0x432AFF97, 0xAB9423A7, 0xFC93A039,
     45   0x655B59C3, 0x8F0CCC92, 0xFFEFF47D, 0x85845DD1,
     46   0x6FA87E4F, 0xFE2CE6E0, 0xA3014314, 0x4E0811A1,
     47   0xF7537E82, 0xBD3AF235, 0x2AD7D2BB, 0xEB86D391
     48 };
     49 
     50 CONST UINT8 Md5HashPadding[] =
     51 {
     52   0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     53   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     54   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     55   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     56   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     57   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     58   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     59   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     60   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     61   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     62   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     63   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     64   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     65   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     66   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
     67   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
     68 };
     69 
     70 //
     71 // ROTATE_LEFT rotates x left n bits.
     72 //
     73 #define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
     74 
     75 #define SA            MedStates[Index2 & 3]
     76 #define SB            MedStates[(Index2 + 1) & 3]
     77 #define SC            MedStates[(Index2 + 2) & 3]
     78 #define SD            MedStates[(Index2 + 3) & 3]
     79 
     80 /**
     81   Tf1 is one basic MD5 transform function.
     82 
     83   @param[in]  A      A  32-bit quantity.
     84   @param[in]  B      A  32-bit quantity.
     85   @param[in]  C      A  32-bit quantity.
     86 
     87   @return             Output was produced as a 32-bit quantity based on the
     88                       three 32-bit input quantity.
     89 **/
     90 UINT32
     91 Tf1 (
     92   IN UINT32 A,
     93   IN UINT32 B,
     94   IN UINT32 C
     95   )
     96 {
     97   return (A & B) | (~A & C);
     98 }
     99 
    100 /**
    101   Tf2 is one basic MD5 transform function.
    102 
    103   @param[in]  A      A  32-bit quantity.
    104   @param[in]  B      A  32-bit quantity.
    105   @param[in]  C      A  32-bit quantity.
    106 
    107   @return             Output was produced as a 32-bit quantity based on the
    108                       three 32-bit input quantity.
    109 **/
    110 UINT32
    111 Tf2 (
    112   IN UINT32 A,
    113   IN UINT32 B,
    114   IN UINT32 C
    115   )
    116 {
    117   return (A & C) | (B & ~C);
    118 }
    119 
    120 /**
    121   Tf3 is one basic MD5 transform function.
    122 
    123   @param[in]  A      A  32-bit quantity.
    124   @param[in]  B      A  32-bit quantity.
    125   @param[in]  C      A  32-bit quantity.
    126 
    127   @return             Output was produced as a 32-bit quantity based on the
    128                       three 32-bit input quantity.
    129 **/
    130 UINT32
    131 Tf3 (
    132   IN UINT32 A,
    133   IN UINT32 B,
    134   IN UINT32 C
    135   )
    136 {
    137   return A ^ B ^ C;
    138 }
    139 
    140 /**
    141   Tf4 is one basic MD5 transform function.
    142 
    143   @param[in]  A      A  32-bit quantity.
    144   @param[in]  B      A  32-bit quantity.
    145   @param[in]  C      A  32-bit quantity.
    146 
    147   @return             Output was produced as a 32-bit quantity based on the
    148                       three 32-bit input quantity.
    149 **/
    150 UINT32
    151 Tf4 (
    152   IN UINT32 A,
    153   IN UINT32 B,
    154   IN UINT32 C
    155   )
    156 {
    157   return B ^ (A | ~C);
    158 }
    159 
    160 typedef
    161 UINT32
    162 (*MD5_TRANSFORM_FUNC) (
    163   IN UINT32  A,
    164   IN UINT32  B,
    165   IN UINT32  C
    166   );
    167 
    168 CONST MD5_TRANSFORM_FUNC Md5_F[] = {
    169   Tf1,
    170   Tf2,
    171   Tf3,
    172   Tf4
    173 };
    174 
    175 /**
    176   Perform the MD5 transform on 64 bytes data segment.
    177 
    178   @param[in, out]  Md5Ctx  It includes the data segment for Md5 transform.
    179 **/
    180 VOID
    181 MD5Transform (
    182   IN OUT MD5_CTX  *Md5Ctx
    183   )
    184 {
    185   UINT32  Index1;
    186   UINT32  Index2;
    187   UINT32  MedStates[MD5_HASHSIZE >> 2];
    188   UINT32  *Data;
    189   UINT32  IndexD;
    190   UINT32  IndexT;
    191 
    192   Data = (UINT32 *) Md5Ctx->M;
    193 
    194   //
    195   // Copy MD5 states to MedStates
    196   //
    197   CopyMem (MedStates, Md5Ctx->States, MD5_HASHSIZE);
    198 
    199   IndexT = 0;
    200   for (Index1 = 0; Index1 < 4; Index1++) {
    201     IndexD = Md5_Data[Index1][0];
    202     for (Index2 = 16; Index2 > 0; Index2--) {
    203       SA += (*Md5_F[Index1]) (SB, SC, SD) + Data[IndexD] + Md5_T[IndexT];
    204       SA  = ROTATE_LEFT (SA, Md5_S[Index1][Index2 & 3]);
    205       SA += SB;
    206 
    207       IndexD += Md5_Data[Index1][1];
    208       IndexD &= 15;
    209 
    210       IndexT++;
    211     }
    212   }
    213 
    214   for (Index1 = 0; Index1 < 4; Index1++) {
    215     Md5Ctx->States[Index1] += MedStates[Index1];
    216   }
    217 }
    218 
    219 /**
    220   Copy data segment into the M field of MD5_CTX structure for later transform.
    221   If the length of data segment is larger than 64 bytes, then does the transform
    222   immediately and the generated Md5 code is stored in the States field of MD5_CTX
    223   data struct for later accumulation.
    224   All of Md5 code generated for the sequential 64-bytes data segaments are be
    225   accumulated in MD5Final() function.
    226 
    227   @param[in, out]  Md5Ctx  The data structure of storing the original data
    228                            segment and the final result.
    229   @param[in]       Data    The data wanted to be transformed.
    230   @param[in]       DataLen The length of data.
    231 **/
    232 VOID
    233 MD5UpdateBlock (
    234   IN OUT MD5_CTX  *Md5Ctx,
    235   IN CONST UINT8  *Data,
    236   IN       UINTN  DataLen
    237   )
    238 {
    239   UINTN Limit;
    240 
    241   for (Limit = 64 - Md5Ctx->Count; DataLen >= 64 - Md5Ctx->Count; Limit = 64) {
    242     CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, Limit);
    243     MD5Transform (Md5Ctx);
    244 
    245     Md5Ctx->Count = 0;
    246     Data         += Limit;
    247     DataLen      -= Limit;
    248   }
    249 
    250   CopyMem (Md5Ctx->M + Md5Ctx->Count, (VOID *)Data, DataLen);
    251   Md5Ctx->Count += DataLen;
    252 }
    253 
    254 /**
    255   Initialize four 32-bits chaining variables and use them to do the Md5 transform.
    256 
    257   @param[out]  Md5Ctx The data structure of Md5.
    258 
    259   @retval EFI_SUCCESS Initialization is ok.
    260 **/
    261 EFI_STATUS
    262 MD5Init (
    263   OUT MD5_CTX  *Md5Ctx
    264   )
    265 {
    266   ZeroMem (Md5Ctx, sizeof (*Md5Ctx));
    267 
    268   //
    269   // Set magic initialization constants.
    270   //
    271   Md5Ctx->States[0] = 0x67452301;
    272   Md5Ctx->States[1] = 0xefcdab89;
    273   Md5Ctx->States[2] = 0x98badcfe;
    274   Md5Ctx->States[3] = 0x10325476;
    275 
    276   return EFI_SUCCESS;
    277 }
    278 
    279 /**
    280   the external interface of Md5 algorithm
    281 
    282   @param[in, out]  Md5Ctx  The data structure of storing the original data
    283                            segment and the final result.
    284   @param[in]       Data    The data wanted to be transformed.
    285   @param[in]       DataLen The length of data.
    286 
    287   @retval EFI_SUCCESS The transform is ok.
    288   @retval Others      Other errors as indicated.
    289 **/
    290 EFI_STATUS
    291 MD5Update (
    292   IN  OUT MD5_CTX  *Md5Ctx,
    293   IN  VOID         *Data,
    294   IN  UINTN        DataLen
    295   )
    296 {
    297   if (EFI_ERROR (Md5Ctx->Status)) {
    298     return Md5Ctx->Status;
    299   }
    300 
    301   MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) Data, DataLen);
    302   Md5Ctx->Length += DataLen;
    303   return EFI_SUCCESS;
    304 }
    305 
    306 /**
    307   Accumulate the MD5 value of every data segment and generate the finial
    308   result according to MD5 algorithm.
    309 
    310   @param[in, out]   Md5Ctx  The data structure of storing the original data
    311                             segment and the final result.
    312   @param[out]      HashVal  The final 128-bits output.
    313 
    314   @retval EFI_SUCCESS  The transform is ok.
    315   @retval Others       Other errors as indicated.
    316 **/
    317 EFI_STATUS
    318 MD5Final (
    319   IN  OUT MD5_CTX  *Md5Ctx,
    320   OUT UINT8        *HashVal
    321   )
    322 {
    323   UINTN PadLength;
    324 
    325   if (Md5Ctx->Status == EFI_ALREADY_STARTED) {
    326     //
    327     // Store Hashed value & Zeroize sensitive context information.
    328     //
    329     CopyMem (HashVal, (UINT8 *) Md5Ctx->States, MD5_HASHSIZE);
    330     ZeroMem ((UINT8 *)Md5Ctx, sizeof (*Md5Ctx));
    331 
    332     return EFI_SUCCESS;
    333   }
    334 
    335   if (EFI_ERROR (Md5Ctx->Status)) {
    336     return Md5Ctx->Status;
    337   }
    338 
    339   PadLength  = Md5Ctx->Count >= 56 ? 120 : 56;
    340   PadLength -= Md5Ctx->Count;
    341   MD5UpdateBlock (Md5Ctx, Md5HashPadding, PadLength);
    342   Md5Ctx->Length = LShiftU64 (Md5Ctx->Length, 3);
    343   MD5UpdateBlock (Md5Ctx, (CONST UINT8 *) &Md5Ctx->Length, 8);
    344 
    345   ZeroMem (Md5Ctx->M, sizeof (Md5Ctx->M));
    346   Md5Ctx->Length  = 0;
    347   Md5Ctx->Status  = EFI_ALREADY_STARTED;
    348   return MD5Final (Md5Ctx, HashVal);
    349 }
    350 
    351