added support for AUTH_HMAC_SHA1_160
[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
17 #include <string.h>
18
19 #include "hmac_signer.h"
20 #include "hmac.h"
21
22 typedef struct private_hmac_signer_t private_hmac_signer_t;
23
24 /**
25 * Private data structure with signing context.
26 */
27 struct private_hmac_signer_t {
28 /**
29 * Public interface of hmac_signer_t.
30 */
31 hmac_signer_t public;
32
33 /**
34 * Assigned hmac function.
35 */
36 hmac_t *hmac;
37
38 /**
39 * Block size (truncation of HMAC Hash)
40 */
41 size_t block_size;
42 };
43
44 /**
45 * Implementation of signer_t.get_signature.
46 */
47 static void get_signature(private_hmac_signer_t *this,
48 chunk_t data, u_int8_t *buffer)
49 {
50 if (buffer == NULL)
51 { /* append mode */
52 this->hmac->get_mac(this->hmac, data, NULL);
53 }
54 else
55 {
56 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
57
58 this->hmac->get_mac(this->hmac, data, mac);
59 memcpy(buffer, mac, this->block_size);
60 }
61 }
62
63 /**
64 * Implementation of signer_t.allocate_signature.
65 */
66 static void allocate_signature (private_hmac_signer_t *this,
67 chunk_t data, chunk_t *chunk)
68 {
69 if (chunk == NULL)
70 { /* append mode */
71 this->hmac->get_mac(this->hmac, data, NULL);
72 }
73 else
74 {
75 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
76
77 this->hmac->get_mac(this->hmac, data, mac);
78
79 chunk->ptr = malloc(this->block_size);
80 chunk->len = this->block_size;
81
82 memcpy(chunk->ptr, mac, this->block_size);
83 }
84 }
85
86 /**
87 * Implementation of signer_t.verify_signature.
88 */
89 static bool verify_signature(private_hmac_signer_t *this,
90 chunk_t data, chunk_t signature)
91 {
92 u_int8_t mac[this->hmac->get_block_size(this->hmac)];
93
94 this->hmac->get_mac(this->hmac, data, mac);
95
96 if (signature.len != this->block_size)
97 {
98 return FALSE;
99 }
100 return memeq(signature.ptr, mac, this->block_size);
101 }
102
103 /**
104 * Implementation of signer_t.get_key_size.
105 */
106 static size_t get_key_size(private_hmac_signer_t *this)
107 {
108 return this->hmac->get_block_size(this->hmac);
109 }
110
111 /**
112 * Implementation of signer_t.get_block_size.
113 */
114 static size_t get_block_size(private_hmac_signer_t *this)
115 {
116 return this->block_size;
117 }
118
119 /**
120 * Implementation of signer_t.set_key.
121 */
122 static void set_key(private_hmac_signer_t *this, chunk_t key)
123 {
124 this->hmac->set_key(this->hmac, key);
125 }
126
127 /**
128 * Implementation of signer_t.destroy.
129 */
130 static status_t destroy(private_hmac_signer_t *this)
131 {
132 this->hmac->destroy(this->hmac);
133 free(this);
134 return SUCCESS;
135 }
136
137 /*
138 * Described in header
139 */
140 hmac_signer_t *hmac_signer_create(integrity_algorithm_t algo)
141 {
142 private_hmac_signer_t *this;
143 size_t trunc;
144 hash_algorithm_t hash;
145
146 switch (algo)
147 {
148 case AUTH_HMAC_SHA1_96:
149 hash = HASH_SHA1;
150 trunc = 12;
151 break;
152 case AUTH_HMAC_SHA1_128:
153 hash = HASH_SHA1;
154 trunc = 16;
155 break;
156 case AUTH_HMAC_SHA1_160:
157 hash = HASH_SHA1;
158 trunc = 20;
159 break;
160 case AUTH_HMAC_MD5_96:
161 hash = HASH_MD5;
162 trunc = 12;
163 break;
164 case AUTH_HMAC_MD5_128:
165 hash = HASH_MD5;
166 trunc = 16;
167 break;
168 case AUTH_HMAC_SHA2_256_128:
169 hash = HASH_SHA256;
170 trunc = 16;
171 break;
172 case AUTH_HMAC_SHA2_384_192:
173 hash = HASH_SHA384;
174 trunc = 24;
175 break;
176 case AUTH_HMAC_SHA2_512_256:
177 hash = HASH_SHA512;
178 trunc = 32;
179 break;
180 default:
181 return NULL;
182 }
183
184 this = malloc_thing(private_hmac_signer_t);
185 this->hmac = hmac_create(hash);
186 if (this->hmac == NULL)
187 {
188 free(this);
189 return NULL;
190 }
191 /* prevent invalid truncation */
192 this->block_size = min(trunc, this->hmac->get_block_size(this->hmac));
193
194 /* interface functions */
195 this->public.signer_interface.get_signature = (void (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
196 this->public.signer_interface.allocate_signature = (void (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
197 this->public.signer_interface.verify_signature = (bool (*) (signer_t*, chunk_t, chunk_t))verify_signature;
198 this->public.signer_interface.get_key_size = (size_t (*) (signer_t*))get_key_size;
199 this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
200 this->public.signer_interface.set_key = (void (*) (signer_t*,chunk_t))set_key;
201 this->public.signer_interface.destroy = (void (*) (signer_t*))destroy;
202
203 return &(this->public);
204 }
205