~increscent/aes-ccm

491531282011a822ff46f9a3389b1d25dbc78a0a — Robert Williams a month ago
initial commit
8 files changed, 489 insertions(+), 0 deletions(-)

A .gitignore
A Makefile
A decrypt.c
A encrypt.c
A lib.c
A lib.h
A tinycrypt
A zencrypt.c
A  => .gitignore +4 -0
@@ 1,4 @@
encrypt
decrypt
zencrypt
*.swp

A  => Makefile +20 -0
@@ 1,20 @@

CC 		= gcc
CFLAGS  = -Wall -Werror -Og -g
LDFLAGS = -lssl -lcrypto -lpthread -lrob

.PHONY: all
all: encrypt decrypt zencrypt

decrypt: decrypt.c lib.c
	$(CC) -o decrypt decrypt.c lib.c $(CFLAGS) $(LDFLAGS)

encrypt: encrypt.c lib.c
	$(CC) -o encrypt encrypt.c lib.c $(CFLAGS) $(LDFLAGS)

zencrypt: zencrypt.c lib.c
	$(CC) -o zencrypt zencrypt.c lib.c tinycrypt/lib/source/*.c -Itinycrypt/lib/include $(CFLAGS) $(LDFLAGS)

.PHONY: clean
clean:
	rm -f encrypt decrypt zencrypt

A  => decrypt.c +83 -0
@@ 1,83 @@

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include "lib.h"

unsigned char KEY[16] = {0xE3, 0xBB, 0x08, 0xF7, 0x9A, 0xCB, 0xF5, 0xEA, 0x14, 0x87, 0x98, 0x0D, 0xBE, 0xF7, 0x8D, 0x49};
//unsigned char IV[13] = {0x01, 0x80, 0x00, 0x01, 0xA5, 0x00, 0x33, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
unsigned char IV[13] = {0x01, 0x80, 0x00, 0x00, 0x53, 0x00, 0x35, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00};
char IV_STR[26] = "01800000530035000100000000";
//unsigned char TAG[8] = {0xA2, 0x69, 0xDC, 0x20, 0x58, 0x38, 0x59, 0xF1};
unsigned char TAG[8] = {0xfa, 0x28, 0x0d, 0x84, 0xeb, 0x5c, 0x25, 0xd0};
//char TAG_STR[16] = "3d34ae2bb1db3e22";
char TAG_STR[16] = "10b0d91559dd4c9c";
//unsigned char CIPHERTEXT[293] = {0xA7, 0x91, 0x55, 0xF3, 0xF9, 0x9D, 0x22, 0x38, 0xB0, 0x7C, 0xB0, 0x49, 0xF9, 0x8E, 0xC3, 0x46, 0xE7, 0x3D, 0x5D, 0x78, 0x7B, 0xE3, 0xA4, 0x6D, 0xE1, 0x30, 0x6E, 0xD2, 0x44, 0xFC, 0xD5, 0xBD, 0x88, 0x06, 0x85, 0x2B, 0x5F, 0xB2, 0x2A, 0xC6, 0x34, 0xF5, 0x14, 0xFA, 0x06, 0x88, 0x1B, 0x64, 0x93, 0x89, 0x83, 0xBE, 0x36, 0x68, 0x58, 0x30, 0x89, 0xF3, 0x66, 0xDB, 0x55, 0x70, 0xA5, 0x7D, 0x89, 0x80, 0x6B, 0xD6, 0xA0, 0x6F, 0x4C, 0x48, 0x5F, 0x4A, 0x41, 0x83, 0xE9, 0xC6, 0x86, 0x31, 0xC3, 0x63, 0xED, 0x5C, 0xA5, 0x6F, 0x4D, 0xBB, 0xD1, 0xD3, 0x20, 0xF8, 0xA7, 0x10, 0x6C, 0x73, 0x48, 0x94, 0xD3, 0x6F, 0xE6, 0xA5, 0x14, 0x5F, 0x0A, 0x42, 0x77, 0x60, 0x39, 0x4A, 0xA2, 0x3C, 0x9D, 0x05, 0x9A, 0xF1, 0xBD, 0xF7, 0xDF, 0xC6, 0x41, 0x3E, 0xDC, 0x7F, 0x29, 0x08, 0xF5, 0x1C, 0xE4, 0x53, 0x7F, 0x7B, 0xE5, 0xC2, 0xFC, 0x2A, 0xEA, 0x2E, 0xCF, 0xEF, 0x99, 0x13, 0x29, 0x31, 0x34, 0x40, 0x53, 0x00, 0xF8, 0xB2, 0x96, 0xA5, 0x7C, 0xEA, 0xC9, 0x73, 0x5C, 0xF0, 0xFB, 0x84, 0xD4, 0x87, 0x3D, 0x53, 0x07, 0x17, 0x61, 0xB0, 0xED, 0x3C, 0x52, 0x8A, 0x07, 0x25, 0x7A, 0x33, 0xF8, 0x32, 0x6D, 0x46, 0xB6, 0xAB, 0x51, 0x84, 0xC4, 0x21, 0x2B, 0x2F, 0x7D, 0x0D, 0x39, 0x12, 0x8C, 0x36, 0x89, 0xB7, 0x66, 0x14, 0x58, 0x69, 0x0B, 0xDC, 0xE8, 0x20, 0x24, 0xC7, 0x8A, 0xAC, 0x76, 0x68, 0xBC, 0x4E, 0xD4, 0x2F, 0x8F, 0x08, 0x6F, 0x81, 0xD7, 0x07, 0x3B, 0x59, 0x10, 0xA5, 0x07, 0xB8, 0xC2, 0x13, 0x76, 0xD0, 0x12, 0x93, 0xE9, 0xD4, 0x3A, 0xB7, 0xFB, 0xE5, 0x3F, 0x1C, 0xF8, 0x46, 0x7E, 0xF3, 0x11, 0x32, 0x63, 0x55, 0xF7, 0xAD, 0x00, 0x18, 0x64, 0x72, 0xB1, 0x87, 0xAD, 0x21, 0xF5, 0x23, 0x9C, 0x79, 0x62, 0xE6, 0xA7, 0xE0, 0x6C, 0x37, 0x17, 0x77, 0x93, 0xFA, 0x7A, 0x45, 0xF6, 0x3E, 0xE1, 0x97, 0xD1, 0x30, 0x59, 0x71, 0x87, 0x68, 0x59, 0x58, 0x3E, 0x93, 0xDC, 0xB8, 0xBB, 0x0F, 0xC2};
unsigned char CIPHERTEXT[293] = {0xc4, 0xef, 0xbe, 0x01, 0x00, 0x01, 0x1a, 0x00, 0x08, 0x00, 0x00, 0xbf, 0x63, 0x6f, 0x66, 0x66, 0x00, 0x64, 0x64, 0x61, 0x74, 0x61, 0x59, 0x01, 0x00, 0x49, 0x4e, 0x46, 0x3a, 0x20, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x09, 0x4a, 0x75, 0x6c, 0x20, 0x32, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x30, 0x3a, 0x30, 0x32, 0x3a, 0x34, 0x33, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x09, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x40, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2e, 0x63, 0x6f, 0x6d, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x3a, 0x09, 0x76, 0x30, 0x2e, 0x31, 0x2d, 0x31, 0x32, 0x39, 0x30, 0x2d, 0x67, 0x61, 0x61, 0x63, 0x30, 0x64, 0x30, 0x32, 0x65, 0x2d, 0x64, 0x69, 0x72, 0x74, 0x79, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x09, 0x54, 0x75, 0x65, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x31, 0x39, 0x20, 0x31, 0x36, 0x3a, 0x31, 0x37, 0x3a, 0x35, 0x39, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x72, 0x63, 0x00, 0x63, 0x6c, 0x65, 0x6e, 0x19, 0x01, 0x00, 0xff};
char CIPHERTEXT_STR[586] = "7ac99054766c4c9887003ac6abeba2d8cab033dbe912d8ea8c5a47087e3926510d7e27b99a3a4c238d8448ecb13134c7213f8fff02de17272253842e566e7446a475835c543811ce23e8ec8e1ae543ec12ac7d8446d8b10e0883e9eef191a81db4c01c2c5fc1b003e437d4654f421b259b8219c2db3864693e708fae34fb7d4e30166f205daf4f144ca8ef993062be4c1887c8af115d23ca8dbcbfaa73a583ea37a304c54f4fe4a8bf37d66d5a68e7cf1b9f8eb523078f1682ec3ea3b459c71252b0f6665276fb1f68e216715dd44973a543ac262de8522e62d65b46fad2b172304acdecd9823eba6829f247bb636e1bb48ccf284056f42ffce7910056bfd144f511eb0ce541eba906e0450b573963ed73055635bdc6ff72fd0460853895eebddd06f9efc9";

int main()
{
    EVP_CIPHER_CTX *ctx;
    int len;
    int plaintext_len;
    int ret;
    unsigned char plaintext[1024];

    hexToBytes(CIPHERTEXT_STR, sizeof(CIPHERTEXT_STR), CIPHERTEXT);
    hexToBytes(TAG_STR, sizeof(TAG_STR), TAG);
    hexToBytes(IV_STR, sizeof(IV_STR), IV);

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors("1");

    /* Initialise the decryption operation. */
    if(1 != EVP_DecryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL))
        handleErrors("2");

    /* Setting IV len to 7. Not strictly necessary as this is the default
     * but shown here for the purposes of this example */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, sizeof(IV), NULL))
        handleErrors("3");

    /* Set expected tag value. */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, sizeof(TAG), TAG))
        handleErrors("4");

    /* Initialise key and IV */
    if(1 != EVP_DecryptInit_ex(ctx, NULL, NULL, KEY, IV))
        handleErrors("5");


    /* Provide the total ciphertext length */
    if(1 != EVP_DecryptUpdate(ctx, NULL, &len, NULL, sizeof(CIPHERTEXT)))
        handleErrors("6");

