1

(1 replies, posted in wolfSSL)

Dear Sir or Madame,

Is there a way to use OCSP stapling in both directions?
The same verification for Server and Client.
Right now the only the Server is sending his status to the Client.

kind regards,

Andreas M

Hi David,

I know that the test case is working, I have tried it too.
I get this issue at the Handshake of wolfssl and openssl.
Can you tell me why.
I am using the newest wolfssl Version and I think I have the same Version of HAL as you.

Thank you,

Andreas

Hi David,

I am using the
@brief STM32H7xx HAL Driver version number V1.9.0
Version 1.9.0

Do you recommend me using another version.
sz: 16
ivSz: 12
authTagSz: 16
authInSz: 13

I get this in the failure case. There is no difference.
They are not changed by:
status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
           STM32_HAL_TIMEOUT);

Thanks,

Andreas

Hi David,

Thank you for your fast response.
I am using the Version 4.5.0 of WolfSSL
I am using HAL_V2.

sz: 16
ivSz: 12
authTagSz: 16
authInSz: 13

This is in decrypt
wc_AesGcmDecrypt_STM32

This works:

byte counter[AES_BLOCK_SIZE];
    byte initialCounter[AES_BLOCK_SIZE];
    byte Tprime[AES_BLOCK_SIZE];
    byte EKY0[AES_BLOCK_SIZE];
    byte *ctr1;

    byte* authInPadded = NULL;
    int authPadSz, wasAlloc = 0;

    /* Use the Software Implementation to verify the auth-Tag */
    ctr1 = counter;
    XMEMSET(initialCounter, 0, AES_BLOCK_SIZE);
    if (ivSz == GCM_NONCE_MID_SZ) {
        XMEMCPY(initialCounter, iv, ivSz);
        initialCounter[AES_BLOCK_SIZE - 1] = 1;
    }

    XMEMCPY(ctr1, initialCounter, AES_BLOCK_SIZE);

    GHASH(aes, authIn, authInSz, in, sz, Tprime, sizeof(Tprime));
    wc_AesEncrypt(aes, ctr1, EKY0);
    xorbuf(Tprime, EKY0, sizeof(Tprime));

    if (ConstantCompare(authTag, Tprime, authTagSz) != 0) {
        ret = AES_GCM_AUTH_E;
    }

This not:

status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
           STM32_HAL_TIMEOUT);


Thank you,

Andreas

Hello,

I am using openssl 1.1.1f on Ubunutu.
I want to connect to an embedded device STM32H753 with wolfSSL.
I am using the HAL Library to use the crypto accelerators of the controller.
When I use the Software Implementation of AES the Handshake is working.
But when I am using the wc_AesGcmDecrypt_STM32 and wc_AesGcmEncrypt_STM32-function the Handshake is not working.

The Authentication Tag is wrong:
status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
            STM32_HAL_TIMEOUT);
           
The result of this function is wrong.

The HAL_CRYP_Encrypt and HAL_CRYP_Decrypt functions are working correct.

When I replace
HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
            STM32_HAL_TIMEOUT);
with
GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
                wc_AesEncrypt(aes, (byte*)ctrInit, (byte*)tag);
                xorbuf(authTag, tag, authTagSz);
               
The Handshake is working.

           
in wc_AesGcmEncrypt_STM32

Can you tell me why the Authentication tag is wrong when I use the HAL-Library?
Let me know when you need more information to solve this issue!

Thank you,

Andreas

Not working:

