Skip to content
lib_its_security.c 107 KiB
Newer Older
YannGarcia's avatar
YannGarcia committed
/*!
 * \File      lib_its_security.c
 * \brief     Source file for Security external functions.
 * \author    FSCOM
 * \copyright FSCOM Copyright Notification
 *            No part may be reproduced except as authorized by written permission.
 *            The copyright and the foregoing restriction extend to reproduction in all media.
 *            All rights reserved.
 * \version   0.1
 * \remark    gcc -Wall -Werror -O0 -ggdb -fstack-check -fstack-protector -fsanitize=leak -fsanitize=address -I. -D__MAIN__ ./lib_its_security.c -L/usr/lib -lssl -lcrypto -lm
 */
#include "lib_its_security.h"

#include <math.h>
#include <assert.h>
#include <arpa/inet.h>

#include <openssl/bio.h>

/**
 * Internal functions
 */

void show_ec_key(const int8_t* p_prefix, lib_its_security_context_t* p_lib_its_security_context) {
  fprintf(stderr, "%s: ", p_prefix);
  BIGNUM *x = BN_new();
  BIGNUM *y = BN_new();
  const EC_POINT *keys = EC_KEY_get0_public_key(p_lib_its_security_context->ec_key);
  if (EC_POINT_get_affine_coordinates_GFp(p_lib_its_security_context->ec_group, keys, x, y, NULL)) {
    BN_print_fp(stderr, x);
    fprintf(stderr, "\n");
    BN_print_fp(stderr, y);
    fprintf(stderr, "\n");
  }
  BN_free(x);
  BN_free(y);
}

void show_ec_point(const int8_t* p_prefix, lib_its_security_context_t* p_lib_its_security_context, EC_POINT* p_ec_point) {
  fprintf(stderr, "%s: ", p_prefix);
  char* result = EC_POINT_point2hex(p_lib_its_security_context->ec_group, p_ec_point, POINT_CONVERSION_UNCOMPRESSED, p_lib_its_security_context->bn_ctx);
  if (result != NULL) {
    fprintf(stderr, "%s\n", result);
    free(result);
  } else {
    fprintf(stderr, "(null)\n");
  }
}

void show_hex(const int8_t* p_prefix, const void* p_buffer, size_t p_buffer_length) {
  fprintf(stderr, "%s: ", p_prefix);
  for (uint8_t* p = (unsigned char*)p_buffer; p_buffer_length; p_buffer_length--, p++) {
    fprintf(stderr, "%02x", *p);
  }
  putc ('\n', stderr);
}

int8_t* bin_to_hex(const uint8_t* p_buffer, const size_t p_buffer_length) {
  int8_t* buf = NULL;
  size_t i = 0, j = 0;

  // Sanity check
  if (p_buffer_length == 0) {
    return NULL;
  }
  
  buf = (int8_t*)malloc(p_buffer_length << 1);
  do {
    *(buf + j) = "0123456789ABCDEF"[(*(p_buffer + i) >> 4) & 0x0F];
    *(buf + j + 1) = "0123456789ABCDEF"[*(p_buffer + i) & 0x0F];
    i += 1; j += 2;
  } while (i < p_buffer_length);

  return buf;
}

uint8_t* hex_to_bin(const int8_t* p_buffer, size_t* p_buffer_length) {
  int8_t a;
  size_t i, len;
  uint8_t* retval = NULL;

  // Sanity check
  if (p_buffer == NULL) {
    return NULL;
  }
  if ((len = strlen((const char*)p_buffer)) & 1) {
    return NULL;
  }

  retval = (uint8_t*)malloc(len >> 1);
  for ( i = 0; i < len; i ++) {
    a = toupper(*(p_buffer + i));
    if (!isxdigit(a)) {
      break;
    }
    if (isdigit(a)) {
      a -= '0';
    } else {
      a = a - 'A' + 0x0A;
    }
    if (i & 1) {
      retval[i >> 1] |= a;
    } else {
      retval[i >> 1] = a<<4;
    }
  } // End of 'for' statement
  if (i < len) {
    free(retval);
    retval = NULL;
  }
  *p_buffer_length = len >> 1;

  return retval;
}

