Description
Version
5.7.2
Description
It seems that the binaries built on/for 32-bit platforms have some troubles in OCSP.
ocsp.test differs on 64-bit platform and 32-bit platform
If I build binaries on GNU/Linux x86_64, scripts/ocsp.test finishes 2 tests: 1st for www.globalsign.com, 2nd for www.google.com. But if I build binaries for GNU/Linux i386, and Mac OS X 10.4 (running on PowerPC 32-bit), the 1st test passes, but the 2nd test fails by "ASN sig error".
Here I report the case of the binary built without single precision module (to compare with the result of PowerPC, a real 32-bit processor, but Mac OS X 10.4 assembler might be too buggy to compile single precision module, as reported in Issue #7905), but almost same error is found in the binary built with single precision module. The error occurs in fp_exptmod_nct(), by too big input length.
The beginning of the error happens in fp_exptmod_nct(), wolfcrypt/src/tfm.c:
3300 int fp_exptmod_nct(fp_int * G, fp_int * X, fp_int * P, fp_int * Y)
3301 {
3302 #if defined(WOLFSSL_ESP32_CRYPT_RSA_PRI_EXPTMOD)
3303 int retHW = FP_OKAY;
3304 #endif
3305
3306 /* handle modulus of zero and prevent overflows */
3307 if (fp_iszero(P) || (P->used > (FP_SIZE/2))) {
3308 return FP_VAL;
3309 }
If P->used is greater than (FP_SIZE / 2), fp_exptmod_nct() returns an error (if everything goes well, FP_OKAY would be returned).
GDB debugging script
I inspected the variables by following .gdbinit
and traced the values for RsaFunctionSync() and fp_exptmod_nct().
break fp_exptmod_nct
commands
silent
printf " fp_exptmod_nct(): P->used = %d, (FP_SIZE / 2) = %d\n", P->used, (FP_SIZE / 2)
cont
end
break RsaFunctionSync
commands
silent
printf "RsaFunctionSync(): receive data with inLen = %d\n", inLen
cont
end
GDB output for a passing case
Below is the passing output of the x86_64 platform. P->used is always less than (FP_SIZE / 2) == 68
(gdb) run -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
Starting program: /tmp/wolfssl-current/build-amd64-no-sp/examples/client/client -X -C -h www.google.com -p
443 -A "certs/external/ca-google-root.pem" -g -o -N
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
... client would read block
... client would read block
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 512
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 32, (FP_SIZE / 2) = 68
... client would read block
Session Ticket CB: ticketSz = 229, ctx = initial session
...
GDB output for a failing case (i686 binary)
Below is the failing output of the cross-built i686 binary (running on x86_64 machine). P->used == 128 is greater than (FP_SIZE / 2) == 68.
(gdb) run -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
Starting program: /tmp/wolfssl-current/build-i686-no-sp/examples/client/client -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
... client would read block
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 512
fp_exptmod_nct(): P->used = 128, (FP_SIZE / 2) = 68
wolfSSL_connect error -155, ASN sig error, confirm failure
wolfSSL error: wolfSSL_connect failed
[Inferior 1 (process 250925) exited with code 01]
GDB output for a failing case (PowerPC)
Below is the failing output of the PowerPC binary (running on MacOS X 10.4). Unfortunately, the last version of gdb ported to MacOS X/ppc cannot handle the preprocessor macro constants, I inserted an unused fp_size variable to copy FP_SIZE value.
(gdb) run -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
Starting program: /tmp/wolfssl-current/build-no-sp/examples/client/client -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
Reading symbols for shared libraries . done
... client would read block
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 68
RsaFunctionSync(): receive data with inLen = 512
fp_exptmod_nct(): P->used = 128, (FP_SIZE / 2) = 68
wolfSSL_connect error -155, ASN sig error, confirm failure
wolfSSL error: wolfSSL_connect failed
Program exited with code 01.
NOTE: "gcc -m32" is not good to reproduce this error
Maybe, I should note that using "-m32" on 64-bit platforms is inappropriate in such testing, because this option does not change the proprocessor macros __x86_64__
or __aarch64__
, thus, the bitwidth of the registers might be different from real 32-bit processor.
Below is the passing output of "-m32" binary built on the x86_64 platform.
(gdb) run -X -C -h www.google.com -p 443 -A "certs/external/ca-google-root.pem" -g -o -N
Starting program: /tmp/wolfssl-current/build-m32-no-sp/examples/client/client -X -C -h www.google.com -p 4
43 -A "certs/external/ca-google-root.pem" -g -o -N
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
... client would read block
... client would read block
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 512
fp_exptmod_nct(): P->used = 128, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
RsaFunctionSync(): receive data with inLen = 256
fp_exptmod_nct(): P->used = 64, (FP_SIZE / 2) = 132
... client would read block
Session Ticket CB: ticketSz = 229, ctx = initial session
...
QUESTION
In summary, FP_SIZE for both platform are same, it looks reasonable, but P->used on 32-bit platform is sometimes too big. On 64-bit platforms, P->used seems to be the one-eighth (1/8) of the inLen of RsaFunctionSync(). But on 32-bit platforms, P->used seems to be quarter (1/4) of the inLen of RsaFunctionSync().
Yet I could not find why they are different, which part of the code I should check?