wolfssl icon indicating copy to clipboard operation
wolfssl copied to clipboard

On 32-bit platform, ocsp.test to www.google.com may fail?

Open mpsuzuki opened this issue 1 year ago • 4 comments
trafficstars

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?

mpsuzuki avatar Aug 31 '24 09:08 mpsuzuki

Hi @mpsuzuki

The default value of FP_MAX_BITS is being set too low for this test. Increase the value to 2*. So for 4096 bit keys, configure with CFLAGS=-DFP_MAX_BITS=8192

Let us know if that resolve the issue.

Thanks, @embhorn - wolfSSL Support

embhorn avatar Sep 02 '24 13:09 embhorn

Thanks, the test finishes successfully. The output of GDB is almost same with the result of "x86_64-linux-gnu-gcc -m32".

(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-sp2/examples/client/client -X -C -h ww
w.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 = 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
Alternate cert chain used
...

On Mac OS X 10.4 on PowerPC,

(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-sp2/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) = 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
Alternate cert chain used
...

Also, the extension of FP_MAX_BITS=8192 seems to solve the similar issue for the binaries compiled for i386 with single precision module. Yet I'm unsure how to calculate the appropriate FP_MAX_BITS, should I submit a patch to extend FP_MAX_BITS for the cases: the architecture is 32-bit and OCSP is enabled?

mpsuzuki avatar Sep 03 '24 05:09 mpsuzuki

Great! I'll check if we would consider changing the default value of FP_MAX_BITS for the 32-bit PPC environment.

embhorn avatar Sep 03 '24 13:09 embhorn

Please consider i386 platform too (it was my original motivation to test this issue). Maybe, 32-bit PPC might be phasing out, but 32-bit x86 might be still non-negligible. I'm interested in other 32-bit platforms, like, 32-bit ARM, 32-bit MIPS, and m68k, but yet I've not made reliable environment to test them.

mpsuzuki avatar Sep 03 '24 13:09 mpsuzuki