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
27 typedef struct private_hmac_t private_hmac_t
;
30 * Private data of a hmac_t object.
32 * The variable names are the same as in the RFC.
34 struct private_hmac_t
{
36 * Public hmac_t interface.
41 * Block size, as in RFC.
51 * Previously xor'ed key using opad.
56 * Previously xor'ed key using ipad.
62 * Implementation of hmac_t.get_mac.
64 static void get_mac(private_hmac_t
*this, chunk_t data
, u_int8_t
*out
)
66 /* H(K XOR opad, H(K XOR ipad, text))
68 * if out is NULL, we append text to the inner hash.
69 * else, we complete the inner and do the outer.
73 u_int8_t buffer
[this->h
->get_hash_size(this->h
)];
78 /* append data to inner */
79 this->h
->get_hash(this->h
, data
, NULL
);
83 /* append and do outer hash */
85 inner
.len
= this->h
->get_hash_size(this->h
);
88 this->h
->get_hash(this->h
, data
, buffer
);
91 this->h
->get_hash(this->h
, this->opaded_key
, NULL
);
92 this->h
->get_hash(this->h
, inner
, out
);
94 /* reinit for next call */
95 this->h
->get_hash(this->h
, this->ipaded_key
, NULL
);
100 * Implementation of hmac_t.allocate_mac.
102 static void allocate_mac(private_hmac_t
*this, chunk_t data
, chunk_t
*out
)
104 /* allocate space and use get_mac */
108 this->hmac
.get_mac(&(this->hmac
), data
, NULL
);
112 out
->len
= this->h
->get_hash_size(this->h
);
113 out
->ptr
= malloc(out
->len
);
114 this->hmac
.get_mac(&(this->hmac
), data
, out
->ptr
);
119 * Implementation of hmac_t.get_block_size.
121 static size_t get_block_size(private_hmac_t
*this)
123 return this->h
->get_hash_size(this->h
);
127 * Implementation of hmac_t.set_key.
129 static void set_key(private_hmac_t
*this, chunk_t key
)
132 u_int8_t buffer
[this->b
];
134 memset(buffer
, 0, this->b
);
136 if (key
.len
> this->b
)
138 /* if key is too long, it will be hashed */
139 this->h
->get_hash(this->h
, key
, buffer
);
143 /* if not, just copy it in our pre-padded k */
144 memcpy(buffer
, key
.ptr
, key
.len
);
147 /* apply ipad and opad to key */
148 for (i
= 0; i
< this->b
; i
++)
150 this->ipaded_key
.ptr
[i
] = buffer
[i
] ^ 0x36;
151 this->opaded_key
.ptr
[i
] = buffer
[i
] ^ 0x5C;
154 /* begin hashing of inner pad */
155 this->h
->reset(this->h
);
156 this->h
->get_hash(this->h
, this->ipaded_key
, NULL
);
160 * Implementation of hmac_t.destroy.
162 static void destroy(private_hmac_t
*this)
164 this->h
->destroy(this->h
);
165 free(this->opaded_key
.ptr
);
166 free(this->ipaded_key
.ptr
);
171 * Described in header
173 hmac_t
*hmac_create(hash_algorithm_t hash_algorithm
)
175 private_hmac_t
*this;
177 this = malloc_thing(private_hmac_t
);
179 /* set hmac_t methods */
180 this->hmac
.get_mac
= (void (*)(hmac_t
*,chunk_t
,u_int8_t
*))get_mac
;
181 this->hmac
.allocate_mac
= (void (*)(hmac_t
*,chunk_t
,chunk_t
*))allocate_mac
;
182 this->hmac
.get_block_size
= (size_t (*)(hmac_t
*))get_block_size
;
183 this->hmac
.set_key
= (void (*)(hmac_t
*,chunk_t
))set_key
;
184 this->hmac
.destroy
= (void (*)(hmac_t
*))destroy
;
186 /* set b, according to hasher */
187 switch (hash_algorithm
)
198 /* build the hasher */
199 this->h
= hasher_create(hash_algorithm
);
201 /* build ipad and opad */
202 this->opaded_key
.ptr
= malloc(this->b
);
203 this->opaded_key
.len
= this->b
;
205 this->ipaded_key
.ptr
= malloc(this->b
);
206 this->ipaded_key
.len
= this->b
;
208 return &(this->hmac
);