/* AES-CTR mode encryption/decryption algorithm * - max data_len is (AES_BLOCK_SZ * 2^16) * - nonce must be AES_BLOCK_SZ bytes * - assumes nonce is ready to use as-is (i.e. any * encryption/randomization of nonce/IV is handled by the caller) * - ptxt and ctxt can point to the same location * - returns -1 on error */ int BCMROMFN(aes_ctr_crypt)(unsigned int *rk, const size_t key_len, const uint8 *nonce, const size_t data_len, const uint8 *ptxt, uint8 *ctxt) { size_t k; uint8 tmp[AES_BLOCK_SZ], ctr[AES_BLOCK_SZ]; if (data_len > (AES_BLOCK_SZ * AES_CTR_MAXBLOCKS)) return (-1); memcpy(ctr, nonce, AES_BLOCK_SZ); for (k = 0; k < (data_len / AES_BLOCK_SZ); k++) { aes_block_encrypt((int)AES_ROUNDS(key_len), rk, ctr, tmp); xor_128bit_block(ptxt, tmp, ctxt); ctr[AES_BLOCK_SZ-1]++; if (!ctr[AES_BLOCK_SZ - 1]) ctr[AES_BLOCK_SZ - 2]++; ptxt += AES_BLOCK_SZ; ctxt += AES_BLOCK_SZ; } /* handle partial block */ if (data_len % AES_BLOCK_SZ) { aes_block_encrypt((int)AES_ROUNDS(key_len), rk, ctr, tmp); for (k = 0; k < (data_len % AES_BLOCK_SZ); k++) ctxt[k] = ptxt[k] ^ tmp[k]; } return (0); }
int BCMROMFN(aes_cbc_encrypt_pad)(uint32 *rk, const size_t key_len, const uint8 *nonce, const size_t data_len, const uint8 *ptxt, uint8 *ctxt, uint8 padd_type) { uint8 tmp[AES_BLOCK_SZ]; uint32 encrypt_len = 0; uint32 j; /* First block get XORed with nonce/IV */ const unsigned char *iv = nonce; unsigned char *crypt_data = ctxt; const unsigned char *plain_data = ptxt; uint32 remaining = (uint32)data_len; while (remaining >= AES_BLOCK_SZ) { xor_128bit_block(iv, plain_data, tmp); aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, crypt_data); remaining -= AES_BLOCK_SZ; iv = crypt_data; crypt_data += AES_BLOCK_SZ; plain_data += AES_BLOCK_SZ; encrypt_len += AES_BLOCK_SZ; } if (padd_type == NO_PADDING) return encrypt_len; if (remaining) { for (j = 0; j < remaining; j++) { tmp[j] = plain_data[j] ^ iv[j]; } } switch (padd_type) { case PAD_LEN_PADDING: for (j = remaining; j < AES_BLOCK_SZ; j++) { tmp[j] = (AES_BLOCK_SZ - remaining) ^ iv[j]; } break; default: return -1; } aes_block_encrypt((int)AES_ROUNDS(key_len), rk, tmp, crypt_data); encrypt_len += AES_BLOCK_SZ; return (encrypt_len); }
bool enc_buffer(void * buffer, size_t real_len, size_t total_len, int cipher_num) { if(real_len > total_len || buffer == NULL) return false; if(total_len % 16 != 0) return false; if(!xor_fibonacci_crypt(buffer, real_len, cipher_num)) { return false; } if(!aes_block_encrypt(buffer,total_len)) { return false; } return true; }
int BCMROMFN(aes_ccm_mac)(unsigned int *rk, const size_t key_len, const uint8 *nonce, const size_t aad_len, const uint8 *aad, const size_t data_len, const uint8 *ptxt, uint8 *mac) { uint8 B_0[AES_BLOCK_SZ], X[AES_BLOCK_SZ]; size_t j, k; if (aad_len > AES_CCM_AAD_MAX_LEN) return (-1); pres("aes_ccm_mac: nonce:", AES_CCM_NONCE_LEN, nonce); pres("aes_ccm_mac: aad:", aad_len, aad); pres("aes_ccm_mac: input:", data_len, ptxt); /* B_0 = Flags || Nonce || l(m) */ B_0[0] = AES_CCM_AUTH_FLAGS; if (aad_len) B_0[0] |= AES_CCM_AUTH_AAD_FLAG; memcpy(&B_0[1], nonce, AES_CCM_NONCE_LEN); B_0[AES_BLOCK_SZ - 2] = (uint8)(data_len >> 8) & 0xff; B_0[AES_BLOCK_SZ - 1] = (uint8)(data_len & 0xff); /* X_1 := E( K, B_0 ) */ pres("aes_ccm_mac: CBC IV in:", AES_BLOCK_SZ, B_0); aes_block_encrypt((int)AES_ROUNDS(key_len), rk, B_0, X); pres("aes_ccm_mac: CBC IV out:", AES_BLOCK_SZ, X); /* X_i + 1 := E( K, X_i XOR B_i ) for i = 1, ..., n */ /* first the AAD */ if (aad_len) { pres("aes_ccm_mac: aad:", aad_len, aad); X[0] ^= (aad_len >> 8) & 0xff; X[1] ^= aad_len & 0xff; k = 2; j = aad_len; while (j--) { X[k] ^= *aad++; k++; if (k == AES_BLOCK_SZ) { pres("aes_ccm_mac: After xor (full block aad):", AES_BLOCK_SZ, X); aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); pres("aes_ccm_mac: After AES (full block aad):", AES_BLOCK_SZ, X); k = 0; } } /* handle partial last block */ if (k % AES_BLOCK_SZ) { pres("aes_ccm_mac: After xor (partial block aad):", AES_BLOCK_SZ, X); aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); pres("aes_ccm_mac: After AES (partial block aad):", AES_BLOCK_SZ, X); } } /* then the message data */ for (k = 0; k < (data_len / AES_BLOCK_SZ); k++) { xor_128bit_block(X, ptxt, X); pres("aes_ccm_mac: After xor (full block data):", AES_BLOCK_SZ, X); ptxt += AES_BLOCK_SZ; aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); pres("aes_ccm_mac: After AES (full block data):", AES_BLOCK_SZ, X); } /* last block may be partial, padding is implicit in this xor */ for (k = 0; k < (data_len % AES_BLOCK_SZ); k++) X[k] ^= *ptxt++; if (data_len % AES_BLOCK_SZ) { pres("aes_ccm_mac: After xor (final block data):", AES_BLOCK_SZ, X); aes_block_encrypt((int)AES_ROUNDS(key_len), rk, X, X); pres("aes_ccm_mac: After AES (final block data):", AES_BLOCK_SZ, X); } /* T := first-M-bytes( X_n+1 ) */ memcpy(mac, X, AES_CCM_AUTH_LEN); pres("aes_ccm_mac: MAC:", AES_CCM_AUTH_LEN, mac); return (0); }
/* aes_wrap: perform AES-based keywrap function defined in RFC3394 * return 0 on success, 1 on error * input is il bytes * output is (il+8) bytes */ int BCMROMFN(aes_wrap)(size_t kl, uint8 *key, size_t il, uint8 *input, uint8 *output) { uint32 rk[4*(AES_MAXROUNDS+1)]; uint8 A[AES_BLOCK_SZ]; uint8 R[AKW_MAX_WRAP_LEN]; uint8 B[AES_BLOCK_SZ]; int n = (int)(il/AKW_BLOCK_LEN), i, j, k; /* validate kl (must be valid AES key length) */ if ((kl != 16) && (kl != 24) && (kl != 32)) { dbg(("aes_wrap: invlaid key length %lu\n", (unsigned long)kl)); return (1); } if (il > AKW_MAX_WRAP_LEN) { dbg(("aes_wrap: input length %lu too large\n", (unsigned long)il)); return (1); } if (il % AKW_BLOCK_LEN) { dbg(("aes_wrap: input length %lu must be a multiple of block length\n", (unsigned long)il)); return (1); } dbg((" Input:\n")); dbg((" KEK: ")); for (k = 0; k < (int)kl; k++) dbg(("%02X", key[k])); dbg(("\n Key Data: ")); for (k = 0; k < (int)il; k++) dbg(("%02X", input[k])); dbg(("\n\n Wrap: \n")); rijndaelKeySetupEnc(rk, key, (int)AES_KEY_BITLEN(kl)); /* Set A = IV */ memcpy(A, aeskeywrapIV, AKW_BLOCK_LEN); /* For i = 1 to n */ /* R[i] = P[i] */ memcpy(R, input, il); /* For j = 0 to 5 */ for (j = 0; j < 6; j++) { /* For i = 1 to n */ for (i = 0; i < n; i++) { dbg(("\n %d\n", (n*j)+i+1)); pinter(" In ", A, il, R); /* B = AES(K, A | R[i]) */ memcpy(&A[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN); aes_block_encrypt((int)AES_ROUNDS(kl), rk, A, B); /* R[i] = LSB(64, B) */ memcpy(&R[i*AKW_BLOCK_LEN], &B[AKW_BLOCK_LEN], AKW_BLOCK_LEN); /* A = MSB(64, B) ^ t where t = (n*j)+i */ memcpy(&A[0], &B[0], AKW_BLOCK_LEN); pinter(" Enc ", A, il, R); A[AKW_BLOCK_LEN-1] ^= ((n*j)+i+1); pinter(" XorT ", A, il, R); } } /* Set C[0] = A */ memcpy(output, A, AKW_BLOCK_LEN); /* For i = 1 to n */ /* C[i] = R[i] */ memcpy(&output[AKW_BLOCK_LEN], R, il); return (0); }