Added support for Camellia cipher to xcbc
[strongswan.git] / src / libstrongswan / plugins / xcbc / xcbc_signer.c
1 /*
2 * Copyright (C) 2008 Martin Willi
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 "xcbc_signer.h"
19 #include "xcbc.h"
20
21 typedef struct private_xcbc_signer_t private_xcbc_signer_t;
22
23 /**
24 * Private data structure with signing context.
25 */
26 struct private_xcbc_signer_t {
27
28 /**
29 * Public interface of xcbc_signer_t.
30 */
31 xcbc_signer_t public;
32
33 /**
34 * Assigned xcbc function.
35 */
36 xcbc_t *xcbc;
37
38 /**
39 * Block size (truncation of XCBC MAC)
40 */
41 size_t block_size;
42 };
43
44 METHOD(signer_t, get_signature, void,
45 private_xcbc_signer_t *this, chunk_t data, u_int8_t *buffer)
46 {
47 if (buffer == NULL)
48 { /* append mode */
49 this->xcbc->get_mac(this->xcbc, data, NULL);
50 }
51 else
52 {
53 u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
54
55 this->xcbc->get_mac(this->xcbc, data, mac);
56 memcpy(buffer, mac, this->block_size);
57 }
58 }
59
60 METHOD(signer_t, allocate_signature, void,
61 private_xcbc_signer_t *this, chunk_t data, chunk_t *chunk)
62 {
63 if (chunk == NULL)
64 { /* append mode */
65 this->xcbc->get_mac(this->xcbc, data, NULL);
66 }
67 else
68 {
69 u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
70
71 this->xcbc->get_mac(this->xcbc, 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_xcbc_signer_t *this, chunk_t data, chunk_t signature)
82 {
83 u_int8_t mac[this->xcbc->get_block_size(this->xcbc)];
84
85 if (signature.len != this->block_size)
86 {
87 return FALSE;
88 }
89
90 this->xcbc->get_mac(this->xcbc, data, mac);
91 return memeq(signature.ptr, mac, this->block_size);
92 }
93
94 METHOD(signer_t, get_key_size, size_t,
95 private_xcbc_signer_t *this)
96 {
97 return this->xcbc->get_block_size(this->xcbc);
98 }
99
100 METHOD(signer_t, get_block_size, size_t,
101 private_xcbc_signer_t *this)
102 {
103 return this->block_size;
104 }
105
106 METHOD(signer_t, set_key, void,
107 private_xcbc_signer_t *this, chunk_t key)
108 {
109 this->xcbc->set_key(this->xcbc, key);
110 }
111
112 METHOD(signer_t, destroy, void,
113 private_xcbc_signer_t *this)
114 {
115 this->xcbc->destroy(this->xcbc);
116 free(this);
117 }
118
119 /*
120 * Described in header
121 */
122 xcbc_signer_t *xcbc_signer_create(integrity_algorithm_t algo)
123 {
124 private_xcbc_signer_t *this;
125 size_t trunc;
126 xcbc_t *xcbc;
127
128 switch (algo)
129 {
130 case AUTH_AES_XCBC_96:
131 xcbc = xcbc_create(ENCR_AES_CBC, 16);
132 trunc = 12;
133 break;
134 case AUTH_CAMELLIA_XCBC_96:
135 xcbc = xcbc_create(ENCR_CAMELLIA_CBC, 16);
136 trunc = 12;
137 break;
138 default:
139 return NULL;
140 }
141 if (xcbc == NULL)
142 {
143 return NULL;
144 }
145
146 INIT(this,
147 .public.signer = {
148 .get_signature = _get_signature,
149 .allocate_signature = _allocate_signature,
150 .verify_signature = _verify_signature,
151 .get_key_size = _get_key_size,
152 .get_block_size = _get_block_size,
153 .set_key = _set_key,
154 .destroy = _destroy,
155 },
156 .xcbc = xcbc,
157 .block_size = min(trunc, xcbc->get_block_size(xcbc)),
158 );
159
160 return &this->public;
161 }
162