1/*-
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/geom/bde/g_bde.c 110697 2003-02-11 12:37:04Z phk $
33 *
34 */
35
36#include <sys/param.h>
37#include <sys/stdint.h>
38#include <sys/bio.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/malloc.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/kthread.h>
45
46#include <crypto/rijndael/rijndael.h>
47#include <crypto/sha2/sha2.h>
48#include <geom/geom.h>
49#include <geom/bde/g_bde.h>
50#define BDE_CLASS_NAME "BDE"
51
52static void
53g_bde_start(struct bio *bp)
54{
55 struct g_geom *gp;
56 struct g_consumer *cp;
57 struct g_bde_softc *sc;
58
59 gp = bp->bio_to->geom;
60 cp = LIST_FIRST(&gp->consumer);
61 sc = gp->softc;
62 switch (bp->bio_cmd) {
63 case BIO_DELETE:
64 case BIO_READ:
65 case BIO_WRITE:
66 g_bde_start1(bp);
67 break;
68 case BIO_GETATTR:
69 case BIO_SETATTR:
70 g_io_deliver(bp, EOPNOTSUPP);
71 break;
72 default:
73 g_io_deliver(bp, EOPNOTSUPP);
74 return;
75 }
76 return;
77}
78
79static void
80g_bde_orphan(struct g_consumer *cp)
81{
82 struct g_geom *gp;
83 struct g_provider *pp;
84 struct g_bde_softc *sc;
85 int error;
86
87 g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name);
88 g_topology_assert();
89 KASSERT(cp->provider->error != 0,
90 ("g_bde_orphan with error == 0"));
91
92 gp = cp->geom;
93 sc = gp->softc;
94 gp->flags |= G_GEOM_WITHER;
95 error = cp->provider->error;
96 LIST_FOREACH(pp, &gp->provider, provider)
97 g_orphan_provider(pp, error);
98 bzero(sc, sizeof(struct g_bde_softc)); /* destroy evidence */
99 return;
100}
101
102static int
103g_bde_access(struct g_provider *pp, int dr, int dw, int de)
104{
105 struct g_geom *gp;
106 struct g_consumer *cp;
107
108 gp = pp->geom;
109 cp = LIST_FIRST(&gp->consumer);
110 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
111 de++;
112 dr++;
113 }
114 /* ... and let go of it on last close */
115 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
116 de--;
117 dr--;
118 }
119 return (g_access_rel(cp, dr, dw, de));
120}
121
122static int
123g_bde_config(struct g_configargs *ga)
124{
125 struct g_geom *gp;
126 struct g_consumer *cp;
127 struct g_provider *pp;
128 struct g_bde_key *kp;
129 int error;
130 u_int sectorsize;
131 off_t mediasize;
132 struct g_bde_softc *sc;
133
134 g_trace(G_T_TOPOLOGY, "g_bde_config(%d)", ga->flag);
135 g_topology_assert();
136 gp = NULL;
137 if (ga->flag == GCFG_DISMANTLE) {
138 /*
139 * Orderly detachment.
140 */
141 if (ga->geom != NULL) {
142 gp = ga->geom;
143 } else if (ga->provider != NULL) {
144 if (ga->provider->geom->class == ga->class) {
145 gp = ga->provider->geom;
146 } else {
147 LIST_FOREACH(cp, &ga->provider->consumers,
148 consumers) {
149 if (cp->geom->class == ga->class) {
150 gp = cp->geom;
151 break;
152 }
153 }
154 }
155 if (gp == NULL)
156 return (EINVAL);
157 } else {
158 return (EINVAL);
159 }
160 KASSERT(gp != NULL, ("NULL geom"));
161 pp = LIST_FIRST(&gp->provider);
162 KASSERT(pp != NULL, ("NULL provider"));
163 if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
164 return (EBUSY);
165 g_orphan_provider(pp, ENXIO);
166 sc = gp->softc;
167 cp = LIST_FIRST(&gp->consumer);
168 KASSERT(cp != NULL, ("NULL consumer"));
169 sc->dead = 1;
170 wakeup(sc);
171 error = g_access_rel(cp, -1, -1, -1);
172 KASSERT(error == 0, ("error on close"));
173 g_detach(cp);
174 g_destroy_consumer(cp);
175 g_topology_unlock();
176 while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
177 tsleep(sc, PRIBIO, "g_bdedie", hz);
178 g_waitidle();
179 g_topology_lock();
180 g_destroy_provider(pp);
181 mtx_destroy(&sc->worklist_mutex);
182 bzero(&sc->key, sizeof sc->key);
183 g_free(sc);
184 g_destroy_geom(gp);
185 return (0);
186 }
187
188 if (ga->flag != GCFG_CREATE)
189 return (EOPNOTSUPP);
190
191 if (ga->provider == NULL)
192 return (EINVAL);
193 /*
194 * Attach
195 */
196 gp = g_new_geomf(ga->class, "%s.bde", ga->provider->name);
197 gp->start = g_bde_start;
198 gp->orphan = g_bde_orphan;
199 gp->access = g_bde_access;
200 gp->spoiled = g_std_spoiled;
201 cp = g_new_consumer(gp);
202 g_attach(cp, ga->provider);
203 error = g_access_rel(cp, 1, 1, 1);
204 if (error) {
205 g_detach(cp);
206 g_destroy_consumer(cp);
207 g_destroy_geom(gp);
208 return (error);
209 }
210 g_topology_unlock();
211 g_waitidle();
212 while (1) {
213 sectorsize = cp->provider->sectorsize;
214 mediasize = cp->provider->mediasize;
215 sc = g_malloc(sizeof(struct g_bde_softc), M_ZERO);
216 gp->softc = sc;
217 sc->geom = gp;
218 sc->consumer = cp;
219
220 error = g_bde_decrypt_lock(sc, ga->ptr,
221 (u_char *)ga->ptr + (sizeof sc->sha2),
222 mediasize, sectorsize, NULL);
223 bzero(sc->sha2, sizeof sc->sha2);
224 if (error)
225 break;
226 kp = &sc->key;
227
228 /* Initialize helper-fields */
229 kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
230 kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
231 kp->zone_width = kp->zone_cont + kp->sectorsize;
232 kp->media_width = kp->sectorN - kp->sector0 -
233 G_BDE_MAXKEYS * kp->sectorsize;
234
235 /* Our external parameters */
236 sc->zone_cont = kp->zone_cont;
237 sc->mediasize = g_bde_max_sector(kp);
238 sc->sectorsize = kp->sectorsize;
239
240 TAILQ_INIT(&sc->freelist);
241 TAILQ_INIT(&sc->worklist);
242 mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
243 mtx_lock(&Giant);
244 /* XXX: error check */
245 kthread_create(g_bde_worker, gp, &sc->thread, 0, 0,
246 "g_bde %s", gp->name);
247 mtx_unlock(&Giant);
248 g_topology_lock();
249 pp = g_new_providerf(gp, gp->name);
250 pp->flags |= G_PF_CANDELETE;
251 pp->mediasize = sc->mediasize;
252 pp->sectorsize = sc->sectorsize;
253 g_error_provider(pp, 0);
254 g_topology_unlock();
255 break;
256 }
257 g_topology_lock();
258 if (error == 0) {
259 ga->geom = gp;
260 return (0);
261 } else {
262 g_access_rel(cp, -1, -1, -1);
263 }
264 g_detach(cp);
265 g_destroy_consumer(cp);
266 if (gp->softc != NULL)
267 g_free(gp->softc);
268 g_destroy_geom(gp);
269 return (error);
270}
271
272static struct g_class g_bde_class = {
273 BDE_CLASS_NAME,
274 NULL,
275 g_bde_config,
276 G_CLASS_INITIALIZER
277};
278
279DECLARE_GEOM_CLASS(g_bde_class, g_bde);
2 * Copyright (c) 2002 Poul-Henning Kamp
3 * Copyright (c) 2002 Networks Associates Technology, Inc.
4 * All rights reserved.
5 *
6 * This software was developed for the FreeBSD Project by Poul-Henning Kamp
7 * and NAI Labs, the Security Research Division of Network Associates, Inc.
8 * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
9 * DARPA CHATS research program.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: head/sys/geom/bde/g_bde.c 110697 2003-02-11 12:37:04Z phk $
33 *
34 */
35
36#include <sys/param.h>
37#include <sys/stdint.h>
38#include <sys/bio.h>
39#include <sys/lock.h>
40#include <sys/mutex.h>
41#include <sys/malloc.h>
42#include <sys/systm.h>
43#include <sys/kernel.h>
44#include <sys/kthread.h>
45
46#include <crypto/rijndael/rijndael.h>
47#include <crypto/sha2/sha2.h>
48#include <geom/geom.h>
49#include <geom/bde/g_bde.h>
50#define BDE_CLASS_NAME "BDE"
51
52static void
53g_bde_start(struct bio *bp)
54{
55 struct g_geom *gp;
56 struct g_consumer *cp;
57 struct g_bde_softc *sc;
58
59 gp = bp->bio_to->geom;
60 cp = LIST_FIRST(&gp->consumer);
61 sc = gp->softc;
62 switch (bp->bio_cmd) {
63 case BIO_DELETE:
64 case BIO_READ:
65 case BIO_WRITE:
66 g_bde_start1(bp);
67 break;
68 case BIO_GETATTR:
69 case BIO_SETATTR:
70 g_io_deliver(bp, EOPNOTSUPP);
71 break;
72 default:
73 g_io_deliver(bp, EOPNOTSUPP);
74 return;
75 }
76 return;
77}
78
79static void
80g_bde_orphan(struct g_consumer *cp)
81{
82 struct g_geom *gp;
83 struct g_provider *pp;
84 struct g_bde_softc *sc;
85 int error;
86
87 g_trace(G_T_TOPOLOGY, "g_bde_orphan(%p/%s)", cp, cp->provider->name);
88 g_topology_assert();
89 KASSERT(cp->provider->error != 0,
90 ("g_bde_orphan with error == 0"));
91
92 gp = cp->geom;
93 sc = gp->softc;
94 gp->flags |= G_GEOM_WITHER;
95 error = cp->provider->error;
96 LIST_FOREACH(pp, &gp->provider, provider)
97 g_orphan_provider(pp, error);
98 bzero(sc, sizeof(struct g_bde_softc)); /* destroy evidence */
99 return;
100}
101
102static int
103g_bde_access(struct g_provider *pp, int dr, int dw, int de)
104{
105 struct g_geom *gp;
106 struct g_consumer *cp;
107
108 gp = pp->geom;
109 cp = LIST_FIRST(&gp->consumer);
110 if (cp->acr == 0 && cp->acw == 0 && cp->ace == 0) {
111 de++;
112 dr++;
113 }
114 /* ... and let go of it on last close */
115 if ((cp->acr + dr) == 0 && (cp->acw + dw) == 0 && (cp->ace + de) == 1) {
116 de--;
117 dr--;
118 }
119 return (g_access_rel(cp, dr, dw, de));
120}
121
122static int
123g_bde_config(struct g_configargs *ga)
124{
125 struct g_geom *gp;
126 struct g_consumer *cp;
127 struct g_provider *pp;
128 struct g_bde_key *kp;
129 int error;
130 u_int sectorsize;
131 off_t mediasize;
132 struct g_bde_softc *sc;
133
134 g_trace(G_T_TOPOLOGY, "g_bde_config(%d)", ga->flag);
135 g_topology_assert();
136 gp = NULL;
137 if (ga->flag == GCFG_DISMANTLE) {
138 /*
139 * Orderly detachment.
140 */
141 if (ga->geom != NULL) {
142 gp = ga->geom;
143 } else if (ga->provider != NULL) {
144 if (ga->provider->geom->class == ga->class) {
145 gp = ga->provider->geom;
146 } else {
147 LIST_FOREACH(cp, &ga->provider->consumers,
148 consumers) {
149 if (cp->geom->class == ga->class) {
150 gp = cp->geom;
151 break;
152 }
153 }
154 }
155 if (gp == NULL)
156 return (EINVAL);
157 } else {
158 return (EINVAL);
159 }
160 KASSERT(gp != NULL, ("NULL geom"));
161 pp = LIST_FIRST(&gp->provider);
162 KASSERT(pp != NULL, ("NULL provider"));
163 if (pp->acr > 0 || pp->acw > 0 || pp->ace > 0)
164 return (EBUSY);
165 g_orphan_provider(pp, ENXIO);
166 sc = gp->softc;
167 cp = LIST_FIRST(&gp->consumer);
168 KASSERT(cp != NULL, ("NULL consumer"));
169 sc->dead = 1;
170 wakeup(sc);
171 error = g_access_rel(cp, -1, -1, -1);
172 KASSERT(error == 0, ("error on close"));
173 g_detach(cp);
174 g_destroy_consumer(cp);
175 g_topology_unlock();
176 while (sc->dead != 2 && !LIST_EMPTY(&pp->consumers))
177 tsleep(sc, PRIBIO, "g_bdedie", hz);
178 g_waitidle();
179 g_topology_lock();
180 g_destroy_provider(pp);
181 mtx_destroy(&sc->worklist_mutex);
182 bzero(&sc->key, sizeof sc->key);
183 g_free(sc);
184 g_destroy_geom(gp);
185 return (0);
186 }
187
188 if (ga->flag != GCFG_CREATE)
189 return (EOPNOTSUPP);
190
191 if (ga->provider == NULL)
192 return (EINVAL);
193 /*
194 * Attach
195 */
196 gp = g_new_geomf(ga->class, "%s.bde", ga->provider->name);
197 gp->start = g_bde_start;
198 gp->orphan = g_bde_orphan;
199 gp->access = g_bde_access;
200 gp->spoiled = g_std_spoiled;
201 cp = g_new_consumer(gp);
202 g_attach(cp, ga->provider);
203 error = g_access_rel(cp, 1, 1, 1);
204 if (error) {
205 g_detach(cp);
206 g_destroy_consumer(cp);
207 g_destroy_geom(gp);
208 return (error);
209 }
210 g_topology_unlock();
211 g_waitidle();
212 while (1) {
213 sectorsize = cp->provider->sectorsize;
214 mediasize = cp->provider->mediasize;
215 sc = g_malloc(sizeof(struct g_bde_softc), M_ZERO);
216 gp->softc = sc;
217 sc->geom = gp;
218 sc->consumer = cp;
219
220 error = g_bde_decrypt_lock(sc, ga->ptr,
221 (u_char *)ga->ptr + (sizeof sc->sha2),
222 mediasize, sectorsize, NULL);
223 bzero(sc->sha2, sizeof sc->sha2);
224 if (error)
225 break;
226 kp = &sc->key;
227
228 /* Initialize helper-fields */
229 kp->keys_per_sector = kp->sectorsize / G_BDE_SKEYLEN;
230 kp->zone_cont = kp->keys_per_sector * kp->sectorsize;
231 kp->zone_width = kp->zone_cont + kp->sectorsize;
232 kp->media_width = kp->sectorN - kp->sector0 -
233 G_BDE_MAXKEYS * kp->sectorsize;
234
235 /* Our external parameters */
236 sc->zone_cont = kp->zone_cont;
237 sc->mediasize = g_bde_max_sector(kp);
238 sc->sectorsize = kp->sectorsize;
239
240 TAILQ_INIT(&sc->freelist);
241 TAILQ_INIT(&sc->worklist);
242 mtx_init(&sc->worklist_mutex, "g_bde_worklist", NULL, MTX_DEF);
243 mtx_lock(&Giant);
244 /* XXX: error check */
245 kthread_create(g_bde_worker, gp, &sc->thread, 0, 0,
246 "g_bde %s", gp->name);
247 mtx_unlock(&Giant);
248 g_topology_lock();
249 pp = g_new_providerf(gp, gp->name);
250 pp->flags |= G_PF_CANDELETE;
251 pp->mediasize = sc->mediasize;
252 pp->sectorsize = sc->sectorsize;
253 g_error_provider(pp, 0);
254 g_topology_unlock();
255 break;
256 }
257 g_topology_lock();
258 if (error == 0) {
259 ga->geom = gp;
260 return (0);
261 } else {
262 g_access_rel(cp, -1, -1, -1);
263 }
264 g_detach(cp);
265 g_destroy_consumer(cp);
266 if (gp->softc != NULL)
267 g_free(gp->softc);
268 g_destroy_geom(gp);
269 return (error);
270}
271
272static struct g_class g_bde_class = {
273 BDE_CLASS_NAME,
274 NULL,
275 g_bde_config,
276 G_CLASS_INITIALIZER
277};
278
279DECLARE_GEOM_CLASS(g_bde_class, g_bde);