]> git.ipfire.org Git - people/ms/strongswan.git/blob - src/libstrongswan/plugins/af_alg/af_alg_signer.c
Add support for untruncated HMAC-SHA-512
[people/ms/strongswan.git] / src / libstrongswan / plugins / af_alg / af_alg_signer.c
1 /*
2 * Copyright (C) 2010 Martin Willi
3 * Copyright (C) 2010 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 #include "af_alg_signer.h"
17 #include "af_alg_ops.h"
18
19 typedef struct private_af_alg_signer_t private_af_alg_signer_t;
20
21 /**
22 * Private data structure with signing context.
23 */
24 struct private_af_alg_signer_t {
25
26 /**
27 * Public interface of af_alg_signer_t.
28 */
29 af_alg_signer_t public;
30
31 /**
32 * AF_ALG operations
33 */
34 af_alg_ops_t *ops;
35
36 /**
37 * Size of the truncated signature
38 */
39 size_t block_size;
40
41 /**
42 * Default key size
43 */
44 size_t key_size;
45 };
46
47 /**
48 * Algorithm database
49 */
50 static struct {
51 integrity_algorithm_t id;
52 char *name;
53 size_t block_size;
54 size_t key_size;
55 } algs[AF_ALG_SIGNER] = {
56 {AUTH_HMAC_SHA1_96, "hmac(sha1)", 12, 20, },
57 {AUTH_HMAC_SHA1_128, "hmac(sha1)", 16, 20, },
58 {AUTH_HMAC_SHA1_160, "hmac(sha1)", 20, 20, },
59 {AUTH_HMAC_SHA2_256_96, "hmac(sha256)", 12, 32, },
60 {AUTH_HMAC_SHA2_256_128, "hmac(sha256)", 16, 32, },
61 {AUTH_HMAC_MD5_96, "hmac(md5)", 12, 16, },
62 {AUTH_HMAC_MD5_128, "hmac(md5)", 16, 16, },
63 {AUTH_HMAC_SHA2_256_256, "hmac(sha384)", 32, 32, },
64 {AUTH_HMAC_SHA2_384_192, "hmac(sha384)", 24, 48, },
65 {AUTH_HMAC_SHA2_384_384, "hmac(sha384)", 48, 48, },
66 {AUTH_HMAC_SHA2_512_256, "hmac(sha512)", 32, 64, },
67 {AUTH_HMAC_SHA2_512_512, "hmac(sha512)", 64, 64, },
68 {AUTH_AES_XCBC_96, "xcbc(aes)", 12, 16, },
69 {AUTH_CAMELLIA_XCBC_96, "xcbc(camellia)", 12, 16, },
70 };
71
72 /**
73 * See header.
74 */
75 void af_alg_signer_probe(plugin_feature_t *features, int *pos)
76 {
77 af_alg_ops_t *ops;
78 int i;
79
80 for (i = 0; i < countof(algs); i++)
81 {
82 ops = af_alg_ops_create("hash", algs[i].name);
83 if (ops)
84 {
85 ops->destroy(ops);
86 features[(*pos)++] = PLUGIN_PROVIDE(SIGNER, algs[i].id);
87 }
88 }
89 }
90
91 /**
92 * Get the kernel algorithm string and block/key size for our identifier
93 */
94 static size_t lookup_alg(integrity_algorithm_t algo, char **name,
95 size_t *key_size)
96 {
97 int i;
98
99 for (i = 0; i < countof(algs); i++)
100 {
101 if (algs[i].id == algo)
102 {
103 *name = algs[i].name;
104 *key_size = algs[i].key_size;
105 return algs[i].block_size;
106 }
107 }
108 return 0;
109 }
110
111 METHOD(signer_t, get_signature, bool,
112 private_af_alg_signer_t *this, chunk_t data, u_int8_t *buffer)
113 {
114 return this->ops->hash(this->ops, data, buffer, this->block_size);
115 }
116
117 METHOD(signer_t, allocate_signature, bool,
118 private_af_alg_signer_t *this, chunk_t data, chunk_t *chunk)
119 {
120 if (chunk)
121 {
122 *chunk = chunk_alloc(this->block_size);
123 return get_signature(this, data, chunk->ptr);
124 }
125 return get_signature(this, data, NULL);
126 }
127
128 METHOD(signer_t, verify_signature, bool,
129 private_af_alg_signer_t *this, chunk_t data, chunk_t signature)
130 {
131 char sig[this->block_size];
132
133 if (signature.len != this->block_size)
134 {
135 return FALSE;
136 }
137 if (!get_signature(this, data, sig))
138 {
139 return FALSE;
140 }
141 return memeq(signature.ptr, sig, signature.len);
142 }
143
144 METHOD(signer_t, get_key_size, size_t,
145 private_af_alg_signer_t *this)
146 {
147 return this->key_size;
148 }
149
150 METHOD(signer_t, get_block_size, size_t,
151 private_af_alg_signer_t *this)
152 {
153 return this->block_size;
154 }
155
156 METHOD(signer_t, set_key, bool,
157 private_af_alg_signer_t *this, chunk_t key)
158 {
159 return this->ops->set_key(this->ops, key);
160 }
161
162 METHOD(signer_t, destroy, void,
163 private_af_alg_signer_t *this)
164 {
165 this->ops->destroy(this->ops);
166 free(this);
167 }
168
169 /*
170 * Described in header
171 */
172 af_alg_signer_t *af_alg_signer_create(integrity_algorithm_t algo)
173 {
174 private_af_alg_signer_t *this;
175 size_t block_size, key_size;
176 char *name;
177
178 block_size = lookup_alg(algo, &name, &key_size);
179 if (!block_size)
180 { /* not supported by kernel */
181 return NULL;
182 }
183
184 INIT(this,
185 .public = {
186 .signer = {
187 .get_signature = _get_signature,
188 .allocate_signature = _allocate_signature,
189 .verify_signature = _verify_signature,
190 .get_key_size = _get_key_size,
191 .get_block_size = _get_block_size,
192 .set_key = _set_key,
193 .destroy = _destroy,
194 },
195 },
196 .ops = af_alg_ops_create("hash", name),
197 .block_size = block_size,
198 .key_size = key_size,
199 );
200 if (!this->ops)
201 {
202 free(this);
203 return NULL;
204 }
205 return &this->public;
206 }