Blame view

RIOT/sys/include/crypto/cbcmode.h 7.59 KB
fb11e647   vrobic   reseau statique a...
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_ */