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;
}


Reply via email to