4 * @brief Implementation of message authentication
5 * using cryptographic hash functions (HMAC). See RFC2104.
10 * Copyright (C) 2005 Jan Hutter, Martin Willi
11 * Hochschule fuer Technik Rapperswil
13 * This program is free software; you can redistribute it and/or modify it
14 * under the terms of the GNU General Public License as published by the
15 * Free Software Foundation; either version 2 of the License, or (at your
16 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
27 #include "../utils/allocator.h"
30 * Private data of an hmac_t object.
33 typedef struct private_hmac_s private_hmac_t
;
35 struct private_hmac_s
{
37 * public hmac_t interface
47 * block size, as in RFC
57 * previously xor'ed key using opad
61 * previously xor'ed key using ipad
67 * implementation of hmac_t.get_mac
69 static status_t
get_mac(private_hmac_t
*this, chunk_t data
, u_int8_t
*out
)
71 /* H(K XOR opad, H(K XOR ipad, text)) */
72 u_int8_t buffer
[this->h
->get_block_size(this->h
)];
75 inner
.len
= this->h
->get_block_size(this->h
);
78 this->h
->get_hash(this->h
, this->ipaded_key
, NULL
);
79 this->h
->get_hash(this->h
, data
, buffer
);
82 this->h
->get_hash(this->h
, this->opaded_key
, NULL
);
83 this->h
->get_hash(this->h
, inner
, out
);
89 * implementation of hmac_t.allocate_mac
91 static status_t
allocate_mac(private_hmac_t
*this, chunk_t data
, chunk_t
*out
)
93 /* allocate space and use get_mac */
94 out
->len
= this->h
->get_block_size(this->h
);
95 out
->ptr
= allocator_alloc(out
->len
);
100 this->public.get_mac(&(this->public), data
, out
->ptr
);
105 * implementation of hmac_t.get_block_size
107 static size_t get_block_size(private_hmac_t
*this)
109 return this->h
->get_block_size(this->h
);
113 * implementation of hmac_t.set_key
115 static status_t
set_key(private_hmac_t
*this, chunk_t key
)
118 u_int8_t buffer
[this->b
];
120 memset(buffer
, 0, this->b
);
122 if (key
.len
> this->b
)
124 /* if key is too long, it will be hashed */
125 this->h
->get_hash(this->h
, key
, buffer
);
129 /* if not, just copy it in our pre-padded k */
130 memcpy(buffer
, key
.ptr
, key
.len
);
133 /* apply ipad and opad to key */
134 for (i
= 0; i
< this->b
; i
++)
136 this->ipaded_key
.ptr
[i
] = buffer
[i
] ^ 0x36;
137 this->opaded_key
.ptr
[i
] = buffer
[i
] ^ 0x5C;
144 * implementation of hmac_t.destroy
146 static status_t
destroy(private_hmac_t
*this)
148 this->h
->destroy(this->h
);
149 allocator_free(this->k
.ptr
);
150 allocator_free(this->opaded_key
.ptr
);
151 allocator_free(this->ipaded_key
.ptr
);
152 allocator_free(this);
157 * Described in header
159 hmac_t
*hmac_create(hash_algorithm_t hash_algorithm
)
161 private_hmac_t
*this;
163 this = allocator_alloc_thing(private_hmac_t
);
168 /* set public methods */
169 this->public.get_mac
= (size_t (*)(hmac_t
*,chunk_t
,u_int8_t
*))get_mac
;
170 this->public.allocate_mac
= (size_t (*)(hmac_t
*,chunk_t
,chunk_t
*))allocate_mac
;
171 this->public.get_block_size
= (size_t (*)(hmac_t
*))get_block_size
;
172 this->public.set_key
= (status_t (*)(hmac_t
*,chunk_t
))set_key
;
173 this->public.destroy
= (status_t (*)(hmac_t
*))destroy
;
175 /* set b, according to hasher */
176 switch (hash_algorithm
)
182 allocator_free(this);
186 /* build the hasher */
187 this->h
= hasher_create(hash_algorithm
);
190 allocator_free(this);
196 /* build ipad and opad */
197 this->opaded_key
.ptr
= allocator_alloc(this->b
);
198 this->opaded_key
.len
= this->b
;
199 if (this->opaded_key
.ptr
== NULL
)
201 this->h
->destroy(this->h
);
202 allocator_free(this->k
.ptr
);
203 allocator_free(this);
206 this->ipaded_key
.ptr
= allocator_alloc(this->b
);
207 this->ipaded_key
.len
= this->b
;
208 if (this->ipaded_key
.ptr
== NULL
)
210 this->h
->destroy(this->h
);
211 allocator_free(this->opaded_key
.ptr
);
212 allocator_free(this);
217 return &(this->public);