- initial version
*/
+#include <openssl/evp.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include "def.h"
+
#include "cryptomod.h"
#include "pdu_channel.h"
#include "pdu_clear_data.h"
uint8_t channels[NB_CHANNELS] = {0};
int encrypt_func (CLEAR_DATA_t *in, ENCRYPTED_DATA_t *out)
+
{
VERBOSE (crypto, TRACE, PRINTF ("encrypt_func\n"));
/* channel id */
out->channel_id = in->channel_id;
- /* draw iv */
- int iv_len = sizeof (out->iv);
- for (int i = 0, r = 0; i < iv_len; i++) {
- if (i % 4) {
- r = rand ();
- }
- out->iv[i] = r & 0xff;
- r >>= 8;
- }
-
/* copy bypass */
#ifndef PROTOCOL_EXT
if (in->bypass_len) {
out->bypass_len = in->bypass_len;
#endif
+ /* get add */
+ int aad_len = sizeof (in->aad);
+
+ /* draw iv */
+ int iv_len = sizeof (out->iv);
+ for (int i = 0, r = 0; i < iv_len; i++) {
+ if (i % 4) {
+ r = rand ();
+ }
+ out->iv[i] = r & 0xff;
+ r >>= 8;
+ }
+
/* scramble with iv */
for (int i = 0; i < in->data_len; i++) {
out->data[i] = (in->data[i] ^ out->iv[i % iv_len]) & 0xff;
}
out->data_len = in->data_len;
- /* encrypt with key */
+ /* look for key */
int cid = in->channel_id;
int kid = channels[cid] - 1;
+ uint8_t key[KEY_LENGTH] = {0};
if (kid >= 0) {
// FIXIT: not thread safe
- uint8_t *key = keys[kid];
int klen = key_lengths[kid];
- for (int i = 0; i < out->data_len; i++) {
- out->data[i] = (out->data[i] ^ key[i % klen]) & 0xff;
- }
+ if (klen != KEY_LENGTH) {
+ VERBOSE (crypto, WARNING, PRINTF ("incorrect key length (%d)\n", klen));
+ }
+ memset (key, 0, (klen > KEY_LENGTH) ? KEY_LENGTH : klen);
} else {
- VERBOSE (crypto, WARNING, PRINTF ("no key associated to channel %d (%d))\n", cid, kid));
+ VERBOSE (crypto, WARNING, PRINTF ("no key associated to channel %d (%d)\n", cid, kid));
}
- usleep (200); // simulate cpu time
+ /* encrypt message */
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_EncryptInit_ex (ctx, EVP_aes_256_gcm (), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL);
+ EVP_EncryptInit_ex (ctx, NULL, NULL, key, out->iv);
+ int out_len = 0;
+ if (aad_len) {
+ EVP_EncryptUpdate (ctx, NULL, &out_len, in->aad, aad_len);
+ }
+ EVP_EncryptUpdate (ctx, out->data, &out_len, in->data, in->data_len);
+ out->data_len = out_len;
+ if (EVP_EncryptFinal_ex (ctx, out->data + out->data_len, &out_len)) {
+ out->data_len += out_len;
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_GET_TAG, TAG_LENGTH, (void *)(out->data + out->data_len));
+ out->data_len += TAG_LENGTH;
+ } else {
+ //memset (out->data, 0, out->data_len);
+ out->data_len = 0;
+ }
+ EVP_CIPHER_CTX_free (ctx);
state = ready_e;
/* channel id */
out->channel_id = in->channel_id;
- /* get iv */
- int iv_len = sizeof (in->iv);
-
/* copy bypass */
#ifndef PROTOCOL_EXT
if (in->bypass_len) {
out->bypass_len = in->bypass_len;
#endif
- /* scramble with iv */
- for (int i = 0; i < in->data_len; i++) {
- out->data[i] = (in->data[i] ^ in->iv[i % iv_len]) & 0xff;
- }
- out->data_len = in->data_len;
+ /* get aad */
+ int aad_len = sizeof (in->aad);
+
+ /* get iv */
+ int iv_len = sizeof (in->iv);
- /* decrypt with key */
+ /* look for key */
int cid = in->channel_id;
int kid = channels[cid] - 1;
+ uint8_t key[KEY_LENGTH] = {0};
if (kid >= 0) {
// FIXIT: not thread safe
- uint8_t *key = keys[kid];
int klen = key_lengths[kid];
- for (int i = 0; i < out->data_len; i++) {
- out->data[i] = (out->data[i] ^ key[i % klen]) & 0xff;
+ if (klen != KEY_LENGTH) {
+ VERBOSE (crypto, WARNING, PRINTF ("incorrect key length (%d)\n", klen));
}
+ memset (key, 0, (klen > KEY_LENGTH) ? KEY_LENGTH : klen);
} else {
VERBOSE (crypto, WARNING, PRINTF ("no key associated to channel %d (%d)\n", cid, kid));
}
- usleep (200); // simulate cpu time
+ /* decrypt message */
+ EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
+ EVP_DecryptInit_ex (ctx, EVP_aes_256_gcm (), NULL, NULL, NULL);
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_GCM_SET_IVLEN, iv_len, NULL);
+ if (EVP_DecryptInit_ex (ctx, NULL, NULL, key, in->iv)) {
+ EVP_CIPHER_CTX_ctrl (ctx, EVP_CTRL_AEAD_SET_TAG, TAG_LENGTH, (void *)(in->data + in->data_len - TAG_LENGTH));
+ }
+ int out_len = 0;
+ if (aad_len) {
+ EVP_DecryptUpdate (ctx, NULL, &out_len, in->aad, aad_len);
+ }
+ if (!EVP_DecryptUpdate (ctx, out->data, &out_len, in->data, in->data_len - TAG_LENGTH)) {
+ VERBOSE (crypto, DEBUG, PRINTF ("decrypt error\n"));
+ memset (out->data, 0, out_len);
+ out->data_len = 0;
+ } else {
+ out->data_len = out_len;
+ EVP_DecryptFinal_ex (ctx, NULL, &out_len);
+ out->data_len += out_len;
+ }
+ EVP_CIPHER_CTX_free (ctx);
state = ready_e;