Topic: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

I am a master student writing my thesis and want to use the crypto library in my work.

I am using a device with ARM Cortex M23 core, and Keil as IDE. The device has 30720 bytes FLSAH and 3072 bytes RAM. No operating system on this device (I try to avoid OS as well).

At the beginning I was using this Sha256 APIs and things were fine. I generate sha256 hash value in the way https://github.com/wolfSSL/wolfssl/blob … est/test.c "sha256_test" does:

        ret = wc_Sha256Update(&sha, (byte*)test_sha[i].input, (word32)test_sha[i].inLen);
        if (ret != 0) {
            ERROR_OUT(WC_TEST_RET_ENC_I(i), exit);
        }
        ret = wc_Sha256GetHash(&sha, hashcopy);
        if (ret != 0)

and here is my user_settings:

/* only use crypto lib */
#define WOLFCRYPT_ONLY

/* no ARM crypto HW*/
//#define WOLFSSL_ARMASM_NO_HW_CRYPTO

/* single threaded, to avoid including pthread.h (which cannot be found by any means)*/
#define SINGLE_THREADED

/* no file system is used*/
#define NO_FILESYSTEM

/* enable SHA512 */
#define WOLFSSL_SHA512

Everything was fine, then I moved to sha512 with the same settings. Still, I try to generate the hash value in the same way as test does:

    ret = wc_Sha512Update(&sha, data, len);
    if (ret != 0) {
        /* error code */
              gen_status = false;
    }
    ret = wc_Sha512GetHash(&sha, hash);
    if (ret != 0) {
        /* error code */
              gen_status = false;
    }

Keil reported these to me:

Build started: Project: ciphers
*** Using Compiler 'V6.19', folder: 'C:\Keil_v5\ARM\ARMCLANG\Bin'
Build target 'ciphers'
Note: source file '.\ciphers\cmac.c' - object file renamed from '.\obj\cmac.o' to '.\obj\cmac_1.o'.
Note: source file '.\wolfssl-5.6.3\wolfcrypt\src\sha256.c' - object file renamed from '.\obj\sha256.o' to '.\obj\sha256_1.o'.
compiling sp_arm32.c...
compiling main.c...
compiling sha256.c...
compiling sha256.c...
compiling sha512.c...
linking...
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text._Transform_Sha512).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.rodata.K512).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.Sha512_Family_Final).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.wc_Sha512Update).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.wc_InitSha512_ex).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.InitSha512).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching main.o(.text.main).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching startup.o(.text).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.wc_Sha512GetHash).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching memcpya.o(.text).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching memseta.o(.text).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching init.o(.text).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching sha512.o(.text.wc_Sha512Final).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching entry9a.o(.ARM.Collect$$$$0000000B).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching system.o(.text.System_init).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching test_table.o(test_table).
.\obj\ciphers.axf: Error: L6406E: No space in execution regions with .ANY selector matching anon$$obj.o(Region$$Table).
.\obj\ciphers.axf: Error: L6407E: Sections of aggregate size 0x2968 bytes could not fit into .ANY selector(s).
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.
Finished: 2 information, 0 warning and 18 error messages.
".\obj\ciphers.axf" - 18 Error(s), 0 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

I guess it's because the RAM is too small. So I got another implementation of sha512 on Github. To my surprise, it worked. So I am sure that the RAM size is enough for sha512 operations.

Then I went through the code can found that the difference between sha256 and sha512 was that, sha256 uses word32, but sha512 uses word64, like

static int _Transform_Sha512(wc_Sha512* sha512)
{
    const word64* K = K512;
    word32 j;
    word64 T[8];

I guess the problem might be here? Therefore, I added this setting to my user_settings

/* 32-bit CPU */
#define WC_32BIT_CPU

Unfortunately noting happened, so I tried

/* 16-bit CPU */
#define WC_16BIT_CPU

New errors appeared

Note: source file '.\ciphers\cmac.c' - object file renamed from '.\obj\cmac.o' to '.\obj\cmac_1.o'.
Note: source file '.\wolfssl-5.6.3\wolfcrypt\src\sha256.c' - object file renamed from '.\obj\sha256.o' to '.\obj\sha256_1.o'.
wolfssl-5.6.3/wolfcrypt/src/sha512.c(770): error: call to undeclared function 'rotrFixed64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
        R( 0); R( 1); R( 2); R( 3);
        ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(728): note: expanded from macro 'R'
    h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+j] + (j ? blk2(i) : blk0(i)); \
            ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(723): note: expanded from macro 'S1'
