wolfssl icon indicating copy to clipboard operation
wolfssl copied to clipboard

[Bug]: wc_HmacSetKey corrupts memory

Open Ziemien opened this issue 3 years ago • 6 comments

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 avatar Aug 10 '22 03:08 Ziemien

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

Ziemien avatar Aug 10 '22 06:08 Ziemien

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

dgarske avatar Aug 10 '22 06:08 dgarske

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 */

Ziemien avatar Aug 10 '22 06:08 Ziemien

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

dgarske avatar Aug 10 '22 14:08 dgarske

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

Ziemien avatar Aug 10 '22 16:08 Ziemien

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

dgarske avatar Aug 10 '22 16:08 dgarske

thank you David

Ziemien avatar Aug 12 '22 04:08 Ziemien