1 /* ===================================================================
2  *
3  * Copyright (c) 2014, Legrandin <helderijs@gmail.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in
14  *    the documentation and/or other materials provided with the
15  *    distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21  * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  * ===================================================================
30  */
31 
32 #include <stdlib.h>
33 
34 #include "block_base.h"
35 
36 #define CIPHER_STATE_TYPE       _PASTE2(MODULE_NAME, _State)
37 #define CIPHER_ENCRYPT          _PASTE2(MODULE_NAME, _encrypt)
38 #define CIPHER_DECRYPT          _PASTE2(MODULE_NAME, _decrypt)
39 #define CIPHER_STOP_OPERATION   _PASTE2(MODULE_NAME, _stop_operation)
40 #define CIPHER_START_OPERATION  _PASTE2(MODULE_NAME, _start_operation)
41 
42 typedef struct {
43     BlockBase  base_state;
44     struct block_state algo_state;
45 } CIPHER_STATE_TYPE;
46 
47 static int CIPHER_ENCRYPT
48            (const BlockBase *state, const uint8_t *in, uint8_t *out, size_t data_len)
49 {
50     size_t block_len;
51 
52     if ((state == NULL) || (in == NULL) || (out == NULL))
53         return ERR_NULL;
54 
55     block_len = state->block_len;
56 
57     for (; data_len>=block_len; data_len-=block_len) {
58         block_encrypt(&((CIPHER_STATE_TYPE*)state)->algo_state, (uint8_t*)in, out);
59         in += block_len;
60         out += block_len;
61     }
62 
63     if (data_len)
64         return ERR_NOT_ENOUGH_DATA;
65 
66     return 0;
67 }
68 
69 static int CIPHER_DECRYPT
70            (const BlockBase *state, const uint8_t *in, uint8_t *out, size_t data_len)
71 {
72     size_t block_len;
73 
74     if ((state == NULL) || (in == NULL) || (out == NULL))
75         return ERR_NULL;
76 
77     block_len = state->block_len;
78 
79     for (; data_len>=block_len; data_len-=block_len) {
80         block_decrypt(&((CIPHER_STATE_TYPE*)state)->algo_state, (uint8_t*)in, out);
81         in += block_len;
82         out += block_len;
83     }
84 
85     if (data_len)
86         return ERR_NOT_ENOUGH_DATA;
87 
88     return 0;
89 }
90 
91 EXPORT_SYM int CIPHER_STOP_OPERATION(BlockBase *state)
92 {
93     if (NULL == state)
94         return ERR_NULL;
95 
96     block_finalize(&((CIPHER_STATE_TYPE*)state)->algo_state);
97     free(state);
98     return 0;
99 }
100 
101 #ifndef NON_STANDARD_START_OPERATION
102 EXPORT_SYM int CIPHER_START_OPERATION(const uint8_t key[], size_t key_len, CIPHER_STATE_TYPE **pResult)
103 {
104     BlockBase *block_base;
105     int res;
106 
107     if ((key == NULL) || (pResult == NULL))
108         return ERR_NULL;
109 
110     *pResult = calloc(1, sizeof(CIPHER_STATE_TYPE));
111     if (NULL == *pResult)
112         return ERR_MEMORY;
113 
114     block_base = &((*pResult)->base_state);
115     block_base->encrypt = &CIPHER_ENCRYPT;
116     block_base->decrypt = &CIPHER_DECRYPT;
117     block_base->destructor = &CIPHER_STOP_OPERATION;
118     block_base->block_len = BLOCK_SIZE;
119 
120     res = block_init(&(*pResult)->algo_state, (unsigned char*)key, key_len);
121     if (res) {
122         free(*pResult);
123         *pResult = NULL;
124     }
125 
126     return res;
127 }
128 #endif
129