int32_t sign(
             lib_its_security_context_t* p_lib_its_security_context,
             const uint8_t* p_data,
             const size_t p_data_length,
             uint8_t** p_sig_r,
             uint8_t** p_sig_s,
             size_t* p_sig_length
             ) {
  // Sanity checks
  if ((p_lib_its_security_context == NULL) || (p_data == NULL)) {
    return -1;
  }

  ECDSA_SIG *signature = ECDSA_do_sign(p_data, p_data_length, p_lib_its_security_context->ec_key);
  if (signature == NULL) {
    return -1;
  }

  if (ECDSA_do_verify(p_data, p_data_length, signature, p_lib_its_security_context->ec_key) != 1) {
    return -1;
  }

  const BIGNUM* r;
  const BIGNUM* s;
  ECDSA_SIG_get0(signature, &r, &s);
  *p_sig_length = BN_num_bytes(s);
  *p_sig_r = (uint8_t*)malloc(*p_sig_length);
  BN_bn2bin(r, (uint8_t*)(*p_sig_r));
  *p_sig_s = (uint8_t*)malloc(*p_sig_length);
  BN_bn2bin(s, (uint8_t*)(*p_sig_s));

  ECDSA_SIG_free(signature);

  return 0;
}

int32_t sign_verify(
                    lib_its_security_context_t* p_lib_its_security_context,
                    const uint8_t* p_data,
                    const size_t p_data_length,
                    const uint8_t* p_sig_r,
                    const uint8_t* p_sig_s,
                    const size_t p_sig_length
                   ) {
  // Sanity checks
  if ((p_lib_its_security_context == NULL) || (p_data == NULL) || (p_sig_r == NULL) || (p_sig_s == NULL)) {
    return -1;
  }

  // Build the signature
  BIGNUM* r = BN_bin2bn(p_sig_r, p_sig_length, NULL);
  BIGNUM* s = BN_bin2bn(p_sig_s, p_sig_length, NULL);
  ECDSA_SIG *signature = ECDSA_SIG_new();
  ECDSA_SIG_set0(signature, r, s);
  // Check the signature
  int32_t result = ECDSA_do_verify(p_data, p_data_length, signature, p_lib_its_security_context->ec_key);
  ECDSA_SIG_free(signature);

  return (result == 1) ? 0 : -1;
}

int bin_to_ec_point(
                    lib_its_security_context_t* p_lib_its_security_context,
                    const uint8_t* p_public_key_x,
                    const uint8_t* p_public_key_y, EC_POINT** p_ec_point
                    ) {
  BIGNUM* pubk_bn = NULL;
  size_t l = 2 * p_lib_its_security_context->key_length + 1;
  uint8_t* v = (uint8_t*)malloc(l);
  *v = 0x04;
  memcpy((void*)(v + 1), (const void*)p_public_key_x, p_lib_its_security_context->key_length);
  memcpy((void*)(v + 1 + p_lib_its_security_context->key_length), (const void*)p_public_key_y, p_lib_its_security_context->key_length);
  pubk_bn = BN_bin2bn(v, l, NULL);
  *p_ec_point = EC_POINT_new(p_lib_its_security_context->ec_group);
  EC_POINT_bn2point(p_lib_its_security_context->ec_group, pubk_bn, *p_ec_point, p_lib_its_security_context->bn_ctx);
  BN_clear_free(pubk_bn);
  free(v);

  return 0;
}

int public_key_to_bin(
                      lib_its_security_context_t* p_lib_its_security_context,
                      uint8_t** p_bin_key
                      ) {
Loading
Loading full blame...