Initialize a CCM state @param ccm The CCM state to initialize @param cipher The index of the cipher to use @param key The secret key @param keylen The length of the secret key @param ptlen The length of the plain/cipher text that will be processed @param taglen The max length of the MAC tag @param aadlen The length of the AAD @return CRYPT_OK on success */
| 23 | @return CRYPT_OK on success |
| 24 | */ |
| 25 | int ccm_init(ccm_state *ccm, int cipher, |
| 26 | const unsigned char *key, int keylen, int ptlen, int taglen, int aadlen) |
| 27 | { |
| 28 | int err; |
| 29 | |
| 30 | LTC_ARGCHK(ccm != NULL); |
| 31 | LTC_ARGCHK(key != NULL); |
| 32 | LTC_ARGCHK(taglen != 0); |
| 33 | |
| 34 | XMEMSET(ccm, 0, sizeof(ccm_state)); |
| 35 | |
| 36 | /* check cipher input */ |
| 37 | if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { |
| 38 | return err; |
| 39 | } |
| 40 | if (cipher_descriptor[cipher].block_length != 16) { |
| 41 | return CRYPT_INVALID_CIPHER; |
| 42 | } |
| 43 | |
| 44 | /* make sure the taglen is even and <= 16 */ |
| 45 | ccm->taglen = taglen; |
| 46 | ccm->taglen &= ~1; |
| 47 | if (ccm->taglen > 16) { |
| 48 | ccm->taglen = 16; |
| 49 | } |
| 50 | |
| 51 | /* can't use < 4 */ |
| 52 | if (ccm->taglen < 4) { |
| 53 | return CRYPT_INVALID_ARG; |
| 54 | } |
| 55 | |
| 56 | /* schedule key */ |
| 57 | if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, &ccm->K)) != CRYPT_OK) { |
| 58 | return err; |
| 59 | } |
| 60 | ccm->cipher = cipher; |
| 61 | |
| 62 | /* let's get the L value */ |
| 63 | ccm->ptlen = ptlen; |
| 64 | ccm->L = 0; |
| 65 | while (ptlen) { |
| 66 | ++ccm->L; |
| 67 | ptlen >>= 8; |
| 68 | } |
| 69 | if (ccm->L <= 1) { |
| 70 | ccm->L = 2; |
| 71 | } |
| 72 | |
| 73 | ccm->aadlen = aadlen; |
| 74 | return CRYPT_OK; |
| 75 | } |
| 76 | |
| 77 | #endif |
| 78 |