1f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* LibTomCrypt, modular cryptographic library -- Tom St Denis 2f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 3f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * LibTomCrypt is a library that provides various cryptographic 4f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * algorithms in a highly modular and flexible manner. 5f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 6f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * The library is free for all purposes without any express 7f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * guarantee it works. 8f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * 9f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com 10f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project */ 11f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#include "tomcrypt.h" 12f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 13f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 14f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @file ccm_memory.c 15f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CCM support, process a block of memory, Tom St Denis 16f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 17f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 18f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef CCM_MODE 19f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 20f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/** 21f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CCM encrypt/decrypt and produce an authentication tag 22f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param cipher The index of the cipher desired 23f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param key The secret key to use 24f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param keylen The length of the secret key (octets) 25f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param uskey A previously scheduled key [optional can be NULL] 26f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param nonce The session nonce [use once] 27f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param noncelen The length of the nonce 28f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param header The header for the session 29f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param headerlen The length of the header (octets) 30f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param pt [out] The plaintext 31f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param ptlen The length of the plaintext (octets) 32f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param ct [out] The ciphertext 33f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param tag [out] The destination tag 34f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param taglen [in/out] The max size and resulting size of the authentication tag 35f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @param direction Encrypt or Decrypt direction (0 or 1) 36f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project @return CRYPT_OK if successful 37f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project*/ 38f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projectint ccm_memory(int cipher, 39f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *key, unsigned long keylen, 40f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project symmetric_key *uskey, 41f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *nonce, unsigned long noncelen, 42f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project const unsigned char *header, unsigned long headerlen, 43f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *pt, unsigned long ptlen, 44f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *ct, 45f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char *tag, unsigned long *taglen, 46f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int direction) 47f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project{ 48f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned char PAD[16], ctr[16], CTRPAD[16], b; 49f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project symmetric_key *skey; 50f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project int err; 51f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project unsigned long len, L, x, y, z, CTRlen; 52f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 53f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (uskey == NULL) { 54f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(key != NULL); 55f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 56f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(nonce != NULL); 57f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (headerlen > 0) { 58f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(header != NULL); 59f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 60f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(pt != NULL); 61f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(ct != NULL); 62f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(tag != NULL); 63f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project LTC_ARGCHK(taglen != NULL); 64f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 65f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_FAST 66f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (16 % sizeof(LTC_FAST_TYPE)) { 67f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_ARG; 68f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 69f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 70f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 71f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* check cipher input */ 72f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_is_valid(cipher)) != CRYPT_OK) { 73f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 74f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 75f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cipher_descriptor[cipher].block_length != 16) { 76f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_CIPHER; 77f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 78f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 79f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* make sure the taglen is even and <= 16 */ 80f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *taglen &= ~1; 81f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*taglen > 16) { 82f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *taglen = 16; 83f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 84f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 85f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* can't use < 4 */ 86f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (*taglen < 4) { 87f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_INVALID_ARG; 88f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 89f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 90f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* is there an accelerator? */ 91f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (cipher_descriptor[cipher].accel_ccm_memory != NULL) { 92f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return cipher_descriptor[cipher].accel_ccm_memory( 93f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project key, keylen, 94f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project uskey, 95f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project nonce, noncelen, 96f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project header, headerlen, 97f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt, ptlen, 98f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct, 99f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tag, taglen, 100f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project direction); 101f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 102f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 103f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* let's get the L value */ 104f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = ptlen; 105f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project L = 0; 106f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (len) { 107f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ++L; 108f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len >>= 8; 109f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 110f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (L <= 1) { 111f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project L = 2; 112f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 113f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 114f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* increase L to match the nonce len */ 115f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project noncelen = (noncelen > 13) ? 13 : noncelen; 116f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((15 - noncelen) > L) { 117f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project L = 15 - noncelen; 118f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 119f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 120f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* decrease noncelen to match L */ 121f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((noncelen + L) > 15) { 122f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project noncelen = 15 - L; 123f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 124f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 125f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* allocate mem for the symmetric key */ 126f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (uskey == NULL) { 127f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project skey = XMALLOC(sizeof(*skey)); 128f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (skey == NULL) { 129f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return CRYPT_MEM; 130f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 131f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 132f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* initialize the cipher */ 133f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].setup(key, keylen, 0, skey)) != CRYPT_OK) { 134f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(skey); 135f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 136f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 137f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 138f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project skey = uskey; 139f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 140f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 141f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* form B_0 == flags | Nonce N | l(m) */ 142f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 143f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] = (unsigned char)(((headerlen > 0) ? (1<<6) : 0) | 144f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (((*taglen - 2)>>1)<<3) | 145f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project (L-1)); 146f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 147f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* nonce */ 148f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < (16 - (L + 1)); y++) { 149f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] = nonce[y]; 150f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 151f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 152f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store len */ 153f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len = ptlen; 154f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 155f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* shift len so the upper bytes of len are the contents of the length */ 156f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = L; y < 4; y++) { 157f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len <<= 8; 158f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 159f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 160f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store l(m) (only store 32-bits) */ 161f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; L > 4 && (L-y)>4; y++) { 162f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] = 0; 163f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 164f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; y < L; y++) { 165f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] = (unsigned char)((len >> 24) & 255); 166f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project len <<= 8; 167f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 168f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 169f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* encrypt PAD */ 170f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 171f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 172f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 173f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 174f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* handle header */ 175f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (headerlen > 0) { 176f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 177f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 178f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store length */ 179f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (headerlen < ((1UL<<16) - (1UL<<8))) { 180f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= (headerlen>>8) & 255; 181f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= headerlen & 255; 182f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 183f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= 0xFF; 184f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= 0xFE; 185f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= (headerlen>>24) & 255; 186f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= (headerlen>>16) & 255; 187f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= (headerlen>>8) & 255; 188f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= headerlen & 255; 189f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 190f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 191f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now add the data */ 192f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < headerlen; y++) { 193f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x == 16) { 194f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* full block so let's encrypt it */ 195f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 196f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 197f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 198f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 199f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 200f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= header[y]; 201f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 202f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 203f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* remainder? */ 204f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x != 0) { 205f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 206f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 207f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 208f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 209f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 210f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 211f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* setup the ctr counter */ 212f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 213f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 214f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* flags */ 215f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[x++] = (unsigned char)L-1; 216f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 217f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* nonce */ 218f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 0; y < (16 - (L+1)); ++y) { 219f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[x++] = nonce[y]; 220f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 221f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* offset */ 222f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project while (x < 16) { 223f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[x++] = 0; 224f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 225f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 226f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 227f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CTRlen = 16; 228f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 229f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* now handle the PT */ 230f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ptlen > 0) { 231f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project y = 0; 232f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_FAST 233f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ptlen & ~15) { 234f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (direction == CCM_ENCRYPT) { 235f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; y < (ptlen & ~15); y += 16) { 236f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* increment the ctr? */ 237f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (z = 15; z > 15-L; z--) { 238f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[z] = (ctr[z] + 1) & 255; 239f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ctr[z]) break; 240f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 241f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { 242f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 243f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 244f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 245f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* xor the PT against the pad first */ 246f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { 247f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); 248f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *((LTC_FAST_TYPE*)(&ct[y+z])) = *((LTC_FAST_TYPE*)(&pt[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); 249f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 250f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 251f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 252f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 253f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 254f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 255f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; y < (ptlen & ~15); y += 16) { 256f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* increment the ctr? */ 257f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (z = 15; z > 15-L; z--) { 258f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[z] = (ctr[z] + 1) & 255; 259f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ctr[z]) break; 260f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 261f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { 262f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 263f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 264f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 265f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* xor the PT against the pad last */ 266f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (z = 0; z < 16; z += sizeof(LTC_FAST_TYPE)) { 267f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *((LTC_FAST_TYPE*)(&pt[y+z])) = *((LTC_FAST_TYPE*)(&ct[y+z])) ^ *((LTC_FAST_TYPE*)(&CTRPAD[z])); 268f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *((LTC_FAST_TYPE*)(&PAD[z])) ^= *((LTC_FAST_TYPE*)(&pt[y+z])); 269f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 270f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 271f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 272f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 273f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 274f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 275f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 276f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 277f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 278f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (; y < ptlen; y++) { 279f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* increment the ctr? */ 280f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (CTRlen == 16) { 281f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (z = 15; z > 15-L; z--) { 282f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[z] = (ctr[z] + 1) & 255; 283f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (ctr[z]) break; 284f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 285f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { 286f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 287f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 288f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project CTRlen = 0; 289f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 290f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 291f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* if we encrypt we add the bytes to the MAC first */ 292f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (direction == CCM_ENCRYPT) { 293f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project b = pt[y]; 294f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ct[y] = b ^ CTRPAD[CTRlen++]; 295f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } else { 296f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project b = ct[y] ^ CTRPAD[CTRlen++]; 297f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project pt[y] = b; 298f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 299f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 300f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x == 16) { 301f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 302f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 303f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 304f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project x = 0; 305f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 306f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project PAD[x++] ^= b; 307f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 308f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 309f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (x != 0) { 310f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(PAD, PAD, skey)) != CRYPT_OK) { 311f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 312f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 313f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 314f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 315f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 316f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* setup CTR for the TAG (zero the count) */ 317f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (y = 15; y > 15 - L; y--) { 318f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project ctr[y] = 0x00; 319f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 320f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if ((err = cipher_descriptor[cipher].ecb_encrypt(ctr, CTRPAD, skey)) != CRYPT_OK) { 321f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project goto error; 322f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 323f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 324f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (skey != uskey) { 325f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project cipher_descriptor[cipher].done(skey); 326f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 327f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 328f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project /* store the TAG */ 329f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project for (x = 0; x < 16 && x < *taglen; x++) { 330f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project tag[x] = PAD[x] ^ CTRPAD[x]; 331f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 332f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project *taglen = x; 333f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 334f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#ifdef LTC_CLEAN_STACK 335f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(skey, sizeof(*skey)); 336f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(PAD, sizeof(PAD)); 337f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project zeromem(CTRPAD, sizeof(CTRPAD)); 338f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 339f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Projecterror: 340f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project if (skey != uskey) { 341f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project XFREE(skey); 342f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project } 343f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 344f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project return err; 345f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project} 346f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 347f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project#endif 348f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project 349f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Source: /cvs/libtom/libtomcrypt/src/encauth/ccm/ccm_memory.c,v $ */ 350f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Revision: 1.18 $ */ 351f7fc46c63fdc8f39234fea409b8dbe116d73ebf8The Android Open Source Project/* $Date: 2006/12/04 21:34:03 $ */ 352