Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_sks.c
blob3b8cfc52aae4d22223f537f29120e620e99ba409
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_sks.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
37 /** @file SKS_Management_Interface
38 * @brief Implementation for the SKS Management Interface.
40 * Allows for the initialization and subsequent key management of associated
41 * SKS PROMs.
43 *****************************************************************************/
46 /*****************************************************************************
47 * Revision history:
49 * 02/10/04 bac Fixed N8_SKSReset bug (Bug 1006) by changing test logic.
50 * 06/06/03 brr Move n8_enums to public include as n8_pub_enums.
51 * 05/16/03 brr Eliminate obsolete include file.
52 * 04/04/02 bac Reformat to conform to coding standards.
53 * 04/01/02 spm Moved deletion of key handle files from n8_SKSResetUnit
54 * ioctl to N8_SKSReset API call.
55 * 03/04/02 spm N8_GetSKSKeyHandle changed to set the value of the unit to
56 * N8_ANY_UNIT if N8_SKS_ROUND_ROBIN is defined. (Bug 645)
57 * Fixed N8_SKSGetKeyHandle so that it now copies the passed
58 * entry name into the entry_name field in the key handle.
59 * 03/18/02 bac Made all public entry points execute the preamble to ensure
60 * the API and chip are initialized.
61 * 02/28/02 brr Do not include any QMgr include files.
62 * 02/22/02 spm Added include of n8_time.h. Converted N8_KPRINT's to DBG's.
63 * 02/20/02 brr Removed references to the queue structure.
64 * 02/14/02 brr Reconcile 2.0 memory management modifications.
65 * 02/05/02 spm Removed #include of <linux/string.h> and
66 * restored #include of n8_OS_intf.h.
67 * 01/28/02 spm Changed while loops in SKS write to n8_usleeps.
68 * A test is made after the sleep has completed to
69 * insure that the go busy flag is cleared by the
70 * hardware. Added break to N8_SKSGetKeyHandle for loop
71 * for the case that the file is found.
72 * 01/22/02 spm Moved n8_ComputeKeyLength to n8_sks_util.c.
73 * 01/22/02 spm Moved n8_SKSInitialize ot n8_sksInit.c.
74 * 01/20/02 spm Removed system calls. Replaced file system handling
75 * with requests to the N8 daemon.
76 * 01/17/02 bac Bug #480 -- SKS write caused persistent N8_HARDWARE_ERROR.
77 * Cleared any existing error flags before the write. Also
78 * expanded the critical section to include the subsequent wait
79 * for no busy.
80 * 01/07/02 bac Fixed semaphore usage to prevent deadlock. Bug #450.
81 * 12/20/01 bac Removed global SKS_Descriptor management array and now use
82 * shared memory in the Queue Control structure. Bug #436.
83 * 12/11/01 mel Fixed bug #414: Added checks for NULL
84 * 12/07/01 bac Fixed merging issues. N8_SKSFree now, definitively, only
85 * takes a handle and not also an entry name.
86 * 12/07/01 bac Made N8_SKSReset more efficient by only calling SKSWrite once,
87 * free and reclaim entries if a new allocation has the same
88 * name, fixed abug in SKSWrite to force it to wait until
89 * finished before proceeding.
90 * 12/03/01 bac Rearrange order of write to SKS/write file in order to write
91 * the file first and return an error if it does not occur.
92 * Failures on write to the SKS cause the files to be removed.
93 * (BUG #391)
94 * 11/29/01 bac Added closedir() as needed to avoid leaking directory
95 * descriptors. (BUG #385). Also allowed the use of N8_ANY_UNIT
96 * on calls to N8_SKSReset. (BUG #386).
97 * 12/03/01 mel Fixed bug #395: in DBG string changed % to %% - to eliminate
98 * compilation error
99 * 11/19/01 bac Reworked the DSA key constraint testing. Fixed
100 * N8_SKSGetKeyHandle to use the full path name. Corrected the
101 * computation of the number of SKS words used by pre-existing
102 * entries so that they not be over-written. Changed
103 * N8_SKSAllocate[RSA|DSA] to accept N8_ANY_KEY as unit
104 * specifiers.
105 * Bugs #347, 352, 362, 355, 358, 361, 356, 359, 354, 357, 360.
106 * 11/16/01 mel Fixed bug #346: N8_SKSReset memory faults when invalid(-2)
107 * TargetSKS paramter is entered
108 * 11/16/01 mel Fixed bug #349: N8_SKSDisplay formatted output could be
109 * printed better.
110 * 11/16/01 mel Fixed bug #348: N8_SKSDisplay memory faults when NULL Pointer
111 * for 1st parameter
112 * 11/16/01 mel Fixed bug #345: N8_SKSFree command returns
113 * N8_UNEXPECTED_ERROR instead of N8_INVALID_KEY
114 * 11/16/01 mel Fixed bug #344: N8_SKSFree with NULL pointer to
115 * N8_SKSKeyHandle_t parameter causes a memory fault
116 * 11/15/01 mel Fixed bug #332: N8_AllocateRSA returns N8_INVALID_OBJECT
117 * instead of N8_INVALID_KEY_SIZE when p.length != q.length
118 * 11/15/01 bac Changed all fprintf(stderrr,...) to DBG()
119 * 11/15/01 mel Fixed bug #330: N8_AllocateRSA seg faults when pointer to
120 * privateKey value is NULL
121 * 11/15/01 mel Fixed bug #329: N8_SKSAllocateRSA memory faults when pointer
122 * to KeyMaterial is NULL
123 * 11/15/01 mel Fixed bug #331: N8_SKSAllocateRSA returns N8_HARDWARE_ERROR
124 * when p.lengthBtyes of q.lengthBytes= 0
125 * 11/14/01 spm Changed prom-to-cache copy fn to work with new register
126 * access macros.
127 * 11/13/01 mel Fixed bug #297: register access macros in n8_sks.c will
128 * only work on the behavioral model
129 * 11/13/01 bac Close all file descriptors when finished with them.
130 * 11/10/01 spm Added SKS prom-to-cache copy routine for use by
131 * QMgr setup. Addressed bug #295 with a comment.
132 * 11/08/01 mel Fixed bug #302: No call to N8_preamble in the n8_sks.c API routines.
133 * 11/04/01 bac Propogate return codes rather than masking them with
134 * N8_UNEXPECTED_ERROR and changed the mode on the call to
135 * mkdir to allow group write access.
136 * 10/30/01 dkm Eliminate warning in VxWorks
137 * 10/22/01 bac Fixed problems calculating free blocks.
138 * 10/19/01 hml Fixed some compiler warnings.
139 * 10/14/01 bac Included string.h to silence compiler warning.
140 * 10/11/01 bac Changed parameters passed to Param_Byte_Length macros to
141 * reflect their new definitions.
142 * 10/10/01 jdj Multi-thread safe semaphores added to file and register
143 * accesses.
144 * 10/09/01 msz Minor changes to calls to opendir and mkdir so they compile
145 * without warnings under vxworks. VxWorks has different
146 * args for mkdir, and doesn't preserve const.
147 * 06/04/01 jdj Original version.
148 ****************************************************************************/
149 /** @defgroup n8_sks SKS Management Interface
152 #include "n8_sks.h"
153 #include "n8_pub_sks.h"
154 #include "n8_rsa.h"
155 #include "n8_dsa.h"
156 #include "n8_util.h"
157 #include "n8_pub_enums.h"
158 #include "n8_driver_api.h"
159 #include "n8_API_Initialize.h"
160 #include "n8_device_info.h"
162 #include "n8_OS_intf.h"
163 #include "n8_semaphore.h"
164 #include "n8_daemon_sks.h"
165 #include "n8_sks_util.h"
166 #include "n8_time.h"
167 #include "n8_SKSManager.h"
169 extern NSPdriverInfo_t nspDriverInfo;
171 /* Local method prototypes */
172 #ifdef N8DEBUG
173 void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p);
174 #endif
176 /* Local methods */
178 /*****************************************************************************
179 * n8_getNumUnits
180 *****************************************************************************/
181 /** @ingroup n8_sks
182 * @brief Returns how many units (chips) there are in the system.
184 * @param
185 * None
187 * @par Externals
188 * nspDriverInfo
190 * @return
191 * Number of units.
193 * @par Errors
194 * None
196 * @par Assumptions
197 * Driver has been opened.
199 *****************************************************************************/
201 static int n8_getNumUnits(void)
204 return nspDriverInfo.numChips;
206 } /* n8_getNumUnits */
209 /*****************************************************************************
210 * n8_checkAndFreeEntry
211 *****************************************************************************/
212 /** @ingroup n8_sks
213 * @brief Check to see if a named entry exists and if so free it.
215 * If a request is made to allocate an entry for a tuple <unit, name> and it
216 * already exists, then we replace it. First we look for the named entry and
217 * delete it if it exists. This allows the harvesting of resources before the
218 * re-allocation to ensure no resources are lost.
220 * @param name RO: name of entry
221 * @param unit RO: unit identifier
223 * @par Externals
224 * None
226 * @return
227 * Status
229 * @par Errors
230 * None
232 * @par Assumptions
233 * None
234 *****************************************************************************/
236 static N8_Status_t n8_checkAndFreeEntry(const N8_Buffer_t *name, const N8_Unit_t unit)
238 N8_Status_t ret;
239 N8_SKSKeyHandle_t tempHandle;
241 tempHandle.unitID = unit;
242 ret = N8_SKSGetKeyHandle(name, &tempHandle);
244 if (ret == N8_STATUS_OK)
246 #if N8_SKS_ROUND_ROBIN
247 /* If we are using round robin algorithm, then N8_SKS_GetKeyHandle will force
248 * the key handle unit ID to N8_ANY_UNIT (-1). We must restore the unit ID
249 * to its original value in this case.
251 tempHandle.unitID = unit;
252 #endif
253 /* an entry of this name exists. free it and reclaim the resources. */
254 ret = N8_SKSFree(&tempHandle);
256 else
258 ret = N8_STATUS_OK;
260 return ret;
263 /*****************************************************************************
264 * n8_verifyUnitID
265 *****************************************************************************/
266 /** @ingroup n8_sks
267 * @brief Given a unit ID, verify that it is valid. If N8_ANY_UNIT is
268 * specified, then have the QMgr select one to use.
270 * @param unit RO: unit ID to be verified
271 * @param keyHandle_p RW: SKSKeyHandle to place the results
273 * @par Externals
274 * None
276 * @return
277 * Status
279 * @par Errors
280 * N8_INVALID_VALUE if the unit id is out of range.
282 * @par Assumptions
283 * None
284 *****************************************************************************/
285 static N8_Status_t
286 n8_verifyUnitID(const N8_Unit_t unit, N8_SKSKeyHandle_t *keyHandle_p)
288 int numSKS;
289 static int sksSelection = 0;
291 /* get the number of units */
292 numSKS = n8_getNumUnits();
294 /* TODO: We are selecting a unit number here. It should be done in */
295 /* QMgr. However, it appeared that we might first need to select a */
296 /* unit in this code, so we can check if the file exists, and the */
297 /* filename is based on the unit id. So, for now, we will select a */
298 /* valid unit ID here, and return it. In the future it would be */
299 /* perhaps better to have the write return what unit was selected. */
300 if (unit == N8_ANY_UNIT)
302 keyHandle_p->unitID = sksSelection;
303 sksSelection = sksSelection + 1;
304 if (sksSelection == numSKS)
306 sksSelection = 0;
309 else if ((unit < 0) || (unit >= numSKS))
311 return N8_INVALID_VALUE;
313 else
315 keyHandle_p->unitID = unit;
318 return N8_STATUS_OK;
321 #ifdef N8DEBUG
322 /*****************************************************************************
323 * n8_printSKSKeyHandle
324 *****************************************************************************/
325 /** @ingroup n8_sks
326 * @brief Display a key handle for an SKS PROM.
328 * @param keyHandle_p RO: A pointer to the key handle to be printed.
330 * @par Externals:
331 * None
333 * @return
334 * None.
336 * @par Errors:
337 * None.
339 * @par Assumptions:
340 * None.
341 *****************************************************************************/
342 void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p)
345 DBG(("Key Handle:\n"));
346 DBG(("Key Type %08x\n",
347 keyHandle_p->key_type));
348 DBG(("Key Length %08x\n\tSKS Offset %08x\n",
349 keyHandle_p->key_length,
350 keyHandle_p->sks_offset));
351 DBG(("Target SKS %08x\n",
352 keyHandle_p->unitID));
353 } /* n8_printSKSKeyHandle */
354 #endif
356 /* Public methods */
358 /*****************************************************************************
359 * N8_SKSDisplay
360 *****************************************************************************/
361 /** @ingroup n8_sks
362 * @brief Display a description entity for an SKS PROM.
364 * Attempts to write a string into a given char string array.
366 * @param keyHandle_p RW: A N8_SKSKeyHandle_t pointer.
367 * @param display_string RO: A char array.
369 * @par Externals:
370 * external_var1 RW: A Read Write external variable<BR>
371 * external_var2 RO: A Read Only external variable<BR>
372 * external_var3 WO: A Write Only external variable: No "break" on last one.
374 * @return
375 * N8_STATUS_OK if no other errors. The display contents should now be
376 * within the provided char array.
378 * @par Assumptions:
379 * The given key handle pointer is valid.
380 *****************************************************************************/
381 N8_Status_t N8_SKSDisplay(N8_SKSKeyHandle_t *keyHandle_p,
382 char *display_string_p)
384 if (keyHandle_p == NULL)
386 return N8_INVALID_KEY;
389 if (display_string_p == NULL)
391 return N8_INVALID_PARAMETER;
394 sprintf(display_string_p,
395 "Key Handle:\n"
396 "\tKey Type %08x\n"
397 "\tKey Length %08x\n"
398 "\tSKS Offset %08x\n"
399 "\tTarget SKS %08x\n",
400 keyHandle_p->key_type, keyHandle_p->key_length,
401 keyHandle_p->sks_offset, keyHandle_p->unitID);
403 return N8_STATUS_OK;
404 } /* N8_SKSDisplay */
407 /*****************************************************************************
408 * N8_SKSAllocateRSA
409 *****************************************************************************/
410 /** @ingroup n8_sks
411 * @brief Allocate and write a private RSA key entry to an SKS PROM.
413 * Attempts to allocate, then write the key into an SKS PROM.
415 * @param keyMaterial_p RW: A N8_RSAKeyMaterial_t pointer.
416 * @param keyEntryName_p RW: A char pointer, the name of the sks entry.
418 * @par Externals:
419 * None
421 * @return
422 * N8_STATUS_OK indicates the key allocation and write successfully completed.
423 * N8_UNEXPECTED_ERROR indicates an error writing the key handle or that
424 * the API was not or could not be initialized.
426 * @par Assumptions:
427 * That the RSA key material pointer is valid.
428 *****************************************************************************/
429 N8_Status_t N8_SKSAllocateRSA(N8_RSAKeyMaterial_t *keyMaterial_p,
430 const N8_Buffer_t *keyEntryName_p)
432 N8_RSAKeyObject_t key;
433 N8_Buffer_t* param;
435 uint32_t sksOffset = 0, targetSKS = 0, keyLength = 0;
436 N8_Status_t ret = N8_STATUS_OK;
437 N8_SKSKeyHandle_t *sks_key_p;
441 ret = N8_preamble();
442 CHECK_RETURN(ret);
443 CHECK_OBJECT(keyMaterial_p, ret);
444 CHECK_OBJECT(keyMaterial_p->privateKey.value_p, ret);
446 CHECK_OBJECT(keyEntryName_p, ret);
447 if (strlen(keyEntryName_p) >= N8_SKS_ENTRY_NAME_MAX_LENGTH)
449 ret = N8_INVALID_OBJECT;
450 break;
452 if ((keyMaterial_p->p.lengthBytes == 0) ||
453 (keyMaterial_p->q.lengthBytes == 0))
455 ret = N8_INVALID_KEY_SIZE;
456 break;
459 sks_key_p = &keyMaterial_p->SKSKeyHandle;
461 ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p);
462 CHECK_RETURN(ret);
464 /* Check requirements for p and q lengths. */
466 /* len(p) == len(q) */
467 if (keyMaterial_p->q.lengthBytes != keyMaterial_p->p.lengthBytes)
469 DBG(("P and Q RSA key material parameters not of same length!\n"));
470 ret = N8_INVALID_KEY_SIZE;
471 break;
473 /* len(p) == len(q) == 1/2 len(private key). note we don't perform the
474 * division in the test as integer division would round down. */
475 if ((keyMaterial_p->q.lengthBytes * 2) !=
476 keyMaterial_p->privateKey.lengthBytes)
478 DBG(("P and Q RSA key material parameter length not half of "
479 "private key length!\n"));
480 ret = N8_INVALID_KEY_SIZE;
481 break;
484 /* public key length mod 32 == 0 or 17-31 */
485 if (keyMaterial_p->privateKey.lengthBytes % 32 != 0 &&
486 keyMaterial_p->privateKey.lengthBytes % 32 <= 16)
488 DBG(("Private key length %% 32 is not in the valid range of 0 or 17-31.\n"));
489 ret = N8_INVALID_KEY_SIZE;
490 break;
493 /* check to see if an entry of this name already exists and free
494 * it if so. */
495 ret = n8_checkAndFreeEntry(keyEntryName_p, keyMaterial_p->SKSKeyHandle.unitID);
496 CHECK_RETURN(ret);
498 ret = N8_RSAInitializeKey(&key, N8_PRIVATE_CRT, keyMaterial_p, NULL);
499 CHECK_RETURN(ret);
501 keyLength = keyMaterial_p->privateKey.lengthBytes;
502 targetSKS = sks_key_p->unitID;
503 sks_key_p->key_type = N8_RSA_VERSION_1_KEY;
505 /* The key length field of the key handle is always in BNC digits. */
506 sks_key_p->key_length =
507 BYTES_TO_PKDIGITS(keyLength);
509 DBG(("Key Length in bytes: %d\n", keyLength));
510 DBG(("Key length in digits: %d\n", sks_key_p->key_length));
512 ret = n8_SKSAllocate(sks_key_p);
513 CHECK_RETURN(ret);
515 /* attempt to write the key information to the mapping files */
516 strcpy(sks_key_p->entry_name, keyEntryName_p);
518 /* request N8 userspace daemon to write out a key handle file */
519 ret = n8_daemon_sks_write(sks_key_p, keyEntryName_p);
521 if (ret != N8_STATUS_OK)
523 /* the write to the key handle failed.
524 * we need to unallocate the space
525 * and return a failure. */
527 DBG(("n8_daemon_sks_write returned error\n"));
529 n8_SKSsetStatus(sks_key_p, SKS_FREE);
530 break;
533 sksOffset = sks_key_p->sks_offset;
535 /* Write the data into the SKS PROM. */
536 DBG(("Writing key data into SKS.\n"));
538 /* Write the p value into the SKS. */
539 DBG(("Writing p param into SKS.\n"));
541 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
542 PK_RSA_P_Param_Byte_Offset(&key);
544 ret = n8_SKSWrite(targetSKS,
545 (uint32_t*) param,
546 SKS_RSA_P_LENGTH(sks_key_p->key_length),
547 sksOffset +
548 SKS_RSA_P_OFFSET(sks_key_p->key_length),
549 FALSE);
550 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
551 CHECK_RETURN(ret);
553 /* Write the p value into the SKS. */
554 DBG(("Writing q param into SKS.\n"));
556 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
557 PK_RSA_Q_Param_Byte_Offset(&key);
559 ret = n8_SKSWrite(targetSKS,
560 (uint32_t*) param,
561 SKS_RSA_Q_LENGTH(sks_key_p->key_length),
562 sksOffset +
563 SKS_RSA_Q_OFFSET(sks_key_p->key_length),
564 FALSE);
565 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
566 CHECK_RETURN(ret);
568 /* Write the dp value into the SKS. */
569 DBG(("Writing dp param into SKS.\n"));
571 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
572 PK_RSA_DP_Param_Byte_Offset(&key);
574 ret = n8_SKSWrite(targetSKS,
575 (uint32_t*) param,
576 SKS_RSA_DP_LENGTH(sks_key_p->key_length),
577 sksOffset +
578 SKS_RSA_DP_OFFSET(sks_key_p->key_length),
579 FALSE);
581 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
582 CHECK_RETURN(ret);
585 /* Write the dq value into the SKS. */
586 DBG(("Writing dq param into SKS.\n"));
588 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
589 PK_RSA_DQ_Param_Byte_Offset(&key);
591 ret = n8_SKSWrite(targetSKS,
592 (uint32_t*) param,
593 SKS_RSA_DQ_LENGTH(sks_key_p->key_length),
594 sksOffset +
595 SKS_RSA_DQ_OFFSET(sks_key_p->key_length),
596 FALSE);
597 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
598 CHECK_RETURN(ret);
600 /* Write the R mod p value into the SKS. */
601 DBG(("Writing R mod p param into SKS.\n"));
603 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
604 PK_RSA_R_MOD_P_Param_Byte_Offset(&key);
607 ret =
608 n8_SKSWrite(targetSKS,
609 (uint32_t*) param,
610 SKS_RSA_RMODP_LENGTH(sks_key_p->key_length),
611 sksOffset +
612 SKS_RSA_RMODP_OFFSET(sks_key_p->key_length),
613 FALSE);
614 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
615 CHECK_RETURN(ret);
617 /* Write the R mod q value into the SKS. */
618 DBG(("Writing R mod q param into SKS.\n"));
620 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
621 PK_RSA_R_MOD_Q_Param_Byte_Offset(&key);
623 ret =
624 n8_SKSWrite(targetSKS,
625 (uint32_t*) param,
626 SKS_RSA_RMODQ_LENGTH(sks_key_p->key_length),
627 sksOffset +
628 SKS_RSA_RMODQ_OFFSET(sks_key_p->key_length),
629 FALSE);
630 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
631 CHECK_RETURN(ret);
633 /* Write the n value into the SKS. */
634 DBG(("Writing n param into SKS.\n"));
636 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
637 PK_RSA_N_Param_Byte_Offset(&key);
639 ret =
640 n8_SKSWrite(targetSKS,
641 (uint32_t*) param,
642 SKS_RSA_N_LENGTH(sks_key_p->key_length),
643 sksOffset +
644 SKS_RSA_N_OFFSET(sks_key_p->key_length),
645 FALSE);
647 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
648 CHECK_RETURN(ret);
650 /* Write the pInv value into the SKS. */
651 DBG(("Writing pInv param into SKS.\n"));
653 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
654 PK_RSA_U_Param_Byte_Offset(&key);
657 ret =
658 n8_SKSWrite(targetSKS,
659 (uint32_t*) param,
660 SKS_RSA_PINV_LENGTH(sks_key_p->key_length),
661 sksOffset +
662 SKS_RSA_PINV_OFFSET(sks_key_p->key_length),
663 FALSE);
665 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
666 CHECK_RETURN(ret);
668 /* Write the cp value into the SKS. */
669 DBG(("Writing cp param into SKS.\n"));
671 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
672 PK_RSA_CP_Param_Byte_Offset(&key);
674 ret = n8_SKSWrite(targetSKS,
675 (uint32_t*) param,
676 SKS_RSA_CP_LENGTH(sks_key_p->key_length),
677 sksOffset +
678 SKS_RSA_CP_OFFSET(sks_key_p->key_length),
679 FALSE);
681 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
682 CHECK_RETURN(ret);
684 /* Write the cq value into the SKS. */
685 DBG(("Writing cq param into SKS.\n"));
687 param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
688 PK_RSA_CQ_Param_Byte_Offset(&key);
690 ret =
691 n8_SKSWrite(targetSKS,
692 (uint32_t*) param,
693 SKS_RSA_CQ_LENGTH(sks_key_p->key_length),
694 sksOffset +
695 SKS_RSA_CQ_OFFSET(sks_key_p->key_length),
696 FALSE);
697 DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
698 } while (FALSE);
700 if (key.structureID == N8_RSA_STRUCT_ID)
702 N8_Status_t freeRet;
703 freeRet = N8_RSAFreeKey(&key);
704 /* if we terminated the processing loop with an error, let's report that
705 * error to the calling function rather than have it masked by the return
706 * from free key. */
707 if (ret == N8_STATUS_OK)
709 ret = freeRet;
712 return ret;
714 } /* N8_SKSAllocateRSA */
717 /*****************************************************************************
718 * N8_SKSAllocateDSA
719 *****************************************************************************/
720 /** @ingroup n8_sks
721 * @brief Allocate and write a private DSA key entry to an SKS PROM.
723 * Attempts to allocate, then write the key into an SKS PROM.
725 * @param keyMaterial_p RW: A N8_DSAKeyMaterial_t pointer.
726 * @param keyEntryName_p RW: A char pointer, the name of the sks entry.
728 * @par Externals:
729 * None
731 * @return
732 * N8_STATUS_OK indicates the key allocation and write successfully
733 * completed.
734 * N8_UNEXPECTED_ERROR indicates an error writing the key handle or that
735 * the API was not or could not be initialized.
737 * @par Assumptions:
738 * That the DSA key material pointer is valid.
739 *****************************************************************************/
740 N8_Status_t N8_SKSAllocateDSA(N8_DSAKeyMaterial_t *keyMaterial_p,
741 const N8_Buffer_t *keyEntryName_p)
743 N8_DSAKeyObject_t key;
744 N8_Buffer_t* param;
745 unsigned int keyLength;
746 uint32_t targetSKS = 0, sksOffset = 0;
747 N8_Status_t ret;
748 N8_SKSKeyHandle_t *sks_key_p;
752 ret = N8_preamble();
753 CHECK_RETURN(ret);
754 CHECK_OBJECT(keyMaterial_p, ret);
755 CHECK_OBJECT(keyMaterial_p->privateKey.value_p, ret);
756 CHECK_OBJECT(keyEntryName_p, ret);
757 if (strlen(keyEntryName_p) >= N8_SKS_ENTRY_NAME_MAX_LENGTH)
759 ret = N8_INVALID_OBJECT;
760 break;
763 if ((keyMaterial_p->p.lengthBytes == 0) ||
764 (keyMaterial_p->q.lengthBytes == 0))
766 ret = N8_INVALID_KEY_SIZE;
767 break;
770 ret = n8_DSAValidateKey(keyMaterial_p, N8_PRIVATE);
771 CHECK_RETURN(ret);
773 sks_key_p = &keyMaterial_p->SKSKeyHandle;
775 ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p);
776 CHECK_RETURN(ret);
778 /* The key length field of the key handle is always in BNC digits. */
779 sks_key_p->key_length =
780 BYTES_TO_PKDIGITS(keyMaterial_p->p.lengthBytes);
782 /* check to see if an entry of this name already exists and free
783 * it if so. */
784 ret = n8_checkAndFreeEntry(keyEntryName_p, keyMaterial_p->SKSKeyHandle.unitID);
785 CHECK_RETURN(ret);
787 ret = N8_DSAInitializeKey(&key, N8_PRIVATE, keyMaterial_p, NULL);
788 CHECK_RETURN(ret);
790 keyLength = sks_key_p->key_length;
791 targetSKS = sks_key_p->unitID;
792 sks_key_p->key_type = N8_DSA_VERSION_1_KEY;
795 /* allocate an sks. */
796 ret = n8_SKSAllocate(sks_key_p);
797 CHECK_RETURN(ret);
799 /* attempt to write the key information to the mapping files */
800 strcpy(sks_key_p->entry_name, keyEntryName_p);
802 /* request N8 userspace daemon to write out a key handle file */
803 ret = n8_daemon_sks_write(sks_key_p, keyEntryName_p);
804 if (ret != N8_STATUS_OK)
806 /* the write to the key handle failed.
807 * we need to unallocate the space
808 * and return a failure. */
809 n8_SKSsetStatus(sks_key_p, SKS_FREE);
810 break;
813 sksOffset = sks_key_p->sks_offset;
815 /* Write the data into the SKS PROM. */
816 DBG(("Writing key data into SKS.\n"));
818 /* The DSA parameter block to be stored the DSA has the following structure:
819 * p sks_offset key_length digits
820 * g*R mod p sks_offset + 4 * key_length key_length digits
821 * q sks_offset + 8 * key_length 2 digits
822 * x sks_offset + 8*kl + 8 2 digits
823 * p sks_offset + 8*kl + 16 1 digit
826 /* Write the p value into the SKS. */
827 DBG(("Writing p param into SKS.\n"));
829 param = key.paramBlock + PK_DSA_P_Param_Offset;
831 ret =
832 n8_SKSWrite(targetSKS,
833 (uint32_t*) param,
834 SKS_DSA_P_LENGTH(sks_key_p->key_length),
835 sksOffset + SKS_DSA_P_OFFSET(sks_key_p->key_length),
836 FALSE);
837 CHECK_RETURN(ret);
839 /* Write the gR mod p value into the SKS. */
840 DBG(("Writing gR mod p param into SKS.\n"));
842 param = key.paramBlock + PK_DSA_GR_MOD_P_Param_Offset(sks_key_p->key_length);
844 ret =
845 n8_SKSWrite(targetSKS,
846 (uint32_t*) param,
847 SKS_DSA_GRMODP_LENGTH(sks_key_p->key_length),
848 sksOffset + SKS_DSA_GRMODP_OFFSET(sks_key_p->key_length),
849 FALSE);
850 CHECK_RETURN(ret);
852 /* Write the q value into the SKS. */
853 DBG(("Writing q param into SKS.\n"));
855 param = key.paramBlock +
856 PK_DSA_Q_Param_Offset(sks_key_p->key_length);
858 ret =
859 n8_SKSWrite(targetSKS,
860 (uint32_t*) param,
861 SKS_DSA_Q_LENGTH(sks_key_p->key_length),
862 sksOffset + SKS_DSA_Q_OFFSET(sks_key_p->key_length),
863 FALSE);
864 CHECK_RETURN(ret);
866 /* Write the x value (private key) into the SKS. */
867 DBG(("Writing x (private key) param into SKS.\n"));
869 param = key.paramBlock +
870 PK_DSA_X_Param_Offset(sks_key_p->key_length);
872 ret =
873 n8_SKSWrite(targetSKS,
874 (uint32_t*) param,
875 SKS_DSA_X_LENGTH(sks_key_p->key_length),
876 sksOffset +
877 SKS_DSA_X_OFFSET(sks_key_p->key_length),
878 FALSE);
879 CHECK_RETURN(ret);
881 /* Write the cp value into the SKS. */
882 DBG(("Writing cp into SKS.\n"));
884 param = key.paramBlock +
885 PK_DSA_CP_Param_Offset(sks_key_p->key_length);
887 ret =
888 n8_SKSWrite(targetSKS,
889 (uint32_t*) param,
890 SKS_DSA_CP_LENGTH(sks_key_p->key_length),
891 sksOffset + SKS_DSA_CP_OFFSET(sks_key_p->key_length),
892 FALSE);
893 CHECK_RETURN(ret);
895 } while (FALSE);
897 if (key.structureID == N8_DSA_STRUCT_ID)
899 N8_Status_t freeRet;
900 freeRet = N8_DSAFreeKey(&key);
901 /* if we terminated the processing loop with an error, let's report that
902 * error to the calling function rather than have it masked by the return
903 * from free key. */
904 if (ret == N8_STATUS_OK)
906 ret = freeRet;
910 return ret;
912 } /* N8_SKSAllocateDSA */
914 /*****************************************************************************
915 * N8_SKSFree
916 *****************************************************************************/
917 /** @ingroup n8_sks
918 * @brief De-allocates and erases a private key entry to an SKS PROM.
920 * Attempts to de-allocate, then erase the key into an SKS PROM.
922 * @param keyHandle_p RW: A N8_SKSKeyHandle_t pointer.
924 * @par Externals:
925 * None
927 * @return
928 * N8_STATUS_OK indicates the key de-allocation and erase successfully
929 * completed.
930 * N8_UNEXPECTED_ERROR indicates an error erasing the SKS key entry or that
931 * the API was not or could not be initialized.
933 * @par Assumptions:
934 * That the key handle pointer is valid.
935 *****************************************************************************/
936 N8_Status_t N8_SKSFree(N8_SKSKeyHandle_t* keyHandle_p)
938 int words_to_free;
939 char* key_type;
940 int i;
941 uint32_t zero = 0x0;
942 N8_Status_t ret;
943 char fullFileName[1024];
945 DBG(("SKS Free\n"));
947 ret = N8_preamble();
948 if (ret != N8_STATUS_OK)
950 return ret;
952 if (keyHandle_p == NULL)
954 ret = N8_INVALID_KEY;
955 return ret;
958 #ifdef N8DEBUG
959 n8_printSKSKeyHandle(keyHandle_p);
960 #endif
962 if ((keyHandle_p->key_type) == N8_RSA_VERSION_1_KEY)
964 words_to_free = SKS_RSA_DATA_LENGTH(keyHandle_p->key_length);
965 key_type = "RSA";
967 else if (keyHandle_p->key_type == N8_DSA_VERSION_1_KEY)
969 words_to_free = SKS_DSA_DATA_LENGTH(keyHandle_p->key_length);
970 key_type = "DSA";
972 else
974 DBG(("Unknown key type.\n"));
975 return N8_INVALID_KEY;
978 DBG(("Zeroing out the key in the SKS PROM.\n"));
980 /* Grab the offset and begin deleting data! */
981 for (i = keyHandle_p->sks_offset;
982 (i < keyHandle_p->sks_offset+words_to_free) && (i < SKS_PROM_MAX_OFFSET);
983 i++)
985 ret = n8_SKSWrite(keyHandle_p->unitID, &zero, 1, i, FALSE);
986 if (ret != N8_STATUS_OK)
988 DBG(("Error writing to SKS in N8_SKSFree. (%s)\n",
989 N8_Status_t_text(ret)));
990 return ret;
994 n8_SKSsetStatus(keyHandle_p, SKS_FREE);
996 sprintf(fullFileName, "%s%d/%s",
997 SKS_KEY_NODE_PATH,
998 keyHandle_p->unitID,
999 keyHandle_p->entry_name);
1001 /* request N8 userspace daemon to delete the specfied file */
1002 n8_daemon_sks_delete(fullFileName);
1004 return N8_STATUS_OK;
1006 } /* N8_SKSFree */
1009 /*****************************************************************************
1010 * N8_SKSGetKeyHandle
1011 *****************************************************************************/
1012 /** @ingroup n8_sks
1013 * @brief Reads a key handle data from a named key entry for an SKS PROM.
1015 * @param systemKeyNode RW: A char pointer, the named key entry.
1016 * @param keyHandle_p WO: A N8_SKSKeyHandle_t pointer.
1018 * @par Externals:
1019 * SKS_initialized_g RW: A boolean value that indicates wether the SKS
1020 * admin interface API has been initialized.
1021 * @return
1022 * N8_STATUS_OK indicates the key read successfully completed.
1023 * N8_UNEXPECTED_ERROR indicates an error reading the SKS key entry or that
1024 * the API was not or could not be initialized.
1026 *****************************************************************************/
1027 N8_Status_t N8_SKSGetKeyHandle(const N8_Buffer_t* keyEntryName,
1028 N8_SKSKeyHandle_t* keyHandle_p)
1031 N8_Status_t ret = N8_STATUS_OK;
1032 char fullFileName[1024];
1033 int numberSKS;
1034 int i;
1035 int found;
1037 DBG(("Get KeyHandle : \n"));
1039 ret = N8_preamble();
1040 if (ret != N8_STATUS_OK)
1042 return ret;
1045 if ((keyEntryName == NULL) || (keyHandle_p == NULL))
1047 return N8_INVALID_OBJECT;
1050 /* get the number of units */
1051 numberSKS = n8_getNumUnits();
1053 /* check to see if we can have a buffer overrun. the +4 is for the trailing
1054 * '/' and for the size of the unitID -- assuming the number of units is no
1055 * more than 999. */
1057 if ((strlen(SKS_KEY_NODE_PATH) + strlen(keyEntryName) + 4) >=
1058 sizeof(fullFileName))
1060 return N8_UNEXPECTED_ERROR;
1062 found = -1;
1063 for (i = 0; i < numberSKS; i++)
1065 sprintf(fullFileName, "%s%d/%s", SKS_KEY_NODE_PATH, i, keyEntryName);
1066 /* request N8 userspace daemon to read from the specfied key
1067 * handle file
1069 ret = n8_daemon_sks_read(keyHandle_p, fullFileName);
1070 if (ret == N8_STATUS_OK)
1072 found = i;
1073 /* n8_daemon_sks_read does not set the entry name */
1074 strcpy(keyHandle_p->entry_name, keyEntryName);
1075 #if N8_SKS_ROUND_ROBIN
1076 keyHandle_p->unitID = N8_ANY_UNIT;
1077 #endif /* N8_SKS_ROUND_ROBIN */
1078 break;
1081 if (found == -1)
1083 ret = N8_INVALID_KEY;
1086 return ret;
1087 } /* N8_SKSGetKeyHandle */
1089 /*****************************************************************************
1090 * N8_SKSReset
1091 *****************************************************************************/
1092 /** @ingroup n8_sks
1093 * @brief Obliterates all data within an SKS PROM.
1095 * Attempts to de-allocate, then erase the all key entries in an SKS PROM.
1096 * THIS SHOULD NEVER BE INVOKED EXCEPT TO CLEAR ALL KEYS IN A GIVEN PROM.
1097 * THIS IS AN IRREVERSIBLE ACTION.
1099 * @param targetSKS RW: A int, the target SKS PROM.
1101 * @par Externals:
1102 * None
1104 * @return
1105 * N8_STATUS_OK indicates the key de-allocation and erase successfully
1106 * completed.
1107 * N8_UNEXPECTED_ERROR indicates an error erasing the SKS key entry or that
1108 * the API was not or could not be initialized.
1110 *****************************************************************************/
1111 N8_Status_t N8_SKSReset(N8_Unit_t targetSKS)
1113 int i;
1114 N8_Status_t ret = N8_STATUS_OK;
1115 N8_Unit_t firstSKS, lastSKS;
1116 int numberSKS;
1118 DBG(("N8_SKSReset: entering...\n"));
1120 ret = N8_preamble();
1121 if (ret != N8_STATUS_OK)
1123 return ret;
1126 /* get the number of units */
1127 numberSKS = n8_getNumUnits();
1129 if (targetSKS == N8_ANY_UNIT)
1131 firstSKS = 0;
1132 lastSKS = numberSKS-1;
1134 else if (targetSKS >= 0 &&
1135 targetSKS < numberSKS)
1137 firstSKS = lastSKS = targetSKS;
1139 else
1141 ret = N8_INVALID_VALUE;
1142 return ret;
1144 /* loop over the SKS units to be reset. it will either be all or just the
1145 * targetSKS. */
1146 for (i = firstSKS; i <= lastSKS; i++)
1149 ret = n8_SKSResetUnit(i);
1150 if (ret != N8_STATUS_OK)
1152 return ret;
1154 /* request N8 userspace daemon to remove
1155 * all the key handle files on the host
1156 * file system that are under the specified
1157 * execution unit
1159 ret = n8_daemon_sks_reset(i);
1160 if (ret != N8_STATUS_OK)
1162 DBG(("Error resetting SKS files: %d\n", ret));
1163 return N8_FILE_ERROR;
1166 DBG(("N8_SKSReset: leaving...\n"));
1169 return ret;
1170 } /* N8_SKSReset */
1172 /*****************************************************************************
1173 * N8_SKSVerifyRSA
1174 *****************************************************************************/
1175 N8_Status_t N8_SKSVerifyRSA(N8_SKSKeyHandle_t* keyHandle_p,
1176 N8_Buffer_t* input_p,
1177 N8_Buffer_t* result_p)
1179 N8_RSAKeyObject_t privateKey;
1180 N8_Buffer_t* decryptBuffer_p;
1181 N8_Status_t ret;
1183 DBG(("Verify RSA Key.\n"));
1185 ret = N8_preamble();
1186 if (ret != N8_STATUS_OK)
1188 return ret;
1190 /* Set the material to NULL as we are using the SKS. */
1191 ret = N8_RSAInitializeKey(&privateKey, N8_PRIVATE_SKS, NULL, NULL);
1192 if (ret != N8_STATUS_OK)
1194 DBG(("Could not initialize RSA private key from SKS. (%s)\n",
1195 N8_Status_t_text(ret)));
1196 return ret;
1199 decryptBuffer_p = (N8_Buffer_t *) N8_UMALLOC(privateKey.privateKeyLength);
1200 if (decryptBuffer_p == NULL)
1202 DBG(("Could not allocate %i bytes for decrypt buffer.\n",
1203 privateKey.privateKeyLength));
1204 return N8_MALLOC_FAILED;
1207 ret = N8_RSADecrypt(&privateKey, input_p,
1208 privateKey.privateKeyLength,
1209 decryptBuffer_p, NULL);
1210 if (ret != N8_STATUS_OK)
1212 DBG(("Could not complete RSA decrypt using SKS private key. (%s)\n",
1213 N8_Status_t_text(ret)));
1214 return ret;
1217 /* Compare the buffers. If they are different, then indicate this in the return code. */
1218 if (memcmp(result_p, decryptBuffer_p, privateKey.privateKeyLength) != 0)
1220 DBG(("Message buffers are not the same. "
1221 "RSA Decrypt failed or SKS private key material is not valid.\n"));
1222 return N8_VERIFICATION_FAILED;
1225 DBG(("RSA Decrypt good: SKS private key is valid.\n"));
1227 return N8_STATUS_OK;
1228 } /* N8_SKSVerifyRSA */
1230 /*****************************************************************************
1231 * N8_SKSVerifyDSA
1232 *****************************************************************************/
1234 N8_Status_t N8_SKSVerifyDSA(N8_SKSKeyHandle_t* keyHandle_p,
1235 N8_Buffer_t* inputHash_p,
1236 N8_Buffer_t* resultRValue_p,
1237 N8_Buffer_t* resultSValue_p)
1239 N8_DSAKeyObject_t privateKey;
1240 N8_Buffer_t* signRValueBuffer_p, *signSValueBuffer_p;
1241 N8_Status_t ret;
1242 DBG(("Verify DSA Key.\n"));
1244 ret = N8_preamble();
1245 if (ret != N8_STATUS_OK)
1247 return ret;
1250 /* Set the material to NULL as we are using the SKS. */
1251 ret = N8_DSAInitializeKey(&privateKey, N8_PRIVATE_SKS, NULL, NULL);
1252 if (ret != N8_STATUS_OK)
1254 DBG(("Could not initialize DSA private key from SKS. (%s)\n",
1255 N8_Status_t_text(ret)));
1256 return ret;
1259 /* !!!!!! Is there a #define for the S and R value byte lengths?!?!?!! */
1260 if ((signRValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0)
1262 DBG(("Could not allocate %i bytes for DSA sign R value buffer.\n",
1263 privateKey.modulusLength));
1264 return N8_MALLOC_FAILED;
1267 if ((signSValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0)
1269 DBG(("Could not allocate %i bytes for DSA sign S value buffer.\n",
1270 privateKey.modulusLength));
1271 return N8_MALLOC_FAILED;
1274 ret = N8_DSASign(&privateKey, inputHash_p, signRValueBuffer_p,
1275 signSValueBuffer_p, NULL);
1276 if (ret != N8_STATUS_OK)
1278 DBG(("Could not complete DSA sign using SKS private key. (%s)\n",
1279 N8_Status_t_text(ret)));
1280 return ret;
1283 /* Compare the buffers. If they are different, then indicate this in the return code. */
1284 if (memcmp(resultRValue_p, signRValueBuffer_p, 20) != 0)
1286 DBG(("Result R value buffers are not the same. "
1287 "DSA Sign failed or SKS private key material is not valid.\n"));
1288 return N8_VERIFICATION_FAILED;
1291 if (memcmp(resultSValue_p, signSValueBuffer_p, 20) != 0)
1293 DBG(("Result S value buffers are not the same. "
1294 "DSA Sign failed or SKS private key material is not valid.\n"));
1295 return N8_VERIFICATION_FAILED;
1298 DBG(("DSA Sign good: SKS private key is valid.\n"));
1300 return N8_STATUS_OK;
1302 } /* N8_SKSVerifyDSA */