4 * @brief Implementation of hmac_t.
8 * Copyright (C) 2005 Jan Hutter, Martin Willi
9 * Hochschule fuer Technik Rapperswil
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General hmac License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 * This program is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
18 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General hmac License
25 #include <utils/allocator.h>
28 typedef struct private_hmac_t private_hmac_t
;
31 * Private data of an hmac_t object.
33 struct private_hmac_t
{
40 * block size, as in RFC
50 * previously xor'ed key using opad
54 * previously xor'ed key using ipad
60 * Implementation of hmac_t.get_mac.
62 static status_t
get_mac(private_hmac_t
*this, chunk_t data
, u_int8_t
*out
)
64 /* H(K XOR opad, H(K XOR ipad, text))
66 * if out is NULL, we append text to the inner hash.
67 * else, we complete the inner and do the outer.
71 u_int8_t buffer
[this->h
->get_block_size(this->h
)];
76 /* append data to inner */
77 this->h
->get_hash(this->h
, data
, NULL
);
81 /* append and do outer hash */
83 inner
.len
= this->h
->get_block_size(this->h
);
86 this->h
->get_hash(this->h
, data
, buffer
);
89 this->h
->get_hash(this->h
, this->opaded_key
, NULL
);
90 this->h
->get_hash(this->h
, inner
, out
);
92 /* reinit for next call */
93 this->h
->get_hash(this->h
, this->ipaded_key
, NULL
);
99 * Implementation of hmac_t.allocate_mac.
101 static status_t
allocate_mac(private_hmac_t
*this, chunk_t data
, chunk_t
*out
)
103 /* allocate space and use get_mac */
107 this->hmac
.get_mac(&(this->hmac
), data
, NULL
);
111 out
->len
= this->h
->get_block_size(this->h
);
112 out
->ptr
= allocator_alloc(out
->len
);
113 if (out
->ptr
== NULL
)
117 this->hmac
.get_mac(&(this->hmac
), data
, out
->ptr
);
123 * Implementation of hmac_t.get_block_size.
125 static size_t get_block_size(private_hmac_t
*this)
127 return this->h
->get_block_size(this->h
);
131 * Implementation of hmac_t.set_key.
133 static status_t
set_key(private_hmac_t
*this, chunk_t key
)
136 u_int8_t buffer
[this->b
];
138 memset(buffer
, 0, this->b
);
140 if (key
.len
> this->b
)
142 /* if key is too long, it will be hashed */
143 this->h
->get_hash(this->h
, key
, buffer
);
147 /* if not, just copy it in our pre-padded k */
148 memcpy(buffer
, key
.ptr
, key
.len
);
151 /* apply ipad and opad to key */
152 for (i
= 0; i
< this->b
; i
++)
154 this->ipaded_key
.ptr
[i
] = buffer
[i
] ^ 0x36;
155 this->opaded_key
.ptr
[i
] = buffer
[i
] ^ 0x5C;
158 /* begin hashing of inner pad */
159 this->h
->reset(this->h
);
160 this->h
->get_hash(this->h
, this->ipaded_key
, NULL
);
166 * Implementation of hmac_t.destroy.
168 static status_t
destroy(private_hmac_t
*this)
170 this->h
->destroy(this->h
);
171 allocator_free(this->opaded_key
.ptr
);
172 allocator_free(this->ipaded_key
.ptr
);
173 allocator_free(this);
178 * Described in header
180 hmac_t
*hmac_create(hash_algorithm_t hash_algorithm
)
182 private_hmac_t
*this;
184 this = allocator_alloc_thing(private_hmac_t
);
189 /* set hmac_t methods */
190 this->hmac
.get_mac
= (size_t (*)(hmac_t
*,chunk_t
,u_int8_t
*))get_mac
;
191 this->hmac
.allocate_mac
= (size_t (*)(hmac_t
*,chunk_t
,chunk_t
*))allocate_mac
;
192 this->hmac
.get_block_size
= (size_t (*)(hmac_t
*))get_block_size
;
193 this->hmac
.set_key
= (status_t (*)(hmac_t
*,chunk_t
))set_key
;
194 this->hmac
.destroy
= (status_t (*)(hmac_t
*))destroy
;
196 /* set b, according to hasher */
197 switch (hash_algorithm
)
204 allocator_free(this);
208 /* build the hasher */
209 this->h
= hasher_create(hash_algorithm
);
212 allocator_free(this);
216 /* build ipad and opad */
217 this->opaded_key
.ptr
= allocator_alloc(this->b
);
218 this->opaded_key
.len
= this->b
;
219 if (this->opaded_key
.ptr
== NULL
)
221 this->h
->destroy(this->h
);
222 allocator_free(this);
225 this->ipaded_key
.ptr
= allocator_alloc(this->b
);
226 this->ipaded_key
.len
= this->b
;
227 if (this->ipaded_key
.ptr
== NULL
)
229 this->h
->destroy(this->h
);
230 allocator_free(this->opaded_key
.ptr
);
231 allocator_free(this);
235 return &(this->hmac
);