diff options
Diffstat (limited to 'security/nss/lib/freebl/ecl')
-rw-r--r-- | security/nss/lib/freebl/ecl/README | 104 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/curve25519_64.c | 2 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecl-curve.h | 218 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecl-priv.h | 7 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecl.c | 127 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecl.h | 13 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecl_curve.c | 93 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/eclt.h | 30 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecp_25519.c | 3 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/ecp_jm.c | 11 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/tests/ec_naft.c | 121 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/tests/ecp_test.c | 409 | ||||
-rw-r--r-- | security/nss/lib/freebl/ecl/uint128.c | 5 |
13 files changed, 304 insertions, 839 deletions
diff --git a/security/nss/lib/freebl/ecl/README b/security/nss/lib/freebl/ecl/README index 04a8b3b01..2996822c8 100644 --- a/security/nss/lib/freebl/ecl/README +++ b/security/nss/lib/freebl/ecl/README @@ -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. diff --git a/security/nss/lib/freebl/ecl/curve25519_64.c b/security/nss/lib/freebl/ecl/curve25519_64.c index 89327ad1c..65f6bd41b 100644 --- a/security/nss/lib/freebl/ecl/curve25519_64.c +++ b/security/nss/lib/freebl/ecl/curve25519_64.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 diff --git a/security/nss/lib/freebl/ecl/ecl-curve.h b/security/nss/lib/freebl/ecl/ecl-curve.h index df061396c..fc8003f5d 100644 --- a/security/nss/lib/freebl/ecl/ecl-curve.h +++ b/security/nss/lib/freebl/ecl/ecl-curve.h @@ -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 */ }; diff --git a/security/nss/lib/freebl/ecl/ecl-priv.h b/security/nss/lib/freebl/ecl/ecl-priv.h index f43f19327..21685599d 100644 --- a/security/nss/lib/freebl/ecl/ecl-priv.h +++ b/security/nss/lib/freebl/ecl/ecl-priv.h @@ -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_ */ diff --git a/security/nss/lib/freebl/ecl/ecl.c b/security/nss/lib/freebl/ecl/ecl.c index 3540af781..ca87b490c 100644 --- a/security/nss/lib/freebl/ecl/ecl.c +++ b/security/nss/lib/freebl/ecl/ecl.c @@ -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,37 +133,16 @@ 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) { - mp_int irr, curvea, curveb, genx, geny, order; int bits; ECGroup *group = NULL; mp_err res = MP_OKAY; - /* initialize values */ - MP_DIGITS(&irr) = 0; - MP_DIGITS(&curvea) = 0; - MP_DIGITS(&curveb) = 0; - MP_DIGITS(&genx) = 0; - MP_DIGITS(&geny) = 0; - MP_DIGITS(&order) = 0; - MP_CHECKOK(mp_init(&irr)); - MP_CHECKOK(mp_init(&curvea)); - MP_CHECKOK(mp_init(&curveb)); - 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)); - /* determine number of bits */ bits = mpl_significant_bits(&irr) - 1; if (bits < MP_OKAY) { @@ -167,12 +151,12 @@ ecgroup_fromNameAndHex(const ECCurveName name, } /* determine which optimizations (if any) to use */ - if (params->field == ECField_GFp) { + if (field == ECField_GFp) { switch (name) { case ECCurve_SECG_PRIME_256R1: group = ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); + &order, cofactor); if (group == NULL) { res = MP_UNDEF; goto CLEANUP; @@ -183,7 +167,7 @@ ecgroup_fromNameAndHex(const ECCurveName name, case ECCurve_SECG_PRIME_521R1: group = ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); + &order, cofactor); if (group == NULL) { res = MP_UNDEF; goto CLEANUP; @@ -194,7 +178,7 @@ ecgroup_fromNameAndHex(const ECCurveName name, /* use generic arithmetic */ group = ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny, - &order, params->cofactor); + &order, cofactor); if (group == NULL) { res = MP_UNDEF; goto CLEANUP; @@ -206,62 +190,95 @@ ecgroup_fromNameAndHex(const ECCurveName name, } /* set name, if any */ - if ((group != NULL) && (params->text != NULL)) { - group->text = strdup(params->text); + 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; + ECGroup *group = NULL; + mp_err res = MP_OKAY; + + /* initialize values */ + MP_DIGITS(&irr) = 0; + MP_DIGITS(&curvea) = 0; + MP_DIGITS(&curveb) = 0; + MP_DIGITS(&genx) = 0; + MP_DIGITS(&geny) = 0; + MP_DIGITS(&order) = 0; + MP_CHECKOK(mp_init(&irr)); + MP_CHECKOK(mp_init(&curvea)); + MP_CHECKOK(mp_init(&curveb)); + MP_CHECKOK(mp_init(&genx)); + MP_CHECKOK(mp_init(&geny)); + MP_CHECKOK(mp_init(&order)); + 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)); + + group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order, + params->cofactor, params->field, params->text); + +CLEANUP: mp_clear(&irr); mp_clear(&curvea); mp_clear(&curveb); 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. */ diff --git a/security/nss/lib/freebl/ecl/ecl.h b/security/nss/lib/freebl/ecl/ecl.h index ddcbb1f3a..f6d5bc4ea 100644 --- a/security/nss/lib/freebl/ecl/ecl.h +++ b/security/nss/lib/freebl/ecl/ecl.h @@ -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 diff --git a/security/nss/lib/freebl/ecl/ecl_curve.c b/security/nss/lib/freebl/ecl/ecl_curve.c deleted file mode 100644 index cf090cfc3..000000000 --- a/security/nss/lib/freebl/ecl/ecl_curve.c +++ /dev/null @@ -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); -} diff --git a/security/nss/lib/freebl/ecl/eclt.h b/security/nss/lib/freebl/ecl/eclt.h new file mode 100644 index 000000000..e763706f2 --- /dev/null +++ b/security/nss/lib/freebl/ecl/eclt.h @@ -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_ */ diff --git a/security/nss/lib/freebl/ecl/ecp_25519.c b/security/nss/lib/freebl/ecl/ecp_25519.c index a8d41520e..1e7875fff 100644 --- a/security/nss/lib/freebl/ecl/ecp_25519.c +++ b/security/nss/lib/freebl/ecl/ecp_25519.c @@ -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; diff --git a/security/nss/lib/freebl/ecl/ecp_jm.c b/security/nss/lib/freebl/ecl/ecp_jm.c index a1106cea8..bd13fa050 100644 --- a/security/nss/lib/freebl/ecl/ecp_jm.c +++ b/security/nss/lib/freebl/ecl/ecp_jm.c @@ -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)); diff --git a/security/nss/lib/freebl/ecl/tests/ec_naft.c b/security/nss/lib/freebl/ecl/tests/ec_naft.c deleted file mode 100644 index 61ef15c36..000000000 --- a/security/nss/lib/freebl/ecl/tests/ec_naft.c +++ /dev/null @@ -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; -} diff --git a/security/nss/lib/freebl/ecl/tests/ecp_test.c b/security/nss/lib/freebl/ecl/tests/ecp_test.c deleted file mode 100644 index dcec4d747..000000000 --- a/security/nss/lib/freebl/ecl/tests/ecp_test.c +++ /dev/null @@ -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; -} diff --git a/security/nss/lib/freebl/ecl/uint128.c b/security/nss/lib/freebl/ecl/uint128.c index 22cbd023c..5465875ad 100644 --- a/security/nss/lib/freebl/ecl/uint128.c +++ b/security/nss/lib/freebl/ecl/uint128.c @@ -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; } |