wolfSSL / wolfssl

The wolfSSL library is a small, fast, portable implementation of TLS/SSL for embedded devices to the cloud. wolfSSL supports up to TLS 1.3 and DTLS 1.3!
https://www.wolfssl.com
GNU General Public License v2.0
2.31k stars 823 forks source link

[Bug]: wc_HmacSetKey corrupts memory #5450

Closed Ziemien closed 2 years ago

Ziemien commented 2 years ago

Contact Details

No response

Version

5.4.0

Description

osx 12.4, clang 14.0.6, used with cmake, installed via brew https://formulae.brew.sh/formula/wolfssl

set(wolfSSL_DIR ${_OSX_HOMEBREW_PATH}/opt/wolfssl)

add_library(wolfssl UNKNOWN IMPORTED)

set_target_properties(
        wolfssl
        PROPERTIES
        IMPORTED_LOCATION "${wolfSSL_DIR}/lib/libwolfssl.dylib"
        INTERFACE_INCLUDE_DIRECTORIES "${wolfSSL_DIR}/include"
)

add_definitions(-DWC_NO_HARDEN -DLARGE_STATIC_BUFFERS)

for how formula is compiled / defined see https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/wolfssl.rb

Reproduction steps

I followed the example from: https://www.wolfssl.com/documentation/manuals/wolfssl/chapter10.html#hmac

#define CATCH_CONFIG_ENABLE_BENCHMARKING

#include <catch2/catch.hpp>

#include <wolfssl/version.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/hmac.h>

TEST_CASE("emotional damage", "[wolfssl]") {
  std::string key = "abcdefgHV1TXd22_kjIaBXlYp_mwsaaakgvAwa19X";
  std::string payload = "parent=mum&meal=dinner&lunch=dimsum";

  Hmac hmac;
  byte hmacDigest[SHA256_DIGEST_SIZE];

  wc_HmacSetKey(&hmac, SHA256, reinterpret_cast<const byte *>(key.data()), key.size());
  wc_HmacUpdate(&hmac, reinterpret_cast<const byte *>(payload.data()), payload.size());
  wc_HmacFinal(&hmac, hmacDigest);
}

wc_HmacSetKey corrupts program memory causing segfaults

Relevant log output

Testing started at 12:04 ...

9: Failure:
fatal error

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
</Catch>
Ziemien commented 2 years ago

I traded this on the Amazon Linux 2, Clang 14.0.6 with libc++

<?xml version="1.0" encoding="UTF-8"?>
<Catch name="test" filters="emotional damage">
  <Group name="test">
    <TestCase name="emotional damage" tags="[wolfssl]" filename="file.cxx" line="6">
      <FatalErrorCondition filename="file.cxx" line="6">
        SIGSEGV - Segmentation violation signal
      </FatalErrorCondition>
      <OverallResult success="false" durationInSeconds="8.5e-05"/>
    </TestCase>
    <OverallResults successes="0" failures="1" expectedFailures="0"/>
    <OverallResultsCases successes="0" failures="1" expectedFailures="0"/>
  </Group>
  <OverallResults successes="0" failures="1" expectedFailures="0"/>
  <OverallResultsCases successes="0" failures="1" expectedFailures="0"/>
</Catch>Segmentation fault
dgarske commented 2 years ago

Hi @Ziemien ,

The reason for the crash is the stack defined for Hmac structure does not match the size that wolfSSL expects.

It sounds like your application is not including the wolfssl/options.h file. This is a generated file containing the build settings used at compile-time. It is important your application also includes / defines the same build settings.

See the FAQ item 1 here: https://www.wolfssl.com/docs/frequently-asked-questions-faq/#How_do_I_manage_the_build_configuration_for_wolfSSL?

Thanks, David Garske, wolfSSL

Ziemien commented 2 years ago

thank you, is --enable-fips require to access SHA256?

this seems to compile but if used with SHA256 as the docs suggested - symbol is undefined

#include <wolfssl/options.h>
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/ssl.h>

#include <wolfssl/wolfcrypt/hmac.h>

wc_HmacSetKey(&hmac, WC_SHA256, ...);
error: no matching function for call to 'wc_HmacSetKey'
  wc_HmacSetKey(&hmac, SHA256, reinterpret_cast<const byte *>(key.data()), key.size());
  ^~~~~~~~~~~~~
/opt/homebrew/opt/wolfssl/include/wolfssl/wolfcrypt/hmac.h:190:17: note: candidate function not viable: no known conversion from 'unsigned char *(const unsigned char *, size_t, unsigned char *)' (aka 'unsigned char *(const unsigned char *, unsigned long, unsigned char *)') to 'int' for 2nd argument
WOLFSSL_API int wc_HmacSetKey(Hmac* hmac, int type, const byte* key, word32 keySz);

options.h

/* wolfssl options.h
 * generated from configure options
 *
 * Copyright (C) 2006-2022 wolfSSL Inc.
 *
 * This file is part of wolfSSL. (formerly known as CyaSSL)
 *
 */

#ifndef WOLFSSL_OPTIONS_H
#define WOLFSSL_OPTIONS_H

