18d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/*
28d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * AES-128 CBC
38d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
48d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
58d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt *
6c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * This software may be distributed under the terms of the BSD license.
7c5ec7f57ead87efa365800228aa0b09a12d9e6c4Dmitry Shmidt * See README for more details.
88d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
98d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
108d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "includes.h"
118d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
128d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "common.h"
138d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes.h"
148d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt#include "aes_wrap.h"
158d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
168d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
178d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * aes_128_cbc_encrypt - AES-128 CBC encryption
188d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Encryption key
198d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iv: Encryption IV for CBC mode (16 bytes)
208d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data to encrypt in-place
218d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data_len: Length of data in bytes (must be divisible by 16)
228d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
238d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
248d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
258d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
268d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
278d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 cbc[AES_BLOCK_SIZE];
288d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos = data;
298d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, j, blocks;
308d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
318d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = aes_encrypt_init(key, 16);
328d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
338d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
348d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cbc, iv, AES_BLOCK_SIZE);
358d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
368d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blocks = data_len / AES_BLOCK_SIZE;
378d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < blocks; i++) {
388d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < AES_BLOCK_SIZE; j++)
398d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			cbc[j] ^= pos[j];
408d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aes_encrypt(ctx, cbc, cbc);
418d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(pos, cbc, AES_BLOCK_SIZE);
428d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += AES_BLOCK_SIZE;
438d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
448d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_encrypt_deinit(ctx);
458d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
468d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
478d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
488d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
498d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt/**
508d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * aes_128_cbc_decrypt - AES-128 CBC decryption
518d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @key: Decryption key
528d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @iv: Decryption IV for CBC mode (16 bytes)
538d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data: Data to decrypt in-place
548d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * @data_len: Length of data in bytes (must be divisible by 16)
558d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt * Returns: 0 on success, -1 on failure
568d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt */
578d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidtint aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
588d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt{
598d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	void *ctx;
608d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
618d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	u8 *pos = data;
628d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	int i, j, blocks;
638d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
648d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	ctx = aes_decrypt_init(key, 16);
658d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	if (ctx == NULL)
668d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		return -1;
678d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	os_memcpy(cbc, iv, AES_BLOCK_SIZE);
688d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt
698d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	blocks = data_len / AES_BLOCK_SIZE;
708d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	for (i = 0; i < blocks; i++) {
718d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(tmp, pos, AES_BLOCK_SIZE);
728d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		aes_decrypt(ctx, pos, pos);
738d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		for (j = 0; j < AES_BLOCK_SIZE; j++)
748d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt			pos[j] ^= cbc[j];
758d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		os_memcpy(cbc, tmp, AES_BLOCK_SIZE);
768d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt		pos += AES_BLOCK_SIZE;
778d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	}
788d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	aes_decrypt_deinit(ctx);
798d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt	return 0;
808d520ff1dc2da35cdca849e982051b86468016d8Dmitry Shmidt}
81