Add a return value to aead_t.encrypt()
[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, bool,
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 return TRUE;
64 }
65
66 METHOD(aead_t, decrypt, bool,
67 private_aead_t *this, chunk_t encrypted, chunk_t assoc, chunk_t iv,
68 chunk_t *plain)
69 {
70 chunk_t sig;
71 size_t bs;
72
73 bs = this->crypter->get_block_size(this->crypter);
74 sig.len = this->signer->get_block_size(this->signer);
75 if (sig.len > encrypted.len || (encrypted.len - sig.len) % bs)
76 {
77 DBG1(DBG_LIB, "invalid encrypted data length %d with block size %d",
78 encrypted.len - sig.len, bs);
79 return FALSE;
80 }
81 chunk_split(encrypted, "mm", encrypted.len - sig.len,
82 &encrypted, sig.len, &sig);
83
84 this->signer->get_signature(this->signer, assoc, NULL);
85 this->signer->get_signature(this->signer, iv, NULL);
86 if (!this->signer->verify_signature(this->signer, encrypted, sig))
87 {
88 DBG1(DBG_LIB, "MAC verification failed");
89 return FALSE;
90 }
91 this->crypter->decrypt(this->crypter, encrypted, iv, plain);
92 return TRUE;
93 }
94
95 METHOD(aead_t, get_block_size, size_t,
96 private_aead_t *this)
97 {
98 return this->crypter->get_block_size(this->crypter);
99 }
100
101 METHOD(aead_t, get_icv_size, size_t,
102 private_aead_t *this)
103 {
104 return this->signer->get_block_size(this->signer);
105 }
106
107 METHOD(aead_t, get_iv_size, size_t,
108 private_aead_t *this)
109 {
110 return this->crypter->get_iv_size(this->crypter);
111 }
112
113 METHOD(aead_t, get_key_size, size_t,
114 private_aead_t *this)
115 {
116 return this->crypter->get_key_size(this->crypter) +
117 this->signer->get_key_size(this->signer);
118 }
119
120 METHOD(aead_t, set_key, void,
121 private_aead_t *this, chunk_t key)
122 {
123 chunk_t sig, enc;
124
125 chunk_split(key, "mm", this->signer->get_key_size(this->signer), &sig,
126 this->crypter->get_key_size(this->crypter), &enc);
127
128 this->signer->set_key(this->signer, sig);
129 this->crypter->set_key(this->crypter, enc);
130 }
131
132 METHOD(aead_t, destroy, void,
133 private_aead_t *this)
134 {
135 this->crypter->destroy(this->crypter);
136 this->signer->destroy(this->signer);
137 free(this);
138 }
139
140 /**
141 * See header
142 */
143 aead_t *aead_create(crypter_t *crypter, signer_t *signer)
144 {
145 private_aead_t *this;
146
147 INIT(this,
148 .public = {
149 .encrypt = _encrypt,
150 .decrypt = _decrypt,
151 .get_block_size = _get_block_size,
152 .get_icv_size = _get_icv_size,
153 .get_iv_size = _get_iv_size,
154 .get_key_size = _get_key_size,
155 .set_key = _set_key,
156 .destroy = _destroy,
157 },
158 .crypter = crypter,
159 .signer = signer,
160 );
161
162 return &this->public;
163 }