[SOLVED] Linker error undefined reference with code from AVR-Crypto-Lib

My current project is using an Arduino Pro Mini (ATmega328) which is running short on space, and I also want to minimize execution time. So I am trying to use AVR-Crypto-Lib from http://www.das-labor.org/wiki/AVR-Crypto-Lib/en.

I’ve run into some trouble early on, with linker problems.
I’ve tried with both C and ASM files, and both give me this error.
I’m using Arduino IDE 1.5.7.

C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-gcc -w -Os -Wl,--gc-sections -mmcu=atmega328p -o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp/aes_test.cpp.elf C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes_test.cpp.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_dec-asm.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_enc-asm.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_invsbox-asm.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_sbox-asm.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\avr-asm-macros.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\gf256mul.S.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_keyschedule.c.o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp/core.a -LC:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp -lm 
C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes_test.cpp.o: In function `setup':
/Arduino/aes_test.ino:30: undefined reference to `aes128_init(void const*, aes128_ctx_t*)'
collect2: error: ld returned 1 exit status

Sample sketch

#include "aes.h"

const int keylen = 16;
const byte aes_key[] =
{
  0x5A, 0xBA, 0xD7, 0x2F, 0xF0, 0x5D, 0x59, 0xAB, 0x5D, 0x81, 0xD5, 0x9D, 0x7E, 0x36, 0xA2, 0x1B,
};

const byte hmacKey[] =
{
  0x88, 0x6B, 0x84, 0xA0, 0x7E, 0xBA, 0x23, 0x5A, 0x38, 0x28, 0x15, 0x3D, 0xEC, 0x45, 0x90, 0x16,
};

//byte my_iv[16];
byte iv[16];

char mytext[] = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.";

void genIV(byte * ivptr) {
  // generate a fresh iv
  randomSeed(analogRead(1));              //Seed for random number generation  
  for(int i=0; i<16; i++){
     ivptr[i] = random(255);               //Load the buffer with random data
  }
}

void setup() {
  // put your setup code here, to run once:
  aes128_ctx_t aesContext;
  aes128_init(aes_key,&aesContext);

}

void loop() {
  // put your main code here, to run repeatedly:

}

Any ideas?

Your setup() function called aes128_init(...) but either you didn't provide it, or you didn't provide an aes128_init(...) that takes the type of parameters that you provided. Where is aes128_init(...) supposed to be defined?

Going out on a limb, I am going to guess that there is supposed to be an aes.c or aes.cpp file that either you are missing or have put in the wrong place.

Thanks vaj4088, although I believe I have covered all of that.

The function aes128_init is supposed to be defined in either aes_keyschedule.c or aes_keyschedule-asm.S, depending on if you want C or ASM implementation. If I include both these two files in the library subset I try to use in the Arduino IDE, the linker errors look like these:

C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_keyschedule.c.o: In function `aes128_init':
G:\filelib\Google Drive\Arduino\apps\libraries\aes/aes_keyschedule.c:88: multiple definition of `aes128_init'
C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_keyschedule-asm.S.o:G:\filelib\Google Drive\Arduino\apps\libraries\aes/aes_keyschedule-asm.S:46: first defined here

And if I keep only one, or none, I receive "undefined reference" error.

aes_keyschedule.c

void aes128_init(const void *key, aes128_ctx_t *ctx)
{
    aes_init(key, 128, (aes_genctx_t*) ctx);
}

aes_keyschedule-asm.S

.global aes128_init
aes128_init:
    movw r20, r22
    clr r23
    ldi r22, 128

aes.h contains include for aes_keyschedule.h, and even if I also put this also in my .ino file, the linker reports the same error.

I managed to temporarily work around the issue by changing the name of aes_keyschedule.c to aes_keyschedule.cpp. However I would prefer to use the ASM code, and I don't know if there is a way to do something similar with aes_keyschedule-asm.S. Obviously the IDE does not compile this properly.

C:\Program Files (x86)\Arduino/hardware/tools/avr/bin/avr-gcc -c -g -x assembler-with-cpp -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=157 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\cores\arduino -IC:\Program Files (x86)\Arduino\hardware\arduino\avr\variants\standard -IG:\filelib\Google Drive\Arduino\apps\libraries\aes -IG:\filelib\Google Drive\Arduino\apps\libraries\aes\utility G:\filelib\Google Drive\Arduino\apps\libraries\aes\aes_keyschedule-asm.S -o C:\Users\myuser\AppData\Local\Temp\build6684416969530087656.tmp\aes\aes_keyschedule-asm.S.o

I finally figured it out.

I need to add extern "C" {} around these function declarations in the .h files, which either have .c files or .S asm files with definitions, for the C++ linker to include them.

For proper inclusion only when necessary, I have to do this only when "__cplusplus" is defined. And do not include typedefs in the "extern" section. If I do not, I run into problems with .c files.

Error, when trying to compile .c file with plain 'extern "C" {}' in header.

error: expected identifier or '(' before string constant
 extern "C"{
        ^

Example for correct 'extern "C" {}' in header:

typedef struct {
  void *ptr;
} example_struct;

#ifdef __cplusplus
extern "C"{
#endif

void example_func(void); // this function is defined in a .c or .S file

#ifdef __cplusplus
} // extern "C"
#endif

The parts I want out of AVR-Crypto-lib are now compiling and linking and everything!

MANY MANY Thanks for this solution As a hardened embedded C programmer of the 8051 family and derivatives for far too many years this error has eluded me and I thought I was loosing the plot. This is my first major foray into the Arduino and this forum has been brilliant in resolving problems.

Thanks again Bob G

though I have added the code

ifdef __cplusplus

extern "C"{

endif

....

it still shows undefined reference to aes128_init error, but without parentheses and arguments.

I feel this error comes because of wrong use of asm file, but i don't have any clue.please help