//    /* Provide any AAD data. This can be called zero or more times as required */
//    if(1 != EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len))
//        handleErrors("7");

    /*
     * Provide the message to be decrypted, and obtain the plaintext output.
     * EVP_DecryptUpdate can be called multiple times if necessary
     */
    ret = EVP_DecryptUpdate(ctx, plaintext, &len, CIPHERTEXT, sizeof(CIPHERTEXT));

    plaintext_len = len;

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    if(ret > 0) {
        printf("Success! Plaintext len: %d\n", plaintext_len);
        printHex(plaintext, plaintext_len);
        /* Success */
        return 0;
    } else {
        printf("Error!\n");
        /* Verify failed */
        return -1;
    }
}

A  => encrypt.c +85 -0
@@ 1,85 @@

#include <stdio.h>
#include <openssl/ssl.h>
#include <openssl/err.h>

#include "lib.h"

unsigned char KEY[16] = {0xE3, 0xBB, 0x08, 0xF7, 0x9A, 0xCB, 0xF5, 0xEA, 0x14, 0x87, 0x98, 0x0D, 0xBE, 0xF7, 0x8D, 0x49};
unsigned char IV[13] = {0};
char IV_STR[26] = "01800000110038000100000000";
//unsigned char TAG[8] = {0xA2, 0x69, 0xDC, 0x20, 0x58, 0x38, 0x59, 0xF1};
//unsigned char PLAINTEXT[293] = {0xA7, 0x91, 0x55, 0xF3, 0xF9, 0x9D, 0x22, 0x38, 0xB0, 0x7C, 0xB0, 0x49, 0xF9, 0x8E, 0xC3, 0x46, 0xE7, 0x3D, 0x5D, 0x78, 0x7B, 0xE3, 0xA4, 0x6D, 0xE1, 0x30, 0x6E, 0xD2, 0x44, 0xFC, 0xD5, 0xBD, 0x88, 0x06, 0x85, 0x2B, 0x5F, 0xB2, 0x2A, 0xC6, 0x34, 0xF5, 0x14, 0xFA, 0x06, 0x88, 0x1B, 0x64, 0x93, 0x89, 0x83, 0xBE, 0x36, 0x68, 0x58, 0x30, 0x89, 0xF3, 0x66, 0xDB, 0x55, 0x70, 0xA5, 0x7D, 0x89, 0x80, 0x6B, 0xD6, 0xA0, 0x6F, 0x4C, 0x48, 0x5F, 0x4A, 0x41, 0x83, 0xE9, 0xC6, 0x86, 0x31, 0xC3, 0x63, 0xED, 0x5C, 0xA5, 0x6F, 0x4D, 0xBB, 0xD1, 0xD3, 0x20, 0xF8, 0xA7, 0x10, 0x6C, 0x73, 0x48, 0x94, 0xD3, 0x6F, 0xE6, 0xA5, 0x14, 0x5F, 0x0A, 0x42, 0x77, 0x60, 0x39, 0x4A, 0xA2, 0x3C, 0x9D, 0x05, 0x9A, 0xF1, 0xBD, 0xF7, 0xDF, 0xC6, 0x41, 0x3E, 0xDC, 0x7F, 0x29, 0x08, 0xF5, 0x1C, 0xE4, 0x53, 0x7F, 0x7B, 0xE5, 0xC2, 0xFC, 0x2A, 0xEA, 0x2E, 0xCF, 0xEF, 0x99, 0x13, 0x29, 0x31, 0x34, 0x40, 0x53, 0x00, 0xF8, 0xB2, 0x96, 0xA5, 0x7C, 0xEA, 0xC9, 0x73, 0x5C, 0xF0, 0xFB, 0x84, 0xD4, 0x87, 0x3D, 0x53, 0x07, 0x17, 0x61, 0xB0, 0xED, 0x3C, 0x52, 0x8A, 0x07, 0x25, 0x7A, 0x33, 0xF8, 0x32, 0x6D, 0x46, 0xB6, 0xAB, 0x51, 0x84, 0xC4, 0x21, 0x2B, 0x2F, 0x7D, 0x0D, 0x39, 0x12, 0x8C, 0x36, 0x89, 0xB7, 0x66, 0x14, 0x58, 0x69, 0x0B, 0xDC, 0xE8, 0x20, 0x24, 0xC7, 0x8A, 0xAC, 0x76, 0x68, 0xBC, 0x4E, 0xD4, 0x2F, 0x8F, 0x08, 0x6F, 0x81, 0xD7, 0x07, 0x3B, 0x59, 0x10, 0xA5, 0x07, 0xB8, 0xC2, 0x13, 0x76, 0xD0, 0x12, 0x93, 0xE9, 0xD4, 0x3A, 0xB7, 0xFB, 0xE5, 0x3F, 0x1C, 0xF8, 0x46, 0x7E, 0xF3, 0x11, 0x32, 0x63, 0x55, 0xF7, 0xAD, 0x00, 0x18, 0x64, 0x72, 0xB1, 0x87, 0xAD, 0x21, 0xF5, 0x23, 0x9C, 0x79, 0x62, 0xE6, 0xA7, 0xE0, 0x6C, 0x37, 0x17, 0x77, 0x93, 0xFA, 0x7A, 0x45, 0xF6, 0x3E, 0xE1, 0x97, 0xD1, 0x30, 0x59, 0x71, 0x87, 0x68, 0x59, 0x58, 0x3E, 0x93, 0xDC, 0xB8, 0xBB, 0x0F, 0xC2};
//unsigned char PLAINTEXT[293] = {0xc4, 0xef, 0xbe, 0x01, 0x00, 0x01, 0x1a, 0x00, 0x08, 0x00, 0x00, 0xbf, 0x63, 0x6f, 0x66, 0x66, 0x00, 0x64, 0x64, 0x61, 0x74, 0x61, 0x59, 0x01, 0x00, 0x49, 0x4e, 0x46, 0x3a, 0x20, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x09, 0x4a, 0x75, 0x6c, 0x20, 0x32, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x09, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x40, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2e, 0x63, 0x6f, 0x6d, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x3a, 0x09, 0x76, 0x30, 0x2e, 0x31, 0x2d, 0x31, 0x32, 0x39, 0x30, 0x2d, 0x67, 0x61, 0x61, 0x63, 0x30, 0x64, 0x30, 0x32, 0x65, 0x2d, 0x64, 0x69, 0x72, 0x74, 0x79, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x09, 0x54, 0x75, 0x65, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x31, 0x39, 0x20, 0x31, 0x36, 0x3a, 0x31, 0x37, 0x3a, 0x35, 0x39, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x72, 0x63, 0x00, 0x63, 0x6c, 0x65, 0x6e, 0x19, 0x01, 0x00, 0xff};
extern unsigned char PLAINTEXT[293];

