cryptlib  3.4.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros
ctx_hrmd.c
Go to the documentation of this file.
1 /****************************************************************************
2 * *
3 * cryptlib HMAC-RIPEMD-160 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 "ripemd.h"
12 #else
13  #include "crypt.h"
14  #include "context/context.h"
15  #include "crypt/ripemd.h"
16 #endif /* Compiler-specific includes */
17 
18 #ifdef USE_RIPEMD160
19 
20 /* A structure to hold the initial and current MAC state info. Rather than
21  redoing the key processing each time when we're calculating multiple MACs
22  with the same key, we just copy the initial state into the current state */
23 
24 typedef struct {
25  RIPEMD160_CTX macState, initialMacState;
26  } MAC_STATE;
27 
28 #define MAC_STATE_SIZE sizeof( MAC_STATE )
29 
30 /****************************************************************************
31 * *
32 * HMAC-RIPEMD-160 Self-test Routines *
33 * *
34 ****************************************************************************/
35 
36 #ifndef CONFIG_NO_SELFTEST
37 
38 /* Test the HMAC-RIPEMD-160 output against the test vectors given in ???? */
39 
40 static const struct {
41  const char FAR_BSS *key; /* HMAC key */
42  const int keyLength; /* Length of key */
43  const char FAR_BSS *data; /* Data to hash */
44  const int length; /* Length of data */
45  const BYTE digest[ RIPEMD160_DIGEST_LENGTH ]; /* Digest of data */
46  } FAR_BSS hmacValues[] = {
47  /* No known test vectors for this algorithm */
48  { "", 0, NULL, 0, { 0 } }
49  };
50 
51 static int selfTest( void )
52  {
53  const CAPABILITY_INFO *capabilityInfo = getHmacRipemd160Capability();
54  BYTE macState[ MAC_STATE_SIZE + 8 ];
55  int i, status;
56 
57  /* Test HMAC-RIPEMD-160 against the test vectors given in ???? */
58  for( i = 0; hmacValues[ i ].data != NULL; i++ )
59  {
60  status = testMAC( capabilityInfo, macState, hmacValues[ i ].key,
61  hmacValues[ i ].keyLength, hmacValues[ i ].data,
62  hmacValues[ i ].length, hmacValues[ i ].digest );
63  if( cryptStatusError( status ) )
64  return( status );
65  }
66 
67  return( CRYPT_OK );
68  }
69 #else
70  #define selfTest NULL
71 #endif /* !CONFIG_NO_SELFTEST */
72 
73 /****************************************************************************
74 * *
75 * Control Routines *
76 * *
77 ****************************************************************************/
78 
79 /* Return context subtype-specific information */
80 
82 static int getInfo( IN_ENUM( CAPABILITY_INFO ) const CAPABILITY_INFO_TYPE type,
84  OUT void *data,
85  IN_INT_Z const int length )
86  {
87  assert( contextInfoPtr == NULL || \
88  isWritePtr( contextInfoPtr, sizeof( CONTEXT_INFO ) ) );
89  assert( ( length == 0 && isWritePtr( data, sizeof( int ) ) ) || \
90  ( length > 0 && isWritePtr( data, length ) ) );
91 
93 
94  if( type == CAPABILITY_INFO_STATESIZE )
95  {
96  int *valuePtr = ( int * ) data;
97 
98  *valuePtr = MAC_STATE_SIZE;
99 
100  return( CRYPT_OK );
101  }
102 
103  return( getDefaultInfo( type, contextInfoPtr, data, length ) );
104  }
105 
106 /****************************************************************************
107 * *
108 * HMAC-RIPEMD-160 Hash Routines *
109 * *
110 ****************************************************************************/
111 
112 /* Hash data using HMAC-RIPEMD-160 */
113 
114 static int hash( CONTEXT_INFO *contextInfoPtr, BYTE *buffer, int noBytes )
115  {
116  MAC_INFO *macInfo = contextInfoPtr->ctxMAC;
117  RIPEMD160_CTX *ripemdInfo = &( ( MAC_STATE * ) macInfo->macInfo )->macState;
118 
119  /* If the hash state was reset to allow another round of MAC'ing, copy
120  the initial MAC state over into the current MAC state */
121  if( !( contextInfoPtr->flags & CONTEXT_FLAG_HASH_INITED ) )
122  {
123  MAC_STATE *macState = macInfo->macInfo;
124 
125  memcpy( &macState->macState, &macState->initialMacState,
126  sizeof( RIPEMD160_CTX ) );
127  }
128 
129  if( noBytes > 0 )
130  RIPEMD160_Update( ripemdInfo, buffer, noBytes );
131  else
132  {
133  BYTE hashBuffer[ RIPEMD160_CBLOCK + 8 ];
134  BYTE digestBuffer[ RIPEMD160_DIGEST_LENGTH + 8 ];
135  int i;
136 
137  /* Complete the inner hash and extract the digest */
138  RIPEMD160_Final( digestBuffer, ripemdInfo );
139 
140  /* Perform the of the outer hash using the zero-padded key XOR'd
141  with the opad value followed by the digest from the inner hash */
142  memset( hashBuffer, HMAC_OPAD, RIPEMD160_CBLOCK );
143  memcpy( hashBuffer, macInfo->userKey,
144  macInfo->userKeyLength );
145  for( i = 0; i < macInfo->userKeyLength; i++ )
146  hashBuffer[ i ] ^= HMAC_OPAD;
147  RIPEMD160_Init( ripemdInfo );
148  RIPEMD160_Update( ripemdInfo, hashBuffer, RIPEMD160_CBLOCK );
149  memset( hashBuffer, 0, RIPEMD160_CBLOCK );
150  RIPEMD160_Update( ripemdInfo, digestBuffer, RIPEMD160_DIGEST_LENGTH );
151  memset( digestBuffer, 0, RIPEMD160_DIGEST_LENGTH );
152  RIPEMD160_Final( macInfo->mac, ripemdInfo );
153  }
154 
155  return( CRYPT_OK );
156  }
157 
158 /****************************************************************************
159 * *
160 * HMAC-RIPEMD-160 Key Management Routines *
161 * *
162 ****************************************************************************/
163 
164 /* Set up an HMAC-RIPEMD-160 key */
165 
166 static int initKey( CONTEXT_INFO *contextInfoPtr, const void *key,
167  const int keyLength )
168  {
169  MAC_INFO *macInfo = contextInfoPtr->ctxMAC;
170  RIPEMD160_CTX *ripemdInfo = &( ( MAC_STATE * ) macInfo->macInfo )->macState;
171  BYTE hashBuffer[ RIPEMD160_CBLOCK + 8 ];
172  int i;
173 
174  RIPEMD160_Init( ripemdInfo );
175 
176  /* If the key size is larger than tha RIPEMD-160 data size, reduce it to
177  the RIPEMD-160 hash size before processing it (yuck. You're required
178  to do this though) */
179  if( keyLength > RIPEMD160_CBLOCK )
180  {
181  /* Hash the user key down to the hash size (RIPEMD160_Init() has
182  already been called when the context was created) */
183  RIPEMD160_Update( ripemdInfo, ( BYTE * ) key, keyLength );
184  RIPEMD160_Final( macInfo->userKey, ripemdInfo );
186 
187  /* Reset the RIPEMD-160 state */
188  RIPEMD160_Init( ripemdInfo );
189  }
190  else
191  {
192  /* Copy the key to internal storage */
193  if( macInfo->userKey != key )
194  memcpy( macInfo->userKey, key, keyLength );
195  macInfo->userKeyLength = keyLength;
196  }
197 
198  /* Perform the start of the inner hash using the zero-padded key XOR'd
199  with the ipad value */
200  memset( hashBuffer, HMAC_IPAD, RIPEMD160_CBLOCK );
201  memcpy( hashBuffer, macInfo->userKey,
202  macInfo->userKeyLength );
203  for( i = 0; i < macInfo->userKeyLength; i++ )
204  hashBuffer[ i ] ^= HMAC_IPAD;
205  RIPEMD160_Update( ripemdInfo, hashBuffer, RIPEMD160_CBLOCK );
206  memset( hashBuffer, 0, RIPEMD160_CBLOCK );
207  contextInfoPtr->flags |= CONTEXT_FLAG_HASH_INITED;
208 
209  /* Save a copy of the initial state in case it's needed later */
210  memcpy( &( ( MAC_STATE * ) macInfo->macInfo )->initialMacState, ripemdInfo,
211  sizeof( RIPEMD160_CTX ) );
212 
213  return( CRYPT_OK );
214  }
215 
216 /****************************************************************************
217 * *
218 * Capability Access Routines *
219 * *
220 ****************************************************************************/
221 
222 static const CAPABILITY_INFO FAR_BSS capabilityInfo = {
223  CRYPT_ALGO_HMAC_RIPEMD160, bitsToBytes( 160 ), "HMAC-RIPEMD160", 14,
225  selfTest, getInfo, NULL, NULL, initKey, NULL, hash, hash
226  };
227 
229  {
230  return( &capabilityInfo );
231  }
232 
233 #endif /* USE_RIPEMD160 */