#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41))
               ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(770): note: did you mean 'rotrFixed'?
wolfssl-5.6.3/wolfcrypt/src/sha512.c(728): note: expanded from macro 'R'
    h(i) += S1(e(i)) + Ch(e(i),f(i),g(i)) + K[(i)+j] + (j ? blk2(i) : blk0(i)); \
            ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(723): note: expanded from macro 'S1'
#define S1(x) (rotrFixed64(x,14) ^ rotrFixed64(x,18) ^ rotrFixed64(x,41))
               ^
wolfssl-5.6.3\wolfcrypt/src/misc.c(111): note: 'rotrFixed' declared here
    WC_MISC_STATIC WC_INLINE word32 rotrFixed(word32 x, word32 y)
                                    ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(840): error: call to undeclared function 'ByteReverseWords64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
                ByteReverseWords64(sha512->buffer, sha512->buffer,
                ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(840): note: did you mean 'ByteReverseWords'?
wolfssl-5.6.3\wolfcrypt/src/misc.c(181): note: 'ByteReverseWords' declared here
WC_MISC_STATIC WC_INLINE void ByteReverseWords(word32* out, const word32* in,
                              ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(913): error: call to undeclared function 'ByteReverseWords64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
            ByteReverseWords64(sha512->buffer, sha512->buffer,
            ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(1019): error: call to undeclared function 'ByteReverseWords64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
            ByteReverseWords64(sha512->buffer,sha512->buffer,
            ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(1061): error: call to undeclared function 'ByteReverseWords64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
            ByteReverseWords64(sha512->buffer, sha512->buffer, WC_SHA512_PAD_SIZE);
            ^
wolfssl-5.6.3/wolfcrypt/src/sha512.c(1132): error: call to undeclared function 'ByteReverseWords64'; ISO C99 and later do not support implicit function declarations [-Wimplicit-function-declaration]
    ByteReverseWords64((word64*)digest, (word64*)sha512->digest,
    ^
6 errors generated.

I am so confused. Is 32-bit CPU a problem? If yes, what settings should I use?

I have also read the user_settings of the MDK5_ARM CryptBenckmark project, but I did not get any hint about this.

Thanks in advance for all reply and advice. Let me know if more info is needed.

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi mnzdbz,

To me it looks like you are running out of flash space. Its not a 32-bit/16-bit issue. Your 32-bit MCU has support for the 64-bit type (word64) using "long long".

I suggest you review our low resource build options and user_settings template here:
* https://github.com/wolfSSL/wolfssl/blob … template.h
* https://github.com/wolfSSL/wolfssl/blob … e.ac#L1962

You would likely benefit from the following:
* USE_SLOW_SHA512

Which C files are you building? Some of the algorithms are on by default and require a NO_ build option (example NO_SHA).

Thanks,
David Garske, wolfSSL

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi David,

Thanks a lot for the reply. It worked.

Now I am using RSA functions + SHA256 to sign some data, and I encountered new problems.

Here are part of my settings:

#ifndef WOLFSSL_USER_SETTINGS_H
#define WOLFSSL_USER_SETTINGS_H

/* If TARGET_EMBEDDED is defined then small target settings are used */
#if !(defined(__MACH__) || defined(__FreeBSD__) || defined(__linux__) || defined(_WIN32))
    #define TARGET_EMBEDDED
#endif

/* ------------------------------------------------------------------------- */
/* Platform */
/* ------------------------------------------------------------------------- */
#define WOLFSSL_GENERAL_ALIGNMENT 4
#define SIZEOF_LONG_LONG 8
#ifdef TARGET_EMBEDDED
    /* disable mutex locking */
    #define SINGLE_THREADED

    /* reduce stack use. For variables over 100 bytes allocate from heap */
    #define WOLFSSL_SMALL_STACK

    /* Disable the built-in socket support and use the IO callbacks.
     * Set IO callbacks with wolfSSL_CTX_SetIORecv/wolfSSL_CTX_SetIOSend
     */
    #define WOLFSSL_USER_IO
#endif
/* ------------------------------------------------------------------------- */
/* Math Configuration */
/* ------------------------------------------------------------------------- */
/* Wolf Single Precision Math */
#if 0
......
#elif 1
    /* Fast Math (tfm.c) (stack based and timing resistant) */
    #define USE_FAST_MATH
    #define TFM_TIMING_RESISTANT
#endif

/* ------------------------------------------------------------------------- */
/* Crypto */
/* ------------------------------------------------------------------------- */
/* RSA */
#undef NO_RSA
#if 1
    #ifdef USE_FAST_MATH
        /* Maximum math bits (Max RSA key bits * 2) */
        #define FP_MAX_BITS 4096
    #endif

    /* half as much memory but twice as slow */
    #define RSA_LOW_MEM

    /* Enables blinding mode, to prevent timing attacks */
    #define WC_RSA_BLINDING

    /* RSA PSS Support */
    #define WC_RSA_PSS
#endif

/* ------------------------------------------------------------------------- */
/* Hashing */
/* ------------------------------------------------------------------------- */
/* Sha256 */
#undef NO_SHA256
#if 1
    /* not unrolled - ~2k smaller and ~25% slower */
    #define USE_SLOW_SHA256
#endif

/* ------------------------------------------------------------------------- */
/* Benchmark / Test */
/* ------------------------------------------------------------------------- */
#ifdef TARGET_EMBEDDED
    /* Use reduced benchmark / test sizes */
    #define BENCH_EMBEDDED
#endif

/* Use test buffers from array (not filesystem) */
#ifndef NO_FILESYSTEM
#define USE_CERT_BUFFERS_256
#define USE_CERT_BUFFERS_2048
#endif

    #ifndef WOLFSSL_STATIC_MEMORY
        #define NO_WOLFSSL_MEMORY

/* ------------------------------------------------------------------------- */
/* Custom Standard Lib */
/* ------------------------------------------------------------------------- */
/* Allows override of all standard library functions */
#undef STRING_USER

/* ------------------------------------------------------------------------- */
/* Enable Features */
/* ------------------------------------------------------------------------- */

//#define WOLFSSL_TLS13
//#define WOLFSSL_OLD_PRIME_CHECK /* Use faster DH prime checking */
//#define HAVE_TLS_EXTENSIONS
//#define HAVE_SUPPORTED_CURVES
//#define WOLFSSL_BASE64_ENCODE

//#define WOLFSSL_KEY_GEN /* For RSA Key gen only */
//#define KEEP_PEER_CERT
//#define HAVE_COMP_KEY

/* TLS Session Cache */
#if 0
    #define SMALL_SESSION_CACHE
#else
    #define NO_SESSION_CACHE
#endif


/* ------------------------------------------------------------------------- */
/* Disable Features */
/* ------------------------------------------------------------------------- */
//#define NO_WOLFSSL_SERVER
//#define NO_WOLFSSL_CLIENT
//#define NO_CRYPT_TEST
//#define NO_CRYPT_BENCHMARK
#define WOLFCRYPT_ONLY

/* do not warm when file is included to be built and not required to be */
#define WOLFSSL_IGNORE_FILE_WARN

/* In-lining of misc.c functions */
/* If defined, must include wolfcrypt/src/misc.c in build */
/* Slower, but about 1k smaller */
//#define NO_INLINE

#ifdef TARGET_EMBEDDED
    #define NO_FILESYSTEM
    #define NO_WRITEV
    #define NO_MAIN_DRIVER
    #define NO_DEV_RANDOM
#endif

#define NO_OLD_TLS
#define NO_PSK

#define NO_DSA
#define NO_RC4
#define NO_MD4
#define NO_PWDBASED
//#define NO_CODING
//#define NO_ASN_TIME
//#define NO_CERTS
//#define NO_SIG_WRAPPER

I generated key and signed some data on my own PC. And I wanted to verify the signature on the embedded platform.

#include <wolfssl/wolfcrypt/signature.h>
#include <wolfssl/wolfcrypt/rsa.h>
#include <wolfssl/wolfcrypt/asn.h>
#include <wolfcrypt/test/test.h>

/* macros */
/* size in bytes */
#define SIG_BUFF_SIZE 128 //1024bits
#define DATA_SIZE 8
#define KEY_SIZE 1024 //bits
#define WC_RSA_EXPONENT 65537L
#define FOURK_BUF 4096

#define HEAP_HINT NULL

/* const */
const enum wc_HashType hash_type = WC_HASH_TYPE_SHA256;
const enum wc_SignatureType sig_type = WC_SIGNATURE_TYPE_RSA;
const byte data[DATA_SIZE] = "testsig!";

int main() {
    int ret;
    RsaKey pub_rsa;
    word32 idx = 0;

    /**********************************************************/
    /*                     Initializing                       */
    /**********************************************************/
    ret = wc_InitRsaKey(&pub_rsa, NULL);
    if (ret != 0) {
        // error initializing RSA key
    }

    /**********************************************************/
    /*              Key convert from .der file                */
    /**********************************************************/
    /* From text */
    byte pub_rsa_der[FOURK_BUF] = {
            0x30, 0x81, ......};
    ret = wc_RsaPublicKeyDecode(pub_rsa_der, &idx, &pub_rsa, 162);

    /**********************************************************/
    /*                Signature veritication                  */
    /**********************************************************/
    byte sig[SIG_BUFF_SIZE] = {
        0x9C, 0x3D,...... };
    word32 sig_len = 128;
    ret = wc_SignatureVerify(hash_type, sig_type, data, DATA_SIZE, sig, sig_len, &pub_rsa, sizeof(pub_rsa));
    if (ret != 0) {
        // error verification
    }

    /**********************************************************/
    /*                 Release space for key                  */
    /**********************************************************/
    wc_FreeRsaKey(&pub_rsa);
    ret = wc_InitRsaKey(&pub_rsa, HEAP_HINT);
    if (ret != 0) {
        // error initializing RSA key
    }
}

The linker reported this to me:

.\obj\ciphers.axf: Error: L6218E: Undefined symbol time (referred from asn.o).

I was compiling all the C files under ./wolfcrypt/src https://github.com/wolfSSL/wolfssl/tree … fcrypt/src. To what I know, such error is raised when I didn't include the source file defining the function named "time". But I couldn't find any file defining the "time" function.

I have already run the same verification in my own PC, and everything was fine. I don't know why this happened to the embedded platform.

Thanks in advance!

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi mnzdbz,

For validation of certificate begin/end dates we need a time source/RTC. If this is not available you can bypass date checking by adding NO_ASN_TIME to your user_settings.h. If you have an RTC, but your stdlib doesn't expose time() then you can define your own API.

Example:

/* user_settings.h - Override Current Time */

/* Allows custom "custom_time()" function to be used for benchmark */
#define WOLFSSL_USER_CURRTIME
#define WOLFSSL_GMTIME
#define USER_TICKS
extern unsigned long my_time(unsigned long* timer);
#define XTIME my_time

/* example code */

/* This is used by wolfCrypt asn.c for cert time checking */
unsigned long my_time(unsigned long* timer)
{
    (void)timer;
    return hw_get_time_sec();
}

Thanks,
David Garske, wolfSSL

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi David,

Thanks for the reply, I disabled asn time and the error disappeared.

I have two more questions:

1. what settings should I apply if I don't use certificate? I tried to add #define NO_CERTS, but many error appeared..

2. how can I reduce the RAM utilization of RSA?

For example, the platform I am using has 3kB RAM starting from address 0x18000000, and I use wc_SignatureVerify to verify some data. After some function calls, in wc_SignatureVerifyHash, a variable called plain_text was put in addr 0x17FFFE2C (it is a uchar[512] array), and Keil reported "Mem Access Error". After verification, the return value is 0xFFFFFF90 (-112), which does not equal to any of valid return values listed in https://www.wolfssl.com/documentation/m … tureverify. But if I run the same codes in my own PC, the return value is 0, which is good.

It seems the platform has run out of RAM space and mem access failure leads to wrong return value. Is there any option that can help reduce RAM utilization?

Thanks in advance!

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi mnzdbz,

1) If you are using wolfCrypt only (no TLS) and do not want to do any X.509 you should be able to use NO_CERTS. We did have some fixes around this recently. But you should be able to use NO_CERTS, WOLFCRYPT_ONLY and WOLFSSL_ASN_TEMPLATE.

2) That is a great question! We have several math options with varying memory use. You are using fast math which uses math variables on the stack. Those sizes are max key size * 2. Example #define FP_MAX_BITS (2*2048)". If you have only 3KB of RAM it is unlikely you'll be able to do any asymmetric operations RSA or ECC. For example a 2048-bit RSA key requires multiple 512 byte math variables and the underlying modulus exponent uses several more.  Do you really only have access to 3KB of RAM?

Thanks,
David Garske, wolfSSL

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi David,

Thanks for the reply! This week I was working on enlarging the RAM size, and I got around 800kB RAM finally. (It is a virtual platform so I spent some time on its source code....)

I tried again but the same return value appeared. So I went through the code line by line and found out that the program fell into error handling:

if (ret == MP_EXPTMOD_E) {
            /* This can happen due to incorrectly set FP_MAX_BITS or missing XREALLOC */
            WOLFSSL_MSG("RSA_FUNCTION MP_EXPTMOD_E: memory/config problem");
        }

Then I checked FP_MAX_BITS in my user_settings, it's 4096, seems fine for RSA-1024. I was trying to find where is XREALLOC defined, but in types.h I found:

    /* idea to add global alloc override by Moises Guimaraes  */
    /* default to libc stuff */
    /* XREALLOC is used once in normal math lib, not in fast math lib */
    /* XFREE on some embedded systems doesn't like free(0) so test  */
    #if defined(HAVE_IO_POOL)
        WOLFSSL_API void* XMALLOC(size_t n, void* heap, int type);
        WOLFSSL_API void* XREALLOC(void *p, size_t n, void* heap, int type);
        WOLFSSL_API void XFREE(void *p, void* heap, int type);

It seems there is no XREALLOC shall be defined in fast math mode, so the problem is the value of FP_MAX_BITS?

I have also tried several values: 1024, 2048, 4096, 8192. But it doesn't help.

Some additional info:
The error code comes from:

static int RsaFunctionSync(......){
        ......
        case RSA_PUBLIC_DECRYPT:
            if (mp_exptmod_nct(tmp, &key->e, &key->n, tmp) != MP_OKAY)
                ret = MP_EXPTMOD_E;
            break;

How can I solve this issue?

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi mnzdbz,

How is your stack configured? Fast math (tfm.c) uses stack not heap. The correct size for FP_MAX_BITS is your maximum key size * 2 (for multiplication of two big integers).

You would likely need about 8KB of stack with your configuration. If you would like to use heap I recommend the following build settings.


#define WOLFSSL_SP_MATH_ALL
#define WOLFSSL_SP_SMALL
#define WOLFSSL_SMALL_STACK

This will use our sp_int.c with heap allocations.

Thanks,
David Garske, wolfSSL

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi David,

Thank you so much for the suggestion.

I enlarged my heap to 7kB(instead of stack) and everything is fine now. It is really weird that the program does not require stack, instead, it requires a big heap... Anyway, considering I am using a virtual prototype, I think there might be something wrong with the platform.

Another thing confusing me recently is about AES (Yes I finally done the asymmetric algorithms, now I move to symmetric).

I found out that AES128 took 17kB of ROM and it took 38ms to encrypt. Then I wanted to reduce the ROM size, so I used WOLFSSL_AES_SMALL_TABLES. Now it only uses only 5kB ROM, but it takes 120+ms...

Is there a compromise? How can I speed it up while keeping the ROM size small?

Share

Re: Keil build error L6406E: No space in.. with 32-bit ARM CPU(Cortex M23)

Hi mnzdbz,

Because you are using WOLFSSL_SMALL_STACK it uses heap instead. If you remove the small stack option it will use stack and not heap.

Which mode of AES? There are AES tables as you found. Not using the tables slows down the operation because it must compute values. Are you building the .c code with optimizations enabled like "-Os" or "-O2"? Those make a big different.

Besides WOLFSSL_AES_SMALL_TABLES you can also play with WOLFSSL_AES_NO_UNROLL to see how that impacts performance and code size.

Thanks,
David Garske, wolfSSL

Share