Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

193 lines
5.3 KiB

  1. // -*- mode: C++; tab-width: 4; indent-tabs-mode: nil -*- (for GNU Emacs)
  2. //
  3. // Copyright (c) 1985-2000 Microsoft Corporation
  4. //
  5. // This file is part of the Microsoft Research IPv6 Network Protocol Stack.
  6. // You should have received a copy of the Microsoft End-User License Agreement
  7. // for this software along with this release; see the file "license.txt".
  8. // If not, please see http://www.research.microsoft.com/msripv6/license.htm,
  9. // or write to Microsoft Research, One Microsoft Way, Redmond, WA 98052-6399.
  10. //
  11. // Abstract:
  12. //
  13. // HMAC (Hashed? Message Authentication Code) wrapper for SHA-1 algorithm.
  14. // This code is based on the algorithm given in RFC 2104, which for HMAC-SHA1
  15. // is SHA-1(Key XOR outer pad, SHA-1(Key XOR inner pad, text)), where the
  16. // inner pad is 64 bytes of 0x36 and the outer pad is 64 bytes of 0x5c.
  17. //
  18. #include <string.h>
  19. #include "oscfg.h"
  20. #include <sha.h>
  21. //* HMAC_SHA1KeyPrep - preprocess raw keying data into directly usuable form.
  22. //
  23. // This routine is called to convert raw keying information into the most
  24. // convienient form for later processing. For SHA-1, we hash keys larger than
  25. // 64 bytes down to 64 bytes. We also perform the XOR operations between the
  26. // key and the inner and outer pads here since they don't change once we have
  27. // the key. Thus we return 128 bytes of data: 64 bytes of the (possibly
  28. // folded) key XOR'd with the inner pad, and 64 bytes of the key XOR'd with
  29. // the outer pad.
  30. //
  31. // REVIEW: Instead of "Temp", we could operate directly "*Key".
  32. //
  33. void
  34. HMAC_SHA1KeyPrep(
  35. uchar *RawKey, // Raw keying information.
  36. uint RawKeySize, // Size of above in bytes.
  37. uchar *Key) // Resulting 128 bytes of preprocessed key info.
  38. {
  39. uchar Temp[128];
  40. uint Loop;
  41. //
  42. // Load raw key into temp storage.
  43. // Constrain size of keying information to 64 bytes.
  44. //
  45. memset(Temp, 0, 64);
  46. if (RawKeySize > 64) {
  47. A_SHA_CTX Context;
  48. //
  49. // Use SHA-1 to hash key down to 20 bytes.
  50. //
  51. A_SHAInit(&Context);
  52. A_SHAUpdate(&Context, RawKey, RawKeySize);
  53. A_SHAFinal(&Context, Temp);
  54. } else
  55. memcpy(Temp, RawKey, RawKeySize);
  56. //
  57. // The first 64 bytes of "Temp" contain our (possibly hashed) key.
  58. // Make a copy of this in the second 64 bytes.
  59. //
  60. memcpy(&Temp[64], Temp, 64);
  61. //
  62. // XOR the first 64 bytes with the inner pad, and the second 64 bytes
  63. // with the outer pad.
  64. //
  65. for (Loop = 0; Loop < 64; Loop++) {
  66. Temp[Loop] ^= 0x36; // Inner Pad.
  67. Temp[Loop + 64] ^= 0x5c; // Outer Pad.
  68. }
  69. //
  70. // Return the result to location designated by our caller.
  71. //
  72. memcpy(Key, Temp, 128);
  73. //
  74. // Zero sensitive information.
  75. // REVIEW: Bother? Or maybe zero the whole thing?
  76. //
  77. memset(Temp, 0, 20);
  78. }
  79. //* HMAC_SHA1Init - prepare to process data.
  80. //
  81. void
  82. HMAC_SHA1Init(
  83. void *GenericContext, // HMAC-SHA1 context maintained across operations.
  84. uchar *Key) // Keying information.
  85. {
  86. A_SHA_CTX *Context = GenericContext;
  87. //
  88. // Start off the inner hash. I.e. "SHA-1(Key XOR inner pad, ...".
  89. //
  90. A_SHAInit(Context);
  91. A_SHAUpdate(Context, Key, 64);
  92. }
  93. //* HMAC_SHA1Op - Process a chunk of data.
  94. //
  95. void
  96. HMAC_SHA1Op(
  97. void *GenericContext, // HMAC-SHA1 context maintained across operations.
  98. uchar *Key, // Keying information.
  99. uchar *Data, // Data to process.
  100. uint Len) // Amount of above in bytes.
  101. {
  102. A_SHA_CTX *Context = GenericContext;
  103. //
  104. // Continue the inner hash. I.e. "SHA-1(..., text)".
  105. //
  106. A_SHAUpdate(Context, Data, Len);
  107. }
  108. //* HMAC_SHA1Final - close off processing current data and return result.
  109. //
  110. // REVIEW: Instead of "Temp", we could operate directly "*Result".
  111. //
  112. void
  113. HMAC_SHA1Final(
  114. void *GenericContext, // HMAC-SHA1 context maintained across operations.
  115. uchar *Key, // Keying information.
  116. uchar *Result) // Where to put result of this process.
  117. {
  118. uchar Temp[20];
  119. A_SHA_CTX *Context = GenericContext;
  120. //
  121. // Finish the inner hash.
  122. //
  123. A_SHAFinal(Context, Temp);
  124. //
  125. // Perform the outer hash. I.e. SHA-1(Key XOR outer pad, ...).
  126. // SHA1Final returns the result directly to our caller.
  127. //
  128. A_SHAInit(Context);
  129. A_SHAUpdate(Context, &Key[64], 64);
  130. A_SHAUpdate(Context, Temp, 20);
  131. A_SHAFinal(Context, Result);
  132. //
  133. // Zero sensitive information.
  134. // REVIEW: Bother?
  135. //
  136. memset(Temp, 0, 20);
  137. }
  138. void
  139. HMAC_SHA1_96Final(
  140. void *GenericContext, // HMAC-SHA1 context maintained across operations.
  141. uchar *Key, // Keying information.
  142. uchar *Result) // Where to put result of this process.
  143. {
  144. uchar Temp[20];
  145. A_SHA_CTX *Context = GenericContext;
  146. //
  147. // Finish the inner hash.
  148. //
  149. A_SHAFinal(Context, Temp);
  150. //
  151. // Perform the outer hash. I.e. SHA-1(Key XOR outer pad, ...).
  152. //
  153. A_SHAInit(Context);
  154. A_SHAUpdate(Context, &Key[64], 64);
  155. A_SHAUpdate(Context, Temp, 20);
  156. A_SHAFinal(Context, Temp);
  157. //
  158. // Truncate the SHA1 20 byte output to 12 bytes.
  159. // The first 12 bytes from the left are stored.
  160. //
  161. memcpy(Result, Temp, 12);
  162. //
  163. // Zero sensitive information.
  164. // REVIEW: Bother?
  165. //
  166. memset(Temp, 0, 20);
  167. }