Skip to content

Commit 70da839

Browse files
authored
Merge pull request #10536 from SparkiDev/curve25519_x64_red_fix
X25519 x64 ASM: fix full reduction
2 parents e80b4b5 + 14b55a0 commit 70da839

3 files changed

Lines changed: 99 additions & 0 deletions

File tree

tests/api/test_curve25519.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,99 @@ int test_wc_curve25519_shared_secret_zero_check(void)
398398
return EXPECT_RESULT();
399399
} /* END test_wc_curve25519_shared_secret_zero_check */
400400

401+
/*
402+
* Known-answer tests for wc_curve25519_shared_secret_ex.
403+
*
404+
* Both vectors share one private scalar and produce a shared secret that is a
405+
* small canonical value (9 and 16, little-endian). Because the result is close
406+
* to a multiple of the field prime, these exercise the final modular reduction
407+
* of the X25519 computation: a result that was only reduced mod 2^256 (or left
408+
* in [p, 2^255)) instead of fully reduced mod 2^255-19 would not match.
409+
* All values are 32-byte little-endian encodings per RFC 7748.
410+
*/
411+
int test_wc_curve25519_shared_secret_ex_kat(void)
412+
{
413+
EXPECT_DECLS;
414+
#if defined(HAVE_CURVE25519) && defined(HAVE_CURVE25519_KEY_IMPORT)
415+
/* Private scalar shared by both vectors. */
416+
static const byte kPriv[CURVE25519_KEYSIZE] = {
417+
0x60, 0xa3, 0xa4, 0xf1, 0x30, 0xb9, 0x8a, 0x5b,
418+
0xe4, 0xb1, 0xce, 0xdb, 0x7c, 0xb8, 0x55, 0x84,
419+
0xa3, 0x52, 0x0e, 0x14, 0x2d, 0x47, 0x4d, 0xc9,
420+
0xcc, 0xb9, 0x09, 0xa0, 0x73, 0xa9, 0x76, 0x7f
421+
};
422+
/* Vector 1 public value, expected shared secret == 9. */
423+
static const byte kPub1[CURVE25519_KEYSIZE] = {
424+
0x3b, 0x18, 0xdf, 0x1e, 0x50, 0xb8, 0x99, 0xeb,
425+
0xd5, 0x88, 0xc3, 0x16, 0x1c, 0xbd, 0x3b, 0xf9,
426+
0x8e, 0xbc, 0xc2, 0xc1, 0xf7, 0xdf, 0x53, 0xb8,
427+
0x11, 0xbd, 0x0e, 0x91, 0xb4, 0xd5, 0x15, 0x3d
428+
};
429+
static const byte kExpected1[CURVE25519_KEYSIZE] = {
430+
0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
431+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
432+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
433+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
434+
};
435+
/* Vector 2 public value, expected shared secret == 16. */
436+
static const byte kPub2[CURVE25519_KEYSIZE] = {
437+
0xca, 0xb6, 0xf9, 0xe7, 0xd8, 0xce, 0x00, 0xdf,
438+
0xce, 0xa9, 0xbb, 0xd8, 0xf0, 0x69, 0xef, 0x7f,
439+
0xb2, 0xac, 0x50, 0x4a, 0xbf, 0x83, 0xb8, 0x7d,
440+
0xb6, 0x01, 0xb5, 0xae, 0x0a, 0x7f, 0x76, 0x15
441+
};
442+
static const byte kExpected2[CURVE25519_KEYSIZE] = {
443+
0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
444+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
445+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
446+
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
447+
};
448+
/* Table-driven so both vectors run through the identical code path. */
449+
struct {
450+
const byte* pub;
451+
const byte* expected;
452+
} vec[2];
453+
curve25519_key private_key;
454+
curve25519_key public_key;
455+
WC_RNG rng;
456+
byte out[CURVE25519_KEYSIZE];
457+
word32 outLen;
458+
int i;
459+
460+
vec[0].pub = kPub1; vec[0].expected = kExpected1;
461+
vec[1].pub = kPub2; vec[1].expected = kExpected2;
462+
463+
XMEMSET(&rng, 0, sizeof(WC_RNG));
464+
ExpectIntEQ(wc_InitRng(&rng), 0);
465+
466+
for (i = 0; i < 2; i++) {
467+
XMEMSET(&private_key, 0, sizeof(private_key));
468+
XMEMSET(&public_key, 0, sizeof(public_key));
469+
ExpectIntEQ(wc_curve25519_init(&private_key), 0);
470+
ExpectIntEQ(wc_curve25519_init(&public_key), 0);
471+
#ifdef WOLFSSL_CURVE25519_BLINDING
472+
ExpectIntEQ(wc_curve25519_set_rng(&private_key, &rng), 0);
473+
#endif
474+
ExpectIntEQ(wc_curve25519_import_private_ex(kPriv, sizeof(kPriv),
475+
&private_key, EC25519_LITTLE_ENDIAN), 0);
476+
ExpectIntEQ(wc_curve25519_import_public_ex(vec[i].pub,
477+
CURVE25519_KEYSIZE, &public_key, EC25519_LITTLE_ENDIAN), 0);
478+
479+
outLen = sizeof(out);
480+
ExpectIntEQ(wc_curve25519_shared_secret_ex(&private_key, &public_key,
481+
out, &outLen, EC25519_LITTLE_ENDIAN), 0);
482+
ExpectIntEQ(outLen, CURVE25519_KEYSIZE);
483+
ExpectIntEQ(XMEMCMP(out, vec[i].expected, CURVE25519_KEYSIZE), 0);
484+
485+
wc_curve25519_free(&private_key);
486+
wc_curve25519_free(&public_key);
487+
}
488+
489+
DoExpectIntEQ(wc_FreeRng(&rng), 0);
490+
#endif
491+
return EXPECT_RESULT();
492+
} /* END test_wc_curve25519_shared_secret_ex_kat */
493+
401494
/*
402495
* Testing wc_curve25519_make_pub
403496
*/

