Topic: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

I just upgrade my project from 3.13.0 to 3.15.7-stable.
I am facing a problem with TimingPadVerify() wich always returns VERIFY_MAC_ERROR.
I had to made the following changes for the function to return 0. After all my application is working fine.

int TimingPadVerify(WOLFSSL* ssl, const byte* input, int padLen, int macSz,
...
    /* Non-zero on failure. */
    good = (byte)~(word32)good;
    good &= good >> 4;
    good &= good >> 2;
    good &= good >> 1;
    /* Make ret negative on masking failure. */
//    ret -= 1 - good;
[b]    if (ret) ret -= 1 - good;   // CGH Le 01/02/2019[/b]
...

Indeed, before negative conversion the comment indicate that

good = 0

means Ok. Making good=0 negative with

ret -= 1 - good

results in good=-1.

What is wrong ?
Thanks for help.

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi @CGH,

Thank you for contacting wolfSSL with your issue. I have requested that one of our developers (who was working on that API last year, around July, to make it constant time for side channel attack prevention) take a look at your report.

Please expect an update from Sean in the next few days sometime.

In the meantime can you tell us what it is you are working on and which organization you are with?


Warm Regards,

K

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi @CGH,

Looking at the code, good will be zero when everything works.
That means that the bits are flipped and good will be all 1s.
Then good is reduced down to a single bit and therefore will have a value of 1.
Therefore ret is unchanged when things work.

Can you confirm that good is 0 before negation and that good is 0 before subtracting from 1?
Also, can you give me a context in which you are testing? That is, which client/servers are using.

Thanks,
Sean
--
Sean Parkinson, wolfSSL
Senior Software Engineer

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi Kaleb and Sean,

Thanks for your prompt feedback.

The project I am working on is to collect travel time via TomTom API's.
This is a personal project.

The client is my embedded firmware using lwip stack.
The server is TomTom API "api.tomtom.com".

After client connection, send "GET HTTP/1.1" through wolfSSL_write() then in function TimingPadVerify() step by step variable values in comment below :

...
    good = MaskPadding(input, pLen, macSz);
// good is 0
    /* 4th argument has potential to underflow, ssl->hmac function should
     * either increment the size by (macSz + padLen + 1) before use or check on
     * the size to make sure is valid. */
    ret = ssl->hmac(ssl, verify, input, pLen - macSz - padLen - 1, padLen,
// ret is 0                                                                    content, 1);
    good |= MaskMac(input, pLen, ssl->specs.hash_size, verify);
// good is 0xFF
    /* Non-zero on failure. */
    good = (byte)~(word32)good;
// good is 0
    good &= good >> 4;
// good is 0
    good &= good >> 2;
// good is 0
    good &= good >> 1;
// good is 0
    /* Make ret negative on masking failure. */

#warning Pourquoi faut-il modifier le code pour que ca fonctionne ?
    ret -= 1 - good;
// ret is -1
...

Regards.

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi @CGH,

MaskMac returning a non-zero value is a failure result.
Therefore, the return of -1 is correct.

I'm not sure why MaskMac would fail. I did a quick test on Linux and it worked.
The MaskMac function is comparing 'expMac' with the MAC in 'data'.
There should be padding at the end of 'data' and before that the MAC.
The padding is a repeated byte that is the length of the padding. If you can't see the padding then maybe the decryption failed.

Note that TimingPadVerify is used with TLS 1.1 and new applications should be using TLS 1.2 as it is newer and more secure.
Try using TLS 1.2 and let me know if that works for you.

Sean
--
Sean Parkinson, wolfSSL
Senior Software Engineer

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi Sean,

I tried with TLS1.2 with the following code initialization before socket connection :

  wolfSSL_Debugging_ON();
  s = t->Socket = DMEM_MallocZ(sizeof(TOMTOM_SOCKET));
  s->WSSL_Ctx = wolfSSL_CTX_new(wolfTLSv1_2_client_method());
  wolfSSL_CTX_load_verify_locations(s->WSSL_Ctx, "ca-cert.pem", 0 );
  wolfSSL_CTX_set_verify(s->WSSL_Ctx, SSL_VERIFY_NONE, 0);
  wolfSSL_SetIORecv(s->WSSL_Ctx, WSSL_TomTomRx);
  wolfSSL_SetIOSend(s->WSSL_Ctx, WSSL_TomTomTx);
  s->WSSL_Obj = wolfSSL_new(s->WSSL_Ctx);
  wolfSSL_set_fd(s->WSSL_Obj, 0);
  wolfSSL_SetVersion(s->WSSL_Obj, WOLFSSL_TLSV1_2);

The problem remain the same.
How can I make sure that the connection will use TLS1.2 ?

Regards.

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi @CGH,

I'm surprised that it isn't using TLS 1.2!
The client method only allows use of the TLS 1.2 protocol.
I'll have to think on this.

Have you replaced the HMAC or hash implementation with a hardware one?

Sean

--
Sean Parkinson, wolfSSL
Senior Software Engineer

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi Sean,

I have checked my hardware and nothing to replace HMAC and hash.

Regards.

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi @CGH

OK. I know what I was doing wrong now.
Let me know which cipher suite you are using.
Please use AES-GCM if possible.

I did successfully connect to and get a page from api.tomtom.com:443 on Linux with the cipher suite ECDHE-RSA-AES128-SHA.

Sean
--
Sean Parkinson, wolfSSL
Senior Software Engineer

Share

10

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi Sean,

I added

#define HAVE_AESGCM
#define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA

In Settings.h

Before connecting to TomTom I added

wolfSSL_set_cipher_list(WOLFSSL *, "<CIPHER_NAME>");

When using cipher "ECDHE-RSA-AES128-SHA", the first call to wolfSSL_write() returns error -1
When using cipher "AES128-GCM-SHA256", all is working fine.

How to conclude about this ?

Thanks again for your help and best Regards.
Christophe.

Share

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

@CGH,

Please avoid using any defines of the nature #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, those defines are detected and set internally within the library and not intended for users to define. To see which rules govern that define look at the header wolfssl-3.15.7/wolfssl/internal.h

 516     #if (defined(HAVE_ECC) || defined(HAVE_CURVE25519)) && !defined(NO_TLS)
 517         #if !defined(NO_AES)
 518             #if !defined(NO_SHA) && defined(HAVE_AES_CBC)
 519                 #if !defined(NO_RSA)
 520                     #ifdef WOLFSSL_AES_128
 521                         #define BUILD_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
 522                     #endif
...

So to activate that specific cipher suite you would want to use these settings:

#undef HAVE_ECC
#define HAVE_ECC
// Make sure that NO_TLS is not defined
// Make sure the NO_AES is not defined
// Make sure that NO_SHA is not defined
// HAVE_AES_CBC should be automatically enabled but if it isn't go ahead and define it.
// Make sure that NO_RSA is not defined

If all of the above conditions are met then that cipher suite will be available.

- KH

12

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

I Kaleb and Sean,

I made it clean the following way.
I declared  WOLFSSL_USER_SETTINGS as defined symbole for IAR compiler.

I added user_settings.h

// =========================================================
//  HARDWARE & DEVELOPMENT TOOLS
// ---------------------------------------------------------
#define FREERTOS
#define WOLFSSL_LWIP
#define WOLFSSL_IAR_ARM
#define NO_WOLFSSL_MEMORY
#define NO_WOLFSSL_SMALL_STACK

// =========================================================
//  WOLFSSL CIPHER SUITES
// ---------------------------------------------------------
#define WC_NO_HARDEN
#define WOLFSSL_STATIC_RSA
#define HAVE_AESGCM
#define HAVE_ECC
#define HAVE_DH
#define USE_FAST_MATH

// =========================================================
//  FatFs ChaN FILE SYSTEM
// ---------------------------------------------------------
#include "FreeRTOS.h"
#include "semphr.h"
#include "ff.h"
#include "GstFS.h"
#define NO_STDIO_FILESYSTEM
#define NO_WOLFSSL_DIR
#define WOLFSSL_USER_FILESYSTEM
#define FILE       FIL
#define XFILE      FIL*
#define XFOPEN     GFS_fopen
#define XFSEEK     GFS_fseek
#define XFTELL     GFS_ftell
#define XREWIND    GFS_rewind
#define XFREAD     GFS_fread
#define XFWRITE    GFS_fwrite
#define XFCLOSE    GFS_fclose
#define XSEEK_END  GFS_SEEK_END
#define XBADFILE   NULL

// =========================================================
//  IAR Compiling options
// ---------------------------------------------------------
#pragma diag_suppress = Pa089

I had to comment one line in settings.h as follow :

#if defined(WOLFSSL_IAR_ARM) || defined(WOLFSSL_ROWLEY_ARM)
    #define NO_MAIN_DRIVER
    #define SINGLE_THREADED
    #if !defined(USE_CERT_BUFFERS_2048) && !defined(USE_CERT_BUFFERS_4096)
        #define USE_CERT_BUFFERS_1024
    #endif
    #define BENCH_EMBEDDED
//    #define NO_FILESYSTEM
    #define NO_WRITEV
    #define WOLFSSL_USER_IO
    #define BENCH_EMBEDDED
#endif

I didn't found an other way to do it.

The testing result is as follow :
Cipher "AES128-GCM-SHA256" is working fine.
When using cipher "ECDHE-RSA-AES128-SHA" TimingPadVerify() returns VERIFY_MAC_ERROR.

Regards.

Share

13

Re: TimingPadVerify() returns VERIFY_MAC_ERROR in release 3.15.7-stable

Hi Sean,

Finally, in addition to "AES128-GCM-SHA256" the cipher "ECDHE-RSA-AES128-GCM-SHA256" is also working.
The cipher "ECDHE-RSA-AES128-SHA" still goes through TimingPadVerify() ending with error.

My user_settings.h is :

// =========================================================
//  HARDWARE & DEVELOPMENT TOOLS
// ---------------------------------------------------------
#define FREERTOS
#define WOLFSSL_LWIP
#define WOLFSSL_IAR_ARM
#define NO_WOLFSSL_MEMORY
#define NO_WOLFSSL_SMALL_STACK

// =========================================================
//  WOLFSSL CIPHER SUITES
// ---------------------------------------------------------
#define WC_NO_HARDEN
#define WOLFSSL_STATIC_RSA
#define HAVE_AESGCM
#define HAVE_ECC
#define HAVE_DH
#define USE_FAST_MATH

// =========================================================
//  FatFs ChaN FILE SYSTEM
// ---------------------------------------------------------
#include "FreeRTOS.h"
#include "semphr.h"
#include "ff.h"
#include "GstFS.h"
#define NO_STDIO_FILESYSTEM
#define NO_WOLFSSL_DIR
#define WOLFSSL_USER_FILESYSTEM
#define FILE       FIL
#define XFILE      FIL*
#define XFOPEN     GFS_fopen
#define XFSEEK     GFS_fseek
#define XFTELL     GFS_ftell
#define XREWIND    GFS_rewind
#define XFREAD     GFS_fread
#define XFWRITE    GFS_fwrite
#define XFCLOSE    GFS_fclose
#define XSEEK_END  GFS_SEEK_END
#define XBADFILE   NULL

// =========================================================
//  STRINGS : To have wolfSSL in some kind of Cooperative mode
// ---------------------------------------------------------
#define STRING_USER
#include <string.h>
#include "WSSLPort.h"

#define XMEMCPY(d,s,l)    WSSLP_Memcpy((d),(s),(l))
#define XMEMSET(b,c,l)    memset((b),(c),(l))
#define XMEMCMP(s1,s2,n)  memcmp((s1),(s2),(n))
#define XMEMMOVE(d,s,l)   memmove((d),(s),(l))

#define XSTRLEN(s1)       strlen((s1))
#define XSTRNCPY(s1,s2,n) strncpy((s1),(s2),(n))
/* strstr, strncmp, and strncat only used by wolfSSL proper,
 * not required for wolfCrypt only */
#define XSTRSTR(s1,s2)    strstr((s1),(s2))
#define XSTRNSTR(s1,s2,n) mystrnstr((s1),(s2),(n))
#define XSTRNCMP(s1,s2,n) strncmp((s1),(s2),(n))
#define XSTRNCAT(s1,s2,n) strncat((s1),(s2),(n))

#define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))

// =========================================================
//  Memory
// ---------------------------------------------------------
#define XMALLOC_OVERRIDE
#include "DrvMem.h"
#define XMALLOC(s, h, t)     ((void)h, (void)t, DMEM_Malloc((s)))
#define XFREE(p, h, t)       ((void)h, (void)t, DMEM_Free((p)))
#define XREALLOC(p, n, h, t) ((void)h, (void)t, DMEM_Realloc((p), (n))


// =========================================================
//  RandomSeed
// ---------------------------------------------------------
#define CUSTOM_RAND_GENERATE_SEED(output, sz) WSSLP_GenerateSeed(output, sz)

Best regards.

Share