Merge branch 'keycomp'
This commit is contained in:
@@ -65,6 +65,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
14,
|
||||
"SECP112R1",
|
||||
"DB7C2ABF62E35E668076BEAD208B",
|
||||
"DB7C2ABF62E35E668076BEAD2088",
|
||||
"659EF8BA043916EEDE8911702B22",
|
||||
"DB7C2ABF62E35E7628DFAC6561C5",
|
||||
"09487239995A5EE76B55F9C2F098",
|
||||
@@ -76,6 +77,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
16,
|
||||
"SECP128R1",
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFDFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"E87579C11079F43DD824993C2CEE5ED3",
|
||||
"FFFFFFFE0000000075A30D1B9038A115",
|
||||
"161FF7528B899B2D0C28607CA52C5B86",
|
||||
@@ -87,6 +89,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
20,
|
||||
"SECP160R1",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF7FFFFFFC",
|
||||
"1C97BEFC54BD7A8B65ACF89F81D4D4ADC565FA45",
|
||||
"0100000000000000000001F4C8F927AED3CA752257",
|
||||
"4A96B5688EF573284664698968C38BB913CBFC82",
|
||||
@@ -98,6 +101,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
24,
|
||||
"ECC-192",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFC",
|
||||
"64210519E59C80E70FA7E9AB72243049FEB8DEECC146B9B1",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22831",
|
||||
"188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012",
|
||||
@@ -109,6 +113,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
28,
|
||||
"ECC-224",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000001",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFE",
|
||||
"B4050A850C04B3ABF54132565044B0B7D7BFD8BA270B39432355FFB4",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFF16A2E0B8F03E13DD29455C5C2A3D",
|
||||
"B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21",
|
||||
@@ -120,6 +125,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
32,
|
||||
"ECC-256",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||
@@ -131,6 +137,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
48,
|
||||
"ECC-384",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||
@@ -142,6 +149,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
66,
|
||||
"ECC-521",
|
||||
"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"51953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||
"1FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||
"C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||
@@ -150,7 +158,7 @@ const ecc_set_type ecc_sets[] = {
|
||||
#endif
|
||||
{
|
||||
0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL
|
||||
}
|
||||
};
|
||||
|
||||
@@ -169,6 +177,13 @@ static int ecc_mul2add(ecc_point* A, mp_int* kA, ecc_point* B, mp_int* kB,
|
||||
ecc_point* C, mp_int* modulus);
|
||||
#endif
|
||||
|
||||
int mp_jacobi(mp_int* a, mp_int* p, int* c);
|
||||
int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret);
|
||||
int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d);
|
||||
|
||||
#ifdef HAVE_COMP_KEY
|
||||
static int ecc_export_x963_compressed(ecc_key*, byte* out, word32* outLen);
|
||||
#endif
|
||||
|
||||
/* helper for either lib */
|
||||
static int get_digit_count(mp_int* a)
|
||||
@@ -2197,10 +2212,26 @@ int ecc_export_x963(ecc_key* key, byte* out, word32* outLen)
|
||||
}
|
||||
|
||||
|
||||
/* export public ECC key in ANSI X9.63 format, extended with
|
||||
* compression option */
|
||||
int ecc_export_x963_ex(ecc_key* key, byte* out, word32* outLen, int compressed)
|
||||
{
|
||||
if (compressed == 0)
|
||||
return ecc_export_x963(key, out, outLen);
|
||||
#ifdef HAVE_COMP_KEY
|
||||
else
|
||||
return ecc_export_x963_compressed(key, out, outLen);
|
||||
#endif
|
||||
|
||||
return NOT_COMPILED_IN;
|
||||
}
|
||||
|
||||
|
||||
/* import public ECC key in ANSI X9.63 format */
|
||||
int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
|
||||
{
|
||||
int x, err;
|
||||
int compressed = 0;
|
||||
|
||||
if (in == NULL || key == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
@@ -2217,24 +2248,25 @@ int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
|
||||
}
|
||||
err = MP_OKAY;
|
||||
|
||||
/* check for 4, 6 or 7 */
|
||||
if (in[0] != 4 && in[0] != 6 && in[0] != 7) {
|
||||
/* check for 4, 2, or 3 */
|
||||
if (in[0] != 0x04 && in[0] != 0x02 && in[0] != 0x03) {
|
||||
err = ASN_PARSE_E;
|
||||
}
|
||||
|
||||
/* read data */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_unsigned_bin(&key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
|
||||
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_unsigned_bin(&key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
|
||||
(inLen-1)>>1);
|
||||
|
||||
if (err == MP_OKAY)
|
||||
mp_set(&key->pubkey.z, 1);
|
||||
if (in[0] == 0x02 || in[0] == 0x03) {
|
||||
#ifdef HAVE_COMP_KEY
|
||||
compressed = 1;
|
||||
#else
|
||||
err = NOT_COMPILED_IN;
|
||||
#endif
|
||||
}
|
||||
|
||||
if (err == MP_OKAY) {
|
||||
/* determine the idx */
|
||||
/* determine the idx */
|
||||
|
||||
if (compressed)
|
||||
inLen = (inLen-1)*2 + 1; /* used uncompressed len */
|
||||
|
||||
for (x = 0; ecc_sets[x].size != 0; x++) {
|
||||
if ((unsigned)ecc_sets[x].size >= ((inLen-1)>>1)) {
|
||||
break;
|
||||
@@ -2250,6 +2282,74 @@ int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key)
|
||||
}
|
||||
}
|
||||
|
||||
/* read data */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_unsigned_bin(&key->pubkey.x, (byte*)in+1, (inLen-1)>>1);
|
||||
|
||||
#ifdef HAVE_COMP_KEY
|
||||
if (err == MP_OKAY && compressed == 1) { /* build y */
|
||||
mp_int t1, t2, prime, a, b;
|
||||
|
||||
if (mp_init_multi(&t1, &t2, &prime, &a, &b, NULL) != MP_OKAY)
|
||||
err = MEMORY_E;
|
||||
|
||||
/* load prime */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_radix(&prime, (char *)key->dp->prime, 16);
|
||||
|
||||
/* load a */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_radix(&a, (char *)key->dp->Af, 16);
|
||||
|
||||
/* load b */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_read_radix(&b, (char *)key->dp->Bf, 16);
|
||||
|
||||
/* compute x^3 */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_sqr(&key->pubkey.x, &t1);
|
||||
|
||||
if (err == MP_OKAY)
|
||||
err = mp_mulmod(&t1, &key->pubkey.x, &prime, &t1);
|
||||
|
||||
/* compute x^3 + a*x */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_mulmod(&a, &key->pubkey.x, &prime, &t2);
|
||||
|
||||
if (err == MP_OKAY)
|
||||
err = mp_add(&t1, &t2, &t1);
|
||||
|
||||
/* compute x^3 + a*x + b */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_add(&t1, &b, &t1);
|
||||
|
||||
/* compute sqrt(x^3 + a*x + b) */
|
||||
if (err == MP_OKAY)
|
||||
err = mp_sqrtmod_prime(&t1, &prime, &t2);
|
||||
|
||||
/* adjust y */
|
||||
if (err == MP_OKAY) {
|
||||
if ((mp_isodd(&t2) && in[0] == 0x03) ||
|
||||
(!mp_isodd(&t2) && in[0] == 0x02)) {
|
||||
err = mp_mod(&t2, &prime, &key->pubkey.y);
|
||||
}
|
||||
else {
|
||||
err = mp_submod(&prime, &t2, &prime, &key->pubkey.y);
|
||||
}
|
||||
}
|
||||
|
||||
mp_clear(&prime);
|
||||
mp_clear(&t2);
|
||||
mp_clear(&t1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (err == MP_OKAY && compressed == 0)
|
||||
err = mp_read_unsigned_bin(&key->pubkey.y, (byte*)in+1+((inLen-1)>>1),
|
||||
(inLen-1)>>1);
|
||||
if (err == MP_OKAY)
|
||||
mp_set(&key->pubkey.z, 1);
|
||||
|
||||
if (err != MP_OKAY) {
|
||||
mp_clear(&key->pubkey.x);
|
||||
mp_clear(&key->pubkey.y);
|
||||
@@ -4424,4 +4524,308 @@ int ecc_decrypt(ecc_key* privKey, ecc_key* pubKey, const byte* msg,
|
||||
|
||||
#endif /* HAVE_ECC_ENCRYPT */
|
||||
|
||||
|
||||
#ifdef HAVE_COMP_KEY
|
||||
|
||||
/* computes the jacobi c = (a | n) (or Legendre if n is prime)
|
||||
* HAC pp. 73 Algorithm 2.149
|
||||
*/
|
||||
int mp_jacobi(mp_int* a, mp_int* p, int* c)
|
||||
{
|
||||
mp_int a1, p1;
|
||||
int k, s, r, res;
|
||||
mp_digit residue;
|
||||
|
||||
/* if p <= 0 return MP_VAL */
|
||||
if (mp_cmp_d(p, 0) != MP_GT) {
|
||||
return MP_VAL;
|
||||
}
|
||||
|
||||
/* step 1. if a == 0, return 0 */
|
||||
if (mp_iszero (a) == 1) {
|
||||
*c = 0;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* step 2. if a == 1, return 1 */
|
||||
if (mp_cmp_d (a, 1) == MP_EQ) {
|
||||
*c = 1;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* default */
|
||||
s = 0;
|
||||
|
||||
/* step 3. write a = a1 * 2**k */
|
||||
if ((res = mp_init_copy (&a1, a)) != MP_OKAY) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = mp_init (&p1)) != MP_OKAY) {
|
||||
mp_clear(&a1);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* divide out larger power of two */
|
||||
k = mp_cnt_lsb(&a1);
|
||||
res = mp_div_2d(&a1, k, &a1, NULL);
|
||||
|
||||
if (res == MP_OKAY) {
|
||||
/* step 4. if e is even set s=1 */
|
||||
if ((k & 1) == 0) {
|
||||
s = 1;
|
||||
} else {
|
||||
/* else set s=1 if p = 1/7 (mod 8) or s=-1 if p = 3/5 (mod 8) */
|
||||
residue = p->dp[0] & 7;
|
||||
|
||||
if (residue == 1 || residue == 7) {
|
||||
s = 1;
|
||||
} else if (residue == 3 || residue == 5) {
|
||||
s = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* step 5. if p == 3 (mod 4) *and* a1 == 3 (mod 4) then s = -s */
|
||||
if ( ((p->dp[0] & 3) == 3) && ((a1.dp[0] & 3) == 3)) {
|
||||
s = -s;
|
||||
}
|
||||
}
|
||||
|
||||
if (res == MP_OKAY) {
|
||||
/* if a1 == 1 we're done */
|
||||
if (mp_cmp_d (&a1, 1) == MP_EQ) {
|
||||
*c = s;
|
||||
} else {
|
||||
/* n1 = n mod a1 */
|
||||
res = mp_mod (p, &a1, &p1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_jacobi (&p1, &a1, &r);
|
||||
|
||||
if (res == MP_OKAY)
|
||||
*c = s * r;
|
||||
}
|
||||
}
|
||||
|
||||
/* done */
|
||||
mp_clear (&p1);
|
||||
mp_clear (&a1);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
int mp_sqrtmod_prime(mp_int* n, mp_int* prime, mp_int* ret)
|
||||
{
|
||||
int res, legendre, done = 0;
|
||||
mp_int t1, C, Q, S, Z, M, T, R, two;
|
||||
mp_digit i;
|
||||
|
||||
/* first handle the simple cases */
|
||||
if (mp_cmp_d(n, 0) == MP_EQ) {
|
||||
mp_zero(ret);
|
||||
return MP_OKAY;
|
||||
}
|
||||
if (mp_cmp_d(prime, 2) == MP_EQ) return MP_VAL; /* prime must be odd */
|
||||
/* TAO removed
|
||||
if ((res = mp_jacobi(n, prime, &legendre)) != MP_OKAY) return res;
|
||||
if (legendre == -1) return MP_VAL; */ /* quadratic non-residue mod prime */
|
||||
|
||||
if ((res = mp_init_multi(&t1, &C, &Q, &S, &Z, &M)) != MP_OKAY)
|
||||
return res;
|
||||
|
||||
if ((res = mp_init_multi(&T, &R, &two, NULL, NULL, NULL))
|
||||
!= MP_OKAY) {
|
||||
mp_clear(&t1); mp_clear(&C); mp_clear(&Q); mp_clear(&S); mp_clear(&Z);
|
||||
mp_clear(&M);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* SPECIAL CASE: if prime mod 4 == 3
|
||||
* compute directly: res = n^(prime+1)/4 mod prime
|
||||
* Handbook of Applied Cryptography algorithm 3.36
|
||||
*/
|
||||
res = mp_mod_d(prime, 4, &i);
|
||||
if (res == MP_OKAY && i == 3) {
|
||||
res = mp_add_d(prime, 1, &t1);
|
||||
|
||||
if (res == MP_OKAY)
|
||||
res = mp_div_2(&t1, &t1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_div_2(&t1, &t1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(n, &t1, prime, ret);
|
||||
|
||||
done = 1;
|
||||
}
|
||||
|
||||
|
||||
/* NOW: TonelliShanks algorithm */
|
||||
|
||||
if (res == MP_OKAY && done == 0) {
|
||||
|
||||
/* factor out powers of 2 from prime-1, defining Q and S
|
||||
* as: prime-1 = Q*2^S */
|
||||
|
||||
res = mp_copy(prime, &Q);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_sub_d(&Q, 1, &Q);
|
||||
/* Q = prime - 1 */
|
||||
if (res == MP_OKAY)
|
||||
mp_zero(&S);
|
||||
/* S = 0 */
|
||||
while (res == MP_OKAY && mp_iseven(&Q)) {
|
||||
res = mp_div_2(&Q, &Q);
|
||||
/* Q = Q / 2 */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_add_d(&S, 1, &S);
|
||||
/* S = S + 1 */
|
||||
}
|
||||
|
||||
/* find a Z such that the Legendre symbol (Z|prime) == -1 */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_set_int(&Z, 2);
|
||||
/* Z = 2 */
|
||||
while (res == MP_OKAY) {
|
||||
res = mp_jacobi(&Z, prime, &legendre);
|
||||
if (legendre == -1)
|
||||
break;
|
||||
if (res == MP_OKAY)
|
||||
res = mp_add_d(&Z, 1, &Z);
|
||||
/* Z = Z + 1 */
|
||||
}
|
||||
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(&Z, &Q, prime, &C);
|
||||
/* C = Z ^ Q mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_add_d(&Q, 1, &t1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_div_2(&t1, &t1);
|
||||
/* t1 = (Q + 1) / 2 */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(n, &t1, prime, &R);
|
||||
/* R = n ^ ((Q + 1) / 2) mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(n, &Q, prime, &T);
|
||||
/* T = n ^ Q mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_copy(&S, &M);
|
||||
/* M = S */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_set_int(&two, 2);
|
||||
|
||||
if (res == MP_OKAY)
|
||||
res = MP_VAL;
|
||||
while (res == MP_OKAY && done == 0) {
|
||||
res = mp_copy(&T, &t1);
|
||||
i = 0;
|
||||
while (res == MP_OKAY) {
|
||||
if (mp_cmp_d(&t1, 1) == MP_EQ)
|
||||
break;
|
||||
res = mp_exptmod(&t1, &two, prime, &t1);
|
||||
if (res == MP_OKAY)
|
||||
i++;
|
||||
}
|
||||
if (res == MP_OKAY && i == 0) {
|
||||
mp_copy(&R, ret);
|
||||
res = MP_OKAY;
|
||||
done = 1;
|
||||
}
|
||||
|
||||
if (done == 0) {
|
||||
if (res == MP_OKAY)
|
||||
res = mp_sub_d(&M, i, &t1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_sub_d(&t1, 1, &t1);
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(&two, &t1, prime, &t1);
|
||||
/* t1 = 2 ^ (M - i - 1) */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_exptmod(&C, &t1, prime, &t1);
|
||||
/* t1 = C ^ (2 ^ (M - i - 1)) mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_sqrmod(&t1, prime, &C);
|
||||
/* C = (t1 * t1) mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_mulmod(&R, &t1, prime, &R);
|
||||
/* R = (R * t1) mod prime */
|
||||
if (res == MP_OKAY)
|
||||
res = mp_mulmod(&T, &C, prime, &T);
|
||||
/* T = (T * C) mod prime */
|
||||
if (res == MP_OKAY)
|
||||
mp_set(&M, i);
|
||||
/* M = i */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* done */
|
||||
mp_clear(&t1);
|
||||
mp_clear(&C);
|
||||
mp_clear(&Q);
|
||||
mp_clear(&S);
|
||||
mp_clear(&Z);
|
||||
mp_clear(&M);
|
||||
mp_clear(&T);
|
||||
mp_clear(&R);
|
||||
mp_clear(&two);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/* export public ECC key in ANSI X9.63 format compressed */
|
||||
int ecc_export_x963_compressed(ecc_key* key, byte* out, word32* outLen)
|
||||
{
|
||||
word32 numlen;
|
||||
int ret = MP_OKAY;
|
||||
|
||||
if (key == NULL || out == NULL || outLen == NULL)
|
||||
return ECC_BAD_ARG_E;
|
||||
|
||||
if (ecc_is_valid_idx(key->idx) == 0) {
|
||||
return ECC_BAD_ARG_E;
|
||||
}
|
||||
numlen = key->dp->size;
|
||||
|
||||
if (*outLen < (1 + numlen)) {
|
||||
*outLen = 1 + numlen;
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
/* store first byte */
|
||||
out[0] = mp_isodd(&key->pubkey.y) ? 0x03 : 0x02;
|
||||
|
||||
/* pad and store x */
|
||||
XMEMSET(out+1, 0, numlen);
|
||||
ret = mp_to_unsigned_bin(&key->pubkey.x,
|
||||
out+1 + (numlen - mp_unsigned_bin_size(&key->pubkey.x)));
|
||||
*outLen = 1 + numlen;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* d = a - b (mod c) */
|
||||
int mp_submod(mp_int* a, mp_int* b, mp_int* c, mp_int* d)
|
||||
{
|
||||
int res;
|
||||
mp_int t;
|
||||
|
||||
if ((res = mp_init (&t)) != MP_OKAY) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if ((res = mp_sub (a, b, &t)) != MP_OKAY) {
|
||||
mp_clear (&t);
|
||||
return res;
|
||||
}
|
||||
res = mp_mod (&t, c, d);
|
||||
mp_clear (&t);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#endif /* HAVE_COMP_KEY */
|
||||
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
@@ -3932,9 +3932,41 @@ int mp_sub_d (mp_int * a, mp_digit b, mp_int * c)
|
||||
#endif /* defined(HAVE_ECC) || !defined(NO_PWDBASED) */
|
||||
|
||||
|
||||
#ifdef CYASSL_KEY_GEN
|
||||
#if defined(CYASSL_KEY_GEN) || defined(HAVE_COMP_KEY)
|
||||
|
||||
static const int lnz[16] = {
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
||||
};
|
||||
|
||||
/* Counts the number of lsbs which are zero before the first zero bit */
|
||||
int mp_cnt_lsb(mp_int *a)
|
||||
{
|
||||
int x;
|
||||
mp_digit q, qq;
|
||||
|
||||
/* easy out */
|
||||
if (mp_iszero(a) == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan lower digits until non-zero */
|
||||
for (x = 0; x < a->used && a->dp[x] == 0; x++);
|
||||
q = a->dp[x];
|
||||
x *= DIGIT_BIT;
|
||||
|
||||
/* now scan this digit until a 1 is found */
|
||||
if ((q & 1) == 0) {
|
||||
do {
|
||||
qq = q & 15;
|
||||
x += lnz[qq];
|
||||
q >>= 4;
|
||||
} while (qq == 0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int mp_cnt_lsb(mp_int *a);
|
||||
|
||||
static int s_is_power_of_two(mp_digit b, int *p)
|
||||
{
|
||||
@@ -4030,11 +4062,14 @@ static int mp_div_d (mp_int * a, mp_digit b, mp_int * c, mp_digit * d)
|
||||
}
|
||||
|
||||
|
||||
static int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
|
||||
int mp_mod_d (mp_int * a, mp_digit b, mp_digit * c)
|
||||
{
|
||||
return mp_div_d(a, b, NULL, c);
|
||||
}
|
||||
|
||||
#endif /* defined(CYASSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
|
||||
|
||||
#ifdef CYASSL_KEY_GEN
|
||||
|
||||
const mp_digit ltm_prime_tab[] = {
|
||||
0x0002, 0x0003, 0x0005, 0x0007, 0x000B, 0x000D, 0x0011, 0x0013,
|
||||
@@ -4291,37 +4326,6 @@ LBL_T:
|
||||
}
|
||||
|
||||
|
||||
static const int lnz[16] = {
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
||||
};
|
||||
|
||||
/* Counts the number of lsbs which are zero before the first zero bit */
|
||||
int mp_cnt_lsb(mp_int *a)
|
||||
{
|
||||
int x;
|
||||
mp_digit q, qq;
|
||||
|
||||
/* easy out */
|
||||
if (mp_iszero(a) == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan lower digits until non-zero */
|
||||
for (x = 0; x < a->used && a->dp[x] == 0; x++);
|
||||
q = a->dp[x];
|
||||
x *= DIGIT_BIT;
|
||||
|
||||
/* now scan this digit until a 1 is found */
|
||||
if ((q & 1) == 0) {
|
||||
do {
|
||||
qq = q & 15;
|
||||
x += lnz[qq];
|
||||
q >>= 4;
|
||||
} while (qq == 0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/* Greatest Common Divisor using the binary method */
|
||||
int mp_gcd (mp_int * a, mp_int * b, mp_int * c)
|
||||
|
||||
@@ -2035,34 +2035,40 @@ int mp_montgomery_calc_normalization(mp_int *a, mp_int *b)
|
||||
#endif /* CYASSL_KEYGEN || HAVE_ECC */
|
||||
|
||||
|
||||
#ifdef CYASSL_KEY_GEN
|
||||
#if defined(CYASSL_KEY_GEN) || defined(HAVE_COMP_KEY)
|
||||
|
||||
void fp_gcd(fp_int *a, fp_int *b, fp_int *c);
|
||||
void fp_lcm(fp_int *a, fp_int *b, fp_int *c);
|
||||
int fp_isprime(fp_int *a);
|
||||
int fp_cnt_lsb(fp_int *a);
|
||||
static const int lnz[16] = {
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
||||
};
|
||||
|
||||
int mp_gcd(fp_int *a, fp_int *b, fp_int *c)
|
||||
/* Counts the number of lsbs which are zero before the first zero bit */
|
||||
int fp_cnt_lsb(fp_int *a)
|
||||
{
|
||||
fp_gcd(a, b, c);
|
||||
return MP_OKAY;
|
||||
int x;
|
||||
fp_digit q, qq;
|
||||
|
||||
/* easy out */
|
||||
if (fp_iszero(a) == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan lower digits until non-zero */
|
||||
for (x = 0; x < a->used && a->dp[x] == 0; x++);
|
||||
q = a->dp[x];
|
||||
x *= DIGIT_BIT;
|
||||
|
||||
/* now scan this digit until a 1 is found */
|
||||
if ((q & 1) == 0) {
|
||||
do {
|
||||
qq = q & 15;
|
||||
x += lnz[qq];
|
||||
q >>= 4;
|
||||
} while (qq == 0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
int mp_lcm(fp_int *a, fp_int *b, fp_int *c)
|
||||
{
|
||||
fp_lcm(a, b, c);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
int mp_prime_is_prime(mp_int* a, int t, int* result)
|
||||
{
|
||||
(void)t;
|
||||
*result = fp_isprime(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int s_is_power_of_two(fp_digit b, int *p)
|
||||
@@ -2155,6 +2161,39 @@ static int fp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
|
||||
return fp_div_d(a, b, NULL, c);
|
||||
}
|
||||
|
||||
int mp_mod_d(fp_int *a, fp_digit b, fp_digit *c)
|
||||
{
|
||||
return fp_mod_d(a, b, c);
|
||||
}
|
||||
|
||||
#endif /* defined(CYASSL_KEY_GEN) || defined(HAVE_COMP_KEY) */
|
||||
|
||||
#ifdef CYASSL_KEY_GEN
|
||||
|
||||
void fp_gcd(fp_int *a, fp_int *b, fp_int *c);
|
||||
void fp_lcm(fp_int *a, fp_int *b, fp_int *c);
|
||||
int fp_isprime(fp_int *a);
|
||||
|
||||
int mp_gcd(fp_int *a, fp_int *b, fp_int *c)
|
||||
{
|
||||
fp_gcd(a, b, c);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
int mp_lcm(fp_int *a, fp_int *b, fp_int *c)
|
||||
{
|
||||
fp_lcm(a, b, c);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
|
||||
int mp_prime_is_prime(mp_int* a, int t, int* result)
|
||||
{
|
||||
(void)t;
|
||||
*result = fp_isprime(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* Miller-Rabin test of "a" to the base of "b" as described in
|
||||
* HAC pp. 139 Algorithm 4.24
|
||||
@@ -2304,37 +2343,6 @@ void fp_lcm(fp_int *a, fp_int *b, fp_int *c)
|
||||
}
|
||||
|
||||
|
||||
static const int lnz[16] = {
|
||||
4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0
|
||||
};
|
||||
|
||||
/* Counts the number of lsbs which are zero before the first zero bit */
|
||||
int fp_cnt_lsb(fp_int *a)
|
||||
{
|
||||
int x;
|
||||
fp_digit q, qq;
|
||||
|
||||
/* easy out */
|
||||
if (fp_iszero(a) == 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* scan lower digits until non-zero */
|
||||
for (x = 0; x < a->used && a->dp[x] == 0; x++);
|
||||
q = a->dp[x];
|
||||
x *= DIGIT_BIT;
|
||||
|
||||
/* now scan this digit until a 1 is found */
|
||||
if ((q & 1) == 0) {
|
||||
do {
|
||||
qq = q & 15;
|
||||
x += lnz[qq];
|
||||
q >>= 4;
|
||||
} while (qq == 0);
|
||||
}
|
||||
return x;
|
||||
}
|
||||
|
||||
|
||||
/* c = (a, b) */
|
||||
void fp_gcd(fp_int *a, fp_int *b, fp_int *c)
|
||||
@@ -2508,6 +2516,22 @@ int mp_init_copy(fp_int * a, fp_int * b)
|
||||
}
|
||||
|
||||
|
||||
#ifdef HAVE_COMP_KEY
|
||||
|
||||
int mp_cnt_lsb(fp_int* a)
|
||||
{
|
||||
fp_cnt_lsb(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
int mp_div_2d(fp_int* a, int b, fp_int* c, fp_int* d)
|
||||
{
|
||||
fp_div_2d(a, b, c, d);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
#endif /* HAVE_COMP_KEY */
|
||||
|
||||
|
||||
#endif /* HAVE_ECC */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user