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_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
43 *****************************************************************************/
46 /*****************************************************************************
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
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.
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
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
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
110 * 11/16/01 mel Fixed bug #348: N8_SKSDisplay memory faults when NULL Pointer
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
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
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
153 #include "n8_pub_sks.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"
167 #include "n8_SKSManager.h"
169 extern NSPdriverInfo_t nspDriverInfo
;
171 /* Local method prototypes */
173 void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t
*keyHandle_p
);
178 /*****************************************************************************
180 *****************************************************************************/
182 * @brief Returns how many units (chips) there are in the system.
197 * Driver has been opened.
199 *****************************************************************************/
201 static int n8_getNumUnits(void)
204 return nspDriverInfo
.numChips
;
206 } /* n8_getNumUnits */
209 /*****************************************************************************
210 * n8_checkAndFreeEntry
211 *****************************************************************************/
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
234 *****************************************************************************/
236 static N8_Status_t
n8_checkAndFreeEntry(const N8_Buffer_t
*name
, const N8_Unit_t unit
)
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
;
253 /* an entry of this name exists. free it and reclaim the resources. */
254 ret
= N8_SKSFree(&tempHandle
);
263 /*****************************************************************************
265 *****************************************************************************/
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
280 * N8_INVALID_VALUE if the unit id is out of range.
284 *****************************************************************************/
286 n8_verifyUnitID(const N8_Unit_t unit
, N8_SKSKeyHandle_t
*keyHandle_p
)
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
)
309 else if ((unit
< 0) || (unit
>= numSKS
))
311 return N8_INVALID_VALUE
;
315 keyHandle_p
->unitID
= unit
;
322 /*****************************************************************************
323 * n8_printSKSKeyHandle
324 *****************************************************************************/
326 * @brief Display a key handle for an SKS PROM.
328 * @param keyHandle_p RO: A pointer to the key handle to be printed.
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 */
358 /*****************************************************************************
360 *****************************************************************************/
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.
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.
375 * N8_STATUS_OK if no other errors. The display contents should now be
376 * within the provided char array.
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
,
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
);
404 } /* N8_SKSDisplay */
407 /*****************************************************************************
409 *****************************************************************************/
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.
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.
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
;
435 uint32_t sksOffset
= 0, targetSKS
= 0, keyLength
= 0;
436 N8_Status_t ret
= N8_STATUS_OK
;
437 N8_SKSKeyHandle_t
*sks_key_p
;
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
;
452 if ((keyMaterial_p
->p
.lengthBytes
== 0) ||
453 (keyMaterial_p
->q
.lengthBytes
== 0))
455 ret
= N8_INVALID_KEY_SIZE
;
459 sks_key_p
= &keyMaterial_p
->SKSKeyHandle
;
461 ret
= n8_verifyUnitID(keyMaterial_p
->unitID
, sks_key_p
);
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
;
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
;
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
;
493 /* check to see if an entry of this name already exists and free
495 ret
= n8_checkAndFreeEntry(keyEntryName_p
, keyMaterial_p
->SKSKeyHandle
.unitID
);
498 ret
= N8_RSAInitializeKey(&key
, N8_PRIVATE_CRT
, keyMaterial_p
, NULL
);
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
);
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
);
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
,
546 SKS_RSA_P_LENGTH(sks_key_p
->key_length
),
548 SKS_RSA_P_OFFSET(sks_key_p
->key_length
),
550 DBG(("Return from write: %s\n", N8_Status_t_text(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
,
561 SKS_RSA_Q_LENGTH(sks_key_p
->key_length
),
563 SKS_RSA_Q_OFFSET(sks_key_p
->key_length
),
565 DBG(("Return from write: %s\n", N8_Status_t_text(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
,
576 SKS_RSA_DP_LENGTH(sks_key_p
->key_length
),
578 SKS_RSA_DP_OFFSET(sks_key_p
->key_length
),
581 DBG(("Return from write: %s\n", N8_Status_t_text(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
,
593 SKS_RSA_DQ_LENGTH(sks_key_p
->key_length
),
595 SKS_RSA_DQ_OFFSET(sks_key_p
->key_length
),
597 DBG(("Return from write: %s\n", N8_Status_t_text(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
);
608 n8_SKSWrite(targetSKS
,
610 SKS_RSA_RMODP_LENGTH(sks_key_p
->key_length
),
612 SKS_RSA_RMODP_OFFSET(sks_key_p
->key_length
),
614 DBG(("Return from write: %s\n", N8_Status_t_text(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
);
624 n8_SKSWrite(targetSKS
,
626 SKS_RSA_RMODQ_LENGTH(sks_key_p
->key_length
),
628 SKS_RSA_RMODQ_OFFSET(sks_key_p
->key_length
),
630 DBG(("Return from write: %s\n", N8_Status_t_text(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
);
640 n8_SKSWrite(targetSKS
,
642 SKS_RSA_N_LENGTH(sks_key_p
->key_length
),
644 SKS_RSA_N_OFFSET(sks_key_p
->key_length
),
647 DBG(("Return from write: %s\n", N8_Status_t_text(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
);
658 n8_SKSWrite(targetSKS
,
660 SKS_RSA_PINV_LENGTH(sks_key_p
->key_length
),
662 SKS_RSA_PINV_OFFSET(sks_key_p
->key_length
),
665 DBG(("Return from write: %s\n", N8_Status_t_text(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
,
676 SKS_RSA_CP_LENGTH(sks_key_p
->key_length
),
678 SKS_RSA_CP_OFFSET(sks_key_p
->key_length
),
681 DBG(("Return from write: %s\n", N8_Status_t_text(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
);
691 n8_SKSWrite(targetSKS
,
693 SKS_RSA_CQ_LENGTH(sks_key_p
->key_length
),
695 SKS_RSA_CQ_OFFSET(sks_key_p
->key_length
),
697 DBG(("Return from write: %s\n", N8_Status_t_text(ret
)));
700 if (key
.structureID
== N8_RSA_STRUCT_ID
)
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
707 if (ret
== N8_STATUS_OK
)
714 } /* N8_SKSAllocateRSA */
717 /*****************************************************************************
719 *****************************************************************************/
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.
732 * N8_STATUS_OK indicates the key allocation and write successfully
734 * N8_UNEXPECTED_ERROR indicates an error writing the key handle or that
735 * the API was not or could not be initialized.
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
;
745 unsigned int keyLength
;
746 uint32_t targetSKS
= 0, sksOffset
= 0;
748 N8_SKSKeyHandle_t
*sks_key_p
;
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
;
763 if ((keyMaterial_p
->p
.lengthBytes
== 0) ||
764 (keyMaterial_p
->q
.lengthBytes
== 0))
766 ret
= N8_INVALID_KEY_SIZE
;
770 ret
= n8_DSAValidateKey(keyMaterial_p
, N8_PRIVATE
);
773 sks_key_p
= &keyMaterial_p
->SKSKeyHandle
;
775 ret
= n8_verifyUnitID(keyMaterial_p
->unitID
, sks_key_p
);
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
784 ret
= n8_checkAndFreeEntry(keyEntryName_p
, keyMaterial_p
->SKSKeyHandle
.unitID
);
787 ret
= N8_DSAInitializeKey(&key
, N8_PRIVATE
, keyMaterial_p
, NULL
);
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
);
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
);
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
;
832 n8_SKSWrite(targetSKS
,
834 SKS_DSA_P_LENGTH(sks_key_p
->key_length
),
835 sksOffset
+ SKS_DSA_P_OFFSET(sks_key_p
->key_length
),
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
);
845 n8_SKSWrite(targetSKS
,
847 SKS_DSA_GRMODP_LENGTH(sks_key_p
->key_length
),
848 sksOffset
+ SKS_DSA_GRMODP_OFFSET(sks_key_p
->key_length
),
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
);
859 n8_SKSWrite(targetSKS
,
861 SKS_DSA_Q_LENGTH(sks_key_p
->key_length
),
862 sksOffset
+ SKS_DSA_Q_OFFSET(sks_key_p
->key_length
),
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
);
873 n8_SKSWrite(targetSKS
,
875 SKS_DSA_X_LENGTH(sks_key_p
->key_length
),
877 SKS_DSA_X_OFFSET(sks_key_p
->key_length
),
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
);
888 n8_SKSWrite(targetSKS
,
890 SKS_DSA_CP_LENGTH(sks_key_p
->key_length
),
891 sksOffset
+ SKS_DSA_CP_OFFSET(sks_key_p
->key_length
),
897 if (key
.structureID
== N8_DSA_STRUCT_ID
)
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
904 if (ret
== N8_STATUS_OK
)
912 } /* N8_SKSAllocateDSA */
914 /*****************************************************************************
916 *****************************************************************************/
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.
928 * N8_STATUS_OK indicates the key de-allocation and erase successfully
930 * N8_UNEXPECTED_ERROR indicates an error erasing the SKS key entry or that
931 * the API was not or could not be initialized.
934 * That the key handle pointer is valid.
935 *****************************************************************************/
936 N8_Status_t
N8_SKSFree(N8_SKSKeyHandle_t
* keyHandle_p
)
943 char fullFileName
[1024];
948 if (ret
!= N8_STATUS_OK
)
952 if (keyHandle_p
== NULL
)
954 ret
= N8_INVALID_KEY
;
959 n8_printSKSKeyHandle(keyHandle_p
);
962 if ((keyHandle_p
->key_type
) == N8_RSA_VERSION_1_KEY
)
964 words_to_free
= SKS_RSA_DATA_LENGTH(keyHandle_p
->key_length
);
967 else if (keyHandle_p
->key_type
== N8_DSA_VERSION_1_KEY
)
969 words_to_free
= SKS_DSA_DATA_LENGTH(keyHandle_p
->key_length
);
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
);
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
)));
994 n8_SKSsetStatus(keyHandle_p
, SKS_FREE
);
996 sprintf(fullFileName
, "%s%d/%s",
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
;
1009 /*****************************************************************************
1010 * N8_SKSGetKeyHandle
1011 *****************************************************************************/
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.
1019 * SKS_initialized_g RW: A boolean value that indicates wether the SKS
1020 * admin interface API has been initialized.
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];
1037 DBG(("Get KeyHandle : \n"));
1039 ret
= N8_preamble();
1040 if (ret
!= N8_STATUS_OK
)
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
1057 if ((strlen(SKS_KEY_NODE_PATH
) + strlen(keyEntryName
) + 4) >=
1058 sizeof(fullFileName
))
1060 return N8_UNEXPECTED_ERROR
;
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
1069 ret
= n8_daemon_sks_read(keyHandle_p
, fullFileName
);
1070 if (ret
== N8_STATUS_OK
)
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 */
1083 ret
= N8_INVALID_KEY
;
1087 } /* N8_SKSGetKeyHandle */
1089 /*****************************************************************************
1091 *****************************************************************************/
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.
1105 * N8_STATUS_OK indicates the key de-allocation and erase successfully
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
)
1114 N8_Status_t ret
= N8_STATUS_OK
;
1115 N8_Unit_t firstSKS
, lastSKS
;
1118 DBG(("N8_SKSReset: entering...\n"));
1120 ret
= N8_preamble();
1121 if (ret
!= N8_STATUS_OK
)
1126 /* get the number of units */
1127 numberSKS
= n8_getNumUnits();
1129 if (targetSKS
== N8_ANY_UNIT
)
1132 lastSKS
= numberSKS
-1;
1134 else if (targetSKS
>= 0 &&
1135 targetSKS
< numberSKS
)
1137 firstSKS
= lastSKS
= targetSKS
;
1141 ret
= N8_INVALID_VALUE
;
1144 /* loop over the SKS units to be reset. it will either be all or just the
1146 for (i
= firstSKS
; i
<= lastSKS
; i
++)
1149 ret
= n8_SKSResetUnit(i
);
1150 if (ret
!= N8_STATUS_OK
)
1154 /* request N8 userspace daemon to remove
1155 * all the key handle files on the host
1156 * file system that are under the specified
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"));
1172 /*****************************************************************************
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
;
1183 DBG(("Verify RSA Key.\n"));
1185 ret
= N8_preamble();
1186 if (ret
!= N8_STATUS_OK
)
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
)));
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
)));
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 /*****************************************************************************
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
;
1242 DBG(("Verify DSA Key.\n"));
1244 ret
= N8_preamble();
1245 if (ret
!= N8_STATUS_OK
)
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
)));
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
)));
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 */