Annotation of sys/uvm/uvm_swap_encrypt.c, Revision 1.1.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