#include "def.h"
#include "cryptomod.h"
+#include "pdu_bypass.h"
#include "pdu_channel.h"
#include "pdu_clear_data.h"
#include "pdu_encrypted_data.h"
uint8_t channels[NB_CHANNELS] = {0};
+int content_filter (BYPASS_t *in)
+{
+ int rc = 1;
+
+ switch (in->id) {
+ case 0: /* bypass message 0 */
+ rc = 0;
+ break;
+ }
+
+ return rc;
+}
+
int encrypt_func (CLEAR_DATA_t *in, ENCRYPTED_DATA_t *out)
{
VERBOSE (crypto, TRACE, PRINTF ("encrypt_func\n"));
+ // FIXIT: not thread safe
state = working_e;
/* channel id */
out->channel_id = in->channel_id;
- /* copy bypass */
+ /* filter bypass */
#ifndef PROTOCOL_EXT
if (in->bypass_len) {
- VERBOSE (cryptomod, WARNING, PRINTF ("not supproted by this protocol\n"));
+ VERBOSE (crypto, WARNING, PRINTF ("bypass not supproted by this protocol\n"));
}
- out->bypass_len = 0
+ out->bypass_len = 0;
#else
- memcpy (out->bypass, in->bypass, in->bypass_len * sizeof (uint8_t));
- out->bypass_len = in->bypass_len;
+ BYPASS_t pdu_bypass = {0};
+ deserial_bypass (in->bypass, in->bypass_len, &pdu_bypass);
+ if (content_filter (&pdu_bypass)) {
+ VERBOSE (crypto, WARNING, PRINTF ("bypass message filtered\n"));
+ out->bypass_len = 0;
+ } else {
+ memcpy (out->bypass, in->bypass, in->bypass_len * sizeof (uint8_t));
+ out->bypass_len = in->bypass_len;
+ }
#endif
/* get add */
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;
-
/* look for key */
int cid = in->channel_id;
int kid = channels[cid] - 1;
}
EVP_EncryptUpdate (ctx, out->data, &out_len, in->data, in->data_len);
out->data_len = out_len;
+ int rc = 0;
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);
+ VERBOSE (crypto, WARNING, PRINTF ("encryption error\n"));
+ //memset (out->data, 0, out->data_len + out_len);
out->data_len = 0;
+ rc = 1;
}
EVP_CIPHER_CTX_free (ctx);
state = ready_e;
- return 0;
+ return rc;
}
int decrypt_func (ENCRYPTED_DATA_t *in, CLEAR_DATA_t *out)
{
VERBOSE (crypto, TRACE, PRINTF ("decrypt_func\n"));
+ // FIXIT: not thread safe
state = working_e;
/* channel id */
out->channel_id = in->channel_id;
- /* copy bypass */
+ /* filter bypass */
#ifndef PROTOCOL_EXT
if (in->bypass_len) {
- VERBOSE (cryptomod, WARNING, PRINTF ("not supproted by this protocol\n"));
+ VERBOSE (crypto, WARNING, PRINTF ("bypass not supproted by this protocol\n"));
}
- out->bypass_len = 0
+ out->bypass_len = 0;
#else
- memcpy (out->bypass, in->bypass, in->bypass_len * sizeof (uint8_t));
- out->bypass_len = in->bypass_len;
+ BYPASS_t pdu_bypass = {0};
+ deserial_bypass (in->bypass, in->bypass_len, &pdu_bypass);
+ if (content_filter (&pdu_bypass)) {
+ VERBOSE (crypto, WARNING, PRINTF ("bypass message filtered\n"));
+ out->bypass_len = 0;
+ } else {
+ memcpy (out->bypass, in->bypass, in->bypass_len * sizeof (uint8_t));
+ out->bypass_len = in->bypass_len;
+ }
#endif
/* get aad */
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 {
+ int rc = 0;
+ if (EVP_DecryptUpdate (ctx, out->data, &out_len, in->data, in->data_len - TAG_LENGTH)) {
out->data_len = out_len;
EVP_DecryptFinal_ex (ctx, NULL, &out_len);
out->data_len += out_len;
+ } else {
+ VERBOSE (crypto, WARNING, PRINTF ("decryption error\n"));
+ //memset (out->data, 0, out_len);
+ out->data_len = 0;
+ rc = 1;
}
EVP_CIPHER_CTX_free (ctx);
state = ready_e;
- return 0;
+ return rc;
}
int load_key_func (KEY_t *in, STATUS_t *out)
VERBOSE (crypto, TRACE, PRINTF ("unload_key_func\n"));
int kid = in->key_id;
- out->status = (keys[kid]) ? ok_e : error_e;
- free (keys[kid]);
- keys[kid] = NULL;
- key_lengths[kid] = 0;
+#ifdef PROTOCOL_EXT
+ for (int i = 0; i < NB_CHANNELS; i++) {
+ if (channels[i] == kid + 1) {
+ VERBOSE (crypto, WARNING, PRINTF ("key (%d) is still associated to a channel (%d)\n", kid, i));
+ out->status = error_e;
+ return 0;
+ }
+ }
+#endif
+
+ if (keys[kid]) {
+ out->status = ok_e;
+ free (keys[kid]);
+ keys[kid] = NULL;
+ key_lengths[kid] = 0;
+ } else {
+ VERBOSE (crypto, WARNING, PRINTF ("key (%d) wasn't loaded\n", kid));
+ out->status = error_e;
+ }
#ifndef PROTOCOL_EXT
channels[kid] = 0;
VERBOSE (crypto, WARNING, PRINTF ("incorrect ERRASE_KEY message\n"));
}
+#ifdef PROTOCOL_EXT
+ for (int i = 0; i < NB_CHANNELS; i++) {
+ if (channels[i]) {
+ VERBOSE (crypto, WARNING, PRINTF ("key (%d) is still associated to a channel (%d)\n", channels[i] - 1, i));
+ out->status = error_e;
+ return 0;
+ }
+ }
+#endif
+
for (int i = 0; i < NB_KEYS; i++) {
free (keys[i]);
#ifndef PROTOCOL_EXT
{
VERBOSE (crypto, TRACE, PRINTF ("associate_channel_func\n"));
- channels[in->channel_id] = in->key_id + 1;
+ int cid = in->channel_id;
+ int kid = in->key_id;
+#ifdef PROTOCOL_EXT
+ if (keys[kid] == NULL) {
+ VERBOSE (crypto, WARNING, PRINTF ("can't associate channnel id to empty key (%d)\n", kid));
+ out->status = error_e;
+ } else {
+ channels[cid] = kid + 1;
+ if (state == initializing_e) {
+ state = ready_e;
+ }
+ out->status = ok_e;
+ }
+#else
+ channels[cid] = kid + 1;
out->status = ok_e;
+#endif
return 0;
}
{
VERBOSE (crypto, TRACE, PRINTF ("dissociate_channel_func\n"));
- out->status = (channels[in->channel_id]) ? ok_e : error_e;
+ int cid = in->channel_id;
- channels[in->channel_id] = 0;
+#ifdef PROTOCOL_EXT
+ if (channels[cid] == 0) {
+ VERBOSE (crypto, WARNING, PRINTF ("no key associated to channnel id (%d)\n", cid));
+ out->status = error_e;
+ } else if (keys[channels[cid] - 1] == NULL) {
+ VERBOSE (crypto, WARNING, PRINTF ("can't dissociate channnel id to empty key (%d)\n", cid));
+ out->status = error_e;
+ } else {
+ channels[cid] = 0;
+ state_t _state = initializing_e;
+ for (int i = 0; i < NB_CHANNELS; i++) {
+ if (channels[i] != 0) {
+ _state = ready_e;
+ }
+ }
+ if (_state == initializing_e) {
+ // FIXIT: not thread safe
+ state = initializing_e;
+ }
+ out->status = ok_e;
+ }
+#else
+ if (channels[cid]) {
+ channels[cid] = 0;
+ out->status = ok_e;
+ } else {
+ VERBOSE (crypto, WARNING, PRINTF ("no key associated to channnel id (%d)\n", cid));
+ out->status = error_e;
+ }
+#endif
return 0;
}
{
VERBOSE (crypto, TRACE, PRINTF ("bypass_func\n"));
- if (in != out) {
- memcpy (out, in, sizeof (RAW_DATA_t));
+ BYPASS_t pdu_bypass = {0};
+ deserial_bypass (in->data, in->data_len, &pdu_bypass);
+ if (content_filter (&pdu_bypass)) {
+ VERBOSE (crypto, WARNING, PRINTF ("bypass message filtered\n"));
+ out->data_len = 0;
+ } else if (out != in) {
+ memcpy (out->data, in->data, in->data_len * sizeof (uint8_t));
+ out->data_len = in->data_len;
}
- return 0;
+ return (out->data_len > 0);
}
int random_func (PRNG_PARAM_t *in, RAW_DATA_t *out)
(memcmp (secret_message, in->data, in->data_len) == 0)) {
out->data_len = strlen (correct_answer);
memcpy (out->data, correct_answer, out->data_len);
- state = ready_e;
+ state = initializing_e;
} else {
out->data_len = strlen (wrong_answer);
memcpy (out->data, wrong_answer, out->data_len);
- state = initializing_e;
+ state = starting_e;
}
return 0;
{
VERBOSE (crypto, TRACE, PRINTF ("reboot_func\n"));
+ // FIXIT: not thread safe
state = booting_e;
+
out->status = ok_e;
return 0;
VERBOSE (crypto, TRACE, PRINTF ("zeroize_func\n"));
clean_crypto_memory ();
+
+ // FIXIT: not thread safe
state = ready_e;
out->status = ok_e;
{
VERBOSE (crypto, TRACE, PRINTF ("lock_crypto_func\n"));
+ // FIXIT: not thread safe
state = shutdowning_e;
out->status = ok_e;
--- /dev/null
+/*
+ File name : pdu_bypass.c
+ Projet : MERLIN
+ Date of creation : 2025/04/07
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : This file contains definition of bypass type
+
+ History :
+ - initial version
+*/
+
+#include <stdint.h>
+
+#include "parse.h"
+
+#include "pdu_bypass.h"
+
+int parse_bypass (char *line, BYPASS_t *out)
+{
+ BEGIN_PARSE (line)
+ PARSE_INT ("ID", out->id)
+ PARSE_ARRAY ("DATA", out->data)
+ PARSE_INT ("DATALEN", out->data_len) /* for checking */
+ END_PARSE ()
+}
+
+int format_bypass (BYPASS_t *in, char *buffer, int maxlen)
+{
+ BEGIN_FORMAT (buffer, maxlen)
+ FORMAT_INT ("ID", in->id)
+ FORMAT_ARRAY ("DATA", in->data)
+ END_FORMAT ()
+}
+
+int serial_bypass (BYPASS_t *in, uint8_t *buffer, int maxlen)
+{
+ BEGIN_SERIAL (buffer, maxlen)
+ SERIAL_INT ("ID", in->id)
+ SERIAL_ARRAY ("DATA", in->data)
+ END_SERIAL ()
+}
+
+int deserial_bypass (uint8_t *buffer, int len, BYPASS_t *out)
+{
+ BEGIN_DESERIAL (buffer, len)
+ DESERIAL_INT ("ID", out->id)
+ DESERIAL_ARRAY ("DATA", out->data)
+ END_DESERIAL ()
+}
+
+int check_bypass (BYPASS_t *first, BYPASS_t *second, int fields)
+{
+ BEGIN_CHECK (fields)
+ CHECK_INT ("ID", first->id, second->id)
+ CHECK_ARRAY ("DATA", first->data, second->data)
+ CHECK_INT ("DATALEN", first->data_len, second->data_len)
+ END_CHECK ()
+}
+
+/* vim: set ts=4 sw=4 si et: */
--- /dev/null
+/*
+ File name : pdu_bypass.h
+ Projet : MERLIN
+ Date of creation : 2025/05/13
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : This file contains functions for bypass pdu
+
+ History :
+ - initial version
+*/
+
+#ifndef __BYPASS_H__
+#define __BYPASS_H__
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+#include "def.h"
+
+__BEGIN_DECLS
+
+/**
+ @defgroup BYPASS
+ @ingroup MESSAGES
+*/
+
+/**
+ @ingroup BYPASS
+
+ bypass type
+*/
+typedef struct {
+ uint8_t id; /**< message id */
+ uint16_t data_len; /**< data length*/
+ uint8_t data[MOREP_PAYLOAD - 1]; /**< data message */
+} BYPASS_t;
+
+/**
+ @ingroup BYPASS
+
+ Parse a string containing some bypass type fields
+
+ @param line string to analyse
+ @param out output structure
+ @return 0 on success
+*/
+int parse_bypass (char *line, BYPASS_t *out);
+
+/**
+ @ingroup BYPASS
+
+ Format bypass type fields into a string
+
+ @param in input structure
+ @param buffer output string
+ @param maxlen buffer limit
+ @return 0 on success
+*/
+int format_bypass (BYPASS_t *in, char *buffer, int maxlen);
+
+/**
+ @ingroup BYPASS
+
+ Serialize bypass type fields into a network stream
+
+ @param in input structure
+ @param buffer network stream
+ @param maxlen buffer limit
+ @return buffer length
+*/
+int serial_bypass (BYPASS_t *in, uint8_t *buffer, int maxlen);
+
+/**
+ @ingroup BYPASS
+
+ Deserial bypass type fields from a network stream
+
+ @param buffer network stream
+ @param len buffer length
+ @param out output structure
+ @return 0 on success
+*/
+int deserial_bypass (uint8_t *buffer, int len, BYPASS_t *out);
+
+/**
+ @ingroup BYPASS
+
+ Check two bypass structures field by field
+
+ @param first first structure
+ @param second second structure
+ @param fields field mask to be checked
+ @return 0 on success
+*/
+int check_bypass (BYPASS_t *first, BYPASS_t *second, int fields);
+
+__END_DECLS
+
+#endif /* __BYPASS_H__ */
+
+/* vim: set ts=4 sw=4 si et: */