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