add compressed key support
This commit is contained in:
parent
b6345d654a
commit
3072edb696
4
certs/ecc-key-comp.pem
Normal file
4
certs/ecc-key-comp.pem
Normal file
@ -0,0 +1,4 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MFcCAQEEIEW2aQJznGyFoThbcujox6zEA41TNQT6bCjcNI3hqAmMoAoGCCqGSM49
|
||||
AwEHoSQDIgACuzOsTCdQSsZKpQTDPN6fNttyLc6U6iv6yyAJOSwW6GE=
|
||||
-----END EC PRIVATE KEY-----
|
@ -9,6 +9,7 @@ EXTRA_DIST += \
|
||||
certs/client-keyEnc.pem \
|
||||
certs/client-key.pem \
|
||||
certs/ecc-key.pem \
|
||||
certs/ecc-key-comp.pem \
|
||||
certs/ecc-keyPkcs8.pem \
|
||||
certs/ecc-client-key.pem \
|
||||
certs/client-ecc-cert.pem \
|
||||
@ -16,6 +17,7 @@ EXTRA_DIST += \
|
||||
certs/dh2048.pem \
|
||||
certs/server-cert.pem \
|
||||
certs/server-ecc.pem \
|
||||
certs/server-ecc-comp.pem \
|
||||
certs/server-ecc-rsa.pem \
|
||||
certs/server-keyEnc.pem \
|
||||
certs/server-key.pem \
|
||||
|
15
certs/server-ecc-comp.pem
Normal file
15
certs/server-ecc-comp.pem
Normal file
@ -0,0 +1,15 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIICZzCCAg2gAwIBAgIJAOpbhU0jW8ssMAoGCCqGSM49BAMCMIGfMQswCQYDVQQG
|
||||
EwJVUzETMBEGA1UECAwKV2FzaGluZ3RvbjEQMA4GA1UEBwwHRWRtb25kczEcMBoG
|
||||
A1UECgwTRWxsaXB0aWMgQ29tcHJlc3NlZDERMA8GA1UECwwIRUNDIENvbXAxGDAW
|
||||
BgNVBAMMD3d3dy53b2xmc3NsLmNvbTEeMBwGCSqGSIb3DQEJARYPd3d3LndvbGZz
|
||||
c2wuY29tMB4XDTE0MDgyNzIyNTczOVoXDTE3MDUyMzIyNTczOVowgZ8xCzAJBgNV
|
||||
BAYTAlVTMRMwEQYDVQQIDApXYXNoaW5ndG9uMRAwDgYDVQQHDAdFZG1vbmRzMRww
|
||||
GgYDVQQKDBNFbGxpcHRpYyBDb21wcmVzc2VkMREwDwYDVQQLDAhFQ0MgQ29tcDEY
|
||||
MBYGA1UEAwwPd3d3LndvbGZzc2wuY29tMR4wHAYJKoZIhvcNAQkBFg93d3cud29s
|
||||
ZnNzbC5jb20wOTATBgcqhkjOPQIBBggqhkjOPQMBBwMiAAK7M6xMJ1BKxkqlBMM8
|
||||
3p8223ItzpTqK/rLIAk5LBboYaNQME4wHQYDVR0OBBYEFIw4Omu4JLffbvRZrFZO
|
||||
quJYploYMB8GA1UdIwQYMBaAFIw4Omu4JLffbvRZrFZOquJYploYMAwGA1UdEwQF
|
||||
MAMBAf8wCgYIKoZIzj0EAwIDSAAwRQIgCNYOU7G50eHWoHoaadAXswKrN5Vj6nyh
|
||||
YUGS3zttSk4CIQD1Abqc61PBUQF6LO4OmBy79zEtWv9PRNH95iJ7V58vXA==
|
||||
-----END CERTIFICATE-----
|
@ -123,6 +123,8 @@ openssl dhparam -in dh2048.param -text > dh2048.pem
|
||||
make a new key
|
||||
openssl ecparam -genkey -text -name secp256r1 -out ecc-key.pem
|
||||
|
||||
convert to compressed
|
||||
openssl ec -in ecc-key.pem -conv_form compressed -out ecc-key-comp.pem
|
||||
|
||||
*** CRL ***
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#
|
||||
#
|
||||
|
||||
AC_INIT([cyassl],[3.1.1],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com])
|
||||
AC_INIT([cyassl],[3.1.2],[https://github.com/cyassl/cyassl/issues],[cyassl],[http://www.wolfssl.com])
|
||||
|
||||
AC_CONFIG_AUX_DIR([build-aux])
|
||||
|
||||
|
@ -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);
|
||||
@ -4315,4 +4415,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 */
|
||||
|
||||
|
@ -4472,8 +4472,32 @@ int ecc_test(void)
|
||||
return -1008;
|
||||
|
||||
if (memcmp(sharedA, sharedB, y))
|
||||
return -1009;
|
||||
|
||||
#ifdef HAVE_COMP_KEY
|
||||
/* try compressed export / import too */
|
||||
x = sizeof(exportBuf);
|
||||
ret = ecc_export_x963_ex(&userA, exportBuf, &x, 1);
|
||||
if (ret != 0)
|
||||
return -1010;
|
||||
|
||||
ecc_free(&pubKey);
|
||||
ecc_init(&pubKey);
|
||||
ret = ecc_import_x963(exportBuf, x, &pubKey);
|
||||
|
||||
if (ret != 0)
|
||||
return -1011;
|
||||
#endif
|
||||
|
||||
y = sizeof(sharedB);
|
||||
ret = ecc_shared_secret(&userB, &pubKey, sharedB, &y);
|
||||
|
||||
if (ret != 0)
|
||||
return -1012;
|
||||
|
||||
if (memcmp(sharedA, sharedB, y))
|
||||
return -1013;
|
||||
|
||||
/* test DSA sign hash */
|
||||
for (i = 0; i < (int)sizeof(digest); i++)
|
||||
digest[i] = (byte)i;
|
||||
@ -4482,21 +4506,21 @@ int ecc_test(void)
|
||||
ret = ecc_sign_hash(digest, sizeof(digest), sig, &x, &rng, &userA);
|
||||
|
||||
if (ret != 0)
|
||||
return -1016;
|
||||
return -1014;
|
||||
|
||||
verify = 0;
|
||||
ret = ecc_verify_hash(sig, x, digest, sizeof(digest), &verify, &userA);
|
||||
|
||||
if (ret != 0)
|
||||
return -1011;
|
||||
return -1015;
|
||||
|
||||
if (verify != 1)
|
||||
return -1012;
|
||||
return -1016;
|
||||
|
||||
x = sizeof(exportBuf);
|
||||
ret = ecc_export_private_only(&userA, exportBuf, &x);
|
||||
if (ret != 0)
|
||||
return -1013;
|
||||
return -1017;
|
||||
|
||||
ecc_free(&pubKey);
|
||||
ecc_free(&userB);
|
||||
|
@ -49,6 +49,7 @@ typedef struct {
|
||||
int size; /* The size of the curve in octets */
|
||||
const char* name; /* name of this curve */
|
||||
const char* prime; /* prime that defines the field, curve is in (hex) */
|
||||
const char* Af; /* fields A param (hex) */
|
||||
const char* Bf; /* fields B param (hex) */
|
||||
const char* order; /* order of the curve (hex) */
|
||||
const char* Gx; /* x coordinate of the base point on curve (hex) */
|
||||
@ -105,6 +106,9 @@ void ecc_fp_free(void);
|
||||
CYASSL_API
|
||||
int ecc_export_x963(ecc_key*, byte* out, word32* outLen);
|
||||
CYASSL_API
|
||||
int ecc_export_x963_ex(ecc_key*, byte* out, word32* outLen, int compressed);
|
||||
/* extended functionality with compressed option */
|
||||
CYASSL_API
|
||||
int ecc_import_x963(const byte* in, word32 inLen, ecc_key* key);
|
||||
CYASSL_API
|
||||
int ecc_import_private_key(const byte* priv, word32 privSz, const byte* pub,
|
||||
|
@ -310,6 +310,9 @@ int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e,
|
||||
int mp_lcm (mp_int * a, mp_int * b, mp_int * c);
|
||||
#endif
|
||||
|
||||
int mp_cnt_lsb(mp_int *a);
|
||||
int mp_mod_d(mp_int* a, mp_digit b, mp_digit* c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -398,7 +398,7 @@ void fp_mul_2(fp_int *a, fp_int *c);
|
||||
void fp_div_2(fp_int *a, fp_int *c);
|
||||
|
||||
/* Counts the number of lsbs which are zero before the first zero bit */
|
||||
/*int fp_cnt_lsb(fp_int *a);*/
|
||||
int fp_cnt_lsb(fp_int *a);
|
||||
|
||||
/* c = a + b */
|
||||
void fp_add(fp_int *a, fp_int *b, fp_int *c);
|
||||
@ -630,11 +630,14 @@ void fp_sqr_comba64(fp_int *a, fp_int *b);
|
||||
#define MP_LT FP_LT /* less than */
|
||||
#define MP_EQ FP_EQ /* equal to */
|
||||
#define MP_GT FP_GT /* greater than */
|
||||
#define MP_VAL FP_VAL /* invalid */
|
||||
#define MP_OKAY FP_OKAY /* ok result */
|
||||
#define MP_NO FP_NO /* yes/no result */
|
||||
#define MP_YES FP_YES /* yes/no result */
|
||||
|
||||
/* Prototypes */
|
||||
#define mp_zero(a) fp_zero(a)
|
||||
#define mp_iseven(a) fp_iseven(a)
|
||||
int mp_init (mp_int * a);
|
||||
void mp_clear (mp_int * a);
|
||||
int mp_init_multi(mp_int* a, mp_int* b, mp_int* c, mp_int* d, mp_int* e, mp_int* f);
|
||||
@ -686,6 +689,10 @@ int mp_lcm(fp_int *a, fp_int *b, fp_int *c);
|
||||
int mp_prime_is_prime(mp_int* a, int t, int* result);
|
||||
#endif /* CYASSL_KEY_GEN */
|
||||
|
||||
int mp_cnt_lsb(fp_int *a);
|
||||
int mp_div_2d(fp_int *a, int b, fp_int *c, fp_int *d);
|
||||
int mp_mod_d(fp_int* a, fp_digit b, fp_digit* c);
|
||||
|
||||
CYASSL_API word32 CheckRunTimeFastMath(void);
|
||||
|
||||
/* If user uses RSA, DH, DSA, or ECC math lib directly then fast math FP_SIZE
|
||||
|
@ -26,8 +26,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LIBCYASSL_VERSION_STRING "3.1.1"
|
||||
#define LIBCYASSL_VERSION_HEX 0x03001001
|
||||
#define LIBCYASSL_VERSION_STRING "3.1.2"
|
||||
#define LIBCYASSL_VERSION_HEX 0x03001002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user