Skip to content

Commit 4a688b0

Browse files
committed
ecc/25519/sp: octet-correct X25519/Ed25519 and SP byte<->mp conversion for CHAR_BIT != 8
1 parent 7929398 commit 4a688b0

6 files changed

Lines changed: 56 additions & 12 deletions

File tree

wolfcrypt/src/fe_operations.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,9 @@ void fe_tobytes(unsigned char *s,const fe h)
525525
sword32 carry7;
526526
sword32 carry8;
527527
sword32 carry9;
528+
#ifdef WOLFSSL_WIDE_BYTE
529+
int i;
530+
#endif
528531

529532
q = (19 * h9 + (sword32)(((word32) 1) << 24)) >> 25;
530533
q = (h0 + q) >> 26;
@@ -593,6 +596,12 @@ void fe_tobytes(unsigned char *s,const fe h)
593596
s[29] = (byte)(h9 >> 2);
594597
s[30] = (byte)(h9 >> 10);
595598
s[31] = (byte)(h9 >> 18);
599+
#ifdef WOLFSSL_WIDE_BYTE
600+
/* CHAR_BIT != 8: a (byte) cast does not truncate to an octet, so mask each
601+
* output cell to its low 8 bits (the intended octet computed above). */
602+
for (i = 0; i < 32; i++)
603+
s[i] = WC_OCTET(s[i]);
604+
#endif
596605
}
597606

598607

wolfcrypt/src/ge_operations.c

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ void sc_reduce(byte* s)
109109
{
110110
sword64 t[24];
111111
sword64 carry;
112+
#ifdef WOLFSSL_WIDE_BYTE
113+
int i;
114+
#endif
112115

113116
t[ 0] = MASK_21 & (load_3(s + 0) >> 0);
114117
t[ 1] = MASK_21 & (load_4(s + 2) >> 5);
@@ -296,6 +299,12 @@ void sc_reduce(byte* s)
296299
s[29] = (byte)(t[11] >> 1);
297300
s[30] = (byte)(t[11] >> 9);
298301
s[31] = (byte)(t[11] >> 17);
302+
#ifdef WOLFSSL_WIDE_BYTE
303+
/* CHAR_BIT != 8: a (byte) cast does not truncate to an octet, so mask each
304+
* output cell to its low 8 bits (the intended octet computed above). */
305+
for (i = 0; i < 32; i++)
306+
s[i] = WC_OCTET(s[i]);
307+
#endif
299308
}
300309

301310
/*
@@ -313,6 +322,9 @@ void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c)
313322
word32 ad[12], bd[12], cd[12];
314323
sword64 t[24];
315324
sword64 carry;
325+
#ifdef WOLFSSL_WIDE_BYTE
326+
int i;
327+
#endif
316328

317329
ad[ 0] = MASK_21 & (load_3(a + 0) >> 0);
318330
ad[ 1] = MASK_21 & (load_4(a + 2) >> 5);
@@ -616,6 +628,12 @@ void sc_muladd(byte* s, const byte* a, const byte* b, const byte* c)
616628
s[29] = (byte)(t[11] >> 1);
617629
s[30] = (byte)(t[11] >> 9);
618630
s[31] = (byte)(t[11] >> 17);
631+
#ifdef WOLFSSL_WIDE_BYTE
632+
/* CHAR_BIT != 8: a (byte) cast does not truncate to an octet, so mask each
633+
* output cell to its low 8 bits (the intended octet computed above). */
634+
for (i = 0; i < 32; i++)
635+
s[i] = WC_OCTET(s[i]);
636+
#endif
619637
}
620638
#endif
621639
#else
@@ -974,7 +992,10 @@ static unsigned char equal(unsigned char b,unsigned char c)
974992

975993
static unsigned char negative(signed char b)
976994
{
977-
return ((unsigned char)b) >> 7;
995+
/* Want bit 7 (the 8-bit sign bit) as 0/1. An (unsigned char) cast does not
996+
* truncate to 8 bits where a byte is wider than an octet (C28x), so mask to
997+
* an octet first; WC_OCTET is a no-op on 8-bit targets. */
998+
return (unsigned char)(WC_OCTET(b) >> 7);
978999
}
9791000