int main()
{
    EVP_CIPHER_CTX *ctx;

    int len;

    int ciphertext_len;
    unsigned char ciphertext[1024];
    unsigned char tag[8];

    hexToBytes(IV_STR, sizeof(IV_STR), IV);

    /* Create and initialise the context */
    if(!(ctx = EVP_CIPHER_CTX_new()))
        handleErrors("0");

    /* Initialise the encryption operation. */
    if(1 != EVP_EncryptInit_ex(ctx, EVP_aes_128_ccm(), NULL, NULL, NULL))
        handleErrors("1");

    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, 15 - sizeof(IV), NULL))
        handleErrors("2");

    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, sizeof(IV), NULL))
        handleErrors("3");

    /* Set tag length */
    EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, sizeof(tag), NULL);

    /* Initialise key and IV */
    if(1 != EVP_EncryptInit_ex(ctx, NULL, NULL, KEY, IV))
        handleErrors("4");

    /* Provide the total plaintext length */
    if(1 != EVP_EncryptUpdate(ctx, NULL, &len, NULL, sizeof(PLAINTEXT)))
        handleErrors("5");

//    /* Provide any AAD data. This can be called zero or one times as required */
//    if(1 != EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len))
//        handleErrors();

    /*
     * Provide the message to be encrypted, and obtain the encrypted output.
     * EVP_EncryptUpdate can only be called once for this.
     */
    if(1 != EVP_EncryptUpdate(ctx, ciphertext, &len, PLAINTEXT, sizeof(PLAINTEXT)))
        handleErrors("6");
    ciphertext_len = len;

    /*
     * Finalise the encryption. Normally ciphertext bytes may be written at
     * this stage, but this does not occur in CCM mode.
     */
    if(1 != EVP_EncryptFinal_ex(ctx, ciphertext + len, &len))
        handleErrors("7");
    ciphertext_len += len;

    /* Get the tag */
    if(1 != EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, sizeof(tag), tag))
        handleErrors("8");

    /* Clean up */
    EVP_CIPHER_CTX_free(ctx);

    printHex(tag, sizeof(tag));
    printf("len: %d\n", ciphertext_len);
    printHex(ciphertext, ciphertext_len);

    return ciphertext_len;
}

