Module Name: src Committed By: mbalmer Date: Fri Aug 14 21:17:22 UTC 2009
Modified Files: src/distrib/sets/lists/man: mi src/share/man/man4: Makefile src/sys/conf: files src/sys/dev/gpio: files.gpio src/sys/secmodel: files.secmodel src/sys/sys: Makefile Added Files: src/share/man/man4: gpiolock.4 src/sys/dev: keylock.c src/sys/dev/gpio: gpiolock.c src/sys/secmodel/keylock: files.keylock keylock.h secmodel_keylock.c src/sys/sys: keylock.h Log Message: Add support for multi-position electro-mechanical keylocks. An example driver, gpiolock(4), is provided as an example how to interface real hardware. A new securemodel, securemodel_keylock, is provided to show how this can be used to tie keylocks to overall system security. This is experimental code. The diff has been on tech-kern for several weeks. Reviewed by many, kauth(9) integration reviewed by Elad Efrat; approved by tonnerre@ and t...@. Thanks to everyone who provided feedback. To generate a diff of this commit: cvs rdiff -u -r1.1152 -r1.1153 src/distrib/sets/lists/man/mi cvs rdiff -u -r1.496 -r1.497 src/share/man/man4/Makefile cvs rdiff -u -r0 -r1.1 src/share/man/man4/gpiolock.4 cvs rdiff -u -r1.952 -r1.953 src/sys/conf/files cvs rdiff -u -r0 -r1.1 src/sys/dev/keylock.c cvs rdiff -u -r1.7 -r1.8 src/sys/dev/gpio/files.gpio cvs rdiff -u -r0 -r1.1 src/sys/dev/gpio/gpiolock.c cvs rdiff -u -r1.2 -r1.3 src/sys/secmodel/files.secmodel cvs rdiff -u -r0 -r1.1 src/sys/secmodel/keylock/files.keylock \ src/sys/secmodel/keylock/keylock.h \ src/sys/secmodel/keylock/secmodel_keylock.c cvs rdiff -u -r1.118 -r1.119 src/sys/sys/Makefile cvs rdiff -u -r0 -r1.1 src/sys/sys/keylock.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/distrib/sets/lists/man/mi diff -u src/distrib/sets/lists/man/mi:1.1152 src/distrib/sets/lists/man/mi:1.1153 --- src/distrib/sets/lists/man/mi:1.1152 Sun Aug 9 08:20:53 2009 +++ src/distrib/sets/lists/man/mi Fri Aug 14 21:17:21 2009 @@ -1,4 +1,4 @@ -# $NetBSD: mi,v 1.1152 2009/08/09 08:20:53 mbalmer Exp $ +# $NetBSD: mi,v 1.1153 2009/08/14 21:17:21 mbalmer Exp $ # # Note: don't delete entries from here - mark them as "obsolete" instead. # @@ -939,6 +939,7 @@ ./usr/share/man/cat4/gpib.0 man-sys-catman .cat ./usr/share/man/cat4/gpio.0 man-sys-catman .cat ./usr/share/man/cat4/gpioiic.0 man-sys-catman .cat +./usr/share/man/cat4/gpiolock.0 man-sys-catman .cat ./usr/share/man/cat4/gpioow.0 man-sys-catman .cat ./usr/share/man/cat4/gpiosim.0 man-sys-catman .cat ./usr/share/man/cat4/gre.0 man-sys-catman .cat @@ -3548,6 +3549,7 @@ ./usr/share/man/html4/gpib.html man-sys-htmlman html ./usr/share/man/html4/gpio.html man-sys-htmlman html ./usr/share/man/html4/gpioiic.html man-sys-htmlman html +./usr/share/man/html4/gpiolock.html man-sys-htmlman html ./usr/share/man/html4/gpioow.html man-sys-htmlman html ./usr/share/man/html4/gpiosim.html man-sys-htmlman html ./usr/share/man/html4/gre.html man-sys-htmlman html @@ -5937,6 +5939,7 @@ ./usr/share/man/man4/gpib.4 man-sys-man .man ./usr/share/man/man4/gpio.4 man-sys-man .man ./usr/share/man/man4/gpioiic.4 man-sys-man .man +./usr/share/man/man4/gpiolock.4 man-sys-man .man ./usr/share/man/man4/gpioow.4 man-sys-man .man ./usr/share/man/man4/gpiosim.4 man-sys-man .man ./usr/share/man/man4/gre.4 man-sys-man .man Index: src/share/man/man4/Makefile diff -u src/share/man/man4/Makefile:1.496 src/share/man/man4/Makefile:1.497 --- src/share/man/man4/Makefile:1.496 Sun Aug 9 08:20:53 2009 +++ src/share/man/man4/Makefile Fri Aug 14 21:17:21 2009 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.496 2009/08/09 08:20:53 mbalmer Exp $ +# $NetBSD: Makefile,v 1.497 2009/08/14 21:17:21 mbalmer Exp $ # @(#)Makefile 8.1 (Berkeley) 6/18/93 MAN= aac.4 ac97.4 acardide.4 aceride.4 acphy.4 acpidalb.4 \ @@ -25,8 +25,8 @@ esa.4 esiop.4 esm.4 eso.4 etherip.4 exphy.4 \ fast_ipsec.4 fd.4 finsio.4 fpa.4 fms.4 fss.4 fxp.4 \ gcscaudio.4 gem.4 genfb.4 gentbi.4 geodeide.4 \ - glxtphy.4 gpib.4 gpio.4 gpiosim.4 gre.4 gphyter.4 gsip.4 hifn.4 hme.4 \ - hpqlb.4 hptide.4 \ + glxtphy.4 gpib.4 gpio.4 gpiolock.4 gpiosim.4 gre.4 gphyter.4 gsip.4 \ + hifn.4 hme.4 hpqlb.4 hptide.4 \ ichlpcib.4 ichsmb.4 icmp.4 icp.4 icsphy.4 iee.4 ieee80211.4 \ ifmedia.4 igsfb.4 iha.4 iic.4 inet.4 ikphy.4 inphy.4 intersil7170.4 \ ioasic.4 ioat.4 iop.4 iophy.4 iopsp.4 ip.4 ipkdb.4 ipmi.4 ipw.4 \ Index: src/sys/conf/files diff -u src/sys/conf/files:1.952 src/sys/conf/files:1.953 --- src/sys/conf/files:1.952 Sun Aug 9 06:40:10 2009 +++ src/sys/conf/files Fri Aug 14 21:17:21 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files,v 1.952 2009/08/09 06:40:10 kiyohara Exp $ +# $NetBSD: files,v 1.953 2009/08/14 21:17:21 mbalmer Exp $ # @(#)files.newconf 7.5 (Berkeley) 5/10/93 version 20090313 @@ -24,6 +24,7 @@ defflag PTRACE defflag COREDUMP defflag MODULAR +defflag KEYLOCK defparam DEFCORENAME defparam HZ @@ -1371,6 +1372,7 @@ file dev/dkwedge/dkwedge_mbr.c dkwedge_method_mbr file dev/firmload.c firmload file dev/fss.c fss needs-count +file dev/keylock.c keylock file dev/lockstat.c lockstat needs-flag file dev/md.c md needs-count file dev/midi.c midi | midibus needs-flag Index: src/sys/dev/gpio/files.gpio diff -u src/sys/dev/gpio/files.gpio:1.7 src/sys/dev/gpio/files.gpio:1.8 --- src/sys/dev/gpio/files.gpio:1.7 Sun Aug 9 08:18:00 2009 +++ src/sys/dev/gpio/files.gpio Fri Aug 14 21:17:22 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files.gpio,v 1.7 2009/08/09 08:18:00 mbalmer Exp $ +# $NetBSD: files.gpio,v 1.8 2009/08/14 21:17:22 mbalmer Exp $ define gpio {[offset = -1], [mask = 0]} @@ -19,3 +19,8 @@ device gpioow: onewirebus, onewire_bitbang attach gpioow at gpio file dev/gpio/gpioow.c gpioow + +# Keylock +device gpiolock: gpiobus +attach gpiolock at gpio +file dev/gpio/gpiolock.c gpiolock Index: src/sys/secmodel/files.secmodel diff -u src/sys/secmodel/files.secmodel:1.2 src/sys/secmodel/files.secmodel:1.3 --- src/sys/secmodel/files.secmodel:1.2 Wed Nov 21 22:49:07 2007 +++ src/sys/secmodel/files.secmodel Fri Aug 14 21:17:22 2009 @@ -1,4 +1,4 @@ -# $NetBSD: files.secmodel,v 1.2 2007/11/21 22:49:07 elad Exp $ +# $NetBSD: files.secmodel,v 1.3 2009/08/14 21:17:22 mbalmer Exp $ # # Traditional 4.4BSD - Securelevel @@ -14,3 +14,8 @@ # Sample overlay model on-top of the traditional one # include "secmodel/overlay/files.overlay" + +# +# Multi-position keylock +# +include "secmodel/keylock/files.keylock" Index: src/sys/sys/Makefile diff -u src/sys/sys/Makefile:1.118 src/sys/sys/Makefile:1.119 --- src/sys/sys/Makefile:1.118 Mon Nov 24 16:05:21 2008 +++ src/sys/sys/Makefile Fri Aug 14 21:17:22 2009 @@ -1,4 +1,4 @@ -# $NetBSD: Makefile,v 1.118 2008/11/24 16:05:21 joerg Exp $ +# $NetBSD: Makefile,v 1.119 2009/08/14 21:17:22 mbalmer Exp $ .include <bsd.sys.mk> @@ -17,7 +17,7 @@ float_ieee754.h fstypes.h gcq.h gmon.h gpio.h hash.h \ ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \ joystick.h \ - kcore.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \ + kcore.h keylock.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \ localedef.h lock.h lockf.h lwp.h lwpctl.h \ malloc.h mallocvar.h mbuf.h md4.h md5.h midiio.h \ mman.h module.h mount.h mqueue.h msg.h msgbuf.h mtio.h mutex.h \ Added files: Index: src/share/man/man4/gpiolock.4 diff -u /dev/null src/share/man/man4/gpiolock.4:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/share/man/man4/gpiolock.4 Fri Aug 14 21:17:21 2009 @@ -0,0 +1,67 @@ +.\" $NetBSD: gpiolock.4,v 1.1 2009/08/14 21:17:21 mbalmer Exp $ +.\" +.\" Copyright (c) 2009 Marc Balmer <m...@msys.ch> +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" +.Dd August 10, 2009 +.Dt GPIOLOCK 4 +.Os +.Sh NAME +.Nm gpiolock +.Nd support for multi-position keylocks attached to GPIO pins +.Sh SYNOPSIS +.Cd "gpiolock* at gpio? offset ? mask ?" +.Cd "gpiolock* at gpio?" +.Sh DESCRIPTION +The +.Nm +driver allows connecting of multi-position keylocks over GPIO pins. +The keylock driver registers with a in-kernel keylock supporting system +and provides +.Xr kauth 9 +support through an experimental security model. +The keylock state can be queried using the hw.keylock sysctl variables. +Only locks with 2-4 positions are currently supported. +The pin number is specified in the kernel configuration with the +.Ar offset +locator. +The +.Ar mask +locator denotes the pins used for the lock (minimum 2, maximum 4 pins are used). +The +.Ar offset +and +.Ar mask +can also be specified when +.Nm +is attached at runtime using the +.Dv GPIOATTACH +.Xr ioctl 2 +on the +.Xr gpio 4 +device. +.Sh SEE ALSO +.Xr gpio 4 , +.Xr intro 4 , +.Sh HISTORY +The +.Nm +driver first appeared in +.Nx 5.0 . +.Sh AUTHORS +.An -nosplit +The +.Nm +driver was written by +.An Marc Balmer Aq m...@msys.ch . Index: src/sys/dev/keylock.c diff -u /dev/null src/sys/dev/keylock.c:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/dev/keylock.c Fri Aug 14 21:17:22 2009 @@ -0,0 +1,210 @@ +/* $NetBSD: keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */ + +/* + * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_secmodel_keylock.h" + +/* Support for multi-position electro-mechanical keylocks */ + +#include <sys/param.h> +#include <sys/kernel.h> +#include <sys/keylock.h> +#include <sys/sysctl.h> + +#ifdef secmodel_keylock +#include <sys/kauth.h> +#include <secmodel/keylock/keylock.h> +#endif + +static int (*keylock_pos_cb)(void *) = NULL; +static void *keylock_pos_cb_arg = NULL; +static int keylock_npos = 0; +static int keylock_order = 0; + +int keylock_pos_sysctl(SYSCTLFN_PROTO); +int keylock_state_sysctl(SYSCTLFN_PROTO); +int keylock_order_sysctl(SYSCTLFN_PROTO); + +SYSCTL_SETUP(sysctl_keylock_setup, "sysctl keylock setup") +{ + const struct sysctlnode *node = NULL; + + sysctl_createv(clog, 0, NULL, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "hw", NULL, + NULL, 0, NULL, 0, + CTL_HW, CTL_EOL); + sysctl_createv(clog, 0, NULL, &node, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "keylock", + SYSCTL_DESCR("Keylock state"), + NULL, 0, NULL, 0, + CTL_HW, CTL_CREATE, CTL_EOL); + + if (node == NULL) + return; + + sysctl_createv(clog, 0, &node, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READONLY, + CTLTYPE_INT, "pos", + SYSCTL_DESCR("Current keylock position"), + keylock_pos_sysctl, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &node, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READONLY, + CTLTYPE_INT, "npos", + SYSCTL_DESCR("Number of keylock positions"), + NULL, 0, &keylock_npos, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &node, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READONLY, + CTLTYPE_INT, "state", + SYSCTL_DESCR("Keylock state"), + keylock_state_sysctl, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + sysctl_createv(clog, 0, &node, NULL, + CTLFLAG_PERMANENT | CTLFLAG_READWRITE, + CTLTYPE_INT, "order", + SYSCTL_DESCR("Keylock closedness order"), + keylock_order_sysctl, 0, NULL, 0, + CTL_CREATE, CTL_EOL); +} + +int +keylock_register(void *cb_arg, int npos, int (*cb)(void *)) +{ + if (keylock_pos_cb != NULL) + return -1; + + keylock_pos_cb = cb; + keylock_pos_cb_arg = cb_arg; + keylock_npos = npos; +#ifdef secmodel_keylock + secmodel_keylock_start(); +#endif + return 0; +} + +void +keylock_unregister(void *cb_arg, int (*cb)(void *)) +{ + if (keylock_pos_cb != cb || keylock_pos_cb_arg != cb_arg) + return; + +#ifdef secmodel_keylock + secmodel_keylock_stop(); +#endif + keylock_pos_cb = NULL; + keylock_pos_cb_arg = NULL; + keylock_npos = 0; +} + +int +keylock_position(void) +{ + if (keylock_pos_cb == NULL) + return 0; + + return (*keylock_pos_cb)(keylock_pos_cb_arg); +} + +int +keylock_num_positions(void) +{ + return keylock_npos; +} + +int +keylock_state(void) +{ + int pos; + + if (keylock_npos == 0) + return KEYLOCK_ABSENT; + + pos = keylock_position(); + if (pos == 0) + return KEYLOCK_TAMPER; + + /* + * XXX How should the intermediate positions be handled? + * At the moment only the ultimate positions are properly handled, + * we need to think about what we do with the intermediate positions. + * For now we return KEYLOCK_SEMIOPEN for them. + */ + if (pos == 1) + return keylock_order == 0 ? KEYLOCK_CLOSE : KEYLOCK_OPEN; + else if (pos == keylock_npos) + return keylock_order == 0 ? KEYLOCK_OPEN : KEYLOCK_CLOSE; + return KEYLOCK_SEMIOPEN; +} + +int +keylock_pos_sysctl(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + int val; + + node = *rnode; + node.sysctl_data = &val; + + val = keylock_position(); + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +int +keylock_state_sysctl(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + int val; + + node = *rnode; + node.sysctl_data = &val; + + val = keylock_state(); + return sysctl_lookup(SYSCTLFN_CALL(&node)); +} + +int +keylock_order_sysctl(SYSCTLFN_ARGS) +{ + struct sysctlnode node; + int val, error; + + node = *rnode; + node.sysctl_data = &val; + + val = keylock_order; + error = sysctl_lookup(SYSCTLFN_CALL(&node)); + if (error || newp == NULL) + return error; + if (keylock_state() != KEYLOCK_OPEN) + return -1; + + keylock_order = val; + return 0; +} + Index: src/sys/dev/gpio/gpiolock.c diff -u /dev/null src/sys/dev/gpio/gpiolock.c:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/dev/gpio/gpiolock.c Fri Aug 14 21:17:22 2009 @@ -0,0 +1,178 @@ +/* $NetBSD: gpiolock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */ + +/* + * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Driver for multi-position keylocks on GPIO pins + */ + +#include "opt_keylock.h" + +#include <sys/param.h> +#include <sys/device.h> +#include <sys/gpio.h> +#include <sys/keylock.h> + +#include <dev/gpio/gpiovar.h> + +#define GPIOLOCK_MAXPINS 4 +#define GPIOLOCK_MINPINS 2 + +struct gpiolock_softc { + void * sc_gpio; + struct gpio_pinmap sc_map; + int _map[GPIOLOCK_MAXPINS]; + + int sc_npins; + int sc_data; + int sc_dying; +}; + +int gpiolock_match(device_t, cfdata_t, void *); +void gpiolock_attach(device_t, device_t, void *); +int gpiolock_detach(device_t, int); +int gpiolock_activate(device_t, enum devact); +int gpiolock_position(void *); + +CFATTACH_DECL_NEW(gpiolock, sizeof(struct gpiolock_softc), + gpiolock_match, gpiolock_attach, gpiolock_detach, gpiolock_activate); + +extern struct cfdriver gpiolock_cd; + +int +gpiolock_match(device_t parent, cfdata_t cf, + void *aux) +{ + struct gpio_attach_args *ga = aux; + int npins; + + if (strcmp(ga->ga_dvname, cf->cf_name)) + return 0; + + if (ga->ga_offset == -1) + return 0; + + /* Check number of pins */ + npins = gpio_npins(ga->ga_mask); + if (npins < GPIOLOCK_MINPINS || npins > GPIOLOCK_MAXPINS) { + aprint_debug("%s: invalid pin mask 0x%02x\n", cf->cf_name, + ga->ga_mask); + return 0; + } + + return 1; +} + +void +gpiolock_attach(device_t parent, device_t self, void *aux) +{ + struct gpiolock_softc *sc = device_private(self); + struct gpio_attach_args *ga = aux; + int pin, caps; + + sc->sc_npins = gpio_npins(ga->ga_mask); + + /* Map pins */ + sc->sc_gpio = ga->ga_gpio; + sc->sc_map.pm_map = sc->_map; + if (gpio_pin_map(sc->sc_gpio, ga->ga_offset, ga->ga_mask, + &sc->sc_map)) { + aprint_error(": can't map pins\n"); + return; + } + + /* Configure data pins */ + for (pin = 0; pin < sc->sc_npins; pin++) { + caps = gpio_pin_caps(sc->sc_gpio, &sc->sc_map, pin); + if (!(caps & GPIO_PIN_INPUT)) { + aprint_error(": data pin is unable to read input\n"); + goto fail; + } + aprint_normal(" [%d]", sc->sc_map.pm_map[pin]); + sc->sc_data = GPIO_PIN_INPUT; + gpio_pin_ctl(sc->sc_gpio, &sc->sc_map, pin, sc->sc_data); + } + +#ifdef KEYLOCK + /* Register keylock */ + if (keylock_register(self, sc->sc_npins, gpiolock_position)) { + aprint_error(": can't register keylock\n"); + goto fail; + } +#endif + pmf_device_register(self, NULL, NULL); + + aprint_normal("\n"); + return; + +fail: + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); +} + +int +gpiolock_detach(device_t self, int flags) +{ + struct gpiolock_softc *sc = device_private(self); + + pmf_device_deregister(self); +#ifdef KEYLOCK + keylock_unregister(self, gpiolock_position); +#endif + gpio_pin_unmap(sc->sc_gpio, &sc->sc_map); + + return 0; +} + +int +gpiolock_activate(device_t self, enum devact act) +{ + struct gpiolock_softc *sc = device_private(self); + + switch (act) { + case DVACT_ACTIVATE: + return EOPNOTSUPP; + case DVACT_DEACTIVATE: + sc->sc_dying = 1; + break; + } + + return 0; +} + +int +gpiolock_position(void *arg) +{ + struct gpiolock_softc *sc = device_private((device_t)arg); + int pos, pin; + + for (pos = pin = 0; pin < sc->sc_npins; pin++) { + if (gpio_pin_read(sc->sc_gpio, &sc->sc_map, pin) == + GPIO_PIN_HIGH) + pos = pin + 1; + } + return pos; +} + Index: src/sys/secmodel/keylock/files.keylock diff -u /dev/null src/sys/secmodel/keylock/files.keylock:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/secmodel/keylock/files.keylock Fri Aug 14 21:17:22 2009 @@ -0,0 +1,5 @@ +# $NetBSD: files.keylock,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ + +defflag secmodel_keylock + +file secmodel/keylock/secmodel_keylock.c secmodel_keylock Index: src/sys/secmodel/keylock/keylock.h diff -u /dev/null src/sys/secmodel/keylock/keylock.h:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/secmodel/keylock/keylock.h Fri Aug 14 21:17:22 2009 @@ -0,0 +1,51 @@ +/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */ +/*- + * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SECMODEL_KEYLOCK_KEYLOCK_H_ +#define _SECMODEL_KEYLOCK_KEYLOCK_H_ + +int secmodel_keylock_sysctl(SYSCTLFN_PROTO); + +void secmodel_keylock_init(void); +void secmodel_keylock_start(void); +void secmodel_keylock_stop(void); + +#if defined(_LKM) +SYSCTL_SETUP_PROTO(sysctl_security_keylock_setup); +#endif /* _LKM */ + +int secmodel_keylock_system_cb(kauth_cred_t, kauth_action_t, void *, + void *, void *, void *, void *); +int secmodel_keylock_process_cb(kauth_cred_t, kauth_action_t, void *, + void *, void *, void *, void *); +int secmodel_keylock_network_cb(kauth_cred_t, kauth_action_t, void *, + void *, void *, void *, void *); +int secmodel_keylock_machdep_cb(kauth_cred_t, kauth_action_t, void *, + void *, void *, void *, void *); +int secmodel_keylock_device_cb(kauth_cred_t, kauth_action_t, void *, + void *, void *, void *, void *); + +#endif /* !_SECMODEL_KEYLOCK_KEYLOCK_H_ */ Index: src/sys/secmodel/keylock/secmodel_keylock.c diff -u /dev/null src/sys/secmodel/keylock/secmodel_keylock.c:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/secmodel/keylock/secmodel_keylock.c Fri Aug 14 21:17:22 2009 @@ -0,0 +1,548 @@ +/* $NetBSD: secmodel_keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */ +/*- + * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * Copyright (c) 2006 Elad Efrat <e...@netbsd.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file contains kauth(9) listeners needed to implement an experimental + * keylock based security scheme. + * + * The position of the keylock is a system-global indication on what + * operations are allowed or not. It affects all users, including root. + * + * Rules: + * + * - If the number of possible keylock positions is 0, assume there is no + * keylock present, do not dissallow any action, i.e. do nothing + * + * - If the number of possible keylock positions is greater than 0, but the + * current lock position is 0, assume tampering with the lock and forbid + * all actions. + * + * - If the lock is in the lowest position, assume the system is locked and + * forbid most actions. + * + * - If the lock is in the highest position, assume the system to be open and + * forbid nothing. + * + * - If the security.models.keylock.order sysctl is set to a value != 0, + * reverse this order. + */ + +#include <sys/cdefs.h> +__KERNEL_RCSID(0, "$NetBSD: secmodel_keylock.c,v 1.1 2009/08/14 21:17:22 mbalmer Exp $"); + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/kauth.h> + +#include <sys/conf.h> +#include <sys/keylock.h> +#include <sys/mount.h> +#include <sys/sysctl.h> +#include <sys/vnode.h> + +#include <miscfs/specfs/specdev.h> + +#include <secmodel/keylock/keylock.h> + +static kauth_listener_t l_system, l_process, l_network, l_machdep, l_device; + +SYSCTL_SETUP(sysctl_security_keylock_setup, + "sysctl security keylock setup") +{ + const struct sysctlnode *rnode; + + sysctl_createv(clog, 0, NULL, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "security", NULL, + NULL, 0, NULL, 0, + CTL_SECURITY, CTL_EOL); + + sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "models", NULL, + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + + sysctl_createv(clog, 0, &rnode, &rnode, + CTLFLAG_PERMANENT, + CTLTYPE_NODE, "keylock", + SYSCTL_DESCR("Keylock security model"), + NULL, 0, NULL, 0, + CTL_CREATE, CTL_EOL); + + sysctl_createv(clog, 0, &rnode, NULL, + CTLFLAG_PERMANENT, + CTLTYPE_STRING, "name", NULL, + NULL, 0, __UNCONST("Keylock"), 0, + CTL_CREATE, CTL_EOL); +} + +void +secmodel_keylock_init(void) +{ +} + +void +secmodel_keylock_start(void) +{ + l_system = kauth_listen_scope(KAUTH_SCOPE_SYSTEM, + secmodel_keylock_system_cb, NULL); + l_process = kauth_listen_scope(KAUTH_SCOPE_PROCESS, + secmodel_keylock_process_cb, NULL); + l_network = kauth_listen_scope(KAUTH_SCOPE_NETWORK, + secmodel_keylock_network_cb, NULL); + l_machdep = kauth_listen_scope(KAUTH_SCOPE_MACHDEP, + secmodel_keylock_machdep_cb, NULL); + l_device = kauth_listen_scope(KAUTH_SCOPE_DEVICE, + secmodel_keylock_device_cb, NULL); +} + +void +secmodel_keylock_stop(void) +{ + kauth_unlisten_scope(l_system); + kauth_unlisten_scope(l_process); + kauth_unlisten_scope(l_network); + kauth_unlisten_scope(l_machdep); + kauth_unlisten_scope(l_device); +} + +/* + * kauth(9) listener + * + * Security model: Multi-position keylock + * Scope: System + * Responsibility: Keylock + */ +int +secmodel_keylock_system_cb(kauth_cred_t cred, + kauth_action_t action, void *cookie, void *arg0, void *arg1, + void *arg2, void *arg3) +{ + int result; + enum kauth_system_req req; + int kstate; + + kstate = keylock_state(); + if (kstate == KEYLOCK_ABSENT) + return KAUTH_RESULT_DEFER; + else if (kstate == KEYLOCK_TAMPER) + return KAUTH_RESULT_DENY; + + result = KAUTH_RESULT_DEFER; + req = (enum kauth_system_req)arg0; + + switch (action) { + case KAUTH_SYSTEM_CHSYSFLAGS: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + + case KAUTH_SYSTEM_TIME: + switch (req) { + case KAUTH_REQ_SYSTEM_TIME_RTCOFFSET: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + + case KAUTH_REQ_SYSTEM_TIME_SYSTEM: { + struct timespec *ts = arg1; + struct timespec *delta = arg2; + + /* + * Don't allow the time to be set forward so far it + * will wrap and become negative, thus allowing an + * attacker to bypass the next check below. The + * cutoff is 1 year before rollover occurs, so even + * if the attacker uses adjtime(2) to move the time + * past the cutoff, it will take a very long time + * to get to the wrap point. + */ + if (keylock_position() > 1 && + ((ts->tv_sec > LLONG_MAX - 365*24*60*60) || + (delta->tv_sec < 0 || delta->tv_nsec < 0))) + result = KAUTH_RESULT_DENY; + break; + } + default: + break; + } + break; + + case KAUTH_SYSTEM_MODULE: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + + case KAUTH_SYSTEM_MOUNT: + switch (req) { + case KAUTH_REQ_SYSTEM_MOUNT_NEW: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + + break; + + case KAUTH_REQ_SYSTEM_MOUNT_UPDATE: + if (kstate == KEYLOCK_CLOSE) { + struct mount *mp = arg1; + u_long flags = (u_long)arg2; + + /* + * Can only degrade from read/write to + * read-only. + */ + if (flags != (mp->mnt_flag | MNT_RDONLY | + MNT_RELOAD | MNT_FORCE | MNT_UPDATE)) + result = KAUTH_RESULT_DENY; + } + break; + default: + break; + } + + break; + + case KAUTH_SYSTEM_SYSCTL: + switch (req) { + case KAUTH_REQ_SYSTEM_SYSCTL_ADD: + case KAUTH_REQ_SYSTEM_SYSCTL_DELETE: + case KAUTH_REQ_SYSTEM_SYSCTL_DESC: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + default: + break; + } + break; + + case KAUTH_SYSTEM_SETIDCORE: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + + case KAUTH_SYSTEM_DEBUG: + switch (req) { + case KAUTH_REQ_SYSTEM_DEBUG_IPKDB: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + default: + break; + } + break; + } + + return result; +} + +/* + * kauth(9) listener + * + * Security model: Multi-position keylock + * Scope: Process + * Responsibility: Keylock + */ +int +secmodel_keylock_process_cb(kauth_cred_t cred, + kauth_action_t action, void *cookie, void *arg0, + void *arg1, void *arg2, void *arg3) +{ + struct proc *p; + int result, kstate; + + kstate = keylock_state(); + if (kstate == KEYLOCK_ABSENT) + return KAUTH_RESULT_DEFER; + else if (kstate == KEYLOCK_TAMPER) + return KAUTH_RESULT_DENY; + + result = KAUTH_RESULT_DEFER; + p = arg0; + + switch (action) { + case KAUTH_PROCESS_PROCFS: { + enum kauth_process_req req; + + req = (enum kauth_process_req)arg2; + switch (req) { + case KAUTH_REQ_PROCESS_PROCFS_READ: + break; + + case KAUTH_REQ_PROCESS_PROCFS_RW: + case KAUTH_REQ_PROCESS_PROCFS_WRITE: + if ((p == initproc) && (kstate != KEYLOCK_OPEN)) + result = KAUTH_RESULT_DENY; + + break; + default: + break; + } + + break; + } + + case KAUTH_PROCESS_PTRACE: + if ((p == initproc) && (kstate != KEYLOCK_OPEN)) + result = KAUTH_RESULT_DENY; + + break; + + case KAUTH_PROCESS_CORENAME: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + } + return result; +} + +/* + * kauth(9) listener + * + * Security model: Multi-position keylock + * Scope: Network + * Responsibility: Keylock + */ +int +secmodel_keylock_network_cb(kauth_cred_t cred, + kauth_action_t action, void *cookie, void *arg0, + void *arg1, void *arg2, void *arg3) +{ + int result, kstate; + enum kauth_network_req req; + + kstate = keylock_state(); + if (kstate == KEYLOCK_ABSENT) + return KAUTH_RESULT_DEFER; + else if (kstate == KEYLOCK_TAMPER) + return KAUTH_RESULT_DENY; + + result = KAUTH_RESULT_DEFER; + req = (enum kauth_network_req)arg0; + + switch (action) { + case KAUTH_NETWORK_FIREWALL: + switch (req) { + case KAUTH_REQ_NETWORK_FIREWALL_FW: + case KAUTH_REQ_NETWORK_FIREWALL_NAT: + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + break; + + default: + break; + } + break; + + case KAUTH_NETWORK_FORWSRCRT: + if (kstate != KEYLOCK_OPEN) + result = KAUTH_RESULT_DENY; + break; + } + + return result; +} + +/* + * kauth(9) listener + * + * Security model: Multi-position keylock + * Scope: Machdep + * Responsibility: Keylock + */ +int +secmodel_keylock_machdep_cb(kauth_cred_t cred, + kauth_action_t action, void *cookie, void *arg0, + void *arg1, void *arg2, void *arg3) +{ + int result, kstate; + + kstate = keylock_state(); + if (kstate == KEYLOCK_ABSENT) + return KAUTH_RESULT_DEFER; + else if (kstate == KEYLOCK_TAMPER) + return KAUTH_RESULT_DENY; + + result = KAUTH_RESULT_DEFER; + + switch (action) { + case KAUTH_MACHDEP_IOPERM_SET: + case KAUTH_MACHDEP_IOPL: + if (kstate != KEYLOCK_OPEN) + result = KAUTH_RESULT_DENY; + break; + + case KAUTH_MACHDEP_UNMANAGEDMEM: + if (kstate != KEYLOCK_OPEN) + result = KAUTH_RESULT_DENY; + break; + } + + return result; +} + +/* + * kauth(9) listener + * + * Security model: Multi-position keylock + * Scope: Device + * Responsibility: Keylock + */ +int +secmodel_keylock_device_cb(kauth_cred_t cred, + kauth_action_t action, void *cookie, void *arg0, + void *arg1, void *arg2, void *arg3) +{ + int result, kstate; + + kstate = keylock_state(); + if (kstate == KEYLOCK_ABSENT) + return KAUTH_RESULT_DEFER; + else if (kstate == KEYLOCK_TAMPER) + return KAUTH_RESULT_DENY; + + result = KAUTH_RESULT_DEFER; + + switch (action) { + case KAUTH_DEVICE_RAWIO_SPEC: { + struct vnode *vp, *bvp; + enum kauth_device_req req; + dev_t dev; + int d_type; + + req = (enum kauth_device_req)arg0; + vp = arg1; + + KASSERT(vp != NULL); + + dev = vp->v_rdev; + d_type = D_OTHER; + bvp = NULL; + + /* Handle /dev/mem and /dev/kmem. */ + if ((vp->v_type == VCHR) && iskmemdev(dev)) { + switch (req) { + case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: + break; + + case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: + case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: + if (kstate != KEYLOCK_OPEN) + result = KAUTH_RESULT_DENY; + break; + default: + break; + } + break; + } + + switch (req) { + case KAUTH_REQ_DEVICE_RAWIO_SPEC_READ: + break; + + case KAUTH_REQ_DEVICE_RAWIO_SPEC_WRITE: + case KAUTH_REQ_DEVICE_RAWIO_SPEC_RW: + switch (vp->v_type) { + case VCHR: { + const struct cdevsw *cdev; + + cdev = cdevsw_lookup(dev); + if (cdev != NULL) { + dev_t blkdev; + + blkdev = devsw_chr2blk(dev); + if (blkdev != NODEV) { + vfinddev(blkdev, VBLK, &bvp); + if (bvp != NULL) + d_type = (cdev->d_flag + & D_TYPEMASK); + } + } + + break; + } + case VBLK: { + const struct bdevsw *bdev; + + bdev = bdevsw_lookup(dev); + if (bdev != NULL) + d_type = (bdev->d_flag & D_TYPEMASK); + + bvp = vp; + + break; + } + default: + break; + } + + if (d_type != D_DISK) + break; + + /* + * XXX: This is bogus. We should be failing the request + * XXX: not only if this specific slice is mounted, but + * XXX: if it's on a disk with any other mounted slice. + */ + if (vfs_mountedon(bvp) && (kstate != KEYLOCK_OPEN)) + break; + + if (kstate == KEYLOCK_CLOSE) + result = KAUTH_RESULT_DENY; + + break; + default: + break; + } + break; + } + + case KAUTH_DEVICE_RAWIO_PASSTHRU: + if (kstate != KEYLOCK_OPEN) { + u_long bits; + + bits = (u_long)arg0; + + KASSERT(bits != 0); + KASSERT((bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_ALL) + == 0); + + if (bits & ~KAUTH_REQ_DEVICE_RAWIO_PASSTHRU_READCONF) + result = KAUTH_RESULT_DENY; + } + break; + + case KAUTH_DEVICE_GPIO_PINSET: + if (kstate != KEYLOCK_OPEN) + result = KAUTH_RESULT_DENY; + break; + default: + break; + } + return result; +} Index: src/sys/sys/keylock.h diff -u /dev/null src/sys/sys/keylock.h:1.1 --- /dev/null Fri Aug 14 21:17:22 2009 +++ src/sys/sys/keylock.h Fri Aug 14 21:17:22 2009 @@ -0,0 +1,49 @@ +/* $NetBSD: keylock.h,v 1.1 2009/08/14 21:17:22 mbalmer Exp $ */ + +/* + * Copyright (c) 2009 Marc Balmer <m...@msys.ch> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _SYS_KEYLOCK_H +#define _SYS_KEYLOCK_H + +#define KEYLOCK_ABSENT 0 +#define KEYLOCK_TAMPER 1 +#define KEYLOCK_OPEN 2 +#define KEYLOCK_SEMIOPEN 3 +#define KEYLOCK_SEMICLOSE 4 +#define KEYLOCK_CLOSE 5 + +#ifdef _KERNEL +/* Functions for keylock drivers */ +extern int keylock_register(void *, int, int (*)(void *)); +extern void keylock_unregister(void *, int (*)(void *)); + +/* Functions to query the keylock state */ +extern int keylock_state(void); +extern int keylock_position(void); +extern int keylock_num_positions(void); +#endif + +#endif /* _SYS_KEYLOCK_H */