--- /dev/null
+/*
+ File name : core.c
+ Date of creation : 10/2/2008
+ Version : 1.0
+ Copyright : Soft'n'Design
+ Author : Laurent Mazet <mazet@softndesign.org>
+
+ Description : Miscellaenous functions on core/thread management
+
+ History :
+ - initial version from tools.h
+*/
+
+#define _GNU_SOURCE
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/time.h>
+#include <unistd.h>
+
+#include "rdtsc.h"
+#include "verbose.h"
+
+#include "core.h"
+
+DECLARE_VERBOSE_LEVEL (coretools, 0);
+
+int get_cpu_number (void)
+{
+ int ncpu = 0;
+ char *procinfo = "processor";
+
+ FILE *F = fopen ("/proc/cpuinfo", "r");
+ if (F) {
+ char line[256] = { '\0' };
+ while (fgets (line, sizeof (line) - 1, F)) {
+ if (strncmp (line, procinfo, strlen (procinfo)) == 0)
+ ncpu++;
+ }
+ fclose (F);
+ }
+
+ return (ncpu == 0) ? 1 : ncpu;
+}
+
+
+/* Thread management */
+
+int enable_realtime (int prio)
+{
+ struct sched_param param;
+
+ param.__sched_priority = prio;
+ return pthread_setschedparam (pthread_self (), SCHED_FIFO, ¶m);
+}
+
+int cpu_setaffinity (const char *cpu_list)
+{
+ cpu_set_t cpuset;
+ char *save_ptr;
+ char *cpu;
+ char delim[] = "+, ";
+
+ if (!cpu_list) return -1;
+
+ char *copy_list = strdup(cpu_list);
+
+ CPU_ZERO(&cpuset);
+ cpu = strtok_r(copy_list, delim, &save_ptr);
+ while (cpu) {
+ CPU_SET(atoi(cpu), &cpuset);
+ cpu = strtok_r(NULL, delim, &save_ptr);
+ }
+
+ free(copy_list);
+
+ return pthread_setaffinity_np(pthread_self (), sizeof(cpu_set_t), &cpuset);
+}
+
+/**
+ Cpu clock
+*/
+static double cpu_clock = 1;
+
+
+/**
+ Internal funciton, executed at load time to calibrate cpu clock
+*/
+void __attribute__((constructor)) _core_init_cpu_clock (void)
+{
+ struct timeval tv1, tv2;
+ long long int ts1, ts2;
+
+ gettimeofday (&tv1, NULL);
+ ts1 = rdtsc ();
+
+ usleep (100000);
+
+ gettimeofday (&tv2, NULL);
+ ts2 = rdtsc ();
+
+ double delta = ((double)tv2.tv_sec + tv2.tv_usec * 1e-6) -
+ ((double)tv1.tv_sec + tv1.tv_usec * 1e-6);
+
+ cpu_clock = (ts2 - ts1) / delta;
+}
+
+unsigned long long tsc2diff (unsigned long long tsc1, unsigned long long tsc2)
+{
+ return (tsc1 > tsc2) ? tsc1 - tsc2 : tsc2 + (~tsc1) + 1;
+}
+
+float tsc2ms (unsigned long long delta_tsc)
+{
+ return (float) (delta_tsc / cpu_clock * 1e6f);
+}
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
--- /dev/null
+/*
+ File name : core.h
+ Date of creation : 10/2/2008
+ Version : 1.0
+ Copyright : Soft'n'Design
+ Author : Laurent Mazet <mazet@softndesign.org>
+
+ Description : Miscellaenous functions on core/thread management
+
+ History :
+ - initial version from tools.h
+*/
+
+#ifndef __CORE_H__
+#define __CORE_H__
+
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ Declare a parameter or a variable unused.
+*/
+#define UNUSED __attribute__ ((unused))
+
+/**
+ Count number of CPU
+
+ @return number of CPU
+*/
+int get_cpu_number (void);
+
+/* Thread management */
+
+/**
+ Set realtime priority
+
+ @param prio priority
+ @return error code (from pthread_setschedparam)
+*/
+int enable_realtime (int prio);
+
+/**
+ Set cpu (core) affinity
+
+ @param cpu_list is a char string describing cpu affinity when core ids are separated by plus (+), comma (,) or space ( )
+ @return error code (from pthread_setaffinity_np)
+*/
+int cpu_setaffinity (const char *cpu_list);
+
+/**
+ Compute the difference between two cycle counters
+
+ @param tsc1 initial cycle counter
+ @param tsc1 last cycle counter
+ @return cycle counter difference
+*/
+unsigned long long tsc2diff (unsigned long long tsc1, unsigned long long tsc2);
+
+/**
+ Evaluation a number of cycles in milisecond
+
+ @param delta_tsc number of cycles
+ @return number of miliseconds
+*/
+float tsc2ms (unsigned long long delta_tsc);
+
+__END_DECLS
+
+#endif /* __CORE_H__ */
+
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
--- /dev/null
+/*
+ File name : cryptomod.c
+ Projet : MERLIN
+ Date of creation : 2025/05/0r2
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : Crypto Module
+
+ History :
+ - initial version
+*/
+
+/* depend: */
+/* cflags: */
+/* linker: core.o morep.o parse.o pdu_channel.o pdu_encrypted_data.o pdu_prng_param.o pdu_status.o pdu_clear_data.o pdu_key.o pdu_raw_data.o task.o */
+
+#include <errno.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "def.h"
+#include "cryptomod.h"
+#include "morep.h"
+#include "pdu_channel.h"
+#include "pdu_encrypted_data.h"
+#include "pdu_prng_param.h"
+#include "pdu_status.h"
+#include "pdu_clear_data.h"
+#include "pdu_key.h"
+#include "pdu_raw_data.h"
+#include "pdu_raw_data.h"
+#include "task.h"
+#include "verbose.h"
+
+char *progname = NULL;
+
+int state = shutdowning_e;
+
+DECLARE_VERBOSE_LEVEL (morep, INFO);
+DECLARE_VERBOSE_LEVEL (crypto, INFO);
+
+#define BUFMAX 4096
+
+#define NBSERVICES 10
+char *services[NBSERVICES] = {
+ "CROSS_CRYPTO_R2B",
+ "LOCAL_CRYPTO_BLACK",
+ "LOCAL_CRYPTO_RED",
+ "PROVISIONING",
+ "PRNG_BLACK",
+ "PRNG_RED",
+ "BYPASS_B2R",
+ "BYPASS_R2B",
+ "CONTROL",
+};
+
+/* definition of all messages */
+message_t message_list[] = {
+
+ /* Cross cryptographic B-2-R service */
+ {"DECRYPT_CROSS_ASYNC", cross_crypto_b2r_e, 0x02, encrypted_data_e, decrypt_func_e},
+ {"DECRYPTED_CROSS_ASYNC", cross_crypto_b2r_e, 0x03, clear_data_e, nofunc_e},
+
+ /* Cross cryptographic R-2-B service */
+ {"ENCRYPT_CROSS_ASYNC", cross_crypto_r2b_e, 0x00, clear_data_e, encrypt_func_e},
+ {"ENCRYPTED_CROSS_ASYNC", cross_crypto_r2b_e, 0x01, encrypted_data_e, nofunc_e},
+
+ /* Local cryptographic Black and Red services */
+ {"ENCRYPT_LOCAL_REQ", local_crypto_e, 0x00, clear_data_e, encrypt_func_e},
+ {"ENCRYPTED_LOCAL_RESP", local_crypto_e, 0x01, encrypted_data_e, nofunc_e},
+ {"DECRYPT_LOCAL_REQ", local_crypto_e, 0x02, encrypted_data_e, decrypt_func_e},
+ {"DECRYPTED_LOCAL_RESP", local_crypto_e, 0x03, clear_data_e, nofunc_e},
+
+ /* Provisioning service */
+ {"LOAD_KEY_REQ", provisioning_e, 0x00, key_e, load_key_func_e},
+ {"LOAD_KEY_RESP", provisioning_e, 0x01, status_e, nofunc_e},
+ {"UNLOAD_KEY_REQ", provisioning_e, 0x02, key_e, unload_key_func_e},
+ {"UNLOAD_KEY_RESP", provisioning_e, 0x03, status_e, nofunc_e},
+ {"ERASE_KEY_REQ", provisioning_e, 0x04, key_e, erase_key_func_e},
+ {"ERASE_KEY_RESP", provisioning_e, 0x05, status_e, nofunc_e},
+ {"ASSOCIATE_CHANNEL_REQ", provisioning_e, 0x06, channel_e, associate_channel_e},
+ {"ASSOCIATE_CHANNEL_RESP", provisioning_e, 0x07, status_e, nofunc_e},
+ {"DISSOCIATE_CHANNEL_REQ", provisioning_e, 0x08, channel_e, dissociate_channel_e},
+ {"DISSOCIATE_CHANNEL_RESP", provisioning_e, 0x09, status_e, nofunc_e},
+
+ /* Bypass B-2-R and R-2-B services */
+ {"BYPASS_CROSS_ASYNC", bypass_e, 0x00, raw_data_e, bypass_func_e},
+ {"BYPASSED_CROSS_ASYNC", bypass_e, 0x01, raw_data_e, nofunc_e},
+
+ /* PRNG Black and Red services */
+ {"RANDOM_REQ", prng_e, 0x00, prng_param_e, random_func_e},
+ {"RANDOM_RESP", prng_e, 0x01, raw_data_e, nofunc_e},
+
+ /* Control service */
+ {"STATUS_REQ", control_e, 0x00, nopdu_e, status_func_e},
+ {"STATUS_RESP", control_e, 0x01, status_e, nofunc_e},
+ {"AUTHENTICATION_REQ", control_e, 0x02, raw_data_e, authentification_func_e},
+ {"AUTHENTICATION_RESP", control_e, 0x03, raw_data_e, nofunc_e},
+ {"REBOOT_REQ", control_e, 0x04, nopdu_e, reboot_func_e},
+ {"REBOOT_RESP", control_e, 0x05, status_e, nofunc_e},
+ {"ZEROIZE_REQ", control_e, 0x06, nopdu_e, zeroize_func_e},
+ {"ZEROIZE_RESP", control_e, 0x07, status_e, nofunc_e},
+ {"LOCK_CRYPTO_REQ", control_e, 0xFE, nopdu_e, lock_crypto_func_e},
+ {"LOCK_CRYPTO_RESP", control_e, 0xFF, status_e, nofunc_e},
+
+ /* End of list */
+ {"", noserv_e, 0x00, undef_pdu_e, nofunc_e}
+};
+
+/* definition of all services */
+service_t service_list[] = {
+ {"CROSS_CRYPTO_B2R", cross_crypto_b2r_e, NULL, NULL}, /* 809 */
+ {"CROSS_CRYPTO_R2B", cross_crypto_r2b_e, NULL, NULL}, /* 809 */
+ {"LOCAL_CRYPTO_BLACK", local_crypto_e, NULL, NULL}, /* 80a */
+ {"LOCAL_CRYPTO_RED", local_crypto_e, NULL, NULL}, /* 80a */
+ {"PROVISIONING", provisioning_e, NULL, NULL}, /* 80b */
+ {"PRNG_BLACK", prng_e, NULL, NULL}, /* 80c */
+ {"PRNG_RED", prng_e, NULL, NULL}, /* 80c */
+ {"BYPASS_B2R", bypass_e, NULL, NULL}, /* 80d */
+ {"BYPASS_R2B", bypass_e, NULL, NULL}, /* 80d */
+ {"CONTROL", control_e, NULL, NULL}, /* 80e */
+ {"", noserv_e, NULL, NULL}
+};
+
+/* various functions */
+
+service_t *find_service (char *servname)
+{
+ service_t *serv = NULL;
+ for (int i = 0; ((service_list + i)->service_id != noserv_e) && (!serv); i++) {
+ service_t *s = service_list + i;
+ if ((s) && (servname) && (strcmp (s->name, servname) == 0)) {
+ serv = s;
+ }
+ }
+ return serv;
+}
+
+/* main thread function */
+
+int main_thread (sub_task_t *s, int id)
+{
+ if ((s == NULL) || (id != 0) || (id >= NBSERVICES)) {
+ VERBOSE (crypto, ERROR, PRINTF ("can't start thread '%d'\n", id));
+ return -1;
+ }
+
+ char *servname = services[id];
+ service_t *serv = find_service (servname);
+ if (!serv) {
+ VERBOSE (crypto, ERROR, PRINTF ("can't find service '%s'\n", servname));
+ return 1;
+ }
+ int in = MOREP_Connect (serv->rx);
+ if (in < 0) {
+ VERBOSE (crypto, ERROR, PRINTF ("can't open TX MOREP for service '%s'\n", servname));
+ return 1;
+ }
+ int out = MOREP_Connect (serv->tx);
+ if (in < 0) {
+ VERBOSE (crypto, ERROR, PRINTF ("can't open RX MOREP for service '%s'\n", servname));
+ MOREP_Close (in);
+ return 1;
+ }
+
+ CHANNEL_t pdu_channel = {0};
+ CLEAR_DATA_t pdu_clear_data = {0};
+ ENCRYPTED_DATA_t pdu_encrypted_data = {0};
+ KEY_t pdu_key = {0};
+ PRNG_PARAM_t pdu_prng_param = {0};
+ RAW_DATA_t pdu_raw_data = {0};
+ STATUS_t pdu_status = {0};
+ int rc = 0;
+
+ while (1) {
+
+ /* listen a message */
+ uint8_t msgtype = 0;
+ uint8_t payload[MOREP_PAYLOAD] = {0};
+ int len = 0;
+ int seqnum = MOREP_Receive (in, &msgtype, payload, &len);
+
+ /* check service/msgtype */
+ message_t *msg = NULL;
+ for (int i = 0; ((message_list + i)->service_id) && (!msg); i++) {
+ message_t *m = message_list + i;
+ if ((m->service_id == serv->service_id) && (m->msgtype == msgtype)) {
+ msg = m;
+ }
+ }
+
+ /* check msg type */
+ if (msg == NULL) {
+ VERBOSE (crypto, WARNING, PRINTF ("R:%s [SEQ=%d MSG=%d LEN=%d] message type is not allowed for this service\n", serv->name, seqnum, msgtype, len));
+ continue;
+ }
+
+ /* deserialize message */
+ rc = 1;
+ switch (msg->pdu) {
+ case nopdu_e:
+ rc = 0;
+ break;
+ case channel_e:
+ rc = deserial_channel (payload, len, &pdu_channel);
+ break;
+ case clear_data_e:
+ rc = deserial_clear_data (payload, len, &pdu_clear_data);
+ break;
+ case encrypted_data_e:
+ rc = deserial_encrypted_data (payload, len, &pdu_encrypted_data);
+ break;
+ case key_e:
+ rc = deserial_key (payload, len, &pdu_key);
+ break;
+ case prng_param_e:
+ rc = deserial_prng_param (payload, len, &pdu_prng_param);
+ break;
+ case raw_data_e:
+ rc = deserial_raw_data (payload, len, &pdu_raw_data);
+ break;
+ case status_e:
+ rc = deserial_status (payload, len, &pdu_status);
+ break;
+ default:
+ }
+ if (rc) {
+ VERBOSE (crypto, WARNING, PRINTF ("can't deserialize message %s\n", msg->name));
+ continue;
+ }
+
+ /* log received message */
+ VERBOSE (crypto, INFO, PRINTF ("R:%s [SEQ=%d MSG=%d LEN=%d PDU=%d] %s\n", serv->name, seqnum, msgtype, len, msg->pdu, msg->name));
+
+ /* process message */
+ rc = 1;
+ switch (msg->func) {
+ case nofunc_e:
+ break;
+ case encrypt_func_e:
+ rc = encrypt_func (&pdu_clear_data, &pdu_encrypted_data);
+ break;
+ case decrypt_func_e:
+ rc = decrypt_func (&pdu_encrypted_data, &pdu_clear_data);
+ break;
+ case load_key_func_e:
+ rc = load_key_func (&pdu_key, &pdu_status);
+ break;
+ case unload_key_func_e:
+ rc = unload_key_func (&pdu_key, &pdu_status);
+ break;
+ case erase_key_func_e:
+ rc = erase_key_func (&pdu_key, &pdu_status);
+ break;
+ case associate_channel_e:
+ rc = associate_channel_func (&pdu_channel, &pdu_status);
+ break;
+ case dissociate_channel_e:
+ rc = dissociate_channel_func (&pdu_channel, &pdu_status);
+ break;
+ case bypass_func_e:
+ //rc = bypass_func (&pdu_raw_data, &pdu_raw_data);
+ rc = 0;
+ break;
+ case random_func_e:
+ rc = random_func (&pdu_prng_param, &pdu_raw_data);
+ break;
+ case status_func_e:
+ rc = random_func (NULL, &pdu_status);
+ break;
+ case authentification_func_e:
+ rc = authentification_func (&pdu_raw_data, &pdu_raw_data);
+ break;
+ case reboot_func_e:
+ rc = reboot_func (NULL, &pdu_status);
+ break;
+ case zeroize_func_e:
+ rc = zeroize_func (NULL, &pdu_status);
+ break;
+ case lock_crypto_func_e:
+ rc = lock_crypto_func (NULL, &pdu_status);
+ break;
+ }
+ if (rc) {
+ VERBOSE (crypto, WARNING, PRINTF ("can't process message %s\n", msg->name));
+ continue;
+ }
+
+ /* prepare message for transmission */
+ msgtype++;
+
+ /* check service/msgtype */
+ msg = NULL;
+ for (int i = 0; ((message_list + i)->service_id) && (!msg); i++) {
+ message_t *m = message_list + i;
+ if ((m->service_id == serv->service_id) && (m->msgtype == msgtype)) {
+ msg = m;
+ }
+ }
+
+ /* check msg type */
+ if (msg == NULL) {
+ VERBOSE (crypto, WARNING, PRINTF ("T:%s [SEQ=%d MSG=%d] message type is not allowed for this service\n", serv->name, seqnum, msgtype));
+ continue;
+ }
+
+ /* serialize message */
+ len = -1;
+ switch (msg->pdu) {
+ case nopdu_e:
+ len = 0;
+ break;
+ case channel_e:
+ len = serial_channel (&pdu_channel, payload, sizeof (payload));
+ break;
+ case clear_data_e:
+ len = serial_clear_data (&pdu_clear_data, payload, sizeof (payload));
+ break;
+ case encrypted_data_e:
+ len = serial_encrypted_data (&pdu_encrypted_data, payload, sizeof (payload));
+ break;
+ case key_e:
+ len = serial_key (&pdu_key, payload, sizeof (payload));
+ break;
+ case prng_param_e:
+ len = serial_prng_param (&pdu_prng_param, payload, sizeof (payload));
+ break;
+ case raw_data_e:
+ len = serial_raw_data (&pdu_raw_data, payload, sizeof (payload));
+ break;
+ case status_e:
+ len = serial_status (&pdu_status, payload, sizeof (payload));
+ break;
+ default:
+ }
+ if (len < 0) {
+ VERBOSE (crypto, WARNING, PRINTF ("can't serialize message %s\n", msg->name));
+ }
+
+ /* send message */
+ seqnum = MOREP_Send (out, msgtype, payload, len);
+
+ /* log transmitted message */
+ VERBOSE (crypto, INFO, PRINTF ("T:%s [SEQ=%d MSG=%d PDU=%d] %s\n", serv->name, seqnum, msgtype, msg->pdu, msg->name));
+ }
+
+ return 0;
+}
+
+/* signal handler */
+void sig_handler (int sig)
+{
+ switch (sig) {
+ case SIGINT:
+ exit (0);
+ break;
+ case SIGTERM:
+ exit (0);
+ break;
+ }
+}
+
+/* usage function */
+void usage (void) {
+ printf ("usage: %s [-h] [-l log] [-r url] [-s srv] [-t url] [-v lvl] [-V lvl]\n", progname);
+ printf (" -h : help message\n");
+ printf (" -l log: log all message into a file or stdout if -\n");
+ printf (" -r url: set MOREP url for a receveiving service\n");
+ printf (" -s srv: define a service\n");
+ printf (" -t url: set MOREP url for a transmiting service\n");
+ printf (" -v lvl: verbose level for MOREP functions (%d)\n", GET_VERBOSE_LEVEL(morep));
+ printf (" -V lvl: verbose level for crypto modul functions (%d)\n", GET_VERBOSE_LEVEL(crypto));
+}
+
+/* main function */
+int main (int argc, char **argv)
+{
+
+ /* get basename */
+ char *ptr = progname = argv[0];
+ while (*ptr) {
+ if ((*ptr == '/') || (*ptr == '\\')) {
+ progname = ptr + 1;
+ }
+ ptr++;
+ }
+
+ /* process argument */
+ char *logname = NULL;
+ char *servname = NULL;
+ while (argc-- > 1) {
+ char *url = NULL;
+ int mode = -1;
+
+ char *arg = *(++argv);
+ if (arg[0] != '-') {
+ usage ();
+ return 1;
+ }
+ char c = arg[1];
+ switch (c) {
+ case 'l':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: log file not specified\n", progname));
+ return 1;
+ }
+ logname = arg;
+ break;
+ case 'r':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: receiver url not specified\n", progname));
+ return 1;
+ }
+ url = arg;
+ mode = 0;
+ break;
+ case 's':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: service not specified\n", progname));
+ return 1;
+ }
+ servname = arg;
+ break;
+ case 't':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: transmitter url not specified\n", progname));
+ return 1;
+ }
+ url = arg;
+ mode = 1;
+ break;
+ case 'v':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: morep verbose level not specified\n", progname));
+ return 1;
+ }
+ CHANGE_VERBOSE_LEVEL (morep, atoi (arg));
+ break;
+ case 'V':
+ arg = (arg[2]) ? arg + 2 : (--argc > 0) ? *(++argv) : NULL;
+ if (arg == NULL) {
+ VERBOSE (crypto, ERROR, PRINTF ("%s: cryptomod verbose level not specified\n", progname));
+ return 1;
+ }
+ CHANGE_VERBOSE_LEVEL (crypto, atoi (arg));
+ break;
+ case 'h':
+ default:
+ usage ();
+ return (c != 'h');
+ }
+
+ /* init communication channel */
+ if (mode != -1) {
+ service_t *serv = find_service (servname);
+ if (serv) {
+ if (mode) {
+ serv->rx = url;
+ } else {
+ serv->tx = url;
+ }
+ } else {
+ VERBOSE (crypto, WARNING, PRINTF ("can't find service '%s'\n", servname));
+ }
+ mode = -1;
+ }
+ }
+
+ /* signals */
+ signal(SIGINT, sig_handler);
+ signal(SIGTERM, sig_handler);
+
+ /* main loop */
+
+ while (state != shutdowning_e) {
+
+ /* booting and starting */
+ state = booting_e;
+
+ task_t *task = create_async_task ("CRYPTOMOD", main_thread, 0, NBSERVICES, NULL);
+
+ }
+
+ /* cleaning */
+ //if ((log) && (log != stdout)) {
+ // fclose (log);
+ //}
+
+ return 0;
+}
+
+/* test: cryptomod.exe -h | grep usage */
+/* test: cryptomod.exe -l | grep 'log file not specified' */
+/* test: cryptomod.exe -r | grep 'url not specified' */
+/* test: cryptomod.exe -s | grep 'service not specified' */
+/* test: cryptomod.exe -t | grep 'url not specified' */
+/* test: cryptomod.exe -v | grep 'morep verbose level not specified' */
+/* test: cryptomod.exe -V | grep 'cryptomod verbose level not specified' */
+
+/* vim: set ts=4 sw=4 si et: */
--- /dev/null
+/*
+ File name : cryptomode.h
+ Projet : MERLIN
+ Date of creation : 2025/05/02
+ Version : 1.0
+ Copyright : Thales SIX
+ Author : Laurent Mazet <laurent.mazet@thalesgroup.com>
+
+ Description : This file defines crypto module types
+
+ History :
+ - initial version
+*/
+
+#ifndef __CRYPTOMOD_H__
+#define __CRYPTOMOD_H__
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ @defgroup CRYPTOMOD Public API of Crypto module
+
+*/
+
+/**
+ @ingroup CRYPTOMOD
+
+ Service enumarate values
+*/
+typedef enum {
+ noserv_e = 0, /**< no service defined */
+ cross_crypto_r2b_e, /**< cross cryptographic R-2-B service */
+ cross_crypto_b2r_e, /**< cross cryptographic B-2-R service */
+ local_crypto_e, /**< local cryptographic Black and Red services */
+ provisioning_e, /**< provisioning service */
+ prng_e, /**< PRNG Black and Red services */
+ bypass_e, /**< bypass B-2-R and R-2-B services */
+ control_e /**< controlservice */
+} service_id_t;
+
+/**
+ @ingroup CRYPTOMOD
+
+ PDU enumarate values
+*/
+typedef enum {
+ undef_pdu_e = 0, /**< undefined PDU */
+ channel_e, /**< CHANNEL_t PDU */
+ clear_data_e, /**< CLEAR_DATA_t PDU */
+ encrypted_data_e, /**< ENCRYPTED_DATA_t PDU */
+ key_e, /**< KEY_t PDU */
+ prng_param_e, /**< PRNG_PARAM_t PDU */
+ raw_data_e, /**< RAW_DATA_t PDU */
+ status_e, /**< STATUS_t PDU */
+ nopdu_e /**< no PDU */
+} pdu_t;
+
+/**
+ @ingroup CRYPTOMOD
+
+ Function type
+*/
+typedef enum {
+ nofunc_e = 0, /**< undefined function */
+ encrypt_func_e, /**< encrypt function */
+ decrypt_func_e, /**< decrypt function */
+ load_key_func_e, /**< load key function */
+ unload_key_func_e, /**< unload key function */
+ erase_key_func_e, /**< erase key function */
+ associate_channel_e, /**< associate channel function */
+ dissociate_channel_e, /**< dissociate channel function */
+ bypass_func_e, /**< bypass function */
+ random_func_e, /**< random function */
+ status_func_e, /**< get status function */
+ authentification_func_e, /**< authentification function */
+ reboot_func_e, /**< reboot function */
+ zeroize_func_e, /**<zeroize function */
+ lock_crypto_func_e /**< lock crypto module function */
+} func_t;
+
+/**
+ @ingroup CRYPTOMOD
+
+ Message type
+*/
+typedef struct {
+ char *name; /**< message name */
+ service_id_t service_id; /**< associated service id */
+ uint8_t msgtype; /**< message id */
+ pdu_t pdu; /**< associated PDU type */
+ func_t func; /**< function type */
+} message_t;
+
+/**
+ @ingroup CRYPTOMOD
+
+ Service type
+*/
+typedef struct {
+ char *name; /**< service name */
+ service_id_t service_id; /**< service id */
+ char *tx; /**< URL for associated TX communication channel */
+ char *rx; /**< URL for assiciated RX communication channel */
+} service_t;
+
+/**
+ @ingroup CRYPTOMOD
+
+ Module states
+*/
+typedef enum {
+ ok_e = 0, /**< ok/idle state */
+ booting_e, /**< booting state */
+ starting_e, /**< starting state */
+ initializing_e, /**< initializing state */
+ ready_e, /**< ready state */
+ working_e, /**< working state */
+ shutdowning_e, /**< shutdowning state */
+ error_e = 255 /**< error state */
+} state_t;
+
+#endif /* __CRYPTOMOD_H__ */
+
+/* vim: set ts=4 sw=4 si et: */
--- /dev/null
+/*
+ File name : rdtsc.h
+ Date of creation : 26/1/2012
+ Version : 1.0
+ Copyright : Soft'n'design
+ Author : Laurent Mazet <mazet@softndesign.org>
+
+ Description : This file contains rdtsc inline function
+
+ History :
+ - initial version
+*/
+
+#ifndef __RDTSC_H__
+#define __RDTSC_H__
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+
+/**
+ Get RDTSC counter
+
+ @return counter
+*/
+#ifdef __i386
+static __inline__ int64_t rdtsc (void) {
+ int64_t x;
+ __asm__ volatile ("rdtsc" : "=A" (x));
+ return x;
+}
+#elif __amd64
+static __inline__ int64_t rdtsc (void) {
+ int64_t a, d;
+ __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
+ return (d << 32) | a;
+}
+#endif
+
+__END_DECLS
+
+#endif /* __RDTSC_H__ */
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
--- /dev/null
+/*
+ File name : task.c
+ Date of creation : 25/01/2010
+ Version : 1.0
+ Copyright : Soft'n'Design
+ Author : Laurent Mazet <mazet@softndesign,org>
+
+ Description : Task management
+
+ History :
+ - initial version
+*/
+
+#define _GNU_SOURCE
+#include <assert.h>
+#include <malloc.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "core.h"
+#include "rdtsc.h"
+#include "verbose.h"
+
+#include "task.h"
+
+long long tsc_start;
+
+void task_stat (task_t * t, int condensed)
+{
+ if (!t->is_sync) return;
+
+ pthread_mutex_lock(&t->stats_mutex);
+
+ if (condensed) {
+ printf ("%s=[%lu]", t->name, (unsigned long) tsc2ms (t->current_exec_time));
+ } else {
+ printf ("task %s prio=%d cpu=%s last run in %lu µs [count=%d overtimes=%lu overloads=%lu, min=%lu average=%lu max=%lu]\n",
+ t->name, t->priority, t->cpu_list,
+ (unsigned long) tsc2ms (t->current_exec_time), t->count, t->overtimes,
+ t->overloads, (unsigned long) tsc2ms (t->min_exec_time),
+ t->count ? (unsigned long) tsc2ms (t->cumul_exec_time / t->count) : 0,
+ (unsigned long) tsc2ms (t->max_exec_time));
+ }
+
+ pthread_mutex_unlock(&t->stats_mutex);
+}
+
+void *task_sync_runner (void *param)
+{
+ sub_task_t *s = (sub_task_t *) param;
+ task_t *t = s->task;
+
+ cpu_setaffinity(t->cpu_list);
+
+ if (t->priority) {
+ enable_realtime (t->priority);
+ }
+ pthread_mutex_init (&s->condition_mutex, NULL);
+ pthread_cond_init (&s->condition_cond, NULL);
+
+ /* potential init function */
+ if (t->init) t->init (s, s->sub_task_id);
+ pthread_mutex_unlock (&t->init_mutex);
+
+ while (1) {
+ // Wait for the trigger
+ pthread_mutex_lock (&s->condition_mutex);
+ while (s->trigger == 0) {
+ pthread_cond_wait (&s->condition_cond, &s->condition_mutex);
+ }
+ pthread_mutex_unlock (&s->condition_mutex);
+
+ // Run the task and measure the execution time
+
+ long long tsc1, tsc2;
+
+ tsc1 = rdtsc ();
+ t->task (s, s->sub_task_id);
+ tsc2 = rdtsc ();
+
+ // Update performances indicators
+
+ pthread_mutex_lock (&t->stats_mutex);
+
+ t->current_exec_time = tsc2diff (tsc2, tsc1);
+ t->cumul_exec_time += t->current_exec_time;
+ t->count++;
+ s->count++;
+
+ if (s->start_time_us) *(s->start_time_us) = tsc2ms(tsc2diff (tsc1, tsc_start));
+ if (s->exec_time_us) *(s->exec_time_us) = tsc2ms(t->current_exec_time);
+
+ if (t->current_exec_time > t->max_exec_time)
+ t->max_exec_time = t->current_exec_time;
+ if (t->current_exec_time / 10 > t->min_exec_time)
+ t->min_exec_time = 0; // To avoid min=0
+ if ((t->current_exec_time < t->min_exec_time) || (t->min_exec_time == 0))
+ t->min_exec_time = t->current_exec_time;
+
+ if (t->current_exec_time > t->max_allowed_time) {
+ VERBOSE (coretools, 1, printf ("Warning: task %s[%d] too slow %luus\n", t->name, s->sub_task_id, (unsigned long) tsc2ms (t->current_exec_time)));
+ t->overtimes++;
+ }
+
+ if (s->count > 10 && t->current_exec_time > 10*t->max_allowed_time) {
+ char ascii_time[80];
+ time_t my_time = time(NULL);
+ strftime(ascii_time, sizeof(ascii_time), "%T", localtime(&my_time));
+ VERBOSE (coretools, 0, printf ("%s: task %s[%d], big overtime %luus\n", ascii_time, t->name, s->sub_task_id, (unsigned long) tsc2ms (t->current_exec_time)));
+ }
+
+ pthread_mutex_unlock (&t->stats_mutex);
+
+ pthread_mutex_lock (&s->condition_mutex);
+ s->trigger = 0;
+ pthread_cond_signal (&s->condition_cond);
+ pthread_mutex_unlock (&s->condition_mutex);
+ }
+
+ return NULL;
+}
+
+int task_trig (task_t * t)
+{
+ assert (t != NULL);
+ int i;
+ for (i=0; i<t->nb_sub_tasks; i++) {
+ sub_task_t *s = &t->sub_task_list[i];
+ pthread_mutex_lock (&s->condition_mutex);
+ while (s->trigger != 0) {
+ pthread_cond_wait (&s->condition_cond, &s->condition_mutex);
+ }
+ s->trigger = 1;
+ pthread_cond_signal (&s->condition_cond);
+ pthread_mutex_unlock (&s->condition_mutex);
+ }
+ return 0;
+}
+
+int task_end (task_t * t)
+{
+ assert (t != NULL);
+ int i;
+ for (i=0; i<t->nb_sub_tasks; i++) {
+ sub_task_t *s = &t->sub_task_list[i];
+ pthread_mutex_lock (&s->condition_mutex);
+ while (s->trigger != 0) {
+ pthread_cond_wait (&s->condition_cond, &s->condition_mutex);
+ }
+ pthread_mutex_unlock (&s->condition_mutex);
+ }
+ return 0;
+}
+
+int task_selective_run (task_t * t, int run_list[])
+{
+ assert (t != NULL);
+ int i;
+
+ // Start all selected sub-tasks
+
+ for (i=0; i<t->nb_sub_tasks; i++) {
+ if (!run_list[i]) continue;
+ sub_task_t *s = &t->sub_task_list[i];
+ pthread_mutex_lock (&s->condition_mutex);
+ while (s->trigger != 0) {
+ pthread_cond_wait (&s->condition_cond, &s->condition_mutex);
+ }
+ s->trigger = 1;
+ pthread_cond_signal (&s->condition_cond);
+ pthread_mutex_unlock (&s->condition_mutex);
+
+ }
+
+ // Wait end of all selected sub-tasks
+
+ for (i=0; i<t->nb_sub_tasks; i++) {
+ if (!run_list[i]) continue;
+ sub_task_t *s = &t->sub_task_list[i];
+ pthread_mutex_lock (&s->condition_mutex);
+ while (s->trigger != 0) {
+ pthread_cond_wait (&s->condition_cond, &s->condition_mutex);
+ }
+ pthread_mutex_unlock (&s->condition_mutex);
+ }
+
+ return 0;
+}
+
+int task_try_trig (task_t * t)
+{
+ assert (t != NULL);
+
+ int i;
+ int nb_running = 0;
+ for (i=0; i<t->nb_sub_tasks; i++) nb_running += t->sub_task_list[i].trigger ? 1 : 0;
+
+ if (nb_running != 0) {
+ t->overloads++;
+ return -1;
+ }
+
+ task_trig(t);
+
+ return 0;
+}
+
+task_t *create_sync_task (const char *name, int (*task) (sub_task_t *, int),
+ float max_allowed_time_us, int (*init) (sub_task_t *, int),
+ int priority, int nb_sub_tasks, const char *cpu_list)
+{
+ int i;
+
+ task_t *t = calloc (1, sizeof (*t));
+ assert (t);
+
+ t->name = strdup (name);
+ t->is_sync = 1;
+ t->task = task;
+ t->max_allowed_time = (long long) (max_allowed_time_us / tsc2ms (1));
+ t->init = init;
+ t->priority = priority;
+ if (cpu_list) {
+ t->cpu_list = strdup(cpu_list);
+ for (i = 0; t->cpu_list[i] != 0; i++) {
+ if (t->cpu_list[i] == ':') {
+ t->cpu_list[i] = 0;
+ int nb = atoi (t->cpu_list + i + 1);
+ if (nb > 0)
+ nb_sub_tasks = nb;
+ }
+ }
+ }
+ pthread_mutex_init (&t->stats_mutex, NULL);
+ pthread_mutex_init (&t->init_mutex, NULL);
+
+ t->sub_task_list = calloc (nb_sub_tasks, sizeof (sub_task_t));
+ assert (t->sub_task_list);
+ t->nb_sub_tasks = nb_sub_tasks;
+
+ printf("Creating task %s[%d] prio=%d cpu=%s ttl=%d\n", t->name, t->nb_sub_tasks, t->priority, t->cpu_list, (int)(max_allowed_time_us));
+
+ pthread_attr_t tattr;
+ int ret = 0;
+
+ size_t size = 1024 * 1024;
+
+ /* initialized with default attributes */
+ ret |= pthread_attr_init (&tattr);
+
+ /* setting the size of the stack also */
+ ret |= pthread_attr_setstacksize (&tattr, size);
+
+ for (i=0; i<nb_sub_tasks; i++) {
+ t->sub_task_list[i].task = t;
+ t->sub_task_list[i].sub_task_id = i;
+ pthread_mutex_lock (&t->init_mutex);
+ pthread_create (&t->sub_task_list[i].thread, &tattr, task_sync_runner, &t->sub_task_list[i]);
+ }
+
+ return t;
+}
+
+void *task_async_runner (void *param)
+{
+ sub_task_t *s = (sub_task_t *) param;
+ task_t *t = s->task;
+
+ cpu_setaffinity(t->cpu_list);
+
+ if (t->priority) {
+ enable_realtime (t->priority);
+ }
+ pthread_mutex_init (&s->condition_mutex, NULL);
+ pthread_cond_init (&s->condition_cond, NULL);
+
+ while (1) {
+ t->task (s, s->sub_task_id);
+ }
+
+ return NULL;
+}
+
+task_t *create_async_task (const char *name, int (*task) (sub_task_t *, int),
+ int priority, int nb_sub_tasks, const char *cpu_list)
+{
+ int i;
+
+ task_t *t = calloc (1, sizeof (*t));
+ assert (t);
+
+ t->name = strdup (name);
+ t->is_sync = 0;
+ t->task = task;
+ t->priority = priority;
+ if (cpu_list) {
+ t->cpu_list = strdup(cpu_list);
+ for (i = 0; t->cpu_list[i] != 0; i++) {
+ if (t->cpu_list[i] == ':') {
+ t->cpu_list[i] = 0;
+ int nb = atoi (t->cpu_list + i + 1);
+ if (nb > 0)
+ nb_sub_tasks = nb;
+ }
+ }
+ }
+
+ t->sub_task_list = calloc (nb_sub_tasks, sizeof (sub_task_t));
+ assert (t->sub_task_list);
+ t->nb_sub_tasks = nb_sub_tasks;
+
+ printf("Creating task %s[%d] prio=%d cpu=%s\n", t->name, t->nb_sub_tasks, t->priority, t->cpu_list);
+
+ pthread_attr_t tattr;
+ int ret = 0;
+
+ size_t size = 1024 * 1024;
+
+ /* initialized with default attributes */
+ ret |= pthread_attr_init (&tattr);
+
+ /* setting the size of the stack also */
+ ret |= pthread_attr_setstacksize (&tattr, size);
+
+ for (i = 0; i < nb_sub_tasks; i++) {
+ t->sub_task_list[i].task = t;
+ t->sub_task_list[i].sub_task_id = i;
+ pthread_create (&t->sub_task_list[i].thread, &tattr, task_async_runner, &t->sub_task_list[i]);
+ }
+
+ return t;
+}
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
--- /dev/null
+/*
+ File name : task.h
+ Date of creation : 25/01/2010
+ Version : 1.0
+ Copyright : Soft'n'Design
+ Author : Laurent Mazet <mazet@softndesign,org>
+
+ Description : Task management
+
+ History :
+ - initial version
+*/
+
+#ifndef __TASK_H__
+#define __TASK_H__
+
+#include <pthread.h>
+
+__BEGIN_DECLS
+
+struct _task_t;
+
+typedef struct {
+ pthread_t thread;
+ pthread_mutex_t condition_mutex;
+ pthread_cond_t condition_cond;
+ int trigger;
+ struct _task_t *task;
+ int sub_task_id;
+
+ int count;
+
+ unsigned long *start_time_us;
+ unsigned long *exec_time_us;
+} sub_task_t;
+
+
+typedef struct _task_t {
+ char *name;
+ int is_sync;
+ int priority;
+ char *cpu_list;
+
+ int (*task) (sub_task_t *s, int subtask_id);
+ long long max_allowed_time;
+
+ sub_task_t *sub_task_list;
+ int nb_sub_tasks;
+
+ // Init function
+
+ int (*init) (sub_task_t *s, int subtask_id);
+ pthread_mutex_t init_mutex;
+
+ // Statistics section
+
+ pthread_mutex_t stats_mutex;
+
+ int count;
+ long long min_exec_time;
+ long long max_exec_time;
+ long long current_exec_time;
+ unsigned long long cumul_exec_time;
+ unsigned long int overtimes;
+ unsigned long int overloads;
+} task_t;
+
+task_t *create_sync_task (const char *name, int (*task) (sub_task_t *, int),
+ float max_allowed_time_us, int (*init) (sub_task_t *, int),
+ int priority, int nb_sub_tasks, const char *cpu_list);
+
+task_t *create_async_task (const char *name, int (*task) (sub_task_t *, int),
+ int priority, int nb_sub_tasks, const char *cpu_list);
+
+int task_trig (task_t * t);
+
+int task_try_trig (task_t * t);
+
+int task_end (task_t * t);
+
+int task_selective_run (task_t * t, int run_list[]);
+
+void task_stat (task_t * t, int condensed);
+
+#endif /* __TASK_H__ */
+
+/* vi:set tabstop=4 expandtab shiftwidth=4: this line set vi mode */
Get error and waring call number.
@param module module name
- @param level verbose level
+ @return level verbose level
*/
-#define GET_VERBOSE_ERRORS(module) verbose_errors_##module
+#define GET_VERBOSE_LEVEL(module) verbose_errors_##module
#endif /* __VERBOSE_H__ */