Compilation error: cannot convert 'unsigned char (*)[16]' to 'unsigned char*'

I can run the following code correctly in Code::Blocks and get the output. But when I try to verify it in Arduino, I face a problem. What is the difference between Arduino IDE and Code::Blocks in compiling codes? The error is:

Compilation error: cannot convert 'unsigned char (*)[16]' to 'unsigned char*' for argument '1' to 'int crypto_aead_encrypt(unsigned char*, long long unsigned int*, const unsigned char*, long long unsigned int, const unsigned char*, long long unsigned int, const unsigned char*, const unsigned char*, const unsigned char*)'

My code is as follows.

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdint.h>
#include <stdbool.h>

#define ROUND			12
#define min(x,y) ((x)<(y)?(x):(y))
#define max(x,y) ((x)>(y)?(x):(y))

#define D				8

#define S				4

#define RATE_INBITS 128
#define RATE_INBYTES ((RATE_INBITS + 7) / 8)

#define SQUEEZE_RATE_INBITS 128
#define SQUEEZE_RATE_INBYTES ((SQUEEZE_RATE_INBITS + 7) / 8)

#define CAPACITY_INBITS 128
#define CAPACITY_INBYTES ((CAPACITY_INBITS + 7) / 8)

#define STATE_INBITS (RATE_INBITS + CAPACITY_INBITS)
#define STATE_INBYTES ((STATE_INBITS + 7) / 8)

#define KEY_INBITS (CRYPTO_KEYBYTES * 8)
#define KEY_INBYTES (CRYPTO_KEYBYTES)

#define NOUNCE_INBITS (CRYPTO_NPUBBYTES * 8)
#define NOUNCE_INBYTES (CRYPTO_NPUBBYTES)

#define TAG_INBITS 128
#define TAG_INBYTES ((TAG_INBITS + 7) / 8)

#define LAST_THREE_BITS_OFFSET (STATE_INBITS - (STATE_INBYTES - 1) * 8 - 3)

#define TAG_MATCH	 0
#define TAG_UNMATCH	-1
#define OTHER_FAILURES -2

#define ENC 0
#define DEC 1

#define CRYPTO_KEYBYTES 16
#define CRYPTO_NSECBYTES 0
#define CRYPTO_NPUBBYTES 16
#define CRYPTO_ABYTES 16
#define CRYPTO_NOOVERLAP 1

typedef uint8_t	byte;
typedef uint32_t	u32;
typedef uint64_t	u64;
typedef uint32_t CWord;
typedef u32 tword;

typedef struct{
	u64 h;
	u64 l;
}u128; // state word

const byte ReductionPoly = 0x3;
const byte WORDFILTER = ((byte) 1<<S)-1;
int DEBUG = 0;

/* to be completed for one time pass mode */
unsigned long long MessBitLen = 0;

const byte RC[D][12] = {
	{1, 3, 7, 14, 13, 11, 6, 12, 9, 2, 5, 10},
	{0, 2, 6, 15, 12, 10, 7, 13, 8, 3, 4, 11},
	{2, 0, 4, 13, 14, 8, 5, 15, 10, 1, 6, 9},
	{6, 4, 0, 9, 10, 12, 1, 11, 14, 5, 2, 13},
	{14, 12, 8, 1, 2, 4, 9, 3, 6, 13, 10, 5},
	{15, 13, 9, 0, 3, 5, 8, 2, 7, 12, 11, 4},
	{13, 15, 11, 2, 1, 7, 10, 0, 5, 14, 9, 6},
	{9, 11, 15, 6, 5, 3, 14, 4, 1, 10, 13, 2}
};

const byte MixColMatrix[D][D] = {
	{ 2,  4,  2, 11,  2,  8,  5,  6},
	{12,  9,  8, 13,  7,  7,  5,  2},
	{ 4,  4, 13, 13,  9,  4, 13,  9},
	{ 1,  6,  5,  1, 12, 13, 15, 14},
	{15, 12,  9, 13, 14,  5, 14, 13},
	{ 9, 14,  5, 15,  4, 12,  9,  6},
	{12,  2,  2, 10,  3,  1,  1, 14},
	{15,  1, 13, 10,  5, 10,  2,  3}
};

byte sbox[16] = {12, 5, 6, 11, 9, 0, 10, 13, 3, 14, 15, 8, 4, 7, 1, 2};

byte FieldMult(byte a, byte b)
{
	byte x = a, ret = 0;
	int i;
	for(i = 0; i < S; i++) {
		if((b>>i)&1) ret ^= x;
		if((x>>(S-1))&1) {
			x <<= 1;
			x ^= ReductionPoly;
		}
		else x <<= 1;
	}
	return ret&WORDFILTER;
}

