ECC curves y^2 = x^3 + ax + b
This commit is contained in:
parent
ea32b2b194
commit
24c0eb84f9
@ -20,7 +20,7 @@ before_script:
|
|||||||
- curl http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz | tar xz
|
- curl http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz | tar xz
|
||||||
- export PATH=$PATH:`pwd`/lcov-1.11/bin
|
- export PATH=$PATH:`pwd`/lcov-1.11/bin
|
||||||
- curl -s https://packagecloud.io/install/repositories/libtom/packages/script.deb.sh | sudo bash
|
- curl -s https://packagecloud.io/install/repositories/libtom/packages/script.deb.sh | sudo bash
|
||||||
- sudo apt-get install libtfm-dev=0.13-5
|
- sudo apt-get install libtfm-dev=0.13-5 libtommath-dev=1.0-5
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
fast_finish: true
|
fast_finish: true
|
||||||
|
@ -947,28 +947,28 @@ static void time_ecc(void)
|
|||||||
unsigned long i, w, x, y, z;
|
unsigned long i, w, x, y, z;
|
||||||
int err, stat;
|
int err, stat;
|
||||||
static unsigned long sizes[] = {
|
static unsigned long sizes[] = {
|
||||||
#ifdef LTC_ECC112
|
#ifdef LTC_ECC_SECP112R1
|
||||||
112/8,
|
112/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC128
|
#ifdef LTC_ECC_SECP128R1
|
||||||
128/8,
|
128/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC160
|
#ifdef LTC_ECC_SECP160R1
|
||||||
160/8,
|
160/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC192
|
#ifdef LTC_ECC_SECP192R1
|
||||||
192/8,
|
192/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC224
|
#ifdef LTC_ECC_SECP224R1
|
||||||
224/8,
|
224/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC256
|
#ifdef LTC_ECC_SECP256R1
|
||||||
256/8,
|
256/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC384
|
#ifdef LTC_ECC_SECP384R1
|
||||||
384/8,
|
384/8,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC521
|
#ifdef LTC_ECC_SECP512R1
|
||||||
521/8,
|
521/8,
|
||||||
#endif
|
#endif
|
||||||
100000};
|
100000};
|
||||||
|
@ -663,7 +663,7 @@ void ecc_gen(void)
|
|||||||
{
|
{
|
||||||
FILE *out;
|
FILE *out;
|
||||||
unsigned char str[512];
|
unsigned char str[512];
|
||||||
void *k, *order, *modulus;
|
void *k, *order, *modulus, *a;
|
||||||
ecc_point *G, *R;
|
ecc_point *G, *R;
|
||||||
int x;
|
int x;
|
||||||
|
|
||||||
@ -674,26 +674,28 @@ void ecc_gen(void)
|
|||||||
mp_init(&k);
|
mp_init(&k);
|
||||||
mp_init(&order);
|
mp_init(&order);
|
||||||
mp_init(&modulus);
|
mp_init(&modulus);
|
||||||
|
mp_init(&a);
|
||||||
|
|
||||||
for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
|
for (x = 0; ltc_ecc_curves[x].prime != NULL; x++) {
|
||||||
fprintf(out, "ECC-%d\n", ltc_ecc_sets[x].size*8);
|
fprintf(out, "%s\n", ltc_ecc_curves[x].OID);
|
||||||
mp_set(k, 1);
|
mp_set(k, 1);
|
||||||
|
|
||||||
mp_read_radix(order, (char *)ltc_ecc_sets[x].order, 16);
|
mp_read_radix(order, (char *)ltc_ecc_curves[x].order, 16);
|
||||||
mp_read_radix(modulus, (char *)ltc_ecc_sets[x].prime, 16);
|
mp_read_radix(modulus, (char *)ltc_ecc_curves[x].prime, 16);
|
||||||
mp_read_radix(G->x, (char *)ltc_ecc_sets[x].Gx, 16);
|
mp_read_radix(a, (char *)ltc_ecc_curves[x].A, 16);
|
||||||
mp_read_radix(G->y, (char *)ltc_ecc_sets[x].Gy, 16);
|
mp_read_radix(G->x, (char *)ltc_ecc_curves[x].Gx, 16);
|
||||||
|
mp_read_radix(G->y, (char *)ltc_ecc_curves[x].Gy, 16);
|
||||||
mp_set(G->z, 1);
|
mp_set(G->z, 1);
|
||||||
|
|
||||||
while (mp_cmp(k, order) == LTC_MP_LT) {
|
while (mp_cmp(k, order) == LTC_MP_LT) {
|
||||||
ltc_mp.ecc_ptmul(k, G, R, modulus, 1);
|
ltc_mp.ecc_ptmul(k, G, R, a, modulus, 1);
|
||||||
mp_tohex(k, (char*)str); fprintf(out, "%s, ", (char*)str);
|
mp_tohex(k, (char*)str); fprintf(out, "%s, ", (char*)str);
|
||||||
mp_tohex(R->x, (char*)str); fprintf(out, "%s, ", (char*)str);
|
mp_tohex(R->x, (char*)str); fprintf(out, "%s, ", (char*)str);
|
||||||
mp_tohex(R->y, (char*)str); fprintf(out, "%s\n", (char*)str);
|
mp_tohex(R->y, (char*)str); fprintf(out, "%s\n", (char*)str);
|
||||||
mp_mul_d(k, 3, k);
|
mp_mul_d(k, 3, k);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mp_clear_multi(k, order, modulus, NULL);
|
mp_clear_multi(k, order, modulus, a, NULL);
|
||||||
ltc_ecc_del_point(G);
|
ltc_ecc_del_point(G);
|
||||||
ltc_ecc_del_point(R);
|
ltc_ecc_del_point(R);
|
||||||
fclose(out);
|
fclose(out);
|
||||||
|
4103
notes/ecc_tv.txt
4103
notes/ecc_tv.txt
File diff suppressed because it is too large
Load Diff
@ -503,14 +503,40 @@
|
|||||||
#ifdef LTC_MECC
|
#ifdef LTC_MECC
|
||||||
/* Supported ECC Key Sizes */
|
/* Supported ECC Key Sizes */
|
||||||
#ifndef LTC_NO_CURVES
|
#ifndef LTC_NO_CURVES
|
||||||
#define LTC_ECC112
|
#define LTC_ECC_BRAINPOOLP160R1
|
||||||
#define LTC_ECC128
|
#define LTC_ECC_BRAINPOOLP160T1
|
||||||
#define LTC_ECC160
|
#define LTC_ECC_BRAINPOOLP192R1
|
||||||
#define LTC_ECC192
|
#define LTC_ECC_BRAINPOOLP192T1
|
||||||
#define LTC_ECC224
|
#define LTC_ECC_BRAINPOOLP224R1
|
||||||
#define LTC_ECC256
|
#define LTC_ECC_BRAINPOOLP224T1
|
||||||
#define LTC_ECC384
|
#define LTC_ECC_BRAINPOOLP256R1
|
||||||
#define LTC_ECC521
|
#define LTC_ECC_BRAINPOOLP256T1
|
||||||
|
#define LTC_ECC_BRAINPOOLP320R1
|
||||||
|
#define LTC_ECC_BRAINPOOLP320T1
|
||||||
|
#define LTC_ECC_BRAINPOOLP384R1
|
||||||
|
#define LTC_ECC_BRAINPOOLP384T1
|
||||||
|
#define LTC_ECC_BRAINPOOLP512R1
|
||||||
|
#define LTC_ECC_BRAINPOOLP512T1
|
||||||
|
#define LTC_ECC_PRIME192V2
|
||||||
|
#define LTC_ECC_PRIME192V3
|
||||||
|
#define LTC_ECC_PRIME239V1
|
||||||
|
#define LTC_ECC_PRIME239V2
|
||||||
|
#define LTC_ECC_PRIME239V3
|
||||||
|
#define LTC_ECC_SECP112R1
|
||||||
|
#define LTC_ECC_SECP112R2
|
||||||
|
#define LTC_ECC_SECP128R1
|
||||||
|
#define LTC_ECC_SECP128R2
|
||||||
|
#define LTC_ECC_SECP160K1
|
||||||
|
#define LTC_ECC_SECP160R1
|
||||||
|
#define LTC_ECC_SECP160R2
|
||||||
|
#define LTC_ECC_SECP192K1
|
||||||
|
#define LTC_ECC_SECP192R1
|
||||||
|
#define LTC_ECC_SECP224K1
|
||||||
|
#define LTC_ECC_SECP224R1
|
||||||
|
#define LTC_ECC_SECP256K1
|
||||||
|
#define LTC_ECC_SECP256R1
|
||||||
|
#define LTC_ECC_SECP384R1
|
||||||
|
#define LTC_ECC_SECP521R1
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -627,6 +653,40 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* ECC backwards compatibility */
|
||||||
|
#if !defined(LTC_ECC_SECP112R1) && defined(LTC_ECC112)
|
||||||
|
#define LTC_ECC_SECP112R1
|
||||||
|
#undef LTC_ECC112
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP128R1) && defined(LTC_ECC128)
|
||||||
|
#define LTC_ECC_SECP128R1
|
||||||
|
#undef LTC_ECC128
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP160R1) && defined(LTC_ECC160)
|
||||||
|
#define LTC_ECC_SECP160R1
|
||||||
|
#undef LTC_ECC160
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP192R1) && defined(LTC_ECC192)
|
||||||
|
#define LTC_ECC_SECP192R1
|
||||||
|
#undef LTC_ECC192
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP224R1) && defined(LTC_ECC224)
|
||||||
|
#define LTC_ECC_SECP224R1
|
||||||
|
#undef LTC_ECC224
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP256R1) && defined(LTC_ECC256)
|
||||||
|
#define LTC_ECC_SECP256R1
|
||||||
|
#undef LTC_ECC256
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP384R1) && defined(LTC_ECC384)
|
||||||
|
#define LTC_ECC_SECP384R1
|
||||||
|
#undef LTC_ECC384
|
||||||
|
#endif
|
||||||
|
#if !defined(LTC_ECC_SECP512R1) && defined(LTC_ECC521)
|
||||||
|
#define LTC_ECC_SECP521R1
|
||||||
|
#undef LTC_ECC521
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ref: $Format:%D$ */
|
/* ref: $Format:%D$ */
|
||||||
/* git commit: $Format:%H$ */
|
/* git commit: $Format:%H$ */
|
||||||
/* commit time: $Format:%ai$ */
|
/* commit time: $Format:%ai$ */
|
||||||
|
@ -246,6 +246,14 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
int (*sqr)(void *a, void *b);
|
int (*sqr)(void *a, void *b);
|
||||||
|
|
||||||
|
/** Square root (mod prime)
|
||||||
|
@param a The integer to compute square root mod prime from
|
||||||
|
@param b The prime
|
||||||
|
@param c The destination
|
||||||
|
@return CRYPT_OK on success
|
||||||
|
*/
|
||||||
|
int (*sqrtmod_prime)(void *a, void *b, void *c);
|
||||||
|
|
||||||
/** Divide an integer
|
/** Divide an integer
|
||||||
@param a The dividend
|
@param a The dividend
|
||||||
@param b The divisor
|
@param b The divisor
|
||||||
@ -366,42 +374,48 @@ typedef struct {
|
|||||||
@param k The integer to multiply the point by
|
@param k The integer to multiply the point by
|
||||||
@param G The point to multiply
|
@param G The point to multiply
|
||||||
@param R The destination for kG
|
@param R The destination for kG
|
||||||
|
@param a ECC curve parameter a
|
||||||
@param modulus The modulus for the field
|
@param modulus The modulus for the field
|
||||||
@param map Boolean indicated whether to map back to affine or not
|
@param map Boolean indicated whether to map back to affine or not
|
||||||
(can be ignored if you work in affine only)
|
(can be ignored if you work in affine only)
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int (*ecc_ptmul)( void *k,
|
int (*ecc_ptmul)( void *k,
|
||||||
ecc_point *G,
|
const ecc_point *G,
|
||||||
ecc_point *R,
|
ecc_point *R,
|
||||||
void *modulus,
|
void *a,
|
||||||
int map);
|
void *modulus,
|
||||||
|
int map);
|
||||||
|
|
||||||
/** ECC GF(p) point addition
|
/** ECC GF(p) point addition
|
||||||
@param P The first point
|
@param P The first point
|
||||||
@param Q The second point
|
@param Q The second point
|
||||||
@param R The destination of P + Q
|
@param R The destination of P + Q
|
||||||
|
@param ma The curve parameter "a" in montgomery form
|
||||||
@param modulus The modulus
|
@param modulus The modulus
|
||||||
@param mp The "b" value from montgomery_setup()
|
@param mp The "b" value from montgomery_setup()
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int (*ecc_ptadd)(ecc_point *P,
|
int (*ecc_ptadd)(const ecc_point *P,
|
||||||
ecc_point *Q,
|
const ecc_point *Q,
|
||||||
ecc_point *R,
|
ecc_point *R,
|
||||||
void *modulus,
|
void *ma,
|
||||||
void *mp);
|
void *modulus,
|
||||||
|
void *mp);
|
||||||
|
|
||||||
/** ECC GF(p) point double
|
/** ECC GF(p) point double
|
||||||
@param P The first point
|
@param P The first point
|
||||||
@param R The destination of 2P
|
@param R The destination of 2P
|
||||||
|
@param ma The curve parameter "a" in montgomery form
|
||||||
@param modulus The modulus
|
@param modulus The modulus
|
||||||
@param mp The "b" value from montgomery_setup()
|
@param mp The "b" value from montgomery_setup()
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int (*ecc_ptdbl)(ecc_point *P,
|
int (*ecc_ptdbl)(const ecc_point *P,
|
||||||
ecc_point *R,
|
ecc_point *R,
|
||||||
void *modulus,
|
void *ma,
|
||||||
void *mp);
|
void *modulus,
|
||||||
|
void *mp);
|
||||||
|
|
||||||
/** ECC mapping from projective to affine,
|
/** ECC mapping from projective to affine,
|
||||||
currently uses (x,y,z) => (x/z^2, y/z^3, 1)
|
currently uses (x,y,z) => (x/z^2, y/z^3, 1)
|
||||||
@ -421,13 +435,15 @@ typedef struct {
|
|||||||
@param B Second point to multiply
|
@param B Second point to multiply
|
||||||
@param kB What to multiple B by
|
@param kB What to multiple B by
|
||||||
@param C [out] Destination point (can overlap with A or B)
|
@param C [out] Destination point (can overlap with A or B)
|
||||||
|
@param ma The curve parameter "a" in montgomery form
|
||||||
@param modulus Modulus for curve
|
@param modulus Modulus for curve
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int (*ecc_mul2add)(ecc_point *A, void *kA,
|
int (*ecc_mul2add)(const ecc_point *A, void *kA,
|
||||||
ecc_point *B, void *kB,
|
const ecc_point *B, void *kB,
|
||||||
ecc_point *C,
|
ecc_point *C,
|
||||||
void *modulus);
|
void *ma,
|
||||||
|
void *modulus);
|
||||||
|
|
||||||
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
|
/* ---- (optional) rsa optimized math (for internal CRT) ---- */
|
||||||
|
|
||||||
@ -547,6 +563,7 @@ extern const ltc_math_descriptor gmp_desc;
|
|||||||
#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
|
#define mp_mul(a, b, c) ltc_mp.mul(a, b, c)
|
||||||
#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
|
#define mp_mul_d(a, b, c) ltc_mp.muli(a, b, c)
|
||||||
#define mp_sqr(a, b) ltc_mp.sqr(a, b)
|
#define mp_sqr(a, b) ltc_mp.sqr(a, b)
|
||||||
|
#define mp_sqrtmod_prime(a, b, c) ltc_mp.sqrtmod_prime(a, b, c)
|
||||||
#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
|
#define mp_div(a, b, c, d) ltc_mp.mpdiv(a, b, c, d)
|
||||||
#define mp_div_2(a, b) ltc_mp.div_2(a, b)
|
#define mp_div_2(a, b) ltc_mp.div_2(a, b)
|
||||||
#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
|
#define mp_mod(a, b, c) ltc_mp.mpdiv(a, b, NULL, c)
|
||||||
|
@ -17,6 +17,10 @@ enum public_key_type {
|
|||||||
|
|
||||||
/* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */
|
/* Indicates standard output formats that can be read e.g. by OpenSSL or GnuTLS */
|
||||||
PK_STD = 0x1000,
|
PK_STD = 0x1000,
|
||||||
|
/* Indicates compressed public ECC key */
|
||||||
|
PK_COMPRESSED = 0x2000,
|
||||||
|
/* Indicates ECC key with the curve specified by OID */
|
||||||
|
PK_CURVEOID = 0x4000
|
||||||
};
|
};
|
||||||
|
|
||||||
int rand_prime(void *N, long len, prng_state *prng, int wprng);
|
int rand_prime(void *N, long len, prng_state *prng, int wprng);
|
||||||
@ -38,6 +42,8 @@ typedef struct Oid {
|
|||||||
} oid_st;
|
} oid_st;
|
||||||
|
|
||||||
int pk_get_oid(int pk, oid_st *st);
|
int pk_get_oid(int pk, oid_st *st);
|
||||||
|
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen);
|
||||||
|
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen);
|
||||||
#endif /* LTC_SOURCE */
|
#endif /* LTC_SOURCE */
|
||||||
|
|
||||||
/* ---- RSA ---- */
|
/* ---- RSA ---- */
|
||||||
@ -252,17 +258,14 @@ int dh_check_pubkey(const dh_key *key);
|
|||||||
/* max private key size */
|
/* max private key size */
|
||||||
#define ECC_MAXSIZE 66
|
#define ECC_MAXSIZE 66
|
||||||
|
|
||||||
/** Structure defines a NIST GF(p) curve */
|
/** Structure defines a GF(p) curve */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** The size of the curve in octets */
|
|
||||||
int size;
|
|
||||||
|
|
||||||
/** name of curve */
|
|
||||||
const char *name;
|
|
||||||
|
|
||||||
/** The prime that defines the field the curve is in (encoded in hex) */
|
/** The prime that defines the field the curve is in (encoded in hex) */
|
||||||
const char *prime;
|
const char *prime;
|
||||||
|
|
||||||
|
/** The fields A param (hex) */
|
||||||
|
const char *A;
|
||||||
|
|
||||||
/** The fields B param (hex) */
|
/** The fields B param (hex) */
|
||||||
const char *B;
|
const char *B;
|
||||||
|
|
||||||
@ -274,7 +277,13 @@ typedef struct {
|
|||||||
|
|
||||||
/** The y co-ordinate of the base point on the curve (hex) */
|
/** The y co-ordinate of the base point on the curve (hex) */
|
||||||
const char *Gy;
|
const char *Gy;
|
||||||
} ltc_ecc_set_type;
|
|
||||||
|
/** The co-factor */
|
||||||
|
unsigned long cofactor;
|
||||||
|
|
||||||
|
/** The OID */
|
||||||
|
const char *OID;
|
||||||
|
} ltc_ecc_curve;
|
||||||
|
|
||||||
/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
|
/** A point on a ECC curve, stored in Jacbobian format such that (x,y,z) => (x/z^2, y/z^3, 1) when interpretted as affine */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -288,18 +297,36 @@ typedef struct {
|
|||||||
void *z;
|
void *z;
|
||||||
} ecc_point;
|
} ecc_point;
|
||||||
|
|
||||||
|
/** ECC key's domain parameters */
|
||||||
|
typedef struct {
|
||||||
|
/** The size of the curve in octets */
|
||||||
|
int size;
|
||||||
|
/** The prime that defines the field the curve is in */
|
||||||
|
void *prime;
|
||||||
|
/** The fields A param */
|
||||||
|
void *A;
|
||||||
|
/** The fields B param */
|
||||||
|
void *B;
|
||||||
|
/** The order of the curve */
|
||||||
|
void *order;
|
||||||
|
/** The base point G on the curve */
|
||||||
|
ecc_point base;
|
||||||
|
/** The co-factor */
|
||||||
|
unsigned long cofactor;
|
||||||
|
/** The OID */
|
||||||
|
unsigned long oid[16];
|
||||||
|
unsigned long oidlen;
|
||||||
|
} ltc_ecc_dp;
|
||||||
|
|
||||||
/** An ECC key */
|
/** An ECC key */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
/** Type of key, PK_PRIVATE or PK_PUBLIC */
|
||||||
int type;
|
int type;
|
||||||
|
|
||||||
/** Index into the ltc_ecc_sets[] for the parameters of this curve; if -1, then this key is using user supplied curve in dp */
|
/** Structure with domain parameters */
|
||||||
int idx;
|
ltc_ecc_dp dp;
|
||||||
|
|
||||||
/** pointer to domain parameters; either points to NIST curves (identified by idx >= 0) or user supplied curve */
|
/** Structure with the public key */
|
||||||
const ltc_ecc_set_type *dp;
|
|
||||||
|
|
||||||
/** The public key */
|
|
||||||
ecc_point pubkey;
|
ecc_point pubkey;
|
||||||
|
|
||||||
/** The private key */
|
/** The private key */
|
||||||
@ -307,69 +334,90 @@ typedef struct {
|
|||||||
} ecc_key;
|
} ecc_key;
|
||||||
|
|
||||||
/** the ECC params provided */
|
/** the ECC params provided */
|
||||||
extern const ltc_ecc_set_type ltc_ecc_sets[];
|
extern const ltc_ecc_curve ltc_ecc_curves[];
|
||||||
|
|
||||||
int ecc_test(void);
|
int ecc_test(void);
|
||||||
void ecc_sizes(int *low, int *high);
|
void ecc_sizes(int *low, int *high);
|
||||||
int ecc_get_size(ecc_key *key);
|
int ecc_get_size(const ecc_key *key);
|
||||||
|
|
||||||
|
int ecc_get_curve(const char* name_or_oid, const ltc_ecc_curve** cu);
|
||||||
|
int ecc_set_dp(const ltc_ecc_curve *cu, ecc_key *key);
|
||||||
|
int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key);
|
||||||
|
int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key);
|
||||||
|
int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
|
||||||
|
int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key);
|
||||||
|
|
||||||
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
|
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key);
|
||||||
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp);
|
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu);
|
||||||
void ecc_free(ecc_key *key);
|
void ecc_free(ecc_key *key);
|
||||||
|
|
||||||
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key);
|
int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key);
|
||||||
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||||
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_set_type *dp);
|
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu);
|
||||||
|
|
||||||
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen);
|
int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen);
|
||||||
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *key);
|
||||||
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp);
|
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu);
|
||||||
|
|
||||||
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
|
||||||
unsigned char *out, unsigned long *outlen);
|
unsigned char *out, unsigned long *outlen);
|
||||||
|
|
||||||
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, int hash,
|
prng_state *prng, int wprng, int hash,
|
||||||
ecc_key *key);
|
const ecc_key *key);
|
||||||
|
|
||||||
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
ecc_key *key);
|
const ecc_key *key);
|
||||||
|
|
||||||
int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
|
int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, ecc_key *key);
|
prng_state *prng, int wprng, const ecc_key *key);
|
||||||
|
|
||||||
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, ecc_key *key);
|
prng_state *prng, int wprng, const ecc_key *key);
|
||||||
|
|
||||||
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
|
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
|
||||||
const unsigned char *hash, unsigned long hashlen,
|
const unsigned char *hash, unsigned long hashlen,
|
||||||
int *stat, ecc_key *key);
|
int *stat, const ecc_key *key);
|
||||||
|
|
||||||
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||||
const unsigned char *hash, unsigned long hashlen,
|
const unsigned char *hash, unsigned long hashlen,
|
||||||
int *stat, ecc_key *key);
|
int *stat, const ecc_key *key);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef LTC_SOURCE
|
||||||
|
/* INTERNAL ONLY - it should be later moved to src/headers/tomcrypt_internal.h */
|
||||||
|
|
||||||
|
int ecc_set_dp_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key);
|
||||||
|
int ecc_copy_dp(const ecc_key *srckey, ecc_key *key);
|
||||||
|
int ecc_set_dp_by_size(int size, ecc_key *key);
|
||||||
|
|
||||||
/* low level functions */
|
/* low level functions */
|
||||||
ecc_point *ltc_ecc_new_point(void);
|
ecc_point *ltc_ecc_new_point(void);
|
||||||
void ltc_ecc_del_point(ecc_point *p);
|
void ltc_ecc_del_point(ecc_point *p);
|
||||||
int ltc_ecc_is_valid_idx(int n);
|
int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p);
|
||||||
|
int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst);
|
||||||
|
int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y);
|
||||||
|
int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval);
|
||||||
|
int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y);
|
||||||
|
int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed);
|
||||||
|
int ltc_ecc_verify_key(const ecc_key *key);
|
||||||
|
|
||||||
/* point ops (mp == montgomery digit) */
|
/* point ops (mp == montgomery digit) */
|
||||||
#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC)
|
#if !defined(LTC_MECC_ACCEL) || defined(LTM_DESC) || defined(GMP_DESC)
|
||||||
/* R = 2P */
|
/* R = 2P */
|
||||||
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp);
|
int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp);
|
||||||
|
|
||||||
/* R = P + Q */
|
/* R = P + Q */
|
||||||
int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp);
|
int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(LTC_MECC_FP)
|
#if defined(LTC_MECC_FP)
|
||||||
/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
|
/* optimized point multiplication using fixed point cache (HAC algorithm 14.117) */
|
||||||
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
|
||||||
|
|
||||||
/* functions for saving/loading/freeing/adding to fixed point cache */
|
/* functions for saving/loading/freeing/adding to fixed point cache */
|
||||||
int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
|
int ltc_ecc_fp_save_state(unsigned char **out, unsigned long *outlen);
|
||||||
@ -382,20 +430,23 @@ void ltc_ecc_fp_tablelock(int lock);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* R = kG */
|
/* R = kG */
|
||||||
int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map);
|
int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map);
|
||||||
|
|
||||||
#ifdef LTC_ECC_SHAMIR
|
#ifdef LTC_ECC_SHAMIR
|
||||||
/* kA*A + kB*B = C */
|
/* kA*A + kB*B = C */
|
||||||
int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
int ltc_ecc_mul2add(const ecc_point *A, void *kA,
|
||||||
ecc_point *B, void *kB,
|
const ecc_point *B, void *kB,
|
||||||
ecc_point *C,
|
ecc_point *C,
|
||||||
void *modulus);
|
void *ma,
|
||||||
|
void *modulus);
|
||||||
|
|
||||||
#ifdef LTC_MECC_FP
|
#ifdef LTC_MECC_FP
|
||||||
/* Shamir's trick with optimized point multiplication using fixed point cache */
|
/* Shamir's trick with optimized point multiplication using fixed point cache */
|
||||||
int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
int ltc_ecc_fp_mul2add(const ecc_point *A, void *kA,
|
||||||
ecc_point *B, void *kB,
|
const ecc_point *B, void *kB,
|
||||||
ecc_point *C, void *modulus);
|
ecc_point *C,
|
||||||
|
void *ma,
|
||||||
|
void *modulus);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@ -404,6 +455,8 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
|||||||
/* map P to affine from projective */
|
/* map P to affine from projective */
|
||||||
int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
|
int ltc_ecc_map(ecc_point *P, void *modulus, void *mp);
|
||||||
|
|
||||||
|
#endif /* LTC_SOURCE */
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LTC_MDSA
|
#ifdef LTC_MDSA
|
||||||
|
@ -668,7 +668,7 @@ static int _add_entry(int idx, ecc_point *g)
|
|||||||
* The algorithm builds patterns in increasing bit order by first making all
|
* The algorithm builds patterns in increasing bit order by first making all
|
||||||
* single bit input patterns, then all two bit input patterns and so on
|
* single bit input patterns, then all two bit input patterns and so on
|
||||||
*/
|
*/
|
||||||
static int _build_lut(int idx, void *modulus, void *mp, void *mu)
|
static int _build_lut(int idx, void *a, void *modulus, void *mp, void *mu)
|
||||||
{
|
{
|
||||||
unsigned x, y, err, bitlen, lut_gap;
|
unsigned x, y, err, bitlen, lut_gap;
|
||||||
void *tmp;
|
void *tmp;
|
||||||
@ -707,7 +707,7 @@ static int _build_lut(int idx, void *modulus, void *mp, void *mu)
|
|||||||
|
|
||||||
/* now double it bitlen/FP_LUT times */
|
/* now double it bitlen/FP_LUT times */
|
||||||
for (y = 0; y < lut_gap; y++) {
|
for (y = 0; y < lut_gap; y++) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<<x], fp_cache[idx].LUT[1<<x], modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptdbl(fp_cache[idx].LUT[1<<x], fp_cache[idx].LUT[1<<x], a, modulus, mp)) != CRYPT_OK) {
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -720,7 +720,7 @@ static int _build_lut(int idx, void *modulus, void *mp, void *mu)
|
|||||||
|
|
||||||
/* perform the add */
|
/* perform the add */
|
||||||
if ((err = ltc_mp.ecc_ptadd(fp_cache[idx].LUT[lut_orders[y].terma], fp_cache[idx].LUT[lut_orders[y].termb],
|
if ((err = ltc_mp.ecc_ptadd(fp_cache[idx].LUT[lut_orders[y].terma], fp_cache[idx].LUT[lut_orders[y].termb],
|
||||||
fp_cache[idx].LUT[y], modulus, mp)) != CRYPT_OK) {
|
fp_cache[idx].LUT[y], a, modulus, mp)) != CRYPT_OK) {
|
||||||
goto ERR;
|
goto ERR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -775,7 +775,7 @@ DONE:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* perform a fixed point ECC mulmod */
|
/* perform a fixed point ECC mulmod */
|
||||||
static int _accel_fp_mul(int idx, void *k, ecc_point *R, void *modulus, void *mp, int map)
|
static int _accel_fp_mul(int idx, void *k, ecc_point *R, void *a, void *modulus, void *mp, int map)
|
||||||
{
|
{
|
||||||
unsigned char kb[128];
|
unsigned char kb[128];
|
||||||
int x;
|
int x;
|
||||||
@ -868,14 +868,14 @@ static int _accel_fp_mul(int idx, void *k, ecc_point *R, void *modulus, void *mp
|
|||||||
|
|
||||||
/* double if not first */
|
/* double if not first */
|
||||||
if (!first) {
|
if (!first) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* add if not first, otherwise copy */
|
/* add if not first, otherwise copy */
|
||||||
if (!first && z) {
|
if (!first && z) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx].LUT[z], R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
} else if (z) {
|
} else if (z) {
|
||||||
@ -900,7 +900,7 @@ static int _accel_fp_mul(int idx, void *k, ecc_point *R, void *modulus, void *mp
|
|||||||
/* perform a fixed point ECC mulmod */
|
/* perform a fixed point ECC mulmod */
|
||||||
static int _accel_fp_mul2add(int idx1, int idx2,
|
static int _accel_fp_mul2add(int idx1, int idx2,
|
||||||
void *kA, void *kB,
|
void *kA, void *kB,
|
||||||
ecc_point *R, void *modulus, void *mp)
|
ecc_point *R, void *a, void *modulus, void *mp)
|
||||||
{
|
{
|
||||||
unsigned char kb[2][128];
|
unsigned char kb[2][128];
|
||||||
int x;
|
int x;
|
||||||
@ -1056,7 +1056,7 @@ static int _accel_fp_mul2add(int idx1, int idx2,
|
|||||||
|
|
||||||
/* double if not first */
|
/* double if not first */
|
||||||
if (!first) {
|
if (!first) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptdbl(R, R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1064,12 +1064,12 @@ static int _accel_fp_mul2add(int idx1, int idx2,
|
|||||||
/* add if not first, otherwise copy */
|
/* add if not first, otherwise copy */
|
||||||
if (!first) {
|
if (!first) {
|
||||||
if (zA) {
|
if (zA) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx1].LUT[zA], R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (zB) {
|
if (zB) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1082,7 +1082,7 @@ static int _accel_fp_mul2add(int idx1, int idx2,
|
|||||||
}
|
}
|
||||||
if (zB && first == 0) {
|
if (zB && first == 0) {
|
||||||
if (zB) {
|
if (zB) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, modulus, mp)) != CRYPT_OK) {
|
if ((err = ltc_mp.ecc_ptadd(R, fp_cache[idx2].LUT[zB], R, a, modulus, mp)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1110,7 +1110,9 @@ static int _accel_fp_mul2add(int idx1, int idx2,
|
|||||||
*/
|
*/
|
||||||
int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
||||||
ecc_point *B, void *kB,
|
ecc_point *B, void *kB,
|
||||||
ecc_point *C, void *modulus)
|
ecc_point *C,
|
||||||
|
void *a,
|
||||||
|
void *modulus)
|
||||||
{
|
{
|
||||||
int idx1, idx2, err;
|
int idx1, idx2, err;
|
||||||
void *mp, *mu;
|
void *mp, *mu;
|
||||||
@ -1166,7 +1168,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build the LUT */
|
/* build the LUT */
|
||||||
if ((err = _build_lut(idx1, modulus, mp, mu)) != CRYPT_OK) {
|
if ((err = _build_lut(idx1, a, modulus, mp, mu)) != CRYPT_OK) {
|
||||||
goto LBL_ERR;;
|
goto LBL_ERR;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1187,7 +1189,7 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build the LUT */
|
/* build the LUT */
|
||||||
if ((err = _build_lut(idx2, modulus, mp, mu)) != CRYPT_OK) {
|
if ((err = _build_lut(idx2, a, modulus, mp, mu)) != CRYPT_OK) {
|
||||||
goto LBL_ERR;;
|
goto LBL_ERR;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1198,9 +1200,9 @@ int ltc_ecc_fp_mul2add(ecc_point *A, void *kA,
|
|||||||
/* compute mp */
|
/* compute mp */
|
||||||
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
|
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
}
|
}
|
||||||
err = _accel_fp_mul2add(idx1, idx2, kA, kB, C, modulus, mp);
|
err = _accel_fp_mul2add(idx1, idx2, kA, kB, C, a, modulus, mp);
|
||||||
} else {
|
} else {
|
||||||
err = ltc_ecc_mul2add(A, kA, B, kB, C, modulus);
|
err = ltc_ecc_mul2add(A, kA, B, kB, C, a, modulus);
|
||||||
}
|
}
|
||||||
LBL_ERR:
|
LBL_ERR:
|
||||||
LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
|
LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
|
||||||
@ -1218,11 +1220,12 @@ LBL_ERR:
|
|||||||
@param k The multiplicand
|
@param k The multiplicand
|
||||||
@param G Base point to multiply
|
@param G Base point to multiply
|
||||||
@param R [out] Destination of product
|
@param R [out] Destination of product
|
||||||
|
@param a ECC curve parameter a
|
||||||
@param modulus The modulus for the curve
|
@param modulus The modulus for the curve
|
||||||
@param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form
|
@param map [boolean] If non-zero maps the point back to affine co-ordinates, otherwise it's left in jacobian-montgomery form
|
||||||
@return CRYPT_OK if successful
|
@return CRYPT_OK if successful
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
|
||||||
{
|
{
|
||||||
int idx, err;
|
int idx, err;
|
||||||
void *mp, *mu;
|
void *mp, *mu;
|
||||||
@ -1264,7 +1267,7 @@ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int ma
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build the LUT */
|
/* build the LUT */
|
||||||
if ((err = _build_lut(idx, modulus, mp, mu)) != CRYPT_OK) {
|
if ((err = _build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) {
|
||||||
goto LBL_ERR;;
|
goto LBL_ERR;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1274,9 +1277,9 @@ int ltc_ecc_fp_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int ma
|
|||||||
/* compute mp */
|
/* compute mp */
|
||||||
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
|
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
}
|
}
|
||||||
err = _accel_fp_mul(idx, k, R, modulus, mp, map);
|
err = _accel_fp_mul(idx, k, R, a, modulus, mp, map);
|
||||||
} else {
|
} else {
|
||||||
err = ltc_ecc_mulmod(k, G, R, modulus, map);
|
err = ltc_ecc_mulmod(k, G, R, a, modulus, map);
|
||||||
}
|
}
|
||||||
LBL_ERR:
|
LBL_ERR:
|
||||||
LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
|
LTC_MUTEX_UNLOCK(<c_ecc_fp_lock);
|
||||||
@ -1363,7 +1366,7 @@ ltc_ecc_fp_add_point(ecc_point *g, void *modulus, int lock)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* build the LUT */
|
/* build the LUT */
|
||||||
if ((err = _build_lut(idx, modulus, mp, mu)) != CRYPT_OK) {
|
if ((err = _build_lut(idx, a, modulus, mp, mu)) != CRYPT_OK) {
|
||||||
goto LBL_ERR;
|
goto LBL_ERR;
|
||||||
}
|
}
|
||||||
fp_cache[idx].lru_count = 2;
|
fp_cache[idx].lru_count = 2;
|
||||||
|
@ -286,6 +286,119 @@ static int sqr(void *a, void *b)
|
|||||||
return CRYPT_OK;
|
return CRYPT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sqrtmod_prime */
|
||||||
|
static int sqrtmod_prime(void *n, void *prime, void *ret)
|
||||||
|
{
|
||||||
|
int res, legendre, i;
|
||||||
|
mpz_t t1, C, Q, S, Z, M, T, R, two;
|
||||||
|
|
||||||
|
LTC_ARGCHK(n != NULL);
|
||||||
|
LTC_ARGCHK(prime != NULL);
|
||||||
|
LTC_ARGCHK(ret != NULL);
|
||||||
|
|
||||||
|
/* first handle the simple cases */
|
||||||
|
if (mpz_cmp_ui(((__mpz_struct *)n), 0) == 0) {
|
||||||
|
mpz_set_ui(ret, 0);
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
if (mpz_cmp_ui(((__mpz_struct *)prime), 2) == 0) return CRYPT_ERROR; /* prime must be odd */
|
||||||
|
legendre = mpz_legendre(n, prime);
|
||||||
|
if (legendre == -1) return CRYPT_ERROR; /* quadratic non-residue mod prime */
|
||||||
|
|
||||||
|
mpz_init(t1); mpz_init(C); mpz_init(Q);
|
||||||
|
mpz_init(S); mpz_init(Z); mpz_init(M);
|
||||||
|
mpz_init(T); mpz_init(R); mpz_init(two);
|
||||||
|
|
||||||
|
/* SPECIAL CASE: if prime mod 4 == 3
|
||||||
|
* compute directly: res = n^(prime+1)/4 mod prime
|
||||||
|
* Handbook of Applied Cryptography algorithm 3.36
|
||||||
|
*/
|
||||||
|
i = mpz_mod_ui(t1, prime, 4); /* t1 is ignored here */
|
||||||
|
if (i == 3) {
|
||||||
|
mpz_add_ui(t1, prime, 1);
|
||||||
|
mpz_fdiv_q_2exp(t1, t1, 2);
|
||||||
|
mpz_powm(ret, n, t1, prime);
|
||||||
|
res = CRYPT_OK;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* NOW: Tonelli-Shanks algorithm */
|
||||||
|
|
||||||
|
/* factor out powers of 2 from prime-1, defining Q and S as: prime-1 = Q*2^S */
|
||||||
|
mpz_set(Q, prime);
|
||||||
|
mpz_sub_ui(Q, Q, 1);
|
||||||
|
/* Q = prime - 1 */
|
||||||
|
mpz_set_ui(S, 0);
|
||||||
|
/* S = 0 */
|
||||||
|
while (mpz_even_p(Q)) {
|
||||||
|
mpz_fdiv_q_2exp(Q, Q, 1);
|
||||||
|
/* Q = Q / 2 */
|
||||||
|
mpz_add_ui(S, S, 1);
|
||||||
|
/* S = S + 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* find a Z such that the Legendre symbol (Z|prime) == -1 */
|
||||||
|
mpz_set_ui(Z, 2);
|
||||||
|
/* Z = 2 */
|
||||||
|
while(1) {
|
||||||
|
legendre = mpz_legendre(Z, prime);
|
||||||
|
if (legendre == -1) break;
|
||||||
|
mpz_add_ui(Z, Z, 1);
|
||||||
|
/* Z = Z + 1 */
|
||||||
|
}
|
||||||
|
|
||||||
|
mpz_powm(C, Z, Q, prime);
|
||||||
|
/* C = Z ^ Q mod prime */
|
||||||
|
mpz_add_ui(t1, Q, 1);
|
||||||
|
mpz_fdiv_q_2exp(t1, t1, 1);
|
||||||
|
/* t1 = (Q + 1) / 2 */
|
||||||
|
mpz_powm(R, n, t1, prime);
|
||||||
|
/* R = n ^ ((Q + 1) / 2) mod prime */
|
||||||
|
mpz_powm(T, n, Q, prime);
|
||||||
|
/* T = n ^ Q mod prime */
|
||||||
|
mpz_set(M, S);
|
||||||
|
/* M = S */
|
||||||
|
mpz_set_ui(two, 2);
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
mpz_set(t1, T);
|
||||||
|
i = 0;
|
||||||
|
while (1) {
|
||||||
|
if (mpz_cmp_ui(((__mpz_struct *)t1), 1) == 0) break;
|
||||||
|
mpz_powm(t1, t1, two, prime);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if (i == 0) {
|
||||||
|
mpz_set(ret, R);
|
||||||
|
res = CRYPT_OK;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
mpz_sub_ui(t1, M, i);
|
||||||
|
mpz_sub_ui(t1, t1, 1);
|
||||||
|
mpz_powm(t1, two, t1, prime);
|
||||||
|
/* t1 = 2 ^ (M - i - 1) */
|
||||||
|
mpz_powm(t1, C, t1, prime);
|
||||||
|
/* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
|
||||||
|
mpz_mul(C, t1, t1);
|
||||||
|
mpz_mod(C, C, prime);
|
||||||
|
/* C = (t1 * t1) mod prime */
|
||||||
|
mpz_mul(R, R, t1);
|
||||||
|
mpz_mod(R, R, prime);
|
||||||
|
/* R = (R * t1) mod prime */
|
||||||
|
mpz_mul(T, T, C);
|
||||||
|
mpz_mod(T, T, prime);
|
||||||
|
/* T = (T * C) mod prime */
|
||||||
|
mpz_set_ui(M, i);
|
||||||
|
/* M = i */
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
mpz_clear(t1); mpz_clear(C); mpz_clear(Q);
|
||||||
|
mpz_clear(S); mpz_clear(Z); mpz_clear(M);
|
||||||
|
mpz_clear(T); mpz_clear(R); mpz_clear(two);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/* div */
|
/* div */
|
||||||
static int divide(void *a, void *b, void *c, void *d)
|
static int divide(void *a, void *b, void *c, void *d)
|
||||||
{
|
{
|
||||||
@ -493,6 +606,7 @@ const ltc_math_descriptor gmp_desc = {
|
|||||||
&mul,
|
&mul,
|
||||||
&muli,
|
&muli,
|
||||||
&sqr,
|
&sqr,
|
||||||
|
&sqrtmod_prime,
|
||||||
÷,
|
÷,
|
||||||
&div_2,
|
&div_2,
|
||||||
&modi,
|
&modi,
|
||||||
|
@ -257,6 +257,15 @@ static int sqr(void *a, void *b)
|
|||||||
return mpi_to_ltc_error(mp_sqr(a, b));
|
return mpi_to_ltc_error(mp_sqr(a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sqrtmod_prime */
|
||||||
|
static int sqrtmod_prime(void *a, void *b, void *c)
|
||||||
|
{
|
||||||
|
LTC_ARGCHK(a != NULL);
|
||||||
|
LTC_ARGCHK(b != NULL);
|
||||||
|
LTC_ARGCHK(c != NULL);
|
||||||
|
return mpi_to_ltc_error(mp_sqrtmod_prime(a, b, c));
|
||||||
|
}
|
||||||
|
|
||||||
/* div */
|
/* div */
|
||||||
static int divide(void *a, void *b, void *c, void *d)
|
static int divide(void *a, void *b, void *c, void *d)
|
||||||
{
|
{
|
||||||
@ -452,6 +461,7 @@ const ltc_math_descriptor ltm_desc = {
|
|||||||
&mul,
|
&mul,
|
||||||
&muli,
|
&muli,
|
||||||
&sqr,
|
&sqr,
|
||||||
|
&sqrtmod_prime,
|
||||||
÷,
|
÷,
|
||||||
&div_2,
|
&div_2,
|
||||||
&modi,
|
&modi,
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
#ifdef LTC_MDSA
|
#if defined(LTC_MDSA) || defined(LTC_MECC)
|
||||||
/**
|
/**
|
||||||
Generate a random number N with given bitlength (note: MSB can be 0)
|
Generate a random number N with given bitlength (note: MSB can be 0)
|
||||||
*/
|
*/
|
||||||
|
@ -265,6 +265,8 @@ static int sqr(void *a, void *b)
|
|||||||
return CRYPT_OK;
|
return CRYPT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* sqrtmod_prime - NOT SUPPORTED */
|
||||||
|
|
||||||
/* div */
|
/* div */
|
||||||
static int divide(void *a, void *b, void *c, void *d)
|
static int divide(void *a, void *b, void *c, void *d)
|
||||||
{
|
{
|
||||||
@ -424,10 +426,11 @@ static int isprime(void *a, int b, int *c)
|
|||||||
|
|
||||||
#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL)
|
#if defined(LTC_MECC) && defined(LTC_MECC_ACCEL)
|
||||||
|
|
||||||
static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *Mp)
|
static int tfm_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *Mp)
|
||||||
{
|
{
|
||||||
fp_int t1, t2;
|
fp_int t1, t2;
|
||||||
fp_digit mp;
|
fp_digit mp;
|
||||||
|
int err, inf;
|
||||||
|
|
||||||
LTC_ARGCHK(P != NULL);
|
LTC_ARGCHK(P != NULL);
|
||||||
LTC_ARGCHK(R != NULL);
|
LTC_ARGCHK(R != NULL);
|
||||||
@ -445,6 +448,15 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
|
|||||||
fp_copy(P->z, R->z);
|
fp_copy(P->z, R->z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* if P is point at infinity >> Result = point at infinity */
|
||||||
|
ltc_mp.set_int(R->x, 1);
|
||||||
|
ltc_mp.set_int(R->y, 1);
|
||||||
|
ltc_mp.set_int(R->z, 0);
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* t1 = Z * Z */
|
/* t1 = Z * Z */
|
||||||
fp_sqr(R->z, &t1);
|
fp_sqr(R->z, &t1);
|
||||||
fp_montgomery_reduce(&t1, modulus, mp);
|
fp_montgomery_reduce(&t1, modulus, mp);
|
||||||
@ -457,28 +469,56 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
|
|||||||
fp_sub(R->z, modulus, R->z);
|
fp_sub(R->z, modulus, R->z);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* &t2 = X - T1 */
|
if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
|
||||||
fp_sub(R->x, &t1, &t2);
|
/* T2 = X - T1 */
|
||||||
if (fp_cmp_d(&t2, 0) == FP_LT) {
|
fp_sub(R->x, &t1, &t2);
|
||||||
fp_add(&t2, modulus, &t2);
|
if (fp_cmp_d(&t2, 0) == LTC_MP_LT) {
|
||||||
|
fp_add(&t2, modulus, &t2);
|
||||||
|
}
|
||||||
|
/* T1 = X + T1 */
|
||||||
|
fp_add(&t1, R->x, &t1);
|
||||||
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
|
fp_sub(&t1, modulus, &t1);
|
||||||
|
}
|
||||||
|
/* T2 = T1 * T2 */
|
||||||
|
fp_mul(&t1, &t2, &t2);
|
||||||
|
fp_montgomery_reduce(&t2, modulus, mp);
|
||||||
|
/* T1 = 2T2 */
|
||||||
|
fp_add(&t2, &t2, &t1);
|
||||||
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
|
fp_sub(&t1, modulus, &t1);
|
||||||
|
}
|
||||||
|
/* T1 = T1 + T2 */
|
||||||
|
fp_add(&t1, &t2, &t1);
|
||||||
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
|
fp_sub(&t1, modulus, &t1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* T1 = X + T1 */
|
else {
|
||||||
fp_add(&t1, R->x, &t1);
|
/* T2 = T1 * T1 */
|
||||||
if (fp_cmp(&t1, modulus) != FP_LT) {
|
fp_sqr(&t1, &t2);
|
||||||
fp_sub(&t1, modulus, &t1);
|
fp_montgomery_reduce(&t2, modulus, mp);
|
||||||
}
|
/* T1 = T2 * a */
|
||||||
/* T2 = T1 * T2 */
|
fp_mul(&t2, ma, &t1);
|
||||||
fp_mul(&t1, &t2, &t2);
|
fp_montgomery_reduce(&t1, modulus, mp);
|
||||||
fp_montgomery_reduce(&t2, modulus, mp);
|
/* T2 = X * X */
|
||||||
/* T1 = 2T2 */
|
fp_sqr(R->x, &t2);
|
||||||
fp_add(&t2, &t2, &t1);
|
fp_montgomery_reduce(&t2, modulus, mp);
|
||||||
if (fp_cmp(&t1, modulus) != FP_LT) {
|
/* T1 = T1 + T2 */
|
||||||
fp_sub(&t1, modulus, &t1);
|
fp_add(&t1, &t2, &t1);
|
||||||
}
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
/* T1 = T1 + T2 */
|
fp_sub(&t1, modulus, &t1);
|
||||||
fp_add(&t1, &t2, &t1);
|
}
|
||||||
if (fp_cmp(&t1, modulus) != FP_LT) {
|
/* T1 = T1 + T2 */
|
||||||
fp_sub(&t1, modulus, &t1);
|
fp_add(&t1, &t2, &t1);
|
||||||
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
|
fp_sub(&t1, modulus, &t1);
|
||||||
|
}
|
||||||
|
/* T1 = T1 + T2 */
|
||||||
|
fp_add(&t1, &t2, &t1);
|
||||||
|
if (fp_cmp(&t1, modulus) != FP_LT) {
|
||||||
|
fp_sub(&t1, modulus, &t1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Y = 2Y */
|
/* Y = 2Y */
|
||||||
@ -541,10 +581,11 @@ static int tfm_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulu
|
|||||||
@param Mp The "b" value from montgomery_setup()
|
@param Mp The "b" value from montgomery_setup()
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *Mp)
|
static int tfm_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *Mp)
|
||||||
{
|
{
|
||||||
fp_int t1, t2, x, y, z;
|
fp_int t1, t2, x, y, z;
|
||||||
fp_digit mp;
|
fp_digit mp;
|
||||||
|
int err, inf;
|
||||||
|
|
||||||
LTC_ARGCHK(P != NULL);
|
LTC_ARGCHK(P != NULL);
|
||||||
LTC_ARGCHK(Q != NULL);
|
LTC_ARGCHK(Q != NULL);
|
||||||
@ -560,12 +601,30 @@ static int tfm_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R
|
|||||||
fp_init(&y);
|
fp_init(&y);
|
||||||
fp_init(&z);
|
fp_init(&z);
|
||||||
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* P is point at infinity >> Result = Q */
|
||||||
|
ltc_mp.copy(Q->x, R->x);
|
||||||
|
ltc_mp.copy(Q->y, R->y);
|
||||||
|
ltc_mp.copy(Q->z, R->z);
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* Q is point at infinity >> Result = P */
|
||||||
|
ltc_mp.copy(P->x, R->x);
|
||||||
|
ltc_mp.copy(P->y, R->y);
|
||||||
|
ltc_mp.copy(P->z, R->z);
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* should we dbl instead? */
|
/* should we dbl instead? */
|
||||||
fp_sub(modulus, Q->y, &t1);
|
fp_sub(modulus, Q->y, &t1);
|
||||||
if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
|
if ( (fp_cmp(P->x, Q->x) == FP_EQ) &&
|
||||||
(Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
|
(Q->z != NULL && fp_cmp(P->z, Q->z) == FP_EQ) &&
|
||||||
(fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
|
(fp_cmp(P->y, Q->y) == FP_EQ || fp_cmp(P->y, &t1) == FP_EQ)) {
|
||||||
return tfm_ecc_projective_dbl_point(P, R, modulus, Mp);
|
return tfm_ecc_projective_dbl_point(P, R, ma, modulus, Mp);
|
||||||
}
|
}
|
||||||
|
|
||||||
fp_copy(P->x, &x);
|
fp_copy(P->x, &x);
|
||||||
@ -741,6 +800,7 @@ const ltc_math_descriptor tfm_desc = {
|
|||||||
&mul,
|
&mul,
|
||||||
&muli,
|
&muli,
|
||||||
&sqr,
|
&sqr,
|
||||||
|
NULL, /* TODO: &sqrtmod_prime */
|
||||||
÷,
|
÷,
|
||||||
&div_2,
|
&div_2,
|
||||||
&modi,
|
&modi,
|
||||||
|
@ -245,7 +245,7 @@ static const crypt_size _crypt_sizes[] = {
|
|||||||
_SZ_STRINGIFY_T(dh_key),
|
_SZ_STRINGIFY_T(dh_key),
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_MECC
|
#ifdef LTC_MECC
|
||||||
_SZ_STRINGIFY_T(ltc_ecc_set_type),
|
_SZ_STRINGIFY_T(ltc_ecc_curve),
|
||||||
_SZ_STRINGIFY_T(ecc_point),
|
_SZ_STRINGIFY_T(ecc_point),
|
||||||
_SZ_STRINGIFY_T(ecc_key),
|
_SZ_STRINGIFY_T(ecc_key),
|
||||||
#endif
|
#endif
|
||||||
|
82
src/misc/pk_oid_str.c
Normal file
82
src/misc/pk_oid_str.c
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
int pk_oid_str_to_num(const char *OID, unsigned long *oid, unsigned long *oidlen)
|
||||||
|
{
|
||||||
|
unsigned long i, j, limit;
|
||||||
|
|
||||||
|
LTC_ARGCHK(oid != NULL);
|
||||||
|
LTC_ARGCHK(oidlen != NULL);
|
||||||
|
|
||||||
|
limit = *oidlen;
|
||||||
|
*oidlen = 0; /* make sure that we return zero oidlen on error */
|
||||||
|
for (i = 0; i < limit; i++) oid[i] = 0;
|
||||||
|
|
||||||
|
if ((OID == NULL) || (strlen(OID) == 0)) return CRYPT_OK;
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < strlen(OID); i++) {
|
||||||
|
if (OID[i] == '.') {
|
||||||
|
if (++j >= limit) return CRYPT_ERROR;
|
||||||
|
}
|
||||||
|
else if ((OID[i] >= '0') && (OID[i] <= '9')) {
|
||||||
|
oid[j] = oid[j] * 10 + (OID[i] - '0');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CRYPT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == 0) return CRYPT_ERROR;
|
||||||
|
*oidlen = j + 1;
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int pk_oid_num_to_str(const unsigned long *oid, unsigned long oidlen, char *OID, unsigned long *outlen)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned long j, k;
|
||||||
|
char tmp[256] = { 0 };
|
||||||
|
unsigned long tmpsz = sizeof(tmp);
|
||||||
|
|
||||||
|
LTC_ARGCHK(oid != NULL);
|
||||||
|
LTC_ARGCHK(OID != NULL);
|
||||||
|
LTC_ARGCHK(outlen != NULL);
|
||||||
|
|
||||||
|
for (i = oidlen - 1, k = 0; i >= 0; i--) {
|
||||||
|
j = oid[i];
|
||||||
|
if (j == 0) {
|
||||||
|
tmp[k] = '0';
|
||||||
|
if (++k >= tmpsz) return CRYPT_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
while (j > 0) {
|
||||||
|
tmp[k] = '0' + (j % 10);
|
||||||
|
if (++k >= tmpsz) return CRYPT_ERROR;
|
||||||
|
j /= 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i > 0) {
|
||||||
|
tmp[k] = '.';
|
||||||
|
if (++k >= tmpsz) return CRYPT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*outlen < k + 1) {
|
||||||
|
*outlen = k + 1;
|
||||||
|
return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
for (j = 0; j < k; j++) OID[j] = tmp[k - j - 1];
|
||||||
|
OID[k] = '\0';
|
||||||
|
*outlen = k; /* the length without terminating NUL byte */
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
466
src/pk/ecc/ecc.c
466
src/pk/ecc/ecc.c
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,99 +16,424 @@
|
|||||||
|
|
||||||
#ifdef LTC_MECC
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
/* This holds the key settings. ***MUST*** be organized by size from smallest to largest. */
|
/* This array holds the curve parameters.
|
||||||
const ltc_ecc_set_type ltc_ecc_sets[] = {
|
* Curves (prime field only) are taken from:
|
||||||
#ifdef LTC_ECC112
|
* - http://www.secg.org/collateral/sec2_final.pdf (named: SECP*)
|
||||||
|
* - http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf (named: NISTP*)
|
||||||
|
* - ANS X9.62 (named: PRIMEP*)
|
||||||
|
* - http://www.ecc-brainpool.org/download/Domain-parameters.pdf (named: BRAINPOOLP*)
|
||||||
|
*/
|
||||||
|
const ltc_ecc_curve ltc_ecc_curves[] = {
|
||||||
|
#ifdef LTC_ECC_SECP112R1
|
||||||
{
|
{
|
||||||
14,
|
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
|
||||||
"SECP112R1",
|
/* A */ "DB7C2ABF62E35E668076BEAD2088",
|
||||||
"DB7C2ABF62E35E668076BEAD208B",
|
/* B */ "659EF8BA043916EEDE8911702B22",
|
||||||
"659EF8BA043916EEDE8911702B22",
|
/* order */ "DB7C2ABF62E35E7628DFAC6561C5",
|
||||||
"DB7C2ABF62E35E7628DFAC6561C5",
|
/* Gx */ "09487239995A5EE76B55F9C2F098",
|
||||||
"09487239995A5EE76B55F9C2F098",
|
/* Gy */ "A89CE5AF8724C0A23E0E0FF77500",
|
||||||
"A89CE5AF8724C0A23E0E0FF77500"
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.6"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC128
|
#ifdef LTC_ECC_SECP112R2
|
||||||
{
|
{
|
||||||
16,
|
/* prime */ "DB7C2ABF62E35E668076BEAD208B",
|
||||||
"SECP128R1",
|
/* A */ "6127C24C05F38A0AAAF65C0EF02C",
|
||||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
/* B */ "51DEF1815DB5ED74FCC34C85D709",
|
||||||
"E87579C11079F43DD824993C2CEE5ED3",
|
/* order */ "36DF0AAFD8B8D7597CA10520D04B",
|
||||||
"FFFFFFFE0000000075A30D1B9038A115",
|
/* Gx */ "4BA30AB5E892B4E1649DD0928643",
|
||||||
"161FF7528B899B2D0C28607CA52C5B86",
|
/* Gy */ "ADCD46F5882E3747DEF36E956E97",
|
||||||
"CF5AC8395BAFEB13C02DA292DDED7A83",
|
/* cofactor */ 4,
|
||||||
|
/* OID */ "1.3.132.0.7"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC160
|
#ifdef LTC_ECC_SECP128R1
|
||||||
{
|
{
|
||||||
20,
|
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
"SECP160R1",
|
/* A */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
/* B */ "E87579C11079F43DD824993C2CEE5ED3",
|
||||||
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
/* order */ "FFFFFFFE0000000075A30D1B9038A115",
|
||||||
"0100000000000000000001F4C8F927AED3CA752257",
|
/* Gx */ "161FF7528B899B2D0C28607CA52C5B86",
|
||||||
"4A96B5688EF573284664698968C38BB913CBFC82",
|
/* Gy */ "CF5AC8395BAFEB13C02DA292DDED7A83",
|
||||||
"23A628553168947D59DCC912042351377AC5FB32",
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.28"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC192
|
#ifdef LTC_ECC_SECP128R2
|
||||||
{
|
{
|
||||||
24,
|
/* prime */ "FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
"ECC-192",
|
/* A */ "D6031998D1B3BBFEBF59CC9BBFF9AEE1",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
/* B */ "5EEEFCA380D02919DC2C6558BB6D8A5D",
|
||||||
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
/* order */ "3FFFFFFF7FFFFFFFBE0024720613B5A3",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
/* Gx */ "7B6AA5D85E572983E6FB32A7CDEBC140",
|
||||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
/* Gy */ "27B6916A894D3AEE7106FE805FC34B44",
|
||||||
"7192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
/* cofactor */ 4,
|
||||||
|
/* OID */ "1.3.132.0.29"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC224
|
#ifdef LTC_ECC_SECP160R1
|
||||||
{
|
{
|
||||||
28,
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
||||||
"ECC-224",
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
/* B */ "1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
||||||
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
/* order */ "0100000000000000000001F4C8F927AED3CA752257",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
/* Gx */ "4A96B5688EF573284664698968C38BB913CBFC82",
|
||||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
/* Gy */ "23A628553168947D59DCC912042351377AC5FB32",
|
||||||
"BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.8"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC256
|
#ifdef LTC_ECC_SECP160R2
|
||||||
{
|
{
|
||||||
32,
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||||
"ECC-256",
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC70",
|
||||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
/* B */ "B4E134D3FB59EB8BAB57274904664D5AF50388BA",
|
||||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
/* order */ "0100000000000000000000351EE786A818F3A1A16B",
|
||||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
/* Gx */ "52DCB034293A117E1F4FF11B30F7199D3144CE6D",
|
||||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
/* Gy */ "FEAFFEF2E331F296E071FA0DF9982CFEA7D43F2E",
|
||||||
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.30"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC384
|
#ifdef LTC_ECC_SECP160K1
|
||||||
{
|
{
|
||||||
48,
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFAC73",
|
||||||
"ECC-384",
|
/* A */ "0000000000000000000000000000000000000000",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
/* B */ "0000000000000000000000000000000000000007",
|
||||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
/* order */ "0100000000000000000001B8FA16DFAB9ACA16B6B3",
|
||||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
/* Gx */ "3B4C382CE37AA192A4019E763036F4F5DD4D7EBB",
|
||||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
/* Gy */ "938CF935318FDCED6BC28286531733C3F03C4FEE",
|
||||||
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.9"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC521
|
#ifdef LTC_ECC_SECP192R1
|
||||||
{
|
{
|
||||||
66,
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
"ECC-521",
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
/* B */ "64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
||||||
"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
||||||
"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
/* Gx */ "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
||||||
"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
/* Gy */ "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811",
|
||||||
"11839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.1"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V2
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
|
/* B */ "CC22D6DFB95C6B25E49C0D6364A4E5980C393AA21668D953",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFE5FB1A724DC80418648D8DD31",
|
||||||
|
/* Gx */ "EEA2BAE7E1497842F2DE7769CFE9C989C072AD696F48034A",
|
||||||
|
/* Gy */ "6574D11D69B6EC7A672BB82A083DF2F2B0847DE970B2DE15",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.2"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V3
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||||
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||||
|
/* B */ "22123DC2395A05CAA7423DAECCC94760A7D462256BD56916",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFF7A62D031C83F4294F640EC13",
|
||||||
|
/* Gx */ "7D29778100C65A1DA1783716588DCE2B8B4AEE8E228F1896",
|
||||||
|
/* Gy */ "38A90F22637337334B49DCB66A6DC8F9978ACA7648A943B0",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.3"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP192K1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFEE37",
|
||||||
|
/* A */ "000000000000000000000000000000000000000000000000",
|
||||||
|
/* B */ "000000000000000000000000000000000000000000000003",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFE26F2FC170F69466A74DEFD8D",
|
||||||
|
/* Gx */ "DB4FF10EC057E9AE26B07D0280B7F4341DA5D1B1EAE06C7D",
|
||||||
|
/* Gy */ "9B2F2F6D9C5628A7844163D015BE86344082AA88D95E2F9D",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.31"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224R1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
||||||
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
||||||
|
/* B */ "B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
||||||
|
/* Gx */ "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
||||||
|
/* Gy */ "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.33"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224K1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFE56D",
|
||||||
|
/* A */ "00000000000000000000000000000000000000000000000000000000",
|
||||||
|
/* B */ "00000000000000000000000000000000000000000000000000000005",
|
||||||
|
/* order */ "010000000000000000000000000001DCE8D2EC6184CAF0A971769FB1F7",
|
||||||
|
/* Gx */ "A1455B334DF099DF30FC28A169A467E9E47075A90F7E650EB6B7A45C",
|
||||||
|
/* Gy */ "7E089FED7FBA344282CAFBD6F7E319F7C0B0BD59E2CA4BDB556D61A5",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.32"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256R1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
/* A */ "FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
|
/* B */ "5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||||
|
/* order */ "FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||||
|
/* Gx */ "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||||
|
/* Gy */ "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.7"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256K1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F",
|
||||||
|
/* A */ "0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
/* B */ "0000000000000000000000000000000000000000000000000000000000000007",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141",
|
||||||
|
/* Gx */ "79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798",
|
||||||
|
/* Gy */ "483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.10"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP384R1
|
||||||
|
{
|
||||||
|
/* prime */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||||
|
/* A */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||||
|
/* B */ "B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||||
|
/* order */ "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||||
|
/* Gx */ "AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||||
|
/* Gy */ "3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.34"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP521R1
|
||||||
|
{
|
||||||
|
/* prime */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||||
|
/* A */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||||
|
/* B */ "0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||||
|
/* order */ "01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||||
|
/* Gx */ "00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||||
|
/* Gy */ "011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.132.0.35"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V1
|
||||||
|
{
|
||||||
|
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
/* B */ "6B016C3BDCF18941D0D654921475CA71A9DB2FB27D1D37796185C2942C0A",
|
||||||
|
/* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF9E5E9A9F5D9071FBD1522688909D0B",
|
||||||
|
/* Gx */ "0FFA963CDCA8816CCC33B8642BEDF905C3D358573D3F27FBBD3B3CB9AAAF",
|
||||||
|
/* Gy */ "7DEBE8E4E90A5DAE6E4054CA530BA04654B36818CE226B39FCCB7B02F1AE",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.4"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V2
|
||||||
|
{
|
||||||
|
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
/* B */ "617FAB6832576CBBFED50D99F0249C3FEE58B94BA0038C7AE84C8C832F2C",
|
||||||
|
/* order */ "7FFFFFFFFFFFFFFFFFFFFFFF800000CFA7E8594377D414C03821BC582063",
|
||||||
|
/* Gx */ "38AF09D98727705120C921BB5E9E26296A3CDCF2F35757A0EAFD87B830E7",
|
||||||
|
/* Gy */ "5B0125E4DBEA0EC7206DA0FC01D9B081329FB555DE6EF460237DFF8BE4BA",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.5"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V3
|
||||||
|
{
|
||||||
|
/* prime */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFF",
|
||||||
|
/* A */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFFFFFFFF8000000000007FFFFFFFFFFC",
|
||||||
|
/* B */ "255705FA2A306654B1F4CB03D6A750A30C250102D4988717D9BA15AB6D3E",
|
||||||
|
/* order */ "7FFFFFFFFFFFFFFFFFFFFFFF7FFFFF975DEB41B3A6057C3C432146526551",
|
||||||
|
/* Gx */ "6768AE8E18BB92CFCF005C949AA2C6D94853D0E660BBF854B1C9505FE95A",
|
||||||
|
/* Gy */ "1607E6898F390C06BC1D552BAD226F3B6FCFE48B6E818499AF18E3ED6CF3",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.2.840.10045.3.1.6"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP160R1
|
||||||
|
{
|
||||||
|
/* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
|
||||||
|
/* A */ "340E7BE2A280EB74E2BE61BADA745D97E8F7C300",
|
||||||
|
/* B */ "1E589A8595423412134FAA2DBDEC95C8D8675E58",
|
||||||
|
/* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
|
||||||
|
/* Gx */ "BED5AF16EA3F6A4F62938C4631EB5AF7BDBCDBC3",
|
||||||
|
/* Gy */ "1667CB477A1A8EC338F94741669C976316DA6321",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.1"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP192R1
|
||||||
|
{
|
||||||
|
/* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
|
||||||
|
/* A */ "6A91174076B1E0E19C39C031FE8685C1CAE040E5C69A28EF",
|
||||||
|
/* B */ "469A28EF7C28CCA3DC721D044F4496BCCA7EF4146FBF25C9",
|
||||||
|
/* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
|
||||||
|
/* Gx */ "C0A0647EAAB6A48753B033C56CB0F0900A2F5C4853375FD6",
|
||||||
|
/* Gy */ "14B690866ABD5BB88B5F4828C1490002E6773FA2FA299B8F",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.3"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP224R1
|
||||||
|
{
|
||||||
|
/* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
|
||||||
|
/* A */ "68A5E62CA9CE6C1C299803A6C1530B514E182AD8B0042A59CAD29F43",
|
||||||
|
/* B */ "2580F63CCFE44138870713B1A92369E33E2135D266DBB372386C400B",
|
||||||
|
/* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
|
||||||
|
/* Gx */ "0D9029AD2C7E5CF4340823B2A87DC68C9E4CE3174C1E6EFDEE12C07D",
|
||||||
|
/* Gy */ "58AA56F772C0726F24C6B89E4ECDAC24354B9E99CAA3F6D3761402CD",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.5"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP256R1
|
||||||
|
{
|
||||||
|
/* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
||||||
|
/* A */ "7D5A0975FC2C3057EEF67530417AFFE7FB8055C126DC5C6CE94A4B44F330B5D9",
|
||||||
|
/* B */ "26DC5C6CE94A4B44F330B5D9BBD77CBF958416295CF7E1CE6BCCDC18FF8C07B6",
|
||||||
|
/* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
|
||||||
|
/* Gx */ "8BD2AEB9CB7E57CB2C4B482FFC81B7AFB9DE27E1E3BD23C23A4453BD9ACE3262",
|
||||||
|
/* Gy */ "547EF835C3DAC4FD97F8461A14611DC9C27745132DED8E545C1D54C72F046997",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.7"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP320R1
|
||||||
|
{
|
||||||
|
/* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
|
||||||
|
/* A */ "3EE30B568FBAB0F883CCEBD46D3F3BB8A2A73513F5EB79DA66190EB085FFA9F492F375A97D860EB4",
|
||||||
|
/* B */ "520883949DFDBC42D3AD198640688A6FE13F41349554B49ACC31DCCD884539816F5EB4AC8FB1F1A6",
|
||||||
|
/* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
|
||||||
|
/* Gx */ "43BD7E9AFB53D8B85289BCC48EE5BFE6F20137D10A087EB6E7871E2A10A599C710AF8D0D39E20611",
|
||||||
|
/* Gy */ "14FDD05545EC1CC8AB4093247F77275E0743FFED117182EAA9C77877AAAC6AC7D35245D1692E8EE1",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.9"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP384R1
|
||||||
|
{
|
||||||
|
/* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
|
||||||
|
/* A */ "7BC382C63D8C150C3C72080ACE05AFA0C2BEA28E4FB22787139165EFBA91F90F8AA5814A503AD4EB04A8C7DD22CE2826",
|
||||||
|
/* B */ "04A8C7DD22CE28268B39B55416F0447C2FB77DE107DCD2A62E880EA53EEB62D57CB4390295DBC9943AB78696FA504C11",
|
||||||
|
/* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
|
||||||
|
/* Gx */ "1D1C64F068CF45FFA2A63A81B7C13F6B8847A3E77EF14FE3DB7FCAFE0CBD10E8E826E03436D646AAEF87B2E247D4AF1E",
|
||||||
|
/* Gy */ "8ABE1D7520F9C2A45CB1EB8E95CFD55262B70B29FEEC5864E19C054FF99129280E4646217791811142820341263C5315",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.11"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP512R1
|
||||||
|
{
|
||||||
|
/* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
|
||||||
|
/* A */ "7830A3318B603B89E2327145AC234CC594CBDD8D3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CA",
|
||||||
|
/* B */ "3DF91610A83441CAEA9863BC2DED5D5AA8253AA10A2EF1C98B9AC8B57F1117A72BF2C7B9E7C1AC4D77FC94CADC083E67984050B75EBAE5DD2809BD638016F723",
|
||||||
|
/* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
|
||||||
|
/* Gx */ "81AEE4BDD82ED9645A21322E9C4C6A9385ED9F70B5D916C1B43B62EEF4D0098EFF3B1F78E2D0D48D50D1687B93B97D5F7C6D5047406A5E688B352209BCB9F822",
|
||||||
|
/* Gy */ "7DDE385D566332ECC0EABFA9CF7822FDF209F70024A57B1AA000C55B881F8111B2DCDE494A5F485E5BCA4BD88A2763AED1CA2B2FA8F0540678CD1E0F3AD80892",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.13"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP160T1
|
||||||
|
{
|
||||||
|
/* prime */ "E95E4A5F737059DC60DFC7AD95B3D8139515620F",
|
||||||
|
/* A */ "E95E4A5F737059DC60DFC7AD95B3D8139515620C",
|
||||||
|
/* B */ "7A556B6DAE535B7B51ED2C4D7DAA7A0B5C55F380",
|
||||||
|
/* order */ "E95E4A5F737059DC60DF5991D45029409E60FC09",
|
||||||
|
/* Gx */ "B199B13B9B34EFC1397E64BAEB05ACC265FF2378",
|
||||||
|
/* Gy */ "ADD6718B7C7C1961F0991B842443772152C9E0AD",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.2"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP192T1
|
||||||
|
{
|
||||||
|
/* prime */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86297",
|
||||||
|
/* A */ "C302F41D932A36CDA7A3463093D18DB78FCE476DE1A86294",
|
||||||
|
/* B */ "13D56FFAEC78681E68F9DEB43B35BEC2FB68542E27897B79",
|
||||||
|
/* order */ "C302F41D932A36CDA7A3462F9E9E916B5BE8F1029AC4ACC1",
|
||||||
|
/* Gx */ "3AE9E58C82F63C30282E1FE7BBF43FA72C446AF6F4618129",
|
||||||
|
/* Gy */ "097E2C5667C2223A902AB5CA449D0084B7E5B3DE7CCC01C9",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.4"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP224T1
|
||||||
|
{
|
||||||
|
/* prime */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FF",
|
||||||
|
/* A */ "D7C134AA264366862A18302575D1D787B09F075797DA89F57EC8C0FC",
|
||||||
|
/* B */ "4B337D934104CD7BEF271BF60CED1ED20DA14C08B3BB64F18A60888D",
|
||||||
|
/* order */ "D7C134AA264366862A18302575D0FB98D116BC4B6DDEBCA3A5A7939F",
|
||||||
|
/* Gx */ "6AB1E344CE25FF3896424E7FFE14762ECB49F8928AC0C76029B4D580",
|
||||||
|
/* Gy */ "0374E9F5143E568CD23F3F4D7C0D4B1E41C8CC0D1C6ABD5F1A46DB4C",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.6"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP256T1
|
||||||
|
{
|
||||||
|
/* prime */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5377",
|
||||||
|
/* A */ "A9FB57DBA1EEA9BC3E660A909D838D726E3BF623D52620282013481D1F6E5374",
|
||||||
|
/* B */ "662C61C430D84EA4FE66A7733D0B76B7BF93EBC4AF2F49256AE58101FEE92B04",
|
||||||
|
/* order */ "A9FB57DBA1EEA9BC3E660A909D838D718C397AA3B561A6F7901E0E82974856A7",
|
||||||
|
/* Gx */ "A3E8EB3CC1CFE7B7732213B23A656149AFA142C47AAFBC2B79A191562E1305F4",
|
||||||
|
/* Gy */ "2D996C823439C56D7F7B22E14644417E69BCB6DE39D027001DABE8F35B25C9BE",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.8"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP320T1
|
||||||
|
{
|
||||||
|
/* prime */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E27",
|
||||||
|
/* A */ "D35E472036BC4FB7E13C785ED201E065F98FCFA6F6F40DEF4F92B9EC7893EC28FCD412B1F1B32E24",
|
||||||
|
/* B */ "A7F561E038EB1ED560B3D147DB782013064C19F27ED27C6780AAF77FB8A547CEB5B4FEF422340353",
|
||||||
|
/* order */ "D35E472036BC4FB7E13C785ED201E065F98FCFA5B68F12A32D482EC7EE8658E98691555B44C59311",
|
||||||
|
/* Gx */ "925BE9FB01AFC6FB4D3E7D4990010F813408AB106C4F09CB7EE07868CC136FFF3357F624A21BED52",
|
||||||
|
/* Gy */ "63BA3A7A27483EBF6671DBEF7ABB30EBEE084E58A0B077AD42A5A0989D1EE71B1B9BC0455FB0D2C3",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.10"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP384T1
|
||||||
|
{
|
||||||
|
/* prime */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC53",
|
||||||
|
/* A */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B412B1DA197FB71123ACD3A729901D1A71874700133107EC50",
|
||||||
|
/* B */ "7F519EADA7BDA81BD826DBA647910F8C4B9346ED8CCDC64E4B1ABD11756DCE1D2074AA263B88805CED70355A33B471EE",
|
||||||
|
/* order */ "8CB91E82A3386D280F5D6F7E50E641DF152F7109ED5456B31F166E6CAC0425A7CF3AB6AF6B7FC3103B883202E9046565",
|
||||||
|
/* Gx */ "18DE98B02DB9A306F2AFCD7235F72A819B80AB12EBD653172476FECD462AABFFC4FF191B946A5F54D8D0AA2F418808CC",
|
||||||
|
/* Gy */ "25AB056962D30651A114AFD2755AD336747F93475B7A1FCA3B88F2B6A208CCFE469408584DC2B2912675BF5B9E582928",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.12"
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP512T1
|
||||||
|
{
|
||||||
|
/* prime */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F3",
|
||||||
|
/* A */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA703308717D4D9B009BC66842AECDA12AE6A380E62881FF2F2D82C68528AA6056583A48F0",
|
||||||
|
/* B */ "7CBBBCF9441CFAB76E1890E46884EAE321F70C0BCB4981527897504BEC3E36A62BCDFA2304976540F6450085F2DAE145C22553B465763689180EA2571867423E",
|
||||||
|
/* order */ "AADD9DB8DBE9C48B3FD4E6AE33C9FC07CB308DB3B3C9D20ED6639CCA70330870553E5C414CA92619418661197FAC10471DB1D381085DDADDB58796829CA90069",
|
||||||
|
/* Gx */ "640ECE5C12788717B9C1BA06CBC2A6FEBA85842458C56DDE9DB1758D39C0313D82BA51735CDB3EA499AA77A7D6943A64F7A3F25FE26F06B51BAA2696FA9035DA",
|
||||||
|
/* Gy */ "5B534BD595F5AF0FA2C892376C84ACE1BB4E3019B71634C01131159CAE03CEE9D9932184BEEF216BD71DF2DADF86A627306ECFF96DBB8BACE198B61E00F8B332",
|
||||||
|
/* cofactor */ 1,
|
||||||
|
/* OID */ "1.3.36.3.3.2.8.1.1.14"
|
||||||
},
|
},
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
0,
|
NULL, NULL, NULL, NULL, NULL, NULL, 0, NULL
|
||||||
NULL, NULL, NULL, NULL, NULL, NULL
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,47 +22,9 @@
|
|||||||
@param outlen [in/out] Length of destination and final output size
|
@param outlen [in/out] Length of destination and final output size
|
||||||
Return CRYPT_OK on success
|
Return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ecc_ansi_x963_export(ecc_key *key, unsigned char *out, unsigned long *outlen)
|
int ecc_ansi_x963_export(const ecc_key *key, unsigned char *out, unsigned long *outlen)
|
||||||
{
|
{
|
||||||
unsigned char buf[ECC_BUF_SIZE];
|
return ecc_get_key(out, outlen, PK_PUBLIC, key);
|
||||||
unsigned long numlen, xlen, ylen;
|
|
||||||
|
|
||||||
LTC_ARGCHK(key != NULL);
|
|
||||||
LTC_ARGCHK(outlen != NULL);
|
|
||||||
|
|
||||||
if (ltc_ecc_is_valid_idx(key->idx) == 0) {
|
|
||||||
return CRYPT_INVALID_ARG;
|
|
||||||
}
|
|
||||||
numlen = key->dp->size;
|
|
||||||
xlen = mp_unsigned_bin_size(key->pubkey.x);
|
|
||||||
ylen = mp_unsigned_bin_size(key->pubkey.y);
|
|
||||||
|
|
||||||
if (xlen > numlen || ylen > numlen || sizeof(buf) < numlen) {
|
|
||||||
return CRYPT_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*outlen < (1 + 2*numlen)) {
|
|
||||||
*outlen = 1 + 2*numlen;
|
|
||||||
return CRYPT_BUFFER_OVERFLOW;
|
|
||||||
}
|
|
||||||
|
|
||||||
LTC_ARGCHK(out != NULL);
|
|
||||||
|
|
||||||
/* store byte 0x04 */
|
|
||||||
out[0] = 0x04;
|
|
||||||
|
|
||||||
/* pad and store x */
|
|
||||||
zeromem(buf, sizeof(buf));
|
|
||||||
mp_to_unsigned_bin(key->pubkey.x, buf + (numlen - xlen));
|
|
||||||
XMEMCPY(out+1, buf, numlen);
|
|
||||||
|
|
||||||
/* pad and store y */
|
|
||||||
zeromem(buf, sizeof(buf));
|
|
||||||
mp_to_unsigned_bin(key->pubkey.y, buf + (numlen - ylen));
|
|
||||||
XMEMCPY(out+1+numlen, buf, numlen);
|
|
||||||
|
|
||||||
*outlen = 1 + 2*numlen;
|
|
||||||
return CRYPT_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,9 +26,9 @@ int ecc_ansi_x963_import(const unsigned char *in, unsigned long inlen, ecc_key *
|
|||||||
return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
|
return ecc_ansi_x963_import_ex(in, inlen, key, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, ltc_ecc_set_type *dp)
|
int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu)
|
||||||
{
|
{
|
||||||
int x, err;
|
int err;
|
||||||
|
|
||||||
LTC_ARGCHK(in != NULL);
|
LTC_ARGCHK(in != NULL);
|
||||||
LTC_ARGCHK(key != NULL);
|
LTC_ARGCHK(key != NULL);
|
||||||
@ -43,56 +38,21 @@ int ecc_ansi_x963_import_ex(const unsigned char *in, unsigned long inlen, ecc_ke
|
|||||||
return CRYPT_INVALID_ARG;
|
return CRYPT_INVALID_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* init key */
|
/* initialize key->dp */
|
||||||
if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
|
if (cu == NULL) {
|
||||||
return CRYPT_MEM;
|
/* this case works only for uncompressed public keys */
|
||||||
|
if ((err = ecc_set_dp_by_size((inlen-1)>>1, key)) != CRYPT_OK) { return err; }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* this one works for both compressed / uncompressed pubkeys */
|
||||||
|
if ((err = ecc_set_dp(cu, key)) != CRYPT_OK) { return err; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for 4, 6 or 7 */
|
/* load public key */
|
||||||
if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
|
if ((err = ecc_set_key((unsigned char *)in, inlen, PK_PUBLIC, key)) != CRYPT_OK) { return err; }
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read data */
|
|
||||||
if ((err = mp_read_unsigned_bin(key->pubkey.x, (unsigned char *)in+1, (inlen-1)>>1)) != CRYPT_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = mp_read_unsigned_bin(key->pubkey.y, (unsigned char *)in+1+((inlen-1)>>1), (inlen-1)>>1)) != CRYPT_OK) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
if (dp == NULL) {
|
|
||||||
/* determine the idx */
|
|
||||||
for (x = 0; ltc_ecc_sets[x].size != 0; x++) {
|
|
||||||
if ((unsigned)ltc_ecc_sets[x].size >= ((inlen-1)>>1)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ltc_ecc_sets[x].size == 0) {
|
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
/* set the idx */
|
|
||||||
key->idx = x;
|
|
||||||
key->dp = <c_ecc_sets[x];
|
|
||||||
} else {
|
|
||||||
if (((inlen-1)>>1) != (unsigned long) dp->size) {
|
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
key->idx = -1;
|
|
||||||
key->dp = dp;
|
|
||||||
}
|
|
||||||
key->type = PK_PUBLIC;
|
|
||||||
|
|
||||||
/* we're done */
|
/* we're done */
|
||||||
return CRYPT_OK;
|
return CRYPT_OK;
|
||||||
error:
|
|
||||||
mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +27,7 @@
|
|||||||
*/
|
*/
|
||||||
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
ecc_key *key)
|
const ecc_key *key)
|
||||||
{
|
{
|
||||||
unsigned char *ecc_shared, *skey, *pub_expt;
|
unsigned char *ecc_shared, *skey, *pub_expt;
|
||||||
unsigned long x, y;
|
unsigned long x, y;
|
||||||
@ -90,9 +85,8 @@ int ecc_decrypt_key(const unsigned char *in, unsigned long inlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* import ECC key from packet */
|
/* import ECC key from packet */
|
||||||
if ((err = ecc_import(decode[1].data, decode[1].size, &pubkey)) != CRYPT_OK) {
|
if ((err = ecc_copy_dp(key, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
goto LBL_ERR;
|
if ((err = ecc_set_key(decode[1].data, decode[1].size, PK_PUBLIC, &pubkey)) != CRYPT_OK) { goto LBL_ERR; }
|
||||||
}
|
|
||||||
|
|
||||||
/* make shared key */
|
/* make shared key */
|
||||||
x = ECC_BUF_SIZE;
|
x = ECC_BUF_SIZE;
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +31,7 @@
|
|||||||
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, int hash,
|
prng_state *prng, int wprng, int hash,
|
||||||
ecc_key *key)
|
const ecc_key *key)
|
||||||
{
|
{
|
||||||
unsigned char *pub_expt, *ecc_shared, *skey;
|
unsigned char *pub_expt, *ecc_shared, *skey;
|
||||||
ecc_key pubkey;
|
ecc_key pubkey;
|
||||||
@ -48,11 +43,6 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
|||||||
LTC_ARGCHK(outlen != NULL);
|
LTC_ARGCHK(outlen != NULL);
|
||||||
LTC_ARGCHK(key != NULL);
|
LTC_ARGCHK(key != NULL);
|
||||||
|
|
||||||
/* check that wprng/cipher/hash are not invalid */
|
|
||||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
if ((err = hash_is_valid(hash)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
@ -62,9 +52,8 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* make a random key and export the public copy */
|
/* make a random key and export the public copy */
|
||||||
if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
|
if ((err = ecc_copy_dp(key, &pubkey)) != CRYPT_OK) { return err; }
|
||||||
return err;
|
if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { return err; }
|
||||||
}
|
|
||||||
|
|
||||||
pub_expt = XMALLOC(ECC_BUF_SIZE);
|
pub_expt = XMALLOC(ECC_BUF_SIZE);
|
||||||
ecc_shared = XMALLOC(ECC_BUF_SIZE);
|
ecc_shared = XMALLOC(ECC_BUF_SIZE);
|
||||||
@ -84,7 +73,14 @@ int ecc_encrypt_key(const unsigned char *in, unsigned long inlen,
|
|||||||
}
|
}
|
||||||
|
|
||||||
pubkeysize = ECC_BUF_SIZE;
|
pubkeysize = ECC_BUF_SIZE;
|
||||||
if ((err = ecc_export(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey)) != CRYPT_OK) {
|
if (ltc_mp.sqrtmod_prime != NULL) {
|
||||||
|
/* PK_COMPRESSED requires sqrtmod_prime */
|
||||||
|
err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC|PK_COMPRESSED, &pubkey);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = ecc_get_key(pub_expt, &pubkeysize, PK_PUBLIC, &pubkey);
|
||||||
|
}
|
||||||
|
if (err != CRYPT_OK) {
|
||||||
ecc_free(&pubkey);
|
ecc_free(&pubkey);
|
||||||
goto LBL_ERR;
|
goto LBL_ERR;
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,7 +24,7 @@
|
|||||||
@param key The key to export
|
@param key The key to export
|
||||||
@return CRYPT_OK if successful
|
@return CRYPT_OK if successful
|
||||||
*/
|
*/
|
||||||
int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key)
|
int ecc_export(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
unsigned char flags[1];
|
unsigned char flags[1];
|
||||||
@ -44,12 +39,8 @@ int ecc_export(unsigned char *out, unsigned long *outlen, int type, ecc_key *key
|
|||||||
return CRYPT_PK_TYPE_MISMATCH;
|
return CRYPT_PK_TYPE_MISMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ltc_ecc_is_valid_idx(key->idx) == 0) {
|
|
||||||
return CRYPT_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we store the NIST byte size */
|
/* we store the NIST byte size */
|
||||||
key_size = key->dp->size;
|
key_size = key->dp.size;
|
||||||
|
|
||||||
if (type == PK_PRIVATE) {
|
if (type == PK_PRIVATE) {
|
||||||
flags[0] = 1;
|
flags[0] = 1;
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,7 +23,12 @@
|
|||||||
void ecc_free(ecc_key *key)
|
void ecc_free(ecc_key *key)
|
||||||
{
|
{
|
||||||
LTC_ARGCHKVD(key != NULL);
|
LTC_ARGCHKVD(key != NULL);
|
||||||
mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
|
|
||||||
|
mp_cleanup_multi(&key->dp.prime, &key->dp.order,
|
||||||
|
&key->dp.A, &key->dp.B,
|
||||||
|
&key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
|
||||||
|
&key->pubkey.x, &key->pubkey.y, &key->pubkey.z,
|
||||||
|
&key->k, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
254
src/pk/ecc/ecc_get_curve.c
Normal file
254
src/pk/ecc/ecc_get_curve.c
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
static const struct {
|
||||||
|
const char *OID;
|
||||||
|
const char *names[6];
|
||||||
|
} _curve_names[] = {
|
||||||
|
#ifdef LTC_ECC_SECP112R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.6", { "SECP112R1", "ECC-112", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP112R2
|
||||||
|
{
|
||||||
|
"1.3.132.0.7", { "SECP112R2", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP128R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.28", { "SECP128R1", "ECC-128", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP128R2
|
||||||
|
{
|
||||||
|
"1.3.132.0.29", { "SECP128R2", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.8", { "SECP160R1", "ECC-160", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160R2
|
||||||
|
{
|
||||||
|
"1.3.132.0.30", { "SECP160R2", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160K1
|
||||||
|
{
|
||||||
|
"1.3.132.0.9", { "SECP160K1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP192R1
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.1", { "SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V2
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.2", { "PRIME192V2", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V3
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.3", { "PRIME192V3", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP192K1
|
||||||
|
{
|
||||||
|
"1.3.132.0.31", { "SECP192K1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.33", { "SECP224R1", "NISTP224", "ECC-224", "P-224", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224K1
|
||||||
|
{
|
||||||
|
"1.3.132.0.32", { "SECP224K1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256R1
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.7", { "SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256K1
|
||||||
|
{
|
||||||
|
"1.3.132.0.10", { "SECP256K1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP384R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.34", { "SECP384R1", "NISTP384", "ECC-384", "P-384", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP521R1
|
||||||
|
{
|
||||||
|
"1.3.132.0.35", { "SECP521R1", "NISTP521", "ECC-521", "P-521", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V1
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.4", { "PRIME239V1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V2
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.5", { "PRIME239V2", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V3
|
||||||
|
{
|
||||||
|
"1.2.840.10045.3.1.6", { "PRIME239V3", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP160R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.1", { "BRAINPOOLP160R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP192R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.3", { "BRAINPOOLP192R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP224R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.5", { "BRAINPOOLP224R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP256R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.7", { "BRAINPOOLP256R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP320R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.9", { "BRAINPOOLP320R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP384R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.11", { "BRAINPOOLP384R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP512R1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.13", { "BRAINPOOLP512R1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP160T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.2", { "BRAINPOOLP160T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP192T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.4", { "BRAINPOOLP192T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP224T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.6", { "BRAINPOOLP224T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP256T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.8", { "BRAINPOOLP256T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP320T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.10", { "BRAINPOOLP320T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP384T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.12", { "BRAINPOOLP384T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP512T1
|
||||||
|
{
|
||||||
|
"1.3.36.3.3.2.8.1.1.14", { "BRAINPOOLP512T1", NULL }
|
||||||
|
},
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
NULL, { NULL }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/* case-insensitive match + ignore '-', '_', ' ' */
|
||||||
|
static int _name_match(const char *left, const char *right)
|
||||||
|
{
|
||||||
|
char lc_r, lc_l;
|
||||||
|
|
||||||
|
while ((*left != '\0') && (*right != '\0')) {
|
||||||
|
while ((*left == ' ') || (*left == '-') || (*left == '_')) left++;
|
||||||
|
while ((*right == ' ') || (*right == '-') || (*right == '_')) right++;
|
||||||
|
if (*left == '\0' || *right == '\0') break;
|
||||||
|
lc_r = *right;
|
||||||
|
lc_l = *left;
|
||||||
|
if ((lc_r >= 'A') && (lc_r <= 'Z')) lc_r += 32;
|
||||||
|
if ((lc_l >= 'A') && (lc_l <= 'Z')) lc_l += 32;
|
||||||
|
if (lc_l != lc_r) return 0;
|
||||||
|
left++;
|
||||||
|
right++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((*left == '\0') && (*right == '\0'))
|
||||||
|
return 1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecc_get_curve(const char *name_or_oid, const ltc_ecc_curve **cu)
|
||||||
|
{
|
||||||
|
int i, j;
|
||||||
|
const char *OID = NULL;
|
||||||
|
|
||||||
|
LTC_ARGCHK(cu != NULL);
|
||||||
|
LTC_ARGCHK(name_or_oid != NULL);
|
||||||
|
|
||||||
|
*cu = NULL;
|
||||||
|
|
||||||
|
for (i = 0; _curve_names[i].OID != NULL && !OID; i++) {
|
||||||
|
if (XSTRCMP(_curve_names[i].OID, name_or_oid) == 0) {
|
||||||
|
OID = _curve_names[i].OID;
|
||||||
|
}
|
||||||
|
for (j = 0; _curve_names[i].names[j] != NULL && !OID; j++) {
|
||||||
|
if (_name_match(_curve_names[i].names[j], name_or_oid)) {
|
||||||
|
OID = _curve_names[i].OID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OID != NULL) {
|
||||||
|
for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) {
|
||||||
|
if (XSTRCMP(ltc_ecc_curves[i].OID, OID) == 0) {
|
||||||
|
*cu = <c_ecc_curves[i];
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRYPT_INVALID_ARG; /* not found */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
60
src/pk/ecc/ecc_get_key.c
Normal file
60
src/pk/ecc/ecc_get_key.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
/** Export raw public or private key (public keys = ANS X9.63 compressed or uncompressed; private keys = raw bytes)
|
||||||
|
@param out [out] destination of export
|
||||||
|
@param outlen [in/out] Length of destination and final output size
|
||||||
|
@param type PK_PRIVATE, PK_PUBLIC or PK_PUBLIC|PK_COMPRESSED
|
||||||
|
@param key Key to export
|
||||||
|
Return CRYPT_OK on success
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ecc_get_key(unsigned char *out, unsigned long *outlen, int type, const ecc_key *key)
|
||||||
|
{
|
||||||
|
unsigned long size, ksize;
|
||||||
|
int err, compressed;
|
||||||
|
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(out != NULL);
|
||||||
|
LTC_ARGCHK(outlen != NULL);
|
||||||
|
|
||||||
|
size = key->dp.size;
|
||||||
|
compressed = type & PK_COMPRESSED ? 1 : 0;
|
||||||
|
type &= ~PK_COMPRESSED;
|
||||||
|
|
||||||
|
if (type == PK_PUBLIC) {
|
||||||
|
if ((err = ltc_ecc_export_point(out, outlen, key->pubkey.x, key->pubkey.y, size, compressed)) != CRYPT_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type == PK_PRIVATE) {
|
||||||
|
if (key->type != PK_PRIVATE) return CRYPT_PK_TYPE_MISMATCH;
|
||||||
|
*outlen = size;
|
||||||
|
if (size > *outlen) return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
if ((ksize = mp_unsigned_bin_size(key->k)) > size) return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
/* pad and store k */
|
||||||
|
if ((err = mp_to_unsigned_bin(key->k, out + (size - ksize))) != CRYPT_OK) return err;
|
||||||
|
zeromem(out, size - ksize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return CRYPT_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
32
src/pk/ecc/ecc_get_oid_str.c
Normal file
32
src/pk/ecc/ecc_get_oid_str.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
/** Extract OID as a string from ECC key
|
||||||
|
@param out [out] destination buffer
|
||||||
|
@param outlen [in/out] Length of destination buffer and final output size (without terminating NUL byte)
|
||||||
|
@param key The ECC key
|
||||||
|
Return CRYPT_OK on success
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ecc_get_oid_str(char *out, unsigned long *outlen, const ecc_key *key)
|
||||||
|
{
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
|
||||||
|
return pk_oid_num_to_str(key->dp.oid, key->dp.oidlen, out, outlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,13 +21,12 @@
|
|||||||
@param key The key to get the size of
|
@param key The key to get the size of
|
||||||
@return The size (octets) of the key or INT_MAX on error
|
@return The size (octets) of the key or INT_MAX on error
|
||||||
*/
|
*/
|
||||||
int ecc_get_size(ecc_key *key)
|
int ecc_get_size(const ecc_key *key)
|
||||||
{
|
{
|
||||||
LTC_ARGCHK(key != NULL);
|
if (key == NULL) {
|
||||||
if (ltc_ecc_is_valid_idx(key->idx))
|
return INT_MAX;
|
||||||
return key->dp->size;
|
}
|
||||||
else
|
return key->dp.size;
|
||||||
return INT_MAX; /* large value known to cause it to fail when passed to ecc_make_key() */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,54 +16,6 @@
|
|||||||
|
|
||||||
#ifdef LTC_MECC
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
static int _is_point(ecc_key *key)
|
|
||||||
{
|
|
||||||
void *prime, *b, *t1, *t2;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
if ((err = mp_init_multi(&prime, &b, &t1, &t2, NULL)) != CRYPT_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* load prime and b */
|
|
||||||
if ((err = mp_read_radix(prime, key->dp->prime, 16)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_read_radix(b, key->dp->B, 16)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* compute y^2 */
|
|
||||||
if ((err = mp_sqr(key->pubkey.y, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* compute x^3 */
|
|
||||||
if ((err = mp_sqr(key->pubkey.x, t2)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_mul(key->pubkey.x, t2, t2)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* compute y^2 - x^3 */
|
|
||||||
if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* compute y^2 - x^3 + 3x */
|
|
||||||
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_add(t1, key->pubkey.x, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
if ((err = mp_mod(t1, prime, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
|
|
||||||
if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
}
|
|
||||||
while (mp_cmp(t1, prime) != LTC_MP_LT) {
|
|
||||||
if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) { goto error; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/* compare to b */
|
|
||||||
if (mp_cmp(t1, b) != LTC_MP_EQ) {
|
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
} else {
|
|
||||||
err = CRYPT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
error:
|
|
||||||
mp_clear_multi(prime, b, t1, t2, NULL);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Import an ECC key from a binary packet
|
Import an ECC key from a binary packet
|
||||||
@param in The packet to import
|
@param in The packet to import
|
||||||
@ -86,10 +33,10 @@ int ecc_import(const unsigned char *in, unsigned long inlen, ecc_key *key)
|
|||||||
@param in The packet to import
|
@param in The packet to import
|
||||||
@param inlen The length of the packet
|
@param inlen The length of the packet
|
||||||
@param key [out] The destination of the import
|
@param key [out] The destination of the import
|
||||||
@param dp pointer to user supplied params; must be the same as the params used when exporting
|
@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
|
@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_set_type *dp)
|
int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, const ltc_ecc_curve *cu)
|
||||||
{
|
{
|
||||||
unsigned long key_size;
|
unsigned long key_size;
|
||||||
unsigned char flags[1];
|
unsigned char flags[1];
|
||||||
@ -99,18 +46,20 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
|
|||||||
LTC_ARGCHK(key != NULL);
|
LTC_ARGCHK(key != NULL);
|
||||||
LTC_ARGCHK(ltc_mp.name != NULL);
|
LTC_ARGCHK(ltc_mp.name != NULL);
|
||||||
|
|
||||||
/* init key */
|
|
||||||
if (mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, NULL) != CRYPT_OK) {
|
|
||||||
return CRYPT_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* find out what type of key it is */
|
/* find out what type of key it is */
|
||||||
err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
|
err = der_decode_sequence_multi(in, inlen, LTC_ASN1_BIT_STRING, 1UL, flags,
|
||||||
LTC_ASN1_EOL, 0UL, NULL);
|
LTC_ASN1_SHORT_INTEGER, 1UL, &key_size,
|
||||||
|
LTC_ASN1_EOL, 0UL, NULL);
|
||||||
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
|
if (err != CRYPT_OK && err != CRYPT_INPUT_TOO_LONG) {
|
||||||
goto done;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* allocate & initialize the key */
|
||||||
|
if (cu == NULL) {
|
||||||
|
if ((err = ecc_set_dp_by_size(key_size, key)) != CRYPT_OK) { goto done; }
|
||||||
|
} else {
|
||||||
|
if ((err = ecc_set_dp(cu, key)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
|
|
||||||
if (flags[0] == 1) {
|
if (flags[0] == 1) {
|
||||||
/* private key */
|
/* private key */
|
||||||
@ -141,30 +90,17 @@ int ecc_import_ex(const unsigned char *in, unsigned long inlen, ecc_key *key, co
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dp == NULL) {
|
|
||||||
/* find the idx */
|
|
||||||
for (key->idx = 0; ltc_ecc_sets[key->idx].size && (unsigned long)ltc_ecc_sets[key->idx].size != key_size; ++key->idx);
|
|
||||||
if (ltc_ecc_sets[key->idx].size == 0) {
|
|
||||||
err = CRYPT_INVALID_PACKET;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
key->dp = <c_ecc_sets[key->idx];
|
|
||||||
} else {
|
|
||||||
key->idx = -1;
|
|
||||||
key->dp = dp;
|
|
||||||
}
|
|
||||||
/* set z */
|
/* set z */
|
||||||
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
|
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
/* is it a point on the curve? */
|
/* point on the curve + other checks */
|
||||||
if ((err = _is_point(key)) != CRYPT_OK) {
|
if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) { goto done; }
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* we're good */
|
/* we're good */
|
||||||
return CRYPT_OK;
|
return CRYPT_OK;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
|
ecc_free(key);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -31,93 +26,53 @@
|
|||||||
*/
|
*/
|
||||||
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
|
int ecc_make_key(prng_state *prng, int wprng, int keysize, ecc_key *key)
|
||||||
{
|
{
|
||||||
int x, err;
|
int err;
|
||||||
|
|
||||||
/* find key size */
|
if ((err = ecc_set_dp_by_size(keysize, key)) != CRYPT_OK) { return err; }
|
||||||
for (x = 0; (keysize > ltc_ecc_sets[x].size) && (ltc_ecc_sets[x].size != 0); x++);
|
if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
|
||||||
keysize = ltc_ecc_sets[x].size;
|
return CRYPT_OK;
|
||||||
|
|
||||||
if (keysize > ECC_MAXSIZE || ltc_ecc_sets[x].size == 0) {
|
|
||||||
return CRYPT_INVALID_KEYSIZE;
|
|
||||||
}
|
|
||||||
err = ecc_make_key_ex(prng, wprng, key, <c_ecc_sets[x]);
|
|
||||||
key->idx = x;
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_set_type *dp)
|
int ecc_make_key_ex(prng_state *prng, int wprng, ecc_key *key, const ltc_ecc_curve *cu)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if ((err = ecc_set_dp(cu, key)) != CRYPT_OK) { return err; }
|
||||||
|
if ((err = ecc_generate_key(prng, wprng, key)) != CRYPT_OK) { return err; }
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecc_generate_key(prng_state *prng, int wprng, ecc_key *key)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
ecc_point *base;
|
|
||||||
void *prime, *order;
|
|
||||||
unsigned char *buf;
|
|
||||||
int keysize;
|
|
||||||
|
|
||||||
LTC_ARGCHK(key != NULL);
|
|
||||||
LTC_ARGCHK(ltc_mp.name != NULL);
|
LTC_ARGCHK(ltc_mp.name != NULL);
|
||||||
LTC_ARGCHK(dp != NULL);
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(key->dp.size > 0);
|
||||||
|
|
||||||
/* good prng? */
|
/* ECC key pair generation according to FIPS-186-4 (B.4.2 Key Pair Generation by Testing Candidates):
|
||||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
* the generated private key k should be the range [1, order-1]
|
||||||
return err;
|
* a/ N = bitlen(order)
|
||||||
|
* b/ generate N random bits and convert them into big integer k
|
||||||
|
* c/ if k not in [1, order-1] go to b/
|
||||||
|
* e/ Q = k*G
|
||||||
|
*/
|
||||||
|
if ((err = rand_bn_upto(key->k, key->dp.order, prng, wprng)) != CRYPT_OK) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
key->idx = -1;
|
|
||||||
key->dp = dp;
|
|
||||||
keysize = dp->size;
|
|
||||||
|
|
||||||
/* allocate ram */
|
|
||||||
base = NULL;
|
|
||||||
buf = XMALLOC(ECC_MAXSIZE);
|
|
||||||
if (buf == NULL) {
|
|
||||||
return CRYPT_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make up random string */
|
|
||||||
if (prng_descriptor[wprng].read(buf, (unsigned long)keysize, prng) != (unsigned long)keysize) {
|
|
||||||
err = CRYPT_ERROR_READPRNG;
|
|
||||||
goto ERR_BUF;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* setup the key variables */
|
|
||||||
if ((err = mp_init_multi(&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k, &prime, &order, NULL)) != CRYPT_OK) {
|
|
||||||
goto ERR_BUF;
|
|
||||||
}
|
|
||||||
base = ltc_ecc_new_point();
|
|
||||||
if (base == NULL) {
|
|
||||||
err = CRYPT_MEM;
|
|
||||||
goto errkey;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* read in the specs for this key */
|
|
||||||
if ((err = mp_read_radix(prime, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto errkey; }
|
|
||||||
if ((err = mp_read_radix(order, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errkey; }
|
|
||||||
if ((err = mp_read_radix(base->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto errkey; }
|
|
||||||
if ((err = mp_read_radix(base->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto errkey; }
|
|
||||||
if ((err = mp_set(base->z, 1)) != CRYPT_OK) { goto errkey; }
|
|
||||||
if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)buf, keysize)) != CRYPT_OK) { goto errkey; }
|
|
||||||
|
|
||||||
/* the key should be smaller than the order of base point */
|
|
||||||
if (mp_cmp(key->k, order) != LTC_MP_LT) {
|
|
||||||
if((err = mp_mod(key->k, order, key->k)) != CRYPT_OK) { goto errkey; }
|
|
||||||
}
|
|
||||||
/* make the public key */
|
/* make the public key */
|
||||||
if ((err = ltc_mp.ecc_ptmul(key->k, base, &key->pubkey, prime, 1)) != CRYPT_OK) { goto errkey; }
|
if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, key->dp.A, key->dp.prime, 1)) != CRYPT_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
key->type = PK_PRIVATE;
|
key->type = PK_PRIVATE;
|
||||||
|
|
||||||
/* free up ram */
|
/* success */
|
||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
errkey:
|
|
||||||
mp_clear_multi(key->pubkey.x, key->pubkey.y, key->pubkey.z, key->k, NULL);
|
error:
|
||||||
|
ecc_free(key);
|
||||||
cleanup:
|
cleanup:
|
||||||
ltc_ecc_del_point(base);
|
|
||||||
mp_clear_multi(prime, order, NULL);
|
|
||||||
ERR_BUF:
|
|
||||||
#ifdef LTC_CLEAN_STACK
|
|
||||||
zeromem(buf, ECC_MAXSIZE);
|
|
||||||
#endif
|
|
||||||
XFREE(buf);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
90
src/pk/ecc/ecc_set_dp.c
Normal file
90
src/pk/ecc/ecc_set_dp.c
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
int ecc_set_dp(const ltc_ecc_curve *curve, ecc_key *key)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(curve != NULL);
|
||||||
|
|
||||||
|
if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
|
||||||
|
&key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
|
||||||
|
&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
|
||||||
|
NULL)) != CRYPT_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A, B, order, prime, Gx, Gy */
|
||||||
|
if ((err = mp_read_radix(key->dp.prime, curve->prime, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_read_radix(key->dp.order, curve->order, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_read_radix(key->dp.A, curve->A, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_read_radix(key->dp.B, curve->B, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_read_radix(key->dp.base.x, curve->Gx, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_read_radix(key->dp.base.y, curve->Gy, 16)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
|
||||||
|
/* cofactor & size */
|
||||||
|
key->dp.cofactor = curve->cofactor;
|
||||||
|
key->dp.size = mp_unsigned_bin_size(key->dp.prime);
|
||||||
|
/* OID string >> unsigned long oid[16] + oidlen */
|
||||||
|
key->dp.oidlen = 16;
|
||||||
|
if ((err = pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen)) != CRYPT_OK) { goto error; }
|
||||||
|
/* success */
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ecc_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecc_set_dp_by_size(int size, ecc_key *key)
|
||||||
|
{
|
||||||
|
const ltc_ecc_curve *cu = NULL;
|
||||||
|
int err = CRYPT_ERROR;
|
||||||
|
|
||||||
|
/* for compatibility with libtomcrypt-1.17 the sizes below must match the specific curves */
|
||||||
|
if (size <= 14) {
|
||||||
|
err = ecc_get_curve("SECP112R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 16) {
|
||||||
|
err = ecc_get_curve("SECP128R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 20) {
|
||||||
|
err = ecc_get_curve("SECP160R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 24) {
|
||||||
|
err = ecc_get_curve("SECP192R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 28) {
|
||||||
|
err = ecc_get_curve("SECP224R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 32) {
|
||||||
|
err = ecc_get_curve("SECP256R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 48) {
|
||||||
|
err = ecc_get_curve("SECP384R1", &cu);
|
||||||
|
}
|
||||||
|
else if (size <= 66) {
|
||||||
|
err = ecc_get_curve("SECP521R1", &cu);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err == CRYPT_OK && cu != NULL) return ecc_set_dp(cu, key);
|
||||||
|
|
||||||
|
return CRYPT_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
129
src/pk/ecc/ecc_set_dp_internal.c
Normal file
129
src/pk/ecc/ecc_set_dp_internal.c
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
static int _ecc_cmp_hex_bn(const char *left_hex, void *right_bn, void *tmp_bn)
|
||||||
|
{
|
||||||
|
if (mp_read_radix(tmp_bn, left_hex, 16) != CRYPT_OK) return 0;
|
||||||
|
if (mp_cmp(tmp_bn, right_bn) != LTC_MP_EQ) return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ecc_oid_lookup(ecc_key *key)
|
||||||
|
{
|
||||||
|
void *bn;
|
||||||
|
const ltc_ecc_curve *curve;
|
||||||
|
|
||||||
|
key->dp.oidlen = 0;
|
||||||
|
if (mp_init(&bn) != CRYPT_OK) return;
|
||||||
|
for (curve = ltc_ecc_curves; curve->prime != NULL; curve++) {
|
||||||
|
if (_ecc_cmp_hex_bn(curve->prime, key->dp.prime, bn) != 1) continue;
|
||||||
|
if (_ecc_cmp_hex_bn(curve->order, key->dp.order, bn) != 1) continue;
|
||||||
|
if (_ecc_cmp_hex_bn(curve->A, key->dp.A, bn) != 1) continue;
|
||||||
|
if (_ecc_cmp_hex_bn(curve->B, key->dp.B, bn) != 1) continue;
|
||||||
|
if (_ecc_cmp_hex_bn(curve->Gx, key->dp.base.x, bn) != 1) continue;
|
||||||
|
if (_ecc_cmp_hex_bn(curve->Gy, key->dp.base.y, bn) != 1) continue;
|
||||||
|
if (key->dp.cofactor != curve->cofactor) continue;
|
||||||
|
break; /* found */
|
||||||
|
}
|
||||||
|
mp_clear(bn);
|
||||||
|
if (curve->prime && curve->OID) {
|
||||||
|
key->dp.oidlen = 16; /* size of key->dp.oid */
|
||||||
|
pk_oid_str_to_num(curve->OID, key->dp.oid, &key->dp.oidlen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecc_copy_dp(const ecc_key *srckey, ecc_key *key)
|
||||||
|
{
|
||||||
|
unsigned long i;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(srckey != NULL);
|
||||||
|
|
||||||
|
if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
|
||||||
|
&key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
|
||||||
|
&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
|
||||||
|
NULL)) != CRYPT_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A, B, order, prime, Gx, Gy */
|
||||||
|
if ((err = mp_copy(srckey->dp.prime, key->dp.prime )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(srckey->dp.order, key->dp.order )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(srckey->dp.A, key->dp.A )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(srckey->dp.B, key->dp.B )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = ltc_ecc_copy_point(&srckey->dp.base, &key->dp.base)) != CRYPT_OK) { goto error; }
|
||||||
|
/* cofactor & size */
|
||||||
|
key->dp.cofactor = srckey->dp.cofactor;
|
||||||
|
key->dp.size = srckey->dp.size;
|
||||||
|
/* OID */
|
||||||
|
if (srckey->dp.oidlen > 0) {
|
||||||
|
key->dp.oidlen = srckey->dp.oidlen;
|
||||||
|
for (i = 0; i < key->dp.oidlen; i++) key->dp.oid[i] = srckey->dp.oid[i];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
_ecc_oid_lookup(key); /* try to find OID in ltc_ecc_curves */
|
||||||
|
}
|
||||||
|
/* success */
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ecc_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ecc_set_dp_from_mpis(void *a, void *b, void *prime, void *order, void *gx, void *gy, unsigned long cofactor, ecc_key *key)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(a != NULL);
|
||||||
|
LTC_ARGCHK(b != NULL);
|
||||||
|
LTC_ARGCHK(prime != NULL);
|
||||||
|
LTC_ARGCHK(order != NULL);
|
||||||
|
LTC_ARGCHK(gx != NULL);
|
||||||
|
LTC_ARGCHK(gy != NULL);
|
||||||
|
|
||||||
|
if ((err = mp_init_multi(&key->dp.prime, &key->dp.order, &key->dp.A, &key->dp.B,
|
||||||
|
&key->dp.base.x, &key->dp.base.y, &key->dp.base.z,
|
||||||
|
&key->pubkey.x, &key->pubkey.y, &key->pubkey.z, &key->k,
|
||||||
|
NULL)) != CRYPT_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A, B, order, prime, Gx, Gy */
|
||||||
|
if ((err = mp_copy(prime, key->dp.prime )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(order, key->dp.order )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(a, key->dp.A )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(b, key->dp.B )) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(gx, key->dp.base.x)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_copy(gy, key->dp.base.y)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_set(key->dp.base.z, 1)) != CRYPT_OK) { goto error; }
|
||||||
|
/* cofactor & size */
|
||||||
|
key->dp.cofactor = cofactor;
|
||||||
|
key->dp.size = mp_unsigned_bin_size(prime);
|
||||||
|
/* try to find OID in ltc_ecc_curves */
|
||||||
|
_ecc_oid_lookup(key);
|
||||||
|
/* success */
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ecc_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
67
src/pk/ecc/ecc_set_key.c
Normal file
67
src/pk/ecc/ecc_set_key.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
int ecc_set_key(const unsigned char *in, unsigned long inlen, int type, ecc_key *key)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
void *prime, *a, *b;
|
||||||
|
|
||||||
|
LTC_ARGCHK(key != NULL);
|
||||||
|
LTC_ARGCHK(in != NULL);
|
||||||
|
LTC_ARGCHK(inlen > 0);
|
||||||
|
|
||||||
|
prime = key->dp.prime;
|
||||||
|
a = key->dp.A;
|
||||||
|
b = key->dp.B;
|
||||||
|
|
||||||
|
if (type == PK_PRIVATE && inlen <= (unsigned long)key->dp.size) {
|
||||||
|
/* load private key */
|
||||||
|
if ((err = mp_read_unsigned_bin(key->k, (unsigned char *)in, inlen)) != CRYPT_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if (mp_iszero(key->k)) {
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
/* compute public key */
|
||||||
|
if ((err = ltc_mp.ecc_ptmul(key->k, &key->dp.base, &key->pubkey, a, prime, 1)) != CRYPT_OK) { goto error; }
|
||||||
|
key->type = type;
|
||||||
|
}
|
||||||
|
else if (type == PK_PUBLIC) {
|
||||||
|
/* load public key */
|
||||||
|
if ((err = ltc_ecc_import_point(in, inlen, prime, a, b, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_set(key->pubkey.z, 1)) != CRYPT_OK) { goto error; }
|
||||||
|
key->type = type;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* point on the curve + other checks */
|
||||||
|
if ((err = ltc_ecc_verify_key(key)) != CRYPT_OK) {
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CRYPT_OK;
|
||||||
|
|
||||||
|
error:
|
||||||
|
ecc_free(key);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -29,12 +24,12 @@
|
|||||||
@param outlen [in/out] The max size and resulting size of the shared secret
|
@param outlen [in/out] The max size and resulting size of the shared secret
|
||||||
@return CRYPT_OK if successful
|
@return CRYPT_OK if successful
|
||||||
*/
|
*/
|
||||||
int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
int ecc_shared_secret(const ecc_key *private_key, const ecc_key *public_key,
|
||||||
unsigned char *out, unsigned long *outlen)
|
unsigned char *out, unsigned long *outlen)
|
||||||
{
|
{
|
||||||
unsigned long x;
|
unsigned long x;
|
||||||
ecc_point *result;
|
ecc_point *result;
|
||||||
void *prime;
|
void *prime, *a;
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
LTC_ARGCHK(private_key != NULL);
|
LTC_ARGCHK(private_key != NULL);
|
||||||
@ -47,27 +42,16 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
|||||||
return CRYPT_PK_NOT_PRIVATE;
|
return CRYPT_PK_NOT_PRIVATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ltc_ecc_is_valid_idx(private_key->idx) == 0 || ltc_ecc_is_valid_idx(public_key->idx) == 0) {
|
|
||||||
return CRYPT_INVALID_ARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (XSTRCMP(private_key->dp->name, public_key->dp->name) != 0) {
|
|
||||||
return CRYPT_PK_TYPE_MISMATCH;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* make new point */
|
/* make new point */
|
||||||
result = ltc_ecc_new_point();
|
result = ltc_ecc_new_point();
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
return CRYPT_MEM;
|
return CRYPT_MEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = mp_init(&prime)) != CRYPT_OK) {
|
prime = private_key->dp.prime;
|
||||||
ltc_ecc_del_point(result);
|
a = private_key->dp.A;
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = mp_read_radix(prime, (char *)private_key->dp->prime, 16)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, a, prime, 1)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptmul(private_key->k, &public_key->pubkey, result, prime, 1)) != CRYPT_OK) { goto done; }
|
|
||||||
|
|
||||||
x = (unsigned long)mp_unsigned_bin_size(prime);
|
x = (unsigned long)mp_unsigned_bin_size(prime);
|
||||||
if (*outlen < x) {
|
if (*outlen < x) {
|
||||||
@ -76,12 +60,11 @@ int ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
zeromem(out, x);
|
zeromem(out, x);
|
||||||
if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
|
if ((err = mp_to_unsigned_bin(result->x, out + (x - mp_unsigned_bin_size(result->x)))) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
*outlen = x;
|
*outlen = x;
|
||||||
done:
|
done:
|
||||||
mp_clear(prime);
|
|
||||||
ltc_ecc_del_point(result);
|
ltc_ecc_del_point(result);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, ecc_key *key, int sigformat)
|
prng_state *prng, int wprng, const ecc_key *key, int sigformat)
|
||||||
{
|
{
|
||||||
ecc_key pubkey;
|
ecc_key pubkey;
|
||||||
void *r, *s, *e, *p;
|
void *r, *s, *e, *p;
|
||||||
@ -36,22 +36,13 @@ static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
|||||||
return CRYPT_PK_NOT_PRIVATE;
|
return CRYPT_PK_NOT_PRIVATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* is the IDX valid ? */
|
|
||||||
if (ltc_ecc_is_valid_idx(key->idx) != 1) {
|
|
||||||
return CRYPT_PK_INVALID_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = prng_is_valid(wprng)) != CRYPT_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* init the bignums */
|
/* init the bignums */
|
||||||
if ((err = mp_init_multi(&r, &s, &p, &e, NULL)) != CRYPT_OK) {
|
if ((err = mp_init_multi(&r, &s, &e, NULL)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto errnokey; }
|
|
||||||
|
|
||||||
/* get the hash and load it as a bignum into 'e' */
|
/* get the hash and load it as a bignum into 'e' */
|
||||||
|
p = key->dp.order;
|
||||||
pbits = mp_count_bits(p);
|
pbits = mp_count_bits(p);
|
||||||
pbytes = (pbits+7) >> 3;
|
pbytes = (pbits+7) >> 3;
|
||||||
if (pbits > inlen*8) {
|
if (pbits > inlen*8) {
|
||||||
@ -72,12 +63,11 @@ static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
|||||||
|
|
||||||
/* make up a key and export the public copy */
|
/* make up a key and export the public copy */
|
||||||
do {
|
do {
|
||||||
if ((err = ecc_make_key_ex(prng, wprng, &pubkey, key->dp)) != CRYPT_OK) {
|
if ((err = ecc_copy_dp(key, &pubkey)) != CRYPT_OK) { goto errnokey; }
|
||||||
goto errnokey;
|
if ((err = ecc_generate_key(prng, wprng, &pubkey)) != CRYPT_OK) { goto errnokey; }
|
||||||
}
|
|
||||||
|
|
||||||
/* find r = x1 mod n */
|
/* find r = x1 mod n */
|
||||||
if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
|
if ((err = mp_mod(pubkey.pubkey.x, p, r)) != CRYPT_OK) { goto error; }
|
||||||
|
|
||||||
if (mp_iszero(r) == LTC_MP_YES) {
|
if (mp_iszero(r) == LTC_MP_YES) {
|
||||||
ecc_free(&pubkey);
|
ecc_free(&pubkey);
|
||||||
@ -121,7 +111,7 @@ static int _ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
|||||||
error:
|
error:
|
||||||
ecc_free(&pubkey);
|
ecc_free(&pubkey);
|
||||||
errnokey:
|
errnokey:
|
||||||
mp_clear_multi(r, s, p, e, NULL);
|
mp_clear_multi(r, s, e, NULL);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +128,7 @@ errnokey:
|
|||||||
*/
|
*/
|
||||||
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, ecc_key *key)
|
prng_state *prng, int wprng, const ecc_key *key)
|
||||||
{
|
{
|
||||||
return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0);
|
return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 0);
|
||||||
}
|
}
|
||||||
@ -156,7 +146,7 @@ int ecc_sign_hash(const unsigned char *in, unsigned long inlen,
|
|||||||
*/
|
*/
|
||||||
int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
|
int ecc_sign_hash_rfc7518(const unsigned char *in, unsigned long inlen,
|
||||||
unsigned char *out, unsigned long *outlen,
|
unsigned char *out, unsigned long *outlen,
|
||||||
prng_state *prng, int wprng, ecc_key *key)
|
prng_state *prng, int wprng, const ecc_key *key)
|
||||||
{
|
{
|
||||||
return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1);
|
return _ecc_sign_hash(in, inlen, out, outlen, prng, wprng, key, 1);
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -23,20 +18,25 @@
|
|||||||
|
|
||||||
void ecc_sizes(int *low, int *high)
|
void ecc_sizes(int *low, int *high)
|
||||||
{
|
{
|
||||||
int i;
|
int i, size;
|
||||||
LTC_ARGCHKVD(low != NULL);
|
void *prime;
|
||||||
LTC_ARGCHKVD(high != NULL);
|
|
||||||
|
|
||||||
*low = INT_MAX;
|
LTC_ARGCHKVD(low != NULL);
|
||||||
*high = 0;
|
LTC_ARGCHKVD(high != NULL);
|
||||||
for (i = 0; ltc_ecc_sets[i].size != 0; i++) {
|
|
||||||
if (ltc_ecc_sets[i].size < *low) {
|
*low = INT_MAX;
|
||||||
*low = ltc_ecc_sets[i].size;
|
*high = 0;
|
||||||
}
|
|
||||||
if (ltc_ecc_sets[i].size > *high) {
|
if (mp_init(&prime) == CRYPT_OK) {
|
||||||
*high = ltc_ecc_sets[i].size;
|
for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) {
|
||||||
}
|
if (mp_read_radix(prime, ltc_ecc_curves[i].prime, 16) == CRYPT_OK) {
|
||||||
}
|
size = mp_unsigned_bin_size(prime);
|
||||||
|
if (size < *low) *low = size;
|
||||||
|
if (size > *high) *high = size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mp_clear(prime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -21,68 +16,12 @@
|
|||||||
|
|
||||||
#ifdef LTC_MECC
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
/**
|
|
||||||
Perform on the ECC system
|
|
||||||
@return CRYPT_OK if successful
|
|
||||||
*/
|
|
||||||
int ecc_test(void)
|
int ecc_test(void)
|
||||||
{
|
{
|
||||||
void *modulus, *order;
|
/* the main ECC tests are in tests/ecc_test.c
|
||||||
ecc_point *G, *GG;
|
* this function is kept just for API compatibility
|
||||||
int i, err, primality;
|
*/
|
||||||
|
return CRYPT_NOP;
|
||||||
if ((err = mp_init_multi(&modulus, &order, NULL)) != CRYPT_OK) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
G = ltc_ecc_new_point();
|
|
||||||
GG = ltc_ecc_new_point();
|
|
||||||
if (G == NULL || GG == NULL) {
|
|
||||||
mp_clear_multi(modulus, order, NULL);
|
|
||||||
ltc_ecc_del_point(G);
|
|
||||||
ltc_ecc_del_point(GG);
|
|
||||||
return CRYPT_MEM;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; ltc_ecc_sets[i].size; i++) {
|
|
||||||
#if 0
|
|
||||||
printf("Testing %d\n", ltc_ecc_sets[i].size);
|
|
||||||
#endif
|
|
||||||
if ((err = mp_read_radix(modulus, (char *)ltc_ecc_sets[i].prime, 16)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_read_radix(order, (char *)ltc_ecc_sets[i].order, 16)) != CRYPT_OK) { goto done; }
|
|
||||||
|
|
||||||
/* is prime actually prime? */
|
|
||||||
if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK) { goto done; }
|
|
||||||
if (primality == 0) {
|
|
||||||
err = CRYPT_FAIL_TESTVECTOR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* is order prime ? */
|
|
||||||
if ((err = mp_prime_is_prime(order, 8, &primality)) != CRYPT_OK) { goto done; }
|
|
||||||
if (primality == 0) {
|
|
||||||
err = CRYPT_FAIL_TESTVECTOR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((err = mp_read_radix(G->x, (char *)ltc_ecc_sets[i].Gx, 16)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_read_radix(G->y, (char *)ltc_ecc_sets[i].Gy, 16)) != CRYPT_OK) { goto done; }
|
|
||||||
mp_set(G->z, 1);
|
|
||||||
|
|
||||||
/* then we should have G == (order + 1)G */
|
|
||||||
if ((err = mp_add_d(order, 1, order)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = ltc_mp.ecc_ptmul(order, G, GG, modulus, 1)) != CRYPT_OK) { goto done; }
|
|
||||||
if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) {
|
|
||||||
err = CRYPT_FAIL_TESTVECTOR;
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = CRYPT_OK;
|
|
||||||
done:
|
|
||||||
ltc_ecc_del_point(GG);
|
|
||||||
ltc_ecc_del_point(G);
|
|
||||||
mp_clear_multi(order, modulus, NULL);
|
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,11 +18,11 @@
|
|||||||
|
|
||||||
static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||||
const unsigned char *hash, unsigned long hashlen,
|
const unsigned char *hash, unsigned long hashlen,
|
||||||
int *stat, ecc_key *key, int sigformat)
|
int *stat, const ecc_key *key, int sigformat)
|
||||||
{
|
{
|
||||||
ecc_point *mG, *mQ;
|
ecc_point *mG = NULL, *mQ = NULL;
|
||||||
void *r, *s, *v, *w, *u1, *u2, *e, *p, *m;
|
void *r, *s, *v, *w, *u1, *u2, *e, *p, *m, *a, *a_plus3 = NULL, *mu = NULL, *ma = NULL;
|
||||||
void *mp;
|
void *mp = NULL;
|
||||||
int err;
|
int err;
|
||||||
unsigned long pbits, pbytes, i, shift_right;
|
unsigned long pbits, pbytes, i, shift_right;
|
||||||
unsigned char ch, buf[MAXBLOCKSIZE];
|
unsigned char ch, buf[MAXBLOCKSIZE];
|
||||||
@ -34,16 +34,17 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
|||||||
|
|
||||||
/* default to invalid signature */
|
/* default to invalid signature */
|
||||||
*stat = 0;
|
*stat = 0;
|
||||||
mp = NULL;
|
|
||||||
|
|
||||||
/* is the IDX valid ? */
|
|
||||||
if (ltc_ecc_is_valid_idx(key->idx) != 1) {
|
|
||||||
return CRYPT_PK_INVALID_TYPE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* allocate ints */
|
/* allocate ints */
|
||||||
if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &p, &e, &m, NULL)) != CRYPT_OK) {
|
if ((err = mp_init_multi(&r, &s, &v, &w, &u1, &u2, &e, &a_plus3, NULL)) != CRYPT_OK) {
|
||||||
return CRYPT_MEM;
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = key->dp.order;
|
||||||
|
m = key->dp.prime;
|
||||||
|
a = key->dp.A;
|
||||||
|
if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) {
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate points */
|
/* allocate points */
|
||||||
@ -72,14 +73,9 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
|||||||
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }
|
LTC_ASN1_EOL, 0UL, NULL)) != CRYPT_OK) { goto error; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the order */
|
|
||||||
if ((err = mp_read_radix(p, (char *)key->dp->order, 16)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* get the modulus */
|
|
||||||
if ((err = mp_read_radix(m, (char *)key->dp->prime, 16)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* check for zero */
|
/* check for zero */
|
||||||
if (mp_iszero(r) || mp_iszero(s) || mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
|
if (mp_cmp_d(r, 0) != LTC_MP_GT || mp_cmp_d(s, 0) != LTC_MP_GT ||
|
||||||
|
mp_cmp(r, p) != LTC_MP_LT || mp_cmp(s, p) != LTC_MP_LT) {
|
||||||
err = CRYPT_INVALID_PACKET;
|
err = CRYPT_INVALID_PACKET;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -113,30 +109,32 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
|||||||
if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
|
if ((err = mp_mulmod(r, w, p, u2)) != CRYPT_OK) { goto error; }
|
||||||
|
|
||||||
/* find mG and mQ */
|
/* find mG and mQ */
|
||||||
if ((err = mp_read_radix(mG->x, (char *)key->dp->Gx, 16)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_ecc_copy_point(&key->dp.base, mG)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_read_radix(mG->y, (char *)key->dp->Gy, 16)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_ecc_copy_point(&key->pubkey, mQ)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_set(mG->z, 1)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
if ((err = mp_copy(key->pubkey.x, mQ->x)) != CRYPT_OK) { goto error; }
|
/* find the montgomery mp */
|
||||||
if ((err = mp_copy(key->pubkey.y, mQ->y)) != CRYPT_OK) { goto error; }
|
if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_copy(key->pubkey.z, mQ->z)) != CRYPT_OK) { goto error; }
|
|
||||||
|
/* for curves with a == -3 keep ma == NULL */
|
||||||
|
if (mp_cmp(a_plus3, m) != LTC_MP_EQ) {
|
||||||
|
if ((err = mp_init_multi(&mu, &ma, NULL)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_montgomery_normalization(mu, m)) != CRYPT_OK) { goto error; }
|
||||||
|
if ((err = mp_mulmod(a, mu, m, ma)) != CRYPT_OK) { goto error; }
|
||||||
|
}
|
||||||
|
|
||||||
/* compute u1*mG + u2*mQ = mG */
|
/* compute u1*mG + u2*mQ = mG */
|
||||||
if (ltc_mp.ecc_mul2add == NULL) {
|
if (ltc_mp.ecc_mul2add == NULL) {
|
||||||
if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, m, 0)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_mp.ecc_ptmul(u1, mG, mG, a, m, 0)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, m, 0)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_mp.ecc_ptmul(u2, mQ, mQ, a, m, 0)) != CRYPT_OK) { goto error; }
|
||||||
|
|
||||||
/* find the montgomery mp */
|
|
||||||
if ((err = mp_montgomery_setup(m, &mp)) != CRYPT_OK) { goto error; }
|
|
||||||
|
|
||||||
/* add them */
|
/* add them */
|
||||||
if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, m, mp)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_mp.ecc_ptadd(mQ, mG, mG, ma, m, mp)) != CRYPT_OK) { goto error; }
|
||||||
|
|
||||||
/* reduce */
|
/* reduce */
|
||||||
if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_mp.ecc_map(mG, m, mp)) != CRYPT_OK) { goto error; }
|
||||||
} else {
|
} else {
|
||||||
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
|
/* use Shamir's trick to compute u1*mG + u2*mQ using half of the doubles */
|
||||||
if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, m)) != CRYPT_OK) { goto error; }
|
if ((err = ltc_mp.ecc_mul2add(mG, u1, mQ, u2, mG, ma, m)) != CRYPT_OK) { goto error; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* v = X_x1 mod n */
|
/* v = X_x1 mod n */
|
||||||
@ -150,9 +148,11 @@ static int _ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
|||||||
/* clear up and return */
|
/* clear up and return */
|
||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
error:
|
error:
|
||||||
ltc_ecc_del_point(mG);
|
if (mG != NULL) ltc_ecc_del_point(mG);
|
||||||
ltc_ecc_del_point(mQ);
|
if (mQ != NULL) ltc_ecc_del_point(mQ);
|
||||||
mp_clear_multi(r, s, v, w, u1, u2, p, e, m, NULL);
|
if (mu != NULL) mp_clear(mu);
|
||||||
|
if (ma != NULL) mp_clear(ma);
|
||||||
|
mp_clear_multi(r, s, v, w, u1, u2, e, a_plus3, NULL);
|
||||||
if (mp != NULL) {
|
if (mp != NULL) {
|
||||||
mp_montgomery_free(mp);
|
mp_montgomery_free(mp);
|
||||||
}
|
}
|
||||||
@ -171,7 +171,7 @@ error:
|
|||||||
*/
|
*/
|
||||||
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
||||||
const unsigned char *hash, unsigned long hashlen,
|
const unsigned char *hash, unsigned long hashlen,
|
||||||
int *stat, ecc_key *key)
|
int *stat, const ecc_key *key)
|
||||||
{
|
{
|
||||||
return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 0);
|
return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 0);
|
||||||
}
|
}
|
||||||
@ -188,7 +188,7 @@ int ecc_verify_hash(const unsigned char *sig, unsigned long siglen,
|
|||||||
*/
|
*/
|
||||||
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
|
int ecc_verify_hash_rfc7518(const unsigned char *sig, unsigned long siglen,
|
||||||
const unsigned char *hash, unsigned long hashlen,
|
const unsigned char *hash, unsigned long hashlen,
|
||||||
int *stat, ecc_key *key)
|
int *stat, const ecc_key *key)
|
||||||
{
|
{
|
||||||
return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 1);
|
return _ecc_verify_hash(sig, siglen, hash, hashlen, stat, key, 1);
|
||||||
}
|
}
|
||||||
|
63
src/pk/ecc/ltc_ecc_export_point.c
Normal file
63
src/pk/ecc/ltc_ecc_export_point.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
int ltc_ecc_export_point(unsigned char *out, unsigned long *outlen, void *x, void *y, unsigned long size, int compressed)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned char buf[ECC_BUF_SIZE];
|
||||||
|
unsigned long xsize, ysize;
|
||||||
|
|
||||||
|
if (size > sizeof(buf)) return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
if ((xsize = mp_unsigned_bin_size(x)) > size) return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
if ((ysize = mp_unsigned_bin_size(y)) > size) return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
|
||||||
|
if(compressed) {
|
||||||
|
if (*outlen < (1 + size)) {
|
||||||
|
*outlen = 1 + size;
|
||||||
|
return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
/* store first byte */
|
||||||
|
out[0] = mp_isodd(y) ? 0x03 : 0x02;
|
||||||
|
/* pad and store x */
|
||||||
|
zeromem(buf, sizeof(buf));
|
||||||
|
if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err;
|
||||||
|
XMEMCPY(out+1, buf, size);
|
||||||
|
/* adjust outlen */
|
||||||
|
*outlen = 1 + size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (*outlen < (1 + 2*size)) {
|
||||||
|
*outlen = 1 + 2*size;
|
||||||
|
return CRYPT_BUFFER_OVERFLOW;
|
||||||
|
}
|
||||||
|
/* store byte 0x04 */
|
||||||
|
out[0] = 0x04;
|
||||||
|
/* pad and store x */
|
||||||
|
zeromem(buf, sizeof(buf));
|
||||||
|
if ((err = mp_to_unsigned_bin(x, buf + (size - xsize))) != CRYPT_OK) return err;
|
||||||
|
XMEMCPY(out+1, buf, size);
|
||||||
|
/* pad and store y */
|
||||||
|
zeromem(buf, sizeof(buf));
|
||||||
|
if ((err = mp_to_unsigned_bin(y, buf + (size - ysize))) != CRYPT_OK) return err;
|
||||||
|
XMEMCPY(out+1+size, buf, size);
|
||||||
|
/* adjust outlen */
|
||||||
|
*outlen = 1 + 2*size;
|
||||||
|
}
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
71
src/pk/ecc/ltc_ecc_import_point.c
Normal file
71
src/pk/ecc/ltc_ecc_import_point.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
int ltc_ecc_import_point(const unsigned char *in, unsigned long inlen, void *prime, void *a, void *b, void *x, void *y)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
unsigned long size;
|
||||||
|
void *t1, *t2;
|
||||||
|
|
||||||
|
/* init key + temporary numbers */
|
||||||
|
if (mp_init_multi(&t1, &t2, NULL) != CRYPT_OK) {
|
||||||
|
return CRYPT_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = mp_unsigned_bin_size(prime);
|
||||||
|
|
||||||
|
if (in[0] == 0x04 && (inlen&1) && ((inlen-1)>>1) == size) {
|
||||||
|
/* read uncompressed point */
|
||||||
|
/* load x */
|
||||||
|
if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* load y */
|
||||||
|
if ((err = mp_read_unsigned_bin(y, (unsigned char *)in+1+size, size)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
}
|
||||||
|
else if ((in[0] == 0x02 || in[0] == 0x03) && (inlen-1) == size && ltc_mp.sqrtmod_prime != NULL) {
|
||||||
|
/* read compressed point - BEWARE: requires sqrtmod_prime */
|
||||||
|
/* load x */
|
||||||
|
if ((err = mp_read_unsigned_bin(x, (unsigned char *)in+1, size)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* compute x^3 */
|
||||||
|
if ((err = mp_sqr(x, t1)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
if ((err = mp_mulmod(t1, x, prime, t1)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* compute x^3 + a*x */
|
||||||
|
if ((err = mp_mulmod(a, x, prime, t2)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* compute x^3 + a*x + b */
|
||||||
|
if ((err = mp_add(t1, b, t1)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* compute sqrt(x^3 + a*x + b) */
|
||||||
|
if ((err = mp_sqrtmod_prime(t1, prime, t2)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
/* adjust y */
|
||||||
|
if ((mp_isodd(t2) && in[0] == 0x03) || (!mp_isodd(t2) && in[0] == 0x02)) {
|
||||||
|
if ((err = mp_mod(t2, prime, y)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((err = mp_submod(prime, t2, prime, y)) != CRYPT_OK) { goto cleanup; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
err = CRYPT_OK;
|
||||||
|
cleanup:
|
||||||
|
mp_clear_multi(t1, t2, NULL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
72
src/pk/ecc/ltc_ecc_is_point.c
Normal file
72
src/pk/ecc/ltc_ecc_is_point.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
/** Returns whether [x,y] is a point on curve defined by dp
|
||||||
|
@param dp curve parameters
|
||||||
|
@param x x point coordinate
|
||||||
|
@param y y point coordinate
|
||||||
|
@return CRYPT_OK if valid
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ltc_ecc_is_point(const ltc_ecc_dp *dp, void *x, void *y)
|
||||||
|
{
|
||||||
|
void *prime, *a, *b, *t1, *t2;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
prime = dp->prime;
|
||||||
|
b = dp->B;
|
||||||
|
a = dp->A;
|
||||||
|
|
||||||
|
if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) return err;
|
||||||
|
|
||||||
|
/* compute y^2 */
|
||||||
|
if ((err = mp_sqr(y, t1)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* compute x^3 */
|
||||||
|
if ((err = mp_sqr(x, t2)) != CRYPT_OK) goto cleanup;
|
||||||
|
if ((err = mp_mod(t2, prime, t2)) != CRYPT_OK) goto cleanup;
|
||||||
|
if ((err = mp_mul(x, t2, t2)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* compute y^2 - x^3 */
|
||||||
|
if ((err = mp_sub(t1, t2, t1)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* compute y^2 - x^3 - a*x */
|
||||||
|
if ((err = mp_submod(prime, a, prime, t2)) != CRYPT_OK) goto cleanup;
|
||||||
|
if ((err = mp_mulmod(t2, x, prime, t2)) != CRYPT_OK) goto cleanup;
|
||||||
|
if ((err = mp_addmod(t1, t2, prime, t1)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* adjust range (0, prime) */
|
||||||
|
while (mp_cmp_d(t1, 0) == LTC_MP_LT) {
|
||||||
|
if ((err = mp_add(t1, prime, t1)) != CRYPT_OK) goto cleanup;
|
||||||
|
}
|
||||||
|
while (mp_cmp(t1, prime) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, prime, t1)) != CRYPT_OK) goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* compare to b */
|
||||||
|
if (mp_cmp(t1, b) != LTC_MP_EQ) {
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
} else {
|
||||||
|
err = CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
mp_clear_multi(t1, t2, NULL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
62
src/pk/ecc/ltc_ecc_is_point_at_infinity.c
Normal file
62
src/pk/ecc/ltc_ecc_is_point_at_infinity.c
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
/* http://crypto.stackexchange.com/questions/41468/point-at-infinity-for-jacobian-coordinates
|
||||||
|
* a point at infinity is any point (x,y,0) such that y^2 == x^3, except (0,0,0)
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ltc_ecc_is_point_at_infinity(const ecc_point *P, void *modulus, int *retval)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
void *x3, *y2;
|
||||||
|
|
||||||
|
/* trivial case */
|
||||||
|
if (!mp_iszero(P->z)) {
|
||||||
|
*retval = 0;
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* point (0,0,0) is not at infinity */
|
||||||
|
if (mp_iszero(P->x) && mp_iszero(P->y)) {
|
||||||
|
*retval = 0;
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize */
|
||||||
|
if ((err = mp_init_multi(&x3, &y2, NULL)) != CRYPT_OK) goto done;
|
||||||
|
|
||||||
|
/* compute y^2 */
|
||||||
|
if ((err = mp_mulmod(P->y, P->y, modulus, y2)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* compute x^3 */
|
||||||
|
if ((err = mp_mulmod(P->x, P->x, modulus, x3)) != CRYPT_OK) goto cleanup;
|
||||||
|
if ((err = mp_mulmod(P->x, x3, modulus, x3)) != CRYPT_OK) goto cleanup;
|
||||||
|
|
||||||
|
/* test y^2 == x^3 */
|
||||||
|
err = CRYPT_OK;
|
||||||
|
if ((mp_cmp(x3, y2) == LTC_MP_EQ) && !mp_iszero(y2))
|
||||||
|
*retval = 1;
|
||||||
|
else
|
||||||
|
*retval = 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
mp_clear_multi(x3, y2, NULL);
|
||||||
|
done:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -1,44 +0,0 @@
|
|||||||
/* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
@file ltc_ecc_is_valid_idx.c
|
|
||||||
ECC Crypto, Tom St Denis
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef LTC_MECC
|
|
||||||
|
|
||||||
/** Returns whether an ECC idx is valid or not
|
|
||||||
@param n The idx number to check
|
|
||||||
@return 1 if valid, 0 if not
|
|
||||||
*/
|
|
||||||
int ltc_ecc_is_valid_idx(int n)
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
|
|
||||||
for (x = 0; ltc_ecc_sets[x].size != 0; x++);
|
|
||||||
/* -1 is a valid index --- indicating that the domain params were supplied by the user */
|
|
||||||
if ((n >= -1) && (n < x)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
/* ref: $Format:%D$ */
|
|
||||||
/* git commit: $Format:%H$ */
|
|
||||||
/* commit time: $Format:%ai$ */
|
|
||||||
|
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -37,6 +32,10 @@ int ltc_ecc_map(ecc_point *P, void *modulus, void *mp)
|
|||||||
LTC_ARGCHK(modulus != NULL);
|
LTC_ARGCHK(modulus != NULL);
|
||||||
LTC_ARGCHK(mp != NULL);
|
LTC_ARGCHK(mp != NULL);
|
||||||
|
|
||||||
|
if (mp_iszero(P->z)) {
|
||||||
|
return ltc_ecc_set_point_xyz(0, 0, 1, P);
|
||||||
|
}
|
||||||
|
|
||||||
if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
|
if ((err = mp_init_multi(&t1, &t2, NULL)) != CRYPT_OK) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,17 +23,20 @@
|
|||||||
@param kA What to multiple A by
|
@param kA What to multiple A by
|
||||||
@param B Second point to multiply
|
@param B Second point to multiply
|
||||||
@param kB What to multiple B by
|
@param kB What to multiple B by
|
||||||
@param C [out] Destination point (can overlap with A or B
|
@param C [out] Destination point (can overlap with A or B)
|
||||||
|
@param ma ECC curve parameter a in montgomery form
|
||||||
@param modulus Modulus for curve
|
@param modulus Modulus for curve
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
int ltc_ecc_mul2add(const ecc_point *A, void *kA,
|
||||||
ecc_point *B, void *kB,
|
const ecc_point *B, void *kB,
|
||||||
ecc_point *C,
|
ecc_point *C,
|
||||||
void *modulus)
|
void *ma,
|
||||||
|
void *modulus)
|
||||||
{
|
{
|
||||||
ecc_point *precomp[16];
|
ecc_point *precomp[16];
|
||||||
unsigned bitbufA, bitbufB, lenA, lenB, len, x, y, nA, nB, nibble;
|
unsigned bitbufA, bitbufB, lenA, lenB, len, nA, nB, nibble;
|
||||||
|
unsigned x, y;
|
||||||
unsigned char *tA, *tB;
|
unsigned char *tA, *tB;
|
||||||
int err, first;
|
int err, first;
|
||||||
void *mp, *mu;
|
void *mp, *mu;
|
||||||
@ -112,17 +110,17 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
|||||||
if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = mp_mulmod(B->z, mu, modulus, precomp[1<<2]->z)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
|
|
||||||
/* precomp [i,0](A + B) table */
|
/* precomp [i,0](A + B) table */
|
||||||
if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptdbl(precomp[1], precomp[2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptadd(precomp[1], precomp[2], precomp[3], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
|
|
||||||
/* precomp [0,i](A + B) table */
|
/* precomp [0,i](A + B) table */
|
||||||
if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptdbl(precomp[1<<2], precomp[2<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptadd(precomp[1<<2], precomp[2<<2], precomp[3<<2], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
|
|
||||||
/* precomp [i,j](A + B) table (i != 0, j != 0) */
|
/* precomp [i,j](A + B) table (i != 0, j != 0) */
|
||||||
for (x = 1; x < 4; x++) {
|
for (x = 1; x < 4; x++) {
|
||||||
for (y = 1; y < 4; y++) {
|
for (y = 1; y < 4; y++) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptadd(precomp[x], precomp[(y<<2)], precomp[x+(y<<2)], ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,8 +154,8 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
|||||||
/* double twice, only if this isn't the first */
|
/* double twice, only if this isn't the first */
|
||||||
if (first == 0) {
|
if (first == 0) {
|
||||||
/* double twice */
|
/* double twice */
|
||||||
if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(C, C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptdbl(C, C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if not both zero */
|
/* if not both zero */
|
||||||
@ -165,12 +163,10 @@ int ltc_ecc_mul2add(ecc_point *A, void *kA,
|
|||||||
if (first == 1) {
|
if (first == 1) {
|
||||||
/* if first, copy from table */
|
/* if first, copy from table */
|
||||||
first = 0;
|
first = 0;
|
||||||
if ((err = mp_copy(precomp[nA + (nB<<2)]->x, C->x)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_ecc_copy_point(precomp[nA + (nB<<2)], C)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
if ((err = mp_copy(precomp[nA + (nB<<2)]->y, C->y)) != CRYPT_OK) { goto ERR_MU; }
|
|
||||||
if ((err = mp_copy(precomp[nA + (nB<<2)]->z, C->z)) != CRYPT_OK) { goto ERR_MU; }
|
|
||||||
} else {
|
} else {
|
||||||
/* if not first, add from table */
|
/* if not first, add from table */
|
||||||
if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
if ((err = ltc_mp.ecc_ptadd(C, precomp[nA + (nB<<2)], C, ma, modulus, mp)) != CRYPT_OK) { goto ERR_MU; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,11 +29,11 @@
|
|||||||
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
|
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
|
||||||
{
|
{
|
||||||
ecc_point *tG, *M[8];
|
ecc_point *tG, *M[8];
|
||||||
int i, j, err;
|
int i, j, err, inf;
|
||||||
void *mu, *mp;
|
void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
|
||||||
ltc_mp_digit buf;
|
ltc_mp_digit buf;
|
||||||
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
|
int first, bitbuf, bitcpy, bitcnt, mode, digidx;
|
||||||
|
|
||||||
@ -47,18 +42,23 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
LTC_ARGCHK(R != NULL);
|
LTC_ARGCHK(R != NULL);
|
||||||
LTC_ARGCHK(modulus != NULL);
|
LTC_ARGCHK(modulus != NULL);
|
||||||
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* return the point at infinity */
|
||||||
|
return ltc_ecc_set_point_xyz(1, 1, 0, R);
|
||||||
|
}
|
||||||
|
|
||||||
/* init montgomery reduction */
|
/* init montgomery reduction */
|
||||||
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
|
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
|
||||||
return err;
|
if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
|
||||||
}
|
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_init(&mu)) != CRYPT_OK) {
|
|
||||||
mp_montgomery_free(mp);
|
/* for curves with a == -3 keep ma == NULL */
|
||||||
return err;
|
if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
|
||||||
}
|
if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
|
if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
|
||||||
mp_montgomery_free(mp);
|
if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
|
||||||
mp_clear(mu);
|
if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alloc ram for window temps */
|
/* alloc ram for window temps */
|
||||||
@ -68,9 +68,8 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
for (j = 0; j < i; j++) {
|
for (j = 0; j < i; j++) {
|
||||||
ltc_ecc_del_point(M[j]);
|
ltc_ecc_del_point(M[j]);
|
||||||
}
|
}
|
||||||
mp_montgomery_free(mp);
|
err = CRYPT_MEM;
|
||||||
mp_clear(mu);
|
goto error;
|
||||||
return CRYPT_MEM;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,9 +79,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
|
|
||||||
/* tG = G and convert to montgomery */
|
/* tG = G and convert to montgomery */
|
||||||
if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
|
if (mp_cmp_d(mu, 1) == LTC_MP_EQ) {
|
||||||
if ((err = mp_copy(G->x, tG->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(G, tG)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(G->y, tG->y)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_copy(G->z, tG->z)) != CRYPT_OK) { goto done; }
|
|
||||||
} else {
|
} else {
|
||||||
if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
|
if ((err = mp_mulmod(G->x, mu, modulus, tG->x)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
|
if ((err = mp_mulmod(G->y, mu, modulus, tG->y)) != CRYPT_OK) { goto done; }
|
||||||
@ -93,13 +90,13 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
|
|
||||||
/* calc the M tab, which holds kG for k==8..15 */
|
/* calc the M tab, which holds kG for k==8..15 */
|
||||||
/* M[0] == 8G */
|
/* M[0] == 8G */
|
||||||
if ((err = ltc_mp.ecc_ptdbl(tG, M[0], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(tG, M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(M[0], M[0], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
/* now find (8+k)G for k=1..7 */
|
/* now find (8+k)G for k=1..7 */
|
||||||
for (j = 9; j < 16; j++) {
|
for (j = 9; j < 16; j++) {
|
||||||
if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(M[j-9], tG, M[j-8], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup sliding window */
|
/* setup sliding window */
|
||||||
@ -133,7 +130,7 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
|
|
||||||
/* if the bit is zero and mode == 1 then we double */
|
/* if the bit is zero and mode == 1 then we double */
|
||||||
if (mode == 1 && i == 0) {
|
if (mode == 1 && i == 0) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,20 +142,18 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
/* if this is the first window we do a simple copy */
|
/* if this is the first window we do a simple copy */
|
||||||
if (first == 1) {
|
if (first == 1) {
|
||||||
/* R = kG [k = first window] */
|
/* R = kG [k = first window] */
|
||||||
if ((err = mp_copy(M[bitbuf-8]->x, R->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(M[bitbuf-8], R)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(M[bitbuf-8]->y, R->y)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_copy(M[bitbuf-8]->z, R->z)) != CRYPT_OK) { goto done; }
|
|
||||||
first = 0;
|
first = 0;
|
||||||
} else {
|
} else {
|
||||||
/* normal window */
|
/* normal window */
|
||||||
/* ok window is filled so double as required and add */
|
/* ok window is filled so double as required and add */
|
||||||
/* double first */
|
/* double first */
|
||||||
for (j = 0; j < WINSIZE; j++) {
|
for (j = 0; j < WINSIZE; j++) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
|
/* then add, bitbuf will be 8..15 [8..2^WINSIZE] guaranteed */
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(R, M[bitbuf-8], R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
/* empty window and reset */
|
/* empty window and reset */
|
||||||
bitcpy = bitbuf = 0;
|
bitcpy = bitbuf = 0;
|
||||||
@ -172,20 +167,18 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
for (j = 0; j < bitcpy; j++) {
|
for (j = 0; j < bitcpy; j++) {
|
||||||
/* only double if we have had at least one add first */
|
/* only double if we have had at least one add first */
|
||||||
if (first == 0) {
|
if (first == 0) {
|
||||||
if ((err = ltc_mp.ecc_ptdbl(R, R, modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(R, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
|
|
||||||
bitbuf <<= 1;
|
bitbuf <<= 1;
|
||||||
if ((bitbuf & (1 << WINSIZE)) != 0) {
|
if ((bitbuf & (1 << WINSIZE)) != 0) {
|
||||||
if (first == 1){
|
if (first == 1){
|
||||||
/* first add, so copy */
|
/* first add, so copy */
|
||||||
if ((err = mp_copy(tG->x, R->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(tG, R)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(tG->y, R->y)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_copy(tG->z, R->z)) != CRYPT_OK) { goto done; }
|
|
||||||
first = 0;
|
first = 0;
|
||||||
} else {
|
} else {
|
||||||
/* then add */
|
/* then add */
|
||||||
if ((err = ltc_mp.ecc_ptadd(R, tG, R, modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(R, tG, R, ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -198,14 +191,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
if (mu != NULL) {
|
|
||||||
mp_clear(mu);
|
|
||||||
}
|
|
||||||
mp_montgomery_free(mp);
|
|
||||||
ltc_ecc_del_point(tG);
|
ltc_ecc_del_point(tG);
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
ltc_ecc_del_point(M[i]);
|
ltc_ecc_del_point(M[i]);
|
||||||
}
|
}
|
||||||
|
error:
|
||||||
|
if (ma != NULL) mp_clear(ma);
|
||||||
|
if (a_plus3 != NULL) mp_clear(a_plus3);
|
||||||
|
if (mu != NULL) mp_clear(mu);
|
||||||
|
if (mp != NULL) mp_montgomery_free(mp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -28,15 +23,16 @@
|
|||||||
@param k The scalar to multiply by
|
@param k The scalar to multiply by
|
||||||
@param G The base point
|
@param G The base point
|
||||||
@param R [out] Destination for kG
|
@param R [out] Destination for kG
|
||||||
|
@param a ECC curve parameter a
|
||||||
@param modulus The modulus of the field the ECC curve is in
|
@param modulus The modulus of the field the ECC curve is in
|
||||||
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
|
@param map Boolean whether to map back to affine or not (1==map, 0 == leave in projective)
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
int ltc_ecc_mulmod(void *k, const ecc_point *G, ecc_point *R, void *a, void *modulus, int map)
|
||||||
{
|
{
|
||||||
ecc_point *tG, *M[3];
|
ecc_point *tG, *M[3];
|
||||||
int i, j, err;
|
int i, j, err, inf;
|
||||||
void *mu, *mp;
|
void *mp = NULL, *mu = NULL, *ma = NULL, *a_plus3 = NULL;
|
||||||
ltc_mp_digit buf;
|
ltc_mp_digit buf;
|
||||||
int bitcnt, mode, digidx;
|
int bitcnt, mode, digidx;
|
||||||
|
|
||||||
@ -45,18 +41,23 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
LTC_ARGCHK(R != NULL);
|
LTC_ARGCHK(R != NULL);
|
||||||
LTC_ARGCHK(modulus != NULL);
|
LTC_ARGCHK(modulus != NULL);
|
||||||
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(G, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* return the point at infinity */
|
||||||
|
return ltc_ecc_set_point_xyz(1, 1, 0, R);
|
||||||
|
}
|
||||||
|
|
||||||
/* init montgomery reduction */
|
/* init montgomery reduction */
|
||||||
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) {
|
if ((err = mp_montgomery_setup(modulus, &mp)) != CRYPT_OK) { goto error; }
|
||||||
return err;
|
if ((err = mp_init(&mu)) != CRYPT_OK) { goto error; }
|
||||||
}
|
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_init(&mu)) != CRYPT_OK) {
|
|
||||||
mp_montgomery_free(mp);
|
/* for curves with a == -3 keep ma == NULL */
|
||||||
return err;
|
if ((err = mp_init(&a_plus3)) != CRYPT_OK) { goto error; }
|
||||||
}
|
if ((err = mp_add_d(a, 3, a_plus3)) != CRYPT_OK) { goto error; }
|
||||||
if ((err = mp_montgomery_normalization(mu, modulus)) != CRYPT_OK) {
|
if (mp_cmp(a_plus3, modulus) != LTC_MP_EQ) {
|
||||||
mp_clear(mu);
|
if ((err = mp_init(&ma)) != CRYPT_OK) { goto error; }
|
||||||
mp_montgomery_free(mp);
|
if ((err = mp_mulmod(a, mu, modulus, ma)) != CRYPT_OK) { goto error; }
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* alloc ram for window temps */
|
/* alloc ram for window temps */
|
||||||
@ -85,11 +86,9 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
|
|
||||||
/* calc the M tab */
|
/* calc the M tab */
|
||||||
/* M[0] == G */
|
/* M[0] == G */
|
||||||
if ((err = mp_copy(tG->x, M[0]->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(tG, M[0])) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(tG->y, M[0]->y)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_copy(tG->z, M[0]->z)) != CRYPT_OK) { goto done; }
|
|
||||||
/* M[1] == 2G */
|
/* M[1] == 2G */
|
||||||
if ((err = ltc_mp.ecc_ptdbl(tG, M[1], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(tG, M[1], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
/* setup sliding window */
|
/* setup sliding window */
|
||||||
mode = 0;
|
mode = 0;
|
||||||
@ -110,32 +109,30 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* grab the next msb from the ltiplicand */
|
/* grab the next msb from the ltiplicand */
|
||||||
i = (buf >> (MP_DIGIT_BIT - 1)) & 1;
|
i = (int)((buf >> (MP_DIGIT_BIT - 1)) & 1);
|
||||||
buf <<= 1;
|
buf <<= 1;
|
||||||
|
|
||||||
if (mode == 0 && i == 0) {
|
if (mode == 0 && i == 0) {
|
||||||
/* dummy operations */
|
/* dummy operations */
|
||||||
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode == 0 && i == 1) {
|
if (mode == 0 && i == 1) {
|
||||||
mode = 1;
|
mode = 1;
|
||||||
/* dummy operations */
|
/* dummy operations */
|
||||||
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(M[1], M[2], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptadd(M[0], M[1], M[i^1], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], modulus, mp)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_mp.ecc_ptdbl(M[i], M[i], ma, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* copy result out */
|
/* copy result out */
|
||||||
if ((err = mp_copy(M[0]->x, R->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(M[0], R)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(M[0]->y, R->y)) != CRYPT_OK) { goto done; }
|
|
||||||
if ((err = mp_copy(M[0]->z, R->z)) != CRYPT_OK) { goto done; }
|
|
||||||
|
|
||||||
/* map R back from projective space */
|
/* map R back from projective space */
|
||||||
if (map) {
|
if (map) {
|
||||||
@ -144,14 +141,15 @@ int ltc_ecc_mulmod(void *k, ecc_point *G, ecc_point *R, void *modulus, int map)
|
|||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
}
|
}
|
||||||
done:
|
done:
|
||||||
if (mu != NULL) {
|
|
||||||
mp_clear(mu);
|
|
||||||
}
|
|
||||||
mp_montgomery_free(mp);
|
|
||||||
ltc_ecc_del_point(tG);
|
ltc_ecc_del_point(tG);
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
ltc_ecc_del_point(M[i]);
|
ltc_ecc_del_point(M[i]);
|
||||||
}
|
}
|
||||||
|
error:
|
||||||
|
if (ma != NULL) mp_clear(ma);
|
||||||
|
if (a_plus3 != NULL) mp_clear(a_plus3);
|
||||||
|
if (mu != NULL) mp_clear(mu);
|
||||||
|
if (mp != NULL) mp_montgomery_free(mp);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -51,6 +46,24 @@ void ltc_ecc_del_point(ecc_point *p)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ltc_ecc_set_point_xyz(ltc_mp_digit x, ltc_mp_digit y, ltc_mp_digit z, ecc_point *p)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if ((err = ltc_mp.set_int(p->x, x)) != CRYPT_OK) return err;
|
||||||
|
if ((err = ltc_mp.set_int(p->y, y)) != CRYPT_OK) return err;
|
||||||
|
if ((err = ltc_mp.set_int(p->z, z)) != CRYPT_OK) return err;
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ltc_ecc_copy_point(const ecc_point *src, ecc_point *dst)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
if ((err = ltc_mp.copy(src->x, dst->x)) != CRYPT_OK) return err;
|
||||||
|
if ((err = ltc_mp.copy(src->y, dst->y)) != CRYPT_OK) return err;
|
||||||
|
if ((err = ltc_mp.copy(src->z, dst->z)) != CRYPT_OK) return err;
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/* ref: $Format:%D$ */
|
/* ref: $Format:%D$ */
|
||||||
/* git commit: $Format:%H$ */
|
/* git commit: $Format:%H$ */
|
||||||
|
@ -7,11 +7,6 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -26,14 +21,15 @@
|
|||||||
@param P The point to add
|
@param P The point to add
|
||||||
@param Q The point to add
|
@param Q The point to add
|
||||||
@param R [out] The destination of the double
|
@param R [out] The destination of the double
|
||||||
|
@param ma ECC curve parameter a in montgomery form
|
||||||
@param modulus The modulus of the field the ECC curve is in
|
@param modulus The modulus of the field the ECC curve is in
|
||||||
@param mp The "b" value from montgomery_setup()
|
@param mp The "b" value from montgomery_setup()
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void *modulus, void *mp)
|
int ltc_ecc_projective_add_point(const ecc_point *P, const ecc_point *Q, ecc_point *R, void *ma, void *modulus, void *mp)
|
||||||
{
|
{
|
||||||
void *t1, *t2, *x, *y, *z;
|
void *t1, *t2, *x, *y, *z;
|
||||||
int err;
|
int err, inf;
|
||||||
|
|
||||||
LTC_ARGCHK(P != NULL);
|
LTC_ARGCHK(P != NULL);
|
||||||
LTC_ARGCHK(Q != NULL);
|
LTC_ARGCHK(Q != NULL);
|
||||||
@ -45,14 +41,32 @@ int ltc_ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, void
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* should we dbl instead? */
|
if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
|
if (inf) {
|
||||||
|
/* P is point at infinity >> Result = Q */
|
||||||
|
err = ltc_ecc_copy_point(Q, R);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
if ( (mp_cmp(P->x, Q->x) == LTC_MP_EQ) &&
|
if ((err = ltc_ecc_is_point_at_infinity(Q, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
(Q->z != NULL && mp_cmp(P->z, Q->z) == LTC_MP_EQ) &&
|
if (inf) {
|
||||||
(mp_cmp(P->y, Q->y) == LTC_MP_EQ || mp_cmp(P->y, t1) == LTC_MP_EQ)) {
|
/* Q is point at infinity >> Result = P */
|
||||||
mp_clear_multi(t1, t2, x, y, z, NULL);
|
err = ltc_ecc_copy_point(P, R);
|
||||||
return ltc_ecc_projective_dbl_point(P, R, modulus, mp);
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((mp_cmp(P->x, Q->x) == LTC_MP_EQ) && (mp_cmp(P->z, Q->z) == LTC_MP_EQ)) {
|
||||||
|
if (mp_cmp(P->y, Q->y) == LTC_MP_EQ) {
|
||||||
|
/* here P = Q >> Result = 2 * P (use doubling) */
|
||||||
|
mp_clear_multi(t1, t2, x, y, z, NULL);
|
||||||
|
return ltc_ecc_projective_dbl_point(P, R, ma, modulus, mp);
|
||||||
|
}
|
||||||
|
if ((err = mp_sub(modulus, Q->y, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(P->y, t1) == LTC_MP_EQ) {
|
||||||
|
/* here Q = -P >>> Result = the point at infinity */
|
||||||
|
err = ltc_ecc_set_point_xyz(1, 1, 0, R);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
|
if ((err = mp_copy(P->x, x)) != CRYPT_OK) { goto done; }
|
||||||
|
@ -7,13 +7,26 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* Implements ECC over Z/pZ for curve y^2 = x^3 - 3x + b
|
|
||||||
*
|
|
||||||
* All curves taken from NIST recommendation paper of July 1999
|
|
||||||
* Available at http://csrc.nist.gov/cryptval/dss.htm
|
|
||||||
*/
|
|
||||||
#include "tomcrypt.h"
|
#include "tomcrypt.h"
|
||||||
|
|
||||||
|
/* ### Point doubling in Jacobian coordinate system ###
|
||||||
|
*
|
||||||
|
* let us have a curve: y^2 = x^3 + a*x + b
|
||||||
|
* in Jacobian coordinates it becomes: y^2 = x^3 + a*x*z^4 + b*z^6
|
||||||
|
*
|
||||||
|
* The doubling of P = (Xp, Yp, Zp) is given by R = (Xr, Yr, Zr) where:
|
||||||
|
* Xr = M^2 - 2*S
|
||||||
|
* Yr = M * (S - Xr) - 8*T
|
||||||
|
* Zr = 2 * Yp * Zp
|
||||||
|
*
|
||||||
|
* M = 3 * Xp^2 + a*Zp^4
|
||||||
|
* T = Yp^4
|
||||||
|
* S = 4 * Xp * Yp^2
|
||||||
|
*
|
||||||
|
* SPECIAL CASE: when a == -3 we can compute M as
|
||||||
|
* M = 3 * (Xp^2 - Zp^4) = 3 * (Xp + Zp^2) * (Xp - Zp^2)
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@file ltc_ecc_projective_dbl_point.c
|
@file ltc_ecc_projective_dbl_point.c
|
||||||
ECC Crypto, Tom St Denis
|
ECC Crypto, Tom St Denis
|
||||||
@ -25,14 +38,15 @@
|
|||||||
Double an ECC point
|
Double an ECC point
|
||||||
@param P The point to double
|
@param P The point to double
|
||||||
@param R [out] The destination of the double
|
@param R [out] The destination of the double
|
||||||
|
@param ma ECC curve parameter a in montgomery form
|
||||||
@param modulus The modulus of the field the ECC curve is in
|
@param modulus The modulus of the field the ECC curve is in
|
||||||
@param mp The "b" value from montgomery_setup()
|
@param mp The "b" value from montgomery_setup()
|
||||||
@return CRYPT_OK on success
|
@return CRYPT_OK on success
|
||||||
*/
|
*/
|
||||||
int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void *mp)
|
int ltc_ecc_projective_dbl_point(const ecc_point *P, ecc_point *R, void *ma, void *modulus, void *mp)
|
||||||
{
|
{
|
||||||
void *t1, *t2;
|
void *t1, *t2;
|
||||||
int err;
|
int err, inf;
|
||||||
|
|
||||||
LTC_ARGCHK(P != NULL);
|
LTC_ARGCHK(P != NULL);
|
||||||
LTC_ARGCHK(R != NULL);
|
LTC_ARGCHK(R != NULL);
|
||||||
@ -44,9 +58,14 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (P != R) {
|
if (P != R) {
|
||||||
if ((err = mp_copy(P->x, R->x)) != CRYPT_OK) { goto done; }
|
if ((err = ltc_ecc_copy_point(P, R)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_copy(P->y, R->y)) != CRYPT_OK) { goto done; }
|
}
|
||||||
if ((err = mp_copy(P->z, R->z)) != CRYPT_OK) { goto done; }
|
|
||||||
|
if ((err = ltc_ecc_is_point_at_infinity(P, modulus, &inf)) != CRYPT_OK) return err;
|
||||||
|
if (inf) {
|
||||||
|
/* if P is point at infinity >> Result = point at infinity */
|
||||||
|
err = ltc_ecc_set_point_xyz(1, 1, 0, R);
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* t1 = Z * Z */
|
/* t1 = Z * Z */
|
||||||
@ -61,28 +80,56 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
|
|||||||
if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
|
if ((err = mp_sub(R->z, modulus, R->z)) != CRYPT_OK) { goto done; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* T2 = X - T1 */
|
if (ma == NULL) { /* special case for curves with a == -3 (10% faster than general case) */
|
||||||
if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
|
/* T2 = X - T1 */
|
||||||
if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
|
if ((err = mp_sub(R->x, t1, t2)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
|
if (mp_cmp_d(t2, 0) == LTC_MP_LT) {
|
||||||
|
if ((err = mp_add(t2, modulus, t2)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
|
/* T1 = X + T1 */
|
||||||
|
if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
|
/* T2 = T1 * T2 */
|
||||||
|
if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
|
/* T1 = 2T2 */
|
||||||
|
if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
|
/* T1 = T1 + T2 */
|
||||||
|
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* T1 = X + T1 */
|
else {
|
||||||
if ((err = mp_add(t1, R->x, t1)) != CRYPT_OK) { goto done; }
|
/* T2 = T1 * T1 */
|
||||||
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
if ((err = mp_sqr(t1, t2)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
}
|
/* T1 = T2 * a */
|
||||||
/* T2 = T1 * T2 */
|
if ((err = mp_mul(t2, ma, t1)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_mul(t1, t2, t2)) != CRYPT_OK) { goto done; }
|
if ((err = mp_montgomery_reduce(t1, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
|
/* T2 = X * X */
|
||||||
/* T1 = 2T2 */
|
if ((err = mp_sqr(R->x, t2)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_add(t2, t2, t1)) != CRYPT_OK) { goto done; }
|
if ((err = mp_montgomery_reduce(t2, modulus, mp)) != CRYPT_OK) { goto done; }
|
||||||
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
/* T1 = T2 + T1 */
|
||||||
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
|
||||||
}
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
/* T1 = T1 + T2 */
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
|
}
|
||||||
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
/* T1 = T2 + T1 */
|
||||||
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
|
/* T1 = T2 + T1 */
|
||||||
|
if ((err = mp_add(t1, t2, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(t1, modulus) != LTC_MP_LT) {
|
||||||
|
if ((err = mp_sub(t1, modulus, t1)) != CRYPT_OK) { goto done; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Y = 2Y */
|
/* Y = 2Y */
|
||||||
@ -135,7 +182,7 @@ int ltc_ecc_projective_dbl_point(ecc_point *P, ecc_point *R, void *modulus, void
|
|||||||
|
|
||||||
err = CRYPT_OK;
|
err = CRYPT_OK;
|
||||||
done:
|
done:
|
||||||
mp_clear_multi(t1, t2, NULL);
|
mp_clear_multi(t2, t1, NULL);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
69
src/pk/ecc/ltc_ecc_verify_key.c
Normal file
69
src/pk/ecc/ltc_ecc_verify_key.c
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/* 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.h"
|
||||||
|
|
||||||
|
/* origin of this code - OLPC */
|
||||||
|
|
||||||
|
#ifdef LTC_MECC
|
||||||
|
|
||||||
|
/**
|
||||||
|
Verify a key according to ANSI spec
|
||||||
|
@param key The key to validate
|
||||||
|
@return CRYPT_OK if successful
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ltc_ecc_verify_key(const ecc_key *key)
|
||||||
|
{
|
||||||
|
int err, inf;
|
||||||
|
ecc_point *point;
|
||||||
|
void *prime = key->dp.prime;
|
||||||
|
void *order = key->dp.order;
|
||||||
|
void *a = key->dp.A;
|
||||||
|
|
||||||
|
/* Test 1: Are the x and y points of the public key in the field? */
|
||||||
|
if (ltc_mp.compare_d(key->pubkey.z, 1) == LTC_MP_EQ) {
|
||||||
|
if ((ltc_mp.compare(key->pubkey.x, prime) != LTC_MP_LT) ||
|
||||||
|
(ltc_mp.compare(key->pubkey.y, prime) != LTC_MP_LT) ||
|
||||||
|
(ltc_mp.compare_d(key->pubkey.x, 0) == LTC_MP_LT) ||
|
||||||
|
(ltc_mp.compare_d(key->pubkey.y, 0) == LTC_MP_LT) ||
|
||||||
|
(mp_iszero(key->pubkey.x) && mp_iszero(key->pubkey.y))
|
||||||
|
)
|
||||||
|
{
|
||||||
|
err = CRYPT_INVALID_PACKET;
|
||||||
|
goto done2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Test 2: is the public key on the curve? */
|
||||||
|
if ((err = ltc_ecc_is_point(&key->dp, key->pubkey.x, key->pubkey.y)) != CRYPT_OK) { goto done2; }
|
||||||
|
|
||||||
|
/* Test 3: does nG = O? (n = order, O = point at infinity, G = public key) */
|
||||||
|
point = ltc_ecc_new_point();
|
||||||
|
if ((err = ltc_ecc_mulmod(order, &(key->pubkey), point, a, prime, 1)) != CRYPT_OK) { goto done1; }
|
||||||
|
|
||||||
|
err = ltc_ecc_is_point_at_infinity(point, prime, &inf);
|
||||||
|
if (err != CRYPT_OK || inf) {
|
||||||
|
err = CRYPT_ERROR;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
err = CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
done1:
|
||||||
|
ltc_ecc_del_point(point);
|
||||||
|
done2:
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ref: $Format:%D$ */
|
||||||
|
/* git commit: $Format:%H$ */
|
||||||
|
/* commit time: $Format:%ai$ */
|
@ -306,21 +306,11 @@ static void _der_tests_print_flexi(ltc_asn1_list* l, unsigned int level)
|
|||||||
case LTC_ASN1_OBJECT_IDENTIFIER:
|
case LTC_ASN1_OBJECT_IDENTIFIER:
|
||||||
name = "OBJECT IDENTIFIER";
|
name = "OBJECT IDENTIFIER";
|
||||||
{
|
{
|
||||||
unsigned long i;
|
unsigned long len = sizeof(buf);
|
||||||
int r;
|
if (pk_oid_num_to_str(l->data, l->size, buf, &len) != CRYPT_OK) {
|
||||||
char* s = buf;
|
fprintf(stderr, "%s boom\n", name);
|
||||||
int sz = sizeof(buf);
|
exit(EXIT_FAILURE);
|
||||||
for (i = 0; i < l->size; ++i) {
|
|
||||||
r = snprintf(s, sz, "%lu.", ((unsigned long*)l->data)[i]);
|
|
||||||
if (r < 0 || r >= sz) {
|
|
||||||
fprintf(stderr, "%s boom\n", name);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
s += r;
|
|
||||||
sz -= r;
|
|
||||||
}
|
}
|
||||||
/* replace the last . with a \0 */
|
|
||||||
*(s - 1) = '\0';
|
|
||||||
text = buf;
|
text = buf;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
596
tests/ecc_test.c
596
tests/ecc_test.c
@ -11,41 +11,42 @@
|
|||||||
#if defined(LTC_MECC)
|
#if defined(LTC_MECC)
|
||||||
|
|
||||||
static unsigned int sizes[] = {
|
static unsigned int sizes[] = {
|
||||||
#ifdef LTC_ECC112
|
#ifdef LTC_ECC_SECP112R1
|
||||||
14,
|
14,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC128
|
#ifdef LTC_ECC_SECP128R1
|
||||||
16,
|
16,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC160
|
#ifdef LTC_ECC_SECP160R1
|
||||||
20,
|
20,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC192
|
#ifdef LTC_ECC_SECP192R1
|
||||||
24,
|
24,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC224
|
#ifdef LTC_ECC_SECP224R1
|
||||||
28,
|
28,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC256
|
#ifdef LTC_ECC_SECP256R1
|
||||||
32,
|
32,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC384
|
#ifdef LTC_ECC_SECP384R1
|
||||||
48,
|
48,
|
||||||
#endif
|
#endif
|
||||||
#ifdef LTC_ECC521
|
#ifdef LTC_ECC_SECP512R1
|
||||||
65
|
66
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef LTC_ECC_SHAMIR
|
#ifdef LTC_ECC_SHAMIR
|
||||||
int ecc_test_shamir(void)
|
static int _ecc_test_shamir(void)
|
||||||
{
|
{
|
||||||
void *modulus, *mp, *kA, *kB, *rA, *rB;
|
void *a, *modulus, *mp, *kA, *kB, *rA, *rB;
|
||||||
|
void *mu, *ma;
|
||||||
ecc_point *G, *A, *B, *C1, *C2;
|
ecc_point *G, *A, *B, *C1, *C2;
|
||||||
int x, y, z;
|
int x, y, z;
|
||||||
unsigned char buf[ECC_BUF_SIZE];
|
unsigned char buf[ECC_BUF_SIZE];
|
||||||
|
|
||||||
DO(mp_init_multi(&kA, &kB, &rA, &rB, &modulus, NULL));
|
DO(mp_init_multi(&kA, &kB, &rA, &rB, &modulus, &a, &mu, &ma, NULL));
|
||||||
LTC_ARGCHK((G = ltc_ecc_new_point()) != NULL);
|
LTC_ARGCHK((G = ltc_ecc_new_point()) != NULL);
|
||||||
LTC_ARGCHK((A = ltc_ecc_new_point()) != NULL);
|
LTC_ARGCHK((A = ltc_ecc_new_point()) != NULL);
|
||||||
LTC_ARGCHK((B = ltc_ecc_new_point()) != NULL);
|
LTC_ARGCHK((B = ltc_ecc_new_point()) != NULL);
|
||||||
@ -54,17 +55,20 @@ int ecc_test_shamir(void)
|
|||||||
|
|
||||||
for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) {
|
for (x = 0; x < (int)(sizeof(sizes)/sizeof(sizes[0])); x++) {
|
||||||
/* get the base point */
|
/* get the base point */
|
||||||
for (z = 0; ltc_ecc_sets[z].name; z++) {
|
for (z = 0; ltc_ecc_curves[z].prime != NULL; z++) {
|
||||||
if (sizes[z] < (unsigned int)ltc_ecc_sets[z].size) break;
|
DO(mp_read_radix(modulus, ltc_ecc_curves[z].prime, 16));
|
||||||
|
if (sizes[x] <= mp_unsigned_bin_size(modulus)) break;
|
||||||
}
|
}
|
||||||
LTC_ARGCHK(ltc_ecc_sets[z].name != NULL);
|
LTC_ARGCHK(ltc_ecc_curves[z].prime != NULL);
|
||||||
|
|
||||||
/* load it */
|
/* load it */
|
||||||
DO(mp_read_radix(G->x, ltc_ecc_sets[z].Gx, 16));
|
DO(mp_read_radix(G->x, ltc_ecc_curves[z].Gx, 16));
|
||||||
DO(mp_read_radix(G->y, ltc_ecc_sets[z].Gy, 16));
|
DO(mp_read_radix(G->y, ltc_ecc_curves[z].Gy, 16));
|
||||||
DO(mp_set(G->z, 1));
|
DO(mp_set(G->z, 1));
|
||||||
DO(mp_read_radix(modulus, ltc_ecc_sets[z].prime, 16));
|
DO(mp_read_radix(a, ltc_ecc_curves[z].A, 16));
|
||||||
DO(mp_montgomery_setup(modulus, &mp));
|
DO(mp_montgomery_setup(modulus, &mp));
|
||||||
|
DO(mp_montgomery_normalization(mu, modulus));
|
||||||
|
DO(mp_mulmod(a, mu, modulus, ma));
|
||||||
|
|
||||||
/* do 100 random tests */
|
/* do 100 random tests */
|
||||||
for (y = 0; y < 100; y++) {
|
for (y = 0; y < 100; y++) {
|
||||||
@ -75,10 +79,10 @@ int ecc_test_shamir(void)
|
|||||||
DO(mp_read_unsigned_bin(rB, buf, sizes[x]));
|
DO(mp_read_unsigned_bin(rB, buf, sizes[x]));
|
||||||
|
|
||||||
/* compute rA * G = A */
|
/* compute rA * G = A */
|
||||||
DO(ltc_mp.ecc_ptmul(rA, G, A, modulus, 1));
|
DO(ltc_mp.ecc_ptmul(rA, G, A, a, modulus, 1));
|
||||||
|
|
||||||
/* compute rB * G = B */
|
/* compute rB * G = B */
|
||||||
DO(ltc_mp.ecc_ptmul(rB, G, B, modulus, 1));
|
DO(ltc_mp.ecc_ptmul(rB, G, B, a, modulus, 1));
|
||||||
|
|
||||||
/* pick a random kA, kB */
|
/* pick a random kA, kB */
|
||||||
LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
|
LTC_ARGCHK(yarrow_read(buf, sizes[x], &yarrow_prng) == sizes[x]);
|
||||||
@ -87,13 +91,13 @@ int ecc_test_shamir(void)
|
|||||||
DO(mp_read_unsigned_bin(kB, buf, sizes[x]));
|
DO(mp_read_unsigned_bin(kB, buf, sizes[x]));
|
||||||
|
|
||||||
/* now, compute kA*A + kB*B = C1 using the older method */
|
/* now, compute kA*A + kB*B = C1 using the older method */
|
||||||
DO(ltc_mp.ecc_ptmul(kA, A, C1, modulus, 0));
|
DO(ltc_mp.ecc_ptmul(kA, A, C1, a, modulus, 0));
|
||||||
DO(ltc_mp.ecc_ptmul(kB, B, C2, modulus, 0));
|
DO(ltc_mp.ecc_ptmul(kB, B, C2, a, modulus, 0));
|
||||||
DO(ltc_mp.ecc_ptadd(C1, C2, C1, modulus, mp));
|
DO(ltc_mp.ecc_ptadd(C1, C2, C1, a, modulus, mp));
|
||||||
DO(ltc_mp.ecc_map(C1, modulus, mp));
|
DO(ltc_mp.ecc_map(C1, modulus, mp));
|
||||||
|
|
||||||
/* now compute using mul2add */
|
/* now compute using mul2add */
|
||||||
DO(ltc_mp.ecc_mul2add(A, kA, B, kB, C2, modulus));
|
DO(ltc_mp.ecc_mul2add(A, kA, B, kB, C2, ma, modulus));
|
||||||
|
|
||||||
/* is they the sames? */
|
/* is they the sames? */
|
||||||
if ((mp_cmp(C1->x, C2->x) != LTC_MP_EQ) || (mp_cmp(C1->y, C2->y) != LTC_MP_EQ) || (mp_cmp(C1->z, C2->z) != LTC_MP_EQ)) {
|
if ((mp_cmp(C1->x, C2->x) != LTC_MP_EQ) || (mp_cmp(C1->y, C2->y) != LTC_MP_EQ) || (mp_cmp(C1->z, C2->z) != LTC_MP_EQ)) {
|
||||||
@ -108,159 +112,423 @@ int ecc_test_shamir(void)
|
|||||||
ltc_ecc_del_point(B);
|
ltc_ecc_del_point(B);
|
||||||
ltc_ecc_del_point(A);
|
ltc_ecc_del_point(A);
|
||||||
ltc_ecc_del_point(G);
|
ltc_ecc_del_point(G);
|
||||||
mp_clear_multi(kA, kB, rA, rB, modulus, NULL);
|
mp_clear_multi(kA, kB, rA, rB, modulus, a, mu, ma, NULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int ecc_tests (void)
|
static int _ecc_issue108(void)
|
||||||
{
|
{
|
||||||
unsigned char buf[4][4096], ch;
|
void *a, *modulus, *order;
|
||||||
unsigned long x, y, z, s;
|
ecc_point *Q, *Result;
|
||||||
int stat, stat2;
|
int err;
|
||||||
ecc_key usera, userb, pubKey, privKey;
|
const ltc_ecc_curve* dp;
|
||||||
|
|
||||||
if (ltc_mp.name == NULL) return CRYPT_NOP;
|
/* init */
|
||||||
|
if ((err = mp_init_multi(&modulus, &order, &a, NULL)) != CRYPT_OK) { return err; }
|
||||||
|
Q = ltc_ecc_new_point();
|
||||||
|
Result = ltc_ecc_new_point();
|
||||||
|
|
||||||
DO(ecc_test ());
|
/* ECC-224 AKA SECP224R1 */
|
||||||
|
if ((err = ecc_get_curve("SECP224R1", &dp)) != CRYPT_OK) { goto done; }
|
||||||
|
/* read A */
|
||||||
|
if ((err = mp_read_radix(a, (char *)dp->A, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
/* read modulus */
|
||||||
|
if ((err = mp_read_radix(modulus, (char *)dp->prime, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
/* read order */
|
||||||
|
if ((err = mp_read_radix(order, (char *)dp->order, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
/* read Q */
|
||||||
|
if ((err = mp_read_radix(Q->x, (char *)"EA3745501BBC6A70BBFDD8AEEDB18CF5073C6DC9AA7CBB5915170D60", 16)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = mp_read_radix(Q->y, (char *)"6C9CB8E68AABFEC989CAC5E2326E0448B7E69C3E56039BA21A44FDAC", 16)) != CRYPT_OK) { goto done; }
|
||||||
|
mp_set(Q->z, 1);
|
||||||
|
/* calculate nQ */
|
||||||
|
if ((err = ltc_mp.ecc_ptmul(order, Q, Result, a, modulus, 1)) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
for (s = 0; s < (sizeof(sizes)/sizeof(sizes[0])); s++) {
|
done:
|
||||||
/* make up two keys */
|
ltc_ecc_del_point(Result);
|
||||||
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera));
|
ltc_ecc_del_point(Q);
|
||||||
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb));
|
mp_clear_multi(modulus, order, a, NULL);
|
||||||
|
return err;
|
||||||
/* make the shared secret */
|
|
||||||
x = sizeof(buf[0]);
|
|
||||||
DO(ecc_shared_secret (&usera, &userb, buf[0], &x));
|
|
||||||
|
|
||||||
y = sizeof(buf[1]);
|
|
||||||
DO(ecc_shared_secret (&userb, &usera, buf[1], &y));
|
|
||||||
|
|
||||||
if (y != x) {
|
|
||||||
fprintf(stderr, "ecc Shared keys are not same size.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memcmp (buf[0], buf[1], x)) {
|
|
||||||
fprintf(stderr, "ecc Shared keys not same contents.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* now export userb */
|
|
||||||
y = sizeof(buf[0]);
|
|
||||||
DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb));
|
|
||||||
ecc_free (&userb);
|
|
||||||
|
|
||||||
/* import and make the shared secret again */
|
|
||||||
DO(ecc_import (buf[1], y, &userb));
|
|
||||||
|
|
||||||
z = sizeof(buf[0]);
|
|
||||||
DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
|
|
||||||
|
|
||||||
if (z != x) {
|
|
||||||
fprintf(stderr, "failed. Size don't match?");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (memcmp (buf[0], buf[2], x)) {
|
|
||||||
fprintf(stderr, "Failed. Contents didn't match.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* export with ANSI X9.63 */
|
|
||||||
y = sizeof(buf[1]);
|
|
||||||
DO(ecc_ansi_x963_export(&userb, buf[1], &y));
|
|
||||||
ecc_free (&userb);
|
|
||||||
|
|
||||||
/* now import the ANSI key */
|
|
||||||
DO(ecc_ansi_x963_import(buf[1], y, &userb));
|
|
||||||
|
|
||||||
/* shared secret */
|
|
||||||
z = sizeof(buf[0]);
|
|
||||||
DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
|
|
||||||
|
|
||||||
if (z != x) {
|
|
||||||
fprintf(stderr, "failed. Size don't match?");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (memcmp (buf[0], buf[2], x)) {
|
|
||||||
fprintf(stderr, "Failed. Contents didn't match.");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ecc_free (&usera);
|
|
||||||
ecc_free (&userb);
|
|
||||||
|
|
||||||
/* test encrypt_key */
|
|
||||||
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera));
|
|
||||||
|
|
||||||
/* export key */
|
|
||||||
x = sizeof(buf[0]);
|
|
||||||
DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera));
|
|
||||||
DO(ecc_import(buf[0], x, &pubKey));
|
|
||||||
x = sizeof(buf[0]);
|
|
||||||
DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera));
|
|
||||||
DO(ecc_import(buf[0], x, &privKey));
|
|
||||||
|
|
||||||
for (ch = 0; ch < 32; ch++) {
|
|
||||||
buf[0][ch] = ch;
|
|
||||||
}
|
|
||||||
y = sizeof (buf[1]);
|
|
||||||
DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey));
|
|
||||||
zeromem (buf[0], sizeof (buf[0]));
|
|
||||||
x = sizeof (buf[0]);
|
|
||||||
DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey));
|
|
||||||
if (x != 32) {
|
|
||||||
fprintf(stderr, "Failed (length)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (ch = 0; ch < 32; ch++) {
|
|
||||||
if (buf[0][ch] != ch) {
|
|
||||||
fprintf(stderr, "Failed (contents)");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* test sign_hash */
|
|
||||||
for (ch = 0; ch < 16; ch++) {
|
|
||||||
buf[0][ch] = ch;
|
|
||||||
}
|
|
||||||
x = sizeof (buf[1]);
|
|
||||||
DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey));
|
|
||||||
DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey));
|
|
||||||
buf[0][0] ^= 1;
|
|
||||||
DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey));
|
|
||||||
if (!(stat == 1 && stat2 == 0)) {
|
|
||||||
fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* test sign_hash_rfc7518 */
|
|
||||||
for (ch = 0; ch < 16; ch++) {
|
|
||||||
buf[0][ch] = ch;
|
|
||||||
}
|
|
||||||
x = sizeof (buf[1]);
|
|
||||||
DO(ecc_sign_hash_rfc7518(buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey));
|
|
||||||
DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat, &pubKey));
|
|
||||||
buf[0][0] ^= 1;
|
|
||||||
DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat2, &privKey));
|
|
||||||
if (!(stat == 1 && stat2 == 0)) {
|
|
||||||
fprintf(stderr, "ecc_verify_hash_rfc7518 failed %d, %d, ", stat, stat2);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
ecc_free (&usera);
|
|
||||||
ecc_free (&pubKey);
|
|
||||||
ecc_free (&privKey);
|
|
||||||
}
|
|
||||||
#ifdef LTC_ECC_SHAMIR
|
|
||||||
return ecc_test_shamir();
|
|
||||||
#else
|
|
||||||
return 0;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
static int _ecc_test_mp(void)
|
||||||
|
{
|
||||||
|
void *a, *modulus, *order;
|
||||||
|
ecc_point *G, *GG;
|
||||||
|
int i, err, primality;
|
||||||
|
|
||||||
|
if ((err = mp_init_multi(&modulus, &order, &a, NULL)) != CRYPT_OK) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
G = ltc_ecc_new_point();
|
||||||
|
GG = ltc_ecc_new_point();
|
||||||
|
if (G == NULL || GG == NULL) {
|
||||||
|
mp_clear_multi(modulus, order, NULL);
|
||||||
|
ltc_ecc_del_point(G);
|
||||||
|
ltc_ecc_del_point(GG);
|
||||||
|
return CRYPT_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; ltc_ecc_curves[i].prime != NULL; i++) {
|
||||||
|
if ((err = mp_read_radix(a, (char *)ltc_ecc_curves[i].A, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = mp_read_radix(modulus, (char *)ltc_ecc_curves[i].prime, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = mp_read_radix(order, (char *)ltc_ecc_curves[i].order, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
|
||||||
|
/* is prime actually prime? */
|
||||||
|
if ((err = mp_prime_is_prime(modulus, 8, &primality)) != CRYPT_OK) { goto done; }
|
||||||
|
if (primality == 0) {
|
||||||
|
err = CRYPT_FAIL_TESTVECTOR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* is order prime ? */
|
||||||
|
if ((err = mp_prime_is_prime(order, 8, &primality)) != CRYPT_OK) { goto done; }
|
||||||
|
if (primality == 0) {
|
||||||
|
err = CRYPT_FAIL_TESTVECTOR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = mp_read_radix(G->x, (char *)ltc_ecc_curves[i].Gx, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = mp_read_radix(G->y, (char *)ltc_ecc_curves[i].Gy, 16)) != CRYPT_OK) { goto done; }
|
||||||
|
mp_set(G->z, 1);
|
||||||
|
|
||||||
|
/* then we should have G == (order + 1)G */
|
||||||
|
if ((err = mp_add_d(order, 1, order)) != CRYPT_OK) { goto done; }
|
||||||
|
if ((err = ltc_mp.ecc_ptmul(order, G, GG, a, modulus, 1)) != CRYPT_OK) { goto done; }
|
||||||
|
if (mp_cmp(G->x, GG->x) != LTC_MP_EQ || mp_cmp(G->y, GG->y) != LTC_MP_EQ) {
|
||||||
|
err = CRYPT_FAIL_TESTVECTOR;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err = CRYPT_OK;
|
||||||
|
done:
|
||||||
|
ltc_ecc_del_point(GG);
|
||||||
|
ltc_ecc_del_point(G);
|
||||||
|
mp_clear_multi(order, modulus, a, NULL);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ecc_old_api(void)
|
||||||
|
{
|
||||||
|
unsigned char buf[4][4096], ch;
|
||||||
|
unsigned long x, y, z, s;
|
||||||
|
int stat, stat2;
|
||||||
|
ecc_key usera, userb, pubKey, privKey;
|
||||||
|
int low, high;
|
||||||
|
|
||||||
|
ecc_sizes(&low, &high);
|
||||||
|
if (low < 14 || high < 14 || low > 100 || high > 100 || high < low) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
|
||||||
|
for (s = 0; s < (sizeof(sizes)/sizeof(sizes[0])); s++) {
|
||||||
|
/* make up two keys */
|
||||||
|
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera));
|
||||||
|
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &userb));
|
||||||
|
if (ecc_get_size(&usera) != (int)sizes[s]) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
if (ecc_get_size(&userb) != (int)sizes[s]) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
|
||||||
|
/* make the shared secret */
|
||||||
|
x = sizeof(buf[0]);
|
||||||
|
DO(ecc_shared_secret (&usera, &userb, buf[0], &x));
|
||||||
|
|
||||||
|
y = sizeof(buf[1]);
|
||||||
|
DO(ecc_shared_secret (&userb, &usera, buf[1], &y));
|
||||||
|
|
||||||
|
if (y != x) {
|
||||||
|
fprintf(stderr, "ecc Shared keys are not same size.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (memcmp (buf[0], buf[1], x)) {
|
||||||
|
fprintf(stderr, "ecc Shared keys not same contents.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* now export userb */
|
||||||
|
y = sizeof(buf[0]);
|
||||||
|
DO(ecc_export (buf[1], &y, PK_PUBLIC, &userb));
|
||||||
|
ecc_free (&userb);
|
||||||
|
|
||||||
|
/* import and make the shared secret again */
|
||||||
|
DO(ecc_import (buf[1], y, &userb));
|
||||||
|
|
||||||
|
z = sizeof(buf[0]);
|
||||||
|
DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
|
||||||
|
|
||||||
|
if (z != x) {
|
||||||
|
fprintf(stderr, "failed. Size don't match?");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (memcmp (buf[0], buf[2], x)) {
|
||||||
|
fprintf(stderr, "Failed. Contents didn't match.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* export with ANSI X9.63 */
|
||||||
|
y = sizeof(buf[1]);
|
||||||
|
DO(ecc_ansi_x963_export(&userb, buf[1], &y));
|
||||||
|
ecc_free (&userb);
|
||||||
|
|
||||||
|
/* now import the ANSI key */
|
||||||
|
DO(ecc_ansi_x963_import(buf[1], y, &userb));
|
||||||
|
|
||||||
|
/* shared secret */
|
||||||
|
z = sizeof(buf[0]);
|
||||||
|
DO(ecc_shared_secret (&usera, &userb, buf[2], &z));
|
||||||
|
|
||||||
|
if (z != x) {
|
||||||
|
fprintf(stderr, "failed. Size don't match?");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (memcmp (buf[0], buf[2], x)) {
|
||||||
|
fprintf(stderr, "Failed. Contents didn't match.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ecc_free (&usera);
|
||||||
|
ecc_free (&userb);
|
||||||
|
|
||||||
|
/* test encrypt_key */
|
||||||
|
DO(ecc_make_key (&yarrow_prng, find_prng ("yarrow"), sizes[s], &usera));
|
||||||
|
|
||||||
|
/* export key */
|
||||||
|
x = sizeof(buf[0]);
|
||||||
|
DO(ecc_export(buf[0], &x, PK_PUBLIC, &usera));
|
||||||
|
DO(ecc_import(buf[0], x, &pubKey));
|
||||||
|
x = sizeof(buf[0]);
|
||||||
|
DO(ecc_export(buf[0], &x, PK_PRIVATE, &usera));
|
||||||
|
DO(ecc_import(buf[0], x, &privKey));
|
||||||
|
|
||||||
|
for (ch = 0; ch < 32; ch++) {
|
||||||
|
buf[0][ch] = ch;
|
||||||
|
}
|
||||||
|
y = sizeof (buf[1]);
|
||||||
|
DO(ecc_encrypt_key (buf[0], 32, buf[1], &y, &yarrow_prng, find_prng ("yarrow"), find_hash ("sha256"), &pubKey));
|
||||||
|
zeromem (buf[0], sizeof (buf[0]));
|
||||||
|
x = sizeof (buf[0]);
|
||||||
|
DO(ecc_decrypt_key (buf[1], y, buf[0], &x, &privKey));
|
||||||
|
if (x != 32) {
|
||||||
|
fprintf(stderr, "Failed (length)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
for (ch = 0; ch < 32; ch++) {
|
||||||
|
if (buf[0][ch] != ch) {
|
||||||
|
fprintf(stderr, "Failed (contents)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* test sign_hash */
|
||||||
|
for (ch = 0; ch < 16; ch++) {
|
||||||
|
buf[0][ch] = ch;
|
||||||
|
}
|
||||||
|
x = sizeof (buf[1]);
|
||||||
|
DO(ecc_sign_hash (buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey));
|
||||||
|
DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat, &pubKey));
|
||||||
|
buf[0][0] ^= 1;
|
||||||
|
DO(ecc_verify_hash (buf[1], x, buf[0], 16, &stat2, &privKey));
|
||||||
|
if (!(stat == 1 && stat2 == 0)) {
|
||||||
|
fprintf(stderr, "ecc_verify_hash failed %d, %d, ", stat, stat2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* test sign_hash_rfc7518 */
|
||||||
|
for (ch = 0; ch < 16; ch++) {
|
||||||
|
buf[0][ch] = ch;
|
||||||
|
}
|
||||||
|
x = sizeof (buf[1]);
|
||||||
|
DO(ecc_sign_hash_rfc7518(buf[0], 16, buf[1], &x, &yarrow_prng, find_prng ("yarrow"), &privKey));
|
||||||
|
DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat, &pubKey));
|
||||||
|
buf[0][0] ^= 1;
|
||||||
|
DO(ecc_verify_hash_rfc7518(buf[1], x, buf[0], 16, &stat2, &privKey));
|
||||||
|
if (!(stat == 1 && stat2 == 0)) {
|
||||||
|
fprintf(stderr, "ecc_verify_hash_rfc7518 failed %d, %d, ", stat, stat2);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
ecc_free (&usera);
|
||||||
|
ecc_free (&pubKey);
|
||||||
|
ecc_free (&privKey);
|
||||||
|
}
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ecc_new_api(void)
|
||||||
|
{
|
||||||
|
const char* names[] = {
|
||||||
|
#ifdef LTC_ECC_SECP112R1
|
||||||
|
"SECP112R1", "ECC-112",
|
||||||
|
"secp112r1", /* name is case-insensitive */
|
||||||
|
"S E C-P-1_1_2r1", /* should pass fuzzy matching */
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP112R2
|
||||||
|
"SECP112R2",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP128R1
|
||||||
|
"SECP128R1", "ECC-128",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP128R2
|
||||||
|
"SECP128R2",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160R1
|
||||||
|
"SECP160R1", "ECC-160",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160R2
|
||||||
|
"SECP160R2",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP160K1
|
||||||
|
"SECP160K1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP160R1
|
||||||
|
"BRAINPOOLP160R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP192R1
|
||||||
|
"SECP192R1", "NISTP192", "PRIME192V1", "ECC-192", "P-192",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V2
|
||||||
|
"PRIME192V2",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME192V3
|
||||||
|
"PRIME192V3",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP192K1
|
||||||
|
"SECP192K1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP192R1
|
||||||
|
"BRAINPOOLP192R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224R1
|
||||||
|
"SECP224R1", "NISTP224", "ECC-224", "P-224",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP224K1
|
||||||
|
"SECP224K1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP224R1
|
||||||
|
"BRAINPOOLP224R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V1
|
||||||
|
"PRIME239V1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V2
|
||||||
|
"PRIME239V2",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_PRIME239V3
|
||||||
|
"PRIME239V3",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256R1
|
||||||
|
"SECP256R1", "NISTP256", "PRIME256V1", "ECC-256", "P-256",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP256K1
|
||||||
|
"SECP256K1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP256R1
|
||||||
|
"BRAINPOOLP256R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP320R1
|
||||||
|
"BRAINPOOLP320R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP384R1
|
||||||
|
"SECP384R1", "NISTP384", "ECC-384", "P-384",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP384R1
|
||||||
|
"BRAINPOOLP384R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_BRAINPOOLP512R1
|
||||||
|
"BRAINPOOLP512R1",
|
||||||
|
#endif
|
||||||
|
#ifdef LTC_ECC_SECP521R1
|
||||||
|
"SECP521R1", "NISTP521", "ECC-521", "P-521",
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
int i, j, stat;
|
||||||
|
const ltc_ecc_curve* dp;
|
||||||
|
ecc_key key, privkey, pubkey;
|
||||||
|
unsigned char buf[1000];
|
||||||
|
unsigned long len;
|
||||||
|
unsigned char data16[16] = { 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1, 0xd1 };
|
||||||
|
unsigned long len16;
|
||||||
|
|
||||||
|
if (ltc_mp.name == NULL) return CRYPT_NOP;
|
||||||
|
|
||||||
|
for (i = 0; i < (int)(sizeof(names)/sizeof(names[0])); i++) {
|
||||||
|
DO(ecc_get_curve(names[i], &dp));
|
||||||
|
/* make new key */
|
||||||
|
DO(ecc_make_key_ex(&yarrow_prng, find_prng ("yarrow"), &key, dp));
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_export(buf, &len, PK_PRIVATE, &key));
|
||||||
|
DO(ecc_import_ex(buf, len, &privkey, dp));
|
||||||
|
ecc_free(&privkey);
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_export(buf, &len, PK_PUBLIC, &key));
|
||||||
|
DO(ecc_import_ex(buf, len, &pubkey, dp));
|
||||||
|
ecc_free(&pubkey);
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_ansi_x963_export(&key, buf, &len));
|
||||||
|
ecc_free(&key);
|
||||||
|
DO(ecc_ansi_x963_import_ex(buf, len, &pubkey, dp));
|
||||||
|
ecc_free(&pubkey);
|
||||||
|
|
||||||
|
/* generate new key */
|
||||||
|
DO(ecc_set_dp(dp, &key));
|
||||||
|
DO(ecc_generate_key(&yarrow_prng, find_prng ("yarrow"), &key));
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_get_key(buf, &len, PK_PRIVATE, &key));
|
||||||
|
ecc_free(&key);
|
||||||
|
|
||||||
|
/* load exported private key */
|
||||||
|
DO(ecc_set_dp(dp, &privkey));
|
||||||
|
DO(ecc_set_key(buf, len, PK_PRIVATE, &privkey));
|
||||||
|
|
||||||
|
#ifndef USE_TFM
|
||||||
|
/* XXX-FIXME: TFM does not support sqrtmod_prime */
|
||||||
|
/* export compressed public key */
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_get_key(buf, &len, PK_PUBLIC|PK_COMPRESSED, &privkey));
|
||||||
|
if (len != 1 + (unsigned)ecc_get_size(&privkey)) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
/* load exported public+compressed key */
|
||||||
|
DO(ecc_set_dp(dp, &pubkey));
|
||||||
|
DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey));
|
||||||
|
ecc_free(&pubkey);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* export long public key */
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_get_key(buf, &len, PK_PUBLIC, &privkey));
|
||||||
|
if (len != 1 + 2 * (unsigned)ecc_get_size(&privkey)) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
/* load exported public key */
|
||||||
|
DO(ecc_set_dp(dp, &pubkey));
|
||||||
|
DO(ecc_set_key(buf, len, PK_PUBLIC, &pubkey));
|
||||||
|
|
||||||
|
/* test signature */
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_sign_hash(data16, 16, buf, &len, &yarrow_prng, find_prng ("yarrow"), &privkey));
|
||||||
|
stat = 0;
|
||||||
|
DO(ecc_verify_hash(buf, len, data16, 16, &stat, &pubkey));
|
||||||
|
if (stat != 1) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
|
||||||
|
/* test encryption */
|
||||||
|
len = sizeof(buf);
|
||||||
|
DO(ecc_encrypt_key(data16, 16, buf, &len, &yarrow_prng, find_prng("yarrow"), find_hash("sha256"), &pubkey));
|
||||||
|
zeromem(data16, 16);
|
||||||
|
len16 = 16;
|
||||||
|
DO(ecc_decrypt_key(buf, len, data16, &len16, &privkey));
|
||||||
|
if (len16 != 16) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
for (j = 0; j < 16; j++) if (data16[j] != 0xd1) return CRYPT_FAIL_TESTVECTOR;
|
||||||
|
|
||||||
|
/* cleanup */
|
||||||
|
ecc_free(&privkey);
|
||||||
|
ecc_free(&pubkey);
|
||||||
|
}
|
||||||
|
return CRYPT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
int ecc_tests(void)
|
int ecc_tests(void)
|
||||||
{
|
{
|
||||||
return CRYPT_NOP;
|
DO(_ecc_old_api()); /* up to 1.18 */
|
||||||
|
DO(_ecc_new_api());
|
||||||
|
DO(_ecc_test_mp());
|
||||||
|
DO(_ecc_issue108());
|
||||||
|
#ifdef LTC_ECC_SHAMIR
|
||||||
|
DO(_ecc_test_shamir());
|
||||||
|
#endif
|
||||||
|
return CRYPT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user