tls_pstm_montgomery.c is buggy...

David Sparks via busybox <[email protected]>
Newsgroups gmane.linux.busybox
Message-ID <GG5NeEUHpOE42jQClrV9E6GW-oF-GWyn1RROcMsy7sESwSpN_uW76mWjhGd1dMm7Vh6pDxcgMOmS8XsdNCZYZdRS1cKP7WkQh8UQ-G-fBE0=@proton.me>
I just came across the following MIPS code at line 328 of
tls_pstm_montgomery_reduce.c:
#define PROPCARRY                     \
asm(                                  \
	" lw       $10,%1        \n\t"    \
	" addu     $10,$10,%0    \n\t"    \
	" sw       $10,%1        \n\t"    \
	" sltu     %0,$10,%0     \n\t"    \
	:"=r"(cy),"=m"(_c[0])\
	:"r"(cy),"r"(_c[0])\
	:"$10");

Notice the lack of constraint forcing the output carry
to be in the same register as the input.  This code
computes the output carry into %0, but the compiler
expects it in %2.

A second bug is the fact that the compiler provides
_c[0] in register %3, but the code fetches it from %1.
Nobody told the compiler to ensure that memory is up to
date!  It might elide a store and pass the value to this
code instead.

Even if the above isn't a bug, it's still a waste of
code, as the compiler will load the value into a register
before the asm(), which will ignore it and fetch it itself.

A third problem, although not a bug, is the use of fixed
register $10 as a temporary.  Far better to declare
a variable and let the compiler pick the register.

The correct way to write this is:
#define PROPCARRY                     \
asm(                                  \
	"addu     %1,%1,%0"    "\n\t" \
	"sltu     %2,%1,%0"           \
	:"=r"(cy), "+r"(_c[0])        \
        :"r"(cy))

Or better yet, don't use asm() at all and just write:
#define PROPCARRY                     \
        cy = (_c[0] += cy) < cy

The MIPS INNERMUL macro has the same problems; it's just
bigger and so messier to explain.

Sheesh.  The correct way to write that is:
#define INNERMUL do {                    \
	pstm_digit lo, hi;               \
	asm(                             \
	"multu    %2,%3"        "\n\t"   \
	"mflo     %0"           "\n\t"   \
	"mfhi     %1"                    \
	:"=r"(lo), "=r"(hi),             \
	:"r"(mu), "r"(*tmpm++));         \
	hi += (lo += cy) < cy;           \
	hi += (_c[0] += lo) < lo;        \
	cy = hi;                         \
} while (0)

I haven't yet checked if this is fixed in upstream
MatrixSSL.
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.