Log in

View Full Version : from openssl to libtomcrypt


_akmal_
16th October 2010, 05:25
hi everybody, i have some source code which uses openssl ecc functions, i want change this functions with libtomcrypt ecc functions but have confusion.

#ifndef AACS_NO_ECDSA
#include <cstring>

#include <openssl/bn.h>
#include <openssl/evp.h>
#include <openssl/obj_mac.h>
#include <openssl/err.h>


EC_KEY * aacs_key()
{
EC_GROUP * group;
EC_KEY * key = EC_KEY_new();

if (key == NULL)
{
return NULL;
}

group = aacs_group();

if (!EC_KEY_set_group(key, group))
{
EC_KEY_free(key);
EC_GROUP_free(group);
return NULL;

} else {

return key;
}
}

EC_GROUP *aacs_group()
{
EC_GROUP *group = NULL;
EC_POINT *P = NULL;
BN_CTX *ctx = NULL;
BIGNUM *p = NULL, *a = NULL, *b = NULL, *x = NULL, *y = NULL, *order = NULL;
int ok = 0;

const char data_p[] = "900812823637587646514106462588455890498729007071";
const char data_a[] = "-3";
const char data_b[] = "366394034647231750324370400222002566844354703832";
const char data_x[] = "264865613959729647018113670854605162895977008838";
const char data_y[] = "51841075954883162510413392745168936296187808697";
const char data_r[] = "900812823637587646514106555566573588779770753047";

if ((ctx = BN_CTX_new()) == NULL)
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
goto err;
}

if ((p = BN_new()) == NULL || (a = BN_new()) == NULL ||
(b = BN_new()) == NULL || (x = BN_new()) == NULL ||
(y = BN_new()) == NULL || (order = BN_new()) == NULL)
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_MALLOC_FAILURE);
goto err;
}

if (!BN_dec2bn(&p, data_p) || !BN_dec2bn(&a, data_a) || !BN_dec2bn(&b, data_b))
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
goto err;
}

if ((group = EC_GROUP_new_curve_GFp(p, a, b, ctx)) == NULL)
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
goto err;
}

if ((P = EC_POINT_new(group)) == NULL)
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
goto err;
}

if (!BN_dec2bn(&x, data_x) || !BN_dec2bn(&y, data_y))
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
goto err;
}

if (!EC_POINT_set_affine_coordinates_GF2m(group, P, x, y, ctx))
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
goto err;
}

if (!BN_dec2bn(&order, data_r) || !BN_set_word(x, 1))
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_BN_LIB);
goto err;
}

if (!EC_GROUP_set_generator(group, P, order, x))
{
ECerr(EC_F_EC_GROUP_NEW_FROM_DATA, ERR_R_EC_LIB);
goto err;
}

ok=1;

err:
if (!ok) {
EC_GROUP_free(group);
group = NULL;
}
if (P)
EC_POINT_free(P);
if (ctx)
BN_CTX_free(ctx);
if (p)
BN_free(p);
if (a)
BN_free(a);
if (b)
BN_free(b);
if (order)
BN_free(order);
if (x)
BN_free(x);
if (y)
BN_free(y);

return group;
}

int aacs_set_cert(/*out*/ EC_KEY *key, const unsigned char *cert)
{
EC_POINT * public_key = NULL;
BIGNUM * x = NULL;
BIGNUM * y = NULL;
const EC_GROUP * group = EC_KEY_get0_group(key);


if ((cert[1] != 0) || (cert[2] != 0x00) || (cert[3] != 0x5C))
{
return -1;
}

if ((x = BN_bin2bn(cert+12, 20, NULL)) == NULL)
{
return -2;
}

if ((y = BN_bin2bn(cert+32, 20, NULL)) == NULL)
{
BN_clear_free(x);
return -3;
}

if ((public_key = EC_POINT_new(group)) == NULL)
{
BN_clear_free(x);
BN_clear_free(y);
return -4;
}

if (!EC_POINT_set_affine_coordinates_GFp(group, public_key, x, y, NULL))
{
BN_clear_free(x);
BN_clear_free(y);
EC_POINT_free(public_key);
return -5;
}

BN_clear_free(x);
BN_clear_free(y);

int rv = EC_KEY_set_public_key(key, public_key);
EC_POINT_free(public_key);

return rv;
}