A  => lib.c +31 -0
@@ 1,31 @@

#include <stdio.h>
#include <stdlib.h>

unsigned char PLAINTEXT[293] = {0xc4, 0xef, 0xbe, 0x01, 0x00, 0x01, 0x1a, 0x00, 0x08, 0x00, 0x00, 0xbf, 0x63, 0x6f, 0x66, 0x66, 0x00, 0x64, 0x64, 0x61, 0x74, 0x61, 0x59, 0x01, 0x00, 0x49, 0x4e, 0x46, 0x3a, 0x20, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x09, 0x4a, 0x75, 0x6c, 0x20, 0x32, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x09, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x40, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2e, 0x63, 0x6f, 0x6d, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x3a, 0x09, 0x76, 0x30, 0x2e, 0x31, 0x2d, 0x31, 0x32, 0x39, 0x30, 0x2d, 0x67, 0x61, 0x61, 0x63, 0x30, 0x64, 0x30, 0x32, 0x65, 0x2d, 0x64, 0x69, 0x72, 0x74, 0x79, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x09, 0x54, 0x75, 0x65, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x31, 0x39, 0x20, 0x31, 0x36, 0x3a, 0x31, 0x37, 0x3a, 0x35, 0x39, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x72, 0x63, 0x00, 0x63, 0x6c, 0x65, 0x6e, 0x19, 0x01, 0x00, 0xff};

void handleErrors(const char *str) {
    fprintf(stderr, "Error: %s\n", str);
    exit(1);
}

void printHex(unsigned char *buf, int len) {
    for (int i = 0; i < len; i++) {
        printf("%02x", buf[i]);
    }

    printf("\n");
}

int hexValue(char c) {
    if (c >= '0' && c <= '9') return c - '0';
    if (c >= 'a' && c <= 'f') return c - 'a' + 10;
    if (c >= 'A' && c <= 'F') return c - 'A' + 10;
    return 0;
}

void hexToBytes(char *str, int len, unsigned char *buf) {
    for (int i = 0; i < len; i += 2) {
        buf[i / 2] = (hexValue(str[i]) << 4) | hexValue(str[i + 1]);
    }
}

A  => lib.h +9 -0
@@ 1,9 @@
#ifndef _LIB_H_
#define _LIB_H_

void handleErrors(const char *str);
void printHex(unsigned char *buf, int len);
int hexValue(char c);
void hexToBytes(char *str, int len, unsigned char *buf);

#endif//_LIB_H_

A  => tinycrypt +1 -0
@@ 1,1 @@
Subproject commit 3e9a49d2672ec01435ffbf0d788db6d95ef28de0

A  => zencrypt.c +256 -0
@@ 1,256 @@

#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>

#include <tinycrypt/constants.h>
#include <tinycrypt/hmac_prng.h>
#include <tinycrypt/aes.h>
#include <tinycrypt/utils.h>

#include "lib.h"

unsigned char KEY[16] = {0xE3, 0xBB, 0x08, 0xF7, 0x9A, 0xCB, 0xF5, 0xEA, 0x14, 0x87, 0x98, 0x0D, 0xBE, 0xF7, 0x8D, 0x49};
unsigned char IV[13] = {0};
char IV_STR[26] = "01800000110038000100000000";
//unsigned char PLAINTEXT[293] = {0xc4, 0xef, 0xbe, 0x01, 0x00, 0x01, 0x1a, 0x00, 0x08, 0x00, 0x00, 0xbf, 0x63, 0x6f, 0x66, 0x66, 0x00, 0x64, 0x64, 0x61, 0x74, 0x61, 0x59, 0x01, 0x00, 0x49, 0x4e, 0x46, 0x3a, 0x20, 0x0a, 0x0a, 0x42, 0x75, 0x69, 0x6c, 0x64, 0x20, 0x54, 0x69, 0x6d, 0x65, 0x3a, 0x09, 0x4a, 0x75, 0x6c, 0x20, 0x32, 0x36, 0x20, 0x32, 0x30, 0x32, 0x32, 0x20, 0x31, 0x32, 0x3a, 0x30, 0x30, 0x3a, 0x30, 0x32, 0x0a, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x3a, 0x09, 0x73, 0x74, 0x65, 0x72, 0x6c, 0x69, 0x6e, 0x67, 0x40, 0x70, 0x61, 0x73, 0x73, 0x69, 0x76, 0x65, 0x6c, 0x6f, 0x67, 0x69, 0x63, 0x2e, 0x63, 0x6f, 0x6d, 0x0a, 0x48, 0x61, 0x73, 0x68, 0x3a, 0x09, 0x76, 0x30, 0x2e, 0x31, 0x2d, 0x31, 0x32, 0x39, 0x30, 0x2d, 0x67, 0x61, 0x61, 0x63, 0x30, 0x64, 0x30, 0x32, 0x65, 0x2d, 0x64, 0x69, 0x72, 0x74, 0x79, 0x0a, 0x44, 0x61, 0x74, 0x65, 0x3a, 0x09, 0x54, 0x75, 0x65, 0x20, 0x4a, 0x75, 0x6c, 0x20, 0x31, 0x39, 0x20, 0x31, 0x36, 0x3a, 0x31, 0x37, 0x3a, 0x35, 0x39, 0x20, 0x32, 0x30, 0x32, 0x32, 0x0a, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x72, 0x63, 0x00, 0x63, 0x6c, 0x65, 0x6e, 0x19, 0x01, 0x00, 0xff};
extern unsigned char PLAINTEXT[293];

void sys_put_be16(int val, unsigned char *buf) {
    buf[0] = (val >> 8) & 0xFF;
    buf[1] = val & 0xFF;
}

static inline void xor16(uint8_t *dst, const uint8_t *a, const uint8_t *b)
{
	dst[0] = a[0] ^ b[0];
	dst[1] = a[1] ^ b[1];
	dst[2] = a[2] ^ b[2];
	dst[3] = a[3] ^ b[3];
	dst[4] = a[4] ^ b[4];
	dst[5] = a[5] ^ b[5];
	dst[6] = a[6] ^ b[6];
	dst[7] = a[7] ^ b[7];
	dst[8] = a[8] ^ b[8];
	dst[9] = a[9] ^ b[9];
	dst[10] = a[10] ^ b[10];
	dst[11] = a[11] ^ b[11];
	dst[12] = a[12] ^ b[12];
	dst[13] = a[13] ^ b[13];
	dst[14] = a[14] ^ b[14];
	dst[15] = a[15] ^ b[15];
}

int bt_encrypt_be(const uint8_t key[16], const uint8_t plaintext[16],
		  uint8_t enc_data[16])
{
	struct tc_aes_key_sched_struct s;

//	BT_DBG("key %s", bt_hex(key, 16));
//	BT_DBG("plaintext %s", bt_hex(plaintext, 16));

	if (tc_aes128_set_encrypt_key(&s, key) == TC_CRYPTO_FAIL) {
		return -EINVAL;
	}

	if (tc_aes_encrypt(enc_data, plaintext, &s) == TC_CRYPTO_FAIL) {
		return -EINVAL;
	}

//	BT_DBG("enc_data %s", bt_hex(enc_data, 16));

	return 0;
}

static int ccm_calculate_X0(const uint8_t key[16], const uint8_t *aad, uint8_t aad_len,
			    size_t mic_size, uint8_t msg_len, uint8_t b[16],
			    uint8_t X0[16])
{
	int i, j, err;

	/* X_0 = e(AppKey, flags || nonce || length) */
	b[0] = (((mic_size - 2) / 2) << 3) | ((!!aad_len) << 6) | 0x01;

	sys_put_be16(msg_len, b + 14);

	err = bt_encrypt_be(key, b, X0);
	if (err) {
		return err;
	}

	/* If AAD is being used to authenticate, include it here */
	if (aad_len) {
		sys_put_be16(aad_len, b);

		for (i = 0; i < sizeof(uint16_t); i++) {
			b[i] = X0[i] ^ b[i];
		}

		j = 0;
		aad_len += sizeof(uint16_t);
		while (aad_len > 16) {
			do {
				b[i] = X0[i] ^ aad[j];
				i++, j++;
			} while (i < 16);

			aad_len -= 16;
			i = 0;

			err = bt_encrypt_be(key, b, X0);
			if (err) {
				return err;
			}
		}

		for (; i < aad_len; i++, j++) {
			b[i] = X0[i] ^ aad[j];
		}

		for (i = aad_len; i < 16; i++) {
			b[i] = X0[i];
		}

		err = bt_encrypt_be(key, b, X0);
		if (err) {
			return err;
		}
	}

	return 0;
}