tests/api/test_curve25519.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ int test_wc_curve25519_export_key_raw_ex(void);
3131
int test_wc_curve25519_make_key(void);
3232
int test_wc_curve25519_shared_secret_ex(void);
3333
int test_wc_curve25519_shared_secret_zero_check(void);
34+
int test_wc_curve25519_shared_secret_ex_kat(void);
3435
int test_wc_curve25519_make_pub(void);
3536
int test_wc_curve25519_export_public_ex(void);
3637
int test_wc_curve25519_export_private_raw_ex(void);
@@ -47,6 +48,7 @@ int test_wc_Curve25519KeyToDer_oneasymkey_version(void);
4748
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_key), \
4849
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_ex), \
4950
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_zero_check),\
51+
TEST_DECL_GROUP("curve25519", test_wc_curve25519_shared_secret_ex_kat), \
5052
TEST_DECL_GROUP("curve25519", test_wc_curve25519_make_pub), \
5153
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_public_ex), \
5254
TEST_DECL_GROUP("curve25519", test_wc_curve25519_export_private_raw_ex), \

wolfcrypt/src/fe_x25519_asm.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4639,6 +4639,7 @@ L_curve25519_base_x64_3:
46394639
adcq $0x00, %r8
46404640
adcq $0x00, %r9
46414641
adcq $0x00, %r10
4642+
andq %rax, %r10
46424643
# Store
46434644
movq %rcx, (%rdi)
46444645
movq %r8, 8(%rdi)
@@ -7054,6 +7055,7 @@ L_curve25519_x64_3:
70547055
adcq $0x00, %r9
70557056
adcq $0x00, %r10
70567057
adcq $0x00, %r11
7058+
andq %rax, %r11
70577059
# Store
70587060
movq %rcx, (%rdi)
70597061
movq %r9, 8(%rdi)
@@ -15107,6 +15109,7 @@ L_curve25519_base_avx2_last_3:
1510715109
adcq $0x00, %r9
1510815110
adcq $0x00, %r10
1510915111
adcq $0x00, %r11
15112+
andq %rcx, %r11
1511015113
# Store
1511115114
movq %r8, (%rdi)
1511215115
movq %r9, 8(%rdi)
@@ -17116,6 +17119,7 @@ L_curve25519_avx2_last_3:
1711617119
adcq $0x00, %r10
1711717120
adcq $0x00, %r11
1711817121
adcq $0x00, %r12
17122+
andq %rcx, %r12
1711917123
# Store
1712017124
movq %r9, (%rdi)
1712117125
movq %r10, 8(%rdi)

0 commit comments

Comments
 (0)