int aacs_verify(const unsigned char *cert, const unsigned char *signature, const unsigned char *nonce, const unsigned char *point)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
EVP_MD_CTX mdctx;
EC_KEY * key = NULL;
ECDSA_SIG *sig = NULL; // Can be freed before beeing intialized, initialize here
int ret = -1;

if ((key = aacs_key()) == NULL)
{
ret = -2;
goto err;
}

if (!aacs_set_cert(key, cert))
{
ret = -3;
goto err;
}

EVP_MD_CTX_init(&mdctx);

EVP_DigestInit(&mdctx, EVP_sha1());
EVP_DigestUpdate(&mdctx, nonce, 20);
EVP_DigestUpdate(&mdctx, point, 40);
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);

if ((sig = ECDSA_SIG_new()) == NULL || BN_bin2bn(signature, 20, sig->r) == NULL || BN_bin2bn(signature+20, 20, sig->s) == NULL)
{
ret = -4;
goto err;
}

ret = ECDSA_do_verify(md_value, md_len, sig, key);

err:
if (sig)
ECDSA_SIG_free(sig);

if (key)
EC_KEY_free(key);

return ret;
}


int aacs_sign(const unsigned char *cert, const unsigned char *priv_key, /*out*/ unsigned char *signature, const unsigned char *nonce, const unsigned char *point)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned int md_len;
EVP_MD_CTX mdctx;
EC_KEY *key = NULL;
ECDSA_SIG *sig = NULL;
BIGNUM *priv_key_bn = NULL;
int ret = -1;

//ECC key creating
if ((key = aacs_key()) == NULL)
{
ret = -2;
goto err;
}

//Set public key
if (!aacs_set_cert(key, cert))
{
ret = -3;
goto err;
}

//Set private key
if (((priv_key_bn = BN_bin2bn(priv_key, 20, NULL)) == NULL) || !EC_KEY_set_private_key(key, priv_key_bn))
{
ret = -4;
goto err;
}

EVP_MD_CTX_init(&mdctx);

EVP_DigestInit(&mdctx, EVP_ecdsa());
EVP_DigestUpdate(&mdctx, nonce, 20);
EVP_DigestUpdate(&mdctx, point, 40);
EVP_DigestFinal_ex(&mdctx, md_value, &md_len);




sig = ECDSA_do_sign(md_value, md_len, key);

if (BN_bn2bin(sig->r, signature) != 20) {
ret = -5;
goto err;
}

if (BN_bn2bin(sig->s, signature+20) != 20) {
ret = -6;
goto err;
}

if (sig)
ret = 1;

err:
if (sig)
ECDSA_SIG_free(sig);

if (key)
EC_KEY_free(key);

if (priv_key_bn)
BN_clear_free(priv_key_bn);

return ret;
}

