#include <libecc/sig/ec_key.h>
#include <libecc/sig/sig_algs.h>
#include <libecc/curves/curves.h>
int priv_key_check_initialized(const ec_priv_key *A)
{
int ret = 0;
MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) && (A->params != NULL)), ret, err);
err:
return ret;
}
int priv_key_check_initialized_and_type(const ec_priv_key *A,
ec_alg_type alg_type)
{
int ret = 0;
MUST_HAVE(((A != NULL) && (A->magic == PRIV_KEY_MAGIC) &&
(A->params != NULL) && (A->key_type == alg_type)), ret, err);
err:
return ret;
}
int ec_priv_key_import_from_buf(ec_priv_key *priv_key,
const ec_params *params,
const u8 *priv_key_buf, u8 priv_key_buf_len,
ec_alg_type ec_key_alg)
{
int ret;
MUST_HAVE((priv_key != NULL), ret, err);
ret = nn_init_from_buf(&(priv_key->x), priv_key_buf, priv_key_buf_len); EG(ret, err);
priv_key->key_type = ec_key_alg;
priv_key->params = (const ec_params *)params;
priv_key->magic = PRIV_KEY_MAGIC;
err:
return ret;
}
int ec_priv_key_export_to_buf(const ec_priv_key *priv_key, u8 *priv_key_buf,
u8 priv_key_buf_len)
{
int ret;
bitcnt_t blen;
ret = priv_key_check_initialized(priv_key); EG(ret, err);
ret = nn_bitlen(&(priv_key->x), &blen); EG(ret, err);
MUST_HAVE(((8 * (u32)priv_key_buf_len) >= (u32)blen), ret, err);
ret = nn_export_to_buf(priv_key_buf, priv_key_buf_len, &(priv_key->x));
err:
return ret;
}
int pub_key_check_initialized(const ec_pub_key *A)
{
int ret = 0;
MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) && (A->params != NULL)), ret, err);
err:
return ret;
}
int pub_key_check_initialized_and_type(const ec_pub_key *A,
ec_alg_type alg_type)
{
int ret = 0;
MUST_HAVE(((A != NULL) && (A->magic == PUB_KEY_MAGIC) &&
(A->params != NULL) && (A->key_type == alg_type)), ret, err);
err:
return ret;
}
int ec_pub_key_import_from_buf(ec_pub_key *pub_key, const ec_params *params,
const u8 *pub_key_buf, u8 pub_key_buf_len,
ec_alg_type ec_key_alg)
{
int ret, isone, check;
MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err);
ret = prj_pt_import_from_buf(&(pub_key->y),
pub_key_buf, pub_key_buf_len,
(ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err);
ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err);
if (!isone) {
ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err);
MUST_HAVE(check, ret, err);
}
pub_key->key_type = ec_key_alg;
pub_key->params = (const ec_params *)params;
pub_key->magic = PUB_KEY_MAGIC;
err:
return ret;
}
int ec_pub_key_import_from_aff_buf(ec_pub_key *pub_key, const ec_params *params,
const u8 *pub_key_buf, u8 pub_key_buf_len,
ec_alg_type ec_key_alg)
{
int ret, isone, check;
MUST_HAVE(((pub_key != NULL) && (pub_key_buf != NULL) && (params != NULL)), ret, err);
ret = prj_pt_import_from_aff_buf(&(pub_key->y),
pub_key_buf, pub_key_buf_len,
(ec_shortw_crv_src_t)&(params->ec_curve)); EG(ret, err);
ret = nn_isone(&(params->ec_gen_cofactor), &isone); EG(ret, err);
if (!isone){
ret = check_prj_pt_order(&(pub_key->y), &(params->ec_gen_order), PUBLIC_PT, &check); EG(ret, err);
MUST_HAVE(check, ret, err);
}
pub_key->key_type = ec_key_alg;
pub_key->params = (const ec_params *)params;
pub_key->magic = PUB_KEY_MAGIC;
err:
return ret;
}
int ec_pub_key_export_to_buf(const ec_pub_key *pub_key, u8 *pub_key_buf,
u8 pub_key_buf_len)
{
int ret;
ret = pub_key_check_initialized(pub_key); EG(ret, err);
ret = prj_pt_export_to_buf(&(pub_key->y), pub_key_buf, pub_key_buf_len);
err:
return ret;
}
int ec_pub_key_export_to_aff_buf(const ec_pub_key *pub_key, u8 *pub_key_buf,
u8 pub_key_buf_len)
{
int ret;
ret = pub_key_check_initialized(pub_key); EG(ret, err);
ret = prj_pt_export_to_aff_buf(&(pub_key->y), pub_key_buf,
pub_key_buf_len);
err:
return ret;
}
int key_pair_check_initialized(const ec_key_pair *A)
{
int ret;
MUST_HAVE((A != NULL), ret, err);
ret = priv_key_check_initialized(&A->priv_key); EG(ret, err);
ret = pub_key_check_initialized(&A->pub_key);
err:
return ret;
}
int key_pair_check_initialized_and_type(const ec_key_pair *A,
ec_alg_type alg_type)
{
int ret;
MUST_HAVE((A != NULL), ret, err);
ret = priv_key_check_initialized_and_type(&A->priv_key, alg_type); EG(ret, err);
ret = pub_key_check_initialized_and_type(&A->pub_key, alg_type);
err:
return ret;
}
int ec_key_pair_import_from_priv_key_buf(ec_key_pair *kp,
const ec_params *params,
const u8 *priv_key, u8 priv_key_len,
ec_alg_type ec_key_alg)
{
int ret;
MUST_HAVE((kp != NULL), ret, err);
ret = ec_priv_key_import_from_buf(&(kp->priv_key), params, priv_key,
priv_key_len, ec_key_alg); EG(ret, err);
ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key));
err:
return ret;
}
int ec_structured_priv_key_import_from_buf(ec_priv_key *priv_key,
const ec_params *params,
const u8 *priv_key_buf,
u8 priv_key_buf_len,
ec_alg_type ec_key_alg)
{
u8 metadata_len = (3 * sizeof(u8));
u8 crv_name_len;
u32 len;
int ret;
MUST_HAVE((priv_key != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err);
MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err);
MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err);
ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
crv_name_len = (u8)len;
ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]),
params->curve_name, crv_name_len); EG(ret, err);
ret = ec_priv_key_import_from_buf(priv_key, params,
priv_key_buf + metadata_len,
(u8)(priv_key_buf_len - metadata_len),
ec_key_alg);
err:
return ret;
}
int ec_structured_priv_key_export_to_buf(const ec_priv_key *priv_key,
u8 *priv_key_buf, u8 priv_key_buf_len)
{
u8 metadata_len = (3 * sizeof(u8));
const u8 *curve_name;
u8 curve_name_len;
u32 len;
ec_curve_type curve_type;
int ret;
ret = priv_key_check_initialized(priv_key); EG(ret, err);
MUST_HAVE((priv_key_buf != NULL) && (priv_key_buf_len > metadata_len) && (priv_key->params->curve_name != NULL), ret, err);
priv_key_buf[0] = (u8)EC_PRIVKEY;
priv_key_buf[1] = (u8)priv_key->key_type;
curve_name = priv_key->params->curve_name;
ret = local_strlen((const char *)curve_name, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
curve_name_len = (u8)len;
ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err);
priv_key_buf[2] = (u8)curve_type;
ret = ec_priv_key_export_to_buf(priv_key, priv_key_buf + metadata_len,
(u8)(priv_key_buf_len - metadata_len));
err:
return ret;
}
int ec_structured_pub_key_import_from_buf(ec_pub_key *pub_key,
const ec_params *params,
const u8 *pub_key_buf,
u8 pub_key_buf_len,
ec_alg_type ec_key_alg)
{
u8 metadata_len = (3 * sizeof(u8));
u8 crv_name_len;
u32 len;
int ret;
MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err);
MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
MUST_HAVE((EC_PUBKEY == pub_key_buf[0]), ret, err);
MUST_HAVE((ec_key_alg == pub_key_buf[1]), ret, err);
ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
crv_name_len = (u8)len;
ret = ec_check_curve_type_and_name((ec_curve_type) (pub_key_buf[2]),
params->curve_name, crv_name_len); EG(ret, err);
ret = ec_pub_key_import_from_buf(pub_key, params,
pub_key_buf + metadata_len,
(u8)(pub_key_buf_len - metadata_len),
ec_key_alg);
err:
return ret;
}
int ec_structured_pub_key_export_to_buf(const ec_pub_key *pub_key,
u8 *pub_key_buf, u8 pub_key_buf_len)
{
u8 metadata_len = (3 * sizeof(u8));
const u8 *curve_name;
u8 curve_name_len;
u32 len;
ec_curve_type curve_type;
int ret;
ret = pub_key_check_initialized(pub_key); EG(ret, err);
MUST_HAVE((pub_key_buf != NULL) && (pub_key_buf_len > metadata_len), ret, err);
MUST_HAVE((pub_key->params->curve_name != NULL), ret, err);
pub_key_buf[0] = (u8)EC_PUBKEY;
pub_key_buf[1] = (u8)pub_key->key_type;
curve_name = pub_key->params->curve_name;
ret = local_strlen((const char *)curve_name, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
curve_name_len = (u8)len;
ret = ec_get_curve_type_by_name(curve_name, curve_name_len, &curve_type); EG(ret, err);
pub_key_buf[2] = (u8)curve_type;
ret = ec_pub_key_export_to_buf(pub_key, pub_key_buf + metadata_len,
(u8)(pub_key_buf_len - metadata_len));
err:
return ret;
}
int ec_structured_key_pair_import_from_priv_key_buf(ec_key_pair *kp,
const ec_params *params,
const u8 *priv_key_buf,
u8 priv_key_buf_len,
ec_alg_type ec_key_alg)
{
u8 metadata_len = (3 * sizeof(u8));
u8 crv_name_len;
u32 len;
int ret;
MUST_HAVE((kp != NULL) && (priv_key_buf != NULL) && (priv_key_buf_len > metadata_len), ret, err);
MUST_HAVE((params != NULL) && (params->curve_name != NULL), ret, err);
MUST_HAVE((EC_PRIVKEY == priv_key_buf[0]), ret, err);
MUST_HAVE((ec_key_alg == priv_key_buf[1]), ret, err);
ret = local_strlen((const char *)params->curve_name, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
crv_name_len = (u8)len;
ret = ec_check_curve_type_and_name((ec_curve_type) (priv_key_buf[2]),
params->curve_name, crv_name_len); EG(ret, err);
ret = ec_key_pair_import_from_priv_key_buf(kp, params,
priv_key_buf + metadata_len,
(u8)(priv_key_buf_len - metadata_len),
ec_key_alg);
err:
return ret;
}
int ec_structured_key_pair_import_from_buf(ec_key_pair *kp,
const ec_params *params,
const u8 *priv_key_buf,
u8 priv_key_buf_len,
const u8 *pub_key_buf,
u8 pub_key_buf_len,
ec_alg_type ec_key_alg)
{
int ret;
MUST_HAVE((kp != NULL), ret, err);
ret = ec_structured_pub_key_import_from_buf(&kp->pub_key, params,
pub_key_buf,
pub_key_buf_len,
ec_key_alg); EG(ret, err);
ret = ec_structured_priv_key_import_from_buf(&kp->priv_key, params,
priv_key_buf,
priv_key_buf_len,
ec_key_alg);
err:
return ret;
}
int ec_key_pair_gen(ec_key_pair *kp, const ec_params *params,
ec_alg_type ec_key_alg)
{
int ret;
MUST_HAVE((kp != NULL) && (params != NULL), ret, err);
ret = nn_get_random_mod(&(kp->priv_key.x), &(params->ec_gen_order)); EG(ret, err);
kp->priv_key.key_type = ec_key_alg;
kp->priv_key.params = (const ec_params *)params;
kp->priv_key.magic = PRIV_KEY_MAGIC;
ret = gen_priv_key(&(kp->priv_key)); EG(ret, err);
ret = init_pubkey_from_privkey(&(kp->pub_key), &(kp->priv_key));
err:
if (ret && (kp != NULL)) {
IGNORE_RET_VAL(local_memset(kp, 0, sizeof(ec_key_pair)));
}
return ret;
}