1 /* $NetBSD: keylock.c,v 1.3 2014/02/25 18:30:09 pooka Exp $ */ 2 3 /* 4 * 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 43 static int (*keylock_pos_cb)(void *) = NULL; 44 static void *keylock_pos_cb_arg = NULL; 45 static int keylock_npos = 0; 46 static int keylock_order = 0; 47 48 int keylock_pos_sysctl(SYSCTLFN_PROTO); 49 int keylock_state_sysctl(SYSCTLFN_PROTO); 50 int keylock_order_sysctl(SYSCTLFN_PROTO); 51 52 SYSCTL_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 92 int 93 keylock_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 107 void 108 keylock_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 121 int 122 keylock_position(void) 123 { 124 if (keylock_pos_cb == NULL) 125 return 0; 126 127 return (*keylock_pos_cb)(keylock_pos_cb_arg); 128 } 129 130 int 131 keylock_num_positions(void) 132 { 133 return keylock_npos; 134 } 135 136 int 137 keylock_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 161 int 162 keylock_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 174 int 175 keylock_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 187 int 188 keylock_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