/* this function supports inline encrypt */
static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz,
                                  const byte* iv, word32 ivSz,
                                  byte* authTag, word32 authTagSz,
                                  const byte* authIn, word32 authInSz)
{
    int ret;
#ifdef WOLFSSL_STM32_CUBEMX
    CRYP_HandleTypeDef hcryp;
#else
    word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
#endif
    word32 keySize;
#ifdef WOLFSSL_STM32_CUBEMX
    int status = HAL_OK;
    word32 blocks = sz / AES_BLOCK_SIZE;
    word32 partialBlock[AES_BLOCK_SIZE/sizeof(word32)];
#else
    int status = SUCCESS;
#endif
    word32 partial = sz % AES_BLOCK_SIZE;
    word32 tag[AES_BLOCK_SIZE/sizeof(word32)];
    //word32 tag1[AES_BLOCK_SIZE/sizeof(word32)];
    word32 ctrInit[AES_BLOCK_SIZE/sizeof(word32)];
    word32 ctr[AES_BLOCK_SIZE/sizeof(word32)];
    word32 authhdr[AES_BLOCK_SIZE/sizeof(word32)];
    byte* authInPadded = NULL;
    int authPadSz, wasAlloc = 0;

    ret = wc_AesGetKeySize(aes, &keySize);
    if (ret != 0)
        return ret;

#ifdef WOLFSSL_STM32_CUBEMX
    ret = wc_Stm32_Aes_Init(aes, &hcryp);
    if (ret != 0)
        return ret;
#endif

    ret = wolfSSL_CryptHwMutexLock();
    if (ret != 0) {
        return ret;
    }

    XMEMSET(ctr, 0, AES_BLOCK_SIZE);
    if (ivSz == GCM_NONCE_MID_SZ) {
        byte* pCtr = (byte*)ctr;
        XMEMCPY(ctr, iv, ivSz);
        pCtr[AES_BLOCK_SIZE - 1] = 1;
    }
    else {
        GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
    }
    XMEMCPY(ctrInit, ctr, sizeof(ctr)); /* save off initial counter for GMAC */

    /* Authentication buffer - must be 4-byte multiple zero padded */
    authPadSz = authInSz % sizeof(word32);
    if (authPadSz != 0) {
        authPadSz = authInSz + sizeof(word32) - authPadSz;
        if (authPadSz <= (int)sizeof(authhdr)) {
            authInPadded = (byte*)authhdr;
        }
        else {
            authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
                DYNAMIC_TYPE_TMP_BUFFER);
            if (authInPadded == NULL) {
                wolfSSL_CryptHwMutexUnLock();
                return MEMORY_E;
            }
            wasAlloc = 1;
        }
        XMEMSET(authInPadded, 0, authPadSz);
        XMEMCPY(authInPadded, authIn, authInSz);
    } else {
        authPadSz = authInSz;
        authInPadded = (byte*)authIn;
    }

    /* Hardware requires counter + 1 */
    IncrementGcmCounter((byte*)ctr);

#ifdef WOLFSSL_STM32_CUBEMX
    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr;
    hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded;

#if defined(STM32_HAL_V2)
    hcryp.Init.Algorithm  = CRYP_AES_GCM;
    hcryp.Init.HeaderSize = authPadSz/sizeof(word32);
    ByteReverseWords(partialBlock, ctr, AES_BLOCK_SIZE);
    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock;
    HAL_CRYP_Init(&hcryp);

    /* GCM payload phase - can handle partial blocks */
    status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in,
        (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT);
    if (status == HAL_OK) {
        /* Compute the authTag */
        status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
            STM32_HAL_TIMEOUT);
    }
#elif defined(STM32_CRYPTO_AES_ONLY)
    /* Set the CRYP parameters */
    hcryp.Init.HeaderSize = authPadSz;
    if (authPadSz == 0)
        hcryp.Init.Header = NULL; /* cannot pass pointer here when authIn == 0 */
    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
    hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
    HAL_CRYP_Init(&hcryp);

    /* GCM init phase */
    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
    if (status == HAL_OK) {
        /* GCM header phase */
        hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE;
        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
    }
    if (status == HAL_OK) {
        /* GCM payload phase - blocks */
        hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE;
        if (blocks) {
            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in,
                (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
        }
    }
    if (status == HAL_OK && (partial != 0 || (sz > 0 && blocks == 0))) {
        /* GCM payload phase - partial remainder */
        XMEMSET(partialBlock, 0, sizeof(partialBlock));
        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
        status = HAL_CRYPEx_AES_Auth(&hcryp, (uint8_t*)partialBlock, partial,
                (uint8_t*)partialBlock, STM32_HAL_TIMEOUT);
        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
    }
    if (status == HAL_OK) {
        /* GCM final phase */
        hcryp.Init.GCMCMACPhase  = CRYP_FINAL_PHASE;
        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, (uint8_t*)tag, STM32_HAL_TIMEOUT);
    }
#else
    hcryp.Init.HeaderSize = authPadSz;
    HAL_CRYP_Init(&hcryp);
    if (blocks) {
        /* GCM payload phase - blocks */
        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in,
            (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
    }
    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
        /* GCM payload phase - partial remainder */
        XMEMSET(partialBlock, 0, sizeof(partialBlock));
        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (uint8_t*)partialBlock, partial,
            (uint8_t*)partialBlock, STM32_HAL_TIMEOUT);
        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
    }
    if (status == HAL_OK) {
        /* Compute the authTag */
        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, (uint8_t*)tag, STM32_HAL_TIMEOUT);
    }
