1 #ifndef HEADER_VMAC_H 2 #define HEADER_VMAC_H 3 4 /* -------------------------------------------------------------------------- 5 * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai. 6 * This implementation is herby placed in the public domain. 7 * The authors offers no warranty. Use at your own risk. 8 * Please send bug reports to the authors. 9 * Last modified: 17 APR 08, 1700 PDT 10 * ----------------------------------------------------------------------- */ 11 12 /* -------------------------------------------------------------------------- 13 * User definable settings. 14 * ----------------------------------------------------------------------- */ 15 #define VMAC_TAG_LEN 64 /* Must be 64 or 128 - 64 sufficient for most */ 16 #define VMAC_KEY_LEN 128 /* Must be 128, 192 or 256 */ 17 #define VMAC_NHBYTES 128 /* Must 2^i for any 3 < i < 13. Standard = 128 */ 18 #define VMAC_PREFER_BIG_ENDIAN 0 /* Prefer non-x86 */ 19 20 #define VMAC_USE_OPENSSL 0 /* Set to non-zero to use OpenSSL's AES */ 21 #define VMAC_CACHE_NONCES 1 /* Set to non-zero to cause caching */ 22 /* of consecutive nonces on 64-bit tags */ 23 24 #define VMAC_RUN_TESTS 0 /* Set to non-zero to check vectors and speed */ 25 #define VMAC_HZ (448e6) /* Set to hz of host machine to get speed */ 26 #define VMAC_HASH_ONLY 0 /* Set to non-zero to time hash only (not-mac) */ 27 /* Speeds of cpus I have access to 28 #define hz (2400e6) glyme Core 2 "Conroe" 29 #define hz (2000e6) jupiter G5 30 #define hz (1592e6) titan 31 #define hz (2793e6) athena/gaia 32 #define hz (1250e6) isis G4 33 #define hz (2160e6) imac Core 2 "Merom" 34 #define hz (266e6) ppc/arm 35 #define hz (400e6) mips 36 */ 37 38 /* -------------------------------------------------------------------------- 39 * This implementation uses uint32_t and uint64_t as names for unsigned 32- 40 * and 64-bit integer types. These are defined in C99 stdint.h. The 41 * following may need adaptation if you are not running a C99 or 42 * Microsoft C environment. 43 * ----------------------------------------------------------------------- */ 44 #define VMAC_USE_STDINT 1 /* Set to zero if system has no stdint.h */ 45 46 #if VMAC_USE_STDINT && !_MSC_VER /* Try stdint.h if non-Microsoft */ 47 #ifdef __cplusplus 48 #define __STDC_CONSTANT_MACROS 49 #endif 50 //#include <stdint.h> 51 #elif (_MSC_VER) /* Microsoft C does not have stdint.h */ 52 typedef unsigned __int32 uint32_t; 53 typedef unsigned __int64 uint64_t; 54 #define UINT64_C(v) v ## UI64 55 #else /* Guess sensibly - may need adaptation */ 56 typedef unsigned int uint32_t; 57 typedef unsigned long long uint64_t; 58 #define UINT64_C(v) v ## ULL 59 #endif 60 61 /* -------------------------------------------------------------------------- 62 * This implementation supports two free AES implementations: OpenSSL's and 63 * Paulo Barreto's. To use OpenSSL's, you will need to include the OpenSSL 64 * crypto library (eg, gcc -lcrypto foo.c). For Barreto's, you will need 65 * to compile rijndael-alg-fst.c, last seen at http://www.iaik.tu-graz.ac.at/ 66 * research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip and 67 * http://homes.esat.kuleuven.be/~rijmen/rijndael/rijndael-fst-3.0.zip. 68 * To use a different implementation, use these definitions as a model. 69 * ----------------------------------------------------------------------- */ 70 #if VMAC_USE_OPENSSL 71 72 #include <openssl/aes.h> 73 typedef AES_KEY aes_int_key; 74 75 #define aes_encryption(in,out,int_key) \ 76 AES_encrypt((unsigned char *)(in),(unsigned char *)(out),(int_key)) 77 #define aes_key_setup(key,int_key) \ 78 AES_set_encrypt_key((key),VMAC_KEY_LEN,(int_key)) 79 80 #else 81 82 //#include "rijndael-alg-fst.h" 83 typedef uint64_t vmac_t; 84 #include "rijndael.h" 85 typedef u32 aes_int_key[4*(VMAC_KEY_LEN/32+7)]; 86 87 #define aes_encryption(in,out,int_key) \ 88 rijndaelEncrypt((u32 *)(int_key), \ 89 ((VMAC_KEY_LEN/32)+6), \ 90 (u8 *)(in), (u8 *)(out)) 91 #define aes_key_setup(user_key,int_key) \ 92 rijndaelKeySetupEnc((u32 *)(int_key), \ 93 (u8 *)(user_key), \ 94 VMAC_KEY_LEN) 95 #endif 96 97 /* --------------------------------------------------------------------- */ 98 99 typedef struct { 100 uint64_t nhkey [(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)]; 101 uint64_t polykey[2*VMAC_TAG_LEN/64]; 102 uint64_t l3key [2*VMAC_TAG_LEN/64]; 103 uint64_t polytmp[2*VMAC_TAG_LEN/64]; 104 aes_int_key cipher_key; 105 #if (VMAC_TAG_LEN == 64) && (VMAC_CACHE_NONCES) 106 uint64_t cached_nonce[2]; 107 uint64_t cached_aes[2]; 108 #endif 109 int first_block_processed; 110 } vmac_ctx_t; 111 112 /* --------------------------------------------------------------------- */ 113 #ifdef __cplusplus 114 extern "C" { 115 #endif 116 /* -------------------------------------------------------------------------- 117 * <<<<< USAGE NOTES >>>>> 118 * 119 * Given msg m (mbytes in length) and nonce buffer n 120 * this function returns a tag as its output. The tag is returned as 121 * a number. When VMAC_TAG_LEN == 64, the 'return'ed integer is the tag, 122 * and *tagl is meaningless. When VMAC_TAG_LEN == 128 the tag is the 123 * number y * 2^64 + *tagl where y is the function's return value. 124 * If you want to consider tags to be strings, then you must do so with 125 * an agreed upon endian orientation for interoperability, and convert 126 * the results appropriately. VHASH hashes m without creating any tag. 127 * Consecutive substrings forming a prefix of a message may be passed 128 * to vhash_update, with vhash or vmac being called with the remainder 129 * to produce the output. 130 * 131 * Requirements: 132 * - On 32-bit architectures with SSE2 instructions, ctx and m MUST be 133 * begin on 16-byte memory boundaries. 134 * - m MUST be your message followed by zeroes to the nearest 16-byte 135 * boundary. If m is a length multiple of 16 bytes, then it is already 136 * at a 16-byte boundary and needs no padding. mbytes should be your 137 * message length without any padding. 138 * - The first bit of the nonce buffer n must be 0. An i byte nonce, is made 139 * as the first 16-i bytes of n being zero, and the final i the nonce. 140 * - vhash_update MUST have mbytes be a positive multiple of VMAC_NHBYTES 141 * ----------------------------------------------------------------------- */ 142 143 #define vmac_update vhash_update 144 145 void vhash_update(unsigned char m[], 146 unsigned int mbytes, 147 vmac_ctx_t *ctx); 148 149 uint64_t vmac(unsigned char m[], 150 unsigned int mbytes, 151 unsigned char n[16], 152 uint64_t *tagl, 153 vmac_ctx_t *ctx); 154 155 uint64_t vhash(unsigned char m[], 156 unsigned int mbytes, 157 uint64_t *tagl, 158 vmac_ctx_t *ctx); 159 160 /* -------------------------------------------------------------------------- 161 * When passed a VMAC_KEY_LEN bit user_key, this function initialazies ctx. 162 * ----------------------------------------------------------------------- */ 163 164 void vmac_set_key(unsigned char user_key[], vmac_ctx_t *ctx); 165 166 /* --------------------------------------------------------------------- */ 167 168 #ifdef __cplusplus 169 } 170 #endif 171 172 #endif /* HEADER_AES_H */ 173