void PrintState(byte state[D][D])
{
	if(!DEBUG) return;
	int i, j;
	for(i = 0; i < D; i++){
		for(j = 0; j < D; j++)
			printf("%2X ", state[i][j]);
		printf("\n");
	}
	printf("\n");
}

void PrintState_Column(CWord state[D])
{
	if(!DEBUG) return;
	int i, j;
	for(i = 0; i < D; i++){
		for(j = 0; j < D; j++)
			printf("%2X ", (state[j]>>(i*S)) & WORDFILTER);
		printf("\n");
	}
	printf("\n");
}

void AddKey(byte state[D][D], int round)
{
	int i;
	for(i = 0; i < D; i++)
		state[i][0] ^= RC[i][round];
}

void SubCell(byte state[D][D])
{
	int i,j;
	for(i = 0; i < D; i++)
		for(j = 0; j <  D; j++)
			state[i][j] = sbox[state[i][j]];
}

void ShiftRow(byte state[D][D])
{
	int i, j;
	byte tmp[D];
	for(i = 1; i < D; i++) {
		for(j = 0; j < D; j++)
			tmp[j] = state[i][j];
		for(j = 0; j < D; j++)
			state[i][j] = tmp[(j+i)%D];
	}
}

void MixColumn(byte state[D][D])
{
	int i, j, k;
	byte tmp[D];
	for(j = 0; j < D; j++){
		for(i = 0; i < D; i++) {
			byte sum = 0;
			for(k = 0; k < D; k++)
				sum ^= FieldMult(MixColMatrix[i][k], state[k][j]);
			tmp[i] = sum;
		}
		for(i = 0; i < D; i++)
			state[i][j] = tmp[i];
	}
}

void Permutation(byte state[D][D], int R)
{
	int i;
	for(i = 0; i < R; i++) {
		if(DEBUG) printf("--- Round %d ---\n", i);
		AddKey(state, i); PrintState(state);
#ifndef _TABLE_
		SubCell(state); PrintState(state);
		ShiftRow(state); PrintState(state);
		MixColumn(state);
#else
		SCShRMCS(state);
#endif
		PrintState(state);
	}
}

void PHOTON_Permutation(unsigned char *State_in)
{
    byte state[D][D];
    int i;

	for (i = 0; i < D * D; i++)
	{
		state[i / D][i % D] = (State_in[i / 2] >> (4 * (i & 1))) & 0xf;
	}

    Permutation(state, ROUND);

	memset(State_in, 0, (D * D) / 2);
	for (i = 0; i < D * D; i++)
	{
		State_in[i / 2] |= (state[i / D][i % D] & 0xf) << (4 * (i & 1));
	}
}

/* Declaration of basic internal functions */
static uint8_t selectConst(
	const bool condition1,
	const bool condition2,
	const uint8_t option1,
	const uint8_t option2,
	const uint8_t option3,
	const uint8_t option4);

static void concatenate(
	uint8_t *out,
	const uint8_t *in_left, const size_t leftlen_inbytes,
	const uint8_t *in_right, const size_t rightlen_inbytes);

static void XOR(
	uint8_t *out,
	const uint8_t *in_left,
	const uint8_t *in_right,
	const size_t iolen_inbytes);

static void XOR_const(
	uint8_t *State_inout,
	const uint8_t  Constant);

static void ROTR1(
	uint8_t *out,
	const uint8_t *in,
	const size_t iolen_inbytes);

static void ShuffleXOR(
	uint8_t *DataBlock_out,
	const uint8_t *OuterState_in,
	const uint8_t *DataBlock_in,
	const size_t DBlen_inbytes);

static void rhoohr(
	uint8_t *OuterState_inout,
	uint8_t *DataBlock_out,
	const uint8_t *DataBlock_in,
	const size_t DBlen_inbytes,
	const uint32_t EncDecInd);

static void HASH(
	uint8_t *State_inout,
	const uint8_t *Data_in,
	const uint64_t Dlen_inbytes,
	const uint8_t  Constant);

static void ENCorDEC(
	uint8_t *State_inout,
	uint8_t *Data_out,
	const uint8_t *Data_in,
	const uint64_t Dlen_inbytes,
	const uint8_t Constant,
	const uint32_t EncDecInd);

static void TAG(
	uint8_t *Tag_out,
	uint8_t *State);

/* Definition of basic internal functions */
static uint8_t selectConst(
	const bool condition1,
	const bool condition2,
	const uint8_t option1,
	const uint8_t option2,
	const uint8_t option3,
	const uint8_t option4)
{
	if (condition1 && condition2) return option1;
	if (condition1) return option2;
	if (condition2) return option3;
	return option4;
}

static void concatenate(
	uint8_t *out,
	const uint8_t *in_left, const size_t leftlen_inbytes,
	const uint8_t *in_right, const size_t rightlen_inbytes)
{
	memcpy(out, in_left, leftlen_inbytes);
	memcpy(out + leftlen_inbytes, in_right, rightlen_inbytes);
}

