Commit 39cc77b5 authored by garciay's avatar garciay
Browse files

Add signatures support

parent 6d7fc90b
Loading
Loading
Loading
Loading
+12 −114
Original line number Diff line number Diff line
@@ -18,10 +18,20 @@ namespace LibItsSecurity__EncdecDeclarations {
    return oct2bit(os);
  }

  INTEGER fx__dec__CertificateBase(BITSTRING& b, IEEE1609dot2::CertificateBase& p) {
  INTEGER fx__dec__CertificateBase(BITSTRING& b, IEEE1609dot2::CertificateBase& p_cert) {
    loggers::get_instance().log_msg(">>> fx__dec__CertificateBase: ", b);

    EtsiTs103097Codec codec;
    OCTETSTRING is = bit2oct(b);
    if (codec.decode(is, p_cert) == -1) {
      loggers::get_instance().warning("fx__dec__CertificateBase: -1 result code was returned");
      return -1;
    }
    
    loggers::get_instance().log_msg("<<< fx__dec__CertificateBase: ", p_cert);
    return 0;
  }
  
  BITSTRING fx__enc__ToBeSignedCertificate(const IEEE1609dot2::ToBeSignedCertificate& p) {
    return int2bit(0, 1);
  }
@@ -30,116 +40,4 @@ namespace LibItsSecurity__EncdecDeclarations {
    return int2bit(0, 1);
  }
  











  
  /*INTEGER fx__dec__ToBeSignedCertificate(BITSTRING& b, LibItsSecurity__TypesAndValues::ToBeSignedCertificate& p) {
    loggers::get_instance().log_msg(">>> fx__dec__ToBeSignedCertificate: ", b);

    return -1;
    }*/
  
/****************************************************
 * @desc    External function to encode a SecuredMessage type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
// BITSTRING fx__enc__SecuredMessage(const LibItsSecurity__TypesAndValues::SecuredMessage& p)
// {
//   return int2bit(0,8);
// }

/****************************************************
 * @desc    External function to encode a SecuredMessage type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
/*BITSTRING fx__enc__SecuredMessage(const LibItsSecurity__TypesAndValues::SecuredMessage& p)
{
  return int2bit(0,8);
  }*/

/****************************************************
 * @desc    External function to decode a SecuredMessage type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/

/*INTEGER fx__dec__SecuredMessage(BITSTRING& b, LibItsSecurity__TypesAndValues::SecuredMessage& p)
{
  return -1;
  }*/

/****************************************************
 * @desc    External function to encode a ToBeSignedSecuredMessage type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
/*BITSTRING fx__enc__ToBeSignedSecuredMessage(const LibItsSecurity__TypesAndValues::ToBeSignedSecuredMessage& p)
{
  return int2bit(0,8);
  }*/

/****************************************************
 * @desc    External function to decode a ToBeSignedSecuredMessage type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/

/*INTEGER fx__dec__ToBeSignedSecuredMessage(BITSTRING& b, LibItsSecurity__TypesAndValues::ToBeSignedSecuredMessage& p)
{
  return -1;
  }*/

/****************************************************
 * @desc    External function to encode a Certificate type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
/*BITSTRING fx__enc__Certificate(const LibItsSecurity__TypesAndValues::Certificate& p)
{
  return int2bit(0,8);
  }*/

/****************************************************
 * @desc    External function to decode a Certificate type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/

/*INTEGER fx__dec__Certificate(BITSTRING& b, LibItsSecurity__TypesAndValues::Certificate& p)
{
  return -1;
  }*/

/****************************************************
 * @desc    External function to encode a ToBeSignedCertificate type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
/*BITSTRING fx__enc__ToBeSignedCertificate(const LibItsSecurity__TypesAndValues::ToBeSignedCertificate& p)
{
  return int2bit(0,8);
  }*/

/****************************************************
 * @desc    External function to decode a ToBeSignedCertificate type
 * @param   value to encode
 * @return  encoded value
 ****************************************************/
/*
INTEGER fx__dec__ToBeSignedCertificate(BITSTRING& b, LibItsSecurity__TypesAndValues::ToBeSignedCertificate& p)
{
  return -1;
}
*/
} //end namespace
+363 −364
Original line number Diff line number Diff line
#include "LibItsSecurity_Functions.hh"

