- SilcHash hash = hmac->hash;
- unsigned char inner_pad[hash->hash->block_len + 1];
- unsigned char outer_pad[hash->hash->block_len + 1];
- unsigned char hvalue[hash->hash->hash_len];
- unsigned char mac[128];
- void *hash_context;
- int i;
-
- SILC_LOG_DEBUG(("Making HMAC for message"));
-
- hash_context = silc_calloc(1, hash->hash->context_len());
-
- memset(inner_pad, 0, sizeof(inner_pad));
- memset(outer_pad, 0, sizeof(outer_pad));
-
- /* If the key length is more than block size of the hash function, the
- key is hashed. */
- if (key_len > hash->hash->block_len) {
- silc_hash_make(hash, key, key_len, hvalue);
- key = hvalue;
- key_len = hash->hash->hash_len;
- }
-
- /* Copy the key into the pads */
- memcpy(inner_pad, key, key_len);
- memcpy(outer_pad, key, key_len);
-
- /* XOR the key with pads */
- for (i = 0; i < hash->hash->block_len; i++) {
- inner_pad[i] ^= 0x36;
- outer_pad[i] ^= 0x5c;
- }
-
- /* Do the HMAC transform (too bad I can't do make_hash directly, sigh) */
- hash->hash->init(hash_context);
- hash->hash->update(hash_context, inner_pad, hash->hash->block_len);
- hash->hash->update(hash_context, data, data_len);
- hash->hash->final(hash_context, mac);
- hash->hash->init(hash_context);
- hash->hash->update(hash_context, outer_pad, hash->hash->block_len);
- hash->hash->update(hash_context, mac, hash->hash->hash_len);
- hash->hash->final(hash_context, mac);
- memcpy(return_hash, mac, hmac->hmac->len);
- memset(mac, 0, sizeof(mac));
- silc_free(hash_context);