# OTA update, signature verification failing

**URL:** <https://forums.freertos.org/t/ota-update-signature-verification-failing/15821>\
**Category:** AWS\
**Created:** [September 14, 2022, 9:33am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821 "2022-09-14T09:33:31Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![guysa](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@guysa](https://forums.freertos.org/u/guysa)\
**Post date:** [September 14, 2022, 9:33am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/1 "2022-09-14T09:33:31Z")

</div>

Hey everyone,  
I’m using STM32F767, following the OTA demo and implemented the required ota\_pal.h functions.  
The process of downloading the file is working good, but I have a problem with the signature verification. (sha256 ECDSA)  
When using a quite small ‘test file’ for the update (~40KB), the verification works as expected.  
But when using the new image file (~650KB), the verification fails.

Specifically in the function prvVerifySignature in iot\_crypto.c, mbedtls\_pk\_verify fail with the error MBEDTLS\_ERR\_ECP\_VERIFY\_FAILED -0x4E00

```auto
static BaseType_t prvVerifySignature(char *pcSignerCertificate,
                                     size_t xSignerCertificateLength,
                                     BaseType_t xHashAlgorithm,
                                     uint8_t *pucHash,
                                     size_t xHashLength,
                                     uint8_t *pucSignature,
                                     size_t xSignatureLength)
{
    BaseType_t xResult = pdTRUE;
    mbedtls_x509_crt xCertCtx;
    mbedtls_md_type_t xMbedHashAlg = MBEDTLS_MD_SHA256;

    CRYPTO_PRINT(("prvVerifySignature"));

    memset(&xCertCtx, 0, sizeof(mbedtls_x509_crt));

    /*
     * Map the hash algorithm
     */
    if (cryptoHASH_ALGORITHM_SHA1 == xHashAlgorithm)
    {
        xMbedHashAlg = MBEDTLS_MD_SHA1;
    }

    /*
     * Decode and create a certificate context
     */
    CRYPTO_PRINT(("calling mbedtls_x509_crt_init"));
    mbedtls_x509_crt_init(&xCertCtx);
    CRYPTO_PRINT(("calling mbedtls_x509_crt_parse"));

    if (0 != mbedtls_x509_crt_parse(
                 &xCertCtx, (const unsigned char *)pcSignerCertificate, xSignerCertificateLength))
    {
        CRYPTO_PRINT(("mbedtls_x509_crt_parse FAILED"));
        xResult = pdFALSE;
    }

    /*
     * Verify the signature using the public key from the decoded certificate
     */
    if (pdTRUE == xResult)
    {
        CRYPTO_PRINT(("calling mbedtls_pk_verify"));

        if (0 != mbedtls_pk_verify(
                     &xCertCtx.pk,
                     xMbedHashAlg,
                     pucHash,
                     xHashLength,
                     pucSignature,
                     xSignatureLength))
        {
            CRYPTO_PRINT(("mbedtls_pk_verify FAILED"));
            xResult = pdFALSE;
        }
    }

    /*
     * Clean-up
     */
    CRYPTO_PRINT(("calling mbedtls_x509_crt_free"));

    mbedtls_x509_crt_free(&xCertCtx);

    return xResult;
}

```

The call to prvVerifySignature comes from CRYPTO\_SignatureVerificationFinal:

```auto
BaseType_t CRYPTO_SignatureVerificationFinal(void *pvContext,
                                             char *pcSignerCertificate,
                                             size_t xSignerCertificateLength,
                                             uint8_t *pucSignature,
                                             size_t xSignatureLength)
{
    CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal."));
    BaseType_t xResult = pdFALSE;

    if (pvContext != NULL)
    {
        SignatureVerificationStatePtr_t pxCtx = (SignatureVerificationStatePtr_t)pvContext; /*lint !e9087 Allow casting void* to other types. */
        uint8_t ucSHA1or256[cryptoSHA256_DIGEST_BYTES]; /* Reserve enough space for the larger of SHA1 or SHA256 results. */
        uint8_t *pucHash = NULL;
        size_t xHashLength = 0;

        if ((pcSignerCertificate != NULL) &&
            (pucSignature != NULL) &&
            (xSignerCertificateLength > 0UL) &&
            (xSignatureLength > 0UL))
        {
            /*
             * Finish the hash
             */
            if (cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm)
            {
                CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal: SHA1."));
                (void)mbedtls_sha1_finish_ret(&pxCtx->xSHA1Context, ucSHA1or256);
                pucHash = ucSHA1or256;
                xHashLength = cryptoSHA1_DIGEST_BYTES;
            }
            else
            {
                CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal: SHA256."));
                if (0 != mbedtls_sha256_finish_ret(&pxCtx->xSHA256Context, ucSHA1or256))
                {
                    CRYPTO_PRINT(("mbedtls_sha256_finish_ret FAILED"));
                }
                pucHash = ucSHA1or256;
                xHashLength = cryptoSHA256_DIGEST_BYTES;
            }

            /*
             * Verify the signature
             */
            CRYPTO_PRINT(("Verifying signature..."));
            xResult = prvVerifySignature(pcSignerCertificate,
                                         xSignerCertificateLength,
                                         pxCtx->xHashAlgorithm,
                                         pucHash,
                                         xHashLength,
                                         pucSignature,
                                         xSignatureLength);
        }
        else
        {
            /* Allow function to be called with only the context pointer for cleanup after a failure. */
            CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal: Invalid parameters."));
        }

        /*
         * Clean-up
         */
        CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal: Cleaning up."));
        vPortFree(pxCtx);
    }
    CRYPTO_PRINT(("CRYPTO_SignatureVerificationFinal finished."));

    return xResult;
}

```

Any ideas to understand what can cause this will help.  
Thank you.

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [September 14, 2022, 11:50am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/2 "2022-09-14T11:50:40Z")

</div>

> [@guysa](#):
>
> When using a quite small ‘test file’ for the update (~40KB), the verification works as expected.  
> But when using the new image file (~650KB), the verification fails.

Is it possible that you are running out of memory somewhere in the TLS stack? Can you enable mbedTLS debug logs?

---

<div class="post-metadata">

**Author:** ![guysa](https://avatars.discourse-cdn.com/v4/letter/g/5f8ce5/32.png) [@guysa](https://forums.freertos.org/u/guysa)\
**Post date:** [September 14, 2022, 12:58pm UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/3 "2022-09-14T12:58:26Z")

</div>

How can I enable the debug logs?  
MBEDTLS\_DEBUG\_C already defined and a call to mbedtls\_debug\_set\_threshold(4) was added in tlsSetup function (that called from TLS\_FreeRTOS\_Connect).  
But still I can’t see nothing that relates to mbedTLS in the terminal log.

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [September 14, 2022, 4:24pm UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/4 "2022-09-14T16:24:09Z")

</div>

Does this help - [Debugging TLS sessions — Mbed TLS documentation](https://mbed-tls.readthedocs.io/en/latest/kb/development/debugging-tls/)

---

<div class="post-metadata">

**Author:** ![cgbdevelco](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/cgbdevelco/32/3675_2.png) [@cgbdevelco](https://forums.freertos.org/u/cgbdevelco)\
**Post date:** [June 28, 2023, 12:10pm UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/6 "2023-06-28T12:10:35Z")

</div>

Running into same issue… What fixed the problem?

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [June 28, 2023, 2:18pm UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/7 "2023-06-28T14:18:04Z")

</div>

Do you have mbedTLS debug logs?

---

<div class="post-metadata">

**Author:** ![cgbdevelco](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/cgbdevelco/32/3675_2.png) [@cgbdevelco](https://forums.freertos.org/u/cgbdevelco)\
**Post date:** [June 29, 2023, 5:45am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/8 "2023-06-29T05:45:33Z")

</div>

Yes, It doesn’t output any errors when doing the verification…

---

<div class="post-metadata">

**Author:** ![cgbdevelco](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/cgbdevelco/32/3675_2.png) [@cgbdevelco](https://forums.freertos.org/u/cgbdevelco)\
**Post date:** [June 29, 2023, 6:22am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/9 "2023-06-29T06:22:22Z")

</div>

My 580 KB image fails verification, If I trim the bin file to e.g. 546KB, verification works.

MBEDTLS\_ERR\_ECP\_VERIFY\_FAILED happens in step 8 inside the ecdsa\_verify\_restartable function. Step 8 calls mbedtls\_mpi\_cmp\_mpi where it return -1 when the following is validated in the bottom of the function

`if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s );`

---

<div class="post-metadata">

**Author:** ![cgbdevelco](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/cgbdevelco/32/3675_2.png) [@cgbdevelco](https://forums.freertos.org/u/cgbdevelco)\
**Post date:** [June 29, 2023, 7:10am UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/10 "2023-06-29T07:10:13Z")

</div>

My debug output, which I’m not even sure is output based on the verification process but rather on background communication with cloud

```auto
[INFO] [OtaConfig] [xValidateImageSignature:265] Started sig-sha256-ecdsa signature verification, file: /

0x20000978: in_left: zu, nb_want: zu

0x20000978: => write

0x20000978: => write record

0x20000978: => encrypt buf

0x20000978: dumping 'before encrypt: output payload' (2 bytes)

0x20000978: 0000: c0 00 ..

0x20000978: dumping 'CID' (0 bytes)

0x20000978: dumping 'IV used (internal)' (12 bytes)

0x20000978: 0000: 1b 68 2b 2e 00 00 00 00 00 00 02 7f .h+.........

0x20000978: dumping 'IV used (transmitted)' (8 bytes)

0x20000978: 0000: 00 00 00 00 00 00 02 7f ........

0x20000978: dumping 'additional data used for AEAD' (13 bytes)

0x20000978: 0000: 00 00 00 00 00 00 02 7f 17 03 03 00 02 .............

0x20000978: before encrypt: msglen = zu, including 0 bytes of padding

0x20000978: dumping 'after encrypt: tag' (16 bytes)

0x20000978: 0000: 7c 20 f4 3d e0 b7 27 69 d5 69 b5 f4 68 90 9d 29 | .=..'i.i..h..)

0x20000978: <= encrypt buf

0x20000978: output record: msgtype = 23, version = [3:3], msglen = zu

0x20000978: dumping 'output record sent to network' (31 bytes)

0x20000978: 0000: 17 03 03 00 1a 00 00 00 00 00 00 02 7f e9 61 7c ..............a|

0x20000978: 0010: 20 f4 3d e0 b7 27 69 d5 69 b5 f4 68 90 9d 29 .=..'i.i..h..)

0x20000978: => flush output

0x20000978: message length: zu, out_left: zu

0x20000978: ssl->f_send() returned 31 (-0xffffffe1)

0x20000978: <= flush output

0x20000978: <= write record

0x20000978: <= write

[INFO] [OtaTask] [OtaThread:337] Received: 290 Queued: 290 Processed: 289 Dropped: 0
0x20000978: => read

0x20000978: => read record

0x20000978: => fetch input

0x20000978: in_left: zu, nb_want: zu

0x20000978: in_left: zu, nb_want: zu

0x20000978: ssl->f_recv(_timeout)() returned 5 (-0xfffffffb)

0x20000978: <= fetch input

0x20000978: dumping 'input record header' (5 bytes)

0x20000978: 0000: 17 03 03 00 1a .....

0x20000978: input record: msgtype = 23, version = [0x303], msglen = zu

0x20000978: => fetch input

0x20000978: in_left: zu, nb_want: zu

0x20000978: in_left: zu, nb_want: zu

0x20000978: ssl->f_recv(_timeout)() returned 26 (-0xffffffe6)

0x20000978: <= fetch input

0x20000978: dumping 'input record from network' (31 bytes)

0x20000978: 0000: 17 03 03 00 1a 00 00 00 00 00 00 01 b1 c1 bf 7c ...............|

0x20000978: 0010: 24 04 43 56 15 80 10 36 4a d7 85 33 51 0b 57 $.CV...6J..3Q.W

0x20000978: => decrypt buf

0x20000978: dumping 'additional data used for AEAD' (13 bytes)

0x20000978: 0000: 00 00 00 00 00 00 01 b1 17 03 03 00 02 .............

0x20000978: dumping 'IV used' (12 bytes)

0x20000978: 0000: 13 2a 4f 42 00 00 00 00 00 00 01 b1 .*OB........

0x20000978: dumping 'TAG used' (16 bytes)

0x20000978: 0000: 7c 24 04 43 56 15 80 10 36 4a d7 85 33 51 0b 57 |$.CV...6J..3Q.W

0x20000978: <= decrypt buf

0x20000978: dumping 'input payload after decrypt' (2 bytes)

0x20000978: 0000: d0 00 ..

0x20000978: <= read record

0x20000978: <= read

[ERROR] [OtaPal] [otaPal_CloseFile:697] Failed to pass sig-sha256-ecdsa signature verification: 3808428032.

```

---

<div class="post-metadata">

**Author:** ![aggarg](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/aggarg/32/4245_2.png) [@aggarg](https://forums.freertos.org/u/aggarg)\
**Post date:** [June 29, 2023, 4:04pm UTC](https://forums.freertos.org/t/ota-update-signature-verification-failing/15821/11 "2023-06-29T16:04:35Z")

</div>

One possibility is that the mbedTLS is running out of memory (though I’d expect that to show up in logs). Which memory scheme are you using for mbedTLS: [Alternative ways of allocating memory in Mbed TLS — Mbed TLS documentation](https://mbed-tls.readthedocs.io/en/latest/kb/how-to/using-static-memory-instead-of-the-heap/)? If heap, you can map them to FreeRTOS heap and enable malloc failed hook to catch malloc failure.

Other thing to check is that the complete image is received and written correctly. Can you read the image back from flash and check that it is same as the one sent from the cloud?
