1214501Srpaulo/* 2214501Srpaulo * AES-128 CBC 3214501Srpaulo * 4214501Srpaulo * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi> 5214501Srpaulo * 6214501Srpaulo * This program is free software; you can redistribute it and/or modify 7214501Srpaulo * it under the terms of the GNU General Public License version 2 as 8214501Srpaulo * published by the Free Software Foundation. 9214501Srpaulo * 10214501Srpaulo * Alternatively, this software may be distributed under the terms of BSD 11214501Srpaulo * license. 12214501Srpaulo * 13214501Srpaulo * See README and COPYING for more details. 14214501Srpaulo */ 15214501Srpaulo 16214501Srpaulo#include "includes.h" 17214501Srpaulo 18214501Srpaulo#include "common.h" 19214501Srpaulo#include "aes.h" 20214501Srpaulo#include "aes_wrap.h" 21214501Srpaulo 22214501Srpaulo/** 23214501Srpaulo * aes_128_cbc_encrypt - AES-128 CBC encryption 24214501Srpaulo * @key: Encryption key 25214501Srpaulo * @iv: Encryption IV for CBC mode (16 bytes) 26214501Srpaulo * @data: Data to encrypt in-place 27214501Srpaulo * @data_len: Length of data in bytes (must be divisible by 16) 28214501Srpaulo * Returns: 0 on success, -1 on failure 29214501Srpaulo */ 30214501Srpauloint aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) 31214501Srpaulo{ 32214501Srpaulo void *ctx; 33214501Srpaulo u8 cbc[AES_BLOCK_SIZE]; 34214501Srpaulo u8 *pos = data; 35214501Srpaulo int i, j, blocks; 36214501Srpaulo 37214501Srpaulo ctx = aes_encrypt_init(key, 16); 38214501Srpaulo if (ctx == NULL) 39214501Srpaulo return -1; 40214501Srpaulo os_memcpy(cbc, iv, AES_BLOCK_SIZE); 41214501Srpaulo 42214501Srpaulo blocks = data_len / AES_BLOCK_SIZE; 43214501Srpaulo for (i = 0; i < blocks; i++) { 44214501Srpaulo for (j = 0; j < AES_BLOCK_SIZE; j++) 45214501Srpaulo cbc[j] ^= pos[j]; 46214501Srpaulo aes_encrypt(ctx, cbc, cbc); 47214501Srpaulo os_memcpy(pos, cbc, AES_BLOCK_SIZE); 48214501Srpaulo pos += AES_BLOCK_SIZE; 49214501Srpaulo } 50214501Srpaulo aes_encrypt_deinit(ctx); 51214501Srpaulo return 0; 52214501Srpaulo} 53214501Srpaulo 54214501Srpaulo 55214501Srpaulo/** 56214501Srpaulo * aes_128_cbc_decrypt - AES-128 CBC decryption 57214501Srpaulo * @key: Decryption key 58214501Srpaulo * @iv: Decryption IV for CBC mode (16 bytes) 59214501Srpaulo * @data: Data to decrypt in-place 60214501Srpaulo * @data_len: Length of data in bytes (must be divisible by 16) 61214501Srpaulo * Returns: 0 on success, -1 on failure 62214501Srpaulo */ 63214501Srpauloint aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len) 64214501Srpaulo{ 65214501Srpaulo void *ctx; 66214501Srpaulo u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE]; 67214501Srpaulo u8 *pos = data; 68214501Srpaulo int i, j, blocks; 69214501Srpaulo 70214501Srpaulo ctx = aes_decrypt_init(key, 16); 71214501Srpaulo if (ctx == NULL) 72214501Srpaulo return -1; 73214501Srpaulo os_memcpy(cbc, iv, AES_BLOCK_SIZE); 74214501Srpaulo 75214501Srpaulo blocks = data_len / AES_BLOCK_SIZE; 76214501Srpaulo for (i = 0; i < blocks; i++) { 77214501Srpaulo os_memcpy(tmp, pos, AES_BLOCK_SIZE); 78214501Srpaulo aes_decrypt(ctx, pos, pos); 79214501Srpaulo for (j = 0; j < AES_BLOCK_SIZE; j++) 80214501Srpaulo pos[j] ^= cbc[j]; 81214501Srpaulo os_memcpy(cbc, tmp, AES_BLOCK_SIZE); 82214501Srpaulo pos += AES_BLOCK_SIZE; 83214501Srpaulo } 84214501Srpaulo aes_decrypt_deinit(ctx); 85214501Srpaulo return 0; 86214501Srpaulo} 87