- AUTH_HMAC_MD5_96 and AUTH_HMAC_SHA1_96 implemented and tested...
[strongswan.git] / Source / charon / transforms / signers / hmac_signer.c
1 /**
2 * @file hmac_signer.c
3 *
4 * @brief Implementation of hmac_signer_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2005 Jan Hutter, Martin Willi
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 Public 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 Public License
20 * for more details.
21 */
22
23 #include "hmac_signer.h"
24
25 #include <utils/allocator.h>
26 #include <transforms/prfs/prf_hmac.h>
27
28 /**
29 * This class represents a hmac signer with 12 byte (96 bit) output
30 */
31 #define BLOCK_SIZE 12
32
33 typedef struct private_hmac_signer_t private_hmac_signer_t;
34
35 /**
36 * private data structure with signing context.
37 */
38 struct private_hmac_signer_t {
39 /**
40 * Public interface for this signer.
41 */
42 hmac_signer_t public;
43
44 /*
45 * Assigned hmac function.
46 */
47 prf_t *hmac_prf;
48 };
49
50
51 static status_t get_signature (private_hmac_signer_t *this, chunk_t data, u_int8_t *buffer)
52 {
53 u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
54 status_t status;
55
56 status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
57 if (status != SUCCESS)
58 {
59 return status;
60 }
61
62 /* copy mac aka signature :-) */
63 memcpy(buffer,full_mac,BLOCK_SIZE);
64
65 return SUCCESS;
66 }
67
68 static status_t allocate_signature (private_hmac_signer_t *this, chunk_t data, chunk_t *chunk)
69 {
70 chunk_t signature;
71 status_t status;
72 u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
73
74 status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
75 if (status != SUCCESS)
76 {
77 return status;
78 }
79
80 signature.ptr = allocator_alloc(BLOCK_SIZE);
81 if (signature.ptr == NULL)
82 {
83 return OUT_OF_RES;
84 }
85 signature.len = BLOCK_SIZE;
86
87 /* copy mac aka signature :-) */
88 memcpy(signature.ptr,full_mac,BLOCK_SIZE);
89
90 *chunk = signature;
91
92 return SUCCESS;
93
94 }
95
96 static status_t verify_signature (private_hmac_signer_t *this, chunk_t data, chunk_t signature, bool *valid)
97 {
98 status_t status;
99 u_int8_t full_mac[this->hmac_prf->get_block_size(this->hmac_prf)];
100
101 status = this->hmac_prf->get_bytes(this->hmac_prf,data,full_mac);
102 if (status != SUCCESS)
103 {
104 return status;
105 }
106
107 if (signature.len != BLOCK_SIZE)
108 {
109 /* signature must have BLOCK_SIZE length */
110 return INVALID_ARG;
111 }
112
113 /* compare mac aka signature :-) */
114 if (memcmp(signature.ptr,full_mac,BLOCK_SIZE) == 0)
115 {
116 *valid = TRUE;
117 }
118 else
119 {
120 *valid = FALSE;
121 }
122
123 return SUCCESS;
124 }
125
126 static size_t get_block_size (private_hmac_signer_t *this)
127 {
128 return BLOCK_SIZE;
129 }
130
131 static status_t set_key (private_hmac_signer_t *this, chunk_t key)
132 {
133 return (this->hmac_prf->set_key(this->hmac_prf,key));
134 }
135
136 /**
137 * implementation of signer_t.destroy.
138 */
139 static status_t destroy(private_hmac_signer_t *this)
140 {
141 this->hmac_prf->destroy(this->hmac_prf);
142 allocator_free(this);
143 return SUCCESS;
144 }
145
146
147 /*
148 * Described in header
149 */
150 hmac_signer_t *hmac_signer_create(hash_algorithm_t hash_algoritm)
151 {
152 private_hmac_signer_t *this = allocator_alloc_thing(private_hmac_signer_t);
153 if (this == NULL)
154 {
155 return NULL;
156 }
157
158 this->hmac_prf = (prf_t *) prf_hmac_create(hash_algoritm);
159
160 if (this->hmac_prf == NULL)
161 {
162 /* hmac prf could not be created !!! */
163 allocator_free(this);
164 return NULL;
165 }
166
167 if (this->hmac_prf->get_block_size(this->hmac_prf) < BLOCK_SIZE)
168 {
169 /* hmac prf with given algorithm has to small block size */
170 allocator_free(this);
171 return NULL;
172
173 }
174
175 /* interface functions */
176 this->public.signer_interface.get_signature = (status_t (*) (signer_t*, chunk_t, u_int8_t*))get_signature;
177 this->public.signer_interface.allocate_signature = (status_t (*) (signer_t*, chunk_t, chunk_t*))allocate_signature;
178 this->public.signer_interface.verify_signature = (status_t (*) (signer_t*, chunk_t, chunk_t,bool *))verify_signature;
179 this->public.signer_interface.get_block_size = (size_t (*) (signer_t*))get_block_size;
180 this->public.signer_interface.set_key = (size_t (*) (signer_t*,chunk_t))set_key;
181 this->public.signer_interface.destroy = (status_t (*) (signer_t*))destroy;
182
183 return &(this->public);
184 }