Hi Anthony,

I tried out setting the

WOLFSSL_DYN_CERT

and that indeed got me further along.
Unfortunately, I am experiencing the same issue

err = -125, Reason "out of memory error"

.

Simply changing to ECC curves did not change the outcome. It also produces out of memory error. As a reference, I used the 'ca-ecc-cert.pem' from the woflssl-examples/certs directory.

Looking forward to your answer, and for us, good night smile
Will

anthony wrote:

Hi Will,

A simpler solution might be to use ECC certs.  Have you investigated that possibility?

Warm regards, Anthony

I haven't yet, no. The reason for the certificate was simply that it was the one used in the example I started out with, if you mean what ECC certificates will be simpler I will probably switch over in the future. Thank you

anthony wrote:

Note that the following passage appears here https://www.wolfssl.com/documentation/m … ter02.html :

WOLFSSL_DYN_CERT

Allow allocation of subjectCN and publicKey fields when parsing certificates even with WOLFSSL_NO_MALLOC set. If using the WOLFSSL_NO_MALLOC option with RSA certificates the public key needs to be retained for CA's for validate certificates on the peer's certificate. This appears as a ConfirmSignature error -173 BAD_FUNC_ARG, since the ca->publicKey is NULL.

Oh, well this is my exact situation. Thank you so much for the help and quick reply! I will get back to you as soon as I have implemented your advice smile

anthony wrote:

During the parsing of the certificate, the public key is not being stored:
So

cert->pubKeyStored

is not getting set to 1.  I was able to get past this by adding

-DWOLFSSL_DYN_CERT

to

CFLAGS

. That said, I later got an out of memory error:
I'll need to ask my colleagues how to increase the memory pool size.
Please stay tuned.

Oh, just noticed your second reply!
Thanks, that is already progress.
Does changing from wolfSSL_CTX_load_verify_locations to wolfSLL_CTX_load_verify_buffer effect the problems, because the switch to the buffer form is probably already part of our plans.
Secondly, doesn't increasing the available memory in the byte memory buffer help, or is this an issue about the buffer usage, not size?

Warm regards,
Will

Hello Anthony,

Thank you for the reply! Sure I can answer your questions.

anthony wrote:

- where are you geographically located?

Bremen, Germany.

anthony wrote:

- is your project personal, academic or professional?
- is there an institution associated with this work?

This is an academic project called Atacama, and it is a master project from the University of Bremen.

anthony wrote:

- what are your goals?

We are trying to port the expressvpn wolfssl-rs wrapper to use rust no-std, and no malloc in C. The primary goal is to make wolfssl dtls usable in Rust based IoT systems. That is also the reason why the stack trace was from rust, but I replicated it in C, so that the language doesn't impact our discussion.

The Atacama project as a whole has 10 master students working towards low power IP communication (CoAP/6Lo/802.15.4), BLE, and genreally improving the state of IoT connectivity in the Rust ecosystem.

If you have any further questions I'm glad to answer them!
In the meantime thank you for looking into it.

Have a nice day,
Will

Hello people,

I have a probelm when trying to use DTLS via wolfSSL without allocating dynamic heap memory.
The server-dtls.c example from the wolfssl-examples repo is compiled with dynamic memory and works as expected.
I tried porting the client-dtls.c example to use static memory instead.
Now, when wolfSSL_connect is called, a BAD_FUNC_ARG is returned deep in the call stack.
Specifically in ConfirmSignature, because the key is null, and the keySz is 0.
I'm at my wits end, and hope that some of you nice people can help me out.

Thank you for your attention,
Best regards Will (whjochim)

Below this point, all information that might be useful in debugging are attached. Including source code, stack trace, and compile commands.

The configure options I used to compile the static libwolfssl library.

./configure --disable-benchmark --disable-dh --disable-examples --disable-oldtls --disable-sha3 --disable-shared --disable-sys-ca-certs --enable-aes-bitsliced --enable-curve25519 --enable-dtls --enable-dtls13 --enable-dtls-frag-ch --enable-dtls-mtu --enable-secure-renegotiation --enable-singlethreaded --enable-sni --enable-sp --enable-sp-asm --enable-static --enable-supportedcurves --enable-tls13 --enable-staticmemory CFLAGS="-g -fPIC -DWOLFSSL_NO_SPHINCS -DWOLFSSL_NO_MALLOC -DWOLFSSL_DTLS_ALLOW_FUTURE -DWOLFSSL_MIN_RSA_BITS=2048 -DWOLFSSL_MIN_ECC_BITS=256 -DUSE_CERT_BUFFERS_4096 -DUSE_CERT_BUFFERS_256 -DDEBUG_WOLFSSL"

The command I used to compile the client

clang -DWOLFSSL_STATIC_MEMORY -DWOLFSSL_DTLS -o client_nomalloc client-dtls-nomalloc.c libwolfssl_nomalloc.a -lm

