cbcmode.h
7.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
/*
* Copyright (C) 2013 Freie Universität Berlin, Computer Systems & Telematics
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup sys_crypto
* @{
*
* @file
* @brief Headers of the implementation of the CBC Mode of Operation
*
* Implementation of the CBC Mode of Operation with Ciphertext-Stealing for encryption.
*
* @author Freie Universitaet Berlin, Computer Systems & Telematics.
* @author Nicolai Schmittberger <nicolai.schmittberger@fu-berlin.de>
* @author Zakaria Kasmi <zkasmi@inf.fu-berlin.de>
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#ifndef CBCMODE_H_
#define CBCMODE_H_
#include "crypto/ciphers.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MIN(a, b) ( ((a) < (b)) ? (a) : (b))
#define DBG_CRYPTO 1
enum {
// we allocate some static buffers on the stack; they have to be less
// than this size
CBCMODE_MAX_BLOCK_SIZE = 8,
CBCMODE_MAX_BLOCK_SIZE_AES = 16
};
/*// We run a simple state machine in the incremental decrypt:
//
// +--> ONE_BLOCK
// |
// ---|
// |
// +--> GENERAL --+---> TWO_LEFT_A ----> TWO_LEFT_B
// ^ |
// | |
// +------+
*/
enum {
ONE_BLOCK,
GENERAL,
TWO_LEFT_A,
TWO_LEFT_B
};
#define FAIL 0
#define SUCCESS 1
/**
* @brief The context for processing the en-/decryption in the CBC-Mode with
* CTS
*
* @param spill1 test1
*/
typedef struct CBCModeContext {
/** Spill-Block 1 for temporary usage */
uint8_t spill1 [CBCMODE_MAX_BLOCK_SIZE ];
/** Spill-Block 2 for temporary usage */
uint8_t spill2 [CBCMODE_MAX_BLOCK_SIZE ];
/** the blocksize currently used */
uint8_t bsize;
/** how many more bytes of ciphertext do we need to recv */
uint16_t remaining;
/** how many bytes of plaintext we've deciphered. */
uint16_t completed;
/** TRUE iff spill1 is the accumulator and spill2 holds prev cipher text. */
/** false o.w. */
uint8_t accum;
/** into the accumulator */
uint8_t offset;
/** state enum */
uint8_t state;
} /*__attribute__ ((packed)) */ CBCModeContext;
/*
* @brief Initialize the Mode. It uses the underlying BlockCipher's
* preferred block cipher mode, and passes the key and keySize
* parameters to the underlying BlockCipher.
*
* @param context structure to hold the opaque data from this
* initialization call. It should be passed to future
* invocations of this module which use this particular key.
* It also contains the opaque context for the underlying
* BlockCipher as well.
* @param keySize key size in bytes
* @param key pointer to the key
*
* @return Whether initialization was successful. The command may be
* unsuccessful if the key size is not valid for the given cipher
* implementation. It can also fail if the preferred block size of
* the cipher does not agree with the preferred size of the mode.
*/
int block_cipher_mode_init(CipherModeContext *context, uint8_t key_size,
uint8_t *key);
/**
* @brief same as BlockCipherMode_init but with the possibility to specify
* the index of the cipher in the archive
*
* @param context structure to hold the opaque data from this
* initialization call. It should be passed to future
* invocations of this module which use this particular
* key. It also contains the opaque context for the
* underlying BlockCipher as well.
* @param key_size key size in bytes.
* @param key pointer to the key.
* @param cipher_index the index of the cipher-algorithm to init in the
* (cipher-)archive
*
* @return Whether initialization was successful. The command may be
* unsuccessful if the key size is not valid for the given cipher
* implementation. It can also fail if the preferred block size of
* the cipher does not agree with the preferred size of the mode.
*/
int block_cipher_mode_init0(CipherModeContext *context, uint8_t key_size,
uint8_t *key, uint8_t cipher_index);
/**
* @brief prints the debug-messages passed by @ref dump_buffer
*
* @param mode the mode of the debug-message
* @param format pointer to the message
*/
void dbg(uint8_t mode, const char *format, ...);
/**
* @brief dumps the passed buffer to the console
*
* @param bufName pointer to the name of the buffer
* @param buf pointer to the buffer itself
* @param size the size of the buffer in bytes
*/
void dump_buffer(char *bufName, uint8_t *buf, uint8_t size);
/**
* @brief Encrypts num_bytes of plaintext blocks (each of size blockSize)
* using the key from the init phase. The IV is a pointer to the
* initialization vector (of size equal to the blockSize) which is
* used to initialize the encryption.
* In place encryption should work provided that the plain and and
* cipher buffer are the same. (they may either be the same or
* non-overlapping. partial overlaps are not supported).
*
* @param context context object for this encryption
* @param plain_blocks a plaintext block numBlocks, where each block is of
* blockSize bytes
* @param cipher_blocks an array of numBlocks * blockSize bytes to hold the
* resulting cyphertext
* @param num_bytes number of data blocks to encrypt
* @param IV an array of the initialization vector. It should be
* of block size bytes
*
* @return Whether the encryption was successful. Possible failure reasons
* include not calling init().
*/
int block_cipher_mode_encrypt(CipherModeContext *context, uint8_t *plain_blocks,
uint8_t *cipher_blocks, uint16_t num_bytes,
uint8_t *IV);
/**
* @brief Decrypts num_bytes of ciphertext blocks (each of size blockSize)
* using the key from the init phase. The IV is a pointer to the
* initialization vector (of size equal to the blockSize) which is
* used to initialize the decryption.
* In place decryption should work provided that the plain and and
* cipher buffer are the same. (they may either be the same or
* non-overlapping. partial overlaps are not supported).
*
* @param context context object for this decryption
* @param cipher_blocks an array of num_bytes * blockSize bytes that holds
* the cipher text
* @param plain_blocks an array of num_bytes * blockSize bytes to hold the
* resulting plaintext.
* @param num_bytes number of data blocks to encrypt
* @param IV an array of the initialization vector. It should be
* of block size bytes
*
* @return Whether the decryption was successful. Possible failure reasons
* include not calling init().
*/
int block_cipher_mode_decrypt(CipherModeContext *context,
uint8_t *cipher_blocks,
uint8_t *plain_blocks,
uint16_t num_bytes,
uint8_t *IV);
#ifdef __cplusplus
}
#endif
/** @} */
#endif /* CBCMODE_H_ */