This source file includes following definitions.
- swap_encrypt_ctl
- swap_key_create
- swap_key_delete
- swap_encrypt
- swap_decrypt
- swap_key_prepare
- swap_key_cleanup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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
59 if (namelen != 1)
60 return (ENOTDIR);
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
73
74
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
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
108 swap_key_cleanup(key);
109
110 memset(key, 0, sizeof(*key));
111 uvm_swpkeysdeleted++;
112 }
113
114
115
116
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
146
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
161
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
210
211
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
228
229
230 void
231 swap_key_cleanup(struct swap_key *key)
232 {
233
234 if (kcur == NULL || kcur != key)
235 return;
236
237
238 memset(&swap_ctxt, 0, sizeof(swap_ctxt));
239
240 kcur = NULL;
241 }