+#if ENCRYPTED_SWAP
+
+#include <libkern/crypto/aesxts.h>
+
+extern int cc_rand_generate(void *, size_t); /* from libkern/cyrpto/rand.h> */
+
+boolean_t swap_crypt_initialized;
+void swap_crypt_initialize(void);
+
+symmetric_xts xts_modectx;
+uint32_t swap_crypt_key1[8]; /* big enough for a 256 bit random key */
+uint32_t swap_crypt_key2[8]; /* big enough for a 256 bit random key */
+
+#if DEVELOPMENT || DEBUG
+boolean_t swap_crypt_xts_tested = FALSE;
+unsigned char swap_crypt_test_page_ref[4096] __attribute__((aligned(4096)));
+unsigned char swap_crypt_test_page_encrypt[4096] __attribute__((aligned(4096)));
+unsigned char swap_crypt_test_page_decrypt[4096] __attribute__((aligned(4096)));
+#endif /* DEVELOPMENT || DEBUG */
+
+unsigned long vm_page_encrypt_counter;
+unsigned long vm_page_decrypt_counter;
+
+
+void
+swap_crypt_initialize(void)
+{
+ uint8_t *enckey1, *enckey2;
+ int keylen1, keylen2;
+ int error;
+
+ assert(swap_crypt_initialized == FALSE);
+
+ keylen1 = sizeof(swap_crypt_key1);
+ enckey1 = (uint8_t *)&swap_crypt_key1;
+ keylen2 = sizeof(swap_crypt_key2);
+ enckey2 = (uint8_t *)&swap_crypt_key2;
+
+ error = cc_rand_generate((void *)enckey1, keylen1);
+ assert(!error);
+
+ error = cc_rand_generate((void *)enckey2, keylen2);
+ assert(!error);
+
+ error = xts_start(0, NULL, enckey1, keylen1, enckey2, keylen2, 0, 0, &xts_modectx);
+ assert(!error);
+
+ swap_crypt_initialized = TRUE;
+
+#if DEVELOPMENT || DEBUG
+ uint8_t *encptr;
+ uint8_t *decptr;
+ uint8_t *refptr;
+ uint8_t *iv;
+ uint64_t ivnum[2];
+ int size = 0;
+ int i = 0;
+ int rc = 0;
+
+ assert(swap_crypt_xts_tested == FALSE);
+
+ /*
+ * Validate the encryption algorithms.
+ *
+ * First initialize the test data.
+ */
+ for (i = 0; i < 4096; i++) {
+ swap_crypt_test_page_ref[i] = (char) i;
+ }
+ ivnum[0] = (uint64_t)0xaa;
+ ivnum[1] = 0;
+ iv = (uint8_t *)ivnum;
+
+ refptr = (uint8_t *)swap_crypt_test_page_ref;
+ encptr = (uint8_t *)swap_crypt_test_page_encrypt;
+ decptr = (uint8_t *)swap_crypt_test_page_decrypt;
+ size = 4096;
+
+ /* encrypt */
+ rc = xts_encrypt(refptr, size, encptr, iv, &xts_modectx);
+ assert(!rc);
+
+ /* compare result with original - should NOT match */
+ for (i = 0; i < 4096; i ++) {
+ if (swap_crypt_test_page_encrypt[i] !=
+ swap_crypt_test_page_ref[i]) {
+ break;
+ }
+ }
+ assert(i != 4096);
+
+ /* decrypt */
+ rc = xts_decrypt(encptr, size, decptr, iv, &xts_modectx);
+ assert(!rc);
+
+ /* compare result with original */
+ for (i = 0; i < 4096; i ++) {
+ if (swap_crypt_test_page_decrypt[i] !=
+ swap_crypt_test_page_ref[i]) {
+ panic("encryption test failed");
+ }
+ }
+ /* encrypt in place */
+ rc = xts_encrypt(decptr, size, decptr, iv, &xts_modectx);
+ assert(!rc);
+
+ /* decrypt in place */
+ rc = xts_decrypt(decptr, size, decptr, iv, &xts_modectx);
+ assert(!rc);
+
+ for (i = 0; i < 4096; i ++) {
+ if (swap_crypt_test_page_decrypt[i] !=
+ swap_crypt_test_page_ref[i]) {
+ panic("in place encryption test failed");
+ }
+ }
+ swap_crypt_xts_tested = TRUE;
+#endif /* DEVELOPMENT || DEBUG */
+}
+
+
+void
+vm_swap_encrypt(c_segment_t c_seg)
+{
+ uint8_t *ptr;
+ uint8_t *iv;
+ uint64_t ivnum[2];
+ int size = 0;
+ int rc = 0;
+
+ if (swap_crypt_initialized == FALSE)
+ swap_crypt_initialize();
+
+#if DEVELOPMENT || DEBUG
+ C_SEG_MAKE_WRITEABLE(c_seg);
+#endif
+ ptr = (uint8_t *)c_seg->c_store.c_buffer;
+ size = round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg->c_populated_offset));
+
+ ivnum[0] = (uint64_t)c_seg;
+ ivnum[1] = 0;
+ iv = (uint8_t *)ivnum;
+
+ rc = xts_encrypt(ptr, size, ptr, iv, &xts_modectx);
+ assert(!rc);
+
+ vm_page_encrypt_counter += (size/PAGE_SIZE_64);
+
+#if DEVELOPMENT || DEBUG
+ C_SEG_WRITE_PROTECT(c_seg);
+#endif
+}
+
+void
+vm_swap_decrypt(c_segment_t c_seg)
+{
+ uint8_t *ptr;
+ uint8_t *iv;
+ uint64_t ivnum[2];
+ int size = 0;
+ int rc = 0;
+
+ assert(swap_crypt_initialized);
+
+#if DEVELOPMENT || DEBUG
+ C_SEG_MAKE_WRITEABLE(c_seg);
+#endif
+ ptr = (uint8_t *)c_seg->c_store.c_buffer;
+ size = round_page_32(C_SEG_OFFSET_TO_BYTES(c_seg->c_populated_offset));
+
+ ivnum[0] = (uint64_t)c_seg;
+ ivnum[1] = 0;
+ iv = (uint8_t *)ivnum;
+
+ rc = xts_decrypt(ptr, size, ptr, iv, &xts_modectx);
+ assert(!rc);
+
+ vm_page_decrypt_counter += (size/PAGE_SIZE_64);
+
+#if DEVELOPMENT || DEBUG
+ C_SEG_WRITE_PROTECT(c_seg);
+#endif
+}
+#endif /* ENCRYPTED_SWAP */
+
+