static int ccm_auth(const uint8_t key[16], uint8_t nonce[13],
		    const uint8_t *cleartext_msg, size_t msg_len, const uint8_t *aad,
		    size_t aad_len, uint8_t *mic, size_t mic_size)
{
	uint8_t b[16], Xn[16], s0[16];
	uint16_t blk_cnt, last_blk;
	int err, j, i;

	last_blk = msg_len % 16;
	blk_cnt = (msg_len + 15) / 16;
	if (!last_blk) {
		last_blk = 16U;
	}

	b[0] = 0x01;
	memcpy(b + 1, nonce, 13);

	/* S[0] = e(AppKey, 0x01 || nonce || 0x0000) */
	sys_put_be16(0x0000, &b[14]);

	err = bt_encrypt_be(key, b, s0);
	if (err) {
		return err;
	}

	ccm_calculate_X0(key, aad, aad_len, mic_size, msg_len, b, Xn);

	for (j = 0; j < blk_cnt; j++) {
		/* X_1 = e(AppKey, X_0 ^ Payload[0-15]) */
		if (j + 1 == blk_cnt) {
			for (i = 0; i < last_blk; i++) {
				b[i] = Xn[i] ^ cleartext_msg[(j * 16) + i];
			}

			memcpy(&b[i], &Xn[i], 16 - i);
		} else {
			xor16(b, Xn, &cleartext_msg[j * 16]);
		}

		err = bt_encrypt_be(key, b, Xn);
		if (err) {
			return err;
		}
	}

	/* MIC = C_mic ^ X_1 */
	for (i = 0; i < mic_size; i++) {
		mic[i] = s0[i] ^ Xn[i];
	}

	return 0;
}

static int ccm_crypt(const uint8_t key[16], const uint8_t nonce[13],
		     const uint8_t *in_msg, uint8_t *out_msg, size_t msg_len)
{
	uint8_t a_i[16], s_i[16];
	uint16_t last_blk, blk_cnt;
	size_t i, j;
	int err;

	last_blk = msg_len % 16;
	blk_cnt = (msg_len + 15) / 16;
	if (!last_blk) {
		last_blk = 16U;
	}

	a_i[0] = 0x01;
	memcpy(&a_i[1], nonce, 13);

	for (j = 0; j < blk_cnt; j++) {
		/* S_1 = e(AppKey, 0x01 || nonce || 0x0001) */
		sys_put_be16(j + 1, &a_i[14]);

		err = bt_encrypt_be(key, a_i, s_i);
		if (err) {
			return err;
		}

		/* Encrypted = Payload[0-15] ^ C_1 */
		if (j < blk_cnt - 1) {
			xor16(&out_msg[j * 16], s_i, &in_msg[j * 16]);
		} else {
			for (i = 0; i < last_blk; i++) {
				out_msg[(j * 16) + i] =
					in_msg[(j * 16) + i] ^ s_i[i];
			}
		}
	}
	return 0;
}

int bt_ccm_encrypt(const uint8_t key[16], uint8_t nonce[13],
		   const uint8_t *plaintext, size_t len, const uint8_t *aad,
		   size_t aad_len, uint8_t *enc_data, size_t mic_size)
{
	uint8_t *mic = enc_data + len;

//	BT_DBG("key %s", bt_hex(key, 16));
//	BT_DBG("nonce %s", bt_hex(nonce, 13));
//	BT_DBG("msg (len %zu) %s", len, bt_hex(plaintext, len));
//	BT_DBG("aad_len %zu mic_size %zu", aad_len, mic_size);

	/* Unsupported AAD size */
	if (aad_len >= 0xff00 || mic_size > 16) {
		return -EINVAL;
	}

	ccm_auth(key, nonce, plaintext, len, aad, aad_len, mic, mic_size);

//	BT_INFO("nonce %s", bt_hex(nonce, 13));
//    BT_INFO("mic: %s", bt_hex(mic, mic_size));

	ccm_crypt(key, nonce, plaintext, enc_data, len);

	return 0;
}

int main() {
    uint8_t mic[8];
    uint8_t ciphertext[293 + sizeof(mic)] = {0};

    hexToBytes(IV_STR, sizeof(IV_STR), IV);

    bt_ccm_encrypt(KEY, IV, PLAINTEXT, sizeof(PLAINTEXT), NULL, 0, ciphertext, sizeof(mic));

    memcpy(mic, ciphertext + sizeof(PLAINTEXT), sizeof(mic));

    printHex(mic, sizeof(mic));
    printHex(ciphertext, sizeof(PLAINTEXT));

    return 0;
}