187866Ssheldonh/* $NetBSD: keylock.c,v 1.2 2009/08/15 09:43:58 mbalmer Exp $ */ 287866Ssheldonh 387866Ssheldonh/* 487866Ssheldonh * Copyright (c) 2009 Marc Balmer <marc@msys.ch> 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28#include "opt_secmodel_keylock.h" 29 30/* Support for multi-position electro-mechanical keylocks */ 31 32#include <sys/param.h> 33#include <sys/kernel.h> 34#include <sys/sysctl.h> 35 36#include <dev/keylock.h> 37 38#ifdef secmodel_keylock 39#include <sys/kauth.h> 40#include <secmodel/keylock/keylock.h> 41#endif 42 43static int (*keylock_pos_cb)(void *) = NULL; 44static void *keylock_pos_cb_arg = NULL; 45static int keylock_npos = 0; 46static int keylock_order = 0; 47 48int keylock_pos_sysctl(SYSCTLFN_PROTO); 49int keylock_state_sysctl(SYSCTLFN_PROTO); 50int keylock_order_sysctl(SYSCTLFN_PROTO); 51 52SYSCTL_SETUP(sysctl_keylock_setup, "sysctl keylock setup") 53{ 54 const struct sysctlnode *node = NULL; 55 56 sysctl_createv(clog, 0, NULL, &node, 57 CTLFLAG_PERMANENT, 58 CTLTYPE_NODE, "keylock", 59 SYSCTL_DESCR("Keylock state"), 60 NULL, 0, NULL, 0, 61 CTL_HW, CTL_CREATE, CTL_EOL); 62 63 if (node == NULL) 64 return; 65 66 sysctl_createv(clog, 0, &node, NULL, 67 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 68 CTLTYPE_INT, "pos", 69 SYSCTL_DESCR("Current keylock position"), 70 keylock_pos_sysctl, 0, NULL, 0, 71 CTL_CREATE, CTL_EOL); 72 sysctl_createv(clog, 0, &node, NULL, 73 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 74 CTLTYPE_INT, "npos", 75 SYSCTL_DESCR("Number of keylock positions"), 76 NULL, 0, &keylock_npos, 0, 77 CTL_CREATE, CTL_EOL); 78 sysctl_createv(clog, 0, &node, NULL, 79 CTLFLAG_PERMANENT | CTLFLAG_READONLY, 80 CTLTYPE_INT, "state", 81 SYSCTL_DESCR("Keylock state"), 82 keylock_state_sysctl, 0, NULL, 0, 83 CTL_CREATE, CTL_EOL); 84 sysctl_createv(clog, 0, &node, NULL, 85 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, 86 CTLTYPE_INT, "order", 87 SYSCTL_DESCR("Keylock closedness order"), 88 keylock_order_sysctl, 0, NULL, 0, 89 CTL_CREATE, CTL_EOL); 90} 91 92int 93keylock_register(void *cb_arg, int npos, int (*cb)(void *)) 94{ 95 if (keylock_pos_cb != NULL) 96 return -1; 97 98 keylock_pos_cb = cb; 99 keylock_pos_cb_arg = cb_arg; 100 keylock_npos = npos; 101#ifdef secmodel_keylock 102 secmodel_keylock_start(); 103#endif 104 return 0; 105} 106 107void 108keylock_unregister(void *cb_arg, int (*cb)(void *)) 109{ 110 if (keylock_pos_cb != cb || keylock_pos_cb_arg != cb_arg) 111 return; 112 113#ifdef secmodel_keylock 114 secmodel_keylock_stop(); 115#endif 116 keylock_pos_cb = NULL; 117 keylock_pos_cb_arg = NULL; 118 keylock_npos = 0; 119} 120 121int 122keylock_position(void) 123{ 124 if (keylock_pos_cb == NULL) 125 return 0; 126 127 return (*keylock_pos_cb)(keylock_pos_cb_arg); 128} 129 130int 131keylock_num_positions(void) 132{ 133 return keylock_npos; 134} 135 136int 137keylock_state(void) 138{ 139 int pos; 140 141 if (keylock_npos == 0) 142 return KEYLOCK_ABSENT; 143 144 pos = keylock_position(); 145 if (pos == 0) 146 return KEYLOCK_TAMPER; 147 148 /* 149 * XXX How should the intermediate positions be handled? 150 * At the moment only the ultimate positions are properly handled, 151 * we need to think about what we do with the intermediate positions. 152 * For now we return KEYLOCK_SEMIOPEN for them. 153 */ 154 if (pos == 1) 155 return keylock_order == 0 ? KEYLOCK_CLOSE : KEYLOCK_OPEN; 156 else if (pos == keylock_npos) 157 return keylock_order == 0 ? KEYLOCK_OPEN : KEYLOCK_CLOSE; 158 return KEYLOCK_SEMIOPEN; 159} 160 161int 162keylock_pos_sysctl(SYSCTLFN_ARGS) 163{ 164 struct sysctlnode node; 165 int val; 166 167 node = *rnode; 168 node.sysctl_data = &val; 169 170 val = keylock_position(); 171 return sysctl_lookup(SYSCTLFN_CALL(&node)); 172} 173 174int 175keylock_state_sysctl(SYSCTLFN_ARGS) 176{ 177 struct sysctlnode node; 178 int val; 179 180 node = *rnode; 181 node.sysctl_data = &val; 182 183 val = keylock_state(); 184 return sysctl_lookup(SYSCTLFN_CALL(&node)); 185} 186 187int 188keylock_order_sysctl(SYSCTLFN_ARGS) 189{ 190 struct sysctlnode node; 191 int val, error; 192 193 node = *rnode; 194 node.sysctl_data = &val; 195 196 val = keylock_order; 197 error = sysctl_lookup(SYSCTLFN_CALL(&node)); 198 if (error || newp == NULL) 199 return error; 200 if (keylock_state() != KEYLOCK_OPEN) 201 return -1; 202 203 keylock_order = val; 204 return 0; 205} 206 207