The source code of the client

*
 * client-dtls.c
 *
 * Copyright (C) 2006-2020 wolfSSL Inc.
 *
 * This file is part of wolfSSL. (formerly known as CyaSSL)
 *
 * wolfSSL is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * wolfSSL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
 *
 *=============================================================================
 *
 * Bare-bones example of a DTLS client for instructional/learning purposes.
 */

#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <wolfssl/options.h>
#include <wolfssl/ssl.h>

#define MAXLINE 4096
#define SERV_PORT 11111

int main(int argc, char **argv) {
  /* standard variables used in a dtls client*/
  int n = 0;
  int sockfd = 0;
  int err1;
  int readErr;
  struct sockaddr_in servAddr;
  WOLFSSL *ssl = 0;
  WOLFSSL_CTX *ctx = 0;
  char cert_array[] = "../certs/ca-cert.pem";
  char *certs = cert_array;
  char sendLine[MAXLINE];
  char recvLine[MAXLINE - 1];
  WOLFSSL_HEAP_HINT *heap = NULL;

  byte memory[320000];

  /* Program argument checking */
  if (argc != 2) {
    printf("usage: %s <IP address>\n", argv[0]);
    return 1;
  }

  wolfSSL_Debugging_ON();

  if (wc_LoadStaticMemory(&heap, memory, sizeof(memory), WOLFMEM_GENERAL, 1) !=
      0) {
    fprintf(stderr, "unable to load static memory");
  }

  /* Initialize wolfSSL before assigning ctx */
  wolfSSL_Init();

  /* wolfSSL_Debugging_ON(); */

  if ((ctx = wolfSSL_CTX_new_ex(wolfDTLSv1_2_client_method_ex(heap), heap)) ==
      NULL) {
    fprintf(stderr, "wolfSSL_CTX_new error.\n");
    return 1;
  }

  /* Load certificates into ctx variable */
  if (wolfSSL_CTX_load_verify_locations(ctx, certs, 0) != SSL_SUCCESS) {
    fprintf(stderr, "Error loading %s, please check the file.\n", certs);
    return 1;
  }

  /* Assign ssl variable */
  ssl = wolfSSL_new(ctx);
  if (ssl == NULL) {
    printf("unable to get ssl object");
    return 1;
  }

  /* servAddr setup */
  memset(&servAddr, 0, sizeof(servAddr));
  servAddr.sin_family = AF_INET;
  servAddr.sin_port = htons(SERV_PORT);
  if (inet_pton(AF_INET, argv[1], &servAddr.sin_addr) < 1) {
    printf("Error and/or invalid IP address");
    return 1;
  }

  wolfSSL_dtls_set_peer(ssl, &servAddr, sizeof(servAddr));

  if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
    printf("cannot create a socket.");
    return 1;
  }

  /* Set the file descriptor for ssl and connect with ssl variable */
  wolfSSL_set_fd(ssl, sockfd);
  if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
    err1 = wolfSSL_get_error(ssl, 0);
    printf("err = %d, %s\n", err1, wolfSSL_ERR_reason_error_string(err1));
    printf("SSL_connect failed");
    return 1;
  }

  /*****************************************************************************/
  /*                  Code for sending datagram to server */
  /* Loop until the user is finished */
  if (fgets(sendLine, MAXLINE, stdin) != NULL) {

    /* Send sendLine to the server */
    if ((wolfSSL_write(ssl, sendLine, strlen(sendLine))) != strlen(sendLine)) {
      printf("SSL_write failed");
    }

    /* n is the # of bytes received */
    n = wolfSSL_read(ssl, recvLine, sizeof(recvLine) - 1);

    if (n < 0) {
      readErr = wolfSSL_get_error(ssl, 0);
      if (readErr != SSL_ERROR_WANT_READ) {
        printf("wolfSSL_read failed");
      }
    }

    /* Add a terminating character to the generic server message */
    recvLine[n] = '\0';
    fputs(recvLine, stdout);
  }
  /*                End code for sending datagram to server */
  /*****************************************************************************/

  /* Housekeeping */
  wolfSSL_shutdown(ssl);
  wolfSSL_free(ssl);
  close(sockfd);
  wolfSSL_CTX_free(ctx);
  wolfSSL_Cleanup();

  return 0;
}

the debug logs

