2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
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>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
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
60 * n8_dameon_sks_reset - Deletes all key handle files from host
64 *****************************************************************************/
66 /*****************************************************************************
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
87 #include <sys/types.h>
92 #include "n8_pub_common.h"
93 #include "n8_daemon_common.h"
95 #include "n8_sks_util.h"
96 #include "n8_OS_intf.h"
99 /*****************************************************************************
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
113 * A text description of all of the return codes of the function.
116 * return status of SKS_ComputeKeyLength call
122 *****************************************************************************/
123 static N8_Status_t
n8_setStatus(N8_SKSKeyHandle_t
*keyHandle_p
,
125 N8_Buffer_t
*alloc_map
)
128 unsigned int alloc_units_to_free
;
129 unsigned int num_sks_words
;
130 unsigned int sks_alloc_unit_offset
;
133 ret
= n8_ComputeKeyLength(keyHandle_p
->key_type
,
134 keyHandle_p
->key_length
,
136 if (ret
!= N8_STATUS_OK
)
138 DBG(("n8_setStatus: n8_ComputeKeyLength returned an error\n"));
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
;
163 /*****************************************************************************
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.
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
209 * N8_STATUS_OK if the file scan returned successfully
210 * N8_FILE_ERROR if there was an error writing the file.
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
)
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
];
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",
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",
251 return N8_FILE_ERROR
;
256 /* we know the directory exists, so close it */
260 /* build full path name for key handle file */
261 sprintf(key_entry
, "%s%i/%s",
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
));
279 return N8_FILE_ERROR
;
287 } /* n8_daemon_sks_write */
289 /*****************************************************************************
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.
301 * N8_STATUS_OK if the file scan returned successfully
302 * N8_FILE_ERROR if there was an error scanning the sks entry.
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
)
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)
332 /* force string delimiting */
333 N8_TRUNC_STR(keyHandle_p
->entry_name
, N8_SKS_ENTRY_NAME_MAX_LENGTH
-1);
338 DBG(("n8_daemon_sks_read: fscanf returned error code "
339 "%d on file %s\n", ret
, key_entry_path
));
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
361 * N8_STATUS_OK on success
364 * N8_FILE_ERROR if remove fails. remove
365 * returns 0 on success and -1 on failure.
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)
388 return N8_FILE_ERROR
;
391 } /* n8_n8_daemon_sks_delete */
394 /*****************************************************************************
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.
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
];
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],
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
,
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
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
,
467 ret
= n8_daemon_sks_read(&keyHandle
,
471 DBG(("Allocating descriptor space for key entry %s.\n",
474 printSKSKeyHandle(&keyHandle
);
476 ret
= n8_setStatus(&keyHandle
,
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
507 * N8_STATUS_OK on success.<br>
508 * N8_FILE_ERROR if errors occur while reading/writing files or
513 * <description of assumptions><br>
514 *****************************************************************************/
515 N8_Status_t
n8_daemon_sks_reset(N8_Unit_t targetSKS
)
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
;
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
));
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"));
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
)
553 if ((strcmp(dirent_p
->d_name
, ".") == 0) ||
554 (strcmp(dirent_p
->d_name
, "..") == 0))
558 DBG(("%s : \n", dirent_p
->d_name
));
560 sprintf(key_entry_path
, "%s%i/%s",
565 ret
= n8_daemon_sks_delete(key_entry_path
);
567 } /* End 'if-else' for read-dir. */
573 } /* n8_daemon_sks_reset */