Initial import.
This commit is contained in:
commit
3210f38e04
292 changed files with 58526 additions and 0 deletions
791
src/ec/ec_prime_i31.c
Normal file
791
src/ec/ec_prime_i31.c
Normal file
|
|
@ -0,0 +1,791 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/*
|
||||
* Parameters for supported curves (field modulus, and 'b' equation
|
||||
* parameter; both values use the 'i31' format, and 'b' is in Montgomery
|
||||
* representation).
|
||||
*/
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_R2[] = {
|
||||
0x00000108,
|
||||
0x00014000, 0x00018000, 0x00000000, 0x7FF40000,
|
||||
0x7FEFFFFF, 0x7FF7FFFF, 0x7FAFFFFF, 0x005FFFFF,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
static const uint32_t P384_P[] = {
|
||||
0x0000018C,
|
||||
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
|
||||
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x00000FFF
|
||||
};
|
||||
|
||||
static const uint32_t P384_R2[] = {
|
||||
0x0000018C,
|
||||
0x00000000, 0x00000080, 0x7FFFFE00, 0x000001FF,
|
||||
0x00000800, 0x00000000, 0x7FFFE000, 0x00001FFF,
|
||||
0x00008000, 0x00008000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P384_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
static const uint32_t P521_P[] = {
|
||||
0x00000219,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x01FFFFFF
|
||||
};
|
||||
|
||||
static const uint32_t P521_R2[] = {
|
||||
0x00000219,
|
||||
0x00001000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000
|
||||
};
|
||||
|
||||
static const uint32_t P521_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint32_t *p;
|
||||
const uint32_t *b;
|
||||
const uint32_t *R2;
|
||||
uint32_t p0i;
|
||||
} curve_params;
|
||||
|
||||
static inline const curve_params *
|
||||
id_to_curve(int curve)
|
||||
{
|
||||
static const curve_params pp[] = {
|
||||
{ P256_P, P256_B, P256_R2, 0x00000001 },
|
||||
{ P384_P, P384_B, P384_R2, 0x00000001 },
|
||||
{ P521_P, P521_B, P521_R2, 0x00000001 }
|
||||
};
|
||||
|
||||
return &pp[curve - BR_EC_secp256r1];
|
||||
}
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
|
||||
/*
|
||||
* Type for a point in Jacobian coordinates:
|
||||
* -- three values, x, y and z, in Montgomery representation
|
||||
* -- affine coordinates are X = x / z^2 and Y = y / z^3
|
||||
* -- for the point at infinity, z = 0
|
||||
*/
|
||||
typedef struct {
|
||||
uint32_t c[3][I31_LEN];
|
||||
} jacobian;
|
||||
|
||||
/*
|
||||
* We use a custom interpreter that uses a dozen registers, and
|
||||
* only four operations:
|
||||
* MSET(d, a) copy a into d
|
||||
* MADD(d, a) d = d+a (modular)
|
||||
* MSUB(d, a) d = d-a (modular)
|
||||
* MMUL(d, a, b) d = a*b (Montgomery multiplication)
|
||||
* MINV(d, a, b) invert d modulo p; a and b are used as scratch registers
|
||||
* MTZ(d) clear return value if d = 0
|
||||
* Destination of MMUL (d) must be distinct from operands (a and b).
|
||||
* There is no such constraint for MSUB and MADD.
|
||||
*
|
||||
* Registers include the operand coordinates, and temporaries.
|
||||
*/
|
||||
#define MSET(d, a) (0x0000 + ((d) << 8) + ((a) << 4))
|
||||
#define MADD(d, a) (0x1000 + ((d) << 8) + ((a) << 4))
|
||||
#define MSUB(d, a) (0x2000 + ((d) << 8) + ((a) << 4))
|
||||
#define MMUL(d, a, b) (0x3000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MINV(d, a, b) (0x4000 + ((d) << 8) + ((a) << 4) + (b))
|
||||
#define MTZ(d) (0x5000 + ((d) << 8))
|
||||
#define ENDCODE 0
|
||||
|
||||
/*
|
||||
* Registers for the input operands.
|
||||
*/
|
||||
#define P1x 0
|
||||
#define P1y 1
|
||||
#define P1z 2
|
||||
#define P2x 3
|
||||
#define P2y 4
|
||||
#define P2z 5
|
||||
|
||||
/*
|
||||
* Alternate names for the first input operand.
|
||||
*/
|
||||
#define Px 0
|
||||
#define Py 1
|
||||
#define Pz 2
|
||||
|
||||
/*
|
||||
* Temporaries.
|
||||
*/
|
||||
#define t1 6
|
||||
#define t2 7
|
||||
#define t3 8
|
||||
#define t4 9
|
||||
#define t5 10
|
||||
#define t6 11
|
||||
#define t7 12
|
||||
|
||||
/*
|
||||
* Extra scratch registers available when there is no second operand (e.g.
|
||||
* for "double" and "affine").
|
||||
*/
|
||||
#define t8 3
|
||||
#define t9 4
|
||||
#define t10 5
|
||||
|
||||
/*
|
||||
* Doubling formulas are:
|
||||
*
|
||||
* s = 4*x*y^2
|
||||
* m = 3*(x + z^2)*(x - z^2)
|
||||
* x' = m^2 - 2*s
|
||||
* y' = m*(s - x') - 8*y^4
|
||||
* z' = 2*y*z
|
||||
*
|
||||
* If y = 0 (P has order 2) then this yields infinity (z' = 0), as it
|
||||
* should. This case should not happen anyway, because our curves have
|
||||
* prime order, and thus do not contain any point of order 2.
|
||||
*
|
||||
* If P is infinity (z = 0), then again the formulas yield infinity,
|
||||
* which is correct. Thus, this code works for all points.
|
||||
*
|
||||
* Cost: 8 multiplications
|
||||
*/
|
||||
static const uint16_t code_double[] = {
|
||||
/*
|
||||
* Compute z^2 (in t1).
|
||||
*/
|
||||
MMUL(t1, Pz, Pz),
|
||||
|
||||
/*
|
||||
* Compute x-z^2 (in t2) and then x+z^2 (in t1).
|
||||
*/
|
||||
MSET(t2, Px),
|
||||
MSUB(t2, t1),
|
||||
MADD(t1, Px),
|
||||
|
||||
/*
|
||||
* Compute m = 3*(x+z^2)*(x-z^2) (in t1).
|
||||
*/
|
||||
MMUL(t3, t1, t2),
|
||||
MSET(t1, t3),
|
||||
MADD(t1, t3),
|
||||
MADD(t1, t3),
|
||||
|
||||
/*
|
||||
* Compute s = 4*x*y^2 (in t2) and 2*y^2 (in t3).
|
||||
*/
|
||||
MMUL(t3, Py, Py),
|
||||
MADD(t3, t3),
|
||||
MMUL(t2, Px, t3),
|
||||
MADD(t2, t2),
|
||||
|
||||
/*
|
||||
* Compute x' = m^2 - 2*s.
|
||||
*/
|
||||
MMUL(Px, t1, t1),
|
||||
MSUB(Px, t2),
|
||||
MSUB(Px, t2),
|
||||
|
||||
/*
|
||||
* Compute z' = 2*y*z.
|
||||
*/
|
||||
MMUL(t4, Py, Pz),
|
||||
MSET(Pz, t4),
|
||||
MADD(Pz, t4),
|
||||
|
||||
/*
|
||||
* Compute y' = m*(s - x') - 8*y^4. Note that we already have
|
||||
* 2*y^2 in t3.
|
||||
*/
|
||||
MSUB(t2, Px),
|
||||
MMUL(Py, t1, t2),
|
||||
MMUL(t4, t3, t3),
|
||||
MSUB(Py, t4),
|
||||
MSUB(Py, t4),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Addtions formulas are:
|
||||
*
|
||||
* u1 = x1 * z2^2
|
||||
* u2 = x2 * z1^2
|
||||
* s1 = y1 * z2^3
|
||||
* s2 = y2 * z1^3
|
||||
* h = u2 - u1
|
||||
* r = s2 - s1
|
||||
* x3 = r^2 - h^3 - 2 * u1 * h^2
|
||||
* y3 = r * (u1 * h^2 - x3) - s1 * h^3
|
||||
* z3 = h * z1 * z2
|
||||
*
|
||||
* If both P1 and P2 are infinity, then z1 == 0 and z2 == 0, implying that
|
||||
* z3 == 0, so the result is correct.
|
||||
* If either of P1 or P2 is infinity, but not both, then z3 == 0, which is
|
||||
* not correct.
|
||||
* h == 0 only if u1 == u2; this happens in two cases:
|
||||
* -- if s1 == s2 then P1 and/or P2 is infinity, or P1 == P2
|
||||
* -- if s1 != s2 then P1 + P2 == infinity (but neither P1 or P2 is infinity)
|
||||
*
|
||||
* Thus, the following situations are not handled correctly:
|
||||
* -- P1 = 0 and P2 != 0
|
||||
* -- P1 != 0 and P2 = 0
|
||||
* -- P1 = P2
|
||||
* All other cases are properly computed. However, even in "incorrect"
|
||||
* situations, the three coordinates still are properly formed field
|
||||
* elements.
|
||||
*
|
||||
* The returned flag is cleared if r == 0. This happens in the following
|
||||
* cases:
|
||||
* -- Both points are on the same horizontal line (same Y coordinate).
|
||||
* -- Both points are infinity.
|
||||
* -- One point is infinity and the other is on line Y = 0.
|
||||
* The third case cannot happen with our curves (there is no valid point
|
||||
* on line Y = 0 since that would be a point of order 2). If the two
|
||||
* source points are non-infinity, then remains only the case where the
|
||||
* two points are on the same horizontal line.
|
||||
*
|
||||
* This allows us to detect the "P1 == P2" case, assuming that P1 != 0 and
|
||||
* P2 != 0:
|
||||
* -- If the returned value is not the point at infinity, then it was properly
|
||||
* computed.
|
||||
* -- Otherwise, if the returned flag is 1, then P1+P2 = 0, and the result
|
||||
* is indeed the point at infinity.
|
||||
* -- Otherwise (result is infinity, flag is 0), then P1 = P2 and we should
|
||||
* use the 'double' code.
|
||||
*
|
||||
* Cost: 16 multiplications
|
||||
*/
|
||||
static const uint16_t code_add[] = {
|
||||
/*
|
||||
* Compute u1 = x1*z2^2 (in t1) and s1 = y1*z2^3 (in t3).
|
||||
*/
|
||||
MMUL(t3, P2z, P2z),
|
||||
MMUL(t1, P1x, t3),
|
||||
MMUL(t4, P2z, t3),
|
||||
MMUL(t3, P1y, t4),
|
||||
|
||||
/*
|
||||
* Compute u2 = x2*z1^2 (in t2) and s2 = y2*z1^3 (in t4).
|
||||
*/
|
||||
MMUL(t4, P1z, P1z),
|
||||
MMUL(t2, P2x, t4),
|
||||
MMUL(t5, P1z, t4),
|
||||
MMUL(t4, P2y, t5),
|
||||
|
||||
/*
|
||||
* Compute h = u2 - u1 (in t2) and r = s2 - s1 (in t4).
|
||||
*/
|
||||
MSUB(t2, t1),
|
||||
MSUB(t4, t3),
|
||||
|
||||
/*
|
||||
* Report cases where r = 0 through the returned flag.
|
||||
*/
|
||||
MTZ(t4),
|
||||
|
||||
/*
|
||||
* Compute u1*h^2 (in t6) and h^3 (in t5).
|
||||
*/
|
||||
MMUL(t7, t2, t2),
|
||||
MMUL(t6, t1, t7),
|
||||
MMUL(t5, t7, t2),
|
||||
|
||||
/*
|
||||
* Compute x3 = r^2 - h^3 - 2*u1*h^2.
|
||||
* t1 and t7 can be used as scratch registers.
|
||||
*/
|
||||
MMUL(P1x, t4, t4),
|
||||
MSUB(P1x, t5),
|
||||
MSUB(P1x, t6),
|
||||
MSUB(P1x, t6),
|
||||
|
||||
/*
|
||||
* Compute y3 = r*(u1*h^2 - x3) - s1*h^3.
|
||||
*/
|
||||
MSUB(t6, P1x),
|
||||
MMUL(P1y, t4, t6),
|
||||
MMUL(t1, t5, t3),
|
||||
MSUB(P1y, t1),
|
||||
|
||||
/*
|
||||
* Compute z3 = h*z1*z2.
|
||||
*/
|
||||
MMUL(t1, P1z, P2z),
|
||||
MMUL(P1z, t1, t2),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Check that the point is on the curve. This code snippet assumes the
|
||||
* following conventions:
|
||||
* -- Coordinates x and y have been freshly decoded in P1 (but not
|
||||
* converted to Montgomery coordinates yet).
|
||||
* -- P2x, P2y and P2z are set to, respectively, R^2, b*R and 1.
|
||||
*/
|
||||
static const uint16_t code_check[] = {
|
||||
|
||||
/* Convert x and y to Montgomery representation. */
|
||||
MMUL(t1, P1x, P2x),
|
||||
MMUL(t2, P1y, P2x),
|
||||
MSET(P1x, t1),
|
||||
MSET(P1y, t2),
|
||||
|
||||
/* Compute x^3 in t1. */
|
||||
MMUL(t2, P1x, P1x),
|
||||
MMUL(t1, P1x, t2),
|
||||
|
||||
/* Subtract 3*x from t1. */
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
MSUB(t1, P1x),
|
||||
|
||||
/* Add b. */
|
||||
MADD(t1, P2y),
|
||||
|
||||
/* Compute y^2 in t2. */
|
||||
MMUL(t2, P1y, P1y),
|
||||
|
||||
/* Compare y^2 with x^3 - 3*x + b; they must match. */
|
||||
MSUB(t1, t2),
|
||||
MTZ(t1),
|
||||
|
||||
/* Set z to 1 (in Montgomery representation). */
|
||||
MMUL(P1z, P2x, P2z),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Conversion back to affine coordinates. This code snippet assumes that
|
||||
* the z coordinate of P2 is set to 1 (not in Montgomery representation).
|
||||
*/
|
||||
static const uint16_t code_affine[] = {
|
||||
|
||||
/* Save z*R in t1. */
|
||||
MSET(t1, P1z),
|
||||
|
||||
/* Compute z^3 in t2. */
|
||||
MMUL(t2, P1z, P1z),
|
||||
MMUL(t3, P1z, t2),
|
||||
MMUL(t2, t3, P2z),
|
||||
|
||||
/* Invert to (1/z^3) in t2. */
|
||||
MINV(t2, t3, t4),
|
||||
|
||||
/* Compute y. */
|
||||
MSET(t3, P1y),
|
||||
MMUL(P1y, t2, t3),
|
||||
|
||||
/* Compute (1/z^2) in t3. */
|
||||
MMUL(t3, t2, t1),
|
||||
|
||||
/* Compute x. */
|
||||
MSET(t2, P1x),
|
||||
MMUL(P1x, t2, t3),
|
||||
|
||||
ENDCODE
|
||||
};
|
||||
|
||||
static uint32_t
|
||||
run_code(jacobian *P1, const jacobian *P2,
|
||||
const curve_params *cc, const uint16_t *code)
|
||||
{
|
||||
uint32_t r;
|
||||
uint32_t t[13][I31_LEN];
|
||||
size_t u;
|
||||
|
||||
r = 1;
|
||||
|
||||
/*
|
||||
* Copy the two operands in the dedicated registers.
|
||||
*/
|
||||
memcpy(t[P1x], P1->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
memcpy(t[P2x], P2->c, 3 * I31_LEN * sizeof(uint32_t));
|
||||
|
||||
/*
|
||||
* Run formulas.
|
||||
*/
|
||||
for (u = 0;; u ++) {
|
||||
unsigned op, d, a, b;
|
||||
|
||||
op = code[u];
|
||||
if (op == 0) {
|
||||
break;
|
||||
}
|
||||
d = (op >> 8) & 0x0F;
|
||||
a = (op >> 4) & 0x0F;
|
||||
b = op & 0x0F;
|
||||
op >>= 12;
|
||||
switch (op) {
|
||||
uint32_t ctl;
|
||||
size_t plen;
|
||||
unsigned char tp[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
|
||||
case 0:
|
||||
memcpy(t[d], t[a], I31_LEN * sizeof(uint32_t));
|
||||
break;
|
||||
case 1:
|
||||
ctl = br_i31_add(t[d], t[a], 1);
|
||||
ctl |= NOT(br_i31_sub(t[d], cc->p, 0));
|
||||
br_i31_sub(t[d], cc->p, ctl);
|
||||
break;
|
||||
case 2:
|
||||
br_i31_add(t[d], cc->p, br_i31_sub(t[d], t[a], 1));
|
||||
break;
|
||||
case 3:
|
||||
br_i31_montymul(t[d], t[a], t[b], cc->p, cc->p0i);
|
||||
break;
|
||||
case 4:
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
br_i31_encode(tp, plen, cc->p);
|
||||
tp[plen - 1] -= 2;
|
||||
br_i31_modpow(t[d], tp, plen,
|
||||
cc->p, cc->p0i, t[a], t[b]);
|
||||
break;
|
||||
default:
|
||||
r &= ~br_i31_iszero(t[d]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy back result.
|
||||
*/
|
||||
memcpy(P1->c, t[P1x], 3 * I31_LEN * sizeof(uint32_t));
|
||||
return r;
|
||||
}
|
||||
|
||||
static void
|
||||
set_one(uint32_t *x, const uint32_t *p)
|
||||
{
|
||||
size_t plen;
|
||||
|
||||
plen = (p[0] + 63) >> 5;
|
||||
memset(x, 0, plen * sizeof *x);
|
||||
x[0] = p[0];
|
||||
x[1] = 0x00000001;
|
||||
}
|
||||
|
||||
static void
|
||||
point_zero(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
memset(P, 0, sizeof *P);
|
||||
P->c[0][0] = P->c[1][0] = P->c[2][0] = cc->p[0];
|
||||
}
|
||||
|
||||
static inline void
|
||||
point_double(jacobian *P, const curve_params *cc)
|
||||
{
|
||||
run_code(P, P, cc, code_double);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
point_add(jacobian *P1, const jacobian *P2, const curve_params *cc)
|
||||
{
|
||||
return run_code(P1, P2, cc, code_add);
|
||||
}
|
||||
|
||||
static void
|
||||
point_mul(jacobian *P, const unsigned char *x, size_t xlen,
|
||||
const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* We do a simple double-and-add ladder with a 2-bit window
|
||||
* to make only one add every two doublings. We thus first
|
||||
* precompute 2P and 3P in some local buffers.
|
||||
*
|
||||
* We always perform two doublings and one addition; the
|
||||
* addition is with P, 2P and 3P and is done in a temporary
|
||||
* array.
|
||||
*
|
||||
* The addition code cannot handle cases where one of the
|
||||
* operands is infinity, which is the case at the start of the
|
||||
* ladder. We therefore need to maintain a flag that controls
|
||||
* this situation.
|
||||
*/
|
||||
uint32_t qz;
|
||||
jacobian P2, P3, Q, T, U;
|
||||
|
||||
memcpy(&P2, P, sizeof P2);
|
||||
point_double(&P2, cc);
|
||||
memcpy(&P3, P, sizeof P3);
|
||||
point_add(&P3, &P2, cc);
|
||||
|
||||
point_zero(&Q, cc);
|
||||
qz = 1;
|
||||
while (xlen -- > 0) {
|
||||
int k;
|
||||
|
||||
for (k = 6; k >= 0; k -= 2) {
|
||||
uint32_t bits;
|
||||
uint32_t bnz;
|
||||
|
||||
point_double(&Q, cc);
|
||||
point_double(&Q, cc);
|
||||
memcpy(&T, P, sizeof T);
|
||||
memcpy(&U, &Q, sizeof U);
|
||||
bits = (*x >> k) & (uint32_t)3;
|
||||
bnz = NEQ(bits, 0);
|
||||
CCOPY(EQ(bits, 2), &T, &P2, sizeof T);
|
||||
CCOPY(EQ(bits, 3), &T, &P3, sizeof T);
|
||||
point_add(&U, &T, cc);
|
||||
CCOPY(bnz & qz, &Q, &T, sizeof Q);
|
||||
CCOPY(bnz & ~qz, &Q, &U, sizeof Q);
|
||||
qz &= ~bnz;
|
||||
}
|
||||
x ++;
|
||||
}
|
||||
memcpy(P, &Q, sizeof Q);
|
||||
}
|
||||
|
||||
/*
|
||||
* Decode point into Jacobian coordinates. This function does not support
|
||||
* the point at infinity. If the point is invalid then this returns 0, but
|
||||
* the coordinates are still set to properly formed field elements.
|
||||
*/
|
||||
static uint32_t
|
||||
point_decode(jacobian *P, const void *src, size_t len, const curve_params *cc)
|
||||
{
|
||||
/*
|
||||
* Points must use uncompressed format:
|
||||
* -- first byte is 0x04;
|
||||
* -- coordinates X and Y use unsigned big-endian, with the same
|
||||
* length as the field modulus.
|
||||
*
|
||||
* We don't support hybrid format (uncompressed, but first byte
|
||||
* has value 0x06 or 0x07, depending on the least significant bit
|
||||
* of Y) because it is rather useless, and explicitly forbidden
|
||||
* by PKIX (RFC 5480, section 2.2).
|
||||
*
|
||||
* We don't support compressed format either, because it is not
|
||||
* much used in practice (there are or were patent-related
|
||||
* concerns about point compression, which explains the lack of
|
||||
* generalised support). Also, point compression support would
|
||||
* need a bit more code.
|
||||
*/
|
||||
const unsigned char *buf;
|
||||
size_t plen, zlen;
|
||||
uint32_t r;
|
||||
jacobian Q;
|
||||
|
||||
buf = src;
|
||||
point_zero(P, cc);
|
||||
plen = (cc->p[0] - (cc->p[0] >> 5) + 7) >> 3;
|
||||
if (len != 1 + (plen << 1)) {
|
||||
return 0;
|
||||
}
|
||||
r = br_i31_decode_mod(P->c[0], buf + 1, plen, cc->p);
|
||||
r &= br_i31_decode_mod(P->c[1], buf + 1 + plen, plen, cc->p);
|
||||
|
||||
/*
|
||||
* Check first byte.
|
||||
*/
|
||||
r &= EQ(buf[0], 0x04);
|
||||
/* obsolete
|
||||
r &= EQ(buf[0], 0x04) | (EQ(buf[0] & 0xFE, 0x06)
|
||||
& ~(uint32_t)(buf[0] ^ buf[plen << 1]));
|
||||
*/
|
||||
|
||||
/*
|
||||
* Convert coordinates and check that the point is valid.
|
||||
*/
|
||||
zlen = ((cc->p[0] + 63) >> 5) * sizeof(uint32_t);
|
||||
memcpy(Q.c[0], cc->R2, zlen);
|
||||
memcpy(Q.c[1], cc->b, zlen);
|
||||
set_one(Q.c[2], cc->p);
|
||||
r &= ~run_code(P, &Q, cc, code_check);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Encode a point. This method assumes that the point is correct and is
|
||||
* not the point at infinity. Encoded size is always 1+2*plen, where
|
||||
* plen is the field modulus length, in bytes.
|
||||
*/
|
||||
static void
|
||||
point_encode(void *dst, const jacobian *P, const curve_params *cc)
|
||||
{
|
||||
unsigned char *buf;
|
||||
uint32_t xbl;
|
||||
size_t plen;
|
||||
jacobian Q, T;
|
||||
|
||||
buf = dst;
|
||||
xbl = cc->p[0];
|
||||
xbl -= (xbl >> 5);
|
||||
plen = (xbl + 7) >> 3;
|
||||
buf[0] = 0x04;
|
||||
memcpy(&Q, P, sizeof *P);
|
||||
set_one(T.c[2], cc->p);
|
||||
run_code(&Q, &T, cc, code_affine);
|
||||
br_i31_encode(buf + 1, plen, Q.c[0]);
|
||||
br_i31_encode(buf + 1 + plen, plen, Q.c[1]);
|
||||
}
|
||||
|
||||
static const br_ec_curve_def *
|
||||
id_to_curve_def(int curve)
|
||||
{
|
||||
switch (curve) {
|
||||
case BR_EC_secp256r1:
|
||||
return &br_secp256r1;
|
||||
case BR_EC_secp384r1:
|
||||
return &br_secp384r1;
|
||||
case BR_EC_secp521r1:
|
||||
return &br_secp521r1;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_generator(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->generator_len;
|
||||
return cd->generator;
|
||||
}
|
||||
|
||||
static const unsigned char *
|
||||
api_order(int curve, size_t *len)
|
||||
{
|
||||
const br_ec_curve_def *cd;
|
||||
|
||||
cd = id_to_curve_def(curve);
|
||||
*len = cd->order_len;
|
||||
return cd->order;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_mul(unsigned char *G, size_t Glen,
|
||||
const unsigned char *x, size_t xlen, int curve)
|
||||
{
|
||||
uint32_t r;
|
||||
const curve_params *cc;
|
||||
jacobian P;
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, G, Glen, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_encode(G, &P, cc);
|
||||
return r;
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
api_muladd(unsigned char *A, const unsigned char *B, size_t len,
|
||||
const unsigned char *x, size_t xlen,
|
||||
const unsigned char *y, size_t ylen, int curve)
|
||||
{
|
||||
uint32_t r, t, z;
|
||||
const curve_params *cc;
|
||||
jacobian P, Q;
|
||||
|
||||
/*
|
||||
* TODO: see about merging the two ladders. Right now, we do
|
||||
* two independant point multiplications, which is a bit
|
||||
* wasteful of CPU resources (but yields short code).
|
||||
*/
|
||||
|
||||
cc = id_to_curve(curve);
|
||||
r = point_decode(&P, A, len, cc);
|
||||
r &= point_decode(&Q, B, len, cc);
|
||||
point_mul(&P, x, xlen, cc);
|
||||
point_mul(&Q, y, ylen, cc);
|
||||
|
||||
/*
|
||||
* We want to compute P+Q. Since the base points A and B are distinct
|
||||
* from infinity, and the multipliers are non-zero and lower than the
|
||||
* curve order, then we know that P and Q are non-infinity. This
|
||||
* leaves two special situations to test for:
|
||||
* -- If P = Q then we must use point_double().
|
||||
* -- If P+Q = 0 then we must report an error.
|
||||
*/
|
||||
t = point_add(&P, &Q, cc);
|
||||
point_double(&Q, cc);
|
||||
z = br_i31_iszero(P.c[2]);
|
||||
|
||||
/*
|
||||
* If z is 1 then either P+Q = 0 (t = 1) or P = Q (t = 0). So we
|
||||
* have the following:
|
||||
*
|
||||
* z = 0, t = 0 return P (normal addition)
|
||||
* z = 0, t = 1 return P (normal addition)
|
||||
* z = 1, t = 0 return Q (a 'double' case)
|
||||
* z = 1, t = 1 report an error (P+Q = 0)
|
||||
*/
|
||||
CCOPY(z & ~t, &P, &Q, sizeof Q);
|
||||
point_encode(A, &P, cc);
|
||||
r &= ~(z & t);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
const br_ec_impl br_ec_prime_i31 = {
|
||||
(uint32_t)0x03800000,
|
||||
&api_generator,
|
||||
&api_order,
|
||||
&api_mul,
|
||||
&api_muladd
|
||||
};
|
||||
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
46
src/ec/ec_prime_i31_secp256r1.c
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P256_P[] = {
|
||||
0x00000108,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x00000007,
|
||||
0x00000000, 0x00000000, 0x00000040, 0x7FFFFF80,
|
||||
0x000000FF
|
||||
};
|
||||
|
||||
static const uint32_t P256_B[] = {
|
||||
0x00000108,
|
||||
0x6FEE1803, 0x6229C4BD, 0x21B139BE, 0x327150AA,
|
||||
0x3567802E, 0x3F7212ED, 0x012E4355, 0x782DD38D,
|
||||
0x0000000E
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp256r1 = {
|
||||
P256_P,
|
||||
P256_B,
|
||||
0x00000001
|
||||
};
|
||||
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
48
src/ec/ec_prime_i31_secp384r1.c
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P384_P[] = {
|
||||
0x0000018C,
|
||||
0x7FFFFFFF, 0x00000001, 0x00000000, 0x7FFFFFF8,
|
||||
0x7FFFFFEF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x00000FFF
|
||||
};
|
||||
|
||||
static const uint32_t P384_B[] = {
|
||||
0x0000018C,
|
||||
0x6E666840, 0x070D0392, 0x5D810231, 0x7651D50C,
|
||||
0x17E218D6, 0x1B192002, 0x44EFE441, 0x3A524E2B,
|
||||
0x2719BA5F, 0x41F02209, 0x36C5643E, 0x5813EFFE,
|
||||
0x000008A5
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp384r1 = {
|
||||
P384_P,
|
||||
P384_B,
|
||||
0x00000001
|
||||
};
|
||||
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
50
src/ec/ec_prime_i31_secp521r1.c
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const uint32_t P521_P[] = {
|
||||
0x00000219,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF, 0x7FFFFFFF,
|
||||
0x01FFFFFF
|
||||
};
|
||||
|
||||
static const uint32_t P521_B[] = {
|
||||
0x00000219,
|
||||
0x540FC00A, 0x228FEA35, 0x2C34F1EF, 0x67BF107A,
|
||||
0x46FC1CD5, 0x1605E9DD, 0x6937B165, 0x272A3D8F,
|
||||
0x42785586, 0x44C8C778, 0x15F3B8B4, 0x64B73366,
|
||||
0x03BA8B69, 0x0D05B42A, 0x21F929A2, 0x2C31C393,
|
||||
0x00654FAE
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_prime_i31_curve br_ec_prime_i31_secp521r1 = {
|
||||
P521_P,
|
||||
P521_B,
|
||||
0x00000001
|
||||
};
|
||||
51
src/ec/ec_secp256r1.c
Normal file
51
src/ec/ec_secp256r1.c
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P256_N[] = {
|
||||
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 unsigned char P256_G[] = {
|
||||
0x04, 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
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp256r1 = {
|
||||
BR_EC_secp256r1,
|
||||
P256_N, sizeof P256_N,
|
||||
P256_G, sizeof P256_G
|
||||
};
|
||||
57
src/ec/ec_secp384r1.c
Normal file
57
src/ec/ec_secp384r1.c
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P384_N[] = {
|
||||
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 unsigned char P384_G[] = {
|
||||
0x04, 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
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp384r1 = {
|
||||
BR_EC_secp384r1,
|
||||
P384_N, sizeof P384_N,
|
||||
P384_G, sizeof P384_G
|
||||
};
|
||||
64
src/ec/ec_secp521r1.c
Normal file
64
src/ec/ec_secp521r1.c
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static const unsigned char P521_N[] = {
|
||||
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 unsigned char P521_G[] = {
|
||||
0x04, 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
|
||||
};
|
||||
|
||||
/* see inner.h */
|
||||
const br_ec_curve_def br_secp521r1 = {
|
||||
BR_EC_secp521r1,
|
||||
P521_N, sizeof P521_N,
|
||||
P521_G, sizeof P521_G
|
||||
};
|
||||
102
src/ec/ecdsa_atr.c
Normal file
102
src/ec/ecdsa_atr.c
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_asn1_to_raw(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Note: this code is a bit lenient in that it accepts a few
|
||||
* deviations to DER with regards to minimality of encoding of
|
||||
* lengths and integer values. These deviations are still
|
||||
* unambiguous.
|
||||
*/
|
||||
|
||||
unsigned char *buf, *r, *s;
|
||||
size_t zlen, rlen, slen, off;
|
||||
unsigned char tmp[254];
|
||||
|
||||
buf = sig;
|
||||
if (sig_len < 8) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[0] != 0x30) {
|
||||
return 0;
|
||||
}
|
||||
zlen = buf[1];
|
||||
if (zlen > 0x80) {
|
||||
if (zlen != 0x81) {
|
||||
return 0;
|
||||
}
|
||||
zlen = buf[2];
|
||||
if (zlen != sig_len - 3) {
|
||||
return 0;
|
||||
}
|
||||
off = 3;
|
||||
} else {
|
||||
if (zlen != sig_len - 2) {
|
||||
return 0;
|
||||
}
|
||||
off = 2;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
rlen = buf[off ++];
|
||||
if (rlen >= 0x80) {
|
||||
return 0;
|
||||
}
|
||||
r = buf + off;
|
||||
off += rlen;
|
||||
if (off + 2 > sig_len) {
|
||||
return 0;
|
||||
}
|
||||
if (buf[off ++] != 0x02) {
|
||||
return 0;
|
||||
}
|
||||
slen = buf[off ++];
|
||||
if (slen >= 0x80 || slen != sig_len - off) {
|
||||
return 0;
|
||||
}
|
||||
s = buf + off;
|
||||
|
||||
while (rlen > 0 && *r == 0) {
|
||||
rlen --;
|
||||
r ++;
|
||||
}
|
||||
while (slen > 0 && *s == 0) {
|
||||
slen --;
|
||||
s ++;
|
||||
}
|
||||
|
||||
zlen = rlen > slen ? rlen : slen;
|
||||
sig_len = zlen << 1;
|
||||
memset(tmp, 0, sig_len);
|
||||
memcpy(tmp + zlen - rlen, r, rlen);
|
||||
memcpy(tmp + sig_len - slen, s, slen);
|
||||
memcpy(sig, tmp, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
47
src/ec/ecdsa_i31_bits.c
Normal file
47
src/ec/ecdsa_i31_bits.c
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
/* see inner.h */
|
||||
void
|
||||
br_ecdsa_i31_bits2int(uint32_t *x,
|
||||
const void *src, size_t len, uint32_t ebitlen)
|
||||
{
|
||||
uint32_t bitlen, hbitlen;
|
||||
int sc;
|
||||
|
||||
bitlen = ebitlen - (ebitlen >> 5);
|
||||
hbitlen = (uint32_t)len << 3;
|
||||
if (hbitlen > bitlen) {
|
||||
len = (bitlen + 7) >> 3;
|
||||
sc = (int)((hbitlen - bitlen) & 7);
|
||||
} else {
|
||||
sc = 0;
|
||||
}
|
||||
br_i31_zero(x, ebitlen);
|
||||
br_i31_decode(x, src, len);
|
||||
br_i31_rshift(x, sc);
|
||||
x[0] = ebitlen;
|
||||
}
|
||||
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
45
src/ec/ecdsa_i31_sign_asn1.c
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_asn1(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
unsigned char rsig[(ORDER_LEN << 1) + 12];
|
||||
size_t sig_len;
|
||||
|
||||
sig_len = br_ecdsa_i31_sign_raw(impl, hf, hash_value, sk, rsig);
|
||||
if (sig_len == 0) {
|
||||
return 0;
|
||||
}
|
||||
sig_len = br_ecdsa_raw_to_asn1(rsig, sig_len);
|
||||
memcpy(sig, rsig, sig_len);
|
||||
return sig_len;
|
||||
}
|
||||
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
176
src/ec/ecdsa_i31_sign_raw.c
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
#define ORDER_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_i31_sign_raw(const br_ec_impl *impl,
|
||||
const br_hash_class *hf, const void *hash_value,
|
||||
const br_ec_private_key *sk, void *sig)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
* We also rely on the last byte of the curve order to be distinct
|
||||
* from 0 and 1.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], x[I31_LEN];
|
||||
uint32_t m[I31_LEN], k[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tt[ORDER_LEN << 1];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t hash_len, nlen, ulen;
|
||||
uint32_t n0i, ctl;
|
||||
br_hmac_drbg_context drbg;
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (sk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
|
||||
/*
|
||||
* Get private key as an i31 integer. This also checks that the
|
||||
* private key is well-defined (not zero, and less than the
|
||||
* curve order).
|
||||
*/
|
||||
if (!br_i31_decode_mod(x, sk->x, sk->xlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(x)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get hash length.
|
||||
*/
|
||||
hash_len = (hf->desc >> BR_HASHDESC_OUT_OFF) & BR_HASHDESC_OUT_MASK;
|
||||
|
||||
/*
|
||||
* Truncate and reduce the hash value modulo the curve order.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(m, hash_value, hash_len, n[0]);
|
||||
br_i31_sub(m, n, br_i31_sub(m, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* RFC 6979 generation of the "k" value.
|
||||
*
|
||||
* The process uses HMAC_DRBG (with the hash function used to
|
||||
* process the message that is to be signed). The seed is the
|
||||
* concatenation of the encodings of the private key and
|
||||
* the hash value (after truncation and modular reduction).
|
||||
*/
|
||||
br_i31_encode(tt, nlen, x);
|
||||
br_i31_encode(tt + nlen, nlen, m);
|
||||
br_hmac_drbg_init(&drbg, hf, tt, nlen << 1);
|
||||
for (;;) {
|
||||
br_hmac_drbg_generate(&drbg, tt, nlen);
|
||||
br_ecdsa_i31_bits2int(k, tt, nlen, n[0]);
|
||||
if (br_i31_iszero(k)) {
|
||||
continue;
|
||||
}
|
||||
if (br_i31_sub(k, n, 0)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute k*G and extract the X coordinate, then reduce it
|
||||
* modulo the curve order. Since we support only curves with
|
||||
* prime order, that reduction is only a matter of computing
|
||||
* a subtraction.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, cd->generator, ulen);
|
||||
br_i31_encode(tt, nlen, k);
|
||||
if (!impl->mul(eU, ulen, tt, nlen, sk->curve)) {
|
||||
/*
|
||||
* Point multiplication may fail here only if the
|
||||
* EC implementation does not support the curve, or the
|
||||
* private key is incorrect (x is a multiple of the curve
|
||||
* order).
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
br_i31_zero(r, n[0]);
|
||||
br_i31_decode(r, &eU[1], ulen >> 1);
|
||||
r[0] = n[0];
|
||||
br_i31_sub(r, n, br_i31_sub(r, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Compute 1/k in double-Montgomery representation. We do so by
|
||||
* first converting _from_ Montgomery representation (twice),
|
||||
* then using a modular exponentiation.
|
||||
*/
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
br_i31_from_monty(k, n, n0i);
|
||||
memcpy(tt, cd->order, nlen);
|
||||
tt[nlen - 1] -= 2;
|
||||
br_i31_modpow(k, tt, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Compute s = (m+xr)/k (mod n).
|
||||
* The k[] array contains R^2/k (double-Montgomery representation);
|
||||
* we thus can use direct Montgomery multiplications and conversions
|
||||
* from Montgomery, avoiding any call to br_i31_to_monty() (which
|
||||
* is slower).
|
||||
*/
|
||||
br_i31_from_monty(m, n, n0i);
|
||||
br_i31_montymul(t1, x, r, n, n0i);
|
||||
ctl = br_i31_add(t1, m, 1);
|
||||
ctl |= br_i31_sub(t1, n, 0) ^ 1;
|
||||
br_i31_sub(t1, n, ctl);
|
||||
br_i31_montymul(s, t1, k, n, n0i);
|
||||
|
||||
/*
|
||||
* Encode r and s in the signature.
|
||||
*/
|
||||
br_i31_encode(sig, nlen, r);
|
||||
br_i31_encode((unsigned char *)sig + nlen, nlen, s);
|
||||
return nlen << 1;
|
||||
}
|
||||
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
44
src/ec/ecdsa_i31_vrfy_asn1.c
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define FIELD_LEN ((BR_MAX_EC_SIZE + 7) >> 3)
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_asn1(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
unsigned char rsig[(FIELD_LEN << 1) + 12];
|
||||
|
||||
if (sig_len > sizeof rsig) {
|
||||
return 0;
|
||||
}
|
||||
memcpy(rsig, sig, sig_len);
|
||||
sig_len = br_ecdsa_asn1_to_raw(rsig, sig_len);
|
||||
return br_ecdsa_i31_vrfy_raw(impl, hash, hash_len, pk, rsig, sig_len);
|
||||
}
|
||||
158
src/ec/ecdsa_i31_vrfy_raw.c
Normal file
158
src/ec/ecdsa_i31_vrfy_raw.c
Normal file
|
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
#define I31_LEN ((BR_MAX_EC_SIZE + 61) / 31)
|
||||
#define POINT_LEN (1 + (((BR_MAX_EC_SIZE + 7) >> 3) << 1))
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
uint32_t
|
||||
br_ecdsa_i31_vrfy_raw(const br_ec_impl *impl,
|
||||
const void *hash, size_t hash_len,
|
||||
const br_ec_public_key *pk,
|
||||
const void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* IMPORTANT: this code is fit only for curves with a prime
|
||||
* order. This is needed so that modular reduction of the X
|
||||
* coordinate of a point can be done with a simple subtraction.
|
||||
*/
|
||||
const br_ec_curve_def *cd;
|
||||
uint32_t n[I31_LEN], r[I31_LEN], s[I31_LEN], t1[I31_LEN], t2[I31_LEN];
|
||||
unsigned char tx[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char ty[(BR_MAX_EC_SIZE + 7) >> 3];
|
||||
unsigned char eU[POINT_LEN];
|
||||
size_t nlen, rlen, ulen;
|
||||
uint32_t n0i, res;
|
||||
|
||||
/*
|
||||
* Get the curve parameters (generator and order).
|
||||
*/
|
||||
switch (pk->curve) {
|
||||
case BR_EC_secp256r1:
|
||||
cd = &br_secp256r1;
|
||||
break;
|
||||
case BR_EC_secp384r1:
|
||||
cd = &br_secp384r1;
|
||||
break;
|
||||
case BR_EC_secp521r1:
|
||||
cd = &br_secp521r1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Signature length must be even.
|
||||
*/
|
||||
if (sig_len & 1) {
|
||||
return 0;
|
||||
}
|
||||
rlen = sig_len >> 1;
|
||||
|
||||
/*
|
||||
* Public key point must have the proper size for this curve.
|
||||
*/
|
||||
if (pk->qlen != cd->generator_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get modulus; then decode the r and s values. They must be
|
||||
* lower than the modulus, and s must not be null.
|
||||
*/
|
||||
nlen = cd->order_len;
|
||||
br_i31_decode(n, cd->order, nlen);
|
||||
n0i = br_i31_ninv31(n[1]);
|
||||
if (!br_i31_decode_mod(r, sig, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (!br_i31_decode_mod(s, (const unsigned char *)sig + rlen, rlen, n)) {
|
||||
return 0;
|
||||
}
|
||||
if (br_i31_iszero(s)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Invert s. We do that with a modular exponentiation; we use
|
||||
* the fact that for all the curves we support, the least
|
||||
* significant byte is not 0 or 1, so we can subtract 2 without
|
||||
* any carry to process.
|
||||
* We also want 1/s in Montgomery representation, which can be
|
||||
* done by converting _from_ Montgomery representation before
|
||||
* the inversion (because (1/s)*R = 1/(s/R)).
|
||||
*/
|
||||
br_i31_from_monty(s, n, n0i);
|
||||
memcpy(tx, cd->order, nlen);
|
||||
tx[nlen - 1] -= 2;
|
||||
br_i31_modpow(s, tx, nlen, n, n0i, t1, t2);
|
||||
|
||||
/*
|
||||
* Truncate the hash to the modulus length (in bits) and reduce
|
||||
* it modulo the curve order. The modular reduction can be done
|
||||
* with a subtraction since the truncation already reduced the
|
||||
* value to the modulus bit length.
|
||||
*/
|
||||
br_ecdsa_i31_bits2int(t1, hash, hash_len, n[0]);
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
|
||||
/*
|
||||
* Multiply the (truncated, reduced) hash value with 1/s, result in
|
||||
* t2, encoded in ty.
|
||||
*/
|
||||
br_i31_montymul(t2, t1, s, n, n0i);
|
||||
br_i31_encode(ty, nlen, t2);
|
||||
|
||||
/*
|
||||
* Multiply r with 1/s, result in t1, encoded in tx.
|
||||
*/
|
||||
br_i31_montymul(t1, r, s, n, n0i);
|
||||
br_i31_encode(tx, nlen, t1);
|
||||
|
||||
/*
|
||||
* Compute the point x*Q + y*G.
|
||||
*/
|
||||
ulen = cd->generator_len;
|
||||
memcpy(eU, pk->q, ulen);
|
||||
res = impl->muladd(eU, cd->generator, ulen,
|
||||
tx, nlen, ty, nlen, cd->curve);
|
||||
|
||||
/*
|
||||
* Get the X coordinate, reduce modulo the curve order, and
|
||||
* compare with the 'r' value.
|
||||
*
|
||||
* The modular reduction can be done with subtractions because
|
||||
* we work with curves of prime order, so the curve order is
|
||||
* close to the field order (Hasse's theorem).
|
||||
*/
|
||||
br_i31_zero(t1, n[0]);
|
||||
br_i31_decode(t1, &eU[1], ulen >> 1);
|
||||
t1[0] = n[0];
|
||||
br_i31_sub(t1, n, br_i31_sub(t1, n, 0) ^ 1);
|
||||
res &= ~br_i31_sub(t1, r, 1);
|
||||
res &= br_i31_iszero(t1);
|
||||
return res;
|
||||
}
|
||||
94
src/ec/ecdsa_rta.c
Normal file
94
src/ec/ecdsa_rta.c
Normal file
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Thomas Pornin <pornin@bolet.org>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "inner.h"
|
||||
|
||||
static size_t
|
||||
asn1_int_length(const unsigned char *x, size_t xlen)
|
||||
{
|
||||
while (xlen > 0 && *x == 0) {
|
||||
x ++;
|
||||
xlen --;
|
||||
}
|
||||
if (xlen == 0 || *x >= 0x80) {
|
||||
xlen ++;
|
||||
}
|
||||
return xlen;
|
||||
}
|
||||
|
||||
/* see bearssl_ec.h */
|
||||
size_t
|
||||
br_ecdsa_raw_to_asn1(void *sig, size_t sig_len)
|
||||
{
|
||||
/*
|
||||
* Internal buffer is large enough to accommodate a signature
|
||||
* such that r and s fit on 125 bytes each (signed encoding),
|
||||
* meaning a curve order of up to 1000 bits. This is the limit
|
||||
* that ensures "simple" length encodings.
|
||||
*/
|
||||
unsigned char *buf;
|
||||
size_t hlen, rlen, slen, zlen, off;
|
||||
unsigned char tmp[257];
|
||||
|
||||
buf = sig;
|
||||
if ((sig_len & 1) != 0) {
|
||||
return 0;
|
||||
}
|
||||
hlen = sig_len >> 1;
|
||||
rlen = asn1_int_length(buf, hlen);
|
||||
slen = asn1_int_length(buf + hlen, hlen);
|
||||
if (rlen > 125 || slen > 125) {
|
||||
return 0;
|
||||
}
|
||||
tmp[0] = 0x30;
|
||||
zlen = rlen + slen + 4;
|
||||
if (zlen >= 0x80) {
|
||||
tmp[1] = 0x81;
|
||||
tmp[2] = zlen;
|
||||
off = 3;
|
||||
} else {
|
||||
tmp[1] = zlen;
|
||||
off = 2;
|
||||
}
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = rlen;
|
||||
if (rlen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + hlen - rlen, rlen);
|
||||
}
|
||||
off += rlen;
|
||||
tmp[off ++] = 0x02;
|
||||
tmp[off ++] = slen;
|
||||
if (slen > hlen) {
|
||||
tmp[off] = 0x00;
|
||||
memcpy(tmp + off + 1, buf + hlen, hlen);
|
||||
} else {
|
||||
memcpy(tmp + off, buf + sig_len - slen, slen);
|
||||
}
|
||||
off += slen;
|
||||
memcpy(sig, tmp, off);
|
||||
return off;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue