Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
mpsuzuki opened this issue Aug 31, 2024 · 4 comments
Open

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

mpsuzuki opened this issue Aug 31, 2024 · 4 comments
Assignees
Labels

Comments

@mpsuzuki
Copy link
Contributor

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?

@embhorn embhorn self-assigned this Sep 2, 2024
@embhorn
Copy link
Member

embhorn commented Sep 2, 2024

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

@mpsuzuki
Copy link
Contributor Author

mpsuzuki commented Sep 3, 2024

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?

@embhorn
Copy link
Member

embhorn commented Sep 3, 2024

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

@mpsuzuki
Copy link
Contributor Author

mpsuzuki commented Sep 3, 2024

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.

@embhorn embhorn assigned douzzer and unassigned embhorn Sep 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants