Simple Geolocalization and Course Transmission Protocol (SGCTP)
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Friends Macros Pages
payload_aes128.cpp
Go to the documentation of this file.
1 // INDENTING (emacs/vi): -*- mode:c++; tab-width:2; c-basic-offset:2; intent-tabs-mode:nil; -*- ex: set tabstop=2 expandtab:
2 
3 /*
4  * Simple Geolocalization and Course Transmission Protocol (SGCTP)
5  * Copyright (C) 2014 Cedric Dufour <http://cedric.dufour.name>
6  *
7  * The Simple Geolocalization and Course Transmission Protocol (SGCTP) is
8  * free software:
9  * you can redistribute it and/or modify it under the terms of the GNU General
10  * Public License as published by the Free Software Foundation, Version 3.
11  *
12  * The Simple Geolocalization and Course Transmission Protocol (SGCTP) is
13  * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
14  * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
15  * PARTICULAR PURPOSE.
16  *
17  * See the GNU General Public License for more details.
18  */
19 
20 // C
21 #include <errno.h>
22 #include <stdlib.h>
23 #include <string.h>
24 
25 #ifdef __SGCTP_USE_OPENSSL__
26 
27 // OpenSSL
28 #include "openssl/evp.h"
29 #include "openssl/rand.h"
30 
31 #else // __SGCTP_USE_OPENSSL__
32 
33 // GCrypt
34 #include "gcrypt.h"
35 
36 #endif // NOT __SGCTP_USE_OPENSSL__
37 
38 // SGCTP
39 #include "sgctp/data.hpp"
40 #include "sgctp/parameters.hpp"
41 #include "sgctp/payload_aes128.hpp"
42 using namespace SGCTP;
43 
44 
45 //----------------------------------------------------------------------
46 // CONSTANTS / STATIC
47 //----------------------------------------------------------------------
48 
49 #ifdef __SGCTP_USE_OPENSSL__
50 const EVP_CIPHER* CPayload_AES128::CRYPTO_CIPHER = EVP_aes_128_cbc();
51 #endif // __SGCTP_USE_OPENSSL__
52 
53 #ifdef __SGCTP_USE_OPENSSL__
54 
55 int CPayload_AES128::makeCryptoNonce( unsigned char *_pucNonce )
56 {
57  // Create crypto nonce
58  RAND_pseudo_bytes( _pucNonce, CRYPTO_NONCE_SIZE );
59 
60  // Done
61  return 0;
62 }
63 
65 {
66  return 0;
67 };
68 
69 #else // __SGCTP_USE_OPENSSL__
70 
71 int CPayload_AES128::makeCryptoNonce( unsigned char *_pucNonce )
72 {
73  int __iReturn;
74 
75  // Initialize crypto engine
76  __iReturn = initCryptoEngine();
77  if( __iReturn < 0 )
78  return __iReturn;
79 
80  // Create crypto nonce
81  gcry_create_nonce( _pucNonce, CRYPTO_NONCE_SIZE );
82 
83  // Done
84  return 0;
85 }
86 
88 {
89  if( gcry_control( GCRYCTL_INITIALIZATION_FINISHED_P ) )
90  return 0;
91  if( !gcry_check_version( "1.5.0" ) )
92  return -ENOSYS;
93  gcry_control( GCRYCTL_SUSPEND_SECMEM_WARN );
94  gcry_control( GCRYCTL_INIT_SECMEM, 16384, 0 );
95  gcry_control( GCRYCTL_RESUME_SECMEM_WARN );
96  gcry_control( GCRYCTL_INITIALIZATION_FINISHED, 0 );
97  return 0;
98 }
99 
100 #endif // NOT __SGCTP_USE_OPENSSL__
101 
102 
103 //----------------------------------------------------------------------
104 // CONSTRUCTORS / DESTRUCTOR
105 //----------------------------------------------------------------------
106 
108  : CPayload()
109  , pucBufferTmp( NULL )
110 {}
111 
113 {
114  if( pucBufferTmp )
116 }
117 
118 
119 //----------------------------------------------------------------------
120 // METHODS: CPayload (implement/override)
121 //----------------------------------------------------------------------
122 
124 {
125  if( !pucBufferTmp )
126  {
128  if( !pucBufferTmp )
129  return -ENOMEM;
130  }
131  return 0;
132 }
133 
134 int CPayload_AES128::serialize( unsigned char *_pucBuffer,
135  const CData &_roData )
136 {
137  int __iReturn;
138 
139  // Check buffer
140  if( !pucBufferTmp )
141  {
142  __iReturn = alloc();
143  if( __iReturn < 0 )
144  return __iReturn;
145  }
146 
147  // Create crypto payload
148 
149  // ... serialize raw payload
150  __iReturn = CPayload::serialize( pucBufferTmp, _roData );
151  if( __iReturn < 0 )
152  return __iReturn;
153  int __iPayloadSize_RAW = __iReturn;
154 
155  // ... add seal
156  memcpy( pucBufferTmp+__iPayloadSize_RAW, pucCryptoSeal, CRYPTO_SEAL_SIZE );
157  __iPayloadSize_RAW += CRYPTO_SEAL_SIZE;
158 
159 #ifndef __SGCTP_USE_OPENSSL__
160 
161  // ... PKCS#7 padding
162  unsigned char __ucPadLength =
163  CRYPTO_BLOCK_SIZE - __iPayloadSize_RAW % CRYPTO_BLOCK_SIZE;
164  memset( pucBufferTmp+__iPayloadSize_RAW, __ucPadLength, __ucPadLength );
165  __iPayloadSize_RAW += __ucPadLength;
166 
167 #endif // NOT __SGCTP_USE_OPENSSL__
168 
169  // Encrypt
170  int __iPayloadSize = 0;
171  unsigned char __pucCryptoIV[CRYPTO_BLOCK_SIZE];
172 
173 #ifdef __SGCTP_USE_OPENSSL__
174 
175  // ... IV
176  RAND_pseudo_bytes( __pucCryptoIV, CRYPTO_BLOCK_SIZE );
177  memcpy( _pucBuffer, __pucCryptoIV, CRYPTO_BLOCK_SIZE );
178  __iPayloadSize += CRYPTO_BLOCK_SIZE;
179 
180  // ... cipher
181  int __iLength;
182  EVP_CIPHER_CTX __evpCipherCtx;
183  EVP_CIPHER_CTX_init( &__evpCipherCtx );
184  EVP_EncryptInit_ex( &__evpCipherCtx,
185  CRYPTO_CIPHER, NULL,
186  pucCryptoKey, __pucCryptoIV );
187  EVP_EncryptUpdate( &__evpCipherCtx,
188  _pucBuffer+__iPayloadSize, &__iLength,
189  pucBufferTmp, __iPayloadSize_RAW );
190  __iPayloadSize += __iLength;
191  EVP_EncryptFinal_ex( &__evpCipherCtx,
192  _pucBuffer+__iPayloadSize, &__iLength );
193  __iPayloadSize += __iLength;
194  EVP_CIPHER_CTX_cleanup( &__evpCipherCtx );
195 
196 #else // __SGCTP_USE_OPENSSL__
197 
198  // ... IV
199  gcry_create_nonce( __pucCryptoIV, CRYPTO_BLOCK_SIZE );
200  memcpy( _pucBuffer, __pucCryptoIV, CRYPTO_BLOCK_SIZE );
201  __iPayloadSize += CRYPTO_BLOCK_SIZE;
202 
203  // ... cipher
204  gcry_cipher_hd_t __gcryCipherHd;
205  gcry_cipher_open( &__gcryCipherHd, CRYPTO_CIPHER, CRYPTO_MODE, 0 );
206  gcry_cipher_setkey( __gcryCipherHd,
208  gcry_cipher_setiv( __gcryCipherHd,
209  __pucCryptoIV, CRYPTO_BLOCK_SIZE );
210  gcry_cipher_encrypt( __gcryCipherHd,
211  _pucBuffer+__iPayloadSize, BUFFER_SIZE-__iPayloadSize,
212  pucBufferTmp, __iPayloadSize_RAW );
213  __iPayloadSize += __iPayloadSize_RAW;
214  gcry_cipher_close( __gcryCipherHd );
215 
216 #endif // NOT __SGCTP_USE_OPENSSL__
217 
218  // Done
219  return __iPayloadSize;
220 }
221 
223  const unsigned char *_pucBuffer,
224  uint16_t _ui16tBufferSize )
225 {
226  int __iReturn;
227 
228  // Check buffer
229  if( _ui16tBufferSize-CRYPTO_BLOCK_SIZE > BUFFER_SIZE )
230  return -EOVERFLOW;
231  if( !pucBufferTmp )
232  {
233  __iReturn = alloc();
234  if( __iReturn < 0 )
235  return __iReturn;
236  }
237 
238  // Decrypt
239  int __iPayloadSize = 0;
240  unsigned char __pucCryptoIV[CRYPTO_BLOCK_SIZE];
241 
242  // ... IV
243  memcpy( __pucCryptoIV, _pucBuffer, CRYPTO_BLOCK_SIZE );
244  __iPayloadSize += CRYPTO_BLOCK_SIZE;
245 
246 #ifdef __SGCTP_USE_OPENSSL__
247 
248  // ... cipher
249  int __iLength;
250  EVP_CIPHER_CTX __evpCipherCtx;
251  EVP_CIPHER_CTX_init( &__evpCipherCtx );
252  EVP_DecryptInit_ex( &__evpCipherCtx,
253  CRYPTO_CIPHER, NULL,
254  pucCryptoKey, __pucCryptoIV );
255  EVP_DecryptUpdate( &__evpCipherCtx,
256  pucBufferTmp, &__iLength,
257  _pucBuffer+__iPayloadSize,
258  _ui16tBufferSize-CRYPTO_BLOCK_SIZE );
259  __iPayloadSize += __iLength;
260  EVP_DecryptFinal_ex( &__evpCipherCtx,
261  pucBufferTmp+__iPayloadSize, &__iLength );
262  __iPayloadSize += __iLength;
263  EVP_CIPHER_CTX_cleanup( &__evpCipherCtx );
264 
265 #else // __SGCTP_USE_OPENSSL__
266 
267  // ... cipher
268  gcry_cipher_hd_t __gcryCipherHd;
269  gcry_cipher_open( &__gcryCipherHd, CRYPTO_CIPHER, CRYPTO_MODE, 0 );
270  gcry_cipher_setkey( __gcryCipherHd,
272  gcry_cipher_setiv( __gcryCipherHd,
273  __pucCryptoIV, CRYPTO_BLOCK_SIZE );
274  gcry_cipher_decrypt( __gcryCipherHd,
276  _pucBuffer+__iPayloadSize,
277  _ui16tBufferSize-CRYPTO_BLOCK_SIZE );
278  __iPayloadSize += _ui16tBufferSize-CRYPTO_BLOCK_SIZE;
279  gcry_cipher_close( __gcryCipherHd );
280 
281 #endif // NOT __SGCTP_USE_OPENSSL__
282 
283  // Extract crypto payload
284  int __iPayloadSize_RAW = __iPayloadSize-CRYPTO_BLOCK_SIZE;
285 
286 #ifndef __SGCTP_USE_OPENSSL__
287 
288  // ... PKCS#7 padding
289  unsigned char __ucPadLength = pucBufferTmp[__iPayloadSize_RAW-1];
290  __iPayloadSize_RAW -= __ucPadLength;
291 
292 #endif // __SGCTP_USE_OPENSSL__
293 
294  // ... check seal
295  __iPayloadSize_RAW -= CRYPTO_SEAL_SIZE;
296  __iReturn = memcmp( pucBufferTmp+__iPayloadSize_RAW,
299  if( __iReturn )
300  return -EBADE;
301 
302  // ... unserialize raw payload
303  __iReturn = CPayload::unserialize( _poData,
304  pucBufferTmp,
305  __iPayloadSize_RAW );
306  if( __iReturn <= 0 )
307  return __iReturn;
308 
309  // Done
310  return __iPayloadSize;
311 }
312 
314 {
315  if( pucBufferTmp )
317  pucBufferTmp = NULL;
318 }
319 
320 
321 //----------------------------------------------------------------------
322 // METHODS
323 //----------------------------------------------------------------------
324 
325 int CPayload_AES128::makeCryptoKey( const unsigned char *_pucPassword,
326  int _iPasswordLength,
327  const unsigned char *_pucNonce )
328 {
329  int __iReturn;
330 
331  // Initialize crypto engine
332  __iReturn = initCryptoEngine();
333  if( __iReturn < 0 )
334  return __iReturn;
335 
336  // Save nonce
337  memcpy( pucCryptoNonce,
338  _pucNonce,
340 
341  // Create crypto key and seal
342  unsigned char __pucCryptoMaterial[CRYPTO_KEY_SIZE+CRYPTO_SEAL_SIZE];
343 
344 #ifdef __SGCTP_USE_OPENSSL__
345 
346  PKCS5_PBKDF2_HMAC_SHA1( _pucPassword, _iPasswordLength,
350  __pucCryptoMaterial );
351 
352 #else // __SGCTP_USE_OPENSSL__
353 
354  gcry_kdf_derive( _pucPassword, _iPasswordLength,
355  GCRY_KDF_PBKDF2, GCRY_MD_SHA1,
359  __pucCryptoMaterial );
360 
361 #endif // NOT __SGCTP_USE_OPENSSL__
362 
363  // Save key and seal
364  memcpy( pucCryptoKey,
365  __pucCryptoMaterial,
366  CRYPTO_KEY_SIZE );
367  memcpy( pucCryptoSeal,
368  __pucCryptoMaterial+CRYPTO_KEY_SIZE,
370 
371  // Done
372  return 0;
373 }
374 
376 {
377  // Initialize crypto engine
378  // -> let's skip this; it MUST have been done in makeCryptoKey
379 
380  // Create crypto key and seal
381  unsigned char __pucCryptoMaterial[CRYPTO_KEY_SIZE+CRYPTO_SEAL_SIZE];
382 
383 #ifdef __SGCTP_USE_OPENSSL__
384 
385  PKCS5_PBKDF2_HMAC_SHA1( pucCryptoKey, CRYPTO_KEY_SIZE,
387  1,
389  __pucCryptoMaterial );
390 
391 #else // __SGCTP_USE_OPENSSL__
392 
393  gcry_kdf_derive( pucCryptoKey, CRYPTO_KEY_SIZE,
394  GCRY_KDF_PBKDF2, GCRY_MD_SHA1,
396  1,
398  __pucCryptoMaterial );
399 
400 #endif // NOT __SGCTP_USE_OPENSSL__
401 
402  // Save key and seal
403  memcpy( pucCryptoKey,
404  __pucCryptoMaterial,
405  CRYPTO_KEY_SIZE );
406  memcpy( pucCryptoSeal,
407  __pucCryptoMaterial+CRYPTO_KEY_SIZE,
409 
410  // Done
411  return 0;
412 }
virtual int unserialize(CData *_poData, const unsigned char *_pucBuffer, uint16_t _ui16tBufferSize)
Unserialize the SGCTP data from the given payload buffer.
Definition: payload.cpp:355
int makeCryptoKey(const unsigned char *_pucPassword, int _iPasswordLength, const unsigned char *_pucNonce)
Create cryptographic key (and seal)
int incrCryptoKey()
Increment cryptographic key (and seal)
static const uint16_t CRYPTO_KEY_ITER
virtual int alloc()
Allocate resources for payload (un-)serialization.
static const uint16_t BUFFER_SIZE
Buffer size required for payload (un-)serialization.
Definition: payload.hpp:50
static void freeBuffer(unsigned char *_pucBuffer)
Free a buffer allocated for payload (un-)serialization.
Definition: payload.hpp:79
static const uint16_t CRYPTO_SEAL_SIZE
static const uint16_t CRYPTO_KEY_SIZE
static const uint16_t CRYPTO_NONCE_SIZE
SGCTP data container.
Definition: data.hpp:44
unsigned char pucCryptoKey[CRYPTO_BLOCK_SIZE]
Cryptographic key (used for encryption/decryption)
virtual int serialize(unsigned char *_pucBuffer, const CData &_roData)
Serialize the given SGCTP data into the given payload buffer.
Definition: payload.cpp:93
static const int CRYPTO_CIPHER
unsigned char pucCryptoSeal[CRYPTO_SEAL_SIZE]
Cryptographic seal (used to check valid decryption)
static int initCryptoEngine()
Initialize cryptographic engine.
(Raw) SGCTP payload
Definition: payload.hpp:41
static int makeCryptoNonce(unsigned char *_pucNonce)
Create cryptographic nonce.
virtual int unserialize(CData *_poData, const unsigned char *_pucBuffer, uint16_t _ui16tBufferSize)
Unserialize the SGCTP data from the given payload buffer.
virtual int serialize(unsigned char *_pucBuffer, const CData &_roData)
Serialize the given SGCTP data into the given payload buffer.
static const uint16_t CRYPTO_BLOCK_SIZE
unsigned char * pucBufferTmp
Payload temporary import/export buffer.
virtual void free()
Free resources for payload (un-)serialization.
static const int CRYPTO_MODE
unsigned char pucCryptoNonce[CRYPTO_NONCE_SIZE]
Cryptographic nonce (used for cryptographic hashing)
static unsigned char * allocBuffer()
Allocate a buffer for payload (un-)serialization.
Definition: payload.hpp:61