fixed 64 bit issue
[strongswan.git] / src / libstrongswan / crypto / hmac.c
1 /**
2 * @file hmac.c
3 *
4 * @brief Implementation of hmac_t.
5 */
6
7 /*
8 * Copyright (C) 2005-2006 Martin Willi
9 * Copyright (C) 2005 Jan Hutter
10 * Hochschule fuer Technik Rapperswil
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General hmac License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General hmac License
20 * for more details.
21 */
22
23 #include <string.h>
24
25 #include "hmac.h"
26
27
28 typedef struct private_hmac_t private_hmac_t;
29
30 /**
31 * Private data of a hmac_t object.
32 *
33 * The variable names are the same as in the RFC.
34 */
35 struct private_hmac_t {
36 /**
37 * Public hmac_t interface.
38 */
39 hmac_t hmac;
40
41 /**
42 * Block size, as in RFC.
43 */
44 u_int8_t b;
45
46 /**
47 * Hash function.
48 */
49 hasher_t *h;
50
51 /**
52 * Previously xor'ed key using opad.
53 */
54 chunk_t opaded_key;
55
56 /**
57 * Previously xor'ed key using ipad.
58 */
59 chunk_t ipaded_key;
60 };
61
62 /**
63 * Implementation of hmac_t.get_mac.
64 */
65 static void get_mac(private_hmac_t *this, chunk_t data, u_int8_t *out)
66 {
67 /* H(K XOR opad, H(K XOR ipad, text))
68 *
69 * if out is NULL, we append text to the inner hash.
70 * else, we complete the inner and do the outer.
71 *
72 */
73
74 u_int8_t buffer[this->h->get_hash_size(this->h)];
75 chunk_t inner;
76
77 if (out == NULL)
78 {
79 /* append data to inner */
80 this->h->get_hash(this->h, data, NULL);
81 }
82 else
83 {
84 /* append and do outer hash */
85 inner.ptr = buffer;
86 inner.len = this->h->get_hash_size(this->h);
87
88 /* complete inner */
89 this->h->get_hash(this->h, data, buffer);
90
91 /* do outer */
92 this->h->get_hash(this->h, this->opaded_key, NULL);
93 this->h->get_hash(this->h, inner, out);
94
95 /* reinit for next call */
96 this->h->get_hash(this->h, this->ipaded_key, NULL);
97 }
98 }
99
100 /**
101 * Implementation of hmac_t.allocate_mac.
102 */
103 static void allocate_mac(private_hmac_t *this, chunk_t data, chunk_t *out)
104 {
105 /* allocate space and use get_mac */
106 if (out == NULL)
107 {
108 /* append mode */
109 this->hmac.get_mac(&(this->hmac), data, NULL);
110 }
111 else
112 {
113 out->len = this->h->get_hash_size(this->h);
114 out->ptr = malloc(out->len);
115 this->hmac.get_mac(&(this->hmac), data, out->ptr);
116 }
117 }
118
119 /**
120 * Implementation of hmac_t.get_block_size.
121 */
122 static size_t get_block_size(private_hmac_t *this)
123 {
124 return this->h->get_hash_size(this->h);
125 }
126
127 /**
128 * Implementation of hmac_t.set_key.
129 */
130 static void set_key(private_hmac_t *this, chunk_t key)
131 {
132 int i;
133 u_int8_t buffer[this->b];
134
135 memset(buffer, 0, this->b);
136
137 if (key.len > this->b)
138 {
139 /* if key is too long, it will be hashed */
140 this->h->get_hash(this->h, key, buffer);
141 }
142 else
143 {
144 /* if not, just copy it in our pre-padded k */
145 memcpy(buffer, key.ptr, key.len);
146 }
147
148 /* apply ipad and opad to key */
149 for (i = 0; i < this->b; i++)
150 {
151 this->ipaded_key.ptr[i] = buffer[i] ^ 0x36;
152 this->opaded_key.ptr[i] = buffer[i] ^ 0x5C;
153 }
154
155 /* begin hashing of inner pad */
156 this->h->reset(this->h);
157 this->h->get_hash(this->h, this->ipaded_key, NULL);
158 }
159
160 /**
161 * Implementation of hmac_t.destroy.
162 */
163 static void destroy(private_hmac_t *this)
164 {
165 this->h->destroy(this->h);
166 free(this->opaded_key.ptr);
167 free(this->ipaded_key.ptr);
168 free(this);
169 }
170
171 /*
172 * Described in header
173 */
174 hmac_t *hmac_create(hash_algorithm_t hash_algorithm)
175 {
176 private_hmac_t *this;
177
178 this = malloc_thing(private_hmac_t);
179
180 /* set hmac_t methods */
181 this->hmac.get_mac = (void (*)(hmac_t *,chunk_t,u_int8_t*))get_mac;
182 this->hmac.allocate_mac = (void (*)(hmac_t *,chunk_t,chunk_t*))allocate_mac;
183 this->hmac.get_block_size = (size_t (*)(hmac_t *))get_block_size;
184 this->hmac.set_key = (void (*)(hmac_t *,chunk_t))set_key;
185 this->hmac.destroy = (void (*)(hmac_t *))destroy;
186
187 /* set b, according to hasher */
188 switch (hash_algorithm)
189 {
190 case HASH_SHA1:
191 case HASH_MD5:
192 this->b = 64;
193 break;
194 default:
195 free(this);
196 return NULL;
197 }
198
199 /* build the hasher */
200 this->h = hasher_create(hash_algorithm);
201
202 /* build ipad and opad */
203 this->opaded_key.ptr = malloc(this->b);
204 this->opaded_key.len = this->b;
205
206 this->ipaded_key.ptr = malloc(this->b);
207 this->ipaded_key.len = this->b;
208
209 return &(this->hmac);
210 }