/* AES-CBC mode decryption algorithm * - handle partial plaintext blocks with padding * - ptxt and ctxt can point to the same location * - returns -1 on error */ int BCMROMFN(aes_cbc_decrypt_pad)(uint32 *rk, const size_t key_len, const uint8 *nonce, const size_t data_len, const uint8 *ctxt, uint8 *ptxt, uint8 padd_type) { uint8 tmp[AES_BLOCK_SZ]; uint32 remaining = (uint32)data_len; /* First block get XORed with nonce/IV */ const unsigned char *iv = nonce; const unsigned char *crypt_data = ctxt; uint32 plaintext_len = 0; unsigned char *plain_data = ptxt; if (data_len % AES_BLOCK_SZ) return (-1); if (data_len < AES_BLOCK_SZ) return (-1); while (remaining >= AES_BLOCK_SZ) { aes_block_decrypt((int)AES_ROUNDS(key_len), rk, crypt_data, tmp); xor_128bit_block(tmp, iv, plain_data); remaining -= AES_BLOCK_SZ; iv = crypt_data; crypt_data += AES_BLOCK_SZ; plain_data += AES_BLOCK_SZ; plaintext_len += AES_BLOCK_SZ; } if (padd_type == PAD_LEN_PADDING) plaintext_len -= ptxt[plaintext_len -1]; return (plaintext_len); }
bool dec_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(!aes_block_decrypt(buffer,total_len)) { return false; } if(!xor_fibonacci_crypt(buffer, real_len, cipher_num)) { return false; } return true; }
/* aes_unwrap: perform AES-based key unwrap function defined in RFC3394, * return 0 on success, 1 on error * input is il bytes * output is (il-8) bytes */ int BCMROMFN(aes_unwrap)(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 + AKW_BLOCK_LEN]; uint8 B[AES_BLOCK_SZ]; size_t ol = il - AKW_BLOCK_LEN; int n = (int)(ol/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 + AKW_BLOCK_LEN)) { dbg(("aes_unwrap: input length %lu too large\n", (unsigned long)il)); return (1); } if (il % AKW_BLOCK_LEN) { dbg(("aes_unwrap: 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 Data: ")); for (k = 0; k < (int)il; k++) dbg(("%02X", input[k])); dbg(("\n\n Unwrap: \n")); rijndaelKeySetupDec(rk, key, (int)AES_KEY_BITLEN(kl)); /* Set A = C[0] */ memcpy(A, input, AKW_BLOCK_LEN); /* For i = 1 to n */ /* R[i] = C[i] */ memcpy(R, &input[AKW_BLOCK_LEN], ol); /* For j = 5 to 0 */ for (j = 5; j >= 0; j--) { /* For i = n to 1 */ for (i = n - 1; i >= 0; i--) { dbg(("\n %d\n", (n*j)+i+1)); pinter(" In ", A, ol, R); /* B = AES - 1 (K, (A ^ t) | R[i]) where t = n * j + i */ A[AKW_BLOCK_LEN - 1] ^= ((n*j)+i+1); pinter(" XorT ", A, ol, R); memcpy(&A[AKW_BLOCK_LEN], &R[i*AKW_BLOCK_LEN], AKW_BLOCK_LEN); aes_block_decrypt((int)AES_ROUNDS(kl), rk, A, B); /* A = MSB(64, B) */ memcpy(&A[0], &B[0], AKW_BLOCK_LEN); /* R[i] = LSB(64, B) */ memcpy(&R[i*AKW_BLOCK_LEN], &B[AKW_BLOCK_LEN], AKW_BLOCK_LEN); pinter(" Dec ", A, ol, R); } } if (!memcmp(A, aeskeywrapIV, AKW_BLOCK_LEN)) { /* For i = 1 to n */ /* P[i] = R[i] */ memcpy(&output[0], R, ol); return 0; } else { dbg(("aes_unwrap: IV mismatch in unwrapped data\n")); return 1; } }