wolfSSL Entering wc_LoadStaticMemory
wolfSSL Entering wc_LoadStaticMemory_ex
wolfSSL Entering wc_partition_static_memory
wolfSSL Leaving wc_LoadStaticMemory, return 0
wolfSSL Entering wolfSSL_Init
wolfSSL Entering wolfCrypt_Init
wolfSSL Entering DTLSv1_2_client_method_ex
wolfSSL Entering wolfSSL_CTX_new_ex
wolfSSL Entering wolfSSL_CertManagerNew
heap param = 0x7ffeef1b42f0
DYNAMIC_TYPE_CERT_MANAGER Allocating = 184 bytes
wolfSSL Leaving wolfSSL_CTX_new_ex, return 0
wolfSSL_CTX_load_verify_locations_ex
Processing CA PEM file
wolfSSL Entering ProcessBuffer
wolfSSL Entering PemToDer
Adding a CA
Getting Cert Name
Getting Cert Name
wolfSSL Entering GetAlgoId
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering DecodeAltNames
        Unsupported name type, skipping
wolfSSL Entering DecodeExtKeyUsage
        Parsed new CA
        Freeing Parsed CA
        Freeing der CA
                OK Freeing der CA
wolfSSL Leaving AddCA, return 0
wolfSSL Leaving ProcessBuffer, return 1
   Processed a CA
Processed at least one valid CA. Other stuff OK
wolfSSL Entering wolfSSL_new
wolfSSL Entering ReinitSSL
RNG_HEALTH_TEST_CHECK_SIZE = 128
sizeof(seedB_data)         = 128
opened /dev/urandom.
rnd read...
wolfSSL Entering SetSSL_CTX
wolfSSL Entering wolfSSL_NewSession
InitSSL done. return 0 (success)
wolfSSL_new InitSSL success
wolfSSL Leaving wolfSSL_new InitSSL =, return 0
wolfSSL Entering wolfSSL_set_fd
wolfSSL Entering wolfSSL_set_read_fd
wolfSSL Leaving wolfSSL_set_read_fd, return 1
wolfSSL Entering wolfSSL_set_write_fd
wolfSSL Leaving wolfSSL_set_write_fd, return 1
TLS 1.2 or lower
wolfSSL Entering wolfSSL_connect
wolfSSL Entering ReinitSSL
wolfSSL Entering RetrySendAlert
wolfSSL Entering SendClientHello
Adding signature algorithms extension
growing output buffer
Signature Algorithms extension to write
Point Formats extension to write
Supported Groups extension to write
Encrypt-Then-Mac extension to write
EMS extension to write
wolfSSL Entering DtlsMsgPoolSave
wolfSSL Entering DtlsMsgNew
wolfSSL Leaving DtlsMsgPoolSave(), return 0
wolfSSL Entering EmbedSendTo
Shrinking output buffer
wolfSSL Leaving SendClientHello, return 0
connect state: CLIENT_HELLO_SENT
Server state up to needed state.
Progressing server state...
ProcessReply...
wolfSSL Entering RetrySendAlert
growing input buffer
wolfSSL Leaving wolfSSL_dtls_get_current_timeout, return 1
wolfSSL Entering EmbedReceiveFrom
wolfSSL Entering wolfSSL_dtls_get_using_nonblock
received record layer msg
got HANDSHAKE
wolfSSL Entering DoDtlsHandShakeMsg
wolfSSL Entering EarlySanityCheckMsgReceived
wolfSSL Leaving EarlySanityCheckMsgReceived, return 0
Branch is in order and a complete message
wolfSSL Entering DoHandShakeMsgType
processing hello verify request
wolfSSL Entering DtlsMsgPoolReset
wolfSSL Entering DtlsMsgListDelete
wolfSSL Entering DtlsMsgDelete
wolfSSL Entering Dtls13RtxFlushBuffered
wolfSSL Leaving DoHandShakeMsgType(), return 0
wolfSSL Entering DtlsTxMsgListClean
wolfSSL Leaving DoDtlsHandShakeMsg(), return 0
Shrinking input buffer
ProcessReply done.
connect state: HELLO_AGAIN
wolfSSL Entering SendClientHello
Adding signature algorithms extension
growing output buffer
Signature Algorithms extension to write
Point Formats extension to write
Supported Groups extension to write
Encrypt-Then-Mac extension to write
EMS extension to write
wolfSSL Entering DtlsMsgPoolSave
wolfSSL Entering DtlsMsgNew
wolfSSL Leaving DtlsMsgPoolSave(), return 0
wolfSSL Entering EmbedSendTo
Shrinking output buffer
wolfSSL Leaving SendClientHello, return 0
connect state: HELLO_AGAIN_REPLY
wolfSSL Entering RetrySendAlert
growing input buffer
wolfSSL Leaving wolfSSL_dtls_get_current_timeout, return 1
wolfSSL Entering EmbedReceiveFrom
wolfSSL Entering wolfSSL_dtls_get_using_nonblock
received record layer msg
got HANDSHAKE
wolfSSL Entering DoDtlsHandShakeMsg
wolfSSL Entering EarlySanityCheckMsgReceived
wolfSSL Leaving EarlySanityCheckMsgReceived, return 0
Branch is in order and a complete message
wolfSSL Entering DoHandShakeMsgType
processing server hello
wolfSSL Entering DoServerHello
Point Formats extension received
Extended Master Secret extension received
wolfSSL Entering wolfSSL_get_options
wolfSSL Entering VerifyClientSuite
wolfSSL Leaving DoServerHello, return 0
wolfSSL Leaving DoHandShakeMsgType(), return 0
wolfSSL Entering DtlsTxMsgListClean
wolfSSL Entering VerifyForTxDtlsMsgDelete
wolfSSL Leaving DoDtlsHandShakeMsg(), return 0
Shrinking input buffer
wolfSSL Entering RetrySendAlert
growing input buffer
wolfSSL Leaving wolfSSL_dtls_get_current_timeout, return 1
wolfSSL Entering EmbedReceiveFrom
wolfSSL Entering wolfSSL_dtls_get_using_nonblock
received record layer msg
got HANDSHAKE
wolfSSL Entering DoDtlsHandShakeMsg
wolfSSL Entering EarlySanityCheckMsgReceived
wolfSSL Leaving EarlySanityCheckMsgReceived, return 0
Branch is in order and a complete message
wolfSSL Entering DoHandShakeMsgType
processing certificate
wolfSSL Entering DoCertificate
wolfSSL Entering ProcessPeerCerts
Loading peer's cert chain
        Put another cert into chain
