Annotation of sys/uvm/uvm_swap_encrypt.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: uvm_swap_encrypt.c,v 1.14 2005/03/26 16:06:46 deraadt Exp $ */
! 2:
! 3: /*
! 4: * Copyright 1999 Niels Provos <provos@citi.umich.edu>
! 5: * All rights reserved.
! 6: *
! 7: * Redistribution and use in source and binary forms, with or without
! 8: * modification, are permitted provided that the following conditions
! 9: * are met:
! 10: * 1. Redistributions of source code must retain the above copyright
! 11: * notice, this list of conditions and the following disclaimer.
! 12: * 2. Redistributions in binary form must reproduce the above copyright
! 13: * notice, this list of conditions and the following disclaimer in the
! 14: * documentation and/or other materials provided with the distribution.
! 15: * 3. All advertising materials mentioning features or use of this software
! 16: * must display the following acknowledgement:
! 17: * This product includes software developed by Niels Provos.
! 18: * 4. The name of the author may not be used to endorse or promote products
! 19: * derived from this software without specific prior written permission.
! 20: *
! 21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
! 25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
! 31: */
! 32:
! 33: #include <sys/param.h>
! 34: #include <sys/systm.h>
! 35: #include <sys/kernel.h>
! 36: #include <sys/malloc.h>
! 37: #include <sys/sysctl.h>
! 38: #include <sys/time.h>
! 39: #include <sys/conf.h>
! 40: #include <dev/rndvar.h>
! 41: #include <crypto/rijndael.h>
! 42:
! 43: #include <uvm/uvm.h>
! 44:
! 45: struct swap_key *kcur = NULL;
! 46: rijndael_ctx swap_ctxt;
! 47:
! 48: int uvm_doswapencrypt = 1;
! 49: u_int uvm_swpkeyscreated = 0;
! 50: u_int uvm_swpkeysdeleted = 0;
! 51:
! 52: int swap_encrypt_initialized = 0;
! 53:
! 54: int
! 55: swap_encrypt_ctl(int *name, u_int namelen, void *oldp, size_t *oldlenp,
! 56: void *newp, size_t newlen, struct proc *p)
! 57: {
! 58: /* all sysctl names at this level are terminal */
! 59: if (namelen != 1)
! 60: return (ENOTDIR); /* overloaded */
! 61:
! 62: switch (name[0]) {
! 63: case SWPENC_ENABLE: {
! 64: int doencrypt = uvm_doswapencrypt;
! 65: int result;
! 66:
! 67: result = sysctl_int(oldp, oldlenp, newp, newlen, &doencrypt);
! 68: if (result)
! 69: return result;
! 70:
! 71: /*
! 72: * Swap Encryption has been turned on, we need to
! 73: * initialize state for swap devices that have been
! 74: * added.
! 75: */
! 76: if (doencrypt)
! 77: uvm_swap_initcrypt_all();
! 78: uvm_doswapencrypt = doencrypt;
! 79: return (0);
! 80: }
! 81: case SWPENC_CREATED:
! 82: return (sysctl_rdint(oldp, oldlenp, newp, uvm_swpkeyscreated));
! 83: case SWPENC_DELETED:
! 84: return (sysctl_rdint(oldp, oldlenp, newp, uvm_swpkeysdeleted));
! 85: default:
! 86: return (EOPNOTSUPP);
! 87: }
! 88: /* NOTREACHED */
! 89: }
! 90:
! 91: void
! 92: swap_key_create(struct swap_key *key)
! 93: {
! 94: int i;
! 95: u_int32_t *p = key->key;
! 96:
! 97: key->refcount = 0;
! 98: for (i = 0; i < sizeof(key->key) / sizeof(u_int32_t); i++)
! 99: *p++ = arc4random();
! 100:
! 101: uvm_swpkeyscreated++;
! 102: }
! 103:
! 104: void
! 105: swap_key_delete(struct swap_key *key)
! 106: {
! 107: /* Make sure that this key gets removed if we just used it */
! 108: swap_key_cleanup(key);
! 109:
! 110: memset(key, 0, sizeof(*key));
! 111: uvm_swpkeysdeleted++;
! 112: }
! 113:
! 114: /*
! 115: * Encrypt the data before it goes to swap, the size should be 64-bit
! 116: * aligned.
! 117: */
! 118:
! 119: void
! 120: swap_encrypt(struct swap_key *key, caddr_t src, caddr_t dst, u_int64_t block,
! 121: size_t count)
! 122: {
! 123: u_int32_t *dsrc = (u_int32_t *)src;
! 124: u_int32_t *ddst = (u_int32_t *)dst;
! 125: u_int32_t iv[4];
! 126: u_int32_t iv1, iv2, iv3, iv4;
! 127:
! 128: if (!swap_encrypt_initialized)
! 129: swap_encrypt_initialized = 1;
! 130:
! 131: swap_key_prepare(key, 1);
! 132:
! 133: count /= sizeof(u_int32_t);
! 134:
! 135: iv[0] = block >> 32; iv[1] = block; iv[2] = ~iv[0]; iv[3] = ~iv[1];
! 136: rijndael_encrypt(&swap_ctxt, (u_char *)iv, (u_char *)iv);
! 137: iv1 = iv[0]; iv2 = iv[1]; iv3 = iv[2]; iv4 = iv[3];
! 138:
! 139: for (; count > 0; count -= 4) {
! 140: ddst[0] = dsrc[0] ^ iv1;
! 141: ddst[1] = dsrc[1] ^ iv2;
! 142: ddst[2] = dsrc[2] ^ iv3;
! 143: ddst[3] = dsrc[3] ^ iv4;
! 144: /*
! 145: * Do not worry about endianess, it only needs to decrypt
! 146: * on this machine.
! 147: */
! 148: rijndael_encrypt(&swap_ctxt, (u_char *)ddst, (u_char *)ddst);
! 149: iv1 = ddst[0];
! 150: iv2 = ddst[1];
! 151: iv3 = ddst[2];
! 152: iv4 = ddst[3];
! 153:
! 154: dsrc += 4;
! 155: ddst += 4;
! 156: }
! 157: }
! 158:
! 159: /*
! 160: * Decrypt the data after we retrieved it from swap, the size should be 64-bit
! 161: * aligned.
! 162: */
! 163:
! 164: void
! 165: swap_decrypt(struct swap_key *key, caddr_t src, caddr_t dst, u_int64_t block,
! 166: size_t count)
! 167: {
! 168: u_int32_t *dsrc = (u_int32_t *)src;
! 169: u_int32_t *ddst = (u_int32_t *)dst;
! 170: u_int32_t iv[4];
! 171: u_int32_t iv1, iv2, iv3, iv4, niv1, niv2, niv3, niv4;
! 172:
! 173: if (!swap_encrypt_initialized)
! 174: panic("swap_decrypt: key not initialized");
! 175:
! 176: swap_key_prepare(key, 0);
! 177:
! 178: count /= sizeof(u_int32_t);
! 179:
! 180: iv[0] = block >> 32; iv[1] = block; iv[2] = ~iv[0]; iv[3] = ~iv[1];
! 181: rijndael_encrypt(&swap_ctxt, (u_char *)iv, (u_char *)iv);
! 182: iv1 = iv[0]; iv2 = iv[1]; iv3 = iv[2]; iv4 = iv[3];
! 183:
! 184: for (; count > 0; count -= 4) {
! 185: ddst[0] = niv1 = dsrc[0];
! 186: ddst[1] = niv2 = dsrc[1];
! 187: ddst[2] = niv3 = dsrc[2];
! 188: ddst[3] = niv4 = dsrc[3];
! 189: rijndael_decrypt(&swap_ctxt, (u_char *)ddst, (u_char *)ddst);
! 190: ddst[0] ^= iv1;
! 191: ddst[1] ^= iv2;
! 192: ddst[2] ^= iv3;
! 193: ddst[3] ^= iv4;
! 194:
! 195: iv1 = niv1;
! 196: iv2 = niv2;
! 197: iv3 = niv3;
! 198: iv4 = niv4;
! 199:
! 200: dsrc += 4;
! 201: ddst += 4;
! 202: }
! 203: }
! 204:
! 205: void
! 206: swap_key_prepare(struct swap_key *key, int encrypt)
! 207: {
! 208: /*
! 209: * Check if we have prepared for this key already,
! 210: * if we only have the encryption schedule, we have
! 211: * to recompute and get the decryption schedule also.
! 212: */
! 213: if (kcur == key && (encrypt || !swap_ctxt.enc_only))
! 214: return;
! 215:
! 216: if (encrypt)
! 217: rijndael_set_key_enc_only(&swap_ctxt, (u_char *)key->key,
! 218: sizeof(key->key) * 8);
! 219: else
! 220: rijndael_set_key(&swap_ctxt, (u_char *)key->key,
! 221: sizeof(key->key) * 8);
! 222:
! 223: kcur = key;
! 224: }
! 225:
! 226: /*
! 227: * Make sure that a specific key is no longer available.
! 228: */
! 229:
! 230: void
! 231: swap_key_cleanup(struct swap_key *key)
! 232: {
! 233: /* Check if we have a key */
! 234: if (kcur == NULL || kcur != key)
! 235: return;
! 236:
! 237: /* Zero out the subkeys */
! 238: memset(&swap_ctxt, 0, sizeof(swap_ctxt));
! 239:
! 240: kcur = NULL;
! 241: }
CVSweb