mirror of
https://github.com/shadps4-emu/ext-cryptopp.git
synced 2024-11-26 19:30:21 +00:00
Fix the cut-in of Moon's implementation (GH #761)
The initial cut-in was missing preamble present in Moon's curve25519_donna function. It originally tested good because we only perform a pairwise consistency check in release builds. Comprehensive testing with debug builds revealed the problem. Debug builds cross-validate against Bernstein's TweetNaCl library.
This commit is contained in:
parent
eb749783da
commit
27cd177209
287
donna_64.cpp
287
donna_64.cpp
@ -2,10 +2,14 @@
|
||||
// This is a integration of Andrew Moon's public domain code.
|
||||
// Also see curve25519-donna-64bit.h.
|
||||
|
||||
// If needed, see Moon's commit "Go back to ignoring 256th bit",
|
||||
// https://github.com/floodyberry/curve25519-donna/commit/57a683d18721a658
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "donna.h"
|
||||
#include "secblock.h"
|
||||
#include "stdcpp.h"
|
||||
#include "misc.h"
|
||||
#include "cpu.h"
|
||||
@ -35,7 +39,6 @@ using CryptoPP::sword64;
|
||||
using CryptoPP::word128;
|
||||
|
||||
using CryptoPP::GetBlock;
|
||||
using CryptoPP::BigEndian;
|
||||
using CryptoPP::LittleEndian;
|
||||
|
||||
typedef word64 bignum25519[5];
|
||||
@ -49,18 +52,17 @@ typedef word64 bignum25519[5];
|
||||
#define shr128(out,in,shift) out = (word64)(in >> (shift));
|
||||
#define shl128(out,in,shift) out = (word64)((in << shift) >> 64);
|
||||
|
||||
#define ALIGN(n) CRYPTOPP_ALIGN_DATA(n)
|
||||
|
||||
const byte basePoint[32] = {9};
|
||||
const word64 reduce_mask_40 = ((word64)1 << 40) - 1;
|
||||
const word64 reduce_mask_51 = ((word64)1 << 51) - 1;
|
||||
const word64 reduce_mask_56 = ((word64)1 << 56) - 1;
|
||||
const word64 reduce_mask_52 = ((word64)1 << 52) - 1;
|
||||
|
||||
/* out = in */
|
||||
inline void
|
||||
curve25519_copy(bignum25519 out, const bignum25519 in) {
|
||||
out[0] = in[0];
|
||||
out[1] = in[1];
|
||||
out[2] = in[2];
|
||||
out[3] = in[3];
|
||||
out[0] = in[0]; out[1] = in[1];
|
||||
out[2] = in[2]; out[3] = in[3];
|
||||
out[4] = in[4];
|
||||
}
|
||||
|
||||
@ -74,87 +76,53 @@ curve25519_add(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
out[4] = a[4] + b[4];
|
||||
}
|
||||
|
||||
/* out = a + b, where a and/or b are the result of a basic op (add,sub) */
|
||||
inline void
|
||||
curve25519_add_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
out[0] = a[0] + b[0];
|
||||
out[1] = a[1] + b[1];
|
||||
out[2] = a[2] + b[2];
|
||||
out[3] = a[3] + b[3];
|
||||
out[4] = a[4] + b[4];
|
||||
}
|
||||
|
||||
inline void
|
||||
curve25519_add_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
word64 c;
|
||||
out[0] = a[0] + b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
|
||||
out[1] = a[1] + b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
|
||||
out[2] = a[2] + b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
|
||||
out[3] = a[3] + b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
|
||||
out[4] = a[4] + b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
|
||||
out[0] += c * 19;
|
||||
}
|
||||
|
||||
/* multiples of p */
|
||||
const word64 twoP0 = 0x0fffffffffffda;
|
||||
const word64 twoP1234 = 0x0ffffffffffffe;
|
||||
const word64 fourP0 = 0x1fffffffffffb4;
|
||||
const word64 fourP1234 = 0x1ffffffffffffc;
|
||||
const word64 two54m152 = (((word64)1) << 54) - 152;
|
||||
const word64 two54m8 = (((word64)1) << 54) - 8;
|
||||
|
||||
/* out = a - b */
|
||||
inline void
|
||||
curve25519_sub(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
out[0] = a[0] + twoP0 - b[0];
|
||||
out[1] = a[1] + twoP1234 - b[1];
|
||||
out[2] = a[2] + twoP1234 - b[2];
|
||||
out[3] = a[3] + twoP1234 - b[3];
|
||||
out[4] = a[4] + twoP1234 - b[4];
|
||||
out[0] = a[0] + two54m152 - b[0];
|
||||
out[1] = a[1] + two54m8 - b[1];
|
||||
out[2] = a[2] + two54m8 - b[2];
|
||||
out[3] = a[3] + two54m8 - b[3];
|
||||
out[4] = a[4] + two54m8 - b[4];
|
||||
}
|
||||
|
||||
/* out = a - b, where a and/or b are the result of a basic op (add,sub) */
|
||||
/* out = (in * scalar) */
|
||||
inline void
|
||||
curve25519_sub_after_basic(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
out[0] = a[0] + fourP0 - b[0];
|
||||
out[1] = a[1] + fourP1234 - b[1];
|
||||
out[2] = a[2] + fourP1234 - b[2];
|
||||
out[3] = a[3] + fourP1234 - b[3];
|
||||
out[4] = a[4] + fourP1234 - b[4];
|
||||
}
|
||||
curve25519_scalar_product(bignum25519 out, const bignum25519 in, const word64 scalar) {
|
||||
word128 a;
|
||||
word64 c;
|
||||
|
||||
inline void
|
||||
curve25519_sub_reduce(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
word64 c;
|
||||
out[0] = a[0] + fourP0 - b[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
|
||||
out[1] = a[1] + fourP1234 - b[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
|
||||
out[2] = a[2] + fourP1234 - b[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
|
||||
out[3] = a[3] + fourP1234 - b[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
|
||||
out[4] = a[4] + fourP1234 - b[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
|
||||
out[0] += c * 19;
|
||||
}
|
||||
|
||||
/* out = -a */
|
||||
inline void
|
||||
curve25519_neg(bignum25519 out, const bignum25519 a) {
|
||||
word64 c;
|
||||
out[0] = twoP0 - a[0] ; c = (out[0] >> 51); out[0] &= reduce_mask_51;
|
||||
out[1] = twoP1234 - a[1] + c; c = (out[1] >> 51); out[1] &= reduce_mask_51;
|
||||
out[2] = twoP1234 - a[2] + c; c = (out[2] >> 51); out[2] &= reduce_mask_51;
|
||||
out[3] = twoP1234 - a[3] + c; c = (out[3] >> 51); out[3] &= reduce_mask_51;
|
||||
out[4] = twoP1234 - a[4] + c; c = (out[4] >> 51); out[4] &= reduce_mask_51;
|
||||
out[0] += c * 19;
|
||||
#if defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
a = ((word128) in[0]) * scalar; out[0] = (word64)a & reduce_mask_51; c = (word64)(a >> 51);
|
||||
a = ((word128) in[1]) * scalar + c; out[1] = (word64)a & reduce_mask_51; c = (word64)(a >> 51);
|
||||
a = ((word128) in[2]) * scalar + c; out[2] = (word64)a & reduce_mask_51; c = (word64)(a >> 51);
|
||||
a = ((word128) in[3]) * scalar + c; out[3] = (word64)a & reduce_mask_51; c = (word64)(a >> 51);
|
||||
a = ((word128) in[4]) * scalar + c; out[4] = (word64)a & reduce_mask_51; c = (word64)(a >> 51);
|
||||
out[0] += c * 19;
|
||||
#else
|
||||
mul64x64_128(a, in[0], scalar) out[0] = lo128(a) & reduce_mask_51; shr128(c, a, 51);
|
||||
mul64x64_128(a, in[1], scalar) add128_64(a, c) out[1] = lo128(a) & reduce_mask_51; shr128(c, a, 51);
|
||||
mul64x64_128(a, in[2], scalar) add128_64(a, c) out[2] = lo128(a) & reduce_mask_51; shr128(c, a, 51);
|
||||
mul64x64_128(a, in[3], scalar) add128_64(a, c) out[3] = lo128(a) & reduce_mask_51; shr128(c, a, 51);
|
||||
mul64x64_128(a, in[4], scalar) add128_64(a, c) out[4] = lo128(a) & reduce_mask_51; shr128(c, a, 51);
|
||||
out[0] += c * 19;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* out = a * b */
|
||||
inline void
|
||||
curve25519_mul(bignum25519 out, const bignum25519 in2, const bignum25519 in) {
|
||||
curve25519_mul(bignum25519 out, const bignum25519 a, const bignum25519 b) {
|
||||
#if !defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
word128 mul;
|
||||
#endif
|
||||
word128 t[5];
|
||||
word64 r0,r1,r2,r3,r4,s0,s1,s2,s3,s4,c;
|
||||
|
||||
r0 = in[0]; r1 = in[1]; r2 = in[2]; r3 = in[3]; r4 = in[4];
|
||||
s0 = in2[0]; s1 = in2[1]; s2 = in2[2]; s3 = in2[3]; s4 = in2[4];
|
||||
r0 = b[0]; r1 = b[1]; r2 = b[2]; r3 = b[3]; r4 = b[4];
|
||||
s0 = a[0]; s1 = a[1]; s2 = a[2]; s3 = a[3]; s4 = a[4];
|
||||
|
||||
#if defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
t[0] = ((word128) r0) * s0;
|
||||
@ -195,13 +163,8 @@ curve25519_mul(bignum25519 out, const bignum25519 in2, const bignum25519 in) {
|
||||
out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4;
|
||||
}
|
||||
|
||||
void
|
||||
curve25519_mul_noinline(bignum25519 out, const bignum25519 in2, const bignum25519 in) {
|
||||
curve25519_mul(out, in2, in);
|
||||
}
|
||||
|
||||
/* out = in^(2 * count) */
|
||||
void
|
||||
inline void
|
||||
curve25519_square_times(bignum25519 out, const bignum25519 in, word64 count) {
|
||||
#if !defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
word128 mul;
|
||||
@ -215,8 +178,7 @@ curve25519_square_times(bignum25519 out, const bignum25519 in, word64 count) {
|
||||
do {
|
||||
d0 = r0 * 2; d1 = r1 * 2;
|
||||
d2 = r2 * 2 * 19;
|
||||
d419 = r4 * 19;
|
||||
d4 = d419 * 2;
|
||||
d419 = r4 * 19; d4 = d419 * 2;
|
||||
|
||||
#if defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 ));
|
||||
@ -232,18 +194,13 @@ curve25519_square_times(bignum25519 out, const bignum25519 in, word64 count) {
|
||||
mul64x64_128(t[4], d0, r4) mul64x64_128(mul, d1, r3) add128(t[4], mul) mul64x64_128(mul, r2, r2) add128(t[4], mul)
|
||||
#endif
|
||||
|
||||
r0 = lo128(t[0]) & reduce_mask_51;
|
||||
r1 = lo128(t[1]) & reduce_mask_51; shl128(c, t[0], 13); r1 += c;
|
||||
r2 = lo128(t[2]) & reduce_mask_51; shl128(c, t[1], 13); r2 += c;
|
||||
r3 = lo128(t[3]) & reduce_mask_51; shl128(c, t[2], 13); r3 += c;
|
||||
r4 = lo128(t[4]) & reduce_mask_51; shl128(c, t[3], 13); r4 += c;
|
||||
shl128(c, t[4], 13); r0 += c * 19;
|
||||
c = r0 >> 51; r0 &= reduce_mask_51;
|
||||
r1 += c ; c = r1 >> 51; r1 &= reduce_mask_51;
|
||||
r2 += c ; c = r2 >> 51; r2 &= reduce_mask_51;
|
||||
r3 += c ; c = r3 >> 51; r3 &= reduce_mask_51;
|
||||
r4 += c ; c = r4 >> 51; r4 &= reduce_mask_51;
|
||||
r0 += c * 19;
|
||||
r0 = lo128(t[0]) & reduce_mask_51; shr128(c, t[0], 51);
|
||||
add128_64(t[1], c) r1 = lo128(t[1]) & reduce_mask_51; shr128(c, t[1], 51);
|
||||
add128_64(t[2], c) r2 = lo128(t[2]) & reduce_mask_51; shr128(c, t[2], 51);
|
||||
add128_64(t[3], c) r3 = lo128(t[3]) & reduce_mask_51; shr128(c, t[3], 51);
|
||||
add128_64(t[4], c) r4 = lo128(t[4]) & reduce_mask_51; shr128(c, t[4], 51);
|
||||
r0 += c * 19; c = r0 >> 51; r0 = r0 & reduce_mask_51;
|
||||
r1 += c;
|
||||
} while(--count);
|
||||
|
||||
out[0] = r0; out[1] = r1; out[2] = r2; out[3] = r3; out[4] = r4;
|
||||
@ -262,8 +219,7 @@ curve25519_square(bignum25519 out, const bignum25519 in) {
|
||||
|
||||
d0 = r0 * 2; d1 = r1 * 2;
|
||||
d2 = r2 * 2 * 19;
|
||||
d419 = r4 * 19;
|
||||
d4 = d419 * 2;
|
||||
d419 = r4 * 19; d4 = d419 * 2;
|
||||
|
||||
#if defined(CRYPTOPP_WORD128_AVAILABLE)
|
||||
t[0] = ((word128) r0) * r0 + ((word128) d4) * r1 + (((word128) d2) * (r3 ));
|
||||
@ -302,7 +258,7 @@ curve25519_expand(bignum25519 out, const byte *in) {
|
||||
out[1] = x0 & reduce_mask_51; x1 = (x1 >> 38) | (x2 << 26);
|
||||
out[2] = x1 & reduce_mask_51; x2 = (x2 >> 25) | (x3 << 39);
|
||||
out[3] = x2 & reduce_mask_51; x3 = (x3 >> 12);
|
||||
out[4] = x3 & reduce_mask_51;
|
||||
out[4] = x3 & reduce_mask_51; /* ignore the top bit */
|
||||
}
|
||||
|
||||
/* Take a fully reduced polynomial form number and contract it into a
|
||||
@ -313,8 +269,11 @@ curve25519_contract(byte *out, const bignum25519 input) {
|
||||
word64 t[5];
|
||||
word64 f, i;
|
||||
|
||||
t[0] = input[0]; t[1] = input[1]; t[2] = input[2];
|
||||
t[3] = input[3]; t[4] = input[4];
|
||||
t[0] = input[0];
|
||||
t[1] = input[1];
|
||||
t[2] = input[2];
|
||||
t[3] = input[3];
|
||||
t[4] = input[4];
|
||||
|
||||
#define curve25519_contract_carry() \
|
||||
t[1] += t[0] >> 51; t[0] &= reduce_mask_51; \
|
||||
@ -337,11 +296,11 @@ curve25519_contract(byte *out, const bignum25519 input) {
|
||||
curve25519_contract_carry_full()
|
||||
|
||||
/* now between 19 and 2^255-1 in both cases, and offset by 19. */
|
||||
t[0] += (reduce_mask_51 + 1) - 19;
|
||||
t[1] += (reduce_mask_51 + 1) - 1;
|
||||
t[2] += (reduce_mask_51 + 1) - 1;
|
||||
t[3] += (reduce_mask_51 + 1) - 1;
|
||||
t[4] += (reduce_mask_51 + 1) - 1;
|
||||
t[0] += 0x8000000000000 - 19;
|
||||
t[1] += 0x8000000000000 - 1;
|
||||
t[2] += 0x8000000000000 - 1;
|
||||
t[3] += 0x8000000000000 - 1;
|
||||
t[4] += 0x8000000000000 - 1;
|
||||
|
||||
/* now between 2^255 and 2^256-20, and offset by 2^255. */
|
||||
curve25519_contract_carry_final()
|
||||
@ -350,10 +309,75 @@ curve25519_contract(byte *out, const bignum25519 input) {
|
||||
f = ((t[n] >> shift) | (t[n+1] << (51 - shift))); \
|
||||
for (i = 0; i < 8; i++, f >>= 8) *out++ = (byte)f;
|
||||
#define write51(n) write51full(n,13*n)
|
||||
|
||||
write51(0)
|
||||
write51(1)
|
||||
write51(2)
|
||||
write51(3)
|
||||
|
||||
#undef curve25519_contract_carry
|
||||
#undef curve25519_contract_carry_full
|
||||
#undef curve25519_contract_carry_final
|
||||
#undef write51full
|
||||
#undef write51
|
||||
}
|
||||
|
||||
/*
|
||||
* Swap the contents of [qx] and [qpx] iff @swap is non-zero
|
||||
*/
|
||||
inline void
|
||||
curve25519_swap_conditional(bignum25519 x, bignum25519 qpx, word64 iswap) {
|
||||
const word64 swap = (word64)(-(int64_t)iswap);
|
||||
word64 x0,x1,x2,x3,x4;
|
||||
|
||||
x0 = swap & (x[0] ^ qpx[0]); x[0] ^= x0; qpx[0] ^= x0;
|
||||
x1 = swap & (x[1] ^ qpx[1]); x[1] ^= x1; qpx[1] ^= x1;
|
||||
x2 = swap & (x[2] ^ qpx[2]); x[2] ^= x2; qpx[2] ^= x2;
|
||||
x3 = swap & (x[3] ^ qpx[3]); x[3] ^= x3; qpx[3] ^= x3;
|
||||
x4 = swap & (x[4] ^ qpx[4]); x[4] ^= x4; qpx[4] ^= x4;
|
||||
}
|
||||
|
||||
/*
|
||||
* In: b = 2^5 - 2^0
|
||||
* Out: b = 2^250 - 2^0
|
||||
*/
|
||||
void
|
||||
curve25519_pow_two5mtwo0_two250mtwo0(bignum25519 b) {
|
||||
ALIGN(16) bignum25519 t0,c;
|
||||
|
||||
/* 2^5 - 2^0 */ /* b */
|
||||
/* 2^10 - 2^5 */ curve25519_square_times(t0, b, 5);
|
||||
/* 2^10 - 2^0 */ curve25519_mul(b, t0, b);
|
||||
/* 2^20 - 2^10 */ curve25519_square_times(t0, b, 10);
|
||||
/* 2^20 - 2^0 */ curve25519_mul(c, t0, b);
|
||||
/* 2^40 - 2^20 */ curve25519_square_times(t0, c, 20);
|
||||
/* 2^40 - 2^0 */ curve25519_mul(t0, t0, c);
|
||||
/* 2^50 - 2^10 */ curve25519_square_times(t0, t0, 10);
|
||||
/* 2^50 - 2^0 */ curve25519_mul(b, t0, b);
|
||||
/* 2^100 - 2^50 */ curve25519_square_times(t0, b, 50);
|
||||
/* 2^100 - 2^0 */ curve25519_mul(c, t0, b);
|
||||
/* 2^200 - 2^100 */ curve25519_square_times(t0, c, 100);
|
||||
/* 2^200 - 2^0 */ curve25519_mul(t0, t0, c);
|
||||
/* 2^250 - 2^50 */ curve25519_square_times(t0, t0, 50);
|
||||
/* 2^250 - 2^0 */ curve25519_mul(b, t0, b);
|
||||
}
|
||||
|
||||
/*
|
||||
* z^(p - 2) = z(2^255 - 21)
|
||||
*/
|
||||
void
|
||||
curve25519_recip(bignum25519 out, const bignum25519 z) {
|
||||
ALIGN(16) bignum25519 a, t0, b;
|
||||
|
||||
/* 2 */ curve25519_square(a, z); /* a = 2 */
|
||||
/* 8 */ curve25519_square_times(t0, a, 2);
|
||||
/* 9 */ curve25519_mul(b, t0, z); /* b = 9 */
|
||||
/* 11 */ curve25519_mul(a, b, a); /* a = 11 */
|
||||
/* 22 */ curve25519_square(t0, a);
|
||||
/* 2^5 - 2^0 = 31 */ curve25519_mul(b, t0, b);
|
||||
/* 2^250 - 2^0 */ curve25519_pow_two5mtwo0_two250mtwo0(b);
|
||||
/* 2^255 - 2^5 */ curve25519_square_times(b, b, 5);
|
||||
/* 2^255 - 21 */ curve25519_mul(out, b, a);
|
||||
}
|
||||
|
||||
ANONYMOUS_NAMESPACE_END
|
||||
@ -363,12 +387,65 @@ NAMESPACE_BEGIN(Donna)
|
||||
|
||||
int curve25519_CXX(byte sharedKey[32], const byte secretKey[32], const byte othersKey[32])
|
||||
{
|
||||
bignum25519 out, r, s;
|
||||
curve25519_expand(r, secretKey);
|
||||
curve25519_expand(s, othersKey);
|
||||
FixedSizeSecBlock<byte, 32> e;
|
||||
for (size_t i = 0;i < 32;++i)
|
||||
e[i] = secretKey[i];
|
||||
e[0] &= 0xf8; e[31] &= 0x7f; e[31] |= 0x40;
|
||||
|
||||
curve25519_mul(out, r, s);
|
||||
curve25519_contract(sharedKey, out);
|
||||
bignum25519 nqpqx = {1}, nqpqz = {0}, nqz = {1}, nqx;
|
||||
bignum25519 q, qx, qpqx, qqx, zzz, zmone;
|
||||
size_t bit, lastbit;
|
||||
|
||||
curve25519_expand(q, othersKey);
|
||||
curve25519_copy(nqx, q);
|
||||
|
||||
/* bit 255 is always 0, and bit 254 is always 1, so skip bit 255 and
|
||||
start pre-swapped on bit 254 */
|
||||
lastbit = 1;
|
||||
|
||||
/* we are doing bits 254..3 in the loop, but are swapping in bits 253..2 */
|
||||
for (int i = 253; i >= 2; i--) {
|
||||
curve25519_add(qx, nqx, nqz);
|
||||
curve25519_sub(nqz, nqx, nqz);
|
||||
curve25519_add(qpqx, nqpqx, nqpqz);
|
||||
curve25519_sub(nqpqz, nqpqx, nqpqz);
|
||||
curve25519_mul(nqpqx, qpqx, nqz);
|
||||
curve25519_mul(nqpqz, qx, nqpqz);
|
||||
curve25519_add(qqx, nqpqx, nqpqz);
|
||||
curve25519_sub(nqpqz, nqpqx, nqpqz);
|
||||
curve25519_square(nqpqz, nqpqz);
|
||||
curve25519_square(nqpqx, qqx);
|
||||
curve25519_mul(nqpqz, nqpqz, q);
|
||||
curve25519_square(qx, qx);
|
||||
curve25519_square(nqz, nqz);
|
||||
curve25519_mul(nqx, qx, nqz);
|
||||
curve25519_sub(nqz, qx, nqz);
|
||||
curve25519_scalar_product(zzz, nqz, 121665);
|
||||
curve25519_add(zzz, zzz, qx);
|
||||
curve25519_mul(nqz, nqz, zzz);
|
||||
|
||||
bit = (e[i/8] >> (i & 7)) & 1;
|
||||
curve25519_swap_conditional(nqx, nqpqx, bit ^ lastbit);
|
||||
curve25519_swap_conditional(nqz, nqpqz, bit ^ lastbit);
|
||||
lastbit = bit;
|
||||
}
|
||||
|
||||
/* the final 3 bits are always zero, so we only need to double */
|
||||
for (int i = 0; i < 3; i++) {
|
||||
curve25519_add(qx, nqx, nqz);
|
||||
curve25519_sub(nqz, nqx, nqz);
|
||||
curve25519_square(qx, qx);
|
||||
curve25519_square(nqz, nqz);
|
||||
curve25519_mul(nqx, qx, nqz);
|
||||
curve25519_sub(nqz, qx, nqz);
|
||||
curve25519_scalar_product(zzz, nqz, 121665);
|
||||
curve25519_add(zzz, zzz, qx);
|
||||
curve25519_mul(nqz, nqz, zzz);
|
||||
}
|
||||
|
||||
curve25519_recip(zmone, nqz);
|
||||
curve25519_mul(nqz, nqx, zmone);
|
||||
curve25519_contract(sharedKey, nqz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user