Files needed to reproduce the bug.
--
Johan Brinch
/*@+boundsread +boundswrite@*/
/*! \file */
#ifndef AES_PRIMITIVES
#define AES_PRIMITIVES
#include <openssl/aes.h>
/**
* AES key size in bits.
*/
#define AES_BITS 128
/**
* AES block size in bytes.
*/
#define AES_BLOCK 16
/**
* Initialize an AES encryption key from a passphrase/key.
*/
/*@unused@*/
int aes_init_encrypt_key(unsigned char *password,
/*@out@*/ AES_KEY **out_key);
/**
* Initialize an AES decryption key from a passphrase/key.
*/
/*@unused@*/
int aes_init_decrypt_key(unsigned char *password,
/*@out@*/ AES_KEY **out_key);
/**
* Wipe an AES key by overwriting it.
*/
/*@unused@*/
int aes_key_wipe(AES_KEY *key);
/**
* Encrypt one or more data blocks of total size "len" from "in" and store the result in "out".
*/
/*@unused@*/
int aes_ecb_encrypt(const AES_KEY *encrypt_key,
const size_t len,
const unsigned char *in,
unsigned char *out)
/*@modifies *out@*/
;
/**
* Decrypt one or more data blocks of total size "len" from "in" and store the result in "out".
*/
/*@unused@*/
int aes_ecb_decrypt(const AES_KEY *decrypt_key,
const size_t len,
const unsigned char *in,
/*@out@*/ unsigned char *out);
#endif
/*@+boundsread +boundswrite@*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <assert.h>
#include "aes.h"
/* EXTERNAL FUNCTIONS */
extern
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
/*@out@*/ AES_KEY *key);
extern
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
/*@out@*/ AES_KEY *key);
extern
void AES_ecb_encrypt(const unsigned char *in,
unsigned char *out,
const AES_KEY *key, const int enc)
/*@sets *out@*/
;
/* INTERNAL FUNCTIONS */
static
int aes_ecb_dir(const AES_KEY *dir_key,
const int direction, // AES_ENCRYPT, AES_DECRYPT
const size_t len,
const unsigned char *in,
unsigned char *out)
/*@sets *out@*/
;
/* PUBLIC/API FUNCTIONS */
int aes_init_encrypt_key(unsigned char *pass,
/*@out@*/ AES_KEY **out_key)
/*@requires maxSet(*out_key) >= 0;@*/
{
// Allocate and setup encryption key
AES_KEY *key = malloc(sizeof(AES_KEY));
if(key == NULL) {
*out_key = NULL;
return ENOMEM;
}
if(AES_set_encrypt_key(pass, AES_BITS, key) != 0) {
free(key);
*out_key = NULL;
return EINVAL;
}
*out_key = key;
return 0;
}
int aes_init_decrypt_key(unsigned char *pass,
/*@out@*/ AES_KEY **out_key)
{
// Allocate and setup decryption key
AES_KEY *key = malloc(sizeof(AES_KEY));
if(key == NULL) {
*out_key = NULL;
return ENOMEM;
}
if(AES_set_decrypt_key(pass, AES_BITS, key) != 0) {
free(key);
*out_key = NULL;
return EINVAL;
}
*out_key = key;
return 0;
}
int aes_key_wipe(AES_KEY *key)
{
memset(key, 0, sizeof(AES_KEY));
return 0;
}
/* Encrypt one or more data blocks */
int aes_ecb_encrypt(const AES_KEY *encrypt_key,
const size_t len,
const unsigned char *in,
unsigned char *out)
/*@sets *out@*/
/*@requires maxSet(out) >= len - 1;@*/
{
return aes_ecb_dir(encrypt_key, AES_ENCRYPT, len, in, out);
}
/* Decrypt one or more data blocks */
int aes_ecb_decrypt(const AES_KEY *decrypt_key,
const size_t len,
const unsigned char *in,
unsigned char *out)
/*@sets *out@*/
{
return aes_ecb_dir(decrypt_key, AES_DECRYPT, len, in, out);
}
/** INTERNAL FUNCTIONS **/
/* Encrypt or decrypt one or more data blocks */
static int aes_ecb_dir(const AES_KEY *dir_key,
const int direction, // AES_ENCRYPT, AES_DECRYPT
const size_t len,
const unsigned char *in,
unsigned char *out)
/*sets *out@*/
{
/*
Splint: Out storage out not defined before return
*/
size_t i;
assert(len != 0 && len % AES_BLOCK_SIZE == 0);
if(len == 0 || len % AES_BLOCK_SIZE != 0) {
return EINVAL;
}
if(dir_key == NULL || in == NULL || out == NULL) {
return EINVAL;
}
for(i = 0; i < len; i+=AES_BLOCK) {
AES_ecb_encrypt(&in[i], &out[i], dir_key, direction);
}
return 0;
}