I need to be compatible with Solaris crypto mech SUN_CKM_AES_CCM. In Linux, I believe I should setup an AEAD request to get "ccm(aes)" mech. Documentation for Linux Crypto does seem rather poor, the best example appears to be tcrypt.c test, and kernel sources.
From Solaris, I did a test encryption of a 512 byte block, with 16 byte hmac, and 12 byte iv. This needs to stay the same, and hopefully the results be identical.
However, what I think should would work, does not;
struct crypto_aead *tfm = NULL;
struct aead_request *req;
unsigned char key[16] = {
0x5c, 0x95, 0x64, 0x42, 0x00, 0x82, 0x1c, 0x9e,
0xd4, 0xac, 0x01, 0x83, 0xc4, 0x9c, 0x14, 0x97
};
unsigned int ivsize;
int ret;
struct scatterlist plaintext[1];
struct scatterlist ciphertext[1];
struct scatterlist hmactext[1];
unsigned char *plaindata = NULL;
unsigned char *cipherdata = NULL;
unsigned char *hmacdata = NULL;
unsigned char *ivp = NULL;
int i;
unsigned char d;
struct tcrypt_result result;
tfm = crypto_alloc_aead("ccm(aes)", 0, 0);
init_completion(&result.completion);
req = aead_request_alloc(tfm, GFP_KERNEL);
aead_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
cipher_work_done, &result);
crypto_aead_clear_flags(tfm, ~0);
ret = crypto_aead_setkey(tfm, key, sizeof(key));
ret = crypto_aead_setauthsize(tfm, 16); // authsize is hmac?
ivsize = crypto_aead_ivsize(tfm);
if (ivsize != 12) {
printk("ivsize is not 12 %d - this needs to be fixed\n", ivsize);
}
plaindata = kmalloc(512, GFP_KERNEL);
cipherdata = kmalloc(512, GFP_KERNEL);
hmacdata = kmalloc(16, GFP_KERNEL);
ivp = kmalloc(ivsize, GFP_KERNEL);
if (!plaindata || !cipherdata || !hmacdata || !ivp) goto out;
// put 00 01 02 03 ... in the input buffer...
for (i = 0, d = 0; i < 512; i++, d++)
plaindata[i] = d;
memset(cipherdata, 0, 512);
memset(hmacdata, 0, 16);
memset(ivp, 0, ivsize);
// Put a8 a9 aa .... in iv
for (i = 0,d=0xa8; i < 12; i++, d++)
ivp[i] = d;
sg_init_one(&plaintext[0], plaindata, 512);
sg_init_one(&ciphertext[0], cipherdata, 512);
sg_init_one(&hmactext[0], hmacdata, 16);
aead_request_set_crypt(req, plaintext, ciphertext, 512, ivp);
aead_request_set_assoc(req, hmactext, 16);
ret = crypto_aead_encrypt(req);
printk("cipher call returns %d \n", ret);
And what we get back is that ivsize is 16 (and I see no way to set it to 12), and that encrypt fails with "-22" or EINVAL. There are lots of errors checking in the code, removed here, that confirm all prior call return success.
As far as I can tell, I follow the tcrypt.c sources pretty close. However, I wonder if the forced ivsize = 16
will mean I can not use the supplied algorithm anyway. That aside, it would be nice to see the encrypt call succeed and what is put in the cipherdata output.
The code is put into a kernel module, and run at _init() time. Initially I used blkcipher "aes", which works, but is not the ccm-aes variant. This made me change to use aead, which I can not get to work.