#endif

    //if (status != HAL_OK)
    //    ret = AES_GCM_AUTH_E;
    HAL_CRYP_DeInit(&hcryp);

#else /* Standard Peripheral Library */
    ByteReverseWords(keyCopy, (word32*)aes->key, keySize);
    status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)ctr,
                         (uint8_t*)keyCopy,      keySize * 8,
                         (uint8_t*)in,           sz,
                         (uint8_t*)authInPadded, authInSz,
                         (uint8_t*)out,          (uint8_t*)tag);
    if (status != SUCCESS)
        ret = AES_GCM_AUTH_E;
#endif /* WOLFSSL_STM32_CUBEMX */

    if (ret == 0) {
        /* return authTag */
        if (authTag) {//change to make it work
            /* For STM32 GCM fallback to software if partial AES block or IV != 12 */
            if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) {
                GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
                wc_AesEncrypt(aes, (byte*)ctrInit, (byte*)tag);
                xorbuf(authTag, tag, authTagSz);
            }
            else {
                XMEMCPY(authTag, tag, authTagSz);
            }
        }
    }


    /* Free memory */
    if (wasAlloc) {
        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
    }

    wolfSSL_CryptHwMutexUnLock();

    return ret;
}

working:

/* this function supports inline encrypt */
static int wc_AesGcmEncrypt_STM32(Aes* aes, byte* out, const byte* in, word32 sz,
                                  const byte* iv, word32 ivSz,
                                  byte* authTag, word32 authTagSz,
                                  const byte* authIn, word32 authInSz)
{
    int ret;
#ifdef WOLFSSL_STM32_CUBEMX
    CRYP_HandleTypeDef hcryp;
#else
    word32 keyCopy[AES_256_KEY_SIZE/sizeof(word32)];
#endif
    word32 keySize;
#ifdef WOLFSSL_STM32_CUBEMX
    int status = HAL_OK;
    word32 blocks = sz / AES_BLOCK_SIZE;
    word32 partialBlock[AES_BLOCK_SIZE/sizeof(word32)];
#else
    int status = SUCCESS;
#endif
    word32 partial = sz % AES_BLOCK_SIZE;
    word32 tag[AES_BLOCK_SIZE/sizeof(word32)];
    //word32 tag1[AES_BLOCK_SIZE/sizeof(word32)];
    word32 ctrInit[AES_BLOCK_SIZE/sizeof(word32)];
    word32 ctr[AES_BLOCK_SIZE/sizeof(word32)];
    word32 authhdr[AES_BLOCK_SIZE/sizeof(word32)];
    byte* authInPadded = NULL;
    int authPadSz, wasAlloc = 0;

    ret = wc_AesGetKeySize(aes, &keySize);
    if (ret != 0)
        return ret;

#ifdef WOLFSSL_STM32_CUBEMX
    ret = wc_Stm32_Aes_Init(aes, &hcryp);
    if (ret != 0)
        return ret;
#endif

    ret = wolfSSL_CryptHwMutexLock();
    if (ret != 0) {
        return ret;
    }

    XMEMSET(ctr, 0, AES_BLOCK_SIZE);
    if (ivSz == GCM_NONCE_MID_SZ) {
        byte* pCtr = (byte*)ctr;
        XMEMCPY(ctr, iv, ivSz);
        pCtr[AES_BLOCK_SIZE - 1] = 1;
    }
    else {
        GHASH(aes, NULL, 0, iv, ivSz, (byte*)ctr, AES_BLOCK_SIZE);
    }
    XMEMCPY(ctrInit, ctr, sizeof(ctr)); /* save off initial counter for GMAC */

    /* Authentication buffer - must be 4-byte multiple zero padded */
    authPadSz = authInSz % sizeof(word32);
    if (authPadSz != 0) {
        authPadSz = authInSz + sizeof(word32) - authPadSz;
        if (authPadSz <= (int)sizeof(authhdr)) {
            authInPadded = (byte*)authhdr;
        }
        else {
            authInPadded = (byte*)XMALLOC(authPadSz, aes->heap,
                DYNAMIC_TYPE_TMP_BUFFER);
            if (authInPadded == NULL) {
                wolfSSL_CryptHwMutexUnLock();
                return MEMORY_E;
            }
            wasAlloc = 1;
        }
        XMEMSET(authInPadded, 0, authPadSz);
        XMEMCPY(authInPadded, authIn, authInSz);
    } else {
        authPadSz = authInSz;
        authInPadded = (byte*)authIn;
    }

    /* Hardware requires counter + 1 */
    IncrementGcmCounter((byte*)ctr);

#ifdef WOLFSSL_STM32_CUBEMX
    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)ctr;
    hcryp.Init.Header = (STM_CRYPT_TYPE*)authInPadded;

