Implemented AES-CMAC based PRF and signer.
[strongswan.git] / src / libstrongswan / plugins / cmac / cmac_signer.c
1 /*
2 * Copyright (C) 2012 Tobias Brunner
3 * Hochschule fuer Technik Rapperswil
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 <string.h>
17
18 #include "cmac_signer.h"
19 #include "cmac.h"
20
21 typedef struct private_cmac_signer_t private_cmac_signer_t;
22
23 /**
24 * Private data structure with signing context.
25 */
26 struct private_cmac_signer_t {
27
28 /**
29 * Public interface.
30 */
31 cmac_signer_t public;
32
33 /**
34 * Assigned cmac function.
35 */
36 cmac_t *cmac;
37
38 /**
39 * Block size (truncation of CMAC MAC)
40 */
41 size_t block_size;
42 };
43
44 METHOD(signer_t, get_signature, void,
45 private_cmac_signer_t *this, chunk_t data, u_int8_t *buffer)
46 {
47 if (buffer == NULL)
48 { /* append mode */
49 this->cmac->get_mac(this->cmac, data, NULL);
50 }
51 else
52 {
53 u_int8_t mac[this->cmac->get_block_size(this->cmac)];
54
55 this->cmac->get_mac(this->cmac, data, mac);
56 memcpy(buffer, mac, this->block_size);
57 }
58 }
59
60 METHOD(signer_t, allocate_signature, void,
61 private_cmac_signer_t *this, chunk_t data, chunk_t *chunk)
62 {
63 if (chunk == NULL)
64 { /* append mode */
65 this->cmac->get_mac(this->cmac, data, NULL);
66 }
67 else
68 {
69 u_int8_t mac[this->cmac->get_block_size(this->cmac)];
70
71 this->cmac->get_mac(this->cmac, data, mac);
72
73 chunk->ptr = malloc(this->block_size);
74 chunk->len = this->block_size;
75
76 memcpy(chunk->ptr, mac, this->block_size);
77 }
78 }
79
80 METHOD(signer_t, verify_signature, bool,
81 private_cmac_signer_t *this, chunk_t data, chunk_t signature)
82 {
83 u_int8_t mac[this->cmac->get_block_size(this->cmac)];
84
85 if (signature.len != this->block_size)
86 {
87 return FALSE;
88 }
89
90 this->cmac->get_mac(this->cmac, data, mac);
91 return memeq(signature.ptr, mac, this->block_size);
92 }
93
94 METHOD(signer_t, get_key_size, size_t,
95 private_cmac_signer_t *this)
96 {
97 return this->cmac->get_block_size(this->cmac);
98 }
99
100 METHOD(signer_t, get_block_size, size_t,
101 private_cmac_signer_t *this)
102 {
103 return this->block_size;
104 }
105
106 METHOD(signer_t, set_key, void,
107 private_cmac_signer_t *this, chunk_t key)
108 {
109 this->cmac->set_key(this->cmac, key);
110 }
111
112 METHOD(signer_t, destroy, void,
113 private_cmac_signer_t *this)
114 {
115 this->cmac->destroy(this->cmac);
116 free(this);
117 }
118
119 /*
120 * Described in header
121 */
122 cmac_signer_t *cmac_signer_create(integrity_algorithm_t algo)
123 {
124 private_cmac_signer_t *this;
125 size_t truncation;
126 cmac_t *cmac;
127
128 switch (algo)
129 {
130 case AUTH_AES_CMAC_96:
131 cmac = cmac_create(ENCR_AES_CBC, 16);
132 truncation = 12;
133 break;
134 default:
135 return NULL;
136 }
137 if (cmac == NULL)
138 {
139 return NULL;
140 }
141
142 INIT(this,
143 .public = {
144 .signer = {
145 .get_signature = _get_signature,
146 .allocate_signature = _allocate_signature,
147 .verify_signature = _verify_signature,
148 .get_key_size = _get_key_size,
149 .get_block_size = _get_block_size,
150 .set_key = _set_key,
151 .destroy = _destroy,
152 },
153 },
154 .cmac = cmac,
155 .block_size = min(truncation, cmac->get_block_size(cmac)),
156 );
157
158 return &this->public;
159 }