int aacs_calculate_bus_key(const unsigned char *cert, const unsigned char *host_key, const unsigned char *drive_key_point_bin, /*out*/ unsigned char *bus_key) {

EC_KEY *key = NULL;
//BN_CTX *ctx = NULL;
BIGNUM *host_key_bn = NULL;
EC_POINT * drive_key_point_pnt = NULL;
EC_POINT * bus_key_point = NULL;
const EC_GROUP * group = NULL;
unsigned char bus_key_long[100];
BIGNUM * x = NULL;
BIGNUM * y = NULL;
BIGNUM * bus_key_point_bn = NULL;
int ret = -1;


if ((key = aacs_key()) == NULL) {
ret = -2;
goto err;
}

if (!aacs_set_cert(key, cert)) {
ret = -3;
goto err;
}

if((host_key_bn = BN_bin2bn(host_key, 20, NULL)) == NULL) {
ret = -4;
goto err;
}

group = EC_KEY_get0_group(key);
if (!group) {
ret = -6;
goto err;
}

if ((x = BN_bin2bn(drive_key_point_bin, 20, NULL)) == NULL) {
ret = -7;
goto err;
}

if ((y = BN_bin2bn(drive_key_point_bin+20, 20, NULL)) == NULL) {
ret = -8;
goto err;
}

if ((drive_key_point_pnt = EC_POINT_new(group)) == NULL) {
ret = -9;
goto err;
}

if (!EC_POINT_set_affine_coordinates_GFp(group, drive_key_point_pnt, x, y, NULL)) {
ret = -10;
goto err;
}

if (!drive_key_point_pnt) {
ret = -11;
goto err;
}

bus_key_point = EC_POINT_new(group);
if (!EC_POINT_mul(group, bus_key_point, NULL, drive_key_point_pnt, host_key_bn, NULL)) {
ret = -12;
goto err;
}

if ((bus_key_point_bn = EC_POINT_point2bn(group, bus_key_point, POINT_CONVERSION_UNCOMPRESSED, NULL, NULL)) == NULL) {
ret = -13;
goto err;
}

if (!BN_bn2bin(bus_key_point_bn, bus_key_long)) {
ret = -14;
goto err;
}

memcpy(bus_key, bus_key_long + 4 + 1, 16); // +1 due to uncompressed code 0x04

ret = 1;
err:
if (key)
EC_KEY_free(key);
if (host_key_bn)
BN_free(host_key_bn);
if (drive_key_point_pnt)
EC_POINT_free(drive_key_point_pnt);
if (bus_key_point)
EC_POINT_free(bus_key_point);
if (x)
BN_clear_free(x);
if (y)
BN_clear_free(y);
if (bus_key_point_bn)
BN_free(bus_key_point_bn);

return ret;
}

#endif

i take this source from aacskeys project, and want to implement aacs sign and verifications functions using libtomcrypt.

Here is my function which uses libtomcrypt functions, but i think i'm doing something wrong because of when i create signature using libtomcrypt function and verify using openssl function, verification fails. I hope somebody will help.
int aacs_sign_libCrypt(const unsigned char *cert, const unsigned char *priv_key, /*out*/ unsigned char *signature, const unsigned char *nonce, const unsigned char *point)
{
unsigned char md_value[EVP_MAX_MD_SIZE];
unsigned long md_len;

//create and init PRNG
prng_state yarrowPrng;
yarrow_start(&yarrowPrng);
yarrow_add_entropy((const unsigned char*)"akmal", 5, &yarrowPrng);
yarrow_ready(&yarrowPrng);

ecc_key key11;

//Set elliptic curve parameters
ltc_ecc_set_type curveParams;
curveParams.name = "aacs";
curveParams.B = "402DAD3EC1CBCD165248D68E1245E0C4DAACB1D8";
curveParams.Gx = "2E64FC22578351E6F4CCA7EB81D0A4BDC54CCEC6";
curveParams.Gy = "0914A25DD05442889DB455C7F23C9A0707F5CBB9";
curveParams.order = "9DC9D81355ECCEB560BDC44F54817B2C7F5AB017";
curveParams.prime = "9DC9D81355ECCEB560BDB09EF9EAE7C479A7D7DF";
curveParams.size = 16;


key11.dp = &curveParams;
key11.idx = -1;
key11.type = PK_PRIVATE;

//allocate memory
ltc_init_multi1(&key11.pubkey.x, &key11.pubkey.y, &key11.pubkey.z, &key11.k, NULL);

//set public key?
mp_read_radix((mp_int*)key11.pubkey.x, (char *)cert+12, 16);
mp_read_radix((mp_int*)key11.pubkey.y, (char *)cert+32, 16);
mp_set_int((mp_int*)key11.pubkey.z, 1);

//set private key?
mp_read_unsigned_bin((mp_int*)key11.k, (unsigned char *)priv_key, key11.dp->size);

//create digest
hash_state md;
sha1_init(&md);
sha1_process(&md, nonce, 20);
sha1_process(&md, point, 40);
sha1_done(&md, md_value);

//create signature
if(ecc_sign_hash1(md_value, SH1_HASH_SIZE, signature, &md_len, &yarrowPrng, 0, &key11) != CRYPT_OK)
{
printf("ECC sign failed!\n");
return -1;
}

yarrow_done(&yarrowPrng);

return 0;
}

P.S. sorry for my english.