mirror of
https://repo.dactyloidae.xyz/Dactyloidae/UXP.git
synced 2026-09-19 23:07:33 +09:00
Update NSS to 3.32.1-RTM
This commit is contained in:
parent
f29876f120
commit
c91ef9012b
512 changed files with 83203 additions and 16839 deletions
|
|
@ -90,20 +90,6 @@ the linear coefficient in the curve defining equation).
|
|||
|
||||
ecp_192.c and ecp_224.c provide optimized field arithmetic.
|
||||
|
||||
Point Arithmetic over Binary Polynomial Fields
|
||||
----------------------------------------------
|
||||
|
||||
ec2_aff.c provides point arithmetic using affine coordinates.
|
||||
|
||||
ec2_proj.c provides point arithmetic using projective coordinates.
|
||||
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
|
||||
x=X/Z, y=Y/Z^2).
|
||||
|
||||
ec2_mont.c provides point multiplication using Montgomery projective
|
||||
coordinates.
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
|
||||
|
||||
Field Arithmetic
|
||||
----------------
|
||||
|
||||
|
|
@ -126,18 +112,6 @@ fields defined by nistp192 and nistp224 primes.
|
|||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Binary Polynomial Field Arithmetic
|
||||
----------------------------------
|
||||
|
||||
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
|
||||
including addition, multiplication, squaring, mod, and division, as well
|
||||
as conversion ob polynomial representations between bitstring and int[].
|
||||
|
||||
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
|
||||
and sqr operations.
|
||||
|
||||
ecl_gf.c provides wrappers around the basic field operations.
|
||||
|
||||
Field Encoding
|
||||
--------------
|
||||
|
||||
|
|
@ -187,81 +161,3 @@ arithmetic. Instead, they use basic field arithmetic with their
|
|||
optimized reduction (as in ecp_192.c and ecp_224.c). They
|
||||
use the same point multiplication and simultaneous point multiplication
|
||||
algorithms as other curves over prime fields.
|
||||
|
||||
Curves over binary polynomial fields by default use generic field
|
||||
arithmetic with montgomery point multiplication and basic kP + lQ
|
||||
computation (multiply, multiply, and add). (Wiring in function
|
||||
ECGroup_cons_GF2m in ecl.c.)
|
||||
|
||||
Curves over binary polynomial fields that have optimized field
|
||||
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
|
||||
field arithmetic. They use the same point multiplication and
|
||||
simultaneous point multiplication algorithms as other curves over binary
|
||||
fields.
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
We provide an example for plugging in an optimized implementation for
|
||||
the Koblitz curve nistk163.
|
||||
|
||||
Suppose the file ec2_k163.c contains the optimized implementation. In
|
||||
particular it contains a point multiplication function:
|
||||
|
||||
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
|
||||
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
|
||||
|
||||
Since only a pt_mul function is provided, the generic pt_add function
|
||||
will be used.
|
||||
|
||||
There are two options for handling the optimized field arithmetic used
|
||||
by the ..._pt_mul function. Say the optimized field arithmetic includes
|
||||
the following functions:
|
||||
|
||||
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
|
||||
mp_int *r, const GFMethod *meth);
|
||||
|
||||
First, the optimized field arithmetic could simply be called directly
|
||||
by the ..._pt_mul function. This would be accomplished by changing
|
||||
the ecgroup_fromNameAndHex function in ecl.c to include the following
|
||||
statements:
|
||||
|
||||
if (name == ECCurve_NIST_K163) {
|
||||
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
|
||||
&geny, &order, params->cofactor);
|
||||
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
|
||||
MP_CHECKOK( ec_group_set_nistk163(group) );
|
||||
}
|
||||
|
||||
and including in ec2_k163.c the following function:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
As a result, ec_GF2m_pt_add and similar functions would use the
|
||||
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
|
||||
ec_GF2m_sqr, and ec_GF2m_div.
|
||||
|
||||
Alternatively, the optimized field arithmetic could be wired into the
|
||||
group's GFMethod. This would be accomplished by putting the following
|
||||
function in ec2_k163.c:
|
||||
|
||||
mp_err ec_group_set_nistk163(ECGroup *group) {
|
||||
group->meth->field_add = &ec_GF2m_nistk163_add;
|
||||
group->meth->field_mul = &ec_GF2m_nistk163_mul;
|
||||
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
|
||||
group->meth->field_div = &ec_GF2m_nistk163_div;
|
||||
group->point_mul = &ec_GF2m_nistk163_pt_mul;
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
For an example of functions that use special field encodings, take a
|
||||
look at ecp_mont.c.
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ fexpand(felem *output, const u8 *in)
|
|||
output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
|
||||
output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
|
||||
output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
|
||||
output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51;
|
||||
output[4] = (*((const uint64_t *)(in + 24)) >> 12) & MASK51;
|
||||
}
|
||||
|
||||
/* Take a fully reduced polynomial form number and contract it into a
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ecl-exp.h"
|
||||
#include "eclt.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifndef __ecl_curve_h_
|
||||
|
|
@ -12,52 +13,201 @@
|
|||
#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
|
||||
#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P256 = {
|
||||
static const PRUint8 irr256[32] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const PRUint8 a256[32] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
|
||||
static const PRUint8 b256[32] =
|
||||
{ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
|
||||
0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
|
||||
0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
|
||||
static const PRUint8 x256[32] =
|
||||
{ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
|
||||
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
|
||||
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
|
||||
static const PRUint8 y256[32] =
|
||||
{ 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
|
||||
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
|
||||
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
|
||||
static const PRUint8 order256[32] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
|
||||
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
|
||||
static const PRUint8 base256[66] =
|
||||
{ 0x04, 0x00,
|
||||
0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
|
||||
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
|
||||
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
|
||||
0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
|
||||
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
|
||||
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
|
||||
|
||||
static const ECCurveBytes ecCurve_NIST_P256 = {
|
||||
"NIST-P256", ECField_GFp, 256,
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
|
||||
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
|
||||
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
|
||||
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
|
||||
1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
irr256, a256, b256, x256, y256, order256, base256,
|
||||
1, 128, 66, 32,
|
||||
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P384 = {
|
||||
static const PRUint8 irr384[48] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const PRUint8 a384[48] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
|
||||
static const PRUint8 b384[48] =
|
||||
{ 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
|
||||
0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
|
||||
0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
|
||||
0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
|
||||
static const PRUint8 x384[48] =
|
||||
{ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
|
||||
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
|
||||
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
|
||||
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
|
||||
static const PRUint8 y384[48] =
|
||||
{ 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
|
||||
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
|
||||
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
|
||||
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
|
||||
static const PRUint8 order384[48] =
|
||||
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
|
||||
0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
|
||||
static const PRUint8 base384[98] =
|
||||
{ 0x04, 0x00,
|
||||
0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
|
||||
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
|
||||
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
|
||||
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
|
||||
0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
|
||||
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
|
||||
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
|
||||
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
|
||||
|
||||
static const ECCurveBytes ecCurve_NIST_P384 = {
|
||||
"NIST-P384", ECField_GFp, 384,
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
|
||||
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
|
||||
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
|
||||
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
|
||||
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
|
||||
1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
irr384, a384, b384, x384, y384, order384, base384,
|
||||
1, 192, 98, 48,
|
||||
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve_NIST_P521 = {
|
||||
static const PRUint8 irr521[66] =
|
||||
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
|
||||
static const PRUint8 a521[66] =
|
||||
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
|
||||
static const PRUint8 b521[66] =
|
||||
{ 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
|
||||
0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
|
||||
0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
|
||||
0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
|
||||
0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
|
||||
0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
|
||||
static const PRUint8 x521[66] =
|
||||
{ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
|
||||
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
|
||||
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
|
||||
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
|
||||
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
|
||||
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
|
||||
static const PRUint8 y521[66] =
|
||||
{ 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
|
||||
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
|
||||
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
|
||||
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
|
||||
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
|
||||
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
|
||||
static const PRUint8 order521[66] =
|
||||
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
|
||||
0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
|
||||
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
|
||||
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
|
||||
static const PRUint8 base521[134] =
|
||||
{
|
||||
0x04, 0x00,
|
||||
0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
|
||||
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
|
||||
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
|
||||
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
|
||||
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
|
||||
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
|
||||
0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
|
||||
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
|
||||
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
|
||||
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
|
||||
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
|
||||
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
|
||||
};
|
||||
|
||||
static const ECCurveBytes ecCurve_NIST_P521 = {
|
||||
"NIST-P521", ECField_GFp, 521,
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
|
||||
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
|
||||
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
|
||||
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
|
||||
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
|
||||
1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
irr521, a521, b521, x521, y521, order521, base521,
|
||||
1, 256, 134, 66,
|
||||
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
|
||||
};
|
||||
|
||||
static const ECCurveParams ecCurve25519 = {
|
||||
static const PRUint8 irr25519[32] =
|
||||
{ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
|
||||
static const PRUint8 a25519[32] =
|
||||
{ 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const PRUint8 b25519[32] =
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
static const PRUint8 x25519[32] =
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
|
||||
static const PRUint8 y25519[32] =
|
||||
{ 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
|
||||
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
|
||||
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
|
||||
static const PRUint8 order25519[32] =
|
||||
{ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
|
||||
0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
|
||||
static const PRUint8 base25519[66] =
|
||||
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
|
||||
0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
|
||||
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
|
||||
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
|
||||
|
||||
static const ECCurveBytes ecCurve_25519 = {
|
||||
"Curve25519", ECField_GFp, 255,
|
||||
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
|
||||
"076D06",
|
||||
"00",
|
||||
"0900000000000000000000000000000000000000000000000000000000000000",
|
||||
"20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
|
||||
"1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
|
||||
8, 128, 32, KU_KEY_AGREEMENT
|
||||
irr25519, a25519, b25519, x25519, y25519, order25519, base25519,
|
||||
8, 128, 66, 32,
|
||||
KU_KEY_AGREEMENT
|
||||
};
|
||||
|
||||
/* mapping between ECCurveName enum and pointers to ECCurveParams */
|
||||
static const ECCurveParams *ecCurve_map[] = {
|
||||
static const ECCurveBytes *ecCurve_map[] = {
|
||||
NULL, /* ECCurve_noName */
|
||||
NULL, /* ECCurve_NIST_P192 */
|
||||
NULL, /* ECCurve_NIST_P224 */
|
||||
|
|
@ -116,7 +266,7 @@ static const ECCurveParams *ecCurve_map[] = {
|
|||
NULL, /* ECCurve_WTLS_1 */
|
||||
NULL, /* ECCurve_WTLS_8 */
|
||||
NULL, /* ECCurve_WTLS_9 */
|
||||
&ecCurve25519, /* ECCurve25519 */
|
||||
&ecCurve_25519, /* ECCurve25519 */
|
||||
NULL /* ECCurve_pastLastCurve */
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -246,12 +246,5 @@ mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
|
|||
/* Optimized point multiplication */
|
||||
mp_err ec_group_set_gfp256_32(ECGroup *group, ECCurveName name);
|
||||
|
||||
/* Optimized floating-point arithmetic */
|
||||
#ifdef ECL_USE_FP
|
||||
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp192_fp(ECGroup *group);
|
||||
mp_err ec_group_set_nistp224_fp(ECGroup *group);
|
||||
#endif
|
||||
|
||||
SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
|
||||
#endif /* __ecl_priv_h_ */
|
||||
|
|
|
|||
|
|
@ -2,11 +2,16 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifdef FREEBL_NO_DEPEND
|
||||
#include "../stubs.h"
|
||||
#endif
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-priv.h"
|
||||
#include "ecp.h"
|
||||
#include "ecl-curve.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
@ -128,14 +133,84 @@ CLEANUP:
|
|||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hex parameters and name, if any. Called by
|
||||
* ECGroup_fromHex and ECGroup_fromName. */
|
||||
/* Construct an ECGroup. */
|
||||
ECGroup *
|
||||
ecgroup_fromNameAndHex(const ECCurveName name,
|
||||
const ECCurveParams *params)
|
||||
construct_ecgroup(const ECCurveName name, mp_int irr, mp_int curvea,
|
||||
mp_int curveb, mp_int genx, mp_int geny, mp_int order,
|
||||
int cofactor, ECField field, const char *text)
|
||||
{
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (field == ECField_GFp) {
|
||||
switch (name) {
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
MP_CHECKOK(ec_group_set_gfp256_32(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (text != NULL)) {
|
||||
group->text = strdup(text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
if (group && res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from parameters and name, if any. */
|
||||
ECGroup *
|
||||
ecgroup_fromName(const ECCurveName name,
|
||||
const ECCurveBytes *params)
|
||||
{
|
||||
mp_int irr, curvea, curveb, genx, geny, order;
|
||||
int bits;
|
||||
ECGroup *group = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
|
||||
|
|
@ -152,66 +227,15 @@ ecgroup_fromNameAndHex(const ECCurveName name,
|
|||
MP_CHECKOK(mp_init(&genx));
|
||||
MP_CHECKOK(mp_init(&geny));
|
||||
MP_CHECKOK(mp_init(&order));
|
||||
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
|
||||
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
|
||||
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
|
||||
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
|
||||
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&irr, params->irr, params->scalarSize));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&curvea, params->curvea, params->scalarSize));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&curveb, params->curveb, params->scalarSize));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&genx, params->genx, params->scalarSize));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&geny, params->geny, params->scalarSize));
|
||||
MP_CHECKOK(mp_read_unsigned_octets(&order, params->order, params->scalarSize));
|
||||
|
||||
/* determine number of bits */
|
||||
bits = mpl_significant_bits(&irr) - 1;
|
||||
if (bits < MP_OKAY) {
|
||||
res = bits;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* determine which optimizations (if any) to use */
|
||||
if (params->field == ECField_GFp) {
|
||||
switch (name) {
|
||||
case ECCurve_SECG_PRIME_256R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(ec_group_set_gfp256(group, name));
|
||||
MP_CHECKOK(ec_group_set_gfp256_32(group, name));
|
||||
break;
|
||||
case ECCurve_SECG_PRIME_521R1:
|
||||
group =
|
||||
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(ec_group_set_gfp521(group, name));
|
||||
break;
|
||||
default:
|
||||
/* use generic arithmetic */
|
||||
group =
|
||||
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
|
||||
&order, params->cofactor);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* set name, if any */
|
||||
if ((group != NULL) && (params->text != NULL)) {
|
||||
group->text = strdup(params->text);
|
||||
if (group->text == NULL) {
|
||||
res = MP_MEM;
|
||||
}
|
||||
}
|
||||
group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
|
||||
params->cofactor, params->field, params->text);
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&irr);
|
||||
|
|
@ -220,48 +244,41 @@ CLEANUP:
|
|||
mp_clear(&genx);
|
||||
mp_clear(&geny);
|
||||
mp_clear(&order);
|
||||
if (res != MP_OKAY) {
|
||||
if (group && res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromHex(const ECCurveParams *params)
|
||||
/* Construct ECCurveBytes from an ECCurveName */
|
||||
const ECCurveBytes *
|
||||
ec_GetNamedCurveParams(const ECCurveName name)
|
||||
{
|
||||
return ecgroup_fromNameAndHex(ECCurve_noName, params);
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ecCurve_map[name];
|
||||
}
|
||||
}
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *
|
||||
ECGroup_fromName(const ECCurveName name)
|
||||
{
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res = MP_OKAY;
|
||||
const ECCurveBytes *params = NULL;
|
||||
|
||||
params = EC_GetNamedCurveParams(name);
|
||||
/* This doesn't work with Curve25519 but it's not necessary to. */
|
||||
PORT_Assert(name != ECCurve25519);
|
||||
|
||||
params = ec_GetNamedCurveParams(name);
|
||||
if (params == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* construct actual group */
|
||||
group = ecgroup_fromNameAndHex(name, params);
|
||||
if (group == NULL) {
|
||||
res = MP_UNDEF;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
if (res != MP_OKAY) {
|
||||
ECGroup_free(group);
|
||||
return NULL;
|
||||
}
|
||||
return group;
|
||||
return ecgroup_fromName(name, params);
|
||||
}
|
||||
|
||||
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */
|
||||
|
|
|
|||
|
|
@ -11,28 +11,17 @@
|
|||
#include "blapi.h"
|
||||
#include "ecl-exp.h"
|
||||
#include "mpi.h"
|
||||
#include "eclt.h"
|
||||
|
||||
struct ECGroupStr;
|
||||
typedef struct ECGroupStr ECGroup;
|
||||
|
||||
/* Construct ECGroup from hexadecimal representations of parameters. */
|
||||
ECGroup *ECGroup_fromHex(const ECCurveParams *params);
|
||||
|
||||
/* Construct ECGroup from named parameters. */
|
||||
ECGroup *ECGroup_fromName(const ECCurveName name);
|
||||
|
||||
/* Free an allocated ECGroup. */
|
||||
void ECGroup_free(ECGroup *group);
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *ECCurveParams_dup(const ECCurveParams *params);
|
||||
|
||||
/* Free an allocated ECCurveParams */
|
||||
void EC_FreeCurveParams(ECCurveParams *params);
|
||||
|
||||
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
|
||||
* y). If x, y = NULL, then P is assumed to be the generator (base point)
|
||||
* of the group of points on the elliptic curve. Input and output values
|
||||
|
|
|
|||
|
|
@ -1,93 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecl-priv.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(func) \
|
||||
if ((func) == NULL) { \
|
||||
res = 0; \
|
||||
goto CLEANUP; \
|
||||
}
|
||||
|
||||
/* Duplicates an ECCurveParams */
|
||||
ECCurveParams *
|
||||
ECCurveParams_dup(const ECCurveParams *params)
|
||||
{
|
||||
int res = 1;
|
||||
ECCurveParams *ret = NULL;
|
||||
|
||||
CHECK(ret = (ECCurveParams *)calloc(1, sizeof(ECCurveParams)));
|
||||
if (params->text != NULL) {
|
||||
CHECK(ret->text = strdup(params->text));
|
||||
}
|
||||
ret->field = params->field;
|
||||
ret->size = params->size;
|
||||
if (params->irr != NULL) {
|
||||
CHECK(ret->irr = strdup(params->irr));
|
||||
}
|
||||
if (params->curvea != NULL) {
|
||||
CHECK(ret->curvea = strdup(params->curvea));
|
||||
}
|
||||
if (params->curveb != NULL) {
|
||||
CHECK(ret->curveb = strdup(params->curveb));
|
||||
}
|
||||
if (params->genx != NULL) {
|
||||
CHECK(ret->genx = strdup(params->genx));
|
||||
}
|
||||
if (params->geny != NULL) {
|
||||
CHECK(ret->geny = strdup(params->geny));
|
||||
}
|
||||
if (params->order != NULL) {
|
||||
CHECK(ret->order = strdup(params->order));
|
||||
}
|
||||
ret->cofactor = params->cofactor;
|
||||
|
||||
CLEANUP:
|
||||
if (res != 1) {
|
||||
EC_FreeCurveParams(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#undef CHECK
|
||||
|
||||
/* Construct ECCurveParams from an ECCurveName */
|
||||
ECCurveParams *
|
||||
EC_GetNamedCurveParams(const ECCurveName name)
|
||||
{
|
||||
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
|
||||
(ecCurve_map[name] == NULL)) {
|
||||
return NULL;
|
||||
} else {
|
||||
return ECCurveParams_dup(ecCurve_map[name]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free the memory allocated (if any) to an ECCurveParams object. */
|
||||
void
|
||||
EC_FreeCurveParams(ECCurveParams *params)
|
||||
{
|
||||
if (params == NULL)
|
||||
return;
|
||||
if (params->text != NULL)
|
||||
free(params->text);
|
||||
if (params->irr != NULL)
|
||||
free(params->irr);
|
||||
if (params->curvea != NULL)
|
||||
free(params->curvea);
|
||||
if (params->curveb != NULL)
|
||||
free(params->curveb);
|
||||
if (params->genx != NULL)
|
||||
free(params->genx);
|
||||
if (params->geny != NULL)
|
||||
free(params->geny);
|
||||
if (params->order != NULL)
|
||||
free(params->order);
|
||||
free(params);
|
||||
}
|
||||
30
security/nss/lib/freebl/ecl/eclt.h
Normal file
30
security/nss/lib/freebl/ecl/eclt.h
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
/* This header holds ECC types and must not be exported publicly. */
|
||||
|
||||
#ifndef __eclt_h_
|
||||
#define __eclt_h_
|
||||
|
||||
/* byte encoding of curve parameters */
|
||||
struct ECCurveBytesStr {
|
||||
char *text;
|
||||
ECField field;
|
||||
size_t size;
|
||||
const PRUint8 *irr;
|
||||
const PRUint8 *curvea;
|
||||
const PRUint8 *curveb;
|
||||
const PRUint8 *genx;
|
||||
const PRUint8 *geny;
|
||||
const PRUint8 *order;
|
||||
const PRUint8 *base;
|
||||
int cofactor;
|
||||
int security;
|
||||
size_t pointSize;
|
||||
size_t scalarSize;
|
||||
unsigned int usage;
|
||||
};
|
||||
typedef struct ECCurveBytesStr ECCurveBytes;
|
||||
|
||||
#endif /* __ecl_h_ */
|
||||
|
|
@ -79,8 +79,7 @@ ec_Curve25519_pt_validate(const SECItem *px)
|
|||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
|
||||
};
|
||||
|
||||
/* The point must not be longer than 32 (it can be smaller). */
|
||||
if (px->len <= 32) {
|
||||
if (px->len == 32) {
|
||||
p = px->data;
|
||||
} else {
|
||||
return SECFailure;
|
||||
|
|
|
|||
|
|
@ -127,6 +127,17 @@ ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
|
|||
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
|
||||
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
|
||||
|
||||
/* Check P == Q */
|
||||
if (mp_cmp(A, px) == 0) {
|
||||
if (mp_cmp(B, py) == 0) {
|
||||
/* If Px == Qx && Py == Qy, double P. */
|
||||
return ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
|
||||
scratch, group);
|
||||
}
|
||||
/* If Px == Qx && Py != Qy, return point at infinity. */
|
||||
return ec_GFp_pt_set_inf_jac(rx, ry, rz);
|
||||
}
|
||||
|
||||
/* C = A - px, D = B - py */
|
||||
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
|
||||
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));
|
||||
|
|
|
|||
|
|
@ -1,121 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "ecl.h"
|
||||
#include "ecp.h"
|
||||
#include "ecl-priv.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Returns 2^e as an integer. This is meant to be used for small powers of
|
||||
* two. */
|
||||
int ec_twoTo(int e);
|
||||
|
||||
/* Number of bits of scalar to test */
|
||||
#define BITSIZE 160
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) \
|
||||
{ \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ \
|
||||
op; \
|
||||
} \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
dUserTime = dNow - dStart; \
|
||||
if (dUserTime) \
|
||||
printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D.
|
||||
* Hankerson, J. Hernandez and A. Menezes, "Software implementation of
|
||||
* elliptic curve cryptography over binary fields", Proc. CHES 2000. */
|
||||
|
||||
mp_err
|
||||
main(void)
|
||||
{
|
||||
signed char naf[BITSIZE + 1];
|
||||
ECGroup *group = NULL;
|
||||
mp_int k;
|
||||
mp_int *scalar;
|
||||
int i, count;
|
||||
int res;
|
||||
int w = 5;
|
||||
char s[1000];
|
||||
|
||||
/* Get a 160 bit scalar to compute wNAF from */
|
||||
group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
|
||||
scalar = &group->genx;
|
||||
|
||||
/* Compute wNAF representation of scalar */
|
||||
ec_compute_wNAF(naf, BITSIZE, scalar, w);
|
||||
|
||||
/* Verify correctness of representation */
|
||||
mp_init(&k); /* init k to 0 */
|
||||
|
||||
for (i = BITSIZE; i >= 0; i--) {
|
||||
mp_add(&k, &k, &k);
|
||||
/* digits in mp_???_d are unsigned */
|
||||
if (naf[i] >= 0) {
|
||||
mp_add_d(&k, naf[i], &k);
|
||||
} else {
|
||||
mp_sub_d(&k, -naf[i], &k);
|
||||
}
|
||||
}
|
||||
|
||||
if (mp_cmp(&k, scalar) != 0) {
|
||||
printf("Error: incorrect NAF value.\n");
|
||||
MP_CHECKOK(mp_toradix(&k, s, 16));
|
||||
printf("NAF value %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(scalar, s, 16));
|
||||
printf("original value %s\n", s);
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* Verify digits of representation are valid */
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] % 2 == 0 && naf[i] != 0) {
|
||||
printf("Error: Even non-zero digit found.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
|
||||
printf("Error: Magnitude of naf digit too large.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify sparsity of representation */
|
||||
count = w - 1;
|
||||
for (i = 0; i <= BITSIZE; i++) {
|
||||
if (naf[i] != 0) {
|
||||
if (count < w - 1) {
|
||||
printf("Error: Sparsity failed.\n");
|
||||
goto CLEANUP;
|
||||
}
|
||||
count = 0;
|
||||
} else
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Check timing */
|
||||
M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
|
||||
|
||||
printf("Test passed.\n");
|
||||
CLEANUP:
|
||||
ECGroup_free(group);
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
|
@ -1,409 +0,0 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mpi.h"
|
||||
#include "mplogic.h"
|
||||
#include "mpprime.h"
|
||||
#include "ecl.h"
|
||||
#include "ecl-curve.h"
|
||||
#include "ecp.h"
|
||||
#include <stdio.h>
|
||||
#include <strings.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
/* Time k repetitions of operation op. */
|
||||
#define M_TimeOperation(op, k) \
|
||||
{ \
|
||||
double dStart, dNow, dUserTime; \
|
||||
struct rusage ru; \
|
||||
int i; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
for (i = 0; i < k; i++) { \
|
||||
{ \
|
||||
op; \
|
||||
} \
|
||||
}; \
|
||||
getrusage(RUSAGE_SELF, &ru); \
|
||||
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
|
||||
dUserTime = dNow - dStart; \
|
||||
if (dUserTime) \
|
||||
printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
|
||||
}
|
||||
|
||||
/* Test curve using generic field arithmetic. */
|
||||
#define ECTEST_GENERIC_GFP(name_c, name) \
|
||||
printf("Testing %s using generic implementation...\n", name_c); \
|
||||
params = EC_GetNamedCurveParams(name); \
|
||||
if (params == NULL) { \
|
||||
printf(" Error: could not construct params.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromHex(params); \
|
||||
if (group == NULL) { \
|
||||
printf(" Error: could not construct group.\n"); \
|
||||
res = MP_NO; \
|
||||
goto CLEANUP; \
|
||||
} \
|
||||
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 1)); \
|
||||
printf("... okay.\n");
|
||||
|
||||
/* Test curve using specific field arithmetic. */
|
||||
#define ECTEST_NAMED_GFP(name_c, name) \
|
||||
printf("Testing %s using specific implementation...\n", name_c); \
|
||||
ECGroup_free(group); \
|
||||
group = ECGroup_fromName(name); \
|
||||
if (group == NULL) { \
|
||||
printf(" Warning: could not construct group.\n"); \
|
||||
printf("... failed; continuing with remaining tests.\n"); \
|
||||
} else { \
|
||||
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 0)); \
|
||||
printf("... okay.\n"); \
|
||||
}
|
||||
|
||||
/* Performs basic tests of elliptic curve cryptography over prime fields.
|
||||
* If tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
|
||||
int generic)
|
||||
{
|
||||
|
||||
mp_int one, order_1, gx, gy, rx, ry, n;
|
||||
int size;
|
||||
mp_err res;
|
||||
char s[1000];
|
||||
|
||||
/* initialize values */
|
||||
MP_CHECKOK(mp_init(&one));
|
||||
MP_CHECKOK(mp_init(&order_1));
|
||||
MP_CHECKOK(mp_init(&gx));
|
||||
MP_CHECKOK(mp_init(&gy));
|
||||
MP_CHECKOK(mp_init(&rx));
|
||||
MP_CHECKOK(mp_init(&ry));
|
||||
MP_CHECKOK(mp_init(&n));
|
||||
|
||||
MP_CHECKOK(mp_set_int(&one, 1));
|
||||
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
|
||||
|
||||
/* encode base point */
|
||||
if (group->meth->field_dec) {
|
||||
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
|
||||
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
|
||||
} else {
|
||||
MP_CHECKOK(mp_copy(&group->genx, &gx));
|
||||
MP_CHECKOK(mp_copy(&group->geny, &gy));
|
||||
}
|
||||
if (ectestPrint) {
|
||||
/* output base point */
|
||||
printf(" base point P:\n");
|
||||
MP_CHECKOK(mp_toradix(&gx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&gy, s, 16));
|
||||
printf(" %s\n", s);
|
||||
if (group->meth->field_enc) {
|
||||
printf(" base point P (encoded):\n");
|
||||
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
|
||||
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order - 1 and check for negative of base
|
||||
* point */
|
||||
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (affine):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
|
||||
group));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (jacobian):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* multiply base point by order and check for point at infinity */
|
||||
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order)*P (ECPoint_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
|
||||
printf(" Error: invalid result (expected point at infinity).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* check that (order-1)P + (order-1)P + P == (order-1)P */
|
||||
MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
|
||||
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
|
||||
if (ectestPrint) {
|
||||
printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
|
||||
MP_CHECKOK(mp_toradix(&rx, s, 16));
|
||||
printf(" %s\n", s);
|
||||
MP_CHECKOK(mp_toradix(&ry, s, 16));
|
||||
printf(" %s\n", s);
|
||||
}
|
||||
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
|
||||
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
|
||||
printf(" Error: invalid result (expected (- base point)).\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
/* test validate_point function */
|
||||
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
|
||||
printf(" Error: validate point on base point failed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
|
||||
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
|
||||
printf(" Error: validate point on invalid point passed.\n");
|
||||
res = MP_NO;
|
||||
goto CLEANUP;
|
||||
}
|
||||
|
||||
if (ectestTime) {
|
||||
/* compute random scalar */
|
||||
size = mpl_significant_bits(&group->meth->irr);
|
||||
if (size < MP_OKAY) {
|
||||
goto CLEANUP;
|
||||
}
|
||||
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
|
||||
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
|
||||
/* timed test */
|
||||
if (generic) {
|
||||
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
|
||||
M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
|
||||
group)),
|
||||
100);
|
||||
#endif
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
} else {
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
|
||||
100);
|
||||
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
|
||||
}
|
||||
}
|
||||
|
||||
CLEANUP:
|
||||
mp_clear(&one);
|
||||
mp_clear(&order_1);
|
||||
mp_clear(&gx);
|
||||
mp_clear(&gy);
|
||||
mp_clear(&rx);
|
||||
mp_clear(&ry);
|
||||
mp_clear(&n);
|
||||
if (res != MP_OKAY) {
|
||||
printf(" Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Prints help information. */
|
||||
void
|
||||
printUsage()
|
||||
{
|
||||
printf("Usage: ecp_test [--print] [--time]\n");
|
||||
printf(" --print Print out results of each point arithmetic test.\n");
|
||||
printf(" --time Benchmark point operations and print results.\n");
|
||||
}
|
||||
|
||||
/* Performs tests of elliptic curve cryptography over prime fields If
|
||||
* tests fail, then it prints an error message, aborts, and returns an
|
||||
* error code. Otherwise, returns 0. */
|
||||
int
|
||||
main(int argv, char **argc)
|
||||
{
|
||||
|
||||
int ectestTime = 0;
|
||||
int ectestPrint = 0;
|
||||
int i;
|
||||
ECGroup *group = NULL;
|
||||
ECCurveParams *params = NULL;
|
||||
mp_err res;
|
||||
|
||||
/* read command-line arguments */
|
||||
for (i = 1; i < argv; i++) {
|
||||
if ((strcasecmp(argc[i], "time") == 0) || (strcasecmp(argc[i], "-time") == 0) || (strcasecmp(argc[i], "--time") == 0)) {
|
||||
ectestTime = 1;
|
||||
} else if ((strcasecmp(argc[i], "print") == 0) || (strcasecmp(argc[i], "-print") == 0) || (strcasecmp(argc[i], "--print") == 0)) {
|
||||
ectestPrint = 1;
|
||||
} else {
|
||||
printUsage();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* generic arithmetic tests */
|
||||
ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
|
||||
/* specific arithmetic tests */
|
||||
ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
|
||||
ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
|
||||
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
|
||||
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
|
||||
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
|
||||
ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
|
||||
ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
|
||||
ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
|
||||
ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
|
||||
ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
|
||||
ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
|
||||
ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
|
||||
ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
|
||||
ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
|
||||
ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
|
||||
ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
|
||||
ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
|
||||
ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
|
||||
ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
|
||||
ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
|
||||
ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
|
||||
ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
|
||||
ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
|
||||
ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
|
||||
ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
|
||||
ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
|
||||
ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
|
||||
|
||||
CLEANUP:
|
||||
EC_FreeCurveParams(params);
|
||||
ECGroup_free(group);
|
||||
if (res != MP_OKAY) {
|
||||
printf("Error: exiting with error value %i\n", res);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
|
@ -31,6 +31,9 @@ init128x(uint64_t x)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define CONSTANT_TIME_CARRY(a, b) \
|
||||
((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1))
|
||||
|
||||
/* arithmetic */
|
||||
|
||||
uint128_t
|
||||
|
|
@ -38,7 +41,7 @@ add128(uint128_t a, uint128_t b)
|
|||
{
|
||||
uint128_t ret;
|
||||
ret.lo = a.lo + b.lo;
|
||||
ret.hi = a.hi + b.hi + (ret.lo < b.lo);
|
||||
ret.hi = a.hi + b.hi + CONSTANT_TIME_CARRY(ret.lo, b.lo);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue