5 Author: Pekka Riikonen <priikone@poseidon.pspt.fi>
7 Copyright (C) 1997 - 2000 Pekka Riikonen
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
23 * Revision 1.2 2000/07/05 06:08:43 priikone
24 * Global cosmetic change.
26 * Revision 1.1.1.1 2000/06/27 11:36:55 priikone
27 * Imported from internal CVS/Added Log headers.
32 #include "silcincludes.h"
34 /* Allocates a new SilcHmac object. First argument is the hash function
35 object to tell the hmac which hash function should be used when creating
36 HMAC's. The new SilcHmac object is returned to new_hmac argument. */
38 int silc_hmac_alloc(SilcHash hash, SilcHmac *new_hmac)
40 SILC_LOG_DEBUG(("Allocating new hmac object"));
42 *new_hmac = silc_calloc(1, sizeof(**new_hmac));
43 (*new_hmac)->hash = hash;
44 (*new_hmac)->set_key = silc_hmac_set_key;
45 (*new_hmac)->make_hmac = silc_hmac_make;
46 (*new_hmac)->make_hmac_with_key = silc_hmac_make_with_key;
47 (*new_hmac)->make_hmac_truncated = silc_hmac_make_truncated;
52 /* Free's the SilcHmac object. */
54 void silc_hmac_free(SilcHmac hmac)
60 /* Creates the HMAC. The created keyed hash value is returned to
61 return_hash argument. */
63 void silc_hmac_make_internal(SilcHmac hmac, unsigned char *data,
64 unsigned int data_len, unsigned char *key,
65 unsigned int key_len, unsigned char *return_hash)
67 SilcHash hash = hmac->hash;
68 unsigned char inner_pad[hash->hash->block_len + 1];
69 unsigned char outer_pad[hash->hash->block_len + 1];
70 unsigned char hvalue[hash->hash->hash_len];
74 SILC_LOG_DEBUG(("Making HMAC for message"));
76 hash_context = silc_calloc(1, hash->hash->context_len());
78 memset(inner_pad, 0, sizeof(inner_pad));
79 memset(outer_pad, 0, sizeof(outer_pad));
81 /* If the key length is more than block size of the hash function, the
83 if (key_len > hash->hash->block_len) {
84 hash->make_hash(hash, key, key_len, hvalue);
86 key_len = hash->hash->hash_len;
89 /* Copy the key into the pads */
90 memcpy(inner_pad, key, key_len);
91 memcpy(outer_pad, key, key_len);
93 /* XOR the key with pads */
94 for (i = 0; i < hash->hash->block_len; i++) {
99 /* Do the HMAC transform (too bad I can't do make_hash directly, sigh) */
100 hash->hash->init(hash_context);
101 hash->hash->update(hash_context, inner_pad, hash->hash->block_len);
102 hash->hash->update(hash_context, data, data_len);
103 hash->hash->final(hash_context, return_hash);
104 hash->hash->init(hash_context);
105 hash->hash->update(hash_context, outer_pad, hash->hash->block_len);
106 hash->hash->update(hash_context, return_hash, hash->hash->hash_len);
107 hash->hash->final(hash_context, return_hash);
110 /* Create the HMAC. This is thee make_hmac function pointer. This
111 uses the internal key set with silc_hmac_set_key. */
113 void silc_hmac_make(SilcHmac hmac, unsigned char *data,
114 unsigned int data_len, unsigned char *return_hash)
116 silc_hmac_make_internal(hmac, data, data_len, hmac->key,
117 hmac->key_len, return_hash);
120 /* Creates the HMAC just as above except that the hash value is truncated
121 to the truncated_len sent as argument. NOTE: One should not truncate to
122 less than half of the length of original hash value. However, this
123 routine allows these dangerous truncations. */
125 void silc_hmac_make_truncated(SilcHmac hmac, unsigned char *data,
126 unsigned int data_len,
127 unsigned int truncated_len,
128 unsigned char *return_hash)
130 unsigned char hvalue[hmac->hash->hash->hash_len];
132 silc_hmac_make_internal(hmac, data, data_len,
133 hmac->key, hmac->key_len, hvalue);
134 memcpy(return_hash, hvalue, truncated_len);
135 memset(hvalue, 0, sizeof(hvalue));
138 /* Creates HMAC just as above except that this doesn't use the internal
139 key. The key is sent as argument to the function. */
141 void silc_hmac_make_with_key(SilcHmac hmac, unsigned char *data,
142 unsigned int data_len,
143 unsigned char *key, unsigned int key_len,
144 unsigned char *return_hash)
146 silc_hmac_make_internal(hmac, data, data_len, key, key_len, return_hash);
149 /* Sets the HMAC key used in the HMAC creation */
151 void silc_hmac_set_key(SilcHmac hmac, const unsigned char *key,
152 unsigned int key_len)
154 hmac->key = silc_calloc(key_len, sizeof(unsigned char));
155 memcpy(hmac->key, key, key_len);