Implemented an AEAD wrapper for traditional crypter/signer transforms
[strongswan.git] / src / libstrongswan / crypto / aead.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 "aead.h"
17
18 #include <debug.h>
19
20 typedef struct private_aead_t private_aead_t;
21
22 /**
23 * Private data of an aead_t object.
24 */
25 struct private_aead_t {
26
27 /**
28 * Public aead_t interface.
29 */
30 aead_t public;
31
32 /**
33 * traditional crypter
34 */
35 crypter_t *crypter;
36
37 /**
38 * draditional signer
39 */
40 signer_t *signer;
41 };
42
43 METHOD(aead_t, encrypt, void,
44 private_aead_t *this, chunk_t plain, chunk_t assoc, chunk_t iv,
45 chunk_t *encrypted)
46 {
47 chunk_t encr, sig;
48
49 this->signer->get_signature(this->signer, assoc, NULL);
50 this->signer->get_signature(this->signer, iv, NULL);
51
52 if (encrypted)
53 {
54 this->crypter->encrypt(this->crypter, plain, iv, &encr);
55 this->signer->allocate_signature(this->signer, encr, &sig);
56 *encrypted = chunk_cat("cmm", iv, encr, sig);
57 }
58 else
59 {
60 this->crypter->encrypt(this->crypter, plain, iv, NULL);
61 this->signer->get_signature(this->signer, plain, plain.ptr + plain.len);
62 }
63 }
64
65 METHOD(aead_t, decrypt, bool,
66 private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
67 chunk_t *plain)
68 {
69 chunk_t sig;
70 size_t bs;
71
72 bs = this->crypter->get_block_size(this->crypter);
73 sig.len = this->signer->get_block_size(this->signer);
74 if (sig.len > encrypted.len || (encrypted.len - sig.len) % bs)
75 {
76 DBG1(DBG_LIB, "invalid encrypted data length %d with block size %d",
77 encrypted.len - sig.len, bs);
78 return FALSE;
79 }
80 chunk_split(encrypted, "mm", encrypted.len - sig.len,
81 &encrypted, sig.len, &sig);
82
83 this->signer->get_signature(this->signer, assoc, NULL);
84 this->signer->get_signature(this->signer, iv, NULL);
85 if (!this->signer->verify_signature(this->signer, encrypted, sig))
86 {
87 DBG1(DBG_LIB, "MAC verification failed");
88 return FALSE;
89 }
90 this->crypter->decrypt(this->crypter, encrypted, iv, plain);
91 return TRUE;
92 }
93
94 METHOD(aead_t, get_block_size, size_t,
95 private_aead_t *this)
96 {
97 return this->crypter->get_block_size(this->crypter);
98 }
99
100 METHOD(aead_t, get_icv_size, size_t,
101 private_aead_t *this)
102 {
103 return this->signer->get_block_size(this->signer);
104 }
105
106 METHOD(aead_t, get_iv_size, size_t,
107 private_aead_t *this)
108 {
109 return this->crypter->get_iv_size(this->crypter);
110 }
111
112 METHOD(aead_t, get_key_size, size_t,
113 private_aead_t *this)
114 {
115 return this->crypter->get_key_size(this->crypter) +
116 this->signer->get_key_size(this->signer);
117 }
118
119 METHOD(aead_t, set_key, void,
120 private_aead_t *this, chunk_t key)
121 {
122 chunk_t sig, enc;
123
124 chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig,
125 this->crypter->get_key_size(this->crypter), &enc);
126
127 this->signer->set_key(this->signer, sig);
128 this->crypter->set_key(this->crypter, enc);
129 }
130
131 METHOD(aead_t, destroy, void,
132 private_aead_t *this)
133 {
134 this->crypter->destroy(this->crypter);
135 this->signer->destroy(this->signer);
136 free(this);
137 }
138
139 /**
140 * See header
141 */
142 aead_t *aead_create(crypter_t *crypter, signer_t *signer)
143 {
144 private_aead_t *this;
145
146 INIT(this,
147 .public = {
148 .encrypt = _encrypt,
149 .decrypt = _decrypt,
150 .get_block_size = _get_block_size,
151 .get_icv_size = _get_icv_size,
152 .get_iv_size = _get_iv_size,
153 .get_key_size = _get_key_size,
154 .set_key = _set_key,
155 .destroy = _destroy,
156 },
157 .crypter = crypter,
158 .signer = signer,
159 );
160
161 return &this->public;
162 }