aboutsummaryrefslogtreecommitdiffstats
path: root/xen/include/crypto
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-03-03 12:48:16 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-03-03 12:48:16 +0000
commit6deab1ae316b5f7da431d8add34c676dfca9c4f9 (patch)
tree83d88eac3224e24acc9a6c4e8be971ed681810d3 /xen/include/crypto
parent8aaf870611964a738533c7300e0858e293f5f23a (diff)
downloadxen-6deab1ae316b5f7da431d8add34c676dfca9c4f9.tar.gz
xen-6deab1ae316b5f7da431d8add34c676dfca9c4f9.tar.bz2
xen-6deab1ae316b5f7da431d8add34c676dfca9c4f9.zip
txt: perform per-domain (and frametable and xenheap) MAC on entry into
S3 and verification on resume. The MAC algorithm is called VMAC and was developed by Ted Krovetz and Wei Dai (more details are in the files). It is based on a universal hash function. The universal hash is passed through a pseudo-random function, implemented using AES. More details can be found at http://fastcrypto.org/vmac/. = The AES code comes from the OpenBSD implementation (which is derived from the implementation referenced in VMAC site). As Xen does not have a good source of entropy to generate its own key (for the keyed hash), it uses the key that tboot passes in. Although the code attempts to MAC all of a domain's pages (code/data, VT-d tables) based on its s3_integrity flag, some of a domain's memory may always be MAC'ed, e.g. shadow page tables. Only xenheap pages that are in use are MAC'ed. We believe that the memory MAC'ed by the Xen code and the ranges passed to tboot to MAC cover all of the memory whose integrity needs to be protected on S3. Any suggestions or ranges that we missed are welcome. Signed-off-by: Shane Wang <shane.wang@intel.com> Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>
Diffstat (limited to 'xen/include/crypto')
-rw-r--r--xen/include/crypto/rijndael.h58
-rw-r--r--xen/include/crypto/vmac.h178
2 files changed, 236 insertions, 0 deletions
diff --git a/xen/include/crypto/rijndael.h b/xen/include/crypto/rijndael.h
new file mode 100644
index 0000000000..29746029e8
--- /dev/null
+++ b/xen/include/crypto/rijndael.h
@@ -0,0 +1,58 @@
+/* $OpenBSD: rijndael.h,v 1.13 2008/06/09 07:49:45 djm Exp $ */
+
+/**
+ * rijndael-alg-fst.h
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __RIJNDAEL_H
+#define __RIJNDAEL_H
+
+#define AES_MAXKEYBITS (256)
+#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
+/* for 256-bit keys, fewer for less */
+#define AES_MAXROUNDS 14
+
+//typedef unsigned char u8;
+//typedef unsigned short u16;
+//typedef unsigned int u32;
+
+/* The structure for key information */
+typedef struct {
+ int enc_only; /* context contains only encrypt schedule */
+ int Nr; /* key-length-dependent number of rounds */
+ u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
+ u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
+} rijndael_ctx;
+
+int rijndael_set_key(rijndael_ctx *, const u_char *, int);
+int rijndael_set_key_enc_only(rijndael_ctx *, const u_char *, int);
+void rijndael_decrypt(rijndael_ctx *, const u_char *, u_char *);
+void rijndael_encrypt(rijndael_ctx *, const u_char *, u_char *);
+
+int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
+int rijndaelKeySetupDec(unsigned int [], const unsigned char [], int);
+void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
+ unsigned char []);
+
+#endif /* __RIJNDAEL_H */
diff --git a/xen/include/crypto/vmac.h b/xen/include/crypto/vmac.h
new file mode 100644
index 0000000000..9e92b3e351
--- /dev/null
+++ b/xen/include/crypto/vmac.h
@@ -0,0 +1,178 @@
+#ifndef HEADER_VMAC_H
+#define HEADER_VMAC_H
+
+/* --------------------------------------------------------------------------
+ * VMAC and VHASH Implementation by Ted Krovetz (tdk@acm.org) and Wei Dai.
+ * This implementation is herby placed in the public domain.
+ * The authors offers no warranty. Use at your own risk.
+ * Please send bug reports to the authors.
+ * Last modified: 17 APR 08, 1700 PDT
+ * ----------------------------------------------------------------------- */
+
+/* --------------------------------------------------------------------------
+ * User definable settings.
+ * ----------------------------------------------------------------------- */
+#define VMAC_TAG_LEN 64 /* Must be 64 or 128 - 64 sufficient for most */
+#define VMAC_KEY_LEN 128 /* Must be 128, 192 or 256 */
+#define VMAC_NHBYTES 128 /* Must 2^i for any 3 < i < 13. Standard = 128 */
+#define VMAC_PREFER_BIG_ENDIAN 0 /* Prefer non-x86 */
+
+#define VMAC_USE_OPENSSL 0 /* Set to non-zero to use OpenSSL's AES */
+#define VMAC_CACHE_NONCES 1 /* Set to non-zero to cause caching */
+ /* of consecutive nonces on 64-bit tags */
+
+#define VMAC_RUN_TESTS 0 /* Set to non-zero to check vectors and speed */
+#define VMAC_HZ (448e6) /* Set to hz of host machine to get speed */
+#define VMAC_HASH_ONLY 0 /* Set to non-zero to time hash only (not-mac) */
+/* Speeds of cpus I have access to
+#define hz (2400e6) glyme Core 2 "Conroe"
+#define hz (2000e6) jupiter G5
+#define hz (1592e6) titan
+#define hz (2793e6) athena/gaia
+#define hz (1250e6) isis G4
+#define hz (2160e6) imac Core 2 "Merom"
+#define hz (266e6) ppc/arm
+#define hz (400e6) mips
+*/
+
+/* --------------------------------------------------------------------------
+ * This implementation uses uint32_t and uint64_t as names for unsigned 32-
+ * and 64-bit integer types. These are defined in C99 stdint.h. The
+ * following may need adaptation if you are not running a C99 or
+ * Microsoft C environment.
+ * ----------------------------------------------------------------------- */
+#define VMAC_USE_STDINT 1 /* Set to zero if system has no stdint.h */
+
+#if VMAC_USE_STDINT && !_MSC_VER /* Try stdint.h if non-Microsoft */
+#ifdef __cplusplus
+#define __STDC_CONSTANT_MACROS
+#endif
+//#include <stdint.h>
+#elif (_MSC_VER) /* Microsoft C does not have stdint.h */
+typedef unsigned __int32 uint32_t;
+typedef unsigned __int64 uint64_t;
+#define UINT64_C(v) v ## UI64
+#else /* Guess sensibly - may need adaptation */
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+#define UINT64_C(v) v ## ULL
+#endif
+
+/* --------------------------------------------------------------------------
+ * This implementation supports two free AES implementations: OpenSSL's and
+ * Paulo Barreto's. To use OpenSSL's, you will need to include the OpenSSL
+ * crypto library (eg, gcc -lcrypto foo.c). For Barreto's, you will need
+ * to compile rijndael-alg-fst.c, last seen at http://www.iaik.tu-graz.ac.at/
+ * research/krypto/AES/old/~rijmen/rijndael/rijndael-fst-3.0.zip and
+ * http://homes.esat.kuleuven.be/~rijmen/rijndael/rijndael-fst-3.0.zip.
+ * To use a different implementation, use these definitions as a model.
+ * ----------------------------------------------------------------------- */
+#if VMAC_USE_OPENSSL
+
+#include <openssl/aes.h>
+typedef AES_KEY aes_int_key;
+
+#define aes_encryption(in,out,int_key) \
+ AES_encrypt((unsigned char *)(in),(unsigned char *)(out),(int_key))
+#define aes_key_setup(key,int_key) \
+ AES_set_encrypt_key((key),VMAC_KEY_LEN,(int_key))
+
+#else
+
+//#include "rijndael-alg-fst.h"
+typedef uint64_t vmac_t;
+#include "rijndael.h"
+typedef u32 aes_int_key[4*(VMAC_KEY_LEN/32+7)];
+
+#define aes_encryption(in,out,int_key) \
+ rijndaelEncrypt((u32 *)(int_key), \
+ ((VMAC_KEY_LEN/32)+6), \
+ (u8 *)(in), (u8 *)(out))
+#define aes_key_setup(user_key,int_key) \
+ rijndaelKeySetupEnc((u32 *)(int_key), \
+ (u8 *)(user_key), \
+ VMAC_KEY_LEN)
+#endif
+
+/* --------------------------------------------------------------------- */
+
+typedef struct {
+ uint64_t nhkey [(VMAC_NHBYTES/8)+2*(VMAC_TAG_LEN/64-1)];
+ uint64_t polykey[2*VMAC_TAG_LEN/64];
+ uint64_t l3key [2*VMAC_TAG_LEN/64];
+ uint64_t polytmp[2*VMAC_TAG_LEN/64];
+ aes_int_key cipher_key;
+ #if (VMAC_TAG_LEN == 64) && (VMAC_CACHE_NONCES)
+ uint64_t cached_nonce[2];
+ uint64_t cached_aes[2];
+ #endif
+ int first_block_processed;
+} vmac_ctx_t;
+
+/* --------------------------------------------------------------------- */
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* --------------------------------------------------------------------------
+ * <<<<< USAGE NOTES >>>>>
+ *
+ * Given msg m (mbytes in length) and nonce buffer n
+ * this function returns a tag as its output. The tag is returned as
+ * a number. When VMAC_TAG_LEN == 64, the 'return'ed integer is the tag,
+ * and *tagl is meaningless. When VMAC_TAG_LEN == 128 the tag is the
+ * number y * 2^64 + *tagl where y is the function's return value.
+ * If you want to consider tags to be strings, then you must do so with
+ * an agreed upon endian orientation for interoperability, and convert
+ * the results appropriately. VHASH hashes m without creating any tag.
+ * Consecutive substrings forming a prefix of a message may be passed
+ * to vhash_update, with vhash or vmac being called with the remainder
+ * to produce the output.
+ *
+ * Requirements:
+ * - On 32-bit architectures with SSE2 instructions, ctx and m MUST be
+ * begin on 16-byte memory boundaries.
+ * - m MUST be your message followed by zeroes to the nearest 16-byte
+ * boundary. If m is a length multiple of 16 bytes, then it is already
+ * at a 16-byte boundary and needs no padding. mbytes should be your
+ * message length without any padding.
+ * - The first bit of the nonce buffer n must be 0. An i byte nonce, is made
+ * as the first 16-i bytes of n being zero, and the final i the nonce.
+ * - vhash_update MUST have mbytes be a positive multiple of VMAC_NHBYTES
+ * ----------------------------------------------------------------------- */
+
+#define vmac_update vhash_update
+
+void vhash_update(unsigned char m[],
+ unsigned int mbytes,
+ vmac_ctx_t *ctx);
+
+uint64_t vmac(unsigned char m[],
+ unsigned int mbytes,
+ unsigned char n[16],
+ uint64_t *tagl,
+ vmac_ctx_t *ctx);
+
+uint64_t vhash(unsigned char m[],
+ unsigned int mbytes,
+ uint64_t *tagl,
+ vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------------
+ * When passed a VMAC_KEY_LEN bit user_key, this function initialazies ctx.
+ * ----------------------------------------------------------------------- */
+
+void vmac_set_key(unsigned char user_key[], vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------------
+ * This function aborts current hash and resets ctx, ready for a new message.
+ * ----------------------------------------------------------------------- */
+
+void vhash_abort(vmac_ctx_t *ctx);
+
+/* --------------------------------------------------------------------- */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEADER_AES_H */