#include <openssl/sha.h>
#include "sha256.hh"
#include "sha384.hh"
#include "ec_keys.hh"

#include <openssl/ec.h>
#include <openssl/ecdsa.h>
#include <openssl/objects.h>

#include "loggers.hh"

#define FIELD_SIZE_256 (256/8)
#define SIGNATURE_SIZE_256 (2+FIELD_SIZE_256*2)
@@ -12,8 +16,8 @@

namespace LibItsSecurity__Functions 
{
//        group signing
/*          * @desc    Produces a 256-bit (32-byte) hash value
  /**
   * @desc    Produces a 256-bit (32-byte) hash value
   * @param   p_toBeHashedData Data to be used to calculate the hash value
   * @return  The hash value
   fx_hashWithSha256(in octetstring p_toBeHashedData) return Oct32;
@@ -21,11 +25,26 @@ namespace LibItsSecurity__Functions
  OCTETSTRING fx__hashWithSha256(
                                 const OCTETSTRING& p__toBeHashedData
                                 ) {

  unsigned char sha256[SHA_DIGEST_LENGTH];
  SHA256((const unsigned char*)p__toBeHashedData,p__toBeHashedData.lengthof(),sha256);
  return OCTETSTRING(SHA_DIGEST_LENGTH,sha256);
}
    sha256 hash;
    std::vector<unsigned char> hashData;
    hash.generate(static_cast<const unsigned char*>(p__toBeHashedData), p__toBeHashedData.lengthof(), hashData);
    return OCTETSTRING(hashData.size(), hashData.data());
  } // End of function fx__hashWithSha256

  /**
   * @desc    Produces a 384-bit (48-byte) hash value
   * @param   p_toBeHashedData Data to be used to calculate the hash value
   * @return  The hash value
   fx_hashWithSha384(in octetstring p_toBeHashedData) return Oct48;
  */
  OCTETSTRING fx__hashWithSha384(
                                 const OCTETSTRING& p__toBeHashedData
                                 ) {
    sha384 hash;
    std::vector<unsigned char> hashData;
    hash.generate(static_cast<const unsigned char*>(p__toBeHashedData), p__toBeHashedData.lengthof(), hashData);
    return OCTETSTRING(hashData.size(), hashData.data());
  } // End of function fx__hashWithSha384

