On 5 March 2013 14:13, Dr. Stephen Henson <st...@openssl.org> wrote: > On Tue, Mar 05, 2013, Leon Brits wrote: > > > Just want to add that I do set the data sizes before EncryptUpdate and > > DecryptUpdate and mentioned in the CCM section of the OpenSSL support > page. > > This page does answer both my questions (appologies), but I still fail to > > decrypt. > > > > I'll add an example for CCM mode in the demos section shortly. CCM mode is > a > bit picky about setting all the parameters correctly in the correct order. >
That would be good!! I am working on some test code myself but cannot get it to work. See source code below. This is adapted from some code I have for GCM that works fine. With CCM though encryption (apparently) works fine, but when I get to decryption I get a 0 response from the final EVP_DecryptUpdate call - no error message on the OpenSSL error stack :-( Happy for you to use this for your demo code - if you can tell me how to fix it!! :-) Any clues? Thanks Matt int encryptccm(unsigned char *plaintext, int plaintext_len, unsigned char *aad, int aad_len, unsigned char *key, unsigned char *iv, unsigned char *ciphertext, unsigned char *tag) { EVP_CIPHER_CTX *ctx; int len; int ciphertext_len; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the encryption operation. */ if(!EVP_EncryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL)) handleErrors(); /* Setting IV len to 7. Not strictly necessary as this is the default * but shown here for the purposes of this example */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL)) handleErrors(); /* Initialise key and IV */ if(!EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Provide the total plaintext length */ if(!EVP_EncryptUpdate(ctx, NULL, &len, NULL, plaintext_len)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ if(!EVP_EncryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); /* Provide the message to be encrypted, and obtain the encrypted output. * EVP_EncryptUpdate can be called multiple times if necessary */ if(!EVP_EncryptUpdate(ctx, ciphertext, &len, plaintext, plaintext_len)) handleErrors(); ciphertext_len = len; /* Finalise the encryption. Normally ciphertext bytes may be written at * this stage, but this does not occur in GCM mode */ if(!EVP_EncryptFinal_ex(ctx, ciphertext + len, &len)) handleErrors(); ciphertext_len += len; /* Get the tag */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_GET_TAG, 14, tag)) handleErrors(); /* Clean up */ EVP_CIPHER_CTX_free(ctx); return ciphertext_len; } int decryptccm(unsigned char *ciphertext, int ciphertext_len, unsigned char *aad, int aad_len, unsigned char *tag, unsigned char *key, unsigned char *iv, unsigned char *plaintext) { EVP_CIPHER_CTX *ctx; int len; int plaintext_len; int ret; /* Create and initialise the context */ if(!(ctx = EVP_CIPHER_CTX_new())) handleErrors(); /* Initialise the decryption operation. */ if(!EVP_DecryptInit_ex(ctx, EVP_aes_256_ccm(), NULL, NULL, NULL)) handleErrors(); /* Setting IV len to 7. Not strictly necessary as this is the default * but shown here for the purposes of this example */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_IVLEN, 7, NULL)) handleErrors(); /* Initialise key and IV */ if(!EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv)) handleErrors(); /* Set expected tag value. Works in OpenSSL 1.0.1d and later */ if(!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_TAG, 14, tag)) handleErrors(); /* Provide the total ciphertext length */ if(!EVP_DecryptUpdate(ctx, NULL, &len, NULL, ciphertext_len)) handleErrors(); /* Provide any AAD data. This can be called zero or more times as * required */ if(!EVP_DecryptUpdate(ctx, NULL, &len, aad, aad_len)) handleErrors(); /* Provide the message to be decrypted, and obtain the plaintext output. * EVP_DecryptUpdate can be called multiple times if necessary */ if(!(ret = EVP_DecryptUpdate(ctx, plaintext, &len, ciphertext, ciphertext_len))) handleErrors(); plaintext_len = len; /* Finalise the decryption. A positive return value indicates success, * anything else is a failure - the plaintext is not trustworthy. */ ret = EVP_DecryptFinal_ex(ctx, plaintext + len, &len); /* Clean up */ EVP_CIPHER_CTX_free(ctx); if(ret > 0) { /* Success */ plaintext_len += len; return plaintext_len; } else { /* Verify failed */ return -1; } }