#ifdef __cplusplus
extern "C" {
#endif

#undef  HAVE_THREAD_LS
#define HAVE_THREAD_LS

#undef  NO_DO178
#define NO_DO178

#undef  USE_FAST_MATH
#define USE_FAST_MATH

#undef  WOLFSSL_AARCH64_BUILD
#define WOLFSSL_AARCH64_BUILD

#ifndef WOLFSSL_OPTIONS_IGNORE_SYS
#undef  _POSIX_THREADS
#define _POSIX_THREADS
#endif

#undef  WOLFSSL_DTLS
#define WOLFSSL_DTLS

#undef  TFM_TIMING_RESISTANT
#define TFM_TIMING_RESISTANT

#undef  ECC_TIMING_RESISTANT
#define ECC_TIMING_RESISTANT

#undef  WC_RSA_BLINDING
#define WC_RSA_BLINDING

#undef  TEST_IPV6
#define TEST_IPV6

#undef  WOLFSSL_IPV6
#define WOLFSSL_IPV6

#undef  PERSIST_SESSION_CACHE
#define PERSIST_SESSION_CACHE

#undef  PERSIST_CERT_CACHE
#define PERSIST_CERT_CACHE

#undef  HAVE_AESCCM
#define HAVE_AESCCM

#undef  WOLFSSL_USE_ALIGN
#define WOLFSSL_USE_ALIGN

#undef  HAVE_CAMELLIA
#define HAVE_CAMELLIA

#undef  WOLFSSL_RIPEMD
#define WOLFSSL_RIPEMD

#undef  HAVE_BLAKE2
#define HAVE_BLAKE2

#undef  HAVE_BLAKE2B
#define HAVE_BLAKE2B

#undef  WOLFSSL_SHA224
#define WOLFSSL_SHA224

#undef  WOLFSSL_SHA512
#define WOLFSSL_SHA512

#undef  WOLFSSL_SHA384
#define WOLFSSL_SHA384

#undef  SESSION_CERTS
#define SESSION_CERTS

#undef  HAVE_HKDF
#define HAVE_HKDF

#undef  NO_DSA
#define NO_DSA

#undef  HAVE_ECC
#define HAVE_ECC

#undef  TFM_ECC256
#define TFM_ECC256

#undef  ECC_SHAMIR
#define ECC_SHAMIR

#undef  HAVE_CURVE25519
#define HAVE_CURVE25519

#undef  HAVE_ECC_ENCRYPT
#define HAVE_ECC_ENCRYPT

#undef  WC_RSA_PSS
#define WC_RSA_PSS

#undef  WOLFSSL_BASE64_ENCODE
#define WOLFSSL_BASE64_ENCODE

#undef  WOLFSSL_SHA3
#define WOLFSSL_SHA3

#undef  WOLFSSL_NO_SHAKE256
#define WOLFSSL_NO_SHAKE256

#undef  HAVE_POLY1305
#define HAVE_POLY1305

#undef  HAVE_CHACHA
#define HAVE_CHACHA

#undef  HAVE_HASHDRBG
#define HAVE_HASHDRBG

#undef  HAVE_OPENSSL_CMD
#define HAVE_OPENSSL_CMD

#undef  HAVE_CRL
#define HAVE_CRL

#undef  HAVE_CRL_MONITOR
#define HAVE_CRL_MONITOR

#undef  HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS

#undef  HAVE_SNI
#define HAVE_SNI

#undef  HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS

#undef  HAVE_ALPN
#define HAVE_ALPN

#undef  HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS

#undef  HAVE_SUPPORTED_CURVES
#define HAVE_SUPPORTED_CURVES

#undef  HAVE_FFDHE_2048
#define HAVE_FFDHE_2048

#undef  HAVE_SUPPORTED_CURVES
#define HAVE_SUPPORTED_CURVES

#undef  WOLFSSL_TLS13
#define WOLFSSL_TLS13

#undef  HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS

#undef  HAVE_EXTENDED_MASTER
#define HAVE_EXTENDED_MASTER

#undef  WOLFSSL_JNI
#define WOLFSSL_JNI

#undef  HAVE_EX_DATA
#define HAVE_EX_DATA

#undef  OPENSSL_EXTRA
#define OPENSSL_EXTRA

#undef  OPENSSL_ALL
#define OPENSSL_ALL

#undef  ATOMIC_USER
#define ATOMIC_USER

#undef  HAVE_PK_CALLBACKS
#define HAVE_PK_CALLBACKS

#undef  WOLFSSL_CERT_EXT
#define WOLFSSL_CERT_EXT

#undef  NO_RC4
#define NO_RC4

#undef  HAVE_ENCRYPT_THEN_MAC
#define HAVE_ENCRYPT_THEN_MAC

#undef  NO_MD4
#define NO_MD4

#undef  WOLFSSL_ENCRYPTED_KEYS
#define WOLFSSL_ENCRYPTED_KEYS

#undef  WOLFSSL_HAVE_SP_RSA
#define WOLFSSL_HAVE_SP_RSA

#undef  WOLFSSL_HAVE_SP_DH
#define WOLFSSL_HAVE_SP_DH

#undef  WOLFSSL_SP_4096
#define WOLFSSL_SP_4096

#undef  WOLFSSL_SP_LARGE_CODE
#define WOLFSSL_SP_LARGE_CODE

#undef  WOLFSSL_HAVE_SP_ECC
#define WOLFSSL_HAVE_SP_ECC

#undef  HAVE_ECC384
#define HAVE_ECC384

#undef  WOLFSSL_SP_384
#define WOLFSSL_SP_384

#undef  HAVE_ECC521
#define HAVE_ECC521

#undef  WOLFSSL_SP_521
#define WOLFSSL_SP_521

#undef  WC_NO_ASYNC_THREADING
#define WC_NO_ASYNC_THREADING

#undef  HAVE_DH_DEFAULT_PARAMS
#define HAVE_DH_DEFAULT_PARAMS

#undef  WOLFSSL_KEY_GEN
#define WOLFSSL_KEY_GEN

#undef  WOLFSSL_CERT_REQ
#define WOLFSSL_CERT_REQ

#undef  WOLFSSL_CERT_GEN
#define WOLFSSL_CERT_GEN

#undef  WOLFSSL_CERT_EXT
#define WOLFSSL_CERT_EXT

#undef  HAVE_ED25519
#define HAVE_ED25519

#undef  HAVE_OCSP
#define HAVE_OCSP

#undef  NO_ERROR_QUEUE
#define NO_ERROR_QUEUE

#undef  OPENSSL_ALL
#define OPENSSL_ALL

#undef  WOLFSSL_EITHER_SIDE
#define WOLFSSL_EITHER_SIDE

#undef  WC_RSA_NO_PADDING
#define WC_RSA_NO_PADDING

#undef  WC_RSA_PSS
#define WC_RSA_PSS

#undef  WOLFSSL_PSS_LONG_SALT
#define WOLFSSL_PSS_LONG_SALT

#undef  WOLFSSL_TICKET_HAVE_ID
#define WOLFSSL_TICKET_HAVE_ID

#undef  WOLFSSL_ERROR_CODE_OPENSSL
#define WOLFSSL_ERROR_CODE_OPENSSL

#undef  NO_MD5
#define NO_MD5

#undef  NO_OLD_TLS
#define NO_OLD_TLS

#undef  OPENSSL_EXTRA
#define OPENSSL_EXTRA

#undef  WOLFSSL_ALWAYS_VERIFY_CB
#define WOLFSSL_ALWAYS_VERIFY_CB

#undef  WOLFSSL_VERIFY_CB_ALL_CERTS
#define WOLFSSL_VERIFY_CB_ALL_CERTS

#undef  WOLFSSL_EXTRA_ALERTS
#define WOLFSSL_EXTRA_ALERTS

#undef  HAVE_EXT_CACHE
#define HAVE_EXT_CACHE

#undef  WOLFSSL_FORCE_CACHE_ON_TICKET
#define WOLFSSL_FORCE_CACHE_ON_TICKET

#undef  WOLFSSL_AKID_NAME
#define WOLFSSL_AKID_NAME

#undef  HAVE_CTS
#define HAVE_CTS

#undef  NO_DES3
#define NO_DES3

#undef  GCM_TABLE_4BIT
#define GCM_TABLE_4BIT

#undef  HAVE_AESGCM
#define HAVE_AESGCM

#undef  HAVE_TLS_EXTENSIONS
#define HAVE_TLS_EXTENSIONS

#undef  HAVE_SERVER_RENEGOTIATION_INFO
#define HAVE_SERVER_RENEGOTIATION_INFO

#undef  TFM_SMALL_SET
#define TFM_SMALL_SET

#undef  TFM_HUGE_SET
#define TFM_HUGE_SET

#undef  HAVE___UINT128_T
#define HAVE___UINT128_T 1

#undef  HAVE_WC_INTROSPECTION
#define HAVE_WC_INTROSPECTION

#ifdef __cplusplus
}
#endif

#endif /* WOLFSSL_OPTIONS_H */
dgarske commented 2 years ago

Hi @Ziemien ,

The SHA256 is on by default unless --disable-sha256 or NO_SHA256 is used.

The issue you are seeing is a data type mismatch trying to call from C++ to C. Specifically the SHA256 to int.

Can you try using WC_SHA256 and casting to (int)? This value comes from an enum, so it is not an int. See sha256.h -> WC_SHA256 = WC_HASH_TYPE_SHA256,.

Thanks, David Garske, wolfSSL

Ziemien commented 2 years ago

WC_SHA256 works fine (at compile time) but not the SHA256 is suggested in the documentation

dgarske commented 2 years ago

Hi @Ziemien ,

The SHA256 was the old / original name. The SHA256 is a macro that maps to WC_SHA256. For some older FIPS releases I think it still uses SHA256. Documentation has been updated here: https://github.com/wolfSSL/wolfssl/pull/5454

Let me know if you have any additional feedback. Feel free to close this issue if there is nothing further.

Thanks, David Garske, wolfSSL

Ziemien commented 2 years ago

thank you David