static void XOR(
	uint8_t *out,
	const uint8_t *in_left,
	const uint8_t *in_right,
	const size_t iolen_inbytes)
{
	size_t i;
	for (i = 0; i < iolen_inbytes; i++) out[i] = in_left[i] ^ in_right[i];
}

static void XOR_const(
	uint8_t *State_inout,
	const uint8_t  Constant)
{
	State_inout[STATE_INBYTES - 1] ^= (Constant << LAST_THREE_BITS_OFFSET);
}

static void ROTR1(
	uint8_t *out,
	const uint8_t *in,
	const size_t iolen_inbytes)
{
	uint8_t tmp = in[0];
	size_t i;
	for (i = 0; i < iolen_inbytes - 1; i++)
	{
		out[i] = (in[i] >> 1) | ((in[(i+1)] & 1) << 7);
	}
	out[iolen_inbytes - 1] = (in[i] >> 1) | ((tmp & 1) << 7);
}

static void ShuffleXOR(
	uint8_t *DataBlock_out,
	const uint8_t *OuterState_in,
	const uint8_t *DataBlock_in,
	const size_t DBlen_inbytes)
{
	const uint8_t *OuterState_part1 = OuterState_in;
	const uint8_t *OuterState_part2 = OuterState_in + RATE_INBYTES / 2;

	uint8_t OuterState_part1_ROTR1[RATE_INBYTES / 2] = { 0 };
	size_t i;

	ROTR1(OuterState_part1_ROTR1, OuterState_part1, RATE_INBYTES / 2);

	i = 0;
	while ((i < DBlen_inbytes) && (i < RATE_INBYTES / 2))
	{
		DataBlock_out[i] = OuterState_part2[i] ^ DataBlock_in[i];
		i++;
	}
	while (i < DBlen_inbytes)
	{
		DataBlock_out[i] = OuterState_part1_ROTR1[i - RATE_INBYTES / 2] ^ DataBlock_in[i];
		i++;
	}
}

static void rhoohr(
	uint8_t *OuterState_inout,
	uint8_t *DataBlock_out,
	const uint8_t *DataBlock_in,
	const size_t DBlen_inbytes,
	const uint32_t EncDecInd)
{
	ShuffleXOR(DataBlock_out, OuterState_inout, DataBlock_in, DBlen_inbytes);

	if (EncDecInd == ENC)
	{
		XOR(OuterState_inout, OuterState_inout, DataBlock_in, DBlen_inbytes);
	}
	else
	{
		XOR(OuterState_inout, OuterState_inout, DataBlock_out, DBlen_inbytes);
	}
}

static void HASH(
	uint8_t *State_inout,
	const uint8_t *Data_in,
	const uint64_t Dlen_inbytes,
	const uint8_t  Constant)
{
	uint8_t *State = State_inout;
	size_t Dlen_inblocks = (Dlen_inbytes + RATE_INBYTES - 1) / RATE_INBYTES;
	size_t LastDBlocklen;
	size_t i;

	for (i = 0; i < Dlen_inblocks - 1; i++)
	{
		PHOTON_Permutation(State);
		XOR(State, State, Data_in + i * RATE_INBYTES, RATE_INBYTES);
	}
	PHOTON_Permutation(State);
	LastDBlocklen = Dlen_inbytes - i * RATE_INBYTES;
	XOR(State, State, Data_in + i * RATE_INBYTES, LastDBlocklen);
	if (LastDBlocklen < RATE_INBYTES) State[LastDBlocklen] ^= 0x01; // ozs

	XOR_const(State, Constant);
}

static void ENCorDEC(
	uint8_t *State_inout,
	uint8_t *Data_out,
	const uint8_t *Data_in,
	const uint64_t Dlen_inbytes,
	const uint8_t Constant,
	const uint32_t EncDecInd)
{
	uint8_t *State = State_inout;
	size_t Dlen_inblocks = (Dlen_inbytes + RATE_INBYTES - 1) / RATE_INBYTES;
	size_t LastDBlocklen;
	size_t i;

	for (i = 0; i < Dlen_inblocks - 1; i++)
	{
		PHOTON_Permutation(State);
		rhoohr(State, Data_out + i * RATE_INBYTES, Data_in + i * RATE_INBYTES, RATE_INBYTES, EncDecInd);
	}
	PHOTON_Permutation(State);
	LastDBlocklen = Dlen_inbytes - i * RATE_INBYTES;
	rhoohr(State, Data_out + i * RATE_INBYTES, Data_in + i * RATE_INBYTES, LastDBlocklen, EncDecInd);
	if (LastDBlocklen < RATE_INBYTES) State[LastDBlocklen] ^= 0x01; // ozs

	XOR_const(State, Constant);
}

