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