/*! * \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