Commit 8d49e1e8 authored by Denis Filatov's avatar Denis Filatov
Browse files

Merge branch 'STF525' of https://forge.etsi.org/gitlab/ITS/ITS into STF525

parents 747ac2ab ee212de8
......@@ -2,6 +2,7 @@
#include <math.h>
#include "base_time.hh"
#include "loggers.hh"
#ifndef M_PI
#define M_PI 3.14159265358979323846
......@@ -14,13 +15,14 @@ namespace LibItsCommon__Functions
/**
* @desc This external function gets the current time
* @return Timestamp - current time since 01/01/2014 in milliseconds
* @return Timestamp - current time since 01/01/2004 in milliseconds
* @see fx_getCurrentTime() return TimestampIts
*/
INTEGER fx__getCurrentTime(
) {
INTEGER i;
i.set_long_long_val(base_time::get_instance().get_its_current_time());
i.set_long_long_val(base_time::get_instance().get_its_current_time_ms());
loggers::get_instance().log_msg("<<< fx__getCurrentTime: ", i);
return i;
}
/**
......@@ -31,7 +33,8 @@ namespace LibItsCommon__Functions
INTEGER fx__getCurrentTimeUtc(
) {
INTEGER i;
i.set_long_long_val(base_time::get_instance().get_current_time());
i.set_long_long_val(base_time::get_instance().get_current_time_ms());
loggers::get_instance().log_msg("<<< fx__getCurrentTimeUtc: ", i);
return i;
}
/**
......
#include "LibItsGeoNetworking_Functions.hh"
#include <time.h>
#include <math.h>
#include "base_time.hh"
#include "loggers.hh"
namespace LibItsGeoNetworking__Functions
{
......@@ -8,17 +9,11 @@ namespace LibItsGeoNetworking__Functions
* @return Unix-Epoch-Time mod 2^32
fx_computeGnTimestamp() return UInt32;
*/
INTEGER fx__computeGnTimestamp(
) {
struct timeval tv;
gettimeofday(&tv, NULL);
// unsigned long long timestampNow = tv.tv_sec*1000 + tv.tv_usec/1000;
long long timestampNow = tv.tv_sec*1000 + tv.tv_usec/1000;
INTEGER i = INTEGER();
i.set_long_long_val(timestampNow % 4294967296);
// return INTEGER(timestampNow % 4294967296);
return i;
INTEGER fx__computeGnTimestamp() {
INTEGER i;
i.set_long_long_val(base_time::get_instance().get_its_current_time_ms() % 4294967296); // Expresses the time in milliseconds at which the latitude and longitude of the ITS-S were acquired by the GeoAdhoc router. The time is encoded as: TST =TST(TAI)mod232 where TST(TAI) is the number of elapsed TAI milliseconds since 2004-01-01 00:00:00.000 UTC
loggers::get_instance().log_msg("<<< fx__computeGnTimestamp: ", i);
return i;
}
} //end namespace
......@@ -853,57 +853,113 @@ namespace LibItsSecurity__Functions
return message;
}
OCTETSTRING fx__encryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode, OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
OCTETSTRING fx__encryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__recipientsPublicKeyCompressed, const INTEGER& p__compressedMode, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyCompressed, INTEGER& p__ephemeralCompressedMode,OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce, const BOOLEAN& p__use__hardcoded__values) {
loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__toBeEncryptedSecuredMessage);
loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__recipientsPublicKeyCompressed: ", p__recipientsPublicKeyCompressed);
loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__compressedMode: %d", static_cast<int>(p__compressedMode));
// 1. Generate new ephemeral Private/Public keys
security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1);
if (ec.generate() == -1) {
loggers::get_instance().warning(": Failed to generate ephemeral keys");
return OCTETSTRING(0, nullptr);
loggers::get_instance().log_msg(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__salt: ", p__salt);
loggers::get_instance().log(">>> fx__encryptWithEciesBrainpoolp256WithSha256: p__use__hardcoded__values: %x", static_cast<const boolean>(p__use__hardcoded__values));
// 1. Generate new Private/Public Ephemeral key
std::unique_ptr<security_ecc> ec;
if (!static_cast<const boolean>(p__use__hardcoded__values)) {
ec.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1));
if (ec->generate() == -1) {
loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256WithSha256: Failed to generate ephemeral keys");
return OCTETSTRING(0, nullptr);
}
} else {
ec.reset(new security_ecc(ec_elliptic_curves::brainpool_p_256_r1, str2oct("0722B39ABC7B6C5301CA0408F454F81553D7FE59F492DBF385B6B6D1F81E0F68"))); // Hardcoded private key
}
// 2. Generate and derive shared secret
// 2. Generate and derive shared secret based on recipient's private keys
security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientsPublicKeyCompressed, (static_cast<int>(p__compressedMode) == 0) ? ecc_compressed_mode::compressed_y_0 : ecc_compressed_mode::compressed_y_1);
if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), OCTETSTRING(0, nullptr)) == -1) {
if (static_cast<const boolean>(p__use__hardcoded__values)) { // Set AES encryption key to an harcoded value
ec->symmetric_encryption_key(str2oct("5A4E63B247C714644E85CAC49BD26C81"));
}
if (ec->generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256WithSha256: Failed to generate and derive secret key");
return OCTETSTRING(0, nullptr);
}
// Set the AES symmetric key
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key());
p__aes__sym__key = ec.symmetric_encryption_key();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: AES symmetric key: ", ec->symmetric_encryption_key());
p__aes__sym__key = ec->symmetric_encryption_key();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: p__aes__sym__key: ", p__aes__sym__key);
// Set the encrypted symmetric key
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: Symmetric encryption key: ", ec.symmetric_encryption_key());
p__encrypted__sym__key = ec.encrypted_symmetric_key();
loggers::get_instance().log_msg("fx__encryptWithEciesNistp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: Encrypted symmetric key: ", ec->encrypted_symmetric_key());
p__encrypted__sym__key = ec->encrypted_symmetric_key();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
// Set the tag of the symmetric key encryption
p__authentication__vector = ec.tag();
p__authentication__vector = ec->tag();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: p__authentication__vector: ", p__authentication__vector);
// Set ephemeral public keys
p__publicEphemeralKeyCompressed = ec.public_key_compressed();
p__publicEphemeralKeyCompressed = ec->public_key_compressed();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: Ephemeral public compressed key: ", p__publicEphemeralKeyCompressed);
p__ephemeralCompressedMode = (ec.public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1;
p__ephemeralCompressedMode = (ec->public_key_compressed_mode() == ecc_compressed_mode::compressed_y_0) ? 0 : 1;
loggers::get_instance().log("fx__encryptWithEciesBrainpoolp256WithSha256: Ephemeral public compressed mode: %d: ", p__ephemeralCompressedMode);
// 3. Retrieve AES 128 parameters
p__nonce = ec.nonce();
p__nonce = ec->nonce();
loggers::get_instance().log_msg("fx__encryptWithEciesBrainpoolp256WithSha256: p__nonce: ", p__nonce);
OCTETSTRING enc_symm_key = ec.symmetric_encryption_key();
loggers::get_instance().log_msg(": enc_symm_key: ", enc_symm_key);
// 4. Encrypt the data using AES-128 CCM
OCTETSTRING enc_message;
if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
if (ec->encrypt(encryption_algotithm::aes_128_ccm, ec->symmetric_encryption_key(), ec->nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
loggers::get_instance().warning("fx__encryptWithEciesBrainpoolp256WithSha256: Failed to encrypt message");
return OCTETSTRING(0, nullptr);
}
enc_message += ec.tag();
enc_message += ec->tag();
loggers::get_instance().log_to_hexa("fx__encryptWithEciesBrainpoolp256WithSha256: enc message||Tag: ", enc_message);
return enc_message;
}
/**
* @desc Test function for ECIES BRAINPOOL P-256r1 Encryption with SHA-256
* @remark For the purpose of testing, the content of p__toBeEncryptedSecuredMessage is the AES 128 symmetric key to be encrypted
*/
OCTETSTRING fx__test__encryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__toBeEncryptedSecuredMessage, const OCTETSTRING& p__privateEphemeralKey, const OCTETSTRING& p__recipientPublicKeyX, const OCTETSTRING& p__recipientPublicKeyY, const OCTETSTRING& p__salt, OCTETSTRING& p__publicEphemeralKeyX, OCTETSTRING& p__publicEphemeralKeyY, OCTETSTRING& p__aes__sym__key, OCTETSTRING& p__encrypted__sym__key, OCTETSTRING& p__authentication__vector, OCTETSTRING& p__nonce) {
// 1. Generate new ephemeral Private/Public keys
security_ecc ec(ec_elliptic_curves::brainpool_p_256_r1, p__privateEphemeralKey);
p__publicEphemeralKeyX = ec.public_key_x();
p__publicEphemeralKeyY = ec.public_key_y();
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: Vx=", p__publicEphemeralKeyX);
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: Vy=", p__publicEphemeralKeyY);
// 2. Generate and derive shared secret
security_ecc ec_comp(ec_elliptic_curves::brainpool_p_256_r1, p__recipientPublicKeyX, p__recipientPublicKeyY);
ec.symmetric_encryption_key(p__toBeEncryptedSecuredMessage);
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: ", ec.encrypted_symmetric_key());
if (ec.generate_and_derive_ephemeral_key(encryption_algotithm::aes_128_ccm, ec_comp.public_key_x(), ec_comp.public_key_y(), p__salt) == -1) {
loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256WithSha256: Failed to generate and derive secret key");
return OCTETSTRING(0, nullptr);
}
// Set the AES symmetric key
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: AES symmetric key: ", ec.symmetric_encryption_key());
p__aes__sym__key = ec.symmetric_encryption_key();
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: p__aes__sym__key: ", p__aes__sym__key);
// Set the encrypted symmetric key
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: Encrypted symmetric key: ", ec.encrypted_symmetric_key());
p__encrypted__sym__key = ec.encrypted_symmetric_key();
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: p__encrypted__sym__key: ", p__encrypted__sym__key);
// Set the tag of the symmetric key encryption
p__authentication__vector = ec.tag();
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: p__authentication__vector: ", p__authentication__vector);
// 3. Retrieve AES 128 parameters
p__nonce = ec.nonce();
loggers::get_instance().log_msg("fx__test__encryptWithEciesBrainpoolp256WithSha256: p__nonce: ", p__nonce);
// 4. Encrypt the data using AES-128 CCM
OCTETSTRING enc_message;
if (ec.encrypt(encryption_algotithm::aes_128_ccm, ec.symmetric_encryption_key(), ec.nonce(), p__toBeEncryptedSecuredMessage, enc_message) == -1) {
loggers::get_instance().warning("fx__test__encryptWithEciesBrainpoolp256WithSha256: Failed to encrypt message");
return OCTETSTRING(0, nullptr);
}
enc_message += ec.tag();
loggers::get_instance().log_to_hexa("fx__test__encryptWithEciesBrainpoolp256WithSha256: enc message||Tag: ", enc_message);
return enc_message;
}
OCTETSTRING fx__decryptWithEciesBrainpoolp256WithSha256(const OCTETSTRING& p__encryptedSecuredMessage, const OCTETSTRING& p__privateEncKey, const OCTETSTRING& p__publicEphemeralKeyCompressed, const INTEGER& p__ephemeralCompressedMode, const OCTETSTRING& p__encrypted__sym__key, const OCTETSTRING& p__authentication__vector, const OCTETSTRING& p__nonce) {
loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__toBeEncryptedSecuredMessage: ", p__encryptedSecuredMessage);
loggers::get_instance().log_msg(">>> fx__decryptWithEciesBrainpoolp256WithSha256: p__privateEncKey: ", p__privateEncKey);
......
......@@ -17,7 +17,7 @@
* \brief This class provides time tools such as getting current time
*/
class base_time {
const unsigned long long its_base_time = 1072915200000L; //! Base time 01/01/2004 12:00am in millseconds
const unsigned long long its_base_time_ms = 1072915200000L; //! Base time 01/01/2004 12:00am in millseconds
static base_time* _instance;
private:
......@@ -28,9 +28,11 @@ public:
virtual ~base_time() { if (_instance != nullptr) delete _instance; };
public:
inline const unsigned long long get_current_time() const;
inline const unsigned long long get_its_base_time() const;
inline const unsigned long long get_its_current_time() const;
inline const unsigned long long get_current_time_ms() const;
inline const unsigned long long get_its_base_time_ms() const;
inline const unsigned long long get_its_current_time_ms() const;
inline const unsigned long long get_its_current_time_us() const;
inline const unsigned long long get_its_current_time_mod_ms() const;
}; // End of class base_time
// static functions
......@@ -38,14 +40,23 @@ base_time& base_time::get_instance() {
return (_instance != nullptr) ? *_instance : *(_instance = new base_time());
}
const unsigned long long base_time::get_current_time() const {
const unsigned long long base_time::get_current_time_ms() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
}
const unsigned long long base_time::get_its_base_time() const {
return base_time::its_base_time;
const unsigned long long base_time::get_its_base_time_ms() const {
return base_time::its_base_time_ms;
}
const unsigned long long base_time::get_its_current_time() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - base_time::its_base_time;
const unsigned long long base_time::get_its_current_time_ms() const {
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - base_time::its_base_time_ms;
}
const unsigned long long base_time::get_its_current_time_us() const {
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - base_time::its_base_time_ms * 1000;
}
const unsigned long long base_time::get_its_current_time_mod_ms() const {
return (std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count() - base_time::its_base_time_ms) % 65536;
}
......@@ -114,13 +114,13 @@ public:
* \param[in] p_value The string value
* \return The hexadecimal value
*/
std::string string_to_hexa(const std::string & p_value);
std::string string_to_hexa(const std::string & p_value, const bool p_uppercase = false);
/*!
* \brief Convert a bytes array int32_t an hexadecimal string
* \param[in] p_value The bytes array value
* \return The hexadecimal value
*/
std::string bytes_to_hexa(const std::vector<uint8_t> & p_value);
std::string bytes_to_hexa(const std::vector<uint8_t> & p_value, const bool p_uppercase = false);
/*!
* \brief Convert an hexadecimal string into a bytes array
* \param[in] p_value The hexadecimal value
......@@ -328,8 +328,24 @@ public:
return ss.str();
}; // End of string_to_bytes
/*!
* \brief Convert a string in to lower case
* \param[in/out] p_value The string value to convert
*/
inline void to_lower(std::string& p_value) {
std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::tolower);
}
/*!
* \brief Convert a string in to upper case
* \param[in/out] p_value The string value to convert
*/
inline void to_upper(std::string& p_value) {
std::transform(p_value.begin(), p_value.end(), p_value.begin(), ::toupper);
}
public:
/*!
* \brief Returns a copy of the string, with leading and trailing special characters omitted
* \param[in] p_value The string value
......@@ -369,5 +385,22 @@ public:
*/
std::vector<std::string> split_arguments_line(const std::string & p_value);
static const std::string lut;
/*!
* \brief Convert the provided buffer into a Base64
* \param[in] p_value The buffer value
* \return The Base64 encoded buffert
*/
std::vector<unsigned char> buffer_to_base64(const std::vector<unsigned char> & p_value);
/*!
* \brief Convert the provided Base64 buffer
* \param[in] p_value The buffer value
* \return The Base64 encoded buffert
*/
std::vector<unsigned char> base64_to_buffer(const std::vector<unsigned char> & p_value);
static const std::string lut_u;
static const std::string lut_l;
static const std::string base64_enc_map;
}; // End of class converter
......@@ -12,8 +12,9 @@ uint32_t converter::swap(const uint32_t p_value) {
return (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
}
const std::string converter::lut = "0123456789ABCDEF";
std::string converter::string_to_hexa(const std::string & p_value) {
const std::string converter::lut_u = "0123456789ABCDEF";
const std::string converter::lut_l = "0123456789abcdef";
std::string converter::string_to_hexa(const std::string & p_value, const bool p_uppercase) {
std::string input(p_value);
std::for_each(
......@@ -27,30 +28,49 @@ std::string converter::string_to_hexa(const std::string & p_value) {
std::string output;
uint32_t length = p_value.length();
output.reserve(2 * length);
for (uint32_t i = 0; i < length; ++i) {
const uint8_t c = input[i];
output.push_back(lut[c >> 4]);
output.push_back(lut[c & 15]);
} // End of 'for' statement
if (p_uppercase) { // TODO Use pointer to reduce code size
for (uint32_t i = 0; i < length; ++i) {
const uint8_t c = input[i];
output.push_back(lut_u[c >> 4]);
output.push_back(lut_u[c & 15]);
} // End of 'for' statement
} else {
for (uint32_t i = 0; i < length; ++i) {
const uint8_t c = input[i];
output.push_back(lut_l[c >> 4]);
output.push_back(lut_l[c & 15]);
} // End of 'for' statement
}
return output;
}
std::string converter::bytes_to_hexa(const std::vector<uint8_t> & p_value) {
std::string converter::bytes_to_hexa(const std::vector<uint8_t> & p_value, const bool p_uppercase) {
std::string ret;
ret.assign(p_value.size()*2, ' ');
for(size_t i=0; i<p_value.size(); i++){
uint8_t c = p_value[i];
ret[i*2] = lut[c>>4];
ret[i*2+1] = lut[c&0xF];
if (p_uppercase) { // TODO Use pointer to reduce code size
for(size_t i=0; i<p_value.size(); i++){
uint8_t c = p_value[i];
ret[i*2] = lut_u[c>>4];
ret[i*2+1] = lut_u[c&0xF];
}
} else {
for(size_t i=0; i<p_value.size(); i++){
uint8_t c = p_value[i];
ret[i*2] = lut_l[c>>4];
ret[i*2+1] = lut_l[c&0xF];
}
}
return ret;
}
inline uint8_t char2byte(const char ch) {
size_t s = converter::lut.find(ch);
if(s == std::string::npos)
throw (std::length_error(""));
inline uint8_t char2byte(const char p_ch) {
size_t s = converter::lut_l.find(p_ch);
if(s == std::string::npos) {
if ((s = converter::lut_u.find(p_ch)) == std::string::npos) {
throw (std::length_error(""));
}
}
return s;
}
......@@ -133,3 +153,50 @@ std::vector<std::string> converter::split_arguments_line(const std::string & p_v
} // else, invalid command line
return output;
}
const std::string converter::base64_enc_map = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
std::vector<unsigned char> converter::buffer_to_base64(const std::vector<unsigned char> & p_value) {
std::vector<unsigned char> out;
int val = 0, valb = -6;
for (unsigned char c : p_value) {
val = (val << 8) + c;
valb += 8;
while (valb >= 0) {
out.push_back(converter::base64_enc_map[(val >> valb) & 0x3F]);
valb -= 6;
} // End of 'while' statement
} // End of 'for' statement
if (valb > -6) {
out.push_back(converter::base64_enc_map[((val << 8) >> (valb + 8)) & 0x3F]);
}
while (out.size() % 4) {
out.push_back('=');
} // End of 'while' statement
return out;
}
std::vector<unsigned char> converter::base64_to_buffer(const std::vector<unsigned char> &p_value) {
std::vector<unsigned char> out;
std::vector<int> T(256, -1);
for (int i = 0; i < 64; i++) {
T[converter::base64_enc_map[i]] = i;
}
int val = 0, valb = -8;
for (unsigned char c : p_value) {
if (T[c] == -1) {
break;
}
val = (val << 6) + T[c];
valb += 6;
if (valb >= 0) {
out.push_back((unsigned char)char((val >> valb) & 0xFF));
valb -= 8;
}
} // End of 'for' statement
return out;
}
......@@ -288,7 +288,7 @@ void geonetworking_layer::receive_data(OCTETSTRING& data, params& params) {
eh->lsReplyHeader().dstPosVector().latitude() = sopv->latitude();
eh->lsReplyHeader().dstPosVector().longitude() = sopv->longitude();
// Update timestamp
eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time());
eh->lsReplyHeader().srcPosVector().timestamp__().set_long_long_val(base_time::get_instance().get_its_current_time_mod_ms());
eh->lsReplyHeader().dstPosVector().timestamp__() = eh->lsReplyHeader().srcPosVector().timestamp__();
loggers::get_instance().log_msg("geonetworking_layer::receive_data: ", *_ls_reply);
......@@ -486,7 +486,7 @@ void geonetworking_layer::send_beacon() {
loggers::get_instance().error("geonetworking_layer::send_beacon: Wrong cast");
}
// Update timestamp
eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time());
eh->beaconHeader().srcPosVector().timestamp__().set_long_long_val((unsigned int)base_time::get_instance().get_its_current_time_mod_ms());
//loggers::get_instance().log_msg("geonetworking_layer::send_beacon: ", *_beacon);
// Encode message using TITAN because of payload in omited
TTCN_Buffer encoding_buffer;
......@@ -943,7 +943,7 @@ int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING& data, params& para
_shb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_shb_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time()));
eh->shbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: shb: ", *_shb_packet);
// Encode GeoNetworking PDU
......@@ -969,7 +969,7 @@ int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING& data, params& para
_tsb_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_tsb_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->tsbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time()));
eh->tsbHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: tsb: ", *_tsb_packet);
// Encode GeoNetworking PDU
......@@ -997,7 +997,7 @@ int geonetworking_layer::build_geonetworking_pdu(OCTETSTRING& data, params& para
_gbc_packet->gnPacket().packet().commonHeader().plLength() = data.lengthof();
_gbc_packet->gnPacket().packet().payload() = OPTIONAL<OCTETSTRING>(data);
// Update timestamp
eh->geoBroadcastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time()));
eh->geoBroadcastHeader().srcPosVector().timestamp__().set_long_long_val(static_cast<unsigned int>(base_time::get_instance().get_its_current_time_mod_ms()));
loggers::get_instance().log_msg("geonetworking_layer::build_geonetworking_pdu: gbc: ", *_gbc_packet);
......
......@@ -159,9 +159,9 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si
const OPTIONAL<INTEGER>& v = dynamic_cast<const OPTIONAL<INTEGER>& >(header_info.generationTime()); // in millisecond
unsigned long long gt = ((INTEGER&)(*v.get_opt_value())).get_long_long_val();
// Get current time timestamp
unsigned long long ms = base_time::get_instance().get_current_time(); // in millisecond
loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld", header_info.generationTime(), ms);
if (abs((double)gt - (double)ms) >= 5.0) { // TODO Use a params for generation_time_epsilon
unsigned long long us = base_time::get_instance().get_its_current_time_us(); // in millisecond
loggers::get_instance().log("security_services::process_ieee_1609_dot2_signed_data: generation time check %ld / %ld, delta = %f", header_info.generationTime(), us, abs((double)gt - (double)us));
if (abs((double)gt - (double)us) >= 5.0) { // TODO Use a params for generation_time_epsilon
loggers::get_instance().warning("security_services::process_ieee_1609_dot2_signed_data: Invalid generation time, discard it");
if (p_verify) {
return -1;
......@@ -306,6 +306,10 @@ int security_services::process_ieee_1609_dot2_signed_data(const IEEE1609dot2::Si
result = -1;
if (p_signed_data.signature__().ischosen(IEEE1609dot2BaseTypes::Signature::ALT_ecdsaNistP256Signature)) {
result = verify_sign_ecdsa_nistp256(hashed_data, p_signed_data.signature__(), certificate_id, p_params);
} else if (p_signed_data.signature__().ischosen(IEEE1609dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP256r1Signature)) {
result = verify_sign_ecdsa_brainpoolp256r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params);
} else if (p_signed_data.signature__().ischosen(IEEE1609dot2BaseTypes::Signature::ALT_ecdsaBrainpoolP384r1Signature)) {
result = verify_sign_ecdsa_brainpoolp384r1(hashed_data, p_signed_data.signature__(), certificate_id, p_params);
} else {
// TODO
loggers::get_instance().error("security_services::process_ieee_1609_dot2_signed_data: TODO");
......@@ -486,10 +490,12 @@ int security_services::sign_payload(const OCTETSTRING& p_unsecured_gn_payload, O
loggers::get_instance().log("security_services::sign_payload: Payload type not set");
// Noting to do
}
unsigned long long ms = base_time::get_instance().get_its_current_time();
unsigned long long us = base_time::get_instance().get_its_current_time_us();
loggers::get_instance().log("security_services::sign_payload: HeaderInfo timestamp: %ld", us);
INTEGER i;
i.set_long_long_val((unsigned int)ms);
i.set_long_long_val(us);
header_info.generationTime() = OPTIONAL<INTEGER>(i);
loggers::get_instance().log("security_services::sign_payload: Finame HeaderInfo timestamp: %ld", us);
// Check if a certificate shall be requested
if (_unknown_certificate.lengthof() == 3) { // HashedId3
IEEE1609dot2BaseTypes::SequenceOfHashedId3 s;
......@@ -512,10 +518,10 @@ int security_services::sign_payload(const OCTETSTRING& p_unsecured_gn_payload, O
return -1;
}
IEEE1609dot2::SignerIdentifier signer;
loggers::get_instance().log("security_services::sign_payload: ms = %d - _last_generation_time = %d - ms - _last_generation_time = %d", (unsigned int)ms, _last_generation_time, (unsigned int)(ms - _last_generation_time));
loggers::get_instance().log("security_services::sign_payload: us = %d - _last_generation_time = %ld - us - _last_generation_time = %ld", us, _last_generation_time, us - _last_generation_time);
std::string certificate_id = p_params[params::certificate];
loggers::get_instance().log("security_services::sign_payload: certificate_id = %s", certificate_id.c_str());
if ((unsigned int)(ms - _last_generation_time) >= 1000 * 0.95) { // Need to add certificate
if ((unsigned int)(us - _last_generation_time) >= 1000 * 0.95) { // Need to add certificate
loggers::get_instance().log("security_services::sign_payload: Need to add certificate");
IEEE1609dot2::CertificateBase cert;
if (_security_db->get_certificate(certificate_id, cert) != 0) {
......@@ -526,7 +532,7 @@ int security_services::sign_payload(const OCTETSTRING& p_unsecured_gn_payload, O
sequenceOfCertificate[0] = cert;
signer.certificate() = sequenceOfCertificate;
// Reset send certificate timer
_last_generation_time = ms;
_last_generation_time = us;
} else {
loggers::get_instance().log("security_services::sign_payload: Add digest");
OCTETSTRING digest;
......@@ -906,6 +912,176 @@ int security_services::verify_sign_ecdsa_nistp256(const OCTETSTRING& p_hash, con
return -1;
}
int security_services::sign_ecdsa_brainpoolp256r1(const OCTETSTRING& p_hash, IEEE1609dot2BaseTypes::Signature& p_signature, params& p_params) {
loggers::get_instance().log_msg(">>> security_services::sign_ecdsa_brainpoolp256r1: ", p_hash);
std::string certificate_id = p_params[params::certificate];
loggers::get_instance().log("security_services::sign_ecdsa_brainpoolp256r1: encoded certificate_id = '%s'", certificate_id.c_str());
OCTETSTRING pkey;
if (_security_db->get_private_key(certificate_id, pkey) != 0) {
loggers::get_instance().warning("security_services::sign_ecdsa_brainpoolp256r1: Failed to get private key");
return -1;
}
// Hash ( Hash (Data input) || Hash (Signer identifier input) )
OCTETSTRING hash_cert;
if (_security_db->get_hash(certificate_id, hash_cert) != 0) {