9801001
static WC_INLINE void cmov(ge_precomp *t,const ge_precomp *u,unsigned char b,

wolfcrypt/src/sp_c32.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -380,13 +380,13 @@ static void sp_2048_to_bin_72(sp_digit* r, byte* a)
380380
for (i=0; i<71 && j>=0; i++) {
381381
b = 0;
382382
/* lint allow cast of mismatch sp_digit and int */
383-
a[j--] |= (byte)((sp_uint32)r[i] << s); /*lint !e9033*/
383+
a[j--] |= (byte)(((sp_uint32)r[i] << s) & 0xFF); /*lint !e9033*/
384384
b += 8 - s;
385385
if (j < 0) {
386386
break;
387387
}
388388
while (b < 29) {
389-
a[j--] = (byte)(r[i] >> b);
389+
a[j--] = (byte)((r[i] >> b) & 0xFF);
390390
b += 8;
391391
if (j < 0) {
392392
break;
@@ -5313,13 +5313,13 @@ static void sp_3072_to_bin_106(sp_digit* r, byte* a)
53135313
for (i=0; i<106 && j>=0; i++) {
53145314
b = 0;
53155315
/* lint allow cast of mismatch sp_digit and int */
5316-
a[j--] |= (byte)((sp_uint32)r[i] << s); /*lint !e9033*/
5316+
a[j--] |= (byte)(((sp_uint32)r[i] << s) & 0xFF); /*lint !e9033*/
53175317
b += 8 - s;
53185318
if (j < 0) {
53195319
break;
53205320
}
53215321
while (b < 29) {
5322-
a[j--] = (byte)(r[i] >> b);
5322+
a[j--] = (byte)((r[i] >> b) & 0xFF);
53235323
b += 8;
53245324
if (j < 0) {
53255325
break;
@@ -12915,13 +12915,13 @@ static void sp_4096_to_bin_142(sp_digit* r, byte* a)
1291512915
for (i=0; i<142 && j>=0; i++) {
1291612916
b = 0;
1291712917
/* lint allow cast of mismatch sp_digit and int */
12918-
a[j--] |= (byte)((sp_uint32)r[i] << s); /*lint !e9033*/
12918+
a[j--] |= (byte)(((sp_uint32)r[i] << s) & 0xFF); /*lint !e9033*/
1291912919
b += 8 - s;
1292012920
if (j < 0) {
1292112921
break;
1292212922
}
1292312923
while (b < 29) {
12924-
a[j--] = (byte)(r[i] >> b);
12924+
a[j--] = (byte)((r[i] >> b) & 0xFF);
1292512925
b += 8;
1292612926
if (j < 0) {
1292712927
break;
@@ -25240,13 +25240,13 @@ static void sp_256_to_bin_9(sp_digit* r, byte* a)
2524025240
for (i=0; i<9 && j>=0; i++) {
2524125241
b = 0;
2524225242
/* lint allow cast of mismatch sp_digit and int */
25243-
a[j--] |= (byte)((sp_uint32)r[i] << s); /*lint !e9033*/
25243+
a[j--] |= (byte)(((sp_uint32)r[i] << s) & 0xFF); /*lint !e9033*/
2524425244
b += 8 - s;
2524525245
if (j < 0) {
2524625246
break;
2524725247
}
2524825248
while (b < 29) {
25249-
a[j--] = (byte)(r[i] >> b);
25249+
a[j--] = (byte)((r[i] >> b) & 0xFF);
2525025250
b += 8;
2525125251
if (j < 0) {
2525225252
break;

wolfcrypt/src/sp_int.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18313,7 +18313,9 @@ int sp_read_unsigned_bin(sp_int* a, const byte* in, word32 inSz)
1831318313
#if SP_WORD_SIZE >= 16
1831418314
/* Handle leftovers. */
1831518315
if (i >= 0) {
18316-
#ifdef BIG_ENDIAN_ORDER
18316+
#if defined(BIG_ENDIAN_ORDER) || defined(WOLFSSL_WIDE_BYTE)
18317+
/* Shift-based packing; CHAR_BIT-agnostic, unlike the byte-aliasing
18318+
* path below (which assumes one octet per cell - wrong on C28x). */
1831718319
int s;
1831818320

1831918321
/* Place remaining bytes into last digit. */

wolfssl/wolfcrypt/settings.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5157,7 +5157,10 @@ blinding by defining WC_BLINDING_NO_RNG_ACKNOWLEDGE_WEAKNESS."
51575157
" with static memory (WOLFSSL_STATIC_MEMORY)"
51585158
#endif
51595159
#if defined(WC_16BIT_CPU) && \
5160-
(defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL))
5160+
(defined(WOLFSSL_SP_MATH) || defined(WOLFSSL_SP_MATH_ALL)) && \
5161+
!defined(WOLFSSL_SP_ALLOW_16BIT_CPU)
5162+
/* SP math works on a 16-bit-int CPU with SP_WORD_SIZE >= 32 (validated on
5163+
* TI C28x); opt past this guard with WOLFSSL_SP_ALLOW_16BIT_CPU. */
51615164
#error "16-bit build (WC_16BIT_CPU) is not available with SP math"
51625165
#endif
51635166

wolfssl/wolfcrypt/sp_int.h

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,17 @@ extern "C" {
5858

5959
typedef unsigned char sp_uint7;
6060
typedef char sp_int7;
61+
#elif UCHAR_MAX == 65535
62+
/* CHAR_BIT == 16 (e.g. TI C28x): the smallest addressable type is 16-bit,
63+
* so there is no native 8-bit type. An "8-bit" SP value is a 16-bit char
64+
* cell holding an octet (0..255); byte I/O masks to an octet (the same
65+
* CHAR_BIT!=8 handling used elsewhere - see WOLFSSL_WIDE_BYTE). */
66+
#define SP_UCHAR_BITS 16
67+
68+
typedef unsigned char sp_uint8;
69+
typedef char sp_int8;
6170
#else
62-
#error "Size of unsigned short not detected"
71+
#error "Size of unsigned char not detected"
6372
#endif
6473

6574
#if USHRT_MAX == 65535

0 commit comments

Comments
 (0)