OpenSSL CCM mode

I have had some trouble understanding how the AES CCM mode in OpenSSL works, but I believe I have figured it out.

You will need a key of size 128,192 or 256 bits.

You will need to decide the Tag(MAC) size (valid sizes are: 4, 6, 10, 12, 14 and 16 bytes) with size Tsize.

The Nonce have to be provided (valid sizes: 7, 8, 9, 10, 11, 12, 13 bytes) with Nsize.

P = plain text data of size Plen

A = Additional authenticated data of size Alen

Please note there is no error checking below!

Encryption

EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);

// Initialize the context with the alg only
EVP_EncryptInit(ctx, EVP_aes_128_ccm(), 0, 0);

// Set nonce and tag sizes
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, Nsize, 0);
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, Tsize, 0);

// Finaly set the key and the nonce
EVP_EncryptInit(ctx, 0, K, N);

// Tell the alg we will encrypt Psize bytes
int outl = 0;
EVP_EncryptUpdate(ctx, 0, &outl, 0, Psize);

// Add the AAD
EVP_EncryptUpdate(ctx, 0, &outl, A, Asize);

// Now we encrypt the data in P, placing the output in CT
EVP_EncryptUpdate(ctx, CT, &outl, P, Psize);

// I am not sure this is necessary
EVP_EncryptFinal(ctx, &CT[outl], &outl);

// Append the tag to the end of the encrypted output
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, Tsize, &CT[Psize]);

Decryption
EVP_CIPHER_CTX* ctx = EVP_CIPHER_CTX_new();
EVP_CIPHER_CTX_init(ctx);

// Just set the alg
EVP_DecryptInit(ctx, EVP_aes_128_ccm(), 0, 0);

// Set nonce size
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, Nsize, 0);

// Set the tag from the end of the encrypted array
EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, Tsize, C + Psize);

// Set key and nonce
EVP_DecryptInit(ctx, 0, K, N);

int outl = 0;
// We will encrypt Psize bytes
EVP_DecryptUpdate(ctx, 0, &outl, 0, Psize);

// Add AAD for verification
EVP_DecryptUpdate(ctx, 0, &outl, A, Asize);

// Time to decrypt the data into D
EVP_DecryptUpdate(ctx, D, &outl, C, Psize);

// Not sure if this is needed
EVP_DecryptFinal(ctx, &D[outl], &outl);