Commit 2c994fad authored by Yann Garcia's avatar Yann Garcia
Browse files

Bug fixed in Native API

parent cb8cf8a4
......@@ -28,484 +28,487 @@
*/
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);
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);
fprintf(stderr, "%s: ", p_prefix);
char* result = EC_POINT_point2hex(p_lib_its_security_context->ec_group, p_ec_point, POINT_CONVERSION_UNCOMPRESSED, p_lib_its_security_context->bn_ctx);
if (result != NULL) {
fprintf(stderr, "%s\n", result);
#ifdef _Win64
free(result);
free(result);
#endif
} else {
fprintf(stderr, "(null)\n");
}
}
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);
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;
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;
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;
}
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;
}
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;
}
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));
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);
ECDSA_SIG_free(signature);
return 0;
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
) {
show_hex((const int8_t*)">>> sign_verify: p_data", p_data, p_data_length);
show_hex((const int8_t*)">>> sign_verify: p_sig_r", p_sig_r, p_sig_length);
show_hex((const int8_t*)">>> sign_verify: p_sig_s", p_sig_s, 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);
fprintf(stderr, "sign_verify: result=%d\n", result);
ECDSA_SIG_free(signature);
return (result == 1) ? 0 : -1;
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
) {
show_hex((const int8_t*)">>> sign_verify: p_data", p_data, p_data_length);
show_hex((const int8_t*)">>> sign_verify: p_sig_r", p_sig_r, p_sig_length);
show_hex((const int8_t*)">>> sign_verify: p_sig_s", p_sig_s, 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);
fprintf(stderr, "sign_verify: result=%d\n", result);
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;
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();
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);
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);
BN_clear_free(pub_bn);
return 0;
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;
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;
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;
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;