Topic: Problems getting dtls with static memory to work
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)