Verifying Peer's cert
Getting Cert Name
Getting Cert Name
wolfSSL Entering GetAlgoId
wolfSSL Entering DecodeCertExtensions
wolfSSL Entering DecodeSubjKeyId
wolfSSL Entering DecodeAuthKeyId
wolfSSL Entering DecodeBasicCaConstraint
wolfSSL Entering DecodeAltNames
        Unsupported name type, skipping
wolfSSL Entering DecodeExtKeyUsage
CA found
Confirm signature failed
Got Peer cert ASN_PARSE_E, BUFFER_E, MEMORY_E, BAD_FUNC_ARG
wolfSSL Leaving ProcessPeerCerts, return -173
wolfSSL Leaving DoCertificate, return -173
wolfSSL Leaving DoHandShakeMsgType(), return -173
wolfSSL Leaving DoDtlsHandShakeMsg(), return -173
wolfSSL error occurred, error = -173
wolfSSL error occurred, error = -173
wolfSSL Entering wolfSSL_get_error
wolfSSL Leaving wolfSSL_get_error, return -173
err = -173, Bad function argument
SSL_connect failed

The Stack trace of the client. Yes, this is technically a different client written in Rust, but it uses the exact same functions from wolfSSL, and produces the same behavior as the C code above.

ConfirmSignature (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/wolfcrypt/src/asn.c:16129)
ParseCertRelative (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/wolfcrypt/src/asn.c:23174)
ProcessPeerCertParse (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:13842)
ProcessPeerCerts (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:14690)
DoCertificate (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:15712)
DoHandShakeMsgType (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:16787)
DoDtlsHandShakeMsg (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:17887)
ProcessReplyEx (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:21284)
ProcessReply (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/internal.c:20591)
wolfSSL_connect (/home/w/Repositories/atacama/wolfssl-rs/target/debug/build/wolfssl-sys-f947a91819bbea53/out/wolfssl-src/src/ssl.c:12624)
wolfssl_sys_client_test::main (/home/w/Repositories/atacama/wolfssl-rs/wolfssl-sys-client-test/src/main.rs:89)
core::ops::function::FnOnce::call_once (@core::ops::function::FnOnce::call_once:6)
std::sys_common::backtrace::__rust_begin_short_backtrace (@std::sys_common::backtrace::__rust_begin_short_backtrace:6)
std::rt::lang_start::{{closure}} (@std::rt::lang_start::{{closure}}:7)
core::ops::function::impls::<impl core::ops::function::FnOnce<A> for &F>::call_once (@std::rt::lang_start_internal:235)
std::panicking::try::do_call (@std::rt::lang_start_internal:233)
std::panicking::try (@std::rt::lang_start_internal:233)
std::panic::catch_unwind (@std::rt::lang_start_internal:233)
std::rt::lang_start_internal::{{closure}} (@std::rt::lang_start_internal:233)
std::panicking::try::do_call (@std::rt::lang_start_internal:233)
std::panicking::try (@std::rt::lang_start_internal:233)
std::panic::catch_unwind (@std::rt::lang_start_internal:233)
std::rt::lang_start_internal (@std::rt::lang_start_internal:233)
std::rt::lang_start (@std::rt::lang_start:16)
main (@main:11)
___lldb_unnamed_symbol3264 (@___lldb_unnamed_symbol3264:29)
__libc_start_main (@__libc_start_main:44)
_start (@_start:15)