#if defined(STM32_HAL_V2)
    hcryp.Init.Algorithm  = CRYP_AES_GCM;
    hcryp.Init.HeaderSize = authPadSz/sizeof(word32);
    ByteReverseWords(partialBlock, ctr, AES_BLOCK_SIZE);
    hcryp.Init.pInitVect = (STM_CRYPT_TYPE*)partialBlock;
    HAL_CRYP_Init(&hcryp);

    /* GCM payload phase - can handle partial blocks */
    status = HAL_CRYP_Encrypt(&hcryp, (uint32_t*)in,
        (blocks * AES_BLOCK_SIZE) + partial, (uint32_t*)out, STM32_HAL_TIMEOUT);
    if (status == HAL_OK) {
        /* Compute the authTag */
        //status = HAL_CRYPEx_AESGCM_GenerateAuthTAG(&hcryp, (uint32_t*)tag,
        //    STM32_HAL_TIMEOUT);
    }
#elif defined(STM32_CRYPTO_AES_ONLY)
    /* Set the CRYP parameters */
    hcryp.Init.HeaderSize = authPadSz;
    if (authPadSz == 0)
        hcryp.Init.Header = NULL; /* cannot pass pointer here when authIn == 0 */
    hcryp.Init.ChainingMode  = CRYP_CHAINMODE_AES_GCM_GMAC;
    hcryp.Init.OperatingMode = CRYP_ALGOMODE_ENCRYPT;
    hcryp.Init.GCMCMACPhase  = CRYP_INIT_PHASE;
    HAL_CRYP_Init(&hcryp);

    /* GCM init phase */
    status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
    if (status == HAL_OK) {
        /* GCM header phase */
        hcryp.Init.GCMCMACPhase = CRYP_HEADER_PHASE;
        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, 0, NULL, STM32_HAL_TIMEOUT);
    }
    if (status == HAL_OK) {
        /* GCM payload phase - blocks */
        hcryp.Init.GCMCMACPhase = CRYP_PAYLOAD_PHASE;
        if (blocks) {
            status = HAL_CRYPEx_AES_Auth(&hcryp, (byte*)in,
                (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
        }
    }
    if (status == HAL_OK && (partial != 0 || (sz > 0 && blocks == 0))) {
        /* GCM payload phase - partial remainder */
        XMEMSET(partialBlock, 0, sizeof(partialBlock));
        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
        status = HAL_CRYPEx_AES_Auth(&hcryp, (uint8_t*)partialBlock, partial,
                (uint8_t*)partialBlock, STM32_HAL_TIMEOUT);
        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
    }
    if (status == HAL_OK) {
        /* GCM final phase */
        hcryp.Init.GCMCMACPhase  = CRYP_FINAL_PHASE;
        status = HAL_CRYPEx_AES_Auth(&hcryp, NULL, sz, (uint8_t*)tag, STM32_HAL_TIMEOUT);
    }
#else
    hcryp.Init.HeaderSize = authPadSz;
    HAL_CRYP_Init(&hcryp);
    if (blocks) {
        /* GCM payload phase - blocks */
        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (byte*)in,
            (blocks * AES_BLOCK_SIZE), out, STM32_HAL_TIMEOUT);
    }
    if (status == HAL_OK && (partial != 0 || blocks == 0)) {
        /* GCM payload phase - partial remainder */
        XMEMSET(partialBlock, 0, sizeof(partialBlock));
        XMEMCPY(partialBlock, in + (blocks * AES_BLOCK_SIZE), partial);
        status = HAL_CRYPEx_AESGCM_Encrypt(&hcryp, (uint8_t*)partialBlock, partial,
            (uint8_t*)partialBlock, STM32_HAL_TIMEOUT);
        XMEMCPY(out + (blocks * AES_BLOCK_SIZE), partialBlock, partial);
    }
    if (status == HAL_OK) {
        /* Compute the authTag */
        status = HAL_CRYPEx_AESGCM_Finish(&hcryp, sz, (uint8_t*)tag, STM32_HAL_TIMEOUT);
    }
#endif

    //if (status != HAL_OK)
    //    ret = AES_GCM_AUTH_E;
    HAL_CRYP_DeInit(&hcryp);

#else /* Standard Peripheral Library */
    ByteReverseWords(keyCopy, (word32*)aes->key, keySize);
    status = CRYP_AES_GCM(MODE_ENCRYPT, (uint8_t*)ctr,
                         (uint8_t*)keyCopy,      keySize * 8,
                         (uint8_t*)in,           sz,
                         (uint8_t*)authInPadded, authInSz,
                         (uint8_t*)out,          (uint8_t*)tag);
    if (status != SUCCESS)
        ret = AES_GCM_AUTH_E;
#endif /* WOLFSSL_STM32_CUBEMX */

    if (ret == 0) {
        /* return authTag */
        if (authTag) {//change to make it work
            /* For STM32 GCM fallback to software if partial AES block or IV != 12 */
            //if (sz == 0 || partial != 0 || ivSz != GCM_NONCE_MID_SZ) {
                GHASH(aes, authIn, authInSz, out, sz, authTag, authTagSz);
                wc_AesEncrypt(aes, (byte*)ctrInit, (byte*)tag);
                xorbuf(authTag, tag, authTagSz);
            //}
            //else {
                XMEMCPY(authTag, tag, authTagSz);
            //}
        }
    }


    /* Free memory */
    if (wasAlloc) {
        XFREE(authInPadded, aes->heap, DYNAMIC_TYPE_TMP_BUFFER);
    }

    wolfSSL_CryptHwMutexUnLock();

    return ret;
}