static void TAG(
	uint8_t *Tag_out,
	uint8_t *State)
{
	size_t i;

	i = TAG_INBYTES;
	while (i > SQUEEZE_RATE_INBYTES)
	{
		PHOTON_Permutation(State);
		memcpy(Tag_out, State, SQUEEZE_RATE_INBYTES);
		Tag_out += SQUEEZE_RATE_INBYTES;
		i -= SQUEEZE_RATE_INBYTES;
	}
	PHOTON_Permutation(State);
	memcpy(Tag_out, State, i);
}

int crypto_aead_encrypt(
	unsigned char *c, unsigned long long *clen,
	const unsigned char *m, unsigned long long mlen,
	const unsigned char *ad, unsigned long long adlen,
	const unsigned char *nsec,
	const unsigned char *npub,
	const unsigned char *k
	)
{
	/*
	...
	... the code for the cipher implementation goes here,
	... generating a ciphertext c[0],c[1],...,c[*clen-1]
	... from a plaintext m[0],m[1],...,m[mlen-1]
	... and associated data ad[0],ad[1],...,ad[adlen-1]
	... and nonce npub[0],npub[1],..
	... and secret key k[0],k[1],...
	... the implementation shall not use nsec
	...
	... return 0;
	*/
	uint8_t *C = c;
	uint8_t *T = c + mlen;
	const uint8_t *M = m;
	const uint8_t *A = ad;
	const uint8_t *N = npub;
	const uint8_t *K = k;

	uint8_t State[STATE_INBYTES] = { 0 };
	uint8_t c0;
	uint8_t c1;

	(void)nsec;

	concatenate(State, N, NOUNCE_INBYTES, K, KEY_INBYTES);

	if ((adlen == 0) && (mlen == 0))
	{
		XOR_const(State, 1);
		TAG(T, State);
		*clen = TAG_INBYTES;
		return 0;
	}

	c0 = selectConst((mlen != 0), ((adlen % RATE_INBYTES) == 0), 1, 2, 3, 4);
	c1 = selectConst((adlen != 0), ((mlen % RATE_INBYTES) == 0), 1, 2, 5, 6);

	if (adlen != 0) HASH(State, A, adlen, c0);
	if ( mlen != 0) ENCorDEC(State, C, M, mlen, c1, ENC);

	TAG(T, State);
	*clen = mlen + TAG_INBYTES;
	return 0;
}

int main() {
    unsigned char c[16];
    unsigned long long clen;
    const unsigned char m[] = {};
    unsigned long long mlen = 0;
    const unsigned char ad[] = {};
    unsigned long long adlen = 0;
    const unsigned char nsec;
    const unsigned char nonce[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
    const unsigned char key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};

    crypto_aead_encrypt(&c, &clen, &m, mlen, &ad, adlen, &nsec, &nonce, &key);

    for (int i = 0; i < sizeof(c); i++) {
    printf("%02X", c[i]);
    }

    return 0;
}

Can anyone help me? I just want to run this code on Arduino.

Copy and post the complete error message using Code Tags.

won't compile using the Arduino IDE because it is standalone, has its own main and no setup() and loop().

so can't reproduce the error. can you post the complete error output?

I'm surprised it works in Code::Blocks, I get the error compiling with the gcc compiler

test.cpp: In function ‘int main()’:
test.cpp:503:25: error: uninitialized const ‘nsec’ [-fpermissive]
     const unsigned char nsec;
                         ^~~~
test.cpp:507:77: error: cannot convert ‘unsigned char (*)[16]’ to ‘unsigned char*’ for argument ‘1’ to ‘int crypto_aead_encrypt(unsigned char*, long long unsigned int*, const unsigned char*, long long unsigned int, const unsigned char*, long long unsigned int, const unsigned char*, const unsigned char*, const unsigned char*)’
     crypto_aead_encrypt(&c, &clen, &m, mlen, &ad, adlen, &nsec, &nonce, &key);

The first argument should be c instead of &c, an array identifier is already a pointer.

There are a couple other '&' to be removed. The line should read:

    crypto_aead_encrypt(c, &clen, m, mlen, ad, adlen, &nsec, nonce, key);

Which fixes that error. But as noted above, there are other problems.

It is not necessary for an Arduino program to have a setup() and loop() function in order to compile.

All that is needed is a main() function declared to return an int. However, this makes writing a working program more difficult than it needs to be

yes.
but it had other issues. looks like it wasn't written to be used with the Arduino IDE

I entirely agree with you, but it was not the lack of setup() and loop() that prevented it compiling

It was

that I was alluding to

1 Like

Definitely not written for an avr processor, compiling for an UNO gives multiple re-definition warnings, but there are other board packages that do not have that problem. Would help to know which board the code is meant for.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.