cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_hsha.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib HMAC-SHA Hash Routines *
4 * Copyright Peter Gutmann 1997-2005 *
5 * *
6 ****************************************************************************/
7 
8 #if defined( INC_ALL )
9  #include "crypt.h"
10  #include "context.h"
11  #include "sha.h"
12 #else
13  #include "crypt.h"
14  #include "context/context.h"
15  #include "crypt/sha.h"
16 #endif /* Compiler-specific includes */
17 
18 /* A structure to hold the initial and current MAC state info. Rather than
19  redoing the key processing each time when we're calculating multiple MACs
20  with the same key, we just copy the initial state into the current state */
21 
22 typedef struct {
23  SHA_CTX macState, initialMacState;
24  } MAC_STATE;
25 
26 #define MAC_STATE_SIZE sizeof( MAC_STATE )
27 
28 /****************************************************************************
29 * *
30 * HMAC-SHA Self-test Routines *
31 * *
32 ****************************************************************************/
33 
34 #ifndef CONFIG_NO_SELFTEST
35 
36 /* Test the HMAC-SHA output against the test vectors given in RFC ???? */
37 
38 static const struct {
39  const char FAR_BSS *key; /* HMAC key */
40  const int keyLength; /* Length of key */
41  const char FAR_BSS *data; /* Data to hash */
42  const int length; /* Length of data */
43  const BYTE digest[ SHA_DIGEST_LENGTH ]; /* Digest of data */
44  } FAR_BSS hmacValues[] = {
45  { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B"
46  "\x0B\x0B\x0B\x0B", 20,
47  "Hi There", 8,
48  { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64,
49  0xE2, 0x8B, 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E,
50  0xF1, 0x46, 0xBE, 0x00 } },
51  { "Jefe", 4,
52  "what do ya want for nothing?", 28,
53  { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2,
54  0xD2, 0x74, 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C,
55  0x25, 0x9A, 0x7C, 0x79 } },
56  { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
57  "\xAA\xAA\xAA\xAA", 20,
58  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
59  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
60  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
61  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
62  "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD", 50,
63  { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD,
64  0x91, 0xA3, 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F,
65  0x63, 0xF1, 0x75, 0xD3 } },
66  { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10"
67  "\x11\x12\x13\x14\x15\x16\x17\x18\x19", 25,
68  "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
69  "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
70  "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
71  "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD"
72  "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD", 50,
73  { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6,
74  0xBC, 0x84, 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C,
75  0x2D, 0x72, 0x35, 0xDA } },
76 #if 0 /* Should be truncated to 96 bits - we don't do truncation */
77  { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C"
78  "\x0C\x0C\x0C\x0C", 20,
79  "Test With Truncation", 20,
80  { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F,
81  0xE7, 0xF2, 0x7B, 0xE1, 0xD5, 0x8B, 0xB9, 0x32,
82  0x4A, 0x9A, 0x5A, 0x04 } },
83 #endif /* 0 */
84  { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
85  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
86  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
87  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
88  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
89  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
90  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
91  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", 80,
92  "Test Using Larger Than Block-Size Key - Hash Key First", 54,
93  { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E,
94  0x95, 0x70, 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55,
95  0xED, 0x40, 0x21, 0x12 } },
96  { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
97  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
98  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
99  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
100  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
101  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
102  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
103  "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA", 80,
104  "Test Using Larger Than Block-Size Key and Larger Than One "
105  "Block-Size Data", 73,
106  { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78,
107  0x6D, 0x6B, 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08,
108  0xBB, 0xFF, 0x1A, 0x91 } },
109  { "", 0, NULL, 0, { 0 } }
110  };
111 
112 static int selfTest( void )
113  {
114  const CAPABILITY_INFO *capabilityInfo = getHmacSHA1Capability();
115  BYTE macState[ MAC_STATE_SIZE + 8 ];
116  int i, status;
117 
118  /* Test HMAC-SHA against the test vectors given in RFC ???? */
119  for( i = 0; hmacValues[ i ].data != NULL; i++ )
120  {
121  status = testMAC( capabilityInfo, macState, hmacValues[ i ].key,
122  hmacValues[ i ].keyLength, hmacValues[ i ].data,
123  hmacValues[ i ].length, hmacValues[ i ].digest );
124  if( cryptStatusError( status ) )
125  return( status );
126  }
127 
128  return( CRYPT_OK );
129  }
130 #else
131  #define selfTest NULL
132 #endif /* !CONFIG_NO_SELFTEST */
133 
134 /****************************************************************************
135 * *
136 * Control Routines *
137 * *
138 ****************************************************************************/
139 
140 /* Return context subtype-specific information */
141 
143 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
145  OUT void *data,
146  IN_INT_Z const int length )
147  {
148  assert( contextInfoPtr == NULL || \
149  isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
150  assert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \
151  ( length > 0 && isWritePtr( data, length ) ) );
152 
154 
155  if( type == CAPABILITY_INFO_STATESIZE )
156  {
157  int *valuePtr = ( int * ) data;
158 
159  *valuePtr = MAC_STATE_SIZE;
160 
161  return( CRYPT_OK );
162  }
163 
164  return( getDefaultInfo( type, contextInfoPtr, data, length ) );
165  }
166 
167 /****************************************************************************
168 * *
169 * HMAC-SHA Hash Routines *
170 * *
171 ****************************************************************************/
172 
173 /* Hash data using HMAC-SHA */
174 
175 static int hash( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
176  {
177  MAC_INFO *macInfo = contextInfoPtr->ctxMAC;
178  SHA_CTX *shaInfo = &( ( MAC_STATE * ) macInfo->macInfo )->macState;
179 
180  /* If the hash state was reset to allow another round of MAC'ing, copy
181  the initial MAC state over into the current MAC state */
182  if( !( contextInfoPtr->flags & CONTEXT_FLAG_HASH_INITED ) )
183  {
184  MAC_STATE *macState = macInfo->macInfo;
185 
186  memcpy( &macState->macState, &macState->initialMacState,
187  sizeof( SHA_CTX ) );
188  }
189 
190  if( noBytes > 0 )
191  SHA1_Update( shaInfo, buffer, noBytes );
192  else
193  {
194  BYTE hashBuffer[ SHA_CBLOCK + 8 ];
195  BYTE digestBuffer[ SHA_DIGEST_LENGTH + 8 ];
196  int i;
197 
198  /* Complete the inner hash and extract the digest */
199  SHA1_Final( digestBuffer, shaInfo );
200 
201  /* Perform the of the outer hash using the zero-padded key XOR'd
202  with the opad value followed by the digest from the inner hash */
203  memset( hashBuffer, HMAC_OPAD, SHA_CBLOCK );
204  memcpy( hashBuffer, macInfo->userKey,
205  macInfo->userKeyLength );
206  for( i = 0; i < macInfo->userKeyLength; i++ )
207  hashBuffer[ i ] ^= HMAC_OPAD;
208  SHA1_Init( shaInfo );
209  SHA1_Update( shaInfo, hashBuffer, SHA_CBLOCK );
210  memset( hashBuffer, 0, SHA_CBLOCK );
211  SHA1_Update( shaInfo, digestBuffer, SHA_DIGEST_LENGTH );
212  memset( digestBuffer, 0, SHA_DIGEST_LENGTH );
213  SHA1_Final( macInfo->mac, shaInfo );
214  }
215 
216  return( CRYPT_OK );
217  }
218 
219 /****************************************************************************
220 * *
221 * HMAC-SHA Key Management Routines *
222 * *
223 ****************************************************************************/
224 
225 /* Set up an HMAC-SHA key */
226 
227 static int initKey( CONTEXT_INFO *contextInfoPtr, const void *key,
228  const int keyLength )
229  {
230  MAC_INFO *macInfo = contextInfoPtr->ctxMAC;
231  SHA_CTX *shaInfo = &( ( MAC_STATE * ) macInfo->macInfo )->macState;
232  BYTE hashBuffer[ SHA_CBLOCK + 8 ];
233  int i;
234 
235  SHA1_Init( shaInfo );
236 
237  /* If the key size is larger than tha SHA data size, reduce it to the
238  SHA hash size before processing it (yuck. You're required to do this
239  though) */
240  if( keyLength > SHA_CBLOCK )
241  {
242  /* Hash the user key down to the hash size (SHA1_Init() has already
243  been called when the context was created) and use the hashed form
244  of the key */
245  SHA1_Update( shaInfo, ( void * ) key, keyLength );
246  SHA1_Final( macInfo->userKey, shaInfo );
247  macInfo->userKeyLength = SHA_DIGEST_LENGTH;
248 
249  /* Reset the SHA state */
250  SHA1_Init( shaInfo );
251  }
252  else
253  {
254  /* Copy the key to internal storage */
255  if( macInfo->userKey != key )
256  memcpy( macInfo->userKey, key, keyLength );
257  macInfo->userKeyLength = keyLength;
258  }
259 
260  /* Perform the start of the inner hash using the zero-padded key XOR'd
261  with the ipad value */
262  memset( hashBuffer, HMAC_IPAD, SHA_CBLOCK );
263  memcpy( hashBuffer, macInfo->userKey,
264  macInfo->userKeyLength );
265  for( i = 0; i < macInfo->userKeyLength; i++ )
266  hashBuffer[ i ] ^= HMAC_IPAD;
267  SHA1_Update( shaInfo, hashBuffer, SHA_CBLOCK );
268  memset( hashBuffer, 0, SHA_CBLOCK );
269  contextInfoPtr->flags |= CONTEXT_FLAG_HASH_INITED;
270 
271  /* Save a copy of the initial state in case it's needed later */
272  memcpy( &( ( MAC_STATE * ) macInfo->macInfo )->initialMacState, shaInfo,
273  sizeof( SHA_CTX ) );
274 
275  return( CRYPT_OK );
276  }
277 
278 /****************************************************************************
279 * *
280 * Capability Access Routines *
281 * *
282 ****************************************************************************/
283 
284 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
285  CRYPT_ALGO_HMAC_SHA1, bitsToBytes( 160 ), "HMAC-SHA", 8,
287  selfTest, getInfo, NULL, NULL, initKey, NULL, hash, hash
288  };
289 
291  {
292  return( &capabilityInfo );
293  }