Hi,

I am trying to integrate WolfSSL in my embedded project.

I am configuring WolfSSL with these flags:

./configure --host=arm-none-eabi CC=arm-none-eabi-gcc LD=arm-none-eabi-ld AR=arm-none-eabi-ar RANLIB=arm-none-eabi-ranlib CFLAGS="-DNO_WOLFSSL_DIR -DWOLFSSL_USER_IO -DNO_WRITEV -mtune=cortex-m7 -mthumb -march=armv7e-m+fp.dp -specs=rdimon.specs -mfloat-abi=hard -DSTM32 -DSTM32H7 -DSTM32H743ZITx -DCPP_FREERTOS_NO_EXCEPTIONS -D__VFP_FP__ -D__FPU_PRESENT=1 -mfpu=fpv5-d16 -Wall -Wextra -fno-common -ffunction-sections -fdata-sections -fmessage-length=0 -ffreestanding -fno-builtin" CXXFLAGS="-DNO_WOLFSSL_DIR -DWOLFSSL_USER_IO -DNO_WRITEV -mtune=cortex-m7 -mthumb -march=armv7e-m+fp.dp -specs=rdimon.specs -mfloat-abi=hard -DSTM32 -DSTM32H7 -DSTM32H743ZITx -DCPP_FREERTOS_NO_EXCEPTIONS -D__VFP_FP__ -D__FPU_PRESENT=1 -mfpu=fpv5-d16 -Wall -Wextra -fno-common -ffunction-sections -fdata-sections -fmessage-length=0 -ffreestanding -fno-builtin" CPPFLAGS="-I./" CCAS=arm-none-eabi-as CCASFLAGS="-mthumb -march=armv7e-m+fp.dp -mtune=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16" LDFLAGS="-lm"

when I am compiling it in my project I get this error:

[build] /home/mua37025/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/bin/ld: /home/mua37025/gcc-arm-none-eabi-9-2020-q2-update-x86_64-linux/gcc-arm-none-eabi-9-2020-q2-update/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+dp/hard/libc.a(lib_a-openr.o): in function `_open_r':
[build] openr.c:(.text._open_r+0x14): undefined reference to `_open'

That is my current sourcecode:

    /*create new WolfSSL context*/
    WOLFSSL_CTX* ctx;

    /*new WolfSSL-session*/
    WOLFSSL* ssl;

    /*wolfSSL initialisieren*/
    wolfSSL_Init();

    /*create the context with the highest possible version*/
    ctx = wolfSSL_CTX_new(wolfSSLv23_client_method());

    /*create new WolfSSL-Session*/
    ssl = wolfSSL_new(ctx);

If I uncomment ssl = wolfSSL_new(ctx);, it is working,

Can you tell me how I have to buildt wolfSSL, so that I do not get this error

Thank you for your help,