Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_daemon_sks.c
blob52ca84f98ec4aabac3a6711cd85f41bbc20c3a0d
1 /*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id[] = "$Id: n8_daemon_sks.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_daemon_sks.c
38 * @brief This file implements the user side of the daemon's SKS
39 * functional interfaces. These should be called directly from a
40 * userspace SKS API (n8_sks.c) or VxWorks environment, since the
41 * reverse-ioctl is not necessary in these cases.
43 *----------------------------------------------------------------------------
44 * N8 Daemon Functional Interfaces
45 *----------------------------------------------------------------------------
47 * n8_daemon_sks_init - Initializes SKS allocation mapping for a single
48 * execution unit using the key handle files found
49 * on the host file system.
51 * n8_daemon_sks_read - Reads data from the specified key handle file into
52 * a key handle structure.
54 * n8_daemon_sks_write - Write data in key handle specified into a key
55 * handle file with specified name.
57 * n8_daemon_sks_delete - Deletes specified key handle file from the host
58 * file system.
60 * n8_dameon_sks_reset - Deletes all key handle files from host
61 * file system.
64 *****************************************************************************/
66 /*****************************************************************************
67 * Revision history:
68 * 04/05/02 brr Fixed warning.
69 * 04/04/02 bac Fixed a bug in the reset routine where a null directory
70 * descriptor was trying to close.
71 * 04/04/02 spm Fixed bug 683. Now sks subdirectories are not created in
72 * the init call (which is now always run as root), but in
73 * the key handle file write call (which will typically be run
74 * as a normal user like admin). This allows the adminstrator
75 * to maintain proper file permissions for these subdirectories.
76 * 03/26/02 spm Simplified n8_daemon_sks_init.
77 * 03/14/02 bac Changed printfs to DBGs.
78 * 02/22/02 spm Changed keyEntryName_p type class to const in sks_write.
79 * 02/14/01 spm Fixed string handling bugs.
80 * 02/05/01 spm Original version.
81 ****************************************************************************/
82 /** @defgroup n8_sks_daemon SKS Daemon Routines
85 #include <stdio.h>
86 #include <stdlib.h>
87 #include <sys/types.h>
88 #include <dirent.h>
89 #include <sys/stat.h>
90 #include <fcntl.h>
91 #include <string.h>
92 #include "n8_pub_common.h"
93 #include "n8_daemon_common.h"
94 #include "n8_sks.h"
95 #include "n8_sks_util.h"
96 #include "n8_OS_intf.h"
99 /*****************************************************************************
100 * n8_setStatus
101 *****************************************************************************/
102 /** @ingroup n8_sks_daemon
103 * @brief Sets the status of the SKS allocation units spanning an SKS key
105 * @param keyHandle_p RO: key handle
106 * @param status RO: free or in use
107 * @param alloc_map RW: SKS allocation descriptor table
109 * @par Externals:
110 * None.
112 * @return
113 * A text description of all of the return codes of the function.
115 * @par Errors:
116 * return status of SKS_ComputeKeyLength call
118 * @par Locks:
119 * None.
121 * @par Assumptions:
122 *****************************************************************************/
123 static N8_Status_t n8_setStatus(N8_SKSKeyHandle_t *keyHandle_p,
124 unsigned int status,
125 N8_Buffer_t *alloc_map)
127 int i;
128 unsigned int alloc_units_to_free;
129 unsigned int num_sks_words;
130 unsigned int sks_alloc_unit_offset;
131 N8_Status_t ret;
133 ret = n8_ComputeKeyLength(keyHandle_p->key_type,
134 keyHandle_p->key_length,
135 &num_sks_words);
136 if (ret != N8_STATUS_OK)
138 DBG(("n8_setStatus: n8_ComputeKeyLength returned an error\n"));
139 return ret;
142 DBG(("num_sks_words:\t%d\n",num_sks_words));
144 /* given the number SKS words, compute the number of allocation units */
145 alloc_units_to_free = CEIL(num_sks_words, SKS_WORDS_PER_ALLOC_UNIT);
147 DBG(("alloc_units_to_free;\t%d\n",alloc_units_to_free));
149 /* given the offset in words, find the first allocation unit */
150 sks_alloc_unit_offset = keyHandle_p->sks_offset / SKS_WORDS_PER_ALLOC_UNIT;
152 DBG(("sks_alloc_unit_offset:\t%d\n",sks_alloc_unit_offset));
154 for (i = 0; i < alloc_units_to_free; i++)
156 alloc_map[sks_alloc_unit_offset + i] = status;
159 return ret;
160 } /* n8_setStatus */
163 /*****************************************************************************
164 * printSKSKeyHandle
165 *****************************************************************************/
166 /** @ingroup n8_sks_daemon
167 * @brief Display a key handle for an SKS PROM.
169 * @param keyHandle_p RO: A pointer to the key handle to be printed.
171 * @par Externals:
172 * None
174 * @return
175 * None.
177 * @par Errors:
178 * None.
180 * @par Assumptions:
181 * None.
182 *****************************************************************************/
183 static void printSKSKeyHandle(N8_SKSKeyHandle_t *keyHandle_p)
186 DBG(("Key Handle:\n\tKey Type %08x\n",
187 keyHandle_p->key_type));
188 DBG(("\tKey Length %08x\n\tSKS Offset %08x\n",
189 keyHandle_p->key_length,
190 keyHandle_p->sks_offset));
191 DBG(("\tTarget SKS %08x\n",
192 keyHandle_p->unitID));
193 } /* printSKSKeyHandle */
197 /*****************************************************************************
198 * n8_daemon_sks_write
199 *****************************************************************************/
200 /** @ingroup n8_sks_daemon
201 * @brief Write a key handle to an SKS entry.
203 * Writes to a file, formatted for the keyhandle contents.
205 * @param sks_key_p RW: SKS key handle to write
206 * @param keyEntryName_p RW: Name of key handle file
208 * @return
209 * N8_STATUS_OK if the file scan returned successfully
210 * N8_FILE_ERROR if there was an error writing the file.
212 * @par Assumptions:
213 * That the file descriptor is valid.
214 *****************************************************************************/
215 N8_Status_t n8_daemon_sks_write(N8_SKSKeyHandle_t *sks_key_p,
216 const char *keyEntryName_p)
218 FILE *fd;
219 char key_entry[N8_DAEMON_MAX_PATH_LEN];
220 char sub_dir[N8_DAEMON_MAX_PATH_LEN];
221 char key_entry_name[N8_SKS_ENTRY_NAME_MAX_LENGTH];
222 DIR *dir_p = NULL;
224 strncpy(key_entry_name, keyEntryName_p, N8_SKS_ENTRY_NAME_MAX_LENGTH);
226 /* Write the key entry. */
227 N8_TRUNC_STR(key_entry_name, N8_SKS_ENTRY_NAME_MAX_LENGTH-1);
229 /* make sure that the SKS unit this key is on has a subdirectory
230 * in /opt/NetOctave/sks
232 * NOTE: when we construct the full path for this directory,
233 * we don't terminate it with '/'. This is because on BSDi
234 * you can't create a directory whose name appended with '/'
236 sprintf(sub_dir, "%s%i",
237 SKS_KEY_NODE_PATH,
238 sks_key_p->unitID);
240 if ((dir_p = opendir(sub_dir)) == NULL)
242 /* the directory for this SKS does not exist. create it. */
243 DBG(("Directory '%s' does not exist. Creating it.\n", sub_dir));
245 if ((N8_mkdir(sub_dir, S_IRWXU | S_IRWXG | S_IROTH )) == -1)
247 DBG(("Cannot N8_mkdir '%s'... make sure %s exists "
248 "and this process is run as owner or group\n",
249 sub_dir,
250 SKS_KEY_NODE_PATH));
251 return N8_FILE_ERROR;
254 else
256 /* we know the directory exists, so close it */
257 closedir(dir_p);
260 /* build full path name for key handle file */
261 sprintf(key_entry, "%s%i/%s",
262 SKS_KEY_NODE_PATH,
263 sks_key_p->unitID,
264 key_entry_name);
266 if ((fd = fopen(key_entry, "w")) == NULL)
268 DBG(("n8_daemon_sks_write: error opening file %s\n", key_entry));
269 return N8_FILE_ERROR;
272 if (fprintf(fd, "%i\n%08x\n%i\n%08x\n",
273 (int) sks_key_p->key_type, sks_key_p->key_length,
274 sks_key_p->unitID, sks_key_p->sks_offset) <= 0)
276 DBG(("n8_daemon_sks_write: error "
277 "writing to file %s\n", key_entry));
278 fclose(fd);
279 return N8_FILE_ERROR;
281 else
283 fclose(fd);
284 return N8_STATUS_OK;
287 } /* n8_daemon_sks_write */
289 /*****************************************************************************
290 * n8_daemon_sks_read
291 *****************************************************************************/
292 /** @ingroup n8_sks_daemon
293 * @brief Read a key handle from an SKS entry.
295 * Reads from a file, formatted for the keyhandle contents.
297 * @param *keyHandle_p RO: A Read Only parameter
298 * @param *keyEntryPath_p RW: A key handle file path.
300 * @return
301 * N8_STATUS_OK if the file scan returned successfully
302 * N8_FILE_ERROR if there was an error scanning the sks entry.
304 * @par Assumptions:
305 * That the file descriptor is valid.
306 *****************************************************************************/
307 N8_Status_t n8_daemon_sks_read(N8_SKSKeyHandle_t* keyHandle_p,
308 char *keyEntryPath_p)
310 FILE *fd;
311 int ret;
312 char key_entry_path[N8_DAEMON_MAX_PATH_LEN];
314 strncpy(key_entry_path, keyEntryPath_p, N8_DAEMON_MAX_PATH_LEN);
316 /* force string delimiting */
317 N8_TRUNC_STR(key_entry_path, N8_DAEMON_MAX_PATH_LEN-1);
319 if ((fd = fopen(key_entry_path, "r")) == NULL)
321 DBG(("n8_daemon_sks_read: error opening file %s\n", key_entry_path));
322 return N8_FILE_ERROR;
326 if ((ret = fscanf(fd, "%i\n%08x\n%i\n%08x",
327 (int*) &keyHandle_p->key_type, &keyHandle_p->key_length,
328 (int*) &keyHandle_p->unitID, &keyHandle_p->sks_offset)) == 4)
330 fclose(fd);
332 /* force string delimiting */
333 N8_TRUNC_STR(keyHandle_p->entry_name, N8_SKS_ENTRY_NAME_MAX_LENGTH-1);
335 return N8_STATUS_OK;
338 DBG(("n8_daemon_sks_read: fscanf returned error code "
339 "%d on file %s\n", ret, key_entry_path));
340 fclose(fd);
341 return N8_FILE_ERROR;
343 } /* n8_daemon_sks_read */
346 /*****************************************************************************
347 * n8_daemon_sks_delete
348 *****************************************************************************/
349 /** @ingroup n8_sks_daemon
350 * @brief One line description of the function.
352 * More detailed description of the function including any unusual algorithms
353 * or suprising details.
355 * @param keyEntryPath_p RW: Full path to key handle file
357 * @par Externals:
358 * None.
360 * @return
361 * N8_STATUS_OK on success
363 * @par Errors:
364 * N8_FILE_ERROR if remove fails. remove
365 * returns 0 on success and -1 on failure.
367 * @par Locks:
368 * None.
370 * @par Assumptions:
371 *****************************************************************************/
372 N8_Status_t n8_daemon_sks_delete(char *keyEntryPath_p)
374 char key_entry_path[N8_DAEMON_MAX_PATH_LEN];
376 strncpy(key_entry_path, keyEntryPath_p, N8_DAEMON_MAX_PATH_LEN);
378 /* force string delimiting */
379 N8_TRUNC_STR(key_entry_path, N8_DAEMON_MAX_PATH_LEN-1);
381 /* Delete the existing key entry. */
382 if (remove(key_entry_path) == 0)
384 return N8_STATUS_OK;
386 else
388 return N8_FILE_ERROR;
391 } /* n8_n8_daemon_sks_delete */
394 /*****************************************************************************
395 * n8_daemon_sks_init
396 *****************************************************************************/
397 /** @ingroup n8_sks_daemon
398 * @brief Initialize an instance of the SKS management interface API.
400 * The current system file entries must be read, and if they exist, the
401 * descriptor tables created for the calling application.
403 * @param targetSKS RO: the SKS unit desc. table to initialize
404 * @param alloc_map RW: descriptor table buffer to initialize
406 * These and all other SKS interface calls should be considered
407 * DESTRUCTIVE with respect to the contents of the SKS PROM.
409 * @par Externals:
410 * None.
412 * @return
413 * N8_STATUS_OK indicates that the API has been initialixed, or that all
414 * intialization proceeded without errors.
415 * N8_FILE_ERROR indicates that either an SKS entry could not be
416 * read, or that the descriptor tables could not be created.
418 *****************************************************************************/
419 N8_Status_t n8_daemon_sks_init(N8_Unit_t targetSKS,
420 N8_Buffer_t *alloc_map)
422 char sks_entry[N8_DAEMON_MAX_PATH_LEN];
423 char sks_entry_name[N8_SKS_ENTRY_NAME_MAX_LENGTH];
425 DIR *dir_p = NULL;
426 struct dirent *dirent_p;
427 N8_Status_t ret = N8_STATUS_OK;
428 N8_SKSKeyHandle_t keyHandle;
430 DBG(("n8_daemon_sks_init\n"));
433 /* Initialize the discriptor mapping to zero */
434 memset(&alloc_map[0],
435 SKS_FREE,
436 SKS_ALLOC_UNITS_PER_PROM * sizeof(N8_Buffer_t));
438 /* Open the SKS entry directory. Read all the key files and
439 * allocate descriptor space for them.
441 sprintf(sks_entry_name, "%s%i/", SKS_KEY_NODE_PATH,
442 targetSKS);
444 DBG(("Target sks dev node is '%s'.\n\n", sks_entry_name));
446 if ((dir_p = opendir(sks_entry_name)) == NULL)
448 /* this just means that no key has been allocated
449 * to this target SKS, so just return OK
450 * (the allocation map we return has already been
451 * initialized)
453 return ret;
456 /* read the entries */
457 DBG(("Reading sks entries in '%s'.\n\n", sks_entry_name));
458 while ((dirent_p = readdir(dir_p)) &&
459 (dirent_p->d_name != NULL))
461 if ((strcmp(dirent_p->d_name, ".") != 0) &&
462 (strcmp(dirent_p->d_name, "..") != 0))
464 sprintf(sks_entry, "%s%s", sks_entry_name,
465 dirent_p->d_name);
467 ret = n8_daemon_sks_read(&keyHandle,
468 sks_entry);
469 CHECK_RETURN(ret);
471 DBG(("Allocating descriptor space for key entry %s.\n",
472 dirent_p->d_name));
474 printSKSKeyHandle(&keyHandle);
476 ret = n8_setStatus(&keyHandle,
477 SKS_INUSE,
478 alloc_map);
479 CHECK_RETURN(ret);
482 } while (FALSE);
484 /* cleanup */
485 closedir(dir_p);
487 return ret;
489 } /* n8_daemon_sks_init */
492 /*****************************************************************************
493 * n8_daemon_sks_reset
494 *****************************************************************************/
495 /** @ingroup n8_sks_daemon
496 * @brief Perform SKS reset for a specific unit.
498 * @param targetSKS RO: Unit number
500 * @par Externals
501 * None
503 * @return
504 * Status
506 * @par Errors
507 * N8_STATUS_OK on success.<br>
508 * N8_FILE_ERROR if errors occur while reading/writing files or
509 * directories.<br>
512 * @par Assumptions
513 * <description of assumptions><br>
514 *****************************************************************************/
515 N8_Status_t n8_daemon_sks_reset(N8_Unit_t targetSKS)
517 DIR* dir_p = NULL;
518 struct dirent* dirent_p;
519 char key_entry[N8_DAEMON_MAX_PATH_LEN];
520 char key_entry_path[N8_DAEMON_MAX_PATH_LEN];
521 N8_Status_t ret = N8_STATUS_OK;
523 DBG(("Reset :\n"));
524 sprintf(key_entry, "%s%i/", SKS_KEY_NODE_PATH, targetSKS);
526 /* Find out which, if any, key entries exist. Then blast 'em. */
527 DBG(("Resetting SKS %i.\n", targetSKS));
529 if ((dir_p = opendir(key_entry)) == NULL)
531 DBG(("Could not open '%s'.\n", key_entry));
532 return N8_STATUS_OK;
535 if ((dirent_p = readdir(dir_p)) == NULL)
537 /* There are no SKS entries in the system. */
538 DBG(("Empty. There are no SKS entries for the target SKS.\n"));
539 /* clean up */
540 closedir(dir_p);
541 return N8_STATUS_OK;
543 else
546 * The SKS entries exist. If there are no key entries, it is assumed
547 * that the PROM is empty!
550 while ((dirent_p = readdir(dir_p)) != NULL)
552 /* skip . and .. */
553 if ((strcmp(dirent_p->d_name, ".") == 0) ||
554 (strcmp(dirent_p->d_name, "..") == 0))
556 continue;
558 DBG(("%s : \n", dirent_p->d_name));
560 sprintf(key_entry_path, "%s%i/%s",
561 SKS_KEY_NODE_PATH,
562 targetSKS,
563 dirent_p->d_name);
565 ret = n8_daemon_sks_delete(key_entry_path);
567 } /* End 'if-else' for read-dir. */
569 /* clean up */
570 closedir(dir_p);
572 return ret;
573 } /* n8_daemon_sks_reset */