  /*          * @desc    Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signaturee
   * @param   p_toBeSignedSecuredMessage    The data to be signed
@@ -37,41 +56,31 @@ OCTETSTRING fx__signWithEcdsaNistp256WithSha256(
                                                  const OCTETSTRING& p__toBeSignedSecuredMessage,
                                                  const OCTETSTRING& p__privateKey
                                                  ) {

  unsigned char sha256[SHA_DIGEST_LENGTH];
  unsigned char signature[SIGNATURE_SIZE_256];
  unsigned char *r = &signature[2], *s = &signature[2+FIELD_SIZE_256];
  memset(signature, 0, sizeof(signature));
  // signature[0] = 0; // ecdsa_nistp256_with_sha256
  // signature[1] = 0; // uncompressed

  SHA256((const unsigned char*)p__toBeSignedSecuredMessage,p__toBeSignedSecuredMessage.lengthof(),sha256);

  EC_KEY * k = EC_KEY_new();

  EC_GROUP * group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
  EC_KEY_set_group(k, group);
  EC_GROUP_free(group);

  BIGNUM * p = BN_new();
  BN_bin2bn((const unsigned char*)p__privateKey, p__privateKey.lengthof(), p);
  EC_KEY_set_private_key(k, p);
  BN_clear_free(p);
  
  if (0 == EC_KEY_check_key(k)){
    
    ECDSA_SIG *sig;
    sig = ECDSA_do_sign(sha256, SHA_DIGEST_LENGTH, k);
    BN_bn2bin(sig->r, r);
    BN_bn2bin(sig->s, s);
    ECDSA_SIG_free(sig);
    sha256 hash;
    std::vector<unsigned char> hashData;
    // TODO Create SHX interface and add generate method with std::vector
    //std::vector<unsigned char> tbs(p__toBeSignedSecuredMessage.lengthof(), static_cast<const unsigned char *>(p__toBeSignedSecuredMessage));
    // hash.generate(tbs, hashData);
    hash.generate(static_cast<const unsigned char*>(p__toBeSignedSecuredMessage), p__toBeSignedSecuredMessage.lengthof(), hashData);
    const unsigned char * p = static_cast<const unsigned char *>(p__privateKey);
    std::vector<unsigned char> p_key(p, p + p__privateKey.lengthof());
    ec_keys k(ec_elliptic_curves::nist_p_256, p_key);
    std::vector<unsigned char> r_sig;
    std::vector<unsigned char> s_sig;
    if (k.sign(hashData, r_sig, s_sig) == 0) {
      OCTETSTRING os(r_sig.size(), r_sig.data());
      // loggers::get_instance().log_to_hexa("r_sig= ", os); 
      // loggers::get_instance().log_to_hexa("s_sig= ", OCTETSTRING(s_sig.size(), s_sig.data()); 
      // loggers::get_instance().log_to_hexa("sig= ", os += OCTETSTRING(s_sig.size(), s_sig.data())); 
      os += OCTETSTRING(s_sig.size(), s_sig.data());
      return os;
    }
  EC_KEY_free(k);

  return OCTETSTRING(sizeof(signature), signature);
    return OCTETSTRING();
  }

/*          * @desc    Verify the signature of the specified data
  /**
   * @desc    Verify the signature of the specified data
   * @param   p_toBeVerifiedData          The data to be verified
   * @param   p_signature                 The signature
   * @param   p_ecdsaNistp256PublicKeyX   The public key (x coordinate)
@@ -85,49 +94,28 @@ BOOLEAN fx__verifyWithEcdsaNistp256WithSha256(
                                                const OCTETSTRING& p__ecdsaNistp256PublicKeyX,
                                                const OCTETSTRING& p__ecdsaNistp256PublicKeyY
                                                ) {
  unsigned char sha256[SHA_DIGEST_LENGTH];
  
  SHA256((const unsigned char*)p__toBeVerifiedData,p__toBeVerifiedData.lengthof(),sha256);
  const unsigned char * r = (const unsigned char*)p__signature;
  const unsigned char * x = (const unsigned char*)p__ecdsaNistp256PublicKeyX;
  const unsigned char * y = (const unsigned char*)p__ecdsaNistp256PublicKeyY;
  int alg = 0, type = 0;
  if(p__signature.lengthof() >= SIGNATURE_SIZE_256)
    alg = *(r++);
  if(p__signature.lengthof() >= (SIGNATURE_SIZE_256-1))
    type = *(r++);

  ECDSA_SIG * sig = ECDSA_SIG_new();
  BN_bin2bn(r,    32, sig->s);
  BN_bin2bn(r+32, 32, sig->r);

  EC_KEY * k;
  EC_GROUP * group;
  EC_POINT * pnt;
  BIGNUM *bnx, *bny;

  k = EC_KEY_new();

  group = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1);
  EC_KEY_set_group(k, group);
  EC_GROUP_free(group); 

  pnt = EC_POINT_new(group);
  bnx = BN_new(); BN_bin2bn(x, p__ecdsaNistp256PublicKeyX.lengthof(), bnx);
  bny = BN_new(); BN_bin2bn(y, p__ecdsaNistp256PublicKeyY.lengthof(), bny);
  EC_POINT_set_affine_coordinates_GFp(group, pnt, bnx, bny, NULL);
  BN_clear_free(bnx); BN_clear_free(bny);
  EC_KEY_set_public_key(k, pnt);
  EC_POINT_free(pnt);

  int rc = ECDSA_do_verify(sha256, SHA_DIGEST_LENGTH, sig, k);
  EC_KEY_free(k);
  ECDSA_SIG_free(sig);

  return rc==0 ? TRUE : FALSE;
    sha256 hash;
    std::vector<unsigned char> hashData;
    // TODO Create SHX interface and add generate method with std::vector
    //std::vector<unsigned char> tbs(p__toBeSignedSecuredMessage.lengthof(), static_cast<const unsigned char *>(p__toBeSignedSecuredMessage));
    // hash.generate(tbs, hashData);
    hash.generate(static_cast<const unsigned char*>(p__toBeVerifiedData), p__toBeVerifiedData.lengthof(), hashData);
    const unsigned char * p = static_cast<const unsigned char *>(p__signature);
    std::vector<unsigned char> signature(p, p + p__signature.lengthof());
    p = static_cast<const unsigned char *>(p__ecdsaNistp256PublicKeyX);
    std::vector<unsigned char> pub_key_x(p, p + p__ecdsaNistp256PublicKeyX.lengthof());
    p = static_cast<const unsigned char *>(p__ecdsaNistp256PublicKeyY);
    std::vector<unsigned char> pub_key_y(p, p + p__ecdsaNistp256PublicKeyY.lengthof());
    ec_keys k(ec_elliptic_curves::nist_p_256, pub_key_x, pub_key_y);
    if (k.sign_verif(hashData, signature, pub_key_x, pub_key_y) == 0) {
      return true;
    }

    return false;
  }

/*          * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
  /**
   * @desc    Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm.
   *          This function should not be used by the ATS
   * @param   p_privateKey    The new private key value
   * @param   p_publicKeyX    The new public key value (x coordinate)
@@ -140,6 +128,17 @@ BOOLEAN fx__generateKeyPair(
                              OCTETSTRING& p__publicKeyX,
                              OCTETSTRING& p__publicKeyY
                              ) {
    ec_keys k(ec_elliptic_curves::nist_p_256);
    if (k.generate() != 0) {
      p__privateKey = OCTETSTRING();
      p__publicKeyX = OCTETSTRING();
      p__publicKeyY = OCTETSTRING();
      return FALSE;
    }

    p__privateKey = OCTETSTRING(k.private_key().size(), k.private_key().data());
    p__publicKeyX = OCTETSTRING(k.public_key_x().size(), k.public_key_x().data());
    p__publicKeyY = OCTETSTRING(k.public_key_y().size(), k.public_key_y().data());
    return TRUE;
  }

+9 −23
Original line number Diff line number Diff line
@@ -8,43 +8,29 @@

int EtsiTs103097Codec::encode (const IEEE1609dot2::CertificateBase& p_cert, OCTETSTRING& data)
{
  loggers::get_instance().log(">>> EtsiTs103097Codec::encode");
  loggers::get_instance().log(">>> EtsiTs103097Codec::encode: %s", p_cert.get_descriptor()->name);
  
  BITSTRING b;
  TTCN_EncDec::clear_error();
  TTCN_Buffer buffer;
  p_cert.encode(*p_cert.get_descriptor(), buffer, TTCN_EncDec::CT_OER);
  /*loggers::get_instance().log("EtsiTs103097Codec::encode: processing Record_Type %s", p_cert.get_descriptor()->name);
  for(int i = 0; i < p_cert.get_count(); i++) {
    loggers::get_instance().log("EtsiTs103097Codec::encode_: processing %s/%s/%s - %d (1 ==> use dynamic_cast<const OPTIONAL<...>) - %d", p_cert.fld_name(i), p_cert.fld_descr(i)->name, p_cert.get_at(i)->get_descriptor()->name, p_cert.get_at(i)->is_optional(), p_cert.get_at(i)->is_present());
    if (p_cert.get_at(i)->is_present()) {
      p_cert.get_at(i)->encode(*p_cert.get_at(i)->get_descriptor(), buffer, TTCN_EncDec::CT_OER);
    }
    loggers::get_instance().log_to_hexa("EtsiTs103097Codec::encode: New encoding buffer: ", buffer);
  } // End of 'for' statement
  */data = OCTETSTRING(buffer.get_len(), buffer.get_data());
  data = OCTETSTRING(buffer.get_len(), buffer.get_data());
  loggers::get_instance().log_msg("EtsiTs103097Codec::encode: ", data);

