From 621654401508ec8c7c456273c44682ebccc6bf90 Mon Sep 17 00:00:00 2001 From: YannGarcia Date: Mon, 2 Mar 2020 08:54:58 +0100 Subject: [PATCH] Build lib_its_security on Windows --- .../lib_its_security/lib_its_security.c | 4451 +++++++++-------- .../lib_its_security/lib_its_security.h | 788 +-- .../itssecurity/test/test_lib_its_security.cc | 59 +- 3 files changed, 2685 insertions(+), 2613 deletions(-) mode change 100644 => 100755 tools/itssecurity/test/test_lib_its_security.cc diff --git a/tools/itssecurity/lib_its_security/lib_its_security.c b/tools/itssecurity/lib_its_security/lib_its_security.c index 2f2ad578f..6fa218b57 100644 --- a/tools/itssecurity/lib_its_security/lib_its_security.c +++ b/tools/itssecurity/lib_its_security/lib_its_security.c @@ -1,2219 +1,2232 @@ -/*! - * \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 -#include -#include - -#include - -/** - * 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 - ) { - const EC_GROUP *ec_group = EC_KEY_get0_group(p_lib_its_security_context->ec_key); - const EC_POINT *pub = EC_KEY_get0_public_key(p_lib_its_security_context->ec_key); - BIGNUM *pub_bn = BN_new(); - - EC_POINT_point2bn(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, pub_bn, p_lib_its_security_context->bn_ctx); - *p_bin_key = (uint8_t*)malloc(BN_num_bytes(pub_bn)); - BN_bn2bin(pub_bn, *p_bin_key); - - BN_clear_free(pub_bn); - - return 0; -} - -int kdf2_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_salt, - const int32_t p_salt_length, - const int32_t p_key_length, - uint8_t** p_digest, size_t* p_digest_length - ) { - // Sanity checks - - int sha256_blk_len = 32; - int num_blk_out = (int)ceil(p_key_length/(float)sha256_blk_len); - uint8_t* digest = (uint8_t*)malloc((num_blk_out + 1) * sha256_blk_len); - int32_t digest_idx = 0; - const size_t hash_input_length = p_lib_its_security_context->secret_key_length + sizeof(int32_t) + p_salt_length; - uint8_t* hash_input = (uint8_t*)malloc(hash_input_length); - int i_ntonl; - for (int32_t i = 1; i < num_blk_out + 1; i++) { - uint8_t* p = hash_input; - memcpy((void*)p, (const void*)p_lib_its_security_context->secret_key, p_lib_its_security_context->secret_key_length); - p += p_lib_its_security_context->secret_key_length; - i_ntonl = htonl(i); - memcpy((void*)p, (const void*)&i_ntonl, sizeof(int32_t)); - p += sizeof(int32_t); - memcpy((void*)p, (const void*)p_salt, p_salt_length); - //show_hex((const int8_t*)"hash_input", (const void*)hash_input, hash_input_length); - uint8_t* h; - hash_with_sha256(hash_input, hash_input_length, &h); - //show_hex((const int8_t*)"h", (const void*)h, 32); - memcpy((void*)digest + digest_idx, (const void*)h, sha256_blk_len); - //show_hex((const int8_t*)"digest", (const void*)digest, digest_idx + sha256_blk_len); - digest_idx += sha256_blk_len; - free(h); - } // End of 'for' statement - free(hash_input); - if (digest_idx > p_key_length * 2) { - digest_idx = p_key_length * 2; - } - *p_digest = (uint8_t*)malloc(digest_idx); - memcpy((void*)(*p_digest), (const void*)digest, digest_idx); - *p_digest_length = digest_idx; - free(digest); - - return 0; -} - -int32_t kdf2( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_salt, - const int32_t p_salt_length, - const int32_t p_key_length, - const unsigned char p_hash_algorithm, - uint8_t** p_digest, - size_t* p_digest_length - ) { - // Sanity checks - - int result = -1; - switch (p_hash_algorithm) { - case 0x00: // SHA 256 - result = kdf2_sha256(p_lib_its_security_context, p_salt, p_salt_length, p_key_length, p_digest, p_digest_length); - break; - } // End of 'switch' statement - - return result; -} - -int32_t generate_and_derive_ephemeral_key_for_encryption( - lib_its_security_context_t* p_ecdh_private_key, - const encryption_algorithm_t p_enc_algorithm, - lib_its_security_context_t* p_public_keys, - const uint8_t* p_salt, - const size_t p_salt_length - ) { - // Sanity checks - if (p_public_keys->private_key != NULL) { - return -1; - } - if ((p_public_keys->public_key_x == NULL) || (p_public_keys->public_key_y == NULL)) { - return -1; - } - - // Set buffers size - p_ecdh_private_key->encryption_algorithm = p_enc_algorithm; - switch (p_ecdh_private_key->encryption_algorithm) { - case aes_128_ccm: - // No break; - case aes_128_gcm: - p_ecdh_private_key->nonce_length = 12; - p_ecdh_private_key->sym_key_length = 16; - p_ecdh_private_key->tag_length = 16; - break; - default: - return -1; - } // End of 'switch' statement - uint8_t k_enc; - uint8_t k_mac; - switch (p_ecdh_private_key->elliptic_curve) { - case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve - // No break; - case brainpool_p_256_r1: - k_enc = 16; - k_mac = 32; - break; - case brainpool_p_384_r1: - k_enc = 24; // TODO To be checked - k_mac = 48; - break; - default: - return -1; - } // End of 'switch' statement - - /* Convert the ephemeral public encryption keys to an EC point */ - EC_POINT *ec_point = NULL; - bin_to_ec_point(p_public_keys, p_public_keys->public_key_x, p_public_keys->public_key_y, &ec_point); - show_ec_point((const int8_t *)"ec_point", p_public_keys, ec_point); - /* Generate the shared secret key (Key Agreement) */ - p_ecdh_private_key->secret_key_length = (EC_GROUP_get_degree(p_ecdh_private_key->ec_group) + 7) / 8; - p_ecdh_private_key->secret_key = (uint8_t*)malloc(p_ecdh_private_key->secret_key_length); - int32_t result = ECDH_compute_key( - p_ecdh_private_key->secret_key, - p_ecdh_private_key->secret_key_length, - ec_point, // From recipient's public keys - p_ecdh_private_key->ec_key, // From ephemeral's private key - NULL); - if (result != p_ecdh_private_key->secret_key_length) { - free(p_ecdh_private_key->secret_key); - p_ecdh_private_key->secret_key = NULL; - EC_POINT_free(ec_point); - return -1; - } - EC_POINT_free(ec_point); - show_hex((const int8_t*)"secret", p_ecdh_private_key->secret_key, p_ecdh_private_key->secret_key_length); - - /* Derive the shared secret key */ - uint8_t* digest; - size_t digest_length; - if (kdf2(p_ecdh_private_key, p_salt, p_salt_length, k_enc + k_mac, 0x00/*sha256*/, &digest, &digest_length) != 0) { - free(p_ecdh_private_key->secret_key); - p_ecdh_private_key->secret_key = NULL; - return -1; - } - show_hex((const int8_t*)"digest", digest, digest_length); - - /* Extract K1 and generate encrypted symmetric key */ - uint8_t* k1 = (uint8_t*)malloc(k_enc); - memcpy((void*)k1, (const void*)digest, k_enc); - show_hex((const int8_t*)"k1", k1, k_enc); - BIGNUM* r = BN_new(); - BN_pseudo_rand(r, k_enc * 8, -1, 0); - p_ecdh_private_key->sym_key = (uint8_t*)malloc(k_enc); - p_ecdh_private_key->sym_key_length = k_enc; - BN_bn2bin(r, p_ecdh_private_key->sym_key); - BN_free(r); - show_hex((const int8_t*)"sym_key", p_ecdh_private_key->sym_key, p_ecdh_private_key->sym_key_length); - p_ecdh_private_key->enc_sym_key = (uint8_t*)malloc(k_enc); - for (int i = 0; i < k_enc; *(p_ecdh_private_key->enc_sym_key + i) = *(k1 + i) ^ *(p_ecdh_private_key->sym_key + i), i++); - show_hex((const int8_t*)"enc_sym_key", p_ecdh_private_key->enc_sym_key, p_ecdh_private_key->sym_key_length); - - // Extract K2 and generate Tag vector - int32_t k2_length = k_enc * 2; - uint8_t* k2 = (uint8_t*)malloc(k2_length); - memcpy((void*)k2, (const void*)(k_enc + digest), k2_length); - show_hex((const int8_t*)"k2", k2, k2_length); - hmac_sha256(p_ecdh_private_key->enc_sym_key, p_ecdh_private_key->sym_key_length, k2, k2_length, &p_ecdh_private_key->tag); - show_hex((const int8_t*)"tag", p_ecdh_private_key->tag, p_ecdh_private_key->tag_length); - - /* Generate random IV (nonce) */ - r = BN_new(); - BN_pseudo_rand(r, p_ecdh_private_key->nonce_length * 8, -1, 0); - p_ecdh_private_key->nonce = (uint8_t*)malloc(p_ecdh_private_key->nonce_length); - BN_bn2bin(r, p_ecdh_private_key->nonce); - BN_free(r); - show_hex((const int8_t*)"nonce", p_ecdh_private_key->nonce, p_ecdh_private_key->nonce_length); - - free(digest); - free(k1); - free(k2); - return 0; -} - -int32_t encrypt( - lib_its_security_context_t* lib_its_security_context, - const uint8_t* p_plain_text_message, - const size_t p_plain_text_message_length, - uint8_t** p_cipher_message, - size_t *p_cipher_message_length - ) { - /* Sanity checks */ - - /* Initialize the context and encryption operation */ - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - /* Allocate buffers size */ - switch (lib_its_security_context->encryption_algorithm) { - case aes_128_ccm: - EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL); - if (lib_its_security_context->tag != NULL) { - free(lib_its_security_context->tag); - } - lib_its_security_context->tag_length = 16; - lib_its_security_context->tag = (uint8_t*)malloc(lib_its_security_context->tag_length); - *p_cipher_message = (uint8_t*)malloc(p_plain_text_message_length); - break; - case aes_256_ccm: - EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL); - break; - case aes_128_gcm: - EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); - if (lib_its_security_context->tag != NULL) { - free(lib_its_security_context->tag); - } - lib_its_security_context->tag_length = 16; - lib_its_security_context->tag = (uint8_t*)malloc(lib_its_security_context->tag_length); - *p_cipher_message = (uint8_t*)malloc(p_plain_text_message_length); - break; - case aes_256_gcm: - EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); - break; - } /* End of 'switch' statement */ - *p_cipher_message_length = p_plain_text_message_length; - /* Set nonce length */ - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, lib_its_security_context->nonce_length, NULL); - /* Set tag length */ - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, lib_its_security_context->tag_length, NULL); - /* Prime the key and nonce */ - EVP_EncryptInit_ex(ctx, NULL, NULL, lib_its_security_context->sym_key, lib_its_security_context->nonce); - // No authentication data - // Encrypt the data - int len = 0; - EVP_EncryptUpdate(ctx, *p_cipher_message, &len, p_plain_text_message, p_plain_text_message_length); - // Finalize the encryption session - EVP_EncryptFinal_ex(ctx, (*p_cipher_message) + len, &len); - /* Get the authentication tag */ - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, lib_its_security_context->tag_length, lib_its_security_context->tag); - - EVP_CIPHER_CTX_free(ctx); - - return 0; -} - -int32_t generate_and_derive_ephemeral_key_for_decryption( - lib_its_security_context_t* p_lib_its_security_context, - const encryption_algorithm_t p_enc_algorithm, - lib_its_security_context_t* p_ephemeral_keys, - const uint8_t* p_enc_sym_key, - const uint8_t* p_nonce, - const uint8_t* p_authentication_vector, - const uint8_t* p_salt, - const size_t p_salt_length - ) { - /* Sanity checks */ - if ((p_lib_its_security_context->public_key_x == NULL) || (p_lib_its_security_context->public_key_y == NULL)) { - return -1; - } - - /* Set buffers size */ - p_lib_its_security_context->encryption_algorithm = p_enc_algorithm; - switch (p_lib_its_security_context->encryption_algorithm) { - case aes_128_ccm: - // No break; - case aes_128_gcm: - p_lib_its_security_context->nonce_length = 12; - p_lib_its_security_context->sym_key_length = 16; - p_lib_its_security_context->tag_length = 16; - break; - default: - return -1; - } // End of 'switch' statement - unsigned int k_enc; - unsigned int k_mac; - switch (p_lib_its_security_context->elliptic_curve) { - case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve - // No break; - case brainpool_p_256_r1: - k_enc = 16; - k_mac = 32; - break; - case brainpool_p_384_r1: - break; - default: - return -1; - } // End of 'switch' statement - - /* Fill context buffer */ - p_lib_its_security_context->nonce = (uint8_t*)malloc(p_lib_its_security_context->nonce_length); - memcpy((void*)p_lib_its_security_context->nonce, (const void*)p_nonce, p_lib_its_security_context->nonce_length); - p_lib_its_security_context->enc_sym_key = (uint8_t*)malloc(p_lib_its_security_context->sym_key_length); - memcpy((void*)p_lib_its_security_context->enc_sym_key, (const void*)p_enc_sym_key, p_lib_its_security_context->sym_key_length); - p_lib_its_security_context->tag = (uint8_t*)malloc(p_lib_its_security_context->tag_length); - memcpy((void*)p_lib_its_security_context->tag, (const void*)p_authentication_vector, p_lib_its_security_context->tag_length); - - /* Convert the ephemeral key to an EC point */ - EC_POINT *ec_point = NULL; - bin_to_ec_point(p_ephemeral_keys, p_ephemeral_keys->public_key_x, p_ephemeral_keys->public_key_y, &ec_point); // EC_POINT from ephemeral keys - // Generate the shared secret key (Key Agreement) - p_lib_its_security_context->secret_key_length = (EC_GROUP_get_degree(p_lib_its_security_context->ec_group) + 7) / 8; - p_lib_its_security_context->secret_key = (uint8_t*)malloc(p_lib_its_security_context->secret_key_length); - int32_t result = ECDH_compute_key( - p_lib_its_security_context->secret_key, - p_lib_its_security_context->secret_key_length, - ec_point, // From ephemeral keys - p_lib_its_security_context->ec_key, // From recipient's private key - NULL); - if (result != p_lib_its_security_context->secret_key_length) { - free(p_lib_its_security_context->secret_key); - p_lib_its_security_context->secret_key = NULL; - EC_POINT_free(ec_point); - return -1; - } - EC_POINT_free(ec_point); - show_hex((const int8_t*)"secret", p_lib_its_security_context->secret_key, p_lib_its_security_context->secret_key_length); - - /* Derive the shared secret key */ - uint8_t* digest; - size_t digest_length; - if (kdf2(p_lib_its_security_context, p_salt, p_salt_length, k_enc + k_mac, 0x00/*sha256*/, &digest, &digest_length) != 0) { - free(p_lib_its_security_context->secret_key); - p_lib_its_security_context->secret_key = NULL; - return -1; - } - show_hex((const int8_t*)"digest", digest, digest_length); - - /* Extract K2 and generate Tag vector */ - int32_t k2_length = k_enc * 2; - uint8_t* k2 = (uint8_t*)malloc(k2_length); - memcpy((void*)k2, (const void*)(k_enc + digest), k2_length); - show_hex((const int8_t*)"k2", k2, k2_length); - hmac_sha256(p_lib_its_security_context->enc_sym_key, p_lib_its_security_context->sym_key_length, k2, k2_length, &p_lib_its_security_context->tag); - show_hex((const int8_t*)"authentication vector", p_lib_its_security_context->tag, p_lib_its_security_context->tag_length); - - /* Extract K1 and generate encrypted symmetric key */ - uint8_t* k1 = (uint8_t*)malloc(k_enc); - memcpy((void*)k1, (const void*)digest, k_enc); - show_hex((const int8_t*)"k1", k1, k_enc); - p_lib_its_security_context->sym_key = (uint8_t*)malloc(k_enc); - for (int i = 0; i < k_enc; *(p_lib_its_security_context->sym_key + i) = *(k1 + i) ^ *(p_lib_its_security_context->enc_sym_key + i), i++); - show_hex((const int8_t*)"sym_key", p_lib_its_security_context->sym_key, p_lib_its_security_context->sym_key_length); - free(k1); - free(k2); - free(digest); - - return 0; -} - -int32_t decrypt( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_cipher_message, - const size_t p_cipher_message_length, - uint8_t**p_plain_text_message, - size_t* p_plain_text_message_length - ) { - /* Sanity checks */ - - /* Initialize the context and decryption operation */ - EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); - switch (p_lib_its_security_context->encryption_algorithm) { - case aes_128_ccm: - EVP_DecryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL); - break; - case aes_256_ccm: - EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL); - break; - case aes_128_gcm: - EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); - break; - case aes_256_gcm: - EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); - break; - } // End of 'switch' statement - /* Set nonce length */ - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, p_lib_its_security_context->nonce_length, NULL); - /* Set expected tag value */ - EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, p_lib_its_security_context->tag_length, p_lib_its_security_context->tag); - /* Specify key and IV */ - EVP_DecryptInit_ex(ctx, NULL, NULL, p_lib_its_security_context->sym_key, p_lib_its_security_context->nonce); - /* Decrypt plaintext, verify tag: can only be called once */ - *p_plain_text_message = (uint8_t*)malloc(p_cipher_message_length); - *p_plain_text_message_length = p_cipher_message_length; - int len = 0; - int result = EVP_DecryptUpdate(ctx, *p_plain_text_message, &len, p_cipher_message, p_cipher_message_length); - EVP_CIPHER_CTX_free(ctx); - if (result != 1) { - free(*p_plain_text_message); - *p_plain_text_message = NULL; - } - - return (result > 0) ? 0 : -1; -} - -/** - * Public functions - */ - -int32_t initialize( - const ecc_elliptic_curves_t p_elliptic_curve, - lib_its_security_context_t** p_lib_its_security_context - ) { - // Sanity checks - if (p_lib_its_security_context == NULL) { - return -1; - } - - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - ERR_clear_error(); - - *p_lib_its_security_context = (lib_its_security_context_t*)malloc(sizeof(lib_its_security_context_t)); - if (*p_lib_its_security_context == NULL) { - return -1; - } - (*p_lib_its_security_context)->elliptic_curve = p_elliptic_curve; - (*p_lib_its_security_context)->ec_key = NULL; - (*p_lib_its_security_context)->ec_group = NULL; - (*p_lib_its_security_context)->bn_ctx = NULL; - (*p_lib_its_security_context)->key_length = -1; - (*p_lib_its_security_context)->private_key = NULL; - (*p_lib_its_security_context)->public_key_x = NULL; - (*p_lib_its_security_context)->public_key_y = NULL; - (*p_lib_its_security_context)->public_key_c = NULL; - (*p_lib_its_security_context)->secret_key = NULL; - (*p_lib_its_security_context)->sym_key = NULL; - (*p_lib_its_security_context)->enc_sym_key = NULL; - (*p_lib_its_security_context)->tag = NULL; - (*p_lib_its_security_context)->nonce = NULL; - (*p_lib_its_security_context)->secret_key_length = -1; - (*p_lib_its_security_context)->sym_key_length = -1; - (*p_lib_its_security_context)->nonce_length = -1; - (*p_lib_its_security_context)->tag_length = -1; - - int32_t result = -1; - switch (p_elliptic_curve) { - case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve - (*p_lib_its_security_context)->key_length = 32; - result = OBJ_txt2nid("prime256v1"); - break; - case brainpool_p_256_r1: - (*p_lib_its_security_context)->key_length = 32; - result = OBJ_txt2nid("brainpoolP256r1"); - break; - case brainpool_p_384_r1: - (*p_lib_its_security_context)->key_length = 48; - result = OBJ_txt2nid("brainpoolP384r1"); - break; - default: - fprintf(stderr, "lib_its_security::initialize: Unsupported EC elliptic_curve\n"); - } // End of 'switch' statement - if (result < 0) { - return -1; - } - - (*p_lib_its_security_context)->ec_key = EC_KEY_new_by_curve_name(result); /* Set the elliptic curve */ - EC_KEY_set_asn1_flag((*p_lib_its_security_context)->ec_key, OPENSSL_EC_NAMED_CURVE); /* Used to save and retrieve keys */ - (*p_lib_its_security_context)->ec_group = (EC_GROUP*)EC_KEY_get0_group((*p_lib_its_security_context)->ec_key); /* Get pointer to the EC_GROUP */ - (*p_lib_its_security_context)->bn_ctx = BN_CTX_new(); - - return 0; -} - -int32_t initialize_with_private_key( - const ecc_elliptic_curves_t p_elliptic_curve, - const uint8_t* p_private_key, - lib_its_security_context_t** p_lib_its_security_context - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_private_key == NULL)) { - return -1; - } - - if (initialize(p_elliptic_curve, p_lib_its_security_context) == -1) { - return -1; - } - EC_KEY_set_conv_form((*p_lib_its_security_context)->ec_key, POINT_CONVERSION_UNCOMPRESSED); - - // Build private key - BIGNUM* p = BN_new(); - BN_bin2bn(p_private_key, (*p_lib_its_security_context)->key_length, p); - // Build public keys - EC_POINT* ec_point = EC_POINT_new((*p_lib_its_security_context)->ec_group); - EC_POINT_mul((*p_lib_its_security_context)->ec_group, ec_point, p, NULL, NULL, (*p_lib_its_security_context)->bn_ctx); - // Set private key - EC_KEY_set_private_key((*p_lib_its_security_context)->ec_key, p); - if (EC_KEY_check_key((*p_lib_its_security_context)->ec_key) != 0) { - EC_POINT_free(ec_point); - BN_clear_free(p); - return -1; - } - BN_clear_free(p); - // Private key is correct, set public keys - EC_KEY_set_public_key((*p_lib_its_security_context)->ec_key, ec_point); - BIGNUM* xy = BN_new(); - EC_POINT_point2bn((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, xy, (*p_lib_its_security_context)->bn_ctx); - if (BN_num_bytes(xy) == 0) { - EC_POINT_free(ec_point); - BN_clear_free(xy); - return -1; - } - - int32_t v_length = BN_num_bytes(xy); - uint8_t* vv = (uint8_t*)malloc(v_length); - BN_bn2bin(xy, vv); - if ((v_length % 2) != 0) { - // Remove first byte - // v_length -= 1; - // memcpy((void*)vv, (const void*)(vv + 1), v_length - 1); - uint8_t *v = (uint8_t*)malloc(v_length - 1); - memcpy((void*)v, (const void*)(vv + 1), v_length - 1); - free(vv); - vv = v; - v_length -= 1; - } - BN_clear_free(xy); - const int l = v_length / 2; - (*p_lib_its_security_context)->public_key_x = (uint8_t*)malloc(l); - memcpy((void*)(*p_lib_its_security_context)->public_key_x, (const void*)vv, l); - (*p_lib_its_security_context)->public_key_y = (uint8_t*)malloc(l); - memcpy((void*)(*p_lib_its_security_context)->public_key_y, (const void*)(vv + l), l); - // Compressed - int len = EC_POINT_point2oct((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, NULL, 0, (*p_lib_its_security_context)->bn_ctx); - if (len != 0) { - (*p_lib_its_security_context)->public_key_c = (uint8_t*)malloc(len); - if (EC_POINT_point2oct((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (*p_lib_its_security_context)->public_key_c, len, (*p_lib_its_security_context)->bn_ctx) != 0) { - (*p_lib_its_security_context)->compressed_mode = ((*vv & 0x01) == 0x00) ? compressed_y_0 : compressed_y_1; - memmove((void*)(*p_lib_its_security_context)->public_key_c, (const void*)(1 + (*p_lib_its_security_context)->public_key_c), len - 1); - } - } - free(vv); - EC_POINT_free(ec_point); - - (*p_lib_its_security_context)->private_key = (uint8_t*)malloc((*p_lib_its_security_context)->key_length); - memcpy((void*)(*p_lib_its_security_context)->private_key, (const void*)p_private_key, (*p_lib_its_security_context)->key_length); - - return 0; -} - -int32_t initialize_with_public_key( - const ecc_elliptic_curves_t p_elliptic_curve, - const uint8_t* p_public_key, - const ecc_compressed_mode_t p_compressed_mode, - lib_its_security_context_t** p_lib_its_security_context - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_public_key == NULL)) { - return -1; - } - - if (initialize(p_elliptic_curve, p_lib_its_security_context) == -1) { - return -1; - } - EC_KEY_set_conv_form((*p_lib_its_security_context)->ec_key, POINT_CONVERSION_UNCOMPRESSED); - - // Set public key - BIGNUM* compressed_key = BN_new(); - BN_bin2bn(p_public_key, (*p_lib_its_security_context)->key_length, compressed_key); - EC_POINT* ec_point = EC_POINT_new((*p_lib_its_security_context)->ec_group); - int32_t result = 0; - switch (p_elliptic_curve) { - case nist_p_256: // Use primary - // No break; - case brainpool_p_256_r1: - // No break; - case brainpool_p_384_r1: - result = EC_POINT_set_compressed_coordinates_GFp((*p_lib_its_security_context)->ec_group, ec_point, compressed_key, (p_compressed_mode == compressed_y_1) ? 1 : 0, (*p_lib_its_security_context)->bn_ctx); // Use primary elliptic curve - break; - default: // Use Binary - result = EC_POINT_set_compressed_coordinates_GF2m((*p_lib_its_security_context)->ec_group, ec_point, compressed_key, (p_compressed_mode == compressed_y_1) ? 1 : 0, (*p_lib_its_security_context)->bn_ctx); - } // End of 'switch' statement - BN_clear_free(compressed_key); - - if (result == 0) { - EC_POINT_free(ec_point); - return -1; - } else if (EC_POINT_is_on_curve((*p_lib_its_security_context)->ec_group, ec_point, (*p_lib_its_security_context)->bn_ctx) == 0) { - EC_POINT_free(ec_point); - return -1; - } - - // Set public keys - BIGNUM* xy = BN_new(); - EC_POINT_point2bn((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, xy, (*p_lib_its_security_context)->bn_ctx); - if (BN_num_bytes(xy) == 0) { - EC_POINT_free(ec_point); - BN_clear_free(xy); - return -1; - } - EC_KEY_set_public_key((*p_lib_its_security_context)->ec_key, ec_point); - // Generate X, Y coordinates - int32_t v_length = BN_num_bytes(xy); - uint8_t* vv = (uint8_t*)malloc(v_length); - BN_bn2bin(xy, vv); - BN_clear_free(xy); - if ((v_length % 2) != 0) { // TODO Check alse xy[0] == 0x04 - // Remove first byte - // v_length -= 1; - // memcpy((void*)vv, (const void*)(vv + 1), v_length - 1); - uint8_t *v = (uint8_t*)malloc(v_length - 1); - memcpy((void*)v, (const void*)(vv + 1), v_length - 1); - free(vv); - vv = v; - v_length -= 1; - } - const int l = v_length / 2; - (*p_lib_its_security_context)->public_key_x = (uint8_t*)malloc(l); - memcpy((void*)(*p_lib_its_security_context)->public_key_x, (const void*)vv, l); - (*p_lib_its_security_context)->public_key_y = (uint8_t*)malloc(l); - memcpy((void*)(*p_lib_its_security_context)->public_key_y, (const void*)(vv + l), l); - (*p_lib_its_security_context)->public_key_c = (uint8_t*)malloc(l); - memcpy((void*)(*p_lib_its_security_context)->public_key_c, (const void*)p_public_key, (*p_lib_its_security_context)->key_length); - (*p_lib_its_security_context)->compressed_mode = p_compressed_mode; - free(vv); - EC_POINT_free(ec_point); - - return 0; -} - -int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (*p_lib_its_security_context == NULL)) { - return -1; - } - - if ((*p_lib_its_security_context)->private_key != NULL) free((*p_lib_its_security_context)->private_key); - if ((*p_lib_its_security_context)->public_key_x != NULL) free((*p_lib_its_security_context)->public_key_x); - if ((*p_lib_its_security_context)->public_key_y != NULL) free((*p_lib_its_security_context)->public_key_y); - if ((*p_lib_its_security_context)->public_key_c != NULL) free((*p_lib_its_security_context)->public_key_c); - if ((*p_lib_its_security_context)->secret_key != NULL) free((*p_lib_its_security_context)->secret_key); - if ((*p_lib_its_security_context)->sym_key != NULL) free((*p_lib_its_security_context)->sym_key); - if ((*p_lib_its_security_context)->enc_sym_key != NULL) free((*p_lib_its_security_context)->enc_sym_key); - if ((*p_lib_its_security_context)->tag != NULL) free((*p_lib_its_security_context)->tag); - if ((*p_lib_its_security_context)->nonce != NULL) free((*p_lib_its_security_context)->nonce); - - if ((*p_lib_its_security_context)->ec_key != NULL) { - EC_KEY_free((*p_lib_its_security_context)->ec_key); - } - // Not required to free ec_group, it was a reference in ec_key - if ((*p_lib_its_security_context)->bn_ctx != NULL) { - BN_CTX_free((*p_lib_its_security_context)->bn_ctx); - } - - free(*p_lib_its_security_context); - *p_lib_its_security_context = NULL; - - return 0; -} - -int32_t hash_with_sha256( - const uint8_t* p_to_be_hashed_data, - const size_t p_to_be_hashed_data_length, - uint8_t** p_hashed_data - ) { - static uint8_t sha256_empty_string[] = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }; //! SHA-256 of an empty string - - // Sanity checks - if (p_hashed_data == NULL) { - return -1; - } - - *p_hashed_data = (uint8_t*)malloc(32); - if ((p_to_be_hashed_data == NULL) || (p_to_be_hashed_data_length == 0)) { - // SHA-256 of an empty value - memcpy((void*)*p_hashed_data, (const void*)sha256_empty_string, 32); - } else { - SHA256_CTX ctx; - SHA256_Init(&ctx); - SHA256_Update(&ctx, p_to_be_hashed_data, p_to_be_hashed_data_length); - SHA256_Final(*p_hashed_data, &ctx); - } - - return 0; -} - -int32_t hash_with_sha384( - const uint8_t* p_to_be_hashed_data, - const size_t p_to_be_hashed_data_length, - uint8_t** p_hashed_data - ) { - static unsigned char sha384_empty_string[] = { 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b }; //! SHA-384 of an empty string - - // Sanity checks - if (p_hashed_data == NULL) { - return -1; - } - - *p_hashed_data = (uint8_t*)malloc(48); - if ((p_to_be_hashed_data == NULL) || (p_to_be_hashed_data_length == 0)) { - // SHA-256 of an empty value - memcpy((void*)*p_hashed_data, (const void*)sha384_empty_string, 48); - } else { - SHA512_CTX ctx; - SHA384_Init(&ctx); - SHA384_Update(&ctx, p_to_be_hashed_data, p_to_be_hashed_data_length); - SHA384_Final(*p_hashed_data, &ctx); - } - - return 0; -} - -int32_t hmac_sha256( - const uint8_t* p_secret_key, - const size_t p_secret_key_length, - const uint8_t* p_message, - const size_t p_message_length, - uint8_t** p_hmac - ) { - /* Sanity checks */ - if ((p_secret_key == NULL) || (p_secret_key_length == 0) || (p_message == NULL) || (p_message_length == 0) || (p_hmac == NULL)) { - return -1; - } - - uint32_t length = 64; - uint8_t* hmac = (uint8_t*)malloc(length); - HMAC_CTX *ctx = HMAC_CTX_new(); - HMAC_Init_ex(ctx, (const void*)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); - /* Compute the hash value */ - HMAC_Update(ctx, p_message, p_message_length); - HMAC_Final(ctx, hmac, &length); - HMAC_CTX_free(ctx); - /* Resize the hmac */ - *p_hmac = (uint8_t*)malloc(16); - memcpy((void*)*p_hmac, (const void*)hmac, 16); - free(hmac); - - return 0; -} - -int32_t prepare_data_to_be_verify( - const 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_certificate_issuer, uint8_t** p_hashed_data - ) { - // Calculate the SHA of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) - uint8_t* hashed_data1; // Hash (Data input) - int32_t result; - if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { - result = hash_with_sha384(p_data, p_data_length, &hashed_data1); - } else { - result = hash_with_sha256(p_data, p_data_length, &hashed_data1); - } - if (result == -1) { - return -1; - } - uint8_t* hashed_data2; // Hash (Signer identifier input) - bool found = true; - for (int i = 0; i < 32; i++) { - if (*(p_certificate_issuer + i) != 0x00) { - found = false; - break; - } - } - if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { - if (!found) { - result = hash_with_sha384(p_certificate_issuer, p_lib_its_security_context->key_length, &hashed_data2); // Hash of empty string - } else { - result = hash_with_sha384(NULL, 0, &hashed_data2); // Hash of empty string - } - } else { - if (!found) { - result = hash_with_sha256(p_certificate_issuer, p_lib_its_security_context->key_length, &hashed_data2); // Hash of empty string - } else { - result = hash_with_sha256(NULL, 0, &hashed_data2); // Hash of empty string - } - } - if (result == -1) { - free(hashed_data1); - return -1; - } - uint8_t* hash_data_buffer = (uint8_t*)malloc(2 * p_lib_its_security_context->key_length); // Hash (Data input) || Hash (Signer identifier input) - memcpy((void*)hash_data_buffer, (const void*)hashed_data1, p_lib_its_security_context->key_length); - memcpy((void*)(hash_data_buffer + p_lib_its_security_context->key_length), (const void*)hashed_data2, p_lib_its_security_context->key_length); - if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { - result = hash_with_sha384(hash_data_buffer, 2 * p_lib_its_security_context->key_length, p_hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - } else { - result = hash_with_sha256(hash_data_buffer, 2 * p_lib_its_security_context->key_length, p_hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) - } - free(hashed_data1); - free(hashed_data2); - free(hash_data_buffer); - - return 0; -} - -int32_t generic_signature( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ) { - uint8_t* hashed_data; - if (prepare_data_to_be_verify(p_lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, &hashed_data) == -1) { - return -1; - } - - // Calculate the signature - uint8_t* r_sig; - uint8_t* s_sig; - size_t sig_length; - if (sign(p_lib_its_security_context, hashed_data, p_lib_its_security_context->key_length, &r_sig, &s_sig, &sig_length) == -1) { - free(hashed_data); - return -1; - } - free(hashed_data); - // Copy the signature - *p_signature = (uint8_t*)malloc(2 * p_lib_its_security_context->key_length); // r_sig || s_sig - memcpy((void*)*p_signature, (const void*)r_sig, p_lib_its_security_context->key_length); - memcpy((void*)(*p_signature + p_lib_its_security_context->key_length), (const void*)s_sig, p_lib_its_security_context->key_length); - - free(r_sig); - free(s_sig); - - return 0; -} - -int32_t generic_verify( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsa_nistp256_publicKey_compressed, - const ecc_compressed_mode_t p_compressed_mode - ) { - uint8_t* hashed_data; - if (prepare_data_to_be_verify(p_lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, &hashed_data) == -1) { - return -1; - } - - uint8_t sig_r[p_lib_its_security_context->key_length]; - memcpy((void*)sig_r, (const void*)p_signature, p_lib_its_security_context->key_length); - uint8_t sig_s[p_lib_its_security_context->key_length]; - memcpy((void*)sig_s, (const void*)(p_signature + p_lib_its_security_context->key_length), p_lib_its_security_context->key_length); - if (sign_verify(p_lib_its_security_context, hashed_data, p_lib_its_security_context->key_length, sig_r, sig_s, p_lib_its_security_context->key_length) == -1) { - free(hashed_data); - return -1; - } - free(hashed_data); - - return 0; -} - -int32_t sign_with_ecdsa_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_private_key(nist_p_256, p_private_key, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_private_key(brainpool_p_256_r1, p_private_key, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_private_key(brainpool_p_384_r1, p_private_key, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t verify_with_ecdsa_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsa_nistp256_publicKey_compressed, - const ecc_compressed_mode_t p_compressed_mode - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsa_nistp256_publicKey_compressed == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_public_key(nist_p_256, p_ecdsa_nistp256_publicKey_compressed, p_compressed_mode, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsa_nistp256_publicKey_compressed, p_compressed_mode); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t verify_with_ecdsa_nistp256_with_sha256_raw( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_signature, - const uint8_t* p_ecdsa_nistp256_publicKey_compressed, - const ecc_compressed_mode_t p_compressed_mode - ) { return -1; } - -int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsaBrainpoolp256PublicKeyCompressed, - const ecc_compressed_mode_t p_compressed_mode - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsaBrainpoolp256PublicKeyCompressed == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_public_key(brainpool_p_256_r1, p_ecdsaBrainpoolp256PublicKeyCompressed, p_compressed_mode, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsaBrainpoolp256PublicKeyCompressed, p_compressed_mode); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsaBrainpoolp384PublicKeyCompressed, - const ecc_compressed_mode_t p_compressed_mode - ) { - // Sanity checks - if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsaBrainpoolp384PublicKeyCompressed == NULL)) { - return -1; - } - - lib_its_security_context_t* lib_its_security_context; - if (initialize_with_public_key(brainpool_p_384_r1, p_ecdsaBrainpoolp384PublicKeyCompressed, p_compressed_mode, &lib_its_security_context) == -1){ - return -1; - } - - int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsaBrainpoolp384PublicKeyCompressed, p_compressed_mode); - uninitialize(&lib_its_security_context); - - return result; -} - -int32_t encrypt_with_ecies_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_encrypted_secured_message, - const size_t p_to_be_encrypted_secured_message_length, - const uint8_t* p_recipients_public_key_compressed, - const ecc_compressed_mode_t p_compressed_mode, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_public_ephemeral_key_compressed, - ecc_compressed_mode_t* p_ephemeral_compressed_mode, - uint8_t** p_aes_sym_key, - uint8_t** p_encrypted_sym_key, - uint8_t** p_authentication_vector, - uint8_t** p_nonce, - uint8_t** p_encrypted_secured_message, - size_t* p_encrypted_secured_message_length - ) { - /* Sanity checks */ - - lib_its_security_context_t* lib_its_security_context = NULL; - lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ - - /* 1. Generate new Private/Public Ephemeral key */ - int32_t result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - goto end; - } - result = generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode); - if (result == -1) { - goto end; - } - - /* 2. Generate and derive shared secret based on recipient's public keys */ - result = initialize_with_public_key(nist_p_256, p_recipients_public_key_compressed, p_compressed_mode, &lib_its_security_context_comp); - if (result == -1) { - goto end; - } - result = generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, p_salt, p_salt_length); - if (result == -1) { - goto end; - } - /* Set the AES symmetric key */ - *p_aes_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_aes_sym_key, (const void*)lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); - /* Set the encrypted symmetric key */ - *p_encrypted_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_encrypted_sym_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); - /* Set the tag of the symmetric key encryption */ - *p_authentication_vector = (uint8_t*)malloc(lib_its_security_context->tag_length); - memcpy((void*)*p_authentication_vector, (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); - /* Set ephemeral public keys */ - *p_public_ephemeral_key_compressed = (uint8_t*)malloc(lib_its_security_context->key_length); - memcpy((void*)*p_public_ephemeral_key_compressed, (const void*)lib_its_security_context->public_key_c, lib_its_security_context->key_length); - *p_ephemeral_compressed_mode = (ecc_compressed_mode_t)(lib_its_security_context->compressed_mode == compressed_y_0) ? 0 : 1; - - /* 3. Retrieve AES 128 parameters */ - *p_nonce = (uint8_t*)malloc(lib_its_security_context->nonce_length); - memcpy((void*)*p_nonce, (const void*)lib_its_security_context->nonce, lib_its_security_context->nonce_length); - /* 4. Encrypt the data using AES-128 CCM */ - lib_its_security_context->encryption_algorithm = aes_128_ccm; - result = encrypt(lib_its_security_context, p_to_be_encrypted_secured_message, p_to_be_encrypted_secured_message_length, p_encrypted_secured_message, p_encrypted_secured_message_length); - if (result == -1) { - // FXIME free all allocated resources - free(*p_aes_sym_key); *p_aes_sym_key = NULL; - free(*p_encrypted_sym_key); *p_encrypted_sym_key = NULL; - free(*p_authentication_vector); *p_authentication_vector = NULL; - free(*p_public_ephemeral_key_compressed); *p_public_ephemeral_key_compressed = NULL; - free(*p_nonce); *p_nonce = NULL; - goto end; - } - show_hex((const int8_t*)"Raw encrypted message", *p_encrypted_secured_message, *p_encrypted_secured_message_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - *p_encrypted_secured_message = (uint8_t*)realloc((void*)*p_encrypted_secured_message, *p_encrypted_secured_message_length + lib_its_security_context->tag_length); - memcpy((void*)(*p_encrypted_secured_message + *p_encrypted_secured_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); - *p_encrypted_secured_message_length += lib_its_security_context->tag_length; - - result = 0; - end: - if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); - if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); - - return result; -} - -int32_t decrypt_with_ecies_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_encrypted_secured_message, - const size_t p_encrypted_secured_message_length, - const uint8_t* p_private_enc_key, - const uint8_t* p_public_ephemeral_key_compressed, - const ecc_compressed_mode_t p_ephemeral_compressed_mode, - const uint8_t* p_encrypted_sym_key, - const uint8_t* p_authentication_vector, - const uint8_t* p_nonce, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_aes_sym_enc_key, - uint8_t** p_plain_text_message, - size_t* p_plain_text_message_length - ) { - /* Sanity checks */ - - lib_its_security_context_t* lib_its_security_context = NULL; - lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ - size_t enc_message_length = 0; - uint8_t* enc_message = NULL; - - /* 1. Initialize security context based on recipient's private key */ - int32_t result = initialize_with_private_key(nist_p_256, p_private_enc_key, &lib_its_security_context); - if (result == -1) { - goto end; - } - - /* 2. Generate the shared secret value based on public ephemeral keys will be required */ - result = initialize_with_public_key(nist_p_256, p_public_ephemeral_key_compressed, p_ephemeral_compressed_mode, &lib_its_security_context_comp); - if (result == -1) { - goto end; - } - result = generate_and_derive_ephemeral_key_for_decryption(lib_its_security_context, aes_128_ccm, lib_its_security_context_comp, p_encrypted_sym_key, p_nonce, p_authentication_vector, p_salt, p_salt_length); - if (result == -1) { - goto end; - } - *p_aes_sym_enc_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_aes_sym_enc_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); - /* Decrypt the message */ - enc_message_length = p_encrypted_secured_message_length - lib_its_security_context->tag_length; - enc_message = (uint8_t*)malloc(enc_message_length); - memcpy((void*)enc_message, (const void*)p_encrypted_secured_message, enc_message_length); // Extract the encrypted message - memcpy((void*)lib_its_security_context->tag, (const void*)(p_encrypted_secured_message + enc_message_length), lib_its_security_context->tag_length); - show_hex((const int8_t*)"Raw encrypted message", enc_message, enc_message_length); - show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); - show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - result = decrypt(lib_its_security_context, enc_message, enc_message_length, p_plain_text_message, p_plain_text_message_length); - if (result == -1) { - free(enc_message); - *p_plain_text_message = NULL; - *p_plain_text_message_length = -1; - goto end; - } - free(enc_message); - - end: - if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); - if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); - - return result; -} - -int32_t encrypt_with_ecies_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_encrypted_secured_message, - const size_t p_to_be_encrypted_secured_message_length, - const uint8_t* p_recipients_public_key_compressed, - const ecc_compressed_mode_t p_compressed_mode, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_public_ephemeral_key_compressed, - ecc_compressed_mode_t* p_ephemeral_compressed_mode, - uint8_t** p_aes_sym_key, - uint8_t** p_encrypted_sym_key, - uint8_t** p_authentication_vector, - uint8_t** p_nonce, - uint8_t** p_encrypted_secured_message, - size_t* p_encrypted_secured_message_length - ) { - /* Sanity checks */ - - lib_its_security_context_t* lib_its_security_context = NULL; - lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ - - /* 1. Generate new Private/Public Ephemeral key */ - int32_t result = initialize(brainpool_p_256_r1, &lib_its_security_context); - if (result == -1) { - goto end; - } - result = generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode); - if (result == -1) { - goto end; - } - - /* 2. Generate and derive shared secret based on recipient's public keys */ - result = initialize_with_public_key(brainpool_p_256_r1, p_recipients_public_key_compressed, p_compressed_mode, &lib_its_security_context_comp); - if (result == -1) { - goto end; - } - result = generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, p_salt, p_salt_length); - if (result == -1) { - goto end; - } - /* Set the AES symmetric key */ - *p_aes_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_aes_sym_key, (const void*)lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); - /* Set the encrypted symmetric key */ - *p_encrypted_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_encrypted_sym_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); - /* Set the tag of the symmetric key encryption */ - *p_authentication_vector = (uint8_t*)malloc(lib_its_security_context->tag_length); - memcpy((void*)*p_authentication_vector, (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); - /* Set ephemeral public keys */ - *p_public_ephemeral_key_compressed = (uint8_t*)malloc(lib_its_security_context->key_length); - memcpy((void*)*p_public_ephemeral_key_compressed, (const void*)lib_its_security_context->public_key_c, lib_its_security_context->key_length); - *p_ephemeral_compressed_mode = (ecc_compressed_mode_t)(lib_its_security_context->compressed_mode == compressed_y_0) ? 0 : 1; - - /* 3. Retrieve AES 128 parameters */ - *p_nonce = (uint8_t*)malloc(lib_its_security_context->nonce_length); - memcpy((void*)*p_nonce, (const void*)lib_its_security_context->nonce, lib_its_security_context->nonce_length); - /* 4. Encrypt the data using AES-128 CCM */ - lib_its_security_context->encryption_algorithm = aes_128_ccm; - result = encrypt(lib_its_security_context, p_to_be_encrypted_secured_message, p_to_be_encrypted_secured_message_length, p_encrypted_secured_message, p_encrypted_secured_message_length); - if (result == -1) { - // FXIME free all allocated resources - free(*p_aes_sym_key); *p_aes_sym_key = NULL; - free(*p_encrypted_sym_key); *p_encrypted_sym_key = NULL; - free(*p_authentication_vector); *p_authentication_vector = NULL; - free(*p_public_ephemeral_key_compressed); *p_public_ephemeral_key_compressed = NULL; - free(*p_nonce); *p_nonce = NULL; - goto end; - } - show_hex((const int8_t*)"Raw encrypted message", *p_encrypted_secured_message, *p_encrypted_secured_message_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - *p_encrypted_secured_message = (uint8_t*)realloc((void*)*p_encrypted_secured_message, *p_encrypted_secured_message_length + lib_its_security_context->tag_length); - memcpy((void*)(*p_encrypted_secured_message + *p_encrypted_secured_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); - *p_encrypted_secured_message_length += lib_its_security_context->tag_length; - - result = 0; - end: - if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); - if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); - - return result; -} - -int32_t decrypt_with_ecies_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_encrypted_secured_message, - const size_t p_encrypted_secured_message_length, - const uint8_t* p_private_enc_key, - const uint8_t* p_public_ephemeral_key_compressed, - const ecc_compressed_mode_t p_ephemeral_compressed_mode, - const uint8_t* p_encrypted_sym_key, - const uint8_t* p_authentication_vector, - const uint8_t* p_nonce, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_aes_sym_enc_key, - uint8_t** p_plain_text_message, - size_t* p_plain_text_message_length - ) { - /* Sanity checks */ - - lib_its_security_context_t* lib_its_security_context = NULL; - lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ - size_t enc_message_length = 0; - uint8_t* enc_message = NULL; - - /* 1. Initialize security context based on recipient's private key */ - int32_t result = initialize_with_private_key(brainpool_p_256_r1, p_private_enc_key, &lib_its_security_context); - if (result == -1) { - goto end; - } - - /* 2. Generate the shared secret value based on public ephemeral keys will be required */ - result = initialize_with_public_key(brainpool_p_256_r1, p_public_ephemeral_key_compressed, p_ephemeral_compressed_mode, &lib_its_security_context_comp); - if (result == -1) { - goto end; - } - result = generate_and_derive_ephemeral_key_for_decryption(lib_its_security_context, aes_128_ccm, lib_its_security_context_comp, p_encrypted_sym_key, p_nonce, p_authentication_vector, p_salt, p_salt_length); - if (result == -1) { - goto end; - } - *p_aes_sym_enc_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); - memcpy((void*)*p_aes_sym_enc_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); - /* Decrypt the message */ - enc_message_length = p_encrypted_secured_message_length - lib_its_security_context->tag_length; - enc_message = (uint8_t*)malloc(enc_message_length); - memcpy((void*)enc_message, (const void*)p_encrypted_secured_message, enc_message_length); // Extract the encrypted message - memcpy((void*)lib_its_security_context->tag, (const void*)(p_encrypted_secured_message + enc_message_length), lib_its_security_context->tag_length); - show_hex((const int8_t*)"Raw encrypted message", enc_message, enc_message_length); - show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); - show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - result = decrypt(lib_its_security_context, enc_message, enc_message_length, p_plain_text_message, p_plain_text_message_length); - if (result == -1) { - free(enc_message); - *p_plain_text_message = NULL; - *p_plain_text_message_length = -1; - goto end; - } - free(enc_message); - - end: - if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); - if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); - - return result; -} - -int32_t generate_key_pair(lib_its_security_context_t* p_lib_its_security_context, uint8_t** p_private_key, uint8_t** p_public_key_x, uint8_t** p_public_key_y, uint8_t** p_public_key_compressed, ecc_compressed_mode_t* p_compressed_mode) { - /* Sanity checks */ - if ((p_lib_its_security_context == NULL) || (p_private_key == NULL) || (p_public_key_x == NULL) || (p_public_key_y == NULL) || (p_public_key_compressed == NULL) || (p_compressed_mode == NULL)) { - return -1; - } - - if (!EC_KEY_generate_key(p_lib_its_security_context->ec_key)) { /* Generate the private and public keys */ - fprintf(stderr, "generate_key_pair: Failed to generate private/public keys\n"); - return -1; - } - - BIGNUM* x = BN_new(); - BIGNUM* y = BN_new(); - const EC_POINT* ec_point = EC_KEY_get0_public_key(p_lib_its_security_context->ec_key); - int32_t result = 0; - size_t size = 0; - switch (p_lib_its_security_context->elliptic_curve) { - case nist_p_256: // Use primary - // No break; - case brainpool_p_256_r1: - size = 32; - result = EC_POINT_get_affine_coordinates_GFp(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); /* Use primer on elliptic curve */ - break; - case brainpool_p_384_r1: - size = 48; - result = EC_POINT_get_affine_coordinates_GFp(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); /* Use primer on elliptic curve */ - break; - default: // Use binary - result = EC_POINT_get_affine_coordinates_GF2m(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); - } // End of 'switch' statement - if (result == 0) { - fprintf(stderr, "generate_key_pair: Failed to get coordinates\n"); - BN_clear_free(x); - BN_clear_free(y); - return -1; - } - - const BIGNUM* p = EC_KEY_get0_private_key(p_lib_its_security_context->ec_key); - *p_private_key = (uint8_t*)malloc(size); - BN_bn2bin(p, (unsigned char*)*p_private_key); - *p_public_key_x = (uint8_t*)malloc(size); - BN_bn2bin(x, (unsigned char*)*p_public_key_x); - *p_public_key_y = (uint8_t*)malloc(size); - BN_bn2bin(y, (unsigned char*)*p_public_key_y); - BN_clear_free(x); x = NULL; - BN_clear_free(y); y = NULL; - - // Compressed - int len = EC_POINT_point2oct(p_lib_its_security_context->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, NULL, 0, p_lib_its_security_context->bn_ctx); - if (len == 0) { - fprintf(stderr, "generate_key_pair: Failed to generate x_coordinate compressed key\n"); - } - *p_public_key_compressed = (uint8_t*)malloc(len); - if (EC_POINT_point2oct(p_lib_its_security_context->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (unsigned char*)*p_public_key_compressed, len, p_lib_its_security_context->bn_ctx) == 0) { - fprintf(stderr, "generate_key_pair: Failed to generate x_coordinate compressed key\n"); - memset((void*)*p_public_key_compressed, 0x00, len); - } else { /* Remove first byte */ - *p_compressed_mode = (ecc_compressed_mode_t)(((*p_public_key_compressed)[0] & 0x01) == 0x00) ? compressed_y_0 : compressed_y_1; - memmove((void*)*p_public_key_compressed, (const void*)(*p_public_key_compressed + 1), len - 1); - } - - return 0; -} - -#if defined(__MAIN__) - -static const uint8_t* test_string = (const uint8_t*)"cafedeca"; - -static lib_its_security_context_t* lib_its_security_context = NULL; -static lib_its_security_context_t* lib_its_security_context_comp = NULL; - -int main(int argc, char** argv) { - int32_t result; - - printf("###########################################################################\n"); - /* Test initialize */ - assert(lib_its_security_context == NULL); - assert(initialize(nist_p_256, NULL) == -1); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - } - assert(lib_its_security_context != NULL); - assert(lib_its_security_context->elliptic_curve == nist_p_256); - assert(lib_its_security_context->ec_key != NULL); - - /* Test hash_with_sha256 */ - { - uint8_t* hashed_data = NULL; - uint8_t* data_to_be_hashed = NULL; - result = hash_with_sha256(data_to_be_hashed, 10, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); - } else { - assert(hashed_data != NULL); - assert(hashed_data[0] == 0xe3); - assert(hashed_data[31] == 0x55); - } - free(hashed_data); hashed_data = NULL; - size_t l; - data_to_be_hashed = hex_to_bin((const int8_t*)test_string, &l); - result = hash_with_sha256(data_to_be_hashed, 0, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); - } else { - assert(hashed_data != NULL); - assert(hashed_data[0] == 0xe3); - assert(hashed_data[31] == 0x55); - } - free(hashed_data); hashed_data = NULL; - result = hash_with_sha256(data_to_be_hashed, l, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"sha256", hashed_data, 32); - assert(hashed_data != NULL); - assert(hashed_data[0] == 0x84); - assert(hashed_data[31] == 0xfb); - } - free(data_to_be_hashed); - free(hashed_data); - } - - /* Test hash_with_sha384 */ - { - uint8_t* hashed_data = NULL; - uint8_t* data_to_be_hashed = NULL; - result = hash_with_sha384(data_to_be_hashed, 10, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); - } else { - assert(hashed_data != NULL); - assert(hashed_data[0] == 0x38); - assert(hashed_data[47] == 0x5b); - } - free(hashed_data); hashed_data = NULL; - size_t l; - data_to_be_hashed = hex_to_bin((const int8_t*)test_string, &l); - result = hash_with_sha384(data_to_be_hashed, 0, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); - } else { - assert(hashed_data != NULL); - assert(hashed_data[0] == 0x38); - assert(hashed_data[47] == 0x5b); - } - free(hashed_data); hashed_data = NULL; - result = hash_with_sha384(data_to_be_hashed, l, &hashed_data); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"sha384", hashed_data, 48); - assert(hashed_data != NULL); - assert(hashed_data[0] == 0x64); - assert(hashed_data[47] == 0x12); - } - free(data_to_be_hashed); - free(hashed_data); - } - - /* Test hmac_sha256 */ - { - uint8_t* hmac = NULL; - size_t secret_length; - uint8_t* secret = hex_to_bin((const int8_t*)"4a656665", &secret_length); - size_t message_length; - uint8_t* message = hex_to_bin((const int8_t*)"7768617420646f2079612077616e7420666f72206e6f7468696e673f", &message_length); - assert(hmac_sha256(secret, secret_length, message, message_length, NULL) == -1); - assert(hmac_sha256(NULL, secret_length, message, message_length, &hmac) == -1); - assert(hmac_sha256(secret, secret_length, NULL, message_length, &hmac) == -1); - assert(hmac_sha256(secret, 0, message, message_length, &hmac) == -1); - assert(hmac_sha256(secret, secret_length, message, 0, &hmac) == -1); - result = hmac_sha256(secret, secret_length, message, message_length, &hmac); - if (result == -1) { - fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"hmac-sha256", hmac, 16); - assert(hmac[0] == 0x5b); - assert(hmac[15] == 0xc7); - free(hmac); - } - free(secret); - free(message); - } - - /* Test generate_key_pair */ - { - uint8_t* private_key; - uint8_t* public_key_x; - uint8_t* public_key_y; - uint8_t* public_key_compressed; - ecc_compressed_mode_t public_key_compressed_mode; - assert(generate_key_pair(NULL, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); - assert(generate_key_pair(lib_its_security_context, NULL, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); - assert(generate_key_pair(lib_its_security_context, &private_key, NULL, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); - assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, NULL, &public_key_compressed, &public_key_compressed_mode) == -1); - assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, NULL, &public_key_compressed_mode) == -1); - assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, NULL) == -1); - result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); - if (result == -1) { - fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"private_key", private_key, 32); - free(private_key); - show_hex((const int8_t*)"public_key_x", public_key_x, 32); - free(public_key_x); - show_hex((const int8_t*)"public_key_y", public_key_y, 32); - free(public_key_y); - show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); - free(public_key_compressed); - printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); - } - } - - /* Test uninitialize */ - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - - printf("###########################################################################\n"); - /* Test basic signature */ - { - assert(lib_its_security_context == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - uint8_t* private_key; - uint8_t* public_key_x; - uint8_t* public_key_y; - uint8_t* public_key_compressed; - ecc_compressed_mode_t public_key_compressed_mode; - result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); - if (result == -1) { - fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"private_key", private_key, 32); - show_hex((const int8_t*)"public_key_x", public_key_x, 32); - show_hex((const int8_t*)"public_key_y", public_key_y, 32); - show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); - printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); - - uint8_t* sig_r; - uint8_t* sig_s; - size_t sig_length; - result = sign(lib_its_security_context, public_key_y, 32, &sig_r, &sig_s, &sig_length); - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } else { - show_hex((const int8_t*)"sig_r", sig_r, 32); - show_hex((const int8_t*)"sig_s", sig_s, 32); - printf("signature length=%ld\n", sig_length); - result = sign_verify(lib_its_security_context, public_key_y, 32, sig_r, sig_s, sig_length); - if (result == 0) { - printf("Signature was verified\n"); - } else { - printf("Signature was NOT verified\n"); - } - *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; - result = sign_verify(lib_its_security_context, public_key_y, 32, sig_r, sig_s, sig_length); - if (result == -1) { - printf("Signature was not verified successfully\n"); - } else { - printf("Signature SHALL NOT be verified\n"); - } - free(sig_r); - free(sig_s); - } - free(private_key); - free(public_key_x); - free(public_key_y); - free(public_key_compressed); - } - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test signature NistP-256 */ - printf("###########################################################################\n"); - { - assert(lib_its_security_context == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - uint8_t* private_key; - uint8_t* public_key_x; - uint8_t* public_key_y; - uint8_t* public_key_compressed; - ecc_compressed_mode_t public_key_compressed_mode; - result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); - if (result == -1) { - fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"private_key ", private_key, 32); - show_hex((const int8_t*)"public_key_x", public_key_x, 32); - show_hex((const int8_t*)"public_key_y", public_key_y, 32); - show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); - printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); - - uint8_t issuer[32] = { 0x00 }; - uint8_t* sig; - result = sign_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, private_key, &sig); - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } else { - show_hex((const int8_t*)"sig", sig, 64); - result = verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, sig, public_key_compressed, public_key_compressed_mode); - if (result == 0) { - printf("Signature was verified\n"); - } else { - printf("Signature was NOT verified\n"); - } - *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; - result = verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, sig, public_key_compressed, public_key_compressed_mode); - if (result == -1) { - printf("Signature was not verified successfully\n"); - } else { - printf("Signature SHALL NOT be verified\n"); - } - free(sig); - } - free(private_key); - free(public_key_x); - free(public_key_y); - free(public_key_compressed); - } - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test signature BrainpoolP-384r1 */ - printf("###########################################################################\n"); - printf("Test signature BrainpoolP-384r1\n"); - { - assert(lib_its_security_context == NULL); - result = initialize(brainpool_p_384_r1, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - uint8_t* private_key; - uint8_t* public_key_x; - uint8_t* public_key_y; - uint8_t* public_key_compressed; - ecc_compressed_mode_t public_key_compressed_mode; - result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); - if (result == -1) { - fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); - } else { - show_hex((const int8_t*)"private_key", private_key, 48); - show_hex((const int8_t*)"public_key_x", public_key_x, 48); - show_hex((const int8_t*)"public_key_y", public_key_y, 48); - show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 48); - printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); - - uint8_t issuer[32] = { 0x00 }; - uint8_t* sig; - result = sign_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, private_key, &sig); - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } else { - show_hex((const int8_t*)"sig", sig, 96); - result = verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, sig, public_key_compressed, public_key_compressed_mode); - if (result == 0) { - printf("Signature was verified\n"); - } else { - printf("Signature was NOT verified\n"); - } - *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; - result = verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, sig, public_key_compressed, public_key_compressed_mode); - if (result == -1) { - printf("Signature was not verified successfully\n"); - } else { - printf("Signature SHALL NOT be verified\n"); - } - free(sig); - } - free(private_key); - free(public_key_x); - free(public_key_y); - free(public_key_compressed); - } - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test kdf_sha256 */ - printf("###########################################################################\n"); - printf("Test kdf_sha256 \n"); - { - assert(lib_its_security_context == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - // Test #1 - lib_its_security_context->secret_key = hex_to_bin((const int8_t*)"035DE77D62E51528ABE1403B25C8F0B8EFD47353EFD65E12F79A77122BF5137C", &lib_its_security_context->secret_key_length); - size_t salt_length; - uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); - size_t expected_digest_length; - uint8_t* expected_digest = hex_to_bin((const int8_t*)"3261BBDBA2301F163E1DEDF5038EDB146EDD08269AF295897089411FEA5372E073C3E330926D3828A7B88DF9CEA4ED65A4A5629424C490A869C1A54F91775EC0", &expected_digest_length); - uint8_t* digest; - size_t digest_length; - assert(kdf2(lib_its_security_context, salt, salt_length, 48, 0x00, &digest, &digest_length) == 0); - assert(expected_digest_length == digest_length); - for (int32_t i = 0; i < expected_digest_length; assert(digest[i] == expected_digest[i]), i++); - free(digest); - free(salt); - free(expected_digest); - free(lib_its_security_context->secret_key); lib_its_security_context->secret_key = NULL; - // Test #2 - lib_its_security_context->secret_key = hex_to_bin((const int8_t*)"8774F7739C1C7D33F1DD108527B8B5F532ED301C7AF9D2D750BA585B95AE6DDB", &lib_its_security_context->secret_key_length); - salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); - expected_digest = hex_to_bin((const int8_t*)"CEFD867314270E19795F9B8622D2E565B463CEA484A2E467BFAAD24AC3CC782BC62C55A95259CEA36ED1049E5454A7A272CDCE7A24B6140A740E4C4002B0A6F9", &expected_digest_length); - assert(kdf2(lib_its_security_context, salt, salt_length, 48, 0x00, &digest, &digest_length) == 0); - assert(expected_digest_length == digest_length); - for (int32_t i = 0; i < expected_digest_length; assert(digest[i] == expected_digest[i]), i++); - free(digest); - free(salt); - free(expected_digest); - free(lib_its_security_context->secret_key); lib_its_security_context->secret_key = NULL; - - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test encrypt function */ - printf("###########################################################################\n"); - printf("Test encrypt \n"); - { - assert(lib_its_security_context == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - // Test #1 - lib_its_security_context->nonce = hex_to_bin((const int8_t*)"8A395AA1C94062766027BFAC", &lib_its_security_context->nonce_length); - lib_its_security_context->sym_key = hex_to_bin((const int8_t*)"A3762D576B7A1DC2A2D8CF11B28A8BF8", &lib_its_security_context->sym_key_length); - size_t plain_text_message_length; - uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); - uint8_t* cipher_message; - size_t cipher_message_length; - lib_its_security_context->encryption_algorithm = aes_128_ccm; - assert(encrypt(lib_its_security_context, plain_text_message, plain_text_message_length, &cipher_message, &cipher_message_length) == 0); - printf("cipher_message_length= %ld\n", cipher_message_length); - show_hex((const int8_t*)"cipher_message", cipher_message, cipher_message_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - cipher_message = (uint8_t*)realloc((void*)cipher_message, cipher_message_length + lib_its_security_context->tag_length); - memcpy((void*)(cipher_message + cipher_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); - cipher_message_length += lib_its_security_context->tag_length; - show_hex((const int8_t*)"cipher_message||tag", cipher_message, cipher_message_length); - size_t expected_cipher_message_length; - uint8_t* expected_cipher_message = hex_to_bin((const int8_t*)"cfea3fed73db25664feb046e0097fb57e541b12d74985965b175462893f32f9b373525b399367140542f44f94abb8b9df77b0d2bcce4709081d7d4ad781b8f28c86d8ee48e3b5427cf57ade2927701066d565073bbb31c2e54bf68da36296f9a23ab4c63a8ac26f92d0b99d28650120cb2d2dc0220a0bc56267736e3607c8a78094e167b65191a20cf9cdcb58d757756de32c75822de5687db6d7a65803137347a43da0db6de10dcfd3f045c3cc2198f29522cb72fc5296fdafa3b13151bb866078c5305b1a9ee08c34fb12b2c2c7bf06866f0d308e0721557d35448c37f126c96328acdc1298f316d6b0e94b2bb15228f5906809f56e39e2a5fba1d06b6222c3ff0234580288c09566c79d72342a2724033a55921dbabf3ec01ee123976b171e3c549", &expected_cipher_message_length); - assert(expected_cipher_message_length == cipher_message_length); - for (int32_t i = 0; i < expected_cipher_message_length; assert(*(expected_cipher_message + i) == *(cipher_message + i)), i++); - free(plain_text_message); - free(expected_cipher_message); - free(cipher_message); - - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test decrypt function */ - printf("###########################################################################\n"); - printf("Test decrypt \n"); - { - assert(lib_its_security_context == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - // Test #1 - lib_its_security_context->nonce = hex_to_bin((const int8_t*)"8A395AA1C94062766027BFAC", &lib_its_security_context->nonce_length); - lib_its_security_context->sym_key = hex_to_bin((const int8_t*)"A3762D576B7A1DC2A2D8CF11B28A8BF8", &lib_its_security_context->sym_key_length); - lib_its_security_context->tag = hex_to_bin((const int8_t*)"5921DBABF3EC01EE123976B171E3C549", &lib_its_security_context->tag_length); - size_t cipher_message_length; - uint8_t* cipher_message = hex_to_bin((const int8_t*)"cfea3fed73db25664feb046e0097fb57e541b12d74985965b175462893f32f9b373525b399367140542f44f94abb8b9df77b0d2bcce4709081d7d4ad781b8f28c86d8ee48e3b5427cf57ade2927701066d565073bbb31c2e54bf68da36296f9a23ab4c63a8ac26f92d0b99d28650120cb2d2dc0220a0bc56267736e3607c8a78094e167b65191a20cf9cdcb58d757756de32c75822de5687db6d7a65803137347a43da0db6de10dcfd3f045c3cc2198f29522cb72fc5296fdafa3b13151bb866078c5305b1a9ee08c34fb12b2c2c7bf06866f0d308e0721557d35448c37f126c96328acdc1298f316d6b0e94b2bb15228f5906809f56e39e2a5fba1d06b6222c3ff0234580288c09566c79d72342a2724033a5", &cipher_message_length); - uint8_t* plain_text_message; - size_t plain_text_message_length; - lib_its_security_context->encryption_algorithm = aes_128_ccm; - assert(decrypt(lib_its_security_context, cipher_message, cipher_message_length, &plain_text_message, &plain_text_message_length) == 0); - printf("plain_text_message_length= %ld\n", plain_text_message_length); - show_hex((const int8_t*)"plain_text_message", plain_text_message, plain_text_message_length); - size_t expected_plain_text_message_length; - uint8_t* expected_plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &expected_plain_text_message_length); - assert(expected_plain_text_message_length == cipher_message_length); - for (int32_t i = 0; i < expected_plain_text_message_length; assert(*(expected_plain_text_message + i) == *(plain_text_message + i)), i++); - free(cipher_message); - free(plain_text_message); - free(expected_plain_text_message); - - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test generate_and_derive_ephemeral_key_for_encryption */ - printf("###########################################################################\n"); - printf("Test generate_and_derive_ephemeral_key_for_encryption \n"); - { - assert(lib_its_security_context == NULL); - assert(lib_its_security_context_comp == NULL); - size_t l; - uint8_t* private_key = hex_to_bin((const int8_t*)"65322BEE2CFC665FBBAC6C0DC42EE73422278DFB7563A6350F7087013E216ACA", &l); - assert(l == 32); - result = initialize_with_private_key(nist_p_256, private_key, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - free(private_key); - - // Test #1 - size_t recipients_public_key_length; - uint8_t* recipients_public_key = hex_to_bin((const int8_t*)"E169F42FB028801B6DB717F5E7A37A7FBB17CB95A811BF224588F6F256FE8DDC", &recipients_public_key_length); - assert(recipients_public_key_length == 32); - assert(initialize_with_public_key(nist_p_256, recipients_public_key, compressed_y_0, &lib_its_security_context_comp) == 0); - assert(lib_its_security_context_comp->ec_key != NULL); - assert(lib_its_security_context_comp->ec_group != NULL); - assert(lib_its_security_context_comp->key_length == 32); - size_t salt_length; - uint8_t* salt = hex_to_bin((const int8_t*)"89BAB7DEA15BDAF3FF0357D952760A25735DD9816941BF6562C042D452D16EBA", &salt_length); - assert(generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, salt, salt_length) == 0); - assert(lib_its_security_context->sym_key_length == 16); - assert(lib_its_security_context->tag_length == 16); - // Expected digest: 22cc5d042f654a9ce39e52fe232248a8d4793603b1ce4e98f67f2d634c24692573a2e89dbe9952e79b32faa0c94bf614b243fd84097d2eb50c4d6a4b996b7c12 - // Expected k1: 22cc5d042f654a9ce39e52fe232248a8 - // Expected k2: d4793603b1ce4e98f67f2d634c24692573a2e89dbe9952e79b32faa0c94bf614 - show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); - show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); - show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); - show_hex((const int8_t*)"enc_sym_key", lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); - - free(recipients_public_key); - free(salt); - - uninitialize(&lib_its_security_context_comp); - lib_its_security_context_comp = NULL; - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test encrypt_with_ecies_nistp256_with_sha256 #1 */ - printf("###########################################################################\n"); - printf("Test xxcrypt_with_ecies_nistp256_with_sha256 #1 \n"); - { - printf("==> encrypt_with_ecies_nistp256_with_sha256 #1 \n"); - assert(lib_its_security_context == NULL); - assert(lib_its_security_context_comp == NULL); - result = initialize(nist_p_256, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - /* Generate recipient's key */ - assert(generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode) == 0); - /* Set parameters */ - size_t plain_text_message_length; - uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); - size_t salt_length; - uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); - /* Encrypt */ - uint8_t* ephemeral_key_compressed = NULL; - ecc_compressed_mode_t ephemeral_compressed_mode; - uint8_t* aes_sym_key = NULL; - uint8_t* encrypted_sym_key = NULL; - uint8_t* authentication_vector = NULL; - uint8_t* nonce = NULL; - uint8_t* encrypted_secured_message = NULL; - size_t encrypted_secured_message_length; - assert(encrypt_with_ecies_nistp256_with_sha256(lib_its_security_context/*recipient's public keys*/, plain_text_message, plain_text_message_length, lib_its_security_context->public_key_c, lib_its_security_context->compressed_mode, salt, salt_length, &ephemeral_key_compressed, &ephemeral_compressed_mode, &aes_sym_key, &encrypted_sym_key, &authentication_vector, &nonce, &encrypted_secured_message, &encrypted_secured_message_length) == 0); - show_hex((const int8_t*)"ephemeral_key_compressed", ephemeral_key_compressed, 32); - show_hex((const int8_t*)"encrypted_secured_message || tag", encrypted_secured_message, encrypted_secured_message_length); - /* Decrypt */ - printf("==> decrypt_with_ecies_nistp256_with_sha256 #1 \n"); - size_t new_plain_text_message_length; - uint8_t* new_plain_text_message = NULL; - uint8_t* new_aes_enc_sym_key = NULL; - assert(decrypt_with_ecies_nistp256_with_sha256(lib_its_security_context, encrypted_secured_message, encrypted_secured_message_length, lib_its_security_context->private_key, ephemeral_key_compressed, ephemeral_compressed_mode, encrypted_sym_key, authentication_vector, nonce, salt, salt_length, &new_aes_enc_sym_key, &new_plain_text_message, &new_plain_text_message_length) == 0); - show_hex((const int8_t*)"new_plain_text_message", new_plain_text_message, new_plain_text_message_length); - show_hex((const int8_t*)"new_aes_enc_sym_key", new_aes_enc_sym_key, 16); - /* TODO Verify result */ - assert(new_plain_text_message_length == plain_text_message_length); - for (int32_t i = 0; i < plain_text_message_length; assert(*(plain_text_message + i) == *(new_plain_text_message + i)), i++); - for (int32_t i = 0; i < 16; assert(*(encrypted_sym_key + i) == *(new_aes_enc_sym_key + i)), i++); - - free(new_plain_text_message); - free(new_aes_enc_sym_key); - free(plain_text_message); - free(salt); - free(aes_sym_key); - free(encrypted_sym_key); - free(authentication_vector); - free(nonce); - free(encrypted_secured_message); - free(ephemeral_key_compressed); - - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - /* Test encrypt_with_ecies_brainpoolp256r1_with_sha256 #1 */ - printf("###########################################################################\n"); - printf("Test xxcrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); - { - printf("==> encrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); - assert(lib_its_security_context == NULL); - assert(lib_its_security_context_comp == NULL); - result = initialize(brainpool_p_256_r1, &lib_its_security_context); - if (result == -1) { - fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - /* Generate recipient's key */ - assert(generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode) == 0); - /* Set parameters */ - size_t plain_text_message_length; - uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); - size_t salt_length; - uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); - /* Encrypt */ - uint8_t* ephemeral_key_compressed = NULL; - ecc_compressed_mode_t ephemeral_compressed_mode; - uint8_t* aes_sym_key = NULL; - uint8_t* encrypted_sym_key = NULL; - uint8_t* authentication_vector = NULL; - uint8_t* nonce = NULL; - uint8_t* encrypted_secured_message = NULL; - size_t encrypted_secured_message_length; - assert(encrypt_with_ecies_brainpoolp256r1_with_sha256(lib_its_security_context/*recipient's public keys*/, plain_text_message, plain_text_message_length, lib_its_security_context->public_key_c, lib_its_security_context->compressed_mode, salt, salt_length, &ephemeral_key_compressed, &ephemeral_compressed_mode, &aes_sym_key, &encrypted_sym_key, &authentication_vector, &nonce, &encrypted_secured_message, &encrypted_secured_message_length) == 0); - show_hex((const int8_t*)"ephemeral_key_compressed", ephemeral_key_compressed, 32); - show_hex((const int8_t*)"encrypted_secured_message || tag", encrypted_secured_message, encrypted_secured_message_length); - /* Decrypt */ - printf("==> decrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); - size_t new_plain_text_message_length; - uint8_t* new_plain_text_message = NULL; - uint8_t* new_aes_enc_sym_key = NULL; - assert(decrypt_with_ecies_brainpoolp256r1_with_sha256(lib_its_security_context, encrypted_secured_message, encrypted_secured_message_length, lib_its_security_context->private_key, ephemeral_key_compressed, ephemeral_compressed_mode, encrypted_sym_key, authentication_vector, nonce, salt, salt_length, &new_aes_enc_sym_key, &new_plain_text_message, &new_plain_text_message_length) == 0); - show_hex((const int8_t*)"new_plain_text_message", new_plain_text_message, new_plain_text_message_length); - show_hex((const int8_t*)"new_aes_enc_sym_key", new_aes_enc_sym_key, 16); - /* TODO Verify result */ - assert(new_plain_text_message_length == plain_text_message_length); - for (int32_t i = 0; i < plain_text_message_length; assert(*(plain_text_message + i) == *(new_plain_text_message + i)), i++); - for (int32_t i = 0; i < 16; assert(*(encrypted_sym_key + i) == *(new_aes_enc_sym_key + i)), i++); - - free(new_plain_text_message); - free(new_aes_enc_sym_key); - free(plain_text_message); - free(salt); - free(aes_sym_key); - free(encrypted_sym_key); - free(authentication_vector); - free(nonce); - free(encrypted_secured_message); - free(ephemeral_key_compressed); - - result = uninitialize(&lib_its_security_context); - lib_its_security_context = NULL; - if (result == -1) { - fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); - return -1; - } - } - - return 0; -} - -#endif +/*! + * \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 +#include +#ifndef _Win64 +#include +#else +#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers + // Windows Header Files +#include +#include +#endif + +#include + +/** + * 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); +#ifdef _Win64 + free(result); +#endif + } 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 + ) { + const EC_GROUP *ec_group = EC_KEY_get0_group(p_lib_its_security_context->ec_key); + const EC_POINT *pub = EC_KEY_get0_public_key(p_lib_its_security_context->ec_key); + BIGNUM *pub_bn = BN_new(); + + EC_POINT_point2bn(ec_group, pub, POINT_CONVERSION_UNCOMPRESSED, pub_bn, p_lib_its_security_context->bn_ctx); + *p_bin_key = (uint8_t*)malloc(BN_num_bytes(pub_bn)); + BN_bn2bin(pub_bn, *p_bin_key); + + BN_clear_free(pub_bn); + + return 0; +} + +int kdf2_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_salt, + const int32_t p_salt_length, + const int32_t p_key_length, + uint8_t** p_digest, size_t* p_digest_length + ) { + // Sanity checks + + int sha256_blk_len = 32; + int num_blk_out = (int)ceil(p_key_length/(float)sha256_blk_len); + uint8_t* digest = (uint8_t*)malloc((num_blk_out + 1) * sha256_blk_len); + int32_t digest_idx = 0; + const size_t hash_input_length = p_lib_its_security_context->secret_key_length + sizeof(int32_t) + p_salt_length; + uint8_t* hash_input = (uint8_t*)malloc(hash_input_length); + int i_ntonl; + for (int32_t i = 1; i < num_blk_out + 1; i++) { + uint8_t* p = hash_input; + memcpy((void*)p, (const void*)p_lib_its_security_context->secret_key, p_lib_its_security_context->secret_key_length); + p += p_lib_its_security_context->secret_key_length; + i_ntonl = htonl(i); + memcpy((void*)p, (const void*)&i_ntonl, sizeof(int32_t)); + p += sizeof(int32_t); + memcpy((void*)p, (const void*)p_salt, p_salt_length); + //show_hex((const int8_t*)"hash_input", (const void*)hash_input, hash_input_length); + uint8_t* h; + hash_with_sha256(hash_input, hash_input_length, &h); + //show_hex((const int8_t*)"h", (const void*)h, 32); + memcpy((void*)(digest + digest_idx), (const void*)h, sha256_blk_len); + //show_hex((const int8_t*)"digest", (const void*)digest, digest_idx + sha256_blk_len); + digest_idx += sha256_blk_len; + free(h); + } // End of 'for' statement + free(hash_input); + if (digest_idx > p_key_length * 2) { + digest_idx = p_key_length * 2; + } + *p_digest = (uint8_t*)malloc(digest_idx); + memcpy((void*)(*p_digest), (const void*)digest, digest_idx); + *p_digest_length = digest_idx; + free(digest); + + return 0; +} + +int32_t kdf2( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_salt, + const int32_t p_salt_length, + const int32_t p_key_length, + const unsigned char p_hash_algorithm, + uint8_t** p_digest, + size_t* p_digest_length + ) { + // Sanity checks + + int result = -1; + switch (p_hash_algorithm) { + case 0x00: // SHA 256 + result = kdf2_sha256(p_lib_its_security_context, p_salt, p_salt_length, p_key_length, p_digest, p_digest_length); + break; + } // End of 'switch' statement + + return result; +} + +int32_t generate_and_derive_ephemeral_key_for_encryption( + lib_its_security_context_t* p_ecdh_private_key, + const encryption_algorithm_t p_enc_algorithm, + lib_its_security_context_t* p_public_keys, + const uint8_t* p_salt, + const size_t p_salt_length + ) { + // Sanity checks + if (p_public_keys->private_key != NULL) { + return -1; + } + if ((p_public_keys->public_key_x == NULL) || (p_public_keys->public_key_y == NULL)) { + return -1; + } + + // Set buffers size + p_ecdh_private_key->encryption_algorithm = p_enc_algorithm; + switch (p_ecdh_private_key->encryption_algorithm) { + case aes_128_ccm: + // No break; + case aes_128_gcm: + p_ecdh_private_key->nonce_length = 12; + p_ecdh_private_key->sym_key_length = 16; + p_ecdh_private_key->tag_length = 16; + break; + default: + return -1; + } // End of 'switch' statement + uint8_t k_enc; + uint8_t k_mac; + switch (p_ecdh_private_key->elliptic_curve) { + case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve + // No break; + case brainpool_p_256_r1: + k_enc = 16; + k_mac = 32; + break; + case brainpool_p_384_r1: + k_enc = 24; // TODO To be checked + k_mac = 48; + break; + default: + return -1; + } // End of 'switch' statement + + /* Convert the ephemeral public encryption keys to an EC point */ + EC_POINT *ec_point = NULL; + bin_to_ec_point(p_public_keys, p_public_keys->public_key_x, p_public_keys->public_key_y, &ec_point); + show_ec_point((const int8_t *)"ec_point", p_public_keys, ec_point); + /* Generate the shared secret key (Key Agreement) */ + p_ecdh_private_key->secret_key_length = (EC_GROUP_get_degree(p_ecdh_private_key->ec_group) + 7) / 8; + p_ecdh_private_key->secret_key = (uint8_t*)malloc(p_ecdh_private_key->secret_key_length); + int32_t result = ECDH_compute_key( + p_ecdh_private_key->secret_key, + p_ecdh_private_key->secret_key_length, + ec_point, // From recipient's public keys + p_ecdh_private_key->ec_key, // From ephemeral's private key + NULL); + if (result != p_ecdh_private_key->secret_key_length) { + free(p_ecdh_private_key->secret_key); + p_ecdh_private_key->secret_key = NULL; + EC_POINT_free(ec_point); + return -1; + } + EC_POINT_free(ec_point); + show_hex((const int8_t*)"secret", p_ecdh_private_key->secret_key, p_ecdh_private_key->secret_key_length); + + /* Derive the shared secret key */ + uint8_t* digest; + size_t digest_length; + if (kdf2(p_ecdh_private_key, p_salt, p_salt_length, k_enc + k_mac, 0x00/*sha256*/, &digest, &digest_length) != 0) { + free(p_ecdh_private_key->secret_key); + p_ecdh_private_key->secret_key = NULL; + return -1; + } + show_hex((const int8_t*)"digest", digest, digest_length); + + /* Extract K1 and generate encrypted symmetric key */ + uint8_t* k1 = (uint8_t*)malloc(k_enc); + memcpy((void*)k1, (const void*)digest, k_enc); + show_hex((const int8_t*)"k1", k1, k_enc); + BIGNUM* r = BN_new(); + BN_pseudo_rand(r, k_enc * 8, -1, 0); + p_ecdh_private_key->sym_key = (uint8_t*)malloc(k_enc); + p_ecdh_private_key->sym_key_length = k_enc; + BN_bn2bin(r, p_ecdh_private_key->sym_key); + BN_free(r); + show_hex((const int8_t*)"sym_key", p_ecdh_private_key->sym_key, p_ecdh_private_key->sym_key_length); + p_ecdh_private_key->enc_sym_key = (uint8_t*)malloc(k_enc); + for (int i = 0; i < k_enc; *(p_ecdh_private_key->enc_sym_key + i) = *(k1 + i) ^ *(p_ecdh_private_key->sym_key + i), i++); + show_hex((const int8_t*)"enc_sym_key", p_ecdh_private_key->enc_sym_key, p_ecdh_private_key->sym_key_length); + + // Extract K2 and generate Tag vector + int32_t k2_length = k_enc * 2; + uint8_t* k2 = (uint8_t*)malloc(k2_length); + memcpy((void*)k2, (const void*)(k_enc + digest), k2_length); + show_hex((const int8_t*)"k2", k2, k2_length); + hmac_sha256(p_ecdh_private_key->enc_sym_key, p_ecdh_private_key->sym_key_length, k2, k2_length, &p_ecdh_private_key->tag); + show_hex((const int8_t*)"tag", p_ecdh_private_key->tag, p_ecdh_private_key->tag_length); + + /* Generate random IV (nonce) */ + r = BN_new(); + BN_pseudo_rand(r, p_ecdh_private_key->nonce_length * 8, -1, 0); + p_ecdh_private_key->nonce = (uint8_t*)malloc(p_ecdh_private_key->nonce_length); + BN_bn2bin(r, p_ecdh_private_key->nonce); + BN_free(r); + show_hex((const int8_t*)"nonce", p_ecdh_private_key->nonce, p_ecdh_private_key->nonce_length); + + free(digest); + free(k1); + free(k2); + return 0; +} + +int32_t encrypt( + lib_its_security_context_t* lib_its_security_context, + const uint8_t* p_plain_text_message, + const size_t p_plain_text_message_length, + uint8_t** p_cipher_message, + size_t *p_cipher_message_length + ) { + /* Sanity checks */ + + /* Initialize the context and encryption operation */ + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + /* Allocate buffers size */ + switch (lib_its_security_context->encryption_algorithm) { + case aes_128_ccm: + EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL); + if (lib_its_security_context->tag != NULL) { + free(lib_its_security_context->tag); + } + lib_its_security_context->tag_length = 16; + lib_its_security_context->tag = (uint8_t*)malloc(lib_its_security_context->tag_length); + *p_cipher_message = (uint8_t*)malloc(p_plain_text_message_length); + break; + case aes_256_ccm: + EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL); + break; + case aes_128_gcm: + EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); + if (lib_its_security_context->tag != NULL) { + free(lib_its_security_context->tag); + } + lib_its_security_context->tag_length = 16; + lib_its_security_context->tag = (uint8_t*)malloc(lib_its_security_context->tag_length); + *p_cipher_message = (uint8_t*)malloc(p_plain_text_message_length); + break; + case aes_256_gcm: + EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + break; + } /* End of 'switch' statement */ + *p_cipher_message_length = p_plain_text_message_length; + /* Set nonce length */ + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, lib_its_security_context->nonce_length, NULL); + /* Set tag length */ + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, lib_its_security_context->tag_length, NULL); + /* Prime the key and nonce */ + EVP_EncryptInit_ex(ctx, NULL, NULL, lib_its_security_context->sym_key, lib_its_security_context->nonce); + // No authentication data + // Encrypt the data + int len = 0; + EVP_EncryptUpdate(ctx, *p_cipher_message, &len, p_plain_text_message, p_plain_text_message_length); + // Finalize the encryption session + EVP_EncryptFinal_ex(ctx, (*p_cipher_message) + len, &len); + /* Get the authentication tag */ + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, lib_its_security_context->tag_length, lib_its_security_context->tag); + + EVP_CIPHER_CTX_free(ctx); + + return 0; +} + +int32_t generate_and_derive_ephemeral_key_for_decryption( + lib_its_security_context_t* p_lib_its_security_context, + const encryption_algorithm_t p_enc_algorithm, + lib_its_security_context_t* p_ephemeral_keys, + const uint8_t* p_enc_sym_key, + const uint8_t* p_nonce, + const uint8_t* p_authentication_vector, + const uint8_t* p_salt, + const size_t p_salt_length + ) { + /* Sanity checks */ + if ((p_lib_its_security_context->public_key_x == NULL) || (p_lib_its_security_context->public_key_y == NULL)) { + return -1; + } + + /* Set buffers size */ + p_lib_its_security_context->encryption_algorithm = p_enc_algorithm; + switch (p_lib_its_security_context->encryption_algorithm) { + case aes_128_ccm: + // No break; + case aes_128_gcm: + p_lib_its_security_context->nonce_length = 12; + p_lib_its_security_context->sym_key_length = 16; + p_lib_its_security_context->tag_length = 16; + break; + default: + return -1; + } // End of 'switch' statement + unsigned int k_enc; + unsigned int k_mac; + switch (p_lib_its_security_context->elliptic_curve) { + case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve + // No break; + case brainpool_p_256_r1: + k_enc = 16; + k_mac = 32; + break; + case brainpool_p_384_r1: + break; + default: + return -1; + } // End of 'switch' statement + + /* Fill context buffer */ + p_lib_its_security_context->nonce = (uint8_t*)malloc(p_lib_its_security_context->nonce_length); + memcpy((void*)p_lib_its_security_context->nonce, (const void*)p_nonce, p_lib_its_security_context->nonce_length); + p_lib_its_security_context->enc_sym_key = (uint8_t*)malloc(p_lib_its_security_context->sym_key_length); + memcpy((void*)p_lib_its_security_context->enc_sym_key, (const void*)p_enc_sym_key, p_lib_its_security_context->sym_key_length); + p_lib_its_security_context->tag = (uint8_t*)malloc(p_lib_its_security_context->tag_length); + memcpy((void*)p_lib_its_security_context->tag, (const void*)p_authentication_vector, p_lib_its_security_context->tag_length); + + /* Convert the ephemeral key to an EC point */ + EC_POINT *ec_point = NULL; + bin_to_ec_point(p_ephemeral_keys, p_ephemeral_keys->public_key_x, p_ephemeral_keys->public_key_y, &ec_point); // EC_POINT from ephemeral keys + // Generate the shared secret key (Key Agreement) + p_lib_its_security_context->secret_key_length = (EC_GROUP_get_degree(p_lib_its_security_context->ec_group) + 7) / 8; + p_lib_its_security_context->secret_key = (uint8_t*)malloc(p_lib_its_security_context->secret_key_length); + int32_t result = ECDH_compute_key( + p_lib_its_security_context->secret_key, + p_lib_its_security_context->secret_key_length, + ec_point, // From ephemeral keys + p_lib_its_security_context->ec_key, // From recipient's private key + NULL); + if (result != p_lib_its_security_context->secret_key_length) { + free(p_lib_its_security_context->secret_key); + p_lib_its_security_context->secret_key = NULL; + EC_POINT_free(ec_point); + return -1; + } + EC_POINT_free(ec_point); + show_hex((const int8_t*)"secret", p_lib_its_security_context->secret_key, p_lib_its_security_context->secret_key_length); + + /* Derive the shared secret key */ + uint8_t* digest; + size_t digest_length; + if (kdf2(p_lib_its_security_context, p_salt, p_salt_length, k_enc + k_mac, 0x00/*sha256*/, &digest, &digest_length) != 0) { + free(p_lib_its_security_context->secret_key); + p_lib_its_security_context->secret_key = NULL; + return -1; + } + show_hex((const int8_t*)"digest", digest, digest_length); + + /* Extract K2 and generate Tag vector */ + int32_t k2_length = k_enc * 2; + uint8_t* k2 = (uint8_t*)malloc(k2_length); + memcpy((void*)k2, (const void*)(k_enc + digest), k2_length); + show_hex((const int8_t*)"k2", k2, k2_length); + hmac_sha256(p_lib_its_security_context->enc_sym_key, p_lib_its_security_context->sym_key_length, k2, k2_length, &p_lib_its_security_context->tag); + show_hex((const int8_t*)"authentication vector", p_lib_its_security_context->tag, p_lib_its_security_context->tag_length); + + /* Extract K1 and generate encrypted symmetric key */ + uint8_t* k1 = (uint8_t*)malloc(k_enc); + memcpy((void*)k1, (const void*)digest, k_enc); + show_hex((const int8_t*)"k1", k1, k_enc); + p_lib_its_security_context->sym_key = (uint8_t*)malloc(k_enc); + for (unsigned int i = 0; i < k_enc; *(p_lib_its_security_context->sym_key + i) = *(k1 + i) ^ *(p_lib_its_security_context->enc_sym_key + i), i++); + show_hex((const int8_t*)"sym_key", p_lib_its_security_context->sym_key, p_lib_its_security_context->sym_key_length); + free(k1); + free(k2); + free(digest); + + return 0; +} + +int32_t decrypt( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_cipher_message, + const size_t p_cipher_message_length, + uint8_t**p_plain_text_message, + size_t* p_plain_text_message_length + ) { + /* Sanity checks */ + + /* Initialize the context and decryption operation */ + EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); + switch (p_lib_its_security_context->encryption_algorithm) { + case aes_128_ccm: + EVP_DecryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL); + break; + case aes_256_ccm: + EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL); + break; + case aes_128_gcm: + EVP_DecryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL); + break; + case aes_256_gcm: + EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + break; + } // End of 'switch' statement + /* Set nonce length */ + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, p_lib_its_security_context->nonce_length, NULL); + /* Set expected tag value */ + EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, p_lib_its_security_context->tag_length, p_lib_its_security_context->tag); + /* Specify key and IV */ + EVP_DecryptInit_ex(ctx, NULL, NULL, p_lib_its_security_context->sym_key, p_lib_its_security_context->nonce); + /* Decrypt plaintext, verify tag: can only be called once */ + *p_plain_text_message = (uint8_t*)malloc(p_cipher_message_length); + *p_plain_text_message_length = p_cipher_message_length; + int len = 0; + int result = EVP_DecryptUpdate(ctx, *p_plain_text_message, &len, p_cipher_message, p_cipher_message_length); + EVP_CIPHER_CTX_free(ctx); + if (result != 1) { + free(*p_plain_text_message); + *p_plain_text_message = NULL; + } + + return (result > 0) ? 0 : -1; +} + +/** + * Public functions + */ + +int32_t initialize( + const ecc_elliptic_curves_t p_elliptic_curve, + lib_its_security_context_t** p_lib_its_security_context + ) { + // Sanity checks + if (p_lib_its_security_context == NULL) { + return -1; + } + + OpenSSL_add_all_algorithms(); + ERR_load_crypto_strings(); + ERR_clear_error(); + + *p_lib_its_security_context = (lib_its_security_context_t*)malloc(sizeof(lib_its_security_context_t)); + if (*p_lib_its_security_context == NULL) { + return -1; + } + (*p_lib_its_security_context)->elliptic_curve = p_elliptic_curve; + (*p_lib_its_security_context)->ec_key = NULL; + (*p_lib_its_security_context)->ec_group = NULL; + (*p_lib_its_security_context)->bn_ctx = NULL; + (*p_lib_its_security_context)->key_length = -1; + (*p_lib_its_security_context)->private_key = NULL; + (*p_lib_its_security_context)->public_key_x = NULL; + (*p_lib_its_security_context)->public_key_y = NULL; + (*p_lib_its_security_context)->public_key_c = NULL; + (*p_lib_its_security_context)->secret_key = NULL; + (*p_lib_its_security_context)->sym_key = NULL; + (*p_lib_its_security_context)->enc_sym_key = NULL; + (*p_lib_its_security_context)->tag = NULL; + (*p_lib_its_security_context)->nonce = NULL; + (*p_lib_its_security_context)->secret_key_length = -1; + (*p_lib_its_security_context)->sym_key_length = -1; + (*p_lib_its_security_context)->nonce_length = -1; + (*p_lib_its_security_context)->tag_length = -1; + + int32_t result = -1; + switch (p_elliptic_curve) { + case nist_p_256: // Use the ANSI X9.62 Prime 256v1 curve + (*p_lib_its_security_context)->key_length = 32; + result = OBJ_txt2nid("prime256v1"); + break; + case brainpool_p_256_r1: + (*p_lib_its_security_context)->key_length = 32; + result = OBJ_txt2nid("brainpoolP256r1"); + break; + case brainpool_p_384_r1: + (*p_lib_its_security_context)->key_length = 48; + result = OBJ_txt2nid("brainpoolP384r1"); + break; + default: + fprintf(stderr, "lib_its_security::initialize: Unsupported EC elliptic_curve\n"); + } // End of 'switch' statement + if (result < 0) { + return -1; + } + + (*p_lib_its_security_context)->ec_key = EC_KEY_new_by_curve_name(result); /* Set the elliptic curve */ + EC_KEY_set_asn1_flag((*p_lib_its_security_context)->ec_key, OPENSSL_EC_NAMED_CURVE); /* Used to save and retrieve keys */ + (*p_lib_its_security_context)->ec_group = (EC_GROUP*)EC_KEY_get0_group((*p_lib_its_security_context)->ec_key); /* Get pointer to the EC_GROUP */ + (*p_lib_its_security_context)->bn_ctx = BN_CTX_new(); + + return 0; +} + +int32_t initialize_with_private_key( + const ecc_elliptic_curves_t p_elliptic_curve, + const uint8_t* p_private_key, + lib_its_security_context_t** p_lib_its_security_context + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_private_key == NULL)) { + return -1; + } + + if (initialize(p_elliptic_curve, p_lib_its_security_context) == -1) { + return -1; + } + EC_KEY_set_conv_form((*p_lib_its_security_context)->ec_key, POINT_CONVERSION_UNCOMPRESSED); + + // Build private key + BIGNUM* p = BN_new(); + BN_bin2bn(p_private_key, (*p_lib_its_security_context)->key_length, p); + // Build public keys + EC_POINT* ec_point = EC_POINT_new((*p_lib_its_security_context)->ec_group); + EC_POINT_mul((*p_lib_its_security_context)->ec_group, ec_point, p, NULL, NULL, (*p_lib_its_security_context)->bn_ctx); + // Set private key + EC_KEY_set_private_key((*p_lib_its_security_context)->ec_key, p); + if (EC_KEY_check_key((*p_lib_its_security_context)->ec_key) != 0) { + EC_POINT_free(ec_point); + BN_clear_free(p); + return -1; + } + BN_clear_free(p); + // Private key is correct, set public keys + EC_KEY_set_public_key((*p_lib_its_security_context)->ec_key, ec_point); + BIGNUM* xy = BN_new(); + EC_POINT_point2bn((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, xy, (*p_lib_its_security_context)->bn_ctx); + if (BN_num_bytes(xy) == 0) { + EC_POINT_free(ec_point); + BN_clear_free(xy); + return -1; + } + + int32_t v_length = BN_num_bytes(xy); + uint8_t* vv = (uint8_t*)malloc(v_length); + BN_bn2bin(xy, vv); + if ((v_length % 2) != 0) { + // Remove first byte + // v_length -= 1; + // memcpy((void*)vv, (const void*)(vv + 1), v_length - 1); + uint8_t *v = (uint8_t*)malloc(v_length - 1); + memcpy((void*)v, (const void*)(vv + 1), v_length - 1); + free(vv); + vv = v; + v_length -= 1; + } + BN_clear_free(xy); + const int l = v_length / 2; + (*p_lib_its_security_context)->public_key_x = (uint8_t*)malloc(l); + memcpy((void*)(*p_lib_its_security_context)->public_key_x, (const void*)vv, l); + (*p_lib_its_security_context)->public_key_y = (uint8_t*)malloc(l); + memcpy((void*)(*p_lib_its_security_context)->public_key_y, (const void*)(vv + l), l); + // Compressed + int len = EC_POINT_point2oct((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, NULL, 0, (*p_lib_its_security_context)->bn_ctx); + if (len != 0) { + (*p_lib_its_security_context)->public_key_c = (uint8_t*)malloc(len); + if (EC_POINT_point2oct((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (*p_lib_its_security_context)->public_key_c, len, (*p_lib_its_security_context)->bn_ctx) != 0) { + (*p_lib_its_security_context)->compressed_mode = ((*vv & 0x01) == 0x00) ? compressed_y_0 : compressed_y_1; + memmove((void*)(*p_lib_its_security_context)->public_key_c, (const void*)(1 + (*p_lib_its_security_context)->public_key_c), len - 1); + } + } + free(vv); + EC_POINT_free(ec_point); + + (*p_lib_its_security_context)->private_key = (uint8_t*)malloc((*p_lib_its_security_context)->key_length); + memcpy((void*)(*p_lib_its_security_context)->private_key, (const void*)p_private_key, (*p_lib_its_security_context)->key_length); + + return 0; +} + +int32_t initialize_with_public_key( + const ecc_elliptic_curves_t p_elliptic_curve, + const uint8_t* p_public_key, + const ecc_compressed_mode_t p_compressed_mode, + lib_its_security_context_t** p_lib_its_security_context + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_public_key == NULL)) { + return -1; + } + + if (initialize(p_elliptic_curve, p_lib_its_security_context) == -1) { + return -1; + } + EC_KEY_set_conv_form((*p_lib_its_security_context)->ec_key, POINT_CONVERSION_UNCOMPRESSED); + + // Set public key + BIGNUM* compressed_key = BN_new(); + BN_bin2bn(p_public_key, (*p_lib_its_security_context)->key_length, compressed_key); + EC_POINT* ec_point = EC_POINT_new((*p_lib_its_security_context)->ec_group); + int32_t result = 0; + switch (p_elliptic_curve) { + case nist_p_256: // Use primary + // No break; + case brainpool_p_256_r1: + // No break; + case brainpool_p_384_r1: + result = EC_POINT_set_compressed_coordinates_GFp((*p_lib_its_security_context)->ec_group, ec_point, compressed_key, (p_compressed_mode == compressed_y_1) ? 1 : 0, (*p_lib_its_security_context)->bn_ctx); // Use primary elliptic curve + break; + default: // Use Binary + result = EC_POINT_set_compressed_coordinates_GF2m((*p_lib_its_security_context)->ec_group, ec_point, compressed_key, (p_compressed_mode == compressed_y_1) ? 1 : 0, (*p_lib_its_security_context)->bn_ctx); + } // End of 'switch' statement + BN_clear_free(compressed_key); + + if (result == 0) { + EC_POINT_free(ec_point); + return -1; + } else if (EC_POINT_is_on_curve((*p_lib_its_security_context)->ec_group, ec_point, (*p_lib_its_security_context)->bn_ctx) == 0) { + EC_POINT_free(ec_point); + return -1; + } + + // Set public keys + BIGNUM* xy = BN_new(); + EC_POINT_point2bn((*p_lib_its_security_context)->ec_group, ec_point, POINT_CONVERSION_UNCOMPRESSED, xy, (*p_lib_its_security_context)->bn_ctx); + if (BN_num_bytes(xy) == 0) { + EC_POINT_free(ec_point); + BN_clear_free(xy); + return -1; + } + EC_KEY_set_public_key((*p_lib_its_security_context)->ec_key, ec_point); + // Generate X, Y coordinates + int32_t v_length = BN_num_bytes(xy); + uint8_t* vv = (uint8_t*)malloc(v_length); + BN_bn2bin(xy, vv); + BN_clear_free(xy); + if ((v_length % 2) != 0) { // TODO Check alse xy[0] == 0x04 + // Remove first byte + // v_length -= 1; + // memcpy((void*)vv, (const void*)(vv + 1), v_length - 1); + uint8_t *v = (uint8_t*)malloc(v_length - 1); + memcpy((void*)v, (const void*)(vv + 1), v_length - 1); + free(vv); + vv = v; + v_length -= 1; + } + const int l = v_length / 2; + (*p_lib_its_security_context)->public_key_x = (uint8_t*)malloc(l); + memcpy((void*)(*p_lib_its_security_context)->public_key_x, (const void*)vv, l); + (*p_lib_its_security_context)->public_key_y = (uint8_t*)malloc(l); + memcpy((void*)(*p_lib_its_security_context)->public_key_y, (const void*)(vv + l), l); + (*p_lib_its_security_context)->public_key_c = (uint8_t*)malloc(l); + memcpy((void*)(*p_lib_its_security_context)->public_key_c, (const void*)p_public_key, (*p_lib_its_security_context)->key_length); + (*p_lib_its_security_context)->compressed_mode = p_compressed_mode; + free(vv); + EC_POINT_free(ec_point); + + return 0; +} + +int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (*p_lib_its_security_context == NULL)) { + return -1; + } + + if ((*p_lib_its_security_context)->private_key != NULL) free((*p_lib_its_security_context)->private_key); + if ((*p_lib_its_security_context)->public_key_x != NULL) free((*p_lib_its_security_context)->public_key_x); + if ((*p_lib_its_security_context)->public_key_y != NULL) free((*p_lib_its_security_context)->public_key_y); + if ((*p_lib_its_security_context)->public_key_c != NULL) free((*p_lib_its_security_context)->public_key_c); + if ((*p_lib_its_security_context)->secret_key != NULL) free((*p_lib_its_security_context)->secret_key); + if ((*p_lib_its_security_context)->sym_key != NULL) free((*p_lib_its_security_context)->sym_key); + if ((*p_lib_its_security_context)->enc_sym_key != NULL) free((*p_lib_its_security_context)->enc_sym_key); + if ((*p_lib_its_security_context)->tag != NULL) free((*p_lib_its_security_context)->tag); + if ((*p_lib_its_security_context)->nonce != NULL) free((*p_lib_its_security_context)->nonce); + + if ((*p_lib_its_security_context)->ec_key != NULL) { + EC_KEY_free((*p_lib_its_security_context)->ec_key); + } + // Not required to free ec_group, it was a reference in ec_key + if ((*p_lib_its_security_context)->bn_ctx != NULL) { + BN_CTX_free((*p_lib_its_security_context)->bn_ctx); + } + + free(*p_lib_its_security_context); + *p_lib_its_security_context = NULL; + + return 0; +} + +int32_t hash_with_sha256( + const uint8_t* p_to_be_hashed_data, + const size_t p_to_be_hashed_data_length, + uint8_t** p_hashed_data + ) { + static uint8_t sha256_empty_string[] = { 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55 }; //! SHA-256 of an empty string + + // Sanity checks + if (p_hashed_data == NULL) { + return -1; + } + + *p_hashed_data = (uint8_t*)malloc(32); + if ((p_to_be_hashed_data == NULL) || (p_to_be_hashed_data_length == 0)) { + // SHA-256 of an empty value + memcpy((void*)*p_hashed_data, (const void*)sha256_empty_string, 32); + } else { + SHA256_CTX ctx; + SHA256_Init(&ctx); + SHA256_Update(&ctx, p_to_be_hashed_data, p_to_be_hashed_data_length); + SHA256_Final(*p_hashed_data, &ctx); + } + + return 0; +} + +int32_t hash_with_sha384( + const uint8_t* p_to_be_hashed_data, + const size_t p_to_be_hashed_data_length, + uint8_t** p_hashed_data + ) { + static unsigned char sha384_empty_string[] = { 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b }; //! SHA-384 of an empty string + + // Sanity checks + if (p_hashed_data == NULL) { + return -1; + } + + *p_hashed_data = (uint8_t*)malloc(48); + if ((p_to_be_hashed_data == NULL) || (p_to_be_hashed_data_length == 0)) { + // SHA-256 of an empty value + memcpy((void*)*p_hashed_data, (const void*)sha384_empty_string, 48); + } else { + SHA512_CTX ctx; + SHA384_Init(&ctx); + SHA384_Update(&ctx, p_to_be_hashed_data, p_to_be_hashed_data_length); + SHA384_Final(*p_hashed_data, &ctx); + } + + return 0; +} + +int32_t hmac_sha256( + const uint8_t* p_secret_key, + const size_t p_secret_key_length, + const uint8_t* p_message, + const size_t p_message_length, + uint8_t** p_hmac + ) { + /* Sanity checks */ + if ((p_secret_key == NULL) || (p_secret_key_length == 0) || (p_message == NULL) || (p_message_length == 0) || (p_hmac == NULL)) { + return -1; + } + + uint32_t length = 64; + uint8_t* hmac = (uint8_t*)malloc(length); + HMAC_CTX *ctx = HMAC_CTX_new(); + HMAC_Init_ex(ctx, (const void*)p_secret_key, (long unsigned int)p_secret_key_length, EVP_sha256(), NULL); + /* Compute the hash value */ + HMAC_Update(ctx, p_message, p_message_length); + HMAC_Final(ctx, hmac, &length); + HMAC_CTX_free(ctx); + /* Resize the hmac */ + *p_hmac = (uint8_t*)malloc(16); + memcpy((void*)*p_hmac, (const void*)hmac, 16); + free(hmac); + + return 0; +} + +int32_t prepare_data_to_be_verify( + const 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_certificate_issuer, uint8_t** p_hashed_data + ) { + // Calculate the SHA of the hashed data for signing: Hash ( Hash (Data input) || Hash (Signer identifier input) ) + uint8_t* hashed_data1; // Hash (Data input) + int32_t result; + if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { + result = hash_with_sha384(p_data, p_data_length, &hashed_data1); + } else { + result = hash_with_sha256(p_data, p_data_length, &hashed_data1); + } + if (result == -1) { + return -1; + } + uint8_t* hashed_data2; // Hash (Signer identifier input) + bool found = true; + for (int i = 0; i < 32; i++) { + if (*(p_certificate_issuer + i) != 0x00) { + found = false; + break; + } + } + if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { + if (!found) { + result = hash_with_sha384(p_certificate_issuer, p_lib_its_security_context->key_length, &hashed_data2); // Hash of empty string + } else { + result = hash_with_sha384(NULL, 0, &hashed_data2); // Hash of empty string + } + } else { + if (!found) { + result = hash_with_sha256(p_certificate_issuer, p_lib_its_security_context->key_length, &hashed_data2); // Hash of empty string + } else { + result = hash_with_sha256(NULL, 0, &hashed_data2); // Hash of empty string + } + } + if (result == -1) { + free(hashed_data1); + return -1; + } + uint8_t* hash_data_buffer = (uint8_t*)malloc(2 * p_lib_its_security_context->key_length); // Hash (Data input) || Hash (Signer identifier input) + memcpy((void*)hash_data_buffer, (const void*)hashed_data1, p_lib_its_security_context->key_length); + memcpy((void*)(hash_data_buffer + p_lib_its_security_context->key_length), (const void*)hashed_data2, p_lib_its_security_context->key_length); + if (p_lib_its_security_context->elliptic_curve == brainpool_p_384_r1) { + result = hash_with_sha384(hash_data_buffer, 2 * p_lib_its_security_context->key_length, p_hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + } else { + result = hash_with_sha256(hash_data_buffer, 2 * p_lib_its_security_context->key_length, p_hashed_data); // Hash ( Hash (Data input) || Hash (Signer identifier input) ) + } + free(hashed_data1); + free(hashed_data2); + free(hash_data_buffer); + + return 0; +} + +int32_t generic_signature( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ) { + uint8_t* hashed_data; + if (prepare_data_to_be_verify(p_lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, &hashed_data) == -1) { + return -1; + } + + // Calculate the signature + uint8_t* r_sig; + uint8_t* s_sig; + size_t sig_length; + if (sign(p_lib_its_security_context, hashed_data, p_lib_its_security_context->key_length, &r_sig, &s_sig, &sig_length) == -1) { + free(hashed_data); + return -1; + } + free(hashed_data); + // Copy the signature + *p_signature = (uint8_t*)malloc(2 * p_lib_its_security_context->key_length); // r_sig || s_sig + memcpy((void*)*p_signature, (const void*)r_sig, p_lib_its_security_context->key_length); + memcpy((void*)(*p_signature + p_lib_its_security_context->key_length), (const void*)s_sig, p_lib_its_security_context->key_length); + + free(r_sig); + free(s_sig); + + return 0; +} + +int32_t generic_verify( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsa_nistp256_publicKey_compressed, + const ecc_compressed_mode_t p_compressed_mode + ) { + uint8_t* hashed_data; + if (prepare_data_to_be_verify(p_lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, &hashed_data) == -1) { + return -1; + } + + uint8_t* sig_r = (uint8_t*)malloc(p_lib_its_security_context->key_length); + memcpy((void*)sig_r, (const void*)p_signature, p_lib_its_security_context->key_length); + uint8_t* sig_s = (uint8_t*)malloc(p_lib_its_security_context->key_length); + memcpy((void*)sig_s, (const void*)(p_signature + p_lib_its_security_context->key_length), p_lib_its_security_context->key_length); + if (sign_verify(p_lib_its_security_context, hashed_data, p_lib_its_security_context->key_length, sig_r, sig_s, p_lib_its_security_context->key_length) == -1) { + free(sig_r); + free(sig_s); + free(hashed_data); + return -1; + } + free(sig_r); + free(sig_s); + free(hashed_data); + + return 0; +} + +int32_t sign_with_ecdsa_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_private_key(nist_p_256, p_private_key, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_private_key(brainpool_p_256_r1, p_private_key, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_signed_secured_message == NULL) || (p_private_key == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_private_key(brainpool_p_384_r1, p_private_key, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_signature(lib_its_security_context, p_to_be_signed_secured_message, p_to_be_signed_secured_message_length, p_certificate_issuer, p_private_key, p_signature); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t verify_with_ecdsa_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsa_nistp256_publicKey_compressed, + const ecc_compressed_mode_t p_compressed_mode + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsa_nistp256_publicKey_compressed == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_public_key(nist_p_256, p_ecdsa_nistp256_publicKey_compressed, p_compressed_mode, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsa_nistp256_publicKey_compressed, p_compressed_mode); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t verify_with_ecdsa_nistp256_with_sha256_raw( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_signature, + const uint8_t* p_ecdsa_nistp256_publicKey_compressed, + const ecc_compressed_mode_t p_compressed_mode + ) { return -1; } + +int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsaBrainpoolp256PublicKeyCompressed, + const ecc_compressed_mode_t p_compressed_mode + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsaBrainpoolp256PublicKeyCompressed == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_public_key(brainpool_p_256_r1, p_ecdsaBrainpoolp256PublicKeyCompressed, p_compressed_mode, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsaBrainpoolp256PublicKeyCompressed, p_compressed_mode); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsaBrainpoolp384PublicKeyCompressed, + const ecc_compressed_mode_t p_compressed_mode + ) { + // Sanity checks + if ((p_lib_its_security_context == NULL) || (p_to_be_verified_data == NULL) || (p_signature == NULL) || (p_ecdsaBrainpoolp384PublicKeyCompressed == NULL)) { + return -1; + } + + lib_its_security_context_t* lib_its_security_context; + if (initialize_with_public_key(brainpool_p_384_r1, p_ecdsaBrainpoolp384PublicKeyCompressed, p_compressed_mode, &lib_its_security_context) == -1){ + return -1; + } + + int32_t result = generic_verify(lib_its_security_context, p_to_be_verified_data, p_to_be_verified_data_length, p_certificate_issuer, p_signature, p_ecdsaBrainpoolp384PublicKeyCompressed, p_compressed_mode); + uninitialize(&lib_its_security_context); + + return result; +} + +int32_t encrypt_with_ecies_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_encrypted_secured_message, + const size_t p_to_be_encrypted_secured_message_length, + const uint8_t* p_recipients_public_key_compressed, + const ecc_compressed_mode_t p_compressed_mode, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_public_ephemeral_key_compressed, + ecc_compressed_mode_t* p_ephemeral_compressed_mode, + uint8_t** p_aes_sym_key, + uint8_t** p_encrypted_sym_key, + uint8_t** p_authentication_vector, + uint8_t** p_nonce, + uint8_t** p_encrypted_secured_message, + size_t* p_encrypted_secured_message_length + ) { + /* Sanity checks */ + + lib_its_security_context_t* lib_its_security_context = NULL; + lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ + + /* 1. Generate new Private/Public Ephemeral key */ + int32_t result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + goto end; + } + result = generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode); + if (result == -1) { + goto end; + } + + /* 2. Generate and derive shared secret based on recipient's public keys */ + result = initialize_with_public_key(nist_p_256, p_recipients_public_key_compressed, p_compressed_mode, &lib_its_security_context_comp); + if (result == -1) { + goto end; + } + result = generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, p_salt, p_salt_length); + if (result == -1) { + goto end; + } + /* Set the AES symmetric key */ + *p_aes_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_aes_sym_key, (const void*)lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); + /* Set the encrypted symmetric key */ + *p_encrypted_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_encrypted_sym_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); + /* Set the tag of the symmetric key encryption */ + *p_authentication_vector = (uint8_t*)malloc(lib_its_security_context->tag_length); + memcpy((void*)*p_authentication_vector, (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); + /* Set ephemeral public keys */ + *p_public_ephemeral_key_compressed = (uint8_t*)malloc(lib_its_security_context->key_length); + memcpy((void*)*p_public_ephemeral_key_compressed, (const void*)lib_its_security_context->public_key_c, lib_its_security_context->key_length); + *p_ephemeral_compressed_mode = (ecc_compressed_mode_t)(lib_its_security_context->compressed_mode == compressed_y_0) ? 0 : 1; + + /* 3. Retrieve AES 128 parameters */ + *p_nonce = (uint8_t*)malloc(lib_its_security_context->nonce_length); + memcpy((void*)*p_nonce, (const void*)lib_its_security_context->nonce, lib_its_security_context->nonce_length); + /* 4. Encrypt the data using AES-128 CCM */ + lib_its_security_context->encryption_algorithm = aes_128_ccm; + result = encrypt(lib_its_security_context, p_to_be_encrypted_secured_message, p_to_be_encrypted_secured_message_length, p_encrypted_secured_message, p_encrypted_secured_message_length); + if (result == -1) { + // FXIME free all allocated resources + free(*p_aes_sym_key); *p_aes_sym_key = NULL; + free(*p_encrypted_sym_key); *p_encrypted_sym_key = NULL; + free(*p_authentication_vector); *p_authentication_vector = NULL; + free(*p_public_ephemeral_key_compressed); *p_public_ephemeral_key_compressed = NULL; + free(*p_nonce); *p_nonce = NULL; + goto end; + } + show_hex((const int8_t*)"Raw encrypted message", *p_encrypted_secured_message, *p_encrypted_secured_message_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + *p_encrypted_secured_message = (uint8_t*)realloc((void*)*p_encrypted_secured_message, *p_encrypted_secured_message_length + lib_its_security_context->tag_length); + memcpy((void*)(*p_encrypted_secured_message + *p_encrypted_secured_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); + *p_encrypted_secured_message_length += lib_its_security_context->tag_length; + + result = 0; + end: + if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); + if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); + + return result; +} + +int32_t decrypt_with_ecies_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_encrypted_secured_message, + const size_t p_encrypted_secured_message_length, + const uint8_t* p_private_enc_key, + const uint8_t* p_public_ephemeral_key_compressed, + const ecc_compressed_mode_t p_ephemeral_compressed_mode, + const uint8_t* p_encrypted_sym_key, + const uint8_t* p_authentication_vector, + const uint8_t* p_nonce, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_aes_sym_enc_key, + uint8_t** p_plain_text_message, + size_t* p_plain_text_message_length + ) { + /* Sanity checks */ + + lib_its_security_context_t* lib_its_security_context = NULL; + lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ + size_t enc_message_length = 0; + uint8_t* enc_message = NULL; + + /* 1. Initialize security context based on recipient's private key */ + int32_t result = initialize_with_private_key(nist_p_256, p_private_enc_key, &lib_its_security_context); + if (result == -1) { + goto end; + } + + /* 2. Generate the shared secret value based on public ephemeral keys will be required */ + result = initialize_with_public_key(nist_p_256, p_public_ephemeral_key_compressed, p_ephemeral_compressed_mode, &lib_its_security_context_comp); + if (result == -1) { + goto end; + } + result = generate_and_derive_ephemeral_key_for_decryption(lib_its_security_context, aes_128_ccm, lib_its_security_context_comp, p_encrypted_sym_key, p_nonce, p_authentication_vector, p_salt, p_salt_length); + if (result == -1) { + goto end; + } + *p_aes_sym_enc_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_aes_sym_enc_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); + /* Decrypt the message */ + enc_message_length = p_encrypted_secured_message_length - lib_its_security_context->tag_length; + enc_message = (uint8_t*)malloc(enc_message_length); + memcpy((void*)enc_message, (const void*)p_encrypted_secured_message, enc_message_length); // Extract the encrypted message + memcpy((void*)lib_its_security_context->tag, (const void*)(p_encrypted_secured_message + enc_message_length), lib_its_security_context->tag_length); + show_hex((const int8_t*)"Raw encrypted message", enc_message, enc_message_length); + show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); + show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + result = decrypt(lib_its_security_context, enc_message, enc_message_length, p_plain_text_message, p_plain_text_message_length); + if (result == -1) { + free(enc_message); + *p_plain_text_message = NULL; + *p_plain_text_message_length = -1; + goto end; + } + free(enc_message); + + end: + if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); + if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); + + return result; +} + +int32_t encrypt_with_ecies_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_encrypted_secured_message, + const size_t p_to_be_encrypted_secured_message_length, + const uint8_t* p_recipients_public_key_compressed, + const ecc_compressed_mode_t p_compressed_mode, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_public_ephemeral_key_compressed, + ecc_compressed_mode_t* p_ephemeral_compressed_mode, + uint8_t** p_aes_sym_key, + uint8_t** p_encrypted_sym_key, + uint8_t** p_authentication_vector, + uint8_t** p_nonce, + uint8_t** p_encrypted_secured_message, + size_t* p_encrypted_secured_message_length + ) { + /* Sanity checks */ + + lib_its_security_context_t* lib_its_security_context = NULL; + lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ + + /* 1. Generate new Private/Public Ephemeral key */ + int32_t result = initialize(brainpool_p_256_r1, &lib_its_security_context); + if (result == -1) { + goto end; + } + result = generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode); + if (result == -1) { + goto end; + } + + /* 2. Generate and derive shared secret based on recipient's public keys */ + result = initialize_with_public_key(brainpool_p_256_r1, p_recipients_public_key_compressed, p_compressed_mode, &lib_its_security_context_comp); + if (result == -1) { + goto end; + } + result = generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, p_salt, p_salt_length); + if (result == -1) { + goto end; + } + /* Set the AES symmetric key */ + *p_aes_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_aes_sym_key, (const void*)lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); + /* Set the encrypted symmetric key */ + *p_encrypted_sym_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_encrypted_sym_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); + /* Set the tag of the symmetric key encryption */ + *p_authentication_vector = (uint8_t*)malloc(lib_its_security_context->tag_length); + memcpy((void*)*p_authentication_vector, (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); + /* Set ephemeral public keys */ + *p_public_ephemeral_key_compressed = (uint8_t*)malloc(lib_its_security_context->key_length); + memcpy((void*)*p_public_ephemeral_key_compressed, (const void*)lib_its_security_context->public_key_c, lib_its_security_context->key_length); + *p_ephemeral_compressed_mode = (ecc_compressed_mode_t)(lib_its_security_context->compressed_mode == compressed_y_0) ? 0 : 1; + + /* 3. Retrieve AES 128 parameters */ + *p_nonce = (uint8_t*)malloc(lib_its_security_context->nonce_length); + memcpy((void*)*p_nonce, (const void*)lib_its_security_context->nonce, lib_its_security_context->nonce_length); + /* 4. Encrypt the data using AES-128 CCM */ + lib_its_security_context->encryption_algorithm = aes_128_ccm; + result = encrypt(lib_its_security_context, p_to_be_encrypted_secured_message, p_to_be_encrypted_secured_message_length, p_encrypted_secured_message, p_encrypted_secured_message_length); + if (result == -1) { + // FXIME free all allocated resources + free(*p_aes_sym_key); *p_aes_sym_key = NULL; + free(*p_encrypted_sym_key); *p_encrypted_sym_key = NULL; + free(*p_authentication_vector); *p_authentication_vector = NULL; + free(*p_public_ephemeral_key_compressed); *p_public_ephemeral_key_compressed = NULL; + free(*p_nonce); *p_nonce = NULL; + goto end; + } + show_hex((const int8_t*)"Raw encrypted message", *p_encrypted_secured_message, *p_encrypted_secured_message_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + *p_encrypted_secured_message = (uint8_t*)realloc((void*)*p_encrypted_secured_message, *p_encrypted_secured_message_length + lib_its_security_context->tag_length); + memcpy((void*)(*p_encrypted_secured_message + *p_encrypted_secured_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); + *p_encrypted_secured_message_length += lib_its_security_context->tag_length; + + result = 0; + end: + if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); + if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); + + return result; +} + +int32_t decrypt_with_ecies_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_encrypted_secured_message, + const size_t p_encrypted_secured_message_length, + const uint8_t* p_private_enc_key, + const uint8_t* p_public_ephemeral_key_compressed, + const ecc_compressed_mode_t p_ephemeral_compressed_mode, + const uint8_t* p_encrypted_sym_key, + const uint8_t* p_authentication_vector, + const uint8_t* p_nonce, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_aes_sym_enc_key, + uint8_t** p_plain_text_message, + size_t* p_plain_text_message_length + ) { + /* Sanity checks */ + + lib_its_security_context_t* lib_its_security_context = NULL; + lib_its_security_context_t* lib_its_security_context_comp = NULL; /* Convert compressed key into XY-coordinates key */ + size_t enc_message_length = 0; + uint8_t* enc_message = NULL; + + /* 1. Initialize security context based on recipient's private key */ + int32_t result = initialize_with_private_key(brainpool_p_256_r1, p_private_enc_key, &lib_its_security_context); + if (result == -1) { + goto end; + } + + /* 2. Generate the shared secret value based on public ephemeral keys will be required */ + result = initialize_with_public_key(brainpool_p_256_r1, p_public_ephemeral_key_compressed, p_ephemeral_compressed_mode, &lib_its_security_context_comp); + if (result == -1) { + goto end; + } + result = generate_and_derive_ephemeral_key_for_decryption(lib_its_security_context, aes_128_ccm, lib_its_security_context_comp, p_encrypted_sym_key, p_nonce, p_authentication_vector, p_salt, p_salt_length); + if (result == -1) { + goto end; + } + *p_aes_sym_enc_key = (uint8_t*)malloc(lib_its_security_context->sym_key_length); + memcpy((void*)*p_aes_sym_enc_key, (const void*)lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); + /* Decrypt the message */ + enc_message_length = p_encrypted_secured_message_length - lib_its_security_context->tag_length; + enc_message = (uint8_t*)malloc(enc_message_length); + memcpy((void*)enc_message, (const void*)p_encrypted_secured_message, enc_message_length); // Extract the encrypted message + memcpy((void*)lib_its_security_context->tag, (const void*)(p_encrypted_secured_message + enc_message_length), lib_its_security_context->tag_length); + show_hex((const int8_t*)"Raw encrypted message", enc_message, enc_message_length); + show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); + show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + result = decrypt(lib_its_security_context, enc_message, enc_message_length, p_plain_text_message, p_plain_text_message_length); + if (result == -1) { + free(enc_message); + *p_plain_text_message = NULL; + *p_plain_text_message_length = -1; + goto end; + } + free(enc_message); + + end: + if (lib_its_security_context != NULL) uninitialize(&lib_its_security_context); + if (lib_its_security_context_comp != NULL) uninitialize(&lib_its_security_context_comp); + + return result; +} + +int32_t generate_key_pair(lib_its_security_context_t* p_lib_its_security_context, uint8_t** p_private_key, uint8_t** p_public_key_x, uint8_t** p_public_key_y, uint8_t** p_public_key_compressed, ecc_compressed_mode_t* p_compressed_mode) { + /* Sanity checks */ + if ((p_lib_its_security_context == NULL) || (p_private_key == NULL) || (p_public_key_x == NULL) || (p_public_key_y == NULL) || (p_public_key_compressed == NULL) || (p_compressed_mode == NULL)) { + return -1; + } + + if (!EC_KEY_generate_key(p_lib_its_security_context->ec_key)) { /* Generate the private and public keys */ + fprintf(stderr, "generate_key_pair: Failed to generate private/public keys\n"); + return -1; + } + + BIGNUM* x = BN_new(); + BIGNUM* y = BN_new(); + const EC_POINT* ec_point = EC_KEY_get0_public_key(p_lib_its_security_context->ec_key); + int32_t result = 0; + size_t size = 0; + switch (p_lib_its_security_context->elliptic_curve) { + case nist_p_256: // Use primary + // No break; + case brainpool_p_256_r1: + size = 32; + result = EC_POINT_get_affine_coordinates_GFp(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); /* Use primer on elliptic curve */ + break; + case brainpool_p_384_r1: + size = 48; + result = EC_POINT_get_affine_coordinates_GFp(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); /* Use primer on elliptic curve */ + break; + default: // Use binary + result = EC_POINT_get_affine_coordinates_GF2m(p_lib_its_security_context->ec_group, ec_point, x, y, p_lib_its_security_context->bn_ctx); + } // End of 'switch' statement + if (result == 0) { + fprintf(stderr, "generate_key_pair: Failed to get coordinates\n"); + BN_clear_free(x); + BN_clear_free(y); + return -1; + } + + const BIGNUM* p = EC_KEY_get0_private_key(p_lib_its_security_context->ec_key); + *p_private_key = (uint8_t*)malloc(size); + BN_bn2bin(p, (unsigned char*)*p_private_key); + *p_public_key_x = (uint8_t*)malloc(size); + BN_bn2bin(x, (unsigned char*)*p_public_key_x); + *p_public_key_y = (uint8_t*)malloc(size); + BN_bn2bin(y, (unsigned char*)*p_public_key_y); + BN_clear_free(x); x = NULL; + BN_clear_free(y); y = NULL; + + // Compressed + int len = EC_POINT_point2oct(p_lib_its_security_context->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, NULL, 0, p_lib_its_security_context->bn_ctx); + if (len == 0) { + fprintf(stderr, "generate_key_pair: Failed to generate x_coordinate compressed key\n"); + } + *p_public_key_compressed = (uint8_t*)malloc(len); + if (EC_POINT_point2oct(p_lib_its_security_context->ec_group, ec_point, POINT_CONVERSION_COMPRESSED, (unsigned char*)*p_public_key_compressed, len, p_lib_its_security_context->bn_ctx) == 0) { + fprintf(stderr, "generate_key_pair: Failed to generate x_coordinate compressed key\n"); + memset((void*)*p_public_key_compressed, 0x00, len); + } else { /* Remove first byte */ + *p_compressed_mode = (ecc_compressed_mode_t)(((*p_public_key_compressed)[0] & 0x01) == 0x00) ? compressed_y_0 : compressed_y_1; + memmove((void*)*p_public_key_compressed, (const void*)(*p_public_key_compressed + 1), len - 1); + } + + return 0; +} + +#if defined(__MAIN__) + +static const uint8_t* test_string = (const uint8_t*)"cafedeca"; + +static lib_its_security_context_t* lib_its_security_context = NULL; +static lib_its_security_context_t* lib_its_security_context_comp = NULL; + +int main(int argc, char** argv) { + int32_t result; + + printf("###########################################################################\n"); + /* Test initialize */ + assert(lib_its_security_context == NULL); + assert(initialize(nist_p_256, NULL) == -1); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + } + assert(lib_its_security_context != NULL); + assert(lib_its_security_context->elliptic_curve == nist_p_256); + assert(lib_its_security_context->ec_key != NULL); + + /* Test hash_with_sha256 */ + { + uint8_t* hashed_data = NULL; + uint8_t* data_to_be_hashed = NULL; + result = hash_with_sha256(data_to_be_hashed, 10, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); + } else { + assert(hashed_data != NULL); + assert(hashed_data[0] == 0xe3); + assert(hashed_data[31] == 0x55); + } + free(hashed_data); hashed_data = NULL; + size_t l; + data_to_be_hashed = hex_to_bin((const int8_t*)test_string, &l); + result = hash_with_sha256(data_to_be_hashed, 0, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); + } else { + assert(hashed_data != NULL); + assert(hashed_data[0] == 0xe3); + assert(hashed_data[31] == 0x55); + } + free(hashed_data); hashed_data = NULL; + result = hash_with_sha256(data_to_be_hashed, l, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha256 failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"sha256", hashed_data, 32); + assert(hashed_data != NULL); + assert(hashed_data[0] == 0x84); + assert(hashed_data[31] == 0xfb); + } + free(data_to_be_hashed); + free(hashed_data); + } + + /* Test hash_with_sha384 */ + { + uint8_t* hashed_data = NULL; + uint8_t* data_to_be_hashed = NULL; + result = hash_with_sha384(data_to_be_hashed, 10, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); + } else { + assert(hashed_data != NULL); + assert(hashed_data[0] == 0x38); + assert(hashed_data[47] == 0x5b); + } + free(hashed_data); hashed_data = NULL; + size_t l; + data_to_be_hashed = hex_to_bin((const int8_t*)test_string, &l); + result = hash_with_sha384(data_to_be_hashed, 0, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); + } else { + assert(hashed_data != NULL); + assert(hashed_data[0] == 0x38); + assert(hashed_data[47] == 0x5b); + } + free(hashed_data); hashed_data = NULL; + result = hash_with_sha384(data_to_be_hashed, l, &hashed_data); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"sha384", hashed_data, 48); + assert(hashed_data != NULL); + assert(hashed_data[0] == 0x64); + assert(hashed_data[47] == 0x12); + } + free(data_to_be_hashed); + free(hashed_data); + } + + /* Test hmac_sha256 */ + { + uint8_t* hmac = NULL; + size_t secret_length; + uint8_t* secret = hex_to_bin((const int8_t*)"4a656665", &secret_length); + size_t message_length; + uint8_t* message = hex_to_bin((const int8_t*)"7768617420646f2079612077616e7420666f72206e6f7468696e673f", &message_length); + assert(hmac_sha256(secret, secret_length, message, message_length, NULL) == -1); + assert(hmac_sha256(NULL, secret_length, message, message_length, &hmac) == -1); + assert(hmac_sha256(secret, secret_length, NULL, message_length, &hmac) == -1); + assert(hmac_sha256(secret, 0, message, message_length, &hmac) == -1); + assert(hmac_sha256(secret, secret_length, message, 0, &hmac) == -1); + result = hmac_sha256(secret, secret_length, message, message_length, &hmac); + if (result == -1) { + fprintf(stderr, "main: hash_with_sha384 failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"hmac-sha256", hmac, 16); + assert(hmac[0] == 0x5b); + assert(hmac[15] == 0xc7); + free(hmac); + } + free(secret); + free(message); + } + + /* Test generate_key_pair */ + { + uint8_t* private_key; + uint8_t* public_key_x; + uint8_t* public_key_y; + uint8_t* public_key_compressed; + ecc_compressed_mode_t public_key_compressed_mode; + assert(generate_key_pair(NULL, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); + assert(generate_key_pair(lib_its_security_context, NULL, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); + assert(generate_key_pair(lib_its_security_context, &private_key, NULL, &public_key_y, &public_key_compressed, &public_key_compressed_mode) == -1); + assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, NULL, &public_key_compressed, &public_key_compressed_mode) == -1); + assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, NULL, &public_key_compressed_mode) == -1); + assert(generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, NULL) == -1); + result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); + if (result == -1) { + fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"private_key", private_key, 32); + free(private_key); + show_hex((const int8_t*)"public_key_x", public_key_x, 32); + free(public_key_x); + show_hex((const int8_t*)"public_key_y", public_key_y, 32); + free(public_key_y); + show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); + free(public_key_compressed); + printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); + } + } + + /* Test uninitialize */ + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + + printf("###########################################################################\n"); + /* Test basic signature */ + { + assert(lib_its_security_context == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + uint8_t* private_key; + uint8_t* public_key_x; + uint8_t* public_key_y; + uint8_t* public_key_compressed; + ecc_compressed_mode_t public_key_compressed_mode; + result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); + if (result == -1) { + fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"private_key", private_key, 32); + show_hex((const int8_t*)"public_key_x", public_key_x, 32); + show_hex((const int8_t*)"public_key_y", public_key_y, 32); + show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); + printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); + + uint8_t* sig_r; + uint8_t* sig_s; + size_t sig_length; + result = sign(lib_its_security_context, public_key_y, 32, &sig_r, &sig_s, &sig_length); + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } else { + show_hex((const int8_t*)"sig_r", sig_r, 32); + show_hex((const int8_t*)"sig_s", sig_s, 32); + printf("signature length=%ld\n", sig_length); + result = sign_verify(lib_its_security_context, public_key_y, 32, sig_r, sig_s, sig_length); + if (result == 0) { + printf("Signature was verified\n"); + } else { + printf("Signature was NOT verified\n"); + } + *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; + result = sign_verify(lib_its_security_context, public_key_y, 32, sig_r, sig_s, sig_length); + if (result == -1) { + printf("Signature was not verified successfully\n"); + } else { + printf("Signature SHALL NOT be verified\n"); + } + free(sig_r); + free(sig_s); + } + free(private_key); + free(public_key_x); + free(public_key_y); + free(public_key_compressed); + } + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test signature NistP-256 */ + printf("###########################################################################\n"); + { + assert(lib_its_security_context == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + uint8_t* private_key; + uint8_t* public_key_x; + uint8_t* public_key_y; + uint8_t* public_key_compressed; + ecc_compressed_mode_t public_key_compressed_mode; + result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); + if (result == -1) { + fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"private_key ", private_key, 32); + show_hex((const int8_t*)"public_key_x", public_key_x, 32); + show_hex((const int8_t*)"public_key_y", public_key_y, 32); + show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 32); + printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); + + uint8_t issuer[32] = { 0x00 }; + uint8_t* sig; + result = sign_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, private_key, &sig); + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } else { + show_hex((const int8_t*)"sig", sig, 64); + result = verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, sig, public_key_compressed, public_key_compressed_mode); + if (result == 0) { + printf("Signature was verified\n"); + } else { + printf("Signature was NOT verified\n"); + } + *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; + result = verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context, public_key_y, 32, issuer, sig, public_key_compressed, public_key_compressed_mode); + if (result == -1) { + printf("Signature was not verified successfully\n"); + } else { + printf("Signature SHALL NOT be verified\n"); + } + free(sig); + } + free(private_key); + free(public_key_x); + free(public_key_y); + free(public_key_compressed); + } + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test signature BrainpoolP-384r1 */ + printf("###########################################################################\n"); + printf("Test signature BrainpoolP-384r1\n"); + { + assert(lib_its_security_context == NULL); + result = initialize(brainpool_p_384_r1, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + uint8_t* private_key; + uint8_t* public_key_x; + uint8_t* public_key_y; + uint8_t* public_key_compressed; + ecc_compressed_mode_t public_key_compressed_mode; + result = generate_key_pair(lib_its_security_context, &private_key, &public_key_x, &public_key_y, &public_key_compressed, &public_key_compressed_mode); + if (result == -1) { + fprintf(stderr, "main: generate_key_pair failed: %d/'%s'\n", result, strerror(errno)); + } else { + show_hex((const int8_t*)"private_key", private_key, 48); + show_hex((const int8_t*)"public_key_x", public_key_x, 48); + show_hex((const int8_t*)"public_key_y", public_key_y, 48); + show_hex((const int8_t*)"public_key_compressed", public_key_compressed, 48); + printf("p_public_key_compressed_mode: %02x\n", public_key_compressed_mode); + + uint8_t issuer[32] = { 0x00 }; + uint8_t* sig; + result = sign_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, private_key, &sig); + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } else { + show_hex((const int8_t*)"sig", sig, 96); + result = verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, sig, public_key_compressed, public_key_compressed_mode); + if (result == 0) { + printf("Signature was verified\n"); + } else { + printf("Signature was NOT verified\n"); + } + *(public_key_y + 1) = 0xaa; *(public_key_y + 2) = 0xaa; + result = verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context, public_key_y, 48, issuer, sig, public_key_compressed, public_key_compressed_mode); + if (result == -1) { + printf("Signature was not verified successfully\n"); + } else { + printf("Signature SHALL NOT be verified\n"); + } + free(sig); + } + free(private_key); + free(public_key_x); + free(public_key_y); + free(public_key_compressed); + } + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test kdf_sha256 */ + printf("###########################################################################\n"); + printf("Test kdf_sha256 \n"); + { + assert(lib_its_security_context == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + // Test #1 + lib_its_security_context->secret_key = hex_to_bin((const int8_t*)"035DE77D62E51528ABE1403B25C8F0B8EFD47353EFD65E12F79A77122BF5137C", &lib_its_security_context->secret_key_length); + size_t salt_length; + uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); + size_t expected_digest_length; + uint8_t* expected_digest = hex_to_bin((const int8_t*)"3261BBDBA2301F163E1DEDF5038EDB146EDD08269AF295897089411FEA5372E073C3E330926D3828A7B88DF9CEA4ED65A4A5629424C490A869C1A54F91775EC0", &expected_digest_length); + uint8_t* digest; + size_t digest_length; + assert(kdf2(lib_its_security_context, salt, salt_length, 48, 0x00, &digest, &digest_length) == 0); + assert(expected_digest_length == digest_length); + for (int32_t i = 0; i < expected_digest_length; assert(digest[i] == expected_digest[i]), i++); + free(digest); + free(salt); + free(expected_digest); + free(lib_its_security_context->secret_key); lib_its_security_context->secret_key = NULL; + // Test #2 + lib_its_security_context->secret_key = hex_to_bin((const int8_t*)"8774F7739C1C7D33F1DD108527B8B5F532ED301C7AF9D2D750BA585B95AE6DDB", &lib_its_security_context->secret_key_length); + salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); + expected_digest = hex_to_bin((const int8_t*)"CEFD867314270E19795F9B8622D2E565B463CEA484A2E467BFAAD24AC3CC782BC62C55A95259CEA36ED1049E5454A7A272CDCE7A24B6140A740E4C4002B0A6F9", &expected_digest_length); + assert(kdf2(lib_its_security_context, salt, salt_length, 48, 0x00, &digest, &digest_length) == 0); + assert(expected_digest_length == digest_length); + for (int32_t i = 0; i < expected_digest_length; assert(digest[i] == expected_digest[i]), i++); + free(digest); + free(salt); + free(expected_digest); + free(lib_its_security_context->secret_key); lib_its_security_context->secret_key = NULL; + + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test encrypt function */ + printf("###########################################################################\n"); + printf("Test encrypt \n"); + { + assert(lib_its_security_context == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + // Test #1 + lib_its_security_context->nonce = hex_to_bin((const int8_t*)"8A395AA1C94062766027BFAC", &lib_its_security_context->nonce_length); + lib_its_security_context->sym_key = hex_to_bin((const int8_t*)"A3762D576B7A1DC2A2D8CF11B28A8BF8", &lib_its_security_context->sym_key_length); + size_t plain_text_message_length; + uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); + uint8_t* cipher_message; + size_t cipher_message_length; + lib_its_security_context->encryption_algorithm = aes_128_ccm; + assert(encrypt(lib_its_security_context, plain_text_message, plain_text_message_length, &cipher_message, &cipher_message_length) == 0); + printf("cipher_message_length= %ld\n", cipher_message_length); + show_hex((const int8_t*)"cipher_message", cipher_message, cipher_message_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + cipher_message = (uint8_t*)realloc((void*)cipher_message, cipher_message_length + lib_its_security_context->tag_length); + memcpy((void*)(cipher_message + cipher_message_length), (const void*)lib_its_security_context->tag, lib_its_security_context->tag_length); + cipher_message_length += lib_its_security_context->tag_length; + show_hex((const int8_t*)"cipher_message||tag", cipher_message, cipher_message_length); + size_t expected_cipher_message_length; + uint8_t* expected_cipher_message = hex_to_bin((const int8_t*)"cfea3fed73db25664feb046e0097fb57e541b12d74985965b175462893f32f9b373525b399367140542f44f94abb8b9df77b0d2bcce4709081d7d4ad781b8f28c86d8ee48e3b5427cf57ade2927701066d565073bbb31c2e54bf68da36296f9a23ab4c63a8ac26f92d0b99d28650120cb2d2dc0220a0bc56267736e3607c8a78094e167b65191a20cf9cdcb58d757756de32c75822de5687db6d7a65803137347a43da0db6de10dcfd3f045c3cc2198f29522cb72fc5296fdafa3b13151bb866078c5305b1a9ee08c34fb12b2c2c7bf06866f0d308e0721557d35448c37f126c96328acdc1298f316d6b0e94b2bb15228f5906809f56e39e2a5fba1d06b6222c3ff0234580288c09566c79d72342a2724033a55921dbabf3ec01ee123976b171e3c549", &expected_cipher_message_length); + assert(expected_cipher_message_length == cipher_message_length); + for (int32_t i = 0; i < expected_cipher_message_length; assert(*(expected_cipher_message + i) == *(cipher_message + i)), i++); + free(plain_text_message); + free(expected_cipher_message); + free(cipher_message); + + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test decrypt function */ + printf("###########################################################################\n"); + printf("Test decrypt \n"); + { + assert(lib_its_security_context == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + // Test #1 + lib_its_security_context->nonce = hex_to_bin((const int8_t*)"8A395AA1C94062766027BFAC", &lib_its_security_context->nonce_length); + lib_its_security_context->sym_key = hex_to_bin((const int8_t*)"A3762D576B7A1DC2A2D8CF11B28A8BF8", &lib_its_security_context->sym_key_length); + lib_its_security_context->tag = hex_to_bin((const int8_t*)"5921DBABF3EC01EE123976B171E3C549", &lib_its_security_context->tag_length); + size_t cipher_message_length; + uint8_t* cipher_message = hex_to_bin((const int8_t*)"cfea3fed73db25664feb046e0097fb57e541b12d74985965b175462893f32f9b373525b399367140542f44f94abb8b9df77b0d2bcce4709081d7d4ad781b8f28c86d8ee48e3b5427cf57ade2927701066d565073bbb31c2e54bf68da36296f9a23ab4c63a8ac26f92d0b99d28650120cb2d2dc0220a0bc56267736e3607c8a78094e167b65191a20cf9cdcb58d757756de32c75822de5687db6d7a65803137347a43da0db6de10dcfd3f045c3cc2198f29522cb72fc5296fdafa3b13151bb866078c5305b1a9ee08c34fb12b2c2c7bf06866f0d308e0721557d35448c37f126c96328acdc1298f316d6b0e94b2bb15228f5906809f56e39e2a5fba1d06b6222c3ff0234580288c09566c79d72342a2724033a5", &cipher_message_length); + uint8_t* plain_text_message; + size_t plain_text_message_length; + lib_its_security_context->encryption_algorithm = aes_128_ccm; + assert(decrypt(lib_its_security_context, cipher_message, cipher_message_length, &plain_text_message, &plain_text_message_length) == 0); + printf("plain_text_message_length= %ld\n", plain_text_message_length); + show_hex((const int8_t*)"plain_text_message", plain_text_message, plain_text_message_length); + size_t expected_plain_text_message_length; + uint8_t* expected_plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &expected_plain_text_message_length); + assert(expected_plain_text_message_length == cipher_message_length); + for (int32_t i = 0; i < expected_plain_text_message_length; assert(*(expected_plain_text_message + i) == *(plain_text_message + i)), i++); + free(cipher_message); + free(plain_text_message); + free(expected_plain_text_message); + + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test generate_and_derive_ephemeral_key_for_encryption */ + printf("###########################################################################\n"); + printf("Test generate_and_derive_ephemeral_key_for_encryption \n"); + { + assert(lib_its_security_context == NULL); + assert(lib_its_security_context_comp == NULL); + size_t l; + uint8_t* private_key = hex_to_bin((const int8_t*)"65322BEE2CFC665FBBAC6C0DC42EE73422278DFB7563A6350F7087013E216ACA", &l); + assert(l == 32); + result = initialize_with_private_key(nist_p_256, private_key, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + free(private_key); + + // Test #1 + size_t recipients_public_key_length; + uint8_t* recipients_public_key = hex_to_bin((const int8_t*)"E169F42FB028801B6DB717F5E7A37A7FBB17CB95A811BF224588F6F256FE8DDC", &recipients_public_key_length); + assert(recipients_public_key_length == 32); + assert(initialize_with_public_key(nist_p_256, recipients_public_key, compressed_y_0, &lib_its_security_context_comp) == 0); + assert(lib_its_security_context_comp->ec_key != NULL); + assert(lib_its_security_context_comp->ec_group != NULL); + assert(lib_its_security_context_comp->key_length == 32); + size_t salt_length; + uint8_t* salt = hex_to_bin((const int8_t*)"89BAB7DEA15BDAF3FF0357D952760A25735DD9816941BF6562C042D452D16EBA", &salt_length); + assert(generate_and_derive_ephemeral_key_for_encryption(lib_its_security_context/*Ephemeral's private key*/, aes_128_ccm, lib_its_security_context_comp/*recipient's public keys*/, salt, salt_length) == 0); + assert(lib_its_security_context->sym_key_length == 16); + assert(lib_its_security_context->tag_length == 16); + // Expected digest: 22cc5d042f654a9ce39e52fe232248a8d4793603b1ce4e98f67f2d634c24692573a2e89dbe9952e79b32faa0c94bf614b243fd84097d2eb50c4d6a4b996b7c12 + // Expected k1: 22cc5d042f654a9ce39e52fe232248a8 + // Expected k2: d4793603b1ce4e98f67f2d634c24692573a2e89dbe9952e79b32faa0c94bf614 + show_hex((const int8_t*)"nonce", lib_its_security_context->nonce, lib_its_security_context->nonce_length); + show_hex((const int8_t*)"tag", lib_its_security_context->tag, lib_its_security_context->tag_length); + show_hex((const int8_t*)"sym_key", lib_its_security_context->sym_key, lib_its_security_context->sym_key_length); + show_hex((const int8_t*)"enc_sym_key", lib_its_security_context->enc_sym_key, lib_its_security_context->sym_key_length); + + free(recipients_public_key); + free(salt); + + uninitialize(&lib_its_security_context_comp); + lib_its_security_context_comp = NULL; + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test encrypt_with_ecies_nistp256_with_sha256 #1 */ + printf("###########################################################################\n"); + printf("Test xxcrypt_with_ecies_nistp256_with_sha256 #1 \n"); + { + printf("==> encrypt_with_ecies_nistp256_with_sha256 #1 \n"); + assert(lib_its_security_context == NULL); + assert(lib_its_security_context_comp == NULL); + result = initialize(nist_p_256, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + /* Generate recipient's key */ + assert(generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode) == 0); + /* Set parameters */ + size_t plain_text_message_length; + uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); + size_t salt_length; + uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); + /* Encrypt */ + uint8_t* ephemeral_key_compressed = NULL; + ecc_compressed_mode_t ephemeral_compressed_mode; + uint8_t* aes_sym_key = NULL; + uint8_t* encrypted_sym_key = NULL; + uint8_t* authentication_vector = NULL; + uint8_t* nonce = NULL; + uint8_t* encrypted_secured_message = NULL; + size_t encrypted_secured_message_length; + assert(encrypt_with_ecies_nistp256_with_sha256(lib_its_security_context/*recipient's public keys*/, plain_text_message, plain_text_message_length, lib_its_security_context->public_key_c, lib_its_security_context->compressed_mode, salt, salt_length, &ephemeral_key_compressed, &ephemeral_compressed_mode, &aes_sym_key, &encrypted_sym_key, &authentication_vector, &nonce, &encrypted_secured_message, &encrypted_secured_message_length) == 0); + show_hex((const int8_t*)"ephemeral_key_compressed", ephemeral_key_compressed, 32); + show_hex((const int8_t*)"encrypted_secured_message || tag", encrypted_secured_message, encrypted_secured_message_length); + /* Decrypt */ + printf("==> decrypt_with_ecies_nistp256_with_sha256 #1 \n"); + size_t new_plain_text_message_length; + uint8_t* new_plain_text_message = NULL; + uint8_t* new_aes_enc_sym_key = NULL; + assert(decrypt_with_ecies_nistp256_with_sha256(lib_its_security_context, encrypted_secured_message, encrypted_secured_message_length, lib_its_security_context->private_key, ephemeral_key_compressed, ephemeral_compressed_mode, encrypted_sym_key, authentication_vector, nonce, salt, salt_length, &new_aes_enc_sym_key, &new_plain_text_message, &new_plain_text_message_length) == 0); + show_hex((const int8_t*)"new_plain_text_message", new_plain_text_message, new_plain_text_message_length); + show_hex((const int8_t*)"new_aes_enc_sym_key", new_aes_enc_sym_key, 16); + /* TODO Verify result */ + assert(new_plain_text_message_length == plain_text_message_length); + for (int32_t i = 0; i < plain_text_message_length; assert(*(plain_text_message + i) == *(new_plain_text_message + i)), i++); + for (int32_t i = 0; i < 16; assert(*(encrypted_sym_key + i) == *(new_aes_enc_sym_key + i)), i++); + + free(new_plain_text_message); + free(new_aes_enc_sym_key); + free(plain_text_message); + free(salt); + free(aes_sym_key); + free(encrypted_sym_key); + free(authentication_vector); + free(nonce); + free(encrypted_secured_message); + free(ephemeral_key_compressed); + + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + /* Test encrypt_with_ecies_brainpoolp256r1_with_sha256 #1 */ + printf("###########################################################################\n"); + printf("Test xxcrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); + { + printf("==> encrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); + assert(lib_its_security_context == NULL); + assert(lib_its_security_context_comp == NULL); + result = initialize(brainpool_p_256_r1, &lib_its_security_context); + if (result == -1) { + fprintf(stderr, "main: initialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + /* Generate recipient's key */ + assert(generate_key_pair(lib_its_security_context, &lib_its_security_context->private_key, &lib_its_security_context->public_key_x, &lib_its_security_context->public_key_y, &lib_its_security_context->public_key_c, &lib_its_security_context->compressed_mode) == 0); + /* Set parameters */ + size_t plain_text_message_length; + uint8_t* plain_text_message = hex_to_bin((const int8_t*)"03810040038081BC01800381004003806400104553435259505400000000000000001101008082671439CBFB6E69370113B14E077A6097AACC62945C122D402A6975AF6FF3DAA77C8110455343525950540000000000000000111DCCE0F98400788301028000FA80017C00010180012481030201C04002026F0001C6B773D2F2B0828080217B7AA6442D85721A9DB6F0C2E307BEC1795B33E6957055F504F8F7A5DD1A956788F6A1146998DA44EC4756C8DB2AB46EBD1D3BAB6894FE8667594FAE2B24374002026F0001C6B773D33130828080AE1B9F9D16A35646C4C84CE4A4C3B50C84125356A74A94B009750941DC94A9DB6D91A2B75633AB573B3369C0DE7CCBD44EC08ABB268EA341FCBB53757E5B7589", &plain_text_message_length); + size_t salt_length; + uint8_t* salt = hex_to_bin((const int8_t*)"4739DA8E1723A178CCF278763454DAE55B67208F1D9DCB312BDA08D4402BDEAA", &salt_length); + /* Encrypt */ + uint8_t* ephemeral_key_compressed = NULL; + ecc_compressed_mode_t ephemeral_compressed_mode; + uint8_t* aes_sym_key = NULL; + uint8_t* encrypted_sym_key = NULL; + uint8_t* authentication_vector = NULL; + uint8_t* nonce = NULL; + uint8_t* encrypted_secured_message = NULL; + size_t encrypted_secured_message_length; + assert(encrypt_with_ecies_brainpoolp256r1_with_sha256(lib_its_security_context/*recipient's public keys*/, plain_text_message, plain_text_message_length, lib_its_security_context->public_key_c, lib_its_security_context->compressed_mode, salt, salt_length, &ephemeral_key_compressed, &ephemeral_compressed_mode, &aes_sym_key, &encrypted_sym_key, &authentication_vector, &nonce, &encrypted_secured_message, &encrypted_secured_message_length) == 0); + show_hex((const int8_t*)"ephemeral_key_compressed", ephemeral_key_compressed, 32); + show_hex((const int8_t*)"encrypted_secured_message || tag", encrypted_secured_message, encrypted_secured_message_length); + /* Decrypt */ + printf("==> decrypt_with_ecies_brainpoolp256r1_with_sha256 #1 \n"); + size_t new_plain_text_message_length; + uint8_t* new_plain_text_message = NULL; + uint8_t* new_aes_enc_sym_key = NULL; + assert(decrypt_with_ecies_brainpoolp256r1_with_sha256(lib_its_security_context, encrypted_secured_message, encrypted_secured_message_length, lib_its_security_context->private_key, ephemeral_key_compressed, ephemeral_compressed_mode, encrypted_sym_key, authentication_vector, nonce, salt, salt_length, &new_aes_enc_sym_key, &new_plain_text_message, &new_plain_text_message_length) == 0); + show_hex((const int8_t*)"new_plain_text_message", new_plain_text_message, new_plain_text_message_length); + show_hex((const int8_t*)"new_aes_enc_sym_key", new_aes_enc_sym_key, 16); + /* TODO Verify result */ + assert(new_plain_text_message_length == plain_text_message_length); + for (int32_t i = 0; i < plain_text_message_length; assert(*(plain_text_message + i) == *(new_plain_text_message + i)), i++); + for (int32_t i = 0; i < 16; assert(*(encrypted_sym_key + i) == *(new_aes_enc_sym_key + i)), i++); + + free(new_plain_text_message); + free(new_aes_enc_sym_key); + free(plain_text_message); + free(salt); + free(aes_sym_key); + free(encrypted_sym_key); + free(authentication_vector); + free(nonce); + free(encrypted_secured_message); + free(ephemeral_key_compressed); + + result = uninitialize(&lib_its_security_context); + lib_its_security_context = NULL; + if (result == -1) { + fprintf(stderr, "main: uninitialize failed: %d/'%s'\n", result, strerror(errno)); + return -1; + } + } + + return 0; +} + +#endif diff --git a/tools/itssecurity/lib_its_security/lib_its_security.h b/tools/itssecurity/lib_its_security/lib_its_security.h index 5eb2bd792..2258ca6a5 100644 --- a/tools/itssecurity/lib_its_security/lib_its_security.h +++ b/tools/itssecurity/lib_its_security/lib_its_security.h @@ -1,384 +1,404 @@ -/*! - * \File lib_its_security.h - * \brief Declaration 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 - */ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/*! - * \enum Supported Elliptic curves - */ -typedef enum ecc_elliptic_curves_ { - nist_p_256, /*!< NIST P-256, P-256, primve256v1 */ - brainpool_p_256_r1, /*!< Brainpool P256r1 */ - brainpool_p_384_r1 /*!< Brainpool P384r1 */ -} ecc_elliptic_curves_t; - -/*! - * \enum Public key coordinates compression mode - */ -typedef enum ecc_compressed_mode_ { - compressed_y_0, /*!< The last significant bit of Y-coodinate ended with 0 */ - compressed_y_1 /*!< The last significant bit of Y-coodinate ended with 1 */ -} ecc_compressed_mode_t; - -/*! - * \enum Supported encryption algorithem - */ -typedef enum ecc_encryption_algorithm_ { - aes_128_ccm, - aes_256_ccm, - aes_128_gcm, - aes_256_gcm -} encryption_algorithm_t; - -/*! - * \struct ITS security context to be used in functions - * \brief This data structure contains all the infomation required to achieve security computation such signature, ciphering... - */ -typedef struct lib_its_security_context_ { - ecc_elliptic_curves_t elliptic_curve; /*! The ellicptic curve to be used */ - EC_KEY* ec_key; /*!< EC_KEY reference */ - EC_GROUP* ec_group; /*!< EC_GROUP reference */ - BN_CTX* bn_ctx; /*!< Pre-alocated memory used to increase OpenSSL processing */ - size_t key_length; /*!< private/public keys length */ - uint8_t* private_key; /*!< Private key */ - uint8_t* public_key_x; /*!< Public key Y-coodinate */ - uint8_t* public_key_y; /*!< Public key Y-coodinate */ - uint8_t* public_key_c; /*!< Compressed Public key */ - ecc_compressed_mode_t compressed_mode; /*!< Compression mode */ - - encryption_algorithm_t encryption_algorithm; /* Encryption algorithm currently used */ - uint8_t* secret_key; - uint8_t* sym_key; - uint8_t* enc_sym_key; - uint8_t* tag; - uint8_t* nonce; - size_t secret_key_length; - size_t sym_key_length; - size_t nonce_length; - size_t tag_length; -} lib_its_security_context_t; - -/** - * \fn int32_t initialize(const ecc_elliptic_curves_t p_elliptic_curve, lib_its_security_context_t** p_lib_its_security_context); - * \brief Initialize the ITS security context according to the specified elliptic curve. This function shall be called before any othe lib_its_security function. - * \param[in] p_elliptic_curve The elliptic curve to be used - * \param[out] p_lib_its_security_context The internl context (To be released using uninitialize function) - * \return 0 on success,-1 otherwise - */ -int32_t initialize(const ecc_elliptic_curves_t p_elliptic_curve, lib_its_security_context_t** p_lib_its_security_context); - -/** - * \fn int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context); - * \brief Release resources allocated by initialize fiunction - * \param[in/out] p_lib_its_security_context The internl context - * \return 0 on success,-1 otherwise - */ -int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context); - -/** - * \fn int32_t hash_with_sha256(const uint8_t* p_to_be_hashed_data,const size_t p_to_be_hashed_data_length,uint8_t** p_hashed_data); - * \brief Produces a 256-bit (32-bytes) hash value - * \param[in] p_to_be_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_hashed_data_length The length of the data to be hashed - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \return 0 on success,-1 otherwise - */ -int32_t hash_with_sha256(const uint8_t* p_to_be_hashed_data, const size_t p_to_be_hashed_data_length, uint8_t** p_hashed_data); -/** - * \fn int32_t hash_with_sha384(const uint8_t* p_to_be_hashed_data,const size_t p_to_be_hashed_data_length,uint8_t** p_hashed_data); - * \brief Produces a 384-bit (48-bytes) hash value - * \param[in] p_to_be_hashed_data Data to be used to calculate the hash value - * \param[in] p_to_be_hashed_data_length The length of the data to be hashed - * \param[in] p_hashed_data The data to be used to calculate the hash value - * \return 0 on success,-1 otherwise - */ -int32_t hash_with_sha384(const uint8_t* p_to_be_hashed_data, const size_t p_to_be_hashed_data_length, uint8_t** p_hashed_data); - -/** - * \fn int32_t hmac_sha256(const uint8_t* p_secret_key,const size p_secret_key_length,const OCTETSTRING& p_message,const size p_message_length, uint8_t** p_hmac); - * \brief Generate a HMAC-SHA256 value based on the provided secret key - * \param[in] p_secret_key The secret key used for the HMAC calculation - * \param[in] p_message The message - * \param[out] p_hmac The HMAC with SHA256 of the message resized to 16-bytes (To be released after use) - * \return 0 on success,-1 otherwise - */ -int32_t hmac_sha256(const uint8_t* p_secret_key, const size_t p_secret_key_length, const uint8_t* p_message, const size_t p_message_length, uint8_t** p_hmac); - -/** - * \fn int32_t sign_with_ecdsa_nistp256_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_signed_secured_message The data to be signed - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_private_key The private key - * \param[out] p_signature The signature of the data to be signed (To be released after use) - * \return The signature value - */ -int32_t sign_with_ecdsa_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ); - -/** - * \fn int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_signed_secured_message The data to be signed - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_private_key The private key - * \param[out] p_signature The signature of the data to be signed (To be released after use) - * \return The signature value - */ -int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ); - -/** - * \fn int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); - * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_signed_secured_message The data to be signed - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_private_key The private key - * \param[out] p_signature The signature of the data to be signed (To be released after use) - * \return 0 on success,-1 otherwise - */ -int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_signed_secured_message, - const size_t p_to_be_signed_secured_message_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_private_key, - uint8_t** p_signature - ); - -/** - * \fn int32_t verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); - * \brief Verify the signature of the specified data based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_verified_data The data to be verified - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_signature The signature - * \param[in] p_ecdsa_nistp256_publicKey_compressed The compressed public key (x coordinate only) - * \return 0 on success,-1 otherwise - */ -int32_t verify_with_ecdsa_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsa_nistp256_publicKey_compressed, - const ecc_compressed_mode_t p_compressed_mode - ); - -/** - * \fn int32_t verify_with_ecdsa_nistp256_with_sha256_raw(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode)); - * \brief Verify the signature of the specified data based on raw data - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_verified_data The data to be verified - * \param[in] p_signature The signature - * \param[in] p_ecdsa_nistp256_publicKey_compressed The compressed public key (x coordinate only) - * \return 0 on success,-1 otherwise - */ -int32_t verify_with_ecdsa_nistp256_with_sha256_raw( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_signature, - const uint8_t* p_ecdsa_nistp256_publicKey_compressed, - const ecc_compressed_mode_t p_compressed_mode - ); - -/** - * \fn int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); - * \brief Verify the signature of the specified data based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_verified_data The data to be verified - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_signature The signature - * \param[in] p_ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only) - * \return 0 on success,-1 otherwise - */ -int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsaBrainpoolp256PublicKeyCompressed, - const ecc_compressed_mode_t p_compressed_mode - ); - -/** - * \fn int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); - * \brief Verify the signature of the specified data based on standard IEEE 1609.2 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_verified_data The data to be verified - * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate - * \param[in] p_signature The signature - * \param[in] p_ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) - * \return 0 on success,-1 otherwise - */ -int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_verified_data, - const size_t p_to_be_verified_data_length, - const uint8_t* p_certificate_issuer, - const uint8_t* p_signature, - const uint8_t* p_ecdsaBrainpoolp384PublicKeyCompressed, - const ecc_compressed_mode_t p_compressed_mode - ); - -/** - * \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key,as defined in IEEE Std 1609.2-2017 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_to_be_encrypted_secured_message The message to be encrypted - * \param[in] p_recipients_public_key_compressed The Recipient's compressed public key - * \param[in] p_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise - * \param[out] p_public_ephemeral_key_compressed The public ephemeral compressed key (To be released after use) - * \param[out] p_ephemeral_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise - * \param[out] p_encrypted_sym_key The encrypted AES 128 symmetric key (To be released after use) - * \param[out] p_authentication_vector The tag of the encrypted AES 128 symmetric key (To be released after use) - * \param[out] p_nonce The nonce vector (To be released after use) - uint8_t** p_encrypted_secured_message, - size_t* p_encrypted_secured_message_length, - * \return 0 on success,-1 otherwise - * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES - * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ - * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf - */ -int32_t encrypt_with_ecies_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_encrypted_secured_message, - const size_t p_to_be_encrypted_secured_message_length, - const uint8_t* p_recipients_public_key_compressed, - const ecc_compressed_mode_t p_compressed_mode, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_public_ephemeral_key_compressed, - ecc_compressed_mode_t* p_ephemeral_compressed_mode, - uint8_t** p_aes_sym_key, - uint8_t** p_encrypted_sym_key, - uint8_t** p_authentication_vector, - uint8_t** p_nonce, - uint8_t** p_encrypted_secured_message, - size_t* p_encrypted_secured_message_length - ); - -/** - * \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key,as defined in IEEE Std 1609.2-2017 - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[in] p_encrypted_secured_message The encrypted message - * \param[in] p_private_enc_key The private encryption key - * \param[in] p_public_ephemeral_key_compressed The public ephemeral compressed key - * \param[in] p_ephemeral_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise - * \param[in] p_encrypted_sym_key The encrypted AES 128 symmetric key - * \param[in] p_authentication_vector The tag of the encrypted AES 128 symmetric key - * \param[in] p_nonce The nonce vector - * \return 0 on success,-1 otherwise - * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES - * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ - * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf - */ -int32_t decrypt_with_ecies_nistp256_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_encrypted_secured_message, - const size_t p_encrypted_secured_message_length, - const uint8_t* p_private_enc_key, - const uint8_t* p_public_ephemeral_key_compressed, - const ecc_compressed_mode_t p_ephemeral_compressed_mode, - const uint8_t* p_encrypted_sym_key, - const uint8_t* p_authentication_vector, - const uint8_t* p_nonce, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_aes_sym_enc_key, - uint8_t** p_plain_text_message, - size_t* p_plain_text_message_length - ); - -int32_t encrypt_with_ecies_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_to_be_encrypted_secured_message, - const size_t p_to_be_encrypted_secured_message_length, - const uint8_t* p_recipients_public_key_compressed, - const ecc_compressed_mode_t p_compressed_mode, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_public_ephemeral_key_compressed, - ecc_compressed_mode_t* p_ephemeral_compressed_mode, - uint8_t** p_aes_sym_key, - uint8_t** p_encrypted_sym_key, - uint8_t** p_authentication_vector, - uint8_t** p_nonce, - uint8_t** p_encrypted_secured_message, - size_t* p_encrypted_secured_message_length - ); - -int32_t decrypt_with_ecies_brainpoolp256r1_with_sha256( - lib_its_security_context_t* p_lib_its_security_context, - const uint8_t* p_encrypted_secured_message, - const size_t p_encrypted_secured_message_length, - const uint8_t* p_private_enc_key, - const uint8_t* p_public_ephemeral_key_compressed, - const ecc_compressed_mode_t p_ephemeral_compressed_mode, - const uint8_t* p_encrypted_sym_key, - const uint8_t* p_authentication_vector, - const uint8_t* p_nonce, - const uint8_t* p_salt, - const size_t p_salt_length, - uint8_t** p_aes_sym_enc_key, - uint8_t** p_plain_text_message, - size_t* p_plain_text_message_length - ); - -/** - * \fn int32_t generate_key_pair(lib_its_security_context_t* p_lib_its_security_context, uint8_t** p_private_key,uint8_t** p_public_key_x,uint8_t** p_public_key_y,uint8_t** p_public_key_compressed, ecc_compressed_mode_t* p_compressed_mode); - * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. - * \param[in/out] p_hashed_data The data to be used to calculate the hash value - * \param[out] p_private_key The new private key value (To be released after use) - * \param[out] p_public_key_x The new public key value (x coordinate) (To be released after use) - * \param[out] p_public_key_x The new public key value (y coordinate) (To be released after use) - * \return 0 on success,-1 otherwise - */ -int32_t generate_key_pair( - lib_its_security_context_t* p_lib_its_security_context, - uint8_t** p_private_key, - uint8_t** p_public_key_x, - uint8_t** p_public_key_y, - uint8_t** p_public_key_compressed, - ecc_compressed_mode_t* p_compressed_mode - ); +/*! + * \File lib_its_security.h + * \brief Declaration 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 + */ +#pragma once + +#ifdef _Win64 +#ifdef LIBITSSECURITY_EXPORTS +#define LIBITSSECURITY_API __declspec(dllexport) +#else +#define LIBITSSECURITY_API __declspec(dllimport) +#endif +#else // _Win64 +#define LIBITSSECURITY_API +#endif // _Win64 + +#ifdef __cplusplus +extern "C" { +#endif // !__cplusplus + +#ifndef _Win64 +#include +#endif // !_Win32 +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/*! + * \enum Supported Elliptic curves + */ +typedef enum ecc_elliptic_curves_ { + nist_p_256, /*!< NIST P-256, P-256, primve256v1 */ + brainpool_p_256_r1, /*!< Brainpool P256r1 */ + brainpool_p_384_r1 /*!< Brainpool P384r1 */ +} ecc_elliptic_curves_t; + +/*! + * \enum Public key coordinates compression mode + */ +typedef enum ecc_compressed_mode_ { + compressed_y_0, /*!< The last significant bit of Y-coordinate ended with 0 */ + compressed_y_1 /*!< The last significant bit of Y-coordinate ended with 1 */ +} ecc_compressed_mode_t; + +/*! + * \enum Supported encryption algorithm + */ +typedef enum ecc_encryption_algorithm_ { + aes_128_ccm, + aes_256_ccm, + aes_128_gcm, + aes_256_gcm +} encryption_algorithm_t; + +/*! + * \struct ITS security context to be used in functions + * \brief This data structure contains all the infomation required to achieve security computation such signature, ciphering... + */ +typedef struct lib_its_security_context_ { + ecc_elliptic_curves_t elliptic_curve; /*! The ellicptic curve to be used */ + EC_KEY* ec_key; /*!< EC_KEY reference */ + EC_GROUP* ec_group; /*!< EC_GROUP reference */ + BN_CTX* bn_ctx; /*!< Pre-alocated memory used to increase OpenSSL processing */ + size_t key_length; /*!< private/public keys length */ + uint8_t* private_key; /*!< Private key */ + uint8_t* public_key_x; /*!< Public key Y-coordinate */ + uint8_t* public_key_y; /*!< Public key Y-coordinate */ + uint8_t* public_key_c; /*!< Compressed Public key */ + ecc_compressed_mode_t compressed_mode; /*!< Compression mode */ + + encryption_algorithm_t encryption_algorithm; /* Encryption algorithm currently used */ + uint8_t* secret_key; + uint8_t* sym_key; + uint8_t* enc_sym_key; + uint8_t* tag; + uint8_t* nonce; + size_t secret_key_length; + size_t sym_key_length; + size_t nonce_length; + size_t tag_length; +} lib_its_security_context_t; + +/** + * \fn int32_t initialize(const ecc_elliptic_curves_t p_elliptic_curve, lib_its_security_context_t** p_lib_its_security_context); + * \brief Initialize the ITS security context according to the specified elliptic curve. This function shall be called before any othe lib_its_security function. + * \param[in] p_elliptic_curve The elliptic curve to be used + * \param[out] p_lib_its_security_context The internal context (To be released using uninitialize function) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t initialize(const ecc_elliptic_curves_t p_elliptic_curve, lib_its_security_context_t** p_lib_its_security_context); + +/** + * \fn int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context); + * \brief Release resources allocated by initialize fiunction + * \param[in/out] p_lib_its_security_context The internal context + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t uninitialize(lib_its_security_context_t** p_lib_its_security_context); + +/** + * \fn int32_t hash_with_sha256(const uint8_t* p_to_be_hashed_data,const size_t p_to_be_hashed_data_length,uint8_t** p_hashed_data); + * \brief Produces a 256-bit (32-bytes) hash value + * \param[in] p_to_be_hashed_data The data to be used to calculate the hash value + * \param[in] p_to_be_hashed_data_length The length of the data to be hashed + * \param[in/out] p_hashed_data The data to be used to calculate the hash value + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t hash_with_sha256(const uint8_t* p_to_be_hashed_data, const size_t p_to_be_hashed_data_length, uint8_t** p_hashed_data); +/** + * \fn int32_t hash_with_sha384(const uint8_t* p_to_be_hashed_data,const size_t p_to_be_hashed_data_length,uint8_t** p_hashed_data); + * \brief Produces a 384-bit (48-bytes) hash value + * \param[in] p_to_be_hashed_data Data to be used to calculate the hash value + * \param[in] p_to_be_hashed_data_length The length of the data to be hashed + * \param[in] p_hashed_data The data to be used to calculate the hash value + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t hash_with_sha384(const uint8_t* p_to_be_hashed_data, const size_t p_to_be_hashed_data_length, uint8_t** p_hashed_data); + +/** + * \fn int32_t hmac_sha256(const uint8_t* p_secret_key,const size p_secret_key_length,const OCTETSTRING& p_message,const size p_message_length, uint8_t** p_hmac); + * \brief Generate a HMAC-SHA256 value based on the provided secret key + * \param[in] p_secret_key The secret key used for the HMAC calculation + * \param[in] p_message The message + * \param[out] p_hmac The HMAC with SHA256 of the message resized to 16-bytes (To be released after use) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t hmac_sha256(const uint8_t* p_secret_key, const size_t p_secret_key_length, const uint8_t* p_message, const size_t p_message_length, uint8_t** p_hmac); + +/** + * \fn int32_t sign_with_ecdsa_nistp256_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The security context + * \param[in] p_to_be_signed_secured_message The data to be signed + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_private_key The private key + * \param[out] p_signature The signature of the data to be signed (To be released after use) + * \return The signature value + */ +LIBITSSECURITY_API int32_t sign_with_ecdsa_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ); + +/** + * \fn int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_signed_secured_message The data to be signed + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_private_key The private key + * \param[out] p_signature The signature of the data to be signed (To be released after use) + * \return The signature value + */ +LIBITSSECURITY_API int32_t sign_with_ecdsa_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ); + +/** + * \fn int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_signed_secured_message,const size_t p_to_be_signed_secured_message_length,const uint8_t* p_certificate_issuer,const uint8_t* p_private_key,uint8_t** p_signature); + * \brief Produces a Elliptic Curve Digital Signature Algorithm (ECDSA) signature based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_signed_secured_message The data to be signed + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_private_key The private key + * \param[out] p_signature The signature of the data to be signed (To be released after use) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t sign_with_ecdsa_brainpoolp384r1_with_sha384( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_signed_secured_message, + const size_t p_to_be_signed_secured_message_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_private_key, + uint8_t** p_signature + ); + +/** + * \fn int32_t verify_with_ecdsa_nistp256_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); + * \brief Verify the signature of the specified data based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_verified_data The data to be verified + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_signature The signature + * \param[in] p_ecdsa_nistp256_publicKey_compressed The compressed public key (x coordinate only) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t verify_with_ecdsa_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsa_nistp256_publicKey_compressed, + const ecc_compressed_mode_t p_compressed_mode + ); + +/** + * \fn int32_t verify_with_ecdsa_nistp256_with_sha256_raw(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode)); + * \brief Verify the signature of the specified data based on raw data + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_verified_data The data to be verified + * \param[in] p_signature The signature + * \param[in] p_ecdsa_nistp256_publicKey_compressed The compressed public key (x coordinate only) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t verify_with_ecdsa_nistp256_with_sha256_raw( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_signature, + const uint8_t* p_ecdsa_nistp256_publicKey_compressed, + const ecc_compressed_mode_t p_compressed_mode + ); + +/** + * \fn int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); + * \brief Verify the signature of the specified data based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_verified_data The data to be verified + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_signature The signature + * \param[in] p_ecdsaBrainpoolp256PublicKeyCompressed The compressed public key (x coordinate only) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t verify_with_ecdsa_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsaBrainpoolp256PublicKeyCompressed, + const ecc_compressed_mode_t p_compressed_mode + ); + +/** + * \fn int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384(lib_its_security_context_t* p_lib_its_security_context, const uint8_t* p_to_be_verified_data,const size_t p_to_be_verified_data_length,const uint8_t* p_certificate_issuer,const uint8_t* p_signature,const uint8_t* p_ecdsa_nistp256_publicKey_compressed, const ecc_compressed_mode_t p_compressed_mode); + * \brief Verify the signature of the specified data based on standard IEEE 1609.2 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_verified_data The data to be verified + * \param[in] p_certificate_issuer The whole-hash issuer certificate or int2oct(0,32) in case of self signed certificate + * \param[in] p_signature The signature + * \param[in] p_ecdsaBrainpoolp384PublicKeyCompressed The compressed public key (x coordinate only) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t verify_with_ecdsa_brainpoolp384r1_with_sha384( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_verified_data, + const size_t p_to_be_verified_data_length, + const uint8_t* p_certificate_issuer, + const uint8_t* p_signature, + const uint8_t* p_ecdsaBrainpoolp384PublicKeyCompressed, + const ecc_compressed_mode_t p_compressed_mode + ); + +/** + * \brief Encrypt the message using ECIES algorithm to encrypt AES 128 CCM symmetric key,as defined in IEEE Std 1609.2-2017 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_to_be_encrypted_secured_message The message to be encrypted + * \param[in] p_recipients_public_key_compressed The Recipient's compressed public key + * \param[in] p_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise + * \param[out] p_public_ephemeral_key_compressed The public ephemeral compressed key (To be released after use) + * \param[out] p_ephemeral_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise + * \param[out] p_encrypted_sym_key The encrypted AES 128 symmetric key (To be released after use) + * \param[out] p_authentication_vector The tag of the encrypted AES 128 symmetric key (To be released after use) + * \param[out] p_nonce The nonce vector (To be released after use) + uint8_t** p_encrypted_secured_message, + size_t* p_encrypted_secured_message_length, + * \return 0 on success, -1 otherwise + * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES + * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ + * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ +LIBITSSECURITY_API int32_t encrypt_with_ecies_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_encrypted_secured_message, + const size_t p_to_be_encrypted_secured_message_length, + const uint8_t* p_recipients_public_key_compressed, + const ecc_compressed_mode_t p_compressed_mode, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_public_ephemeral_key_compressed, + ecc_compressed_mode_t* p_ephemeral_compressed_mode, + uint8_t** p_aes_sym_key, + uint8_t** p_encrypted_sym_key, + uint8_t** p_authentication_vector, + uint8_t** p_nonce, + uint8_t** p_encrypted_secured_message, + size_t* p_encrypted_secured_message_length + ); + +/** + * \brief Decrypt the message using ECIES algorithm to decrypt AES 128 CCM symmetric key,as defined in IEEE Std 1609.2-2017 + * \param[in/out] p_lib_its_security_context The internal context + * \param[in] p_encrypted_secured_message The encrypted message + * \param[in] p_private_enc_key The private encryption key + * \param[in] p_public_ephemeral_key_compressed The public ephemeral compressed key + * \param[in] p_ephemeral_compressed_mode The compressed mode,0 if the latest bit of Y-coordinate is 0,1 otherwise + * \param[in] p_encrypted_sym_key The encrypted AES 128 symmetric key + * \param[in] p_authentication_vector The tag of the encrypted AES 128 symmetric key + * \param[in] p_nonce The nonce vector + * \return 0 on success, -1 otherwise + * \see IEEE Std 1609.2-2017 Clause 5.3.5 Public key encryption algorithms: ECIES + * \see https://www.nominet.uk/researchblog/how-elliptic-curve-cryptography-encryption-works/ + * \see http://digital.csic.es/bitstream/10261/32671/1/V2-I2-P7-13.pdf + */ +LIBITSSECURITY_API int32_t decrypt_with_ecies_nistp256_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_encrypted_secured_message, + const size_t p_encrypted_secured_message_length, + const uint8_t* p_private_enc_key, + const uint8_t* p_public_ephemeral_key_compressed, + const ecc_compressed_mode_t p_ephemeral_compressed_mode, + const uint8_t* p_encrypted_sym_key, + const uint8_t* p_authentication_vector, + const uint8_t* p_nonce, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_aes_sym_enc_key, + uint8_t** p_plain_text_message, + size_t* p_plain_text_message_length + ); + +LIBITSSECURITY_API int32_t encrypt_with_ecies_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_to_be_encrypted_secured_message, + const size_t p_to_be_encrypted_secured_message_length, + const uint8_t* p_recipients_public_key_compressed, + const ecc_compressed_mode_t p_compressed_mode, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_public_ephemeral_key_compressed, + ecc_compressed_mode_t* p_ephemeral_compressed_mode, + uint8_t** p_aes_sym_key, + uint8_t** p_encrypted_sym_key, + uint8_t** p_authentication_vector, + uint8_t** p_nonce, + uint8_t** p_encrypted_secured_message, + size_t* p_encrypted_secured_message_length + ); + +LIBITSSECURITY_API int32_t decrypt_with_ecies_brainpoolp256r1_with_sha256( + lib_its_security_context_t* p_lib_its_security_context, + const uint8_t* p_encrypted_secured_message, + const size_t p_encrypted_secured_message_length, + const uint8_t* p_private_enc_key, + const uint8_t* p_public_ephemeral_key_compressed, + const ecc_compressed_mode_t p_ephemeral_compressed_mode, + const uint8_t* p_encrypted_sym_key, + const uint8_t* p_authentication_vector, + const uint8_t* p_nonce, + const uint8_t* p_salt, + const size_t p_salt_length, + uint8_t** p_aes_sym_enc_key, + uint8_t** p_plain_text_message, + size_t* p_plain_text_message_length + ); + +/** + * \fn int32_t generate_key_pair(lib_its_security_context_t* p_lib_its_security_context, uint8_t** p_private_key,uint8_t** p_public_key_x,uint8_t** p_public_key_y,uint8_t** p_public_key_compressed, ecc_compressed_mode_t* p_compressed_mode); + * \brief Produce a new public/private key pair based on Elliptic Curve Digital Signature Algorithm (ECDSA) algorithm. + * \param[in/out] p_lib_its_security_context The internal context + * \param[out] p_private_key The new private key value (To be released after use) + * \param[out] p_public_key_x The new public key value (x coordinate) (To be released after use) + * \param[out] p_public_key_x The new public key value (y coordinate) (To be released after use) + * \return 0 on success, -1 otherwise + */ +LIBITSSECURITY_API int32_t generate_key_pair( + lib_its_security_context_t* p_lib_its_security_context, + uint8_t** p_private_key, + uint8_t** p_public_key_x, + uint8_t** p_public_key_y, + uint8_t** p_public_key_compressed, + ecc_compressed_mode_t* p_compressed_mode + ); + +#ifdef __cplusplus +} +#endif // !__cplusplus diff --git a/tools/itssecurity/test/test_lib_its_security.cc b/tools/itssecurity/test/test_lib_its_security.cc old mode 100644 new mode 100755 index d13d5c2c5..ce079dc2b --- a/tools/itssecurity/test/test_lib_its_security.cc +++ b/tools/itssecurity/test/test_lib_its_security.cc @@ -1,24 +1,65 @@ -#ifdef _Win64 -#include "pch.h" -#else -#include -#endif +#include "gtest/gtest.h" extern "C" { #include "lib_its_security.h" -int8_t* bin_to_hex(const uint8_t* p_buffer, const size_t p_buffer_length); +#ifndef _Win64 uint8_t* hex_to_bin(const int8_t* p_buffer, size_t* p_buffer_length); +#endif +} + +#ifdef _Win64 +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; +} +#endif +#ifndef _Win64 /** * @class lib_its_security unit tests suite implementation */ class lib_its_security_test_suite : public ::testing::Test { protected: - virtual void SetUp() { }; - virtual void TearDown() { }; + virtual void SetUp() { }; + virtual void TearDown() { }; }; +#endif TEST(lib_its_security_test_suite, Init1) { EXPECT_TRUE(initialize(nist_p_256, NULL) == -1); @@ -1222,5 +1263,3 @@ int main(int argc, char **argv) { return RUN_ALL_TESTS(); } - - -- GitLab