reintegrated eap-radius branch into trunk
[strongswan.git] / src / libstrongswan / plugins / hmac / hmac_signer.c
1 /*
2 * Copyright (C) 2005-2008 Martin Willi
3 * Copyright (C) 2005 Jan Hutter
4 * Hochschule fuer Technik Rapperswil
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation; either version 2 of the License, or (at your
9 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
10 *
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * for more details.
15 *
16 * $Id$
17 */
18
19 #include <string.h>
20
21 #include "hmac_signer.h"
22 #include "hmac.h"
23
24 typedef struct private_hmac_signer_t private_hmac_signer_t;
25
26 /**
27 * Private data structure with signing context.
28 */
29 struct private_hmac_signer_t {
30 /**
31 * Public interface of hmac_signer_t.
32 */
33 hmac_signer_t public;
34
35 /**
36 * Assigned hmac function.
37 */
38 hmac_t *hmac;
39
40 /**
41 * Block size (truncation of HMAC Hash)
42 */
43 size_t block_size;
44 };
45
46 /**
47 * Implementation of signer_t.get_signature.
48 */
49 static void get_signature(private_hmac_signer_t *this,
50 chunk_t data, u_int8_t *buffer)
51 {
52 if (buffer == NULL)
53 { /* append mode */
54 this->hmac->get_mac(this->hmac, data, NULL);
55 }
56 else
57 {
58 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
59
60 this->hmac->get_mac(this->hmac, data, mac);
61 memcpy(buffer, mac, this->block_size);
62 }
63 }
64
65 /**
66 * Implementation of signer_t.allocate_signature.
67 */
68 static void allocate_signature (private_hmac_signer_t *this,
69 chunk_t data, chunk_t *chunk)
70 {
71 if (chunk == NULL)
72 { /* append mode */
73 this->hmac->get_mac(this->hmac, data, NULL);
74 }
75 else
76 {
77 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
78
79 this->hmac->get_mac(this->hmac, data, mac);
80
81 chunk->ptr = malloc(this->block_size);
82 chunk->len = this->block_size;
83
84 memcpy(chunk->ptr, mac, this->block_size);
85 }
86 }
87
88 /**
89 * Implementation of signer_t.verify_signature.
90 */
91 static bool verify_signature(private_hmac_signer_t *this,
92 chunk_t data, chunk_t signature)
93 {
94 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
95
96 this->hmac->get_mac(this->hmac, data, mac);
97
98 if (signature.len != this->block_size)
99 {
100 return FALSE;
101 }
102 return memeq(signature.ptr, mac, this->block_size);
103 }
104
105 /**
106 * Implementation of signer_t.get_key_size.
107 */
108 static size_t get_key_size(private_hmac_signer_t *this)
109 {
110 return this->hmac->get_block_size(this->hmac);
111 }
112
113 /**
114 * Implementation of signer_t.get_block_size.
115 */
116 static size_t get_block_size(private_hmac_signer_t *this)
117 {
118 return this->block_size;
119 }
120
121 /**
122 * Implementation of signer_t.set_key.
123 */
124 static void set_key(private_hmac_signer_t *this, chunk_t key)
125 {
126 this->hmac->set_key(this->hmac, key);
127 }
128
129 /**
130 * Implementation of signer_t.destroy.
131 */
132 static status_t destroy(private_hmac_signer_t *this)
133 {
134 this->hmac->destroy(this->hmac);
135 free(this);
136 return SUCCESS;
137 }
138
139 /*
140 * Described in header
141 */
142 hmac_signer_t *hmac_signer_create(integrity_algorithm_t algo)
143 {
144 private_hmac_signer_t *this;
145 size_t trunc;
146 hash_algorithm_t hash;
147
148 switch (algo)
149 {
150 case AUTH_HMAC_SHA1_96:
151 hash = HASH_SHA1;
152 trunc = 12;
153 break;
154 case AUTH_HMAC_SHA1_128:
155 hash = HASH_SHA1;
156 trunc = 16;
157 break;
158 case AUTH_HMAC_MD5_96:
159 hash = HASH_MD5;
160 trunc = 12;
161 break;
162 case AUTH_HMAC_MD5_128:
163 hash = HASH_MD5;
164 trunc = 16;
165 break;
166 case AUTH_HMAC_SHA2_256_128:
167 hash = HASH_SHA256;
168 trunc = 16;
169 break;
170 case AUTH_HMAC_SHA2_384_192:
171 hash = HASH_SHA384;
172 trunc = 24;
173 break;
174 case AUTH_HMAC_SHA2_512_256:
175 hash = HASH_SHA512;
176 trunc = 32;
177 break;
178 default:
179 return NULL;
180 }
181
182 this = malloc_thing(private_hmac_signer_t);
183 this->hmac = hmac_create(hash);
184 if (this->hmac == NULL)
185 {
186 free(this);
187 return NULL;
188 }
189 /* prevent invalid truncation */
190 this->block_size = min(trunc, this->hmac->get_block_size(this->hmac));
191
192 /* interface functions */
193 this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
194 this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
195 this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature;
196 this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size;
197 this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
198 this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key;
199 this->public.signer_interface.destroy = (void (*) (signer_t*))destroy;
200
201 return &(this->public);
202 }
203