blob: 6d24ea68f90b7cdd2e4a6238c24d73e51bfa4790 [file] [log] [blame]
// SPDX-License-Identifier: BSD-2-Clause
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
*
* LibTomCrypt is a library that provides various cryptographic
* algorithms in a highly modular and flexible manner.
*
* The library is free for all purposes without any express
* guarantee it works.
*/
#include "tomcrypt_private.h"
/**
@file ecc_import.c
ECC Crypto, Tom St Denis
*/
#ifdef LTC_MECC
/**
Import an ECC key from a binary packet
@param in The packet to import
@param inlen The length of the packet
@param key [out] The destination of the import
@return CRYPT_OK if successful, upon error all allocated memory will be freed
*/
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
{
return ecc_import_ex(in, inlen, key, NULL);
}
/**
Import an ECC key from a binary packet, using user supplied domain params rather than one of the NIST ones
@param in The packet to import
@param inlen The length of the packet
@param key [out] The destination of the import
@param cu pointer to user supplied params; must be the same as the params used when exporting
@return CRYPT_OK if successful, upon error all allocated memory will be freed
*/
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu)
{
unsigned long key_size;
unsigned char flags[1];
int err;
LTC_ARGCHK(in != NULL);
LTC_ARGCHK(key != NULL);
LTC_ARGCHK(ltc_mp.name != NULL);
/* find out what type of key it is */
err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
LTC_ASN1_EOL, 0UL, NULL);
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
return err;
}
/* allocate & initialize the key */
if (cu == NULL) {
if ((err = ecc_set_curve_by_size(key_size, key)) != CRYPT_OK) { goto done; }
} else {
if ((err = ecc_set_curve(cu, key)) != CRYPT_OK) { goto done; }
}
if (flags[0] == 1) {
/* private key */
key->type = PK_PRIVATE;
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
LTC_ASN1_INTEGER, 1UL, key->k,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto done;
}
} else if (flags[0] == 0) {
/* public key */
key->type = PK_PUBLIC;
if ((err = der_decode_sequence_multi(in, inlen,
LTC_ASN1_BIT_STRING, 1UL, flags,
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
LTC_ASN1_INTEGER, 1UL, key->pubkey.x,
LTC_ASN1_INTEGER, 1UL, key->pubkey.y,
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) {
goto done;
}
}
else {
err = CRYPT_INVALID_PACKET;
goto done;
}
/* set z */
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
/* point on the curve + other checks */
if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; }
/* we're good */
return CRYPT_OK;
done:
ecc_free(key);
return err;
}
#endif
/* ref: $Format:%D$ */
/* git commit: $Format:%H$ */
/* commit time: $Format:%ai$ */