2 * Copyright (C) 2019 Sean Parkinson, wolfSSL Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 #include "wolfssl_crypter.h"
25 #include "wolfssl_common.h"
26 #include <wolfssl/wolfcrypt/aes.h>
27 #include <wolfssl/wolfcrypt/camellia.h>
28 #include <wolfssl/wolfcrypt/des3.h>
30 #include <utils/debug.h>
32 typedef struct private_wolfssl_crypter_t private_wolfssl_crypter_t
;
34 #define CTR_SALT_LEN 4
37 * Private data of wolfssl_crypter_t
39 struct private_wolfssl_crypter_t
{
42 * Public part of this class.
44 wolfssl_crypter_t
public;
50 #if !defined(NO_AES) && (!defined(NO_AES_CBC) || defined(WOLFSSL_AES_COUNTER))
63 * Encryption algorithm identifier
65 encryption_algorithm_t alg
;
88 METHOD(crypter_t
, decrypt
, bool,
89 private_wolfssl_crypter_t
*this, chunk_t data
, chunk_t iv
, chunk_t
*dst
)
94 u_char nonce
[AES_BLOCK_SIZE
] = {0};
95 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
96 chunk_t d
= chunk_empty
;
102 *dst
= chunk_alloc(data
.len
);
106 if (this->salt
.len
> 0)
108 memcpy(nonce
, this->salt
.ptr
, this->salt
.len
);
109 memcpy(nonce
+ this->salt
.len
, iv
.ptr
, this->iv_size
);
110 nonce
[AES_BLOCK_SIZE
- 1] = 1;
116 memcpy(out
, data
.ptr
, data
.len
);
119 #if !defined(NO_AES) && !defined(NO_AES_CBC)
121 ret
= wc_AesSetKey(&this->cipher
.aes
, this->key
.ptr
, this->key
.len
,
122 iv
.ptr
, AES_DECRYPTION
);
125 ret
= wc_AesCbcDecrypt(&this->cipher
.aes
, out
, data
.ptr
,
128 success
= (ret
== 0);
131 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
135 d
= chunk_alloc(data
.len
);
138 ret
= wc_AesSetKeyDirect(&this->cipher
.aes
, this->key
.ptr
,
139 this->key
.len
, nonce
, AES_ENCRYPTION
);
142 ret
= wc_AesCtrEncrypt(&this->cipher
.aes
, out
, data
.ptr
,
145 if (ret
== 0 && out
== d
.ptr
)
147 memcpy(data
.ptr
, out
, data
.len
);
150 success
= (ret
== 0);
154 case ENCR_CAMELLIA_CBC
:
155 ret
= wc_CamelliaSetKey(&this->cipher
.camellia
, this->key
.ptr
,
156 this->key
.len
, iv
.ptr
);
159 ret
= wc_CamelliaCbcDecrypt(&this->cipher
.camellia
, out
,
162 success
= (ret
== 0);
167 ret
= wc_Des3_SetKey(&this->cipher
.des3
, this->key
.ptr
, iv
.ptr
,
171 ret
= wc_Des3_CbcDecrypt(&this->cipher
.des3
, out
, data
.ptr
,
174 success
= (ret
== 0);
177 ret
= wc_Des_SetKey(&this->cipher
.des
, this->key
.ptr
, iv
.ptr
,
181 ret
= wc_Des_CbcDecrypt(&this->cipher
.des
, out
, data
.ptr
,
187 #ifdef WOLFSSL_DES_ECB
189 ret
= wc_Des_SetKey(&this->cipher
.des
, this->key
.ptr
, iv
.ptr
,
193 ret
= wc_Des_EcbDecrypt(&this->cipher
.des
, out
, data
.ptr
,
196 success
= (ret
== 0);
204 memwipe(nonce
, sizeof(nonce
));
208 METHOD(crypter_t
, encrypt
, bool,
209 private_wolfssl_crypter_t
*this, chunk_t data
, chunk_t iv
, chunk_t
*dst
)
212 bool success
= FALSE
;
214 u_char nonce
[AES_BLOCK_SIZE
] = {0};
215 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
216 chunk_t d
= chunk_empty
;
222 *dst
= chunk_alloc(data
.len
);
226 if (this->salt
.len
> 0)
228 memcpy(nonce
, this->salt
.ptr
, this->salt
.len
);
229 memcpy(nonce
+ this->salt
.len
, iv
.ptr
, this->iv_size
);
230 nonce
[AES_BLOCK_SIZE
- 1] = 1;
236 memcpy(out
, data
.ptr
, data
.len
);
239 #if !defined(NO_AES) && !defined(NO_AES_CBC)
241 ret
= wc_AesSetKey(&this->cipher
.aes
, this->key
.ptr
, this->key
.len
,
242 iv
.ptr
, AES_ENCRYPTION
);
245 ret
= wc_AesCbcEncrypt(&this->cipher
.aes
, out
, data
.ptr
,
248 success
= (ret
== 0);
251 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
255 d
= chunk_alloc(data
.len
);
258 ret
= wc_AesSetKeyDirect(&this->cipher
.aes
, this->key
.ptr
,
259 this->key
.len
, nonce
, AES_ENCRYPTION
);
262 ret
= wc_AesCtrEncrypt(&this->cipher
.aes
, out
, data
.ptr
,
265 if (ret
== 0 && out
== d
.ptr
)
267 memcpy(data
.ptr
, out
, data
.len
);
270 success
= (ret
== 0);
274 case ENCR_CAMELLIA_CBC
:
275 ret
= wc_CamelliaSetKey(&this->cipher
.camellia
, this->key
.ptr
,
276 this->key
.len
, iv
.ptr
);
279 ret
= wc_CamelliaCbcEncrypt(&this->cipher
.camellia
, out
,
282 success
= (ret
== 0);
287 ret
= wc_Des3_SetKey(&this->cipher
.des3
, this->key
.ptr
, iv
.ptr
,
291 ret
= wc_Des3_CbcEncrypt(&this->cipher
.des3
, out
, data
.ptr
,
294 success
= (ret
== 0);
297 ret
= wc_Des_SetKey(&this->cipher
.des
, this->key
.ptr
, iv
.ptr
,
301 ret
= wc_Des_CbcEncrypt(&this->cipher
.des
, out
, data
.ptr
,
304 success
= (ret
== 0);
306 #ifdef WOLFSSL_DES_ECB
308 ret
= wc_Des_SetKey(&this->cipher
.des
, this->key
.ptr
, iv
.ptr
,
312 ret
= wc_Des_EcbEncrypt(&this->cipher
.des
, out
, data
.ptr
,
315 success
= (ret
== 0);
326 METHOD(crypter_t
, get_block_size
, size_t,
327 private_wolfssl_crypter_t
*this)
329 return this->block_size
;
332 METHOD(crypter_t
, get_iv_size
, size_t,
333 private_wolfssl_crypter_t
*this)
335 return this->iv_size
;
338 METHOD(crypter_t
, get_key_size
, size_t,
339 private_wolfssl_crypter_t
*this)
341 return this->key
.len
+ this->salt
.len
;
344 METHOD(crypter_t
, set_key
, bool,
345 private_wolfssl_crypter_t
*this, chunk_t key
)
347 if (key
.len
!= get_key_size(this))
351 memcpy(this->salt
.ptr
, key
.ptr
+ key
.len
- this->salt
.len
, this->salt
.len
);
352 memcpy(this->key
.ptr
, key
.ptr
, this->key
.len
);
356 METHOD(crypter_t
, destroy
, void,
357 private_wolfssl_crypter_t
*this)
359 chunk_clear(&this->key
);
360 chunk_clear(&this->salt
);
363 #if !defined(NO_AES) && !defined(NO_AES_CBC)
365 wc_AesFree(&this->cipher
.aes
);
368 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
370 wc_AesFree(&this->cipher
.aes
);
375 wc_Des3Free(&this->cipher
.des3
);
385 * Described in header
387 wolfssl_crypter_t
*wolfssl_crypter_create(encryption_algorithm_t algo
,
390 private_wolfssl_crypter_t
*this;
403 #if !defined(NO_AES) && !defined(NO_AES_CBC)
413 block_size
= AES_BLOCK_SIZE
;
414 iv_size
= AES_IV_SIZE
;
421 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
433 salt_len
= CTR_SALT_LEN
;
441 case ENCR_CAMELLIA_CBC
:
450 block_size
= CAMELLIA_BLOCK_SIZE
;
451 iv_size
= CAMELLIA_BLOCK_SIZE
;
464 block_size
= DES_BLOCK_SIZE
;
465 iv_size
= DES_BLOCK_SIZE
;
468 #ifdef WOLFSSL_DES_ECB
475 block_size
= DES_BLOCK_SIZE
;
476 iv_size
= DES_BLOCK_SIZE
;
488 .get_block_size
= _get_block_size
,
489 .get_iv_size
= _get_iv_size
,
490 .get_key_size
= _get_key_size
,
496 .block_size
= block_size
,
502 #if !defined(NO_AES) && !defined(NO_AES_CBC)
504 ret
= wc_AesInit(&this->cipher
.aes
, NULL
, INVALID_DEVID
);
507 #if !defined(NO_AES) && defined(WOLFSSL_AES_COUNTER)
509 ret
= wc_AesInit(&this->cipher
.aes
, NULL
, INVALID_DEVID
);
514 ret
= wc_Des3Init(&this->cipher
.des3
, NULL
, INVALID_DEVID
);
526 this->key
= chunk_alloc(key_size
);
527 this->salt
= chunk_alloc(salt_len
);
529 return &this->public;