aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/crypto/curve25519.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/crypto/curve25519.c')
-rw-r--r--src/crypto/curve25519.c89
1 files changed, 84 insertions, 5 deletions
diff --git a/src/crypto/curve25519.c b/src/crypto/curve25519.c
index 780df70..1d79ab6 100644
--- a/src/crypto/curve25519.c
+++ b/src/crypto/curve25519.c
@@ -39,10 +39,89 @@ typedef u64 fe[10];
typedef u64 fe51[5];
asmlinkage void curve25519_sandy2x_ladder(fe *, const u8 *);
asmlinkage void curve25519_sandy2x_ladder_base(fe *, const u8 *);
-asmlinkage void curve25519_sandy2x_fe_frombytes(fe, const u8 *);
asmlinkage void curve25519_sandy2x_fe51_pack(u8 *, const fe51 *);
asmlinkage void curve25519_sandy2x_fe51_mul(fe51 *, const fe51 *, const fe51 *);
-asmlinkage void curve25519_sandy2x_fe51_invert(fe51 *, const fe51 *);
+asmlinkage void curve25519_sandy2x_fe51_nsquare(fe51 *, const fe51 *, int);
+
+static inline u32 le24_to_cpupv(const u8 *in)
+{
+ return le16_to_cpup((__le16 *)in) | ((u32)in[2]) << 16;
+}
+
+static inline void fe_frombytes(fe h, const u8 *s)
+{
+ u64 h0 = le32_to_cpup((__le32 *)s);
+ u64 h1 = le24_to_cpupv(s + 4) << 6;
+ u64 h2 = le24_to_cpupv(s + 7) << 5;
+ u64 h3 = le24_to_cpupv(s + 10) << 3;
+ u64 h4 = le24_to_cpupv(s + 13) << 2;
+ u64 h5 = le32_to_cpup((__le32 *)(s + 16));
+ u64 h6 = le24_to_cpupv(s + 20) << 7;
+ u64 h7 = le24_to_cpupv(s + 23) << 5;
+ u64 h8 = le24_to_cpupv(s + 26) << 4;
+ u64 h9 = (le24_to_cpupv(s + 29) & 8388607) << 2;
+ u64 carry0, carry1, carry2, carry3, carry4, carry5, carry6, carry7, carry8, carry9;
+
+ carry9 = h9 >> 25; h0 += carry9 * 19; h9 &= 0x1FFFFFF;
+ carry1 = h1 >> 25; h2 += carry1; h1 &= 0x1FFFFFF;
+ carry3 = h3 >> 25; h4 += carry3; h3 &= 0x1FFFFFF;
+ carry5 = h5 >> 25; h6 += carry5; h5 &= 0x1FFFFFF;
+ carry7 = h7 >> 25; h8 += carry7; h7 &= 0x1FFFFFF;
+
+ carry0 = h0 >> 26; h1 += carry0; h0 &= 0x3FFFFFF;
+ carry2 = h2 >> 26; h3 += carry2; h2 &= 0x3FFFFFF;
+ carry4 = h4 >> 26; h5 += carry4; h4 &= 0x3FFFFFF;
+ carry6 = h6 >> 26; h7 += carry6; h6 &= 0x3FFFFFF;
+ carry8 = h8 >> 26; h9 += carry8; h8 &= 0x3FFFFFF;
+
+ h[0] = h0;
+ h[1] = h1;
+ h[2] = h2;
+ h[3] = h3;
+ h[4] = h4;
+ h[5] = h5;
+ h[6] = h6;
+ h[7] = h7;
+ h[8] = h8;
+ h[9] = h9;
+}
+
+static inline void fe51_invert(fe51 *r, const fe51 *x)
+{
+ fe51 z2, z9, z11, z2_5_0, z2_10_0, z2_20_0, z2_50_0, z2_100_0, t;
+
+ /* 2 */ curve25519_sandy2x_fe51_nsquare(&z2, x, 1);
+ /* 4 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2, 1);
+ /* 8 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&t, 1);
+ /* 9 */ curve25519_sandy2x_fe51_mul(&z9, (const fe51 *)&t, x);
+ /* 11 */ curve25519_sandy2x_fe51_mul(&z11, (const fe51 *)&z9, (const fe51 *)&z2);
+ /* 22 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z11, 1);
+ /* 2^5 - 2^0 = 31 */ curve25519_sandy2x_fe51_mul(&z2_5_0, (const fe51 *)&t, (const fe51 *)&z9);
+
+ /* 2^10 - 2^5 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2_5_0, 5);
+ /* 2^10 - 2^0 */ curve25519_sandy2x_fe51_mul(&z2_10_0, (const fe51 *)&t, (const fe51 *)&z2_5_0);
+
+ /* 2^20 - 2^10 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2_10_0, 10);
+ /* 2^20 - 2^0 */ curve25519_sandy2x_fe51_mul(&z2_20_0, (const fe51 *)&t, (const fe51 *)&z2_10_0);
+
+ /* 2^40 - 2^20 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2_20_0, 20);
+ /* 2^40 - 2^0 */ curve25519_sandy2x_fe51_mul(&t, (const fe51 *)&t, (const fe51 *)&z2_20_0);
+
+ /* 2^50 - 2^10 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&t, 10);
+ /* 2^50 - 2^0 */ curve25519_sandy2x_fe51_mul(&z2_50_0, (const fe51 *)&t, (const fe51 *)&z2_10_0);
+
+ /* 2^100 - 2^50 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2_50_0, 50);
+ /* 2^100 - 2^0 */ curve25519_sandy2x_fe51_mul(&z2_100_0, (const fe51 *)&t, (const fe51 *)&z2_50_0);
+
+ /* 2^200 - 2^100 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&z2_100_0, 100);
+ /* 2^200 - 2^0 */ curve25519_sandy2x_fe51_mul(&t, (const fe51 *)&t, (const fe51 *)&z2_100_0);
+
+ /* 2^250 - 2^50 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&t, 50);
+ /* 2^250 - 2^0 */ curve25519_sandy2x_fe51_mul(&t, (const fe51 *)&t, (const fe51 *)&z2_50_0);
+
+ /* 2^255 - 2^5 */ curve25519_sandy2x_fe51_nsquare(&t, (const fe51 *)&t, 5);
+ /* 2^255 - 21 */ curve25519_sandy2x_fe51_mul(r, (const fe51 *)t, (const fe51 *)&z11);
+}
static void curve25519_sandy2x(u8 mypublic[CURVE25519_POINT_SIZE], const u8 secret[CURVE25519_POINT_SIZE], const u8 basepoint[CURVE25519_POINT_SIZE])
{
@@ -54,7 +133,7 @@ static void curve25519_sandy2x(u8 mypublic[CURVE25519_POINT_SIZE], const u8 secr
#define x1 var[0]
#define x2 var[1]
#define z2 var[2]
- curve25519_sandy2x_fe_frombytes(x1, basepoint);
+ fe_frombytes(x1, basepoint);
curve25519_sandy2x_ladder(var, e);
z_51[0] = (z2[1] << 26) + z2[0];
z_51[1] = (z2[3] << 26) + z2[2];
@@ -69,7 +148,7 @@ static void curve25519_sandy2x(u8 mypublic[CURVE25519_POINT_SIZE], const u8 secr
#undef x1
#undef x2
#undef z2
- curve25519_sandy2x_fe51_invert(&z_51, (const fe51 *)&z_51);
+ fe51_invert(&z_51, (const fe51 *)&z_51);
curve25519_sandy2x_fe51_mul(&x_51, (const fe51 *)&x_51, (const fe51 *)&z_51);
curve25519_sandy2x_fe51_pack(mypublic, (const fe51 *)&x_51);
@@ -101,7 +180,7 @@ static void curve25519_sandy2x_base(u8 pub[CURVE25519_POINT_SIZE], const u8 secr
x_51[4] = (x2[9] << 26) + x2[8];
#undef x2
#undef z2
- curve25519_sandy2x_fe51_invert(&z_51, (const fe51 *)&z_51);
+ fe51_invert(&z_51, (const fe51 *)&z_51);
curve25519_sandy2x_fe51_mul(&x_51, (const fe51 *)&x_51, (const fe51 *)&z_51);
curve25519_sandy2x_fe51_pack(pub, (const fe51 *)&x_51);