As you said you are OK with a little bit less security in the more performant algorithm, I suggest Speck for that. It was developed by the NSA, so although some might worry about a backdoor (I personally doubt there is one though I would not know the difference if there were), it probably also means that ordinary people will not break it easily if at all. Indeed it has been out 2 years and has been analyzed but not broken. It comes in a variety of key and block sizes. I actually have C++ code (maybe not the most optimized, but it does pass test vectors) for 32/64 (block size 32, key size 64) and for 128/128. Will post both in this answer. They are very fast and small.
32/64
#include "Speck.h"
#include <iostream>
#include <stdint.h>
using namespace std;
#define M 4
#define NUMBER_OF_ROUNDS 22
#define BIG_BIT_SHIFT 7
#define SMALL_BIT_SHIFT 2
#define ROR(x, r) ((x >> r) | (x << (16 - r)))
#define ROL(x, r) ((x << r) | (x >> (16 - r)))
#define R(x, y, k) (x = ROR(x, BIG_BIT_SHIFT), x += y, x ^= k, y = ROL(y, SMALL_BIT_SHIFT), y ^= x)
#define UNR(x, y, k) (y ^= x,y = ROR(y, SMALL_BIT_SHIFT),x ^= k,x -= y,x = ROL(x, BIG_BIT_SHIFT))
void Speck_32_64::generateRoundKeys(uint16_t *K, uint16_t *RK)
{
uint16_t keyChunks[M];
keyChunks[0] = K[0];
keyChunks[1] = K[1];
keyChunks[2] = K[2];
keyChunks[3] = K[3];
uint64_t i;
uint16_t indexer = 0;
for (i = 0; i < NUMBER_OF_ROUNDS; i++)
{
RK[i] = keyChunks[0];
indexer = 1 + i % (M-1);
R(keyChunks[indexer], keyChunks[0], i);
}
}
void Speck_32_64::encrypt(uint16_t *pt, uint16_t *ct, uint16_t *K)
{
uint64_t i, B = K[1], A = K[0];
ct[0] = pt[0]; ct[1] = pt[1];
uint16_t RK[NUMBER_OF_ROUNDS];
generateRoundKeys(K, RK);
for (i = 0; i < NUMBER_OF_ROUNDS; i++)
{
R(ct[1], ct[0], RK[i]);
}
}
void Speck_32_64::decrypt(uint16_t *pt, uint16_t *ct, uint16_t *K)
{
uint64_t i, B = K[1], A = K[0];
pt[0] = ct[0]; pt[1] = ct[1];
uint16_t RK[NUMBER_OF_ROUNDS];
generateRoundKeys(K, RK);
for (i = NUMBER_OF_ROUNDS; i > 0; i--)
{
UNR(pt[1], pt[0], RK[i - 1]);
}
}
128/128
#include "Speck.h"
#include <iostream>
#include <stdint.h>
using namespace std;
#define ROR(x, r) ((x >> r) | (x << (64 - r)))
#define ROL(x, r) ((x << r) | (x >> (64 - r)))
#define R(x, y, k) (x = ROR(x, 8), x += y, x ^= k, y = ROL(y, 3), y ^= x)
#define UNR(x, y, k) (y ^= x,y = ROR(y, 3),x ^= k,x -= y,x = ROL(x, 8))
void Speck_128_128::generateRoundKeys(uint64_t *K, uint64_t *RK)
{
uint64_t i, B = K[1], A = K[0];
for (i = 0; i < 32; i++)
{
RK[i] = A;
R(B, A, i);
}
}
void Speck_128_128::encrypt(uint64_t *pt, uint64_t *ct, uint64_t *K)
{
uint64_t i, B = K[1], A = K[0];
ct[0] = pt[0]; ct[1] = pt[1];
uint64_t RK[32];
generateRoundKeys(K, RK);
for (i = 0; i < 32; i++)
{
R(ct[1], ct[0], RK[i]);
}
}
void Speck_128_128::decrypt(uint64_t *pt, uint64_t *ct, uint64_t *K)
{
uint64_t i, B = K[1], A = K[0];
pt[0] = ct[0]; pt[1] = ct[1];
uint64_t RK[32];
generateRoundKeys(K, RK);
for (i = 32; i > 0; i--)
{
UNR(pt[1], pt[0], RK[i - 1]);
}
}