openssl / openssl/openssl

Add a catch-all `unknown sys error reason code` for cases where get_last_sys_error() returns 0

Open
#18,785 5 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

backlog fix branch: 3.0 branch: master triaged: bug
Dominant language
C
Stars
30.8k
Forks
11.5k
Avg merge
10m
Merged PRs (30d)
1

Description

Hi,

while porting our code from OpenSSL 1.1.1 to 3.0.0 I came across some interesting behavior in the error handling.

Testcase (Windows 10 21H1, Visual Studio 2022, OpenSSL 3.0.5):

#include <iostream>

#include <openssl/err.h>
#include <openssl/ssl.h>

// see https://github.com/chriskohlhoff/asio/blob/9902fe7d1d6b5321f4ab2f4ddbfd19cf39160891/asio/include/asio/ssl/impl/context.ipp#L541-L554
void load_verify_file(SSL_CTX* ctx, const char* file)
{
    ::ERR_clear_error();

    if (::SSL_CTX_load_verify_file(ctx, file) != 1) {

        const char *file, *func, *data;
        int line, flags;
        auto e = ERR_peek_error_all(&file, &line, &func, &data, &flags);

        std::cout << "e=0x" << std::hex << e << '\n';
        std::cout << " file=" << std::dec << file << '\n';
        std::cout << " line=" << std::dec << line << '\n';
        std::cout << " func=" << std::dec << func << '\n';
        std::cout << " data=" << std::dec << data << '\n';
        std::cout << " flags=" << std::dec << flags << '\n';
    }
}

int main() {

    const SSL_METHOD* m = TLS_method();

#if 0
    SSL_CTX* ctx1 = SSL_CTX_new(m);
    load_verify_file(ctx1, "D:/Git/rtc-platform/modules/network/Test/Data/test_trustedroots.pem");
    SSL_CTX_free(ctx1);
#endif

    SSL_CTX* ctx2 = SSL_CTX_new(m);
    load_verify_file(ctx2, "");
    SSL_CTX_free(ctx2);

    return 0;
}

If the SSL_CTX_load_verify_file function was successful before (even for a different context) its return value is 0 and the error code is 0x80000000. If I remove initialization of ctx1 the error code changes to 0x80000003.

With ctx1:

e=0x80000000
 file=crypto\bio\bss_file.c
 line=67
 func=BIO_new_file
 data=calling fopen(, r)
 flags=3

Without ctx1:

e=0x80000003
 file=crypto\bio\bss_file.c
 line=67
 func=BIO_new_file
 data=calling fopen(, r)
 flags=3

The problem is that ASIO translates 0x80000000 error into an boost error:

asio::error_code context::translate_error(long error)
{
#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)
  if (ERR_SYSTEM_ERROR(error))
  {
    return asio::error_code(
        static_cast<int>(ERR_GET_REASON(error)),
        asio::error::get_system_category());
  }
#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L)

  return asio::error_code(static_cast<int>(error),
      asio::error::get_ssl_category());
}

And 0x80000000 maps to the reason 0 which unfortunately means "No error" in the asio context.

Could you please add your thoughts about the issue?

  1. Why does the error code issued by SSL_CTX_load_verify_file change
  2. Is returning a reason of 0 a bug?

Thanks,
Gregor

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Windows testcase around SSL_CTX_load_verify_file and inspect ERR_peek_error_all, ERR_SYSTEM_ERROR, and ERR_GET_REASON, including the crypto\bio\bss_file.c path shown in the report. Compare the two context-initialization paths and determine whether reason 0 needs a catch-all code or the Asio translation should change; done requires a documented decision and coverage for the observed behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
cryptography, security
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.