  return 0;
  // Int Rc = Asncodec.Encode(p_cert, b);
  // if(rc){
  //   data = bit2oct(b);
  //   loggers::get_instance().log_msg("EtsiTs103097Codec::encode: ", data);
  // }
  // return rc;
}

int EtsiTs103097Codec::decode (const OCTETSTRING& data, IEEE1609dot2::CertificateBase& p_cert, Params* params)
{
  loggers::get_instance().log_msg(">>> EtsiTs103097Codec::decode: ", data);

  return -1;
  // int rc = asnCodec.decode(oct2bit(data), p_cert);
  // loggers::get_instance().log("EtsiTs103097Codec::decode: ASN.1 codec returned %d", rc);
  // if(rc) {
  //   loggers::get_instance().log_msg("EtsiTs103097Codec::decode: ", p_cert);
  // }
  // return rc;
  TTCN_EncDec::clear_error();
  TTCN_Buffer decoding_buffer(data);
  _params = params;
  p_cert.decode(*p_cert.get_descriptor(), decoding_buffer, TTCN_EncDec::CT_OER);
  
  loggers::get_instance().log_msg("<<< EtsiTs103097Codec::decode: ", (const Base_Type&)p_cert);
  return 0;
}

extern "C" {
+235 −0
Original line number Diff line number Diff line
#include <openssl/ecdsa.h>

#include "ec_keys.hh"

#include "loggers.hh" // To be remove to build a security shared library

ec_keys::ec_keys(const ec_elliptic_curves p_elliptic_curve): _elliptic_curve(p_elliptic_curve), _ec_key(nullptr), _ec_group(nullptr), _bn_ctx(nullptr), _pr_key(), _pu_key_x(), _pu_key_y() {
  loggers::get_instance().log(">>> ec_keys::ec_keys: %d", static_cast<int>(p_elliptic_curve));
  
  ::ERR_load_crypto_strings();

  int result;
  switch (p_elliptic_curve) {
  case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve 
    result = ::OBJ_txt2nid("prime256v1");
    if (result < 0) {
      loggers::get_instance().error("ec_keys::ec_keys: Unsupported EC prime256v1 elliptic_curve");
    }
    _ec_key = ::EC_KEY_new_by_curve_name(result); // Set the elliptic curve
    break;
  default:
    loggers::get_instance().error("ec_keys::ec_keys: Unsupported EC elliptic_curve");
  } // End of 'switch' statement
  ::EC_KEY_set_asn1_flag(_ec_key, OPENSSL_EC_NAMED_CURVE); // Used to save and retrieve keys
  _ec_group = ::EC_KEY_get0_group(_ec_key); // Get pointer to the EC_GROUP
  _bn_ctx = ::BN_CTX_new();
} // End of constructor

ec_keys::ec_keys(const ec_elliptic_curves p_elliptic_curve, const std::vector<unsigned char>& p_private_key): _elliptic_curve(p_elliptic_curve), _ec_key(nullptr), _ec_group(nullptr), _bn_ctx(nullptr), _pr_key(p_private_key), _pu_key_x(), _pu_key_y() {
  loggers::get_instance().log(">>> ec_keys::ec_keys (1): %d", static_cast<int>(p_elliptic_curve));
  
  ::ERR_load_crypto_strings();

  int result;
  switch (p_elliptic_curve) {
  case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve 
    result = ::OBJ_txt2nid("prime256v1");
    if (result < 0) {
      loggers::get_instance().error("ec_keys::ec_keys (1): Unsupported EC prime256v1 elliptic_curve");
    }
    _ec_key = ::EC_KEY_new_by_curve_name(result); // Set the elliptic curve
    break;
  default:
    loggers::get_instance().error("ec_keys::ec_keys (1): Unsupported EC elliptic_curve");
  } // End of 'switch' statement
  ::EC_KEY_set_asn1_flag(_ec_key, OPENSSL_EC_NAMED_CURVE); // Used to save and retrieve keys
  ::EC_KEY_set_conv_form(_ec_key, POINT_CONVERSION_COMPRESSED);
  _ec_group = ::EC_KEY_get0_group(_ec_key); // Get pointer to the EC_GROUP

  _bn_ctx = ::BN_CTX_new();
  
  // TODO Sanity checks on key size

  // Build private key
  BIGNUM p;
  ::BN_init(&p);
  ::BN_bin2bn(_pr_key.data(), _pr_key.size(), &p);
  // Build public keys
  EC_POINT* ec_point = ::EC_POINT_new(_ec_group);
  ::EC_POINT_mul(_ec_group, ec_point, &p, NULL, NULL, _bn_ctx);
  // Set private key
  ::EC_KEY_set_private_key(_ec_key, &p);
  if (::EC_KEY_check_key(_ec_key) != 0) {
    loggers::get_instance().error("ec_keys::ec_keys (1): Invalid private key");
  }
  // Private key is correct, set public keys
  ::EC_KEY_set_public_key(_ec_key, ec_point);

  BIGNUM xy;
  ::BN_init(&xy);
  ::EC_POINT_point2bn(_ec_group, ec_point, POINT_CONVERSION_COMPRESSED, &xy, _bn_ctx);
  std::vector<unsigned char> v(BN_num_bytes(&xy));
  BN_bn2bin(&xy, v.data());
  const int l = v.size() / 2;
  _pu_key_x.resize(l);
  std::copy(v.cbegin(), v.cbegin() + l - 1, _pu_key_x.begin());
  _pu_key_y.resize(l);
  std::copy(v.cbegin() + l, v.cend(), _pu_key_y.begin());
  ::EC_POINT_free(ec_point);
  
} // End of constructor

ec_keys::ec_keys(const ec_elliptic_curves p_elliptic_curve, const std::vector<unsigned char>& p_public_key_x, const std::vector<unsigned char>& p_public_key_y): _elliptic_curve(p_elliptic_curve), _ec_key(nullptr), _ec_group(nullptr), _bn_ctx(nullptr), _pr_key(), _pu_key_x(p_public_key_x), _pu_key_y(p_public_key_y) {
  loggers::get_instance().log(">>> ec_keys::ec_keys (2): %d", static_cast<int>(p_elliptic_curve));
  
  ::ERR_load_crypto_strings();

  int result;
  switch (p_elliptic_curve) {
  case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve 
    result = ::OBJ_txt2nid("prime256v1");
    if (result < 0) {
      loggers::get_instance().error("ec_keys::ec_keys (2): Unsupported EC prime256v1 elliptic_curve");
    }
    _ec_key = ::EC_KEY_new_by_curve_name(result); // Set the elliptic curve
    break;
  default:
    loggers::get_instance().error("ec_keys::ec_keys (2): Unsupported EC elliptic_curve");
  } // End of 'switch' statement
  ::EC_KEY_set_asn1_flag(_ec_key, OPENSSL_EC_NAMED_CURVE); // Used to save and retrieve keys
  ::EC_KEY_set_conv_form(_ec_key, POINT_CONVERSION_COMPRESSED);
  _ec_group = ::EC_KEY_get0_group(_ec_key); // Get pointer to the EC_GROUP

  _bn_ctx = ::BN_CTX_new();
  
  // TODO Sanity checks on key size
  
  // Set public key
  BIGNUM x;
  ::BN_init(&x);
  ::BN_bin2bn(_pu_key_x.data(), _pu_key_x.size(), &x);
  BIGNUM y;
  ::BN_init(&y);
  ::BN_bin2bn(_pu_key_y.data(), _pu_key_y.size(), &y);
  EC_POINT* ec_point = ::EC_POINT_new(_ec_group);
  result = 0;
  switch (_elliptic_curve) {
  case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve: Use primary
    result = ::EC_POINT_set_affine_coordinates_GFp(_ec_group, ec_point, &x, &y, _bn_ctx); // Use primary elliptic curve
    break;
  default:
    result = ::EC_POINT_set_affine_coordinates_GF2m(_ec_group, ec_point, &x, &y, _bn_ctx);
  } // End of 'switch' statement
  if (result == 0) {
    loggers::get_instance().error("ec_keys::ec_keys (1): Failed to get coordinates");
  }
  ::EC_KEY_set_public_key(_ec_key, ec_point);
  ::EC_POINT_free(ec_point);
} // End of constructor

ec_keys::~ec_keys() {
  loggers::get_instance().log(">>> ec_keys::~ec_keys");
  if(_ec_key != nullptr) {
    ::EC_KEY_free(_ec_key);
  }
  BN_CTX_free(_bn_ctx);
}

int ec_keys::generate() {
  loggers::get_instance().log(">>> ec_keys::generate");
  
  // Sanity check
  if (!::EC_KEY_generate_key(_ec_key)) { // Generate the private and public key 
    loggers::get_instance().error("ec_keys::generate: Wrong parameters");
    return -1;
  }

  BIGNUM x, y;
  ::BN_init(&x);
  ::BN_init(&y);
  const EC_POINT* ec_point = EC_KEY_get0_public_key(_ec_key);
  int result = 0;
  switch (_elliptic_curve) {
  case ec_elliptic_curves::nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve: Use primary
    result = ::EC_POINT_get_affine_coordinates_GFp(_ec_group, ec_point, &x, &y, _bn_ctx); // Use primer on elliptic curve
    break;
  default:
    result = ::EC_POINT_get_affine_coordinates_GF2m(_ec_group, ec_point, &x, &y, _bn_ctx);
  } // End of 'switch' statement
  if (result == 0) {
    loggers::get_instance().error("ec_keys::generate: Failed to get coordinates");
  }
  const BIGNUM* p = ::EC_KEY_get0_private_key(_ec_key);
  
  _pr_key.resize(BN_num_bytes(p));
  ::BN_bn2bin(p, _pr_key.data());
  _pu_key_x.resize(BN_num_bytes(&x));
  ::BN_bn2bin(&x, _pu_key_x.data());
  _pu_key_y.resize(BN_num_bytes(&y));
  ::BN_bn2bin(&y, _pu_key_y.data());

  // TODO Compressed
  // int len = ::EC_POINT_point2oct(_ec_group, ec_point, POINT_CONVERSION_COMPRESSED, NULL, 0, _bn_ctx); 
  // std::vector<unsigned char> cy;
  // cy.resize(len);
  // ::EC_POINT_point2oct(_ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (unsigned char *)cy.data(), len, _bn_ctx); 
  
  return 0;
}

int ec_keys::sign(const std::vector<unsigned char>& p_data, std::vector<unsigned char>& p_r_sig, std::vector<unsigned char>& p_s_sig) {
  loggers::get_instance().log(">>> ec_keys::sign");

  // Sanity checks
  if(_pr_key.size() == 0) { // No private key
    return -1;
  }
  // TODO Check data length
  
  ECDSA_SIG *signature = ::ECDSA_do_sign(p_data.data(), p_data.size(), _ec_key);
  if (signature == nullptr) {
    loggers::get_instance().warning("ec_keys::sign: Signature failed");
    return -1;
  }
  loggers::get_instance().log("ec_keys::sign: succeed");

  if (::ECDSA_do_verify(p_data.data(), p_data.size(), signature, _ec_key) != 1) {
    loggers::get_instance().warning("ec_keys::sign: Signature not verified");
    return -1;
  }
  
  p_r_sig.resize(BN_num_bytes(signature->r));
  ::BN_bn2bin(signature->r, p_r_sig.data());
  loggers::get_instance().log_to_hexa("ec_keys::sign: r=", p_r_sig.data(), p_r_sig.size());
  p_s_sig.resize(BN_num_bytes(signature->r));
  ::BN_bn2bin(signature->s, p_s_sig.data());
  loggers::get_instance().log_to_hexa("ec_keys::sign: s=", p_s_sig.data(), p_s_sig.size());

  ::ECDSA_SIG_free(signature);
  
  return 0;
}

int ec_keys::sign_verif(const std::vector<unsigned char>& p_data, const std::vector<unsigned char>& p_signature, const std::vector<unsigned char>& p_ublic_key_x, const std::vector<unsigned char>& p_ublic_key_y) {
  loggers::get_instance().log(">>> ec_keys::sign_verif");

  // Sanity checks
  // TODO Check data length

  // Build the EC_POINT
  
  // Build the signature
  BIGNUM r, s;
  ::BN_init(&r);
  ::BN_init(&s);
  ::BN_bin2bn(p_signature.data(), p_signature.size() / 2, &r);
  ::BN_bin2bn(p_signature.data() + p_signature.size() / 2, p_signature.size() / 2, &s);
  ECDSA_SIG *signature = ECDSA_SIG_new();
  signature->r = &r;
  signature->s = &s;
  int result = ::ECDSA_do_verify(p_data.data(), p_data.size(), signature, _ec_key);
  ::ECDSA_SIG_free(signature);
  loggers::get_instance().log("ec_keys::sign_verif: %s", (result == 1) ? "succeed": "failed");
  return result != 1;
}
+47 −0

File added.

Preview size limit exceeded, changes collapsed.

Loading