1/*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
4 *
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:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
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.
21 *
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.
33 */
34
35static char const n8_id[] = "$Id: n8_sks.c,v 1.2 2011/08/01 12:28:54 mbalmer Exp $";
36/*****************************************************************************/
37/** @file SKS_Management_Interface
38 *  @brief Implementation for the SKS Management Interface.
39 *
40 * Allows for the initialization and subsequent key management of associated
41 * SKS PROMs.
42 *
43 *****************************************************************************/
44
45
46/*****************************************************************************
47 * Revision history:
48 *
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
150 */
151
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"
161
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"
168
169extern NSPdriverInfo_t  nspDriverInfo;
170
171/* Local method prototypes */
172#ifdef N8DEBUG
173void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p);
174#endif
175
176/* Local methods */
177
178/*****************************************************************************
179 * n8_getNumUnits
180 *****************************************************************************/
181/** @ingroup n8_sks
182 * @brief Returns how many units (chips) there are in the system.
183 *
184 *  @param
185 *    None
186 *
187 * @par Externals
188 *    nspDriverInfo
189 *
190 * @return
191 *    Number of units.
192 *
193 * @par Errors
194 *    None
195 *
196 * @par Assumptions
197 *    Driver has been opened.
198 *
199 *****************************************************************************/
200
201static int n8_getNumUnits(void)
202{
203
204   return nspDriverInfo.numChips;
205
206} /* n8_getNumUnits */
207
208
209/*****************************************************************************
210 * n8_checkAndFreeEntry
211 *****************************************************************************/
212/** @ingroup n8_sks
213 * @brief Check to see if a named entry exists and if so free it.
214 *
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.
219 *
220 *  @param name                RO:  name of entry
221 *  @param unit                RO:  unit identifier
222 *
223 * @par Externals
224 *    None
225 *
226 * @return
227 *    Status
228 *
229 * @par Errors
230 *    None
231 *
232 * @par Assumptions
233 *    None
234 *****************************************************************************/
235
236static N8_Status_t n8_checkAndFreeEntry(const N8_Buffer_t *name, const N8_Unit_t unit)
237{
238   N8_Status_t ret;
239   N8_SKSKeyHandle_t tempHandle;
240
241   tempHandle.unitID = unit;
242   ret = N8_SKSGetKeyHandle(name, &tempHandle);
243
244   if (ret == N8_STATUS_OK)
245   {
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.
250       */
251      tempHandle.unitID = unit;
252#endif
253      /* an entry of this name exists.  free it and reclaim the resources. */
254      ret = N8_SKSFree(&tempHandle);
255   }
256   else
257   {
258      ret = N8_STATUS_OK;
259   }
260   return ret;
261}
262
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.
269 *
270 *  @param unit                RO:  unit ID to be verified
271 *  @param keyHandle_p         RW:  SKSKeyHandle to place the results
272 *
273 * @par Externals
274 *      None
275 *
276 * @return
277 *    Status
278 *
279 * @par Errors
280 *    N8_INVALID_VALUE if the unit id is out of range.
281 *
282 * @par Assumptions
283 *    None
284 *****************************************************************************/
285static N8_Status_t
286n8_verifyUnitID(const N8_Unit_t unit, N8_SKSKeyHandle_t *keyHandle_p)
287{
288   int numSKS;
289   static int sksSelection = 0;
290
291   /* get the number of units */
292   numSKS = n8_getNumUnits();
293
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)
301   {
302      keyHandle_p->unitID = sksSelection;
303      sksSelection = sksSelection + 1;
304      if (sksSelection == numSKS)
305      {
306         sksSelection = 0;
307      }
308   }
309   else if ((unit < 0) || (unit >= numSKS))
310   {
311      return N8_INVALID_VALUE;
312   }
313   else
314   {
315      keyHandle_p->unitID = unit;
316   }
317
318   return N8_STATUS_OK;
319}
320
321#ifdef N8DEBUG
322/*****************************************************************************
323 * n8_printSKSKeyHandle
324 *****************************************************************************/
325/** @ingroup n8_sks
326 * @brief Display a key handle for an SKS PROM.
327 *
328 * @param keyHandle_p RO: A pointer to the key handle to be printed.
329 *
330 * @par Externals:
331 *    None
332 *
333 * @return
334 *    None.
335 *
336 * @par Errors:
337 *    None.
338 *
339 * @par Assumptions:
340 *    None.
341 *****************************************************************************/
342void n8_printSKSKeyHandle(const N8_SKSKeyHandle_t *keyHandle_p)
343{
344
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
355
356/* Public methods */
357
358/*****************************************************************************
359 * N8_SKSDisplay
360 *****************************************************************************/
361/** @ingroup n8_sks
362 * @brief Display a description entity for an SKS PROM.
363 *
364 * Attempts to write a string into a given char string array.
365 *
366 * @param keyHandle_p       RW: A N8_SKSKeyHandle_t pointer.
367 * @param display_string    RO: A char array.
368 *
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.
373 *
374 * @return
375 *    N8_STATUS_OK if no other errors. The display contents should now be
376 *      within the provided char array.
377 *
378 * @par Assumptions:
379 *    The given key handle pointer is valid.
380 *****************************************************************************/
381N8_Status_t N8_SKSDisplay(N8_SKSKeyHandle_t *keyHandle_p,
382                          char              *display_string_p)
383{
384   if (keyHandle_p == NULL)
385   {
386      return N8_INVALID_KEY;
387   }
388
389   if (display_string_p == NULL)
390   {
391      return N8_INVALID_PARAMETER;
392   }
393
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);
402
403   return N8_STATUS_OK;
404} /* N8_SKSDisplay */
405
406
407/*****************************************************************************
408 * N8_SKSAllocateRSA
409 *****************************************************************************/
410/** @ingroup n8_sks
411 * @brief Allocate and write a private RSA key entry to an SKS PROM.
412 *
413 * Attempts to allocate, then write the key into an SKS PROM.
414 *
415 * @param keyMaterial_p       RW: A N8_RSAKeyMaterial_t pointer.
416 * @param keyEntryName_p      RW: A char pointer, the name of the sks entry.
417 *
418 * @par Externals:
419 *    None
420 *
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.
425 *
426 * @par Assumptions:
427 *    That the RSA key material pointer is valid.
428 *****************************************************************************/
429N8_Status_t N8_SKSAllocateRSA(N8_RSAKeyMaterial_t *keyMaterial_p,
430                              const N8_Buffer_t *keyEntryName_p)
431{
432   N8_RSAKeyObject_t key;
433   N8_Buffer_t* param;
434
435   uint32_t sksOffset = 0, targetSKS = 0, keyLength = 0;
436   N8_Status_t ret = N8_STATUS_OK;
437   N8_SKSKeyHandle_t *sks_key_p;
438
439   do
440   {
441      ret = N8_preamble();
442      CHECK_RETURN(ret);
443      CHECK_OBJECT(keyMaterial_p, ret);
444      CHECK_OBJECT(keyMaterial_p->privateKey.value_p, ret);
445
446      CHECK_OBJECT(keyEntryName_p, ret);
447      if (strlen(keyEntryName_p) >= N8_SKS_ENTRY_NAME_MAX_LENGTH)
448      {
449         ret = N8_INVALID_OBJECT;
450         break;
451      }
452      if ((keyMaterial_p->p.lengthBytes == 0) ||
453          (keyMaterial_p->q.lengthBytes == 0))
454      {
455         ret = N8_INVALID_KEY_SIZE;
456         break;
457      }
458
459      sks_key_p = &keyMaterial_p->SKSKeyHandle;
460
461      ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p);
462      CHECK_RETURN(ret);
463
464      /* Check requirements for p and q lengths. */
465
466      /* len(p) == len(q) */
467      if (keyMaterial_p->q.lengthBytes != keyMaterial_p->p.lengthBytes)
468      {
469         DBG(("P and Q RSA key material parameters not of same length!\n"));
470         ret = N8_INVALID_KEY_SIZE;
471         break;
472      }
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)
477      {
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;
482      }
483
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)
487      {
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;
491      }
492
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);
497
498      ret = N8_RSAInitializeKey(&key, N8_PRIVATE_CRT, keyMaterial_p, NULL);
499      CHECK_RETURN(ret);
500
501      keyLength = keyMaterial_p->privateKey.lengthBytes;
502      targetSKS = sks_key_p->unitID;
503      sks_key_p->key_type = N8_RSA_VERSION_1_KEY;
504
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);
508
509      DBG(("Key Length in bytes:  %d\n", keyLength));
510      DBG(("Key length in digits: %d\n", sks_key_p->key_length));
511
512      ret = n8_SKSAllocate(sks_key_p);
513      CHECK_RETURN(ret);
514
515      /* attempt to write the key information to the mapping files */
516      strcpy(sks_key_p->entry_name, keyEntryName_p);
517
518      /* request N8 userspace daemon to write out a key handle file */
519      ret = n8_daemon_sks_write(sks_key_p, keyEntryName_p);
520
521      if (ret != N8_STATUS_OK)
522      {
523         /* the write to the key handle failed.
524          * we need to unallocate the space
525          * and return a failure. */
526
527         DBG(("n8_daemon_sks_write returned error\n"));
528
529         n8_SKSsetStatus(sks_key_p, SKS_FREE);
530         break;
531      }
532
533      sksOffset = sks_key_p->sks_offset;
534
535      /* Write the data into the SKS PROM. */
536      DBG(("Writing key data into SKS.\n"));
537
538      /* Write the p value into the SKS. */
539      DBG(("Writing p param into SKS.\n"));
540
541      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
542         PK_RSA_P_Param_Byte_Offset(&key);
543
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);
552
553      /* Write the p value into the SKS. */
554      DBG(("Writing q param into SKS.\n"));
555
556      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
557         PK_RSA_Q_Param_Byte_Offset(&key);
558
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);
567
568      /* Write the dp value into the SKS. */
569      DBG(("Writing dp param into SKS.\n"));
570
571      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
572         PK_RSA_DP_Param_Byte_Offset(&key);
573
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);
580
581      DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
582      CHECK_RETURN(ret);
583
584
585      /* Write the dq value into the SKS. */
586      DBG(("Writing dq param into SKS.\n"));
587
588      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
589         PK_RSA_DQ_Param_Byte_Offset(&key);
590
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);
599
600      /* Write the R mod p value into the SKS. */
601      DBG(("Writing R mod p param into SKS.\n"));
602
603      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
604         PK_RSA_R_MOD_P_Param_Byte_Offset(&key);
605
606
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);
616
617      /* Write the R mod q value into the SKS. */
618      DBG(("Writing R mod q param into SKS.\n"));
619
620      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
621         PK_RSA_R_MOD_Q_Param_Byte_Offset(&key);
622
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);
632
633      /* Write the n value into the SKS. */
634      DBG(("Writing n param into SKS.\n"));
635
636      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
637         PK_RSA_N_Param_Byte_Offset(&key);
638
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);
646
647      DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
648      CHECK_RETURN(ret);
649
650      /* Write the pInv value into the SKS. */
651      DBG(("Writing pInv param into SKS.\n"));
652
653      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
654         PK_RSA_U_Param_Byte_Offset(&key);
655
656
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);
664
665      DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
666      CHECK_RETURN(ret);
667
668      /* Write the cp value into the SKS. */
669      DBG(("Writing cp param into SKS.\n"));
670
671      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
672         PK_RSA_CP_Param_Byte_Offset(&key);
673
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);
680
681      DBG(("Return from write: %s\n", N8_Status_t_text(ret)));
682      CHECK_RETURN(ret);
683
684      /* Write the cq value into the SKS. */
685      DBG(("Writing cq param into SKS.\n"));
686
687      param = (N8_Buffer_t*) key.kmem_p->VirtualAddress +
688         PK_RSA_CQ_Param_Byte_Offset(&key);
689
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);
699
700   if (key.structureID == N8_RSA_STRUCT_ID)
701   {
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)
708      {
709         ret = freeRet;
710      }
711   }
712   return ret;
713
714} /* N8_SKSAllocateRSA */
715
716
717/*****************************************************************************
718 * N8_SKSAllocateDSA
719 *****************************************************************************/
720/** @ingroup n8_sks
721 * @brief Allocate and write a private DSA key entry to an SKS PROM.
722 *
723 * Attempts to allocate, then write the key into an SKS PROM.
724 *
725 * @param keyMaterial_p       RW: A N8_DSAKeyMaterial_t pointer.
726 * @param keyEntryName_p      RW: A char pointer, the name of the sks entry.
727 *
728 * @par Externals:
729 *    None
730 *
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.
736 *
737 * @par Assumptions:
738 *    That the DSA key material pointer is valid.
739 *****************************************************************************/
740N8_Status_t N8_SKSAllocateDSA(N8_DSAKeyMaterial_t *keyMaterial_p,
741                              const N8_Buffer_t *keyEntryName_p)
742{
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;
749
750   do
751   {
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)
758      {
759         ret = N8_INVALID_OBJECT;
760         break;
761      }
762
763      if ((keyMaterial_p->p.lengthBytes == 0) ||
764          (keyMaterial_p->q.lengthBytes == 0))
765      {
766         ret = N8_INVALID_KEY_SIZE;
767         break;
768      }
769
770      ret = n8_DSAValidateKey(keyMaterial_p, N8_PRIVATE);
771      CHECK_RETURN(ret);
772
773      sks_key_p = &keyMaterial_p->SKSKeyHandle;
774
775      ret = n8_verifyUnitID(keyMaterial_p->unitID, sks_key_p);
776      CHECK_RETURN(ret);
777
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);
781
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);
786
787      ret = N8_DSAInitializeKey(&key, N8_PRIVATE, keyMaterial_p, NULL);
788      CHECK_RETURN(ret);
789
790      keyLength = sks_key_p->key_length;
791      targetSKS = sks_key_p->unitID;
792      sks_key_p->key_type = N8_DSA_VERSION_1_KEY;
793
794
795      /* allocate an sks. */
796      ret = n8_SKSAllocate(sks_key_p);
797      CHECK_RETURN(ret);
798
799      /* attempt to write the key information to the mapping files */
800      strcpy(sks_key_p->entry_name, keyEntryName_p);
801
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)
805      {
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;
811      }
812
813      sksOffset = sks_key_p->sks_offset;
814
815      /* Write the data into the SKS PROM. */
816      DBG(("Writing key data into SKS.\n"));
817
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
824       */
825
826      /* Write the p value into the SKS. */
827      DBG(("Writing p param into SKS.\n"));
828
829      param = key.paramBlock + PK_DSA_P_Param_Offset;
830
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);
838
839      /* Write the gR mod p value into the SKS. */
840      DBG(("Writing gR mod p param into SKS.\n"));
841
842      param = key.paramBlock +  PK_DSA_GR_MOD_P_Param_Offset(sks_key_p->key_length);
843
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);
851
852      /* Write the q value into the SKS. */
853      DBG(("Writing q param into SKS.\n"));
854
855      param = key.paramBlock +
856         PK_DSA_Q_Param_Offset(sks_key_p->key_length);
857
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);
865
866      /* Write the x value (private key) into the SKS. */
867      DBG(("Writing x (private key) param into SKS.\n"));
868
869      param = key.paramBlock +
870         PK_DSA_X_Param_Offset(sks_key_p->key_length);
871
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);
880
881      /* Write the cp value into the SKS. */
882      DBG(("Writing cp into SKS.\n"));
883
884      param = key.paramBlock +
885         PK_DSA_CP_Param_Offset(sks_key_p->key_length);
886
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);
894
895   } while (FALSE);
896
897   if (key.structureID == N8_DSA_STRUCT_ID)
898   {
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)
905      {
906         ret = freeRet;
907      }
908   }
909
910   return ret;
911
912} /* N8_SKSAllocateDSA */
913
914/*****************************************************************************
915 * N8_SKSFree
916 *****************************************************************************/
917/** @ingroup n8_sks
918 * @brief De-allocates and erases a private key entry to an SKS PROM.
919 *
920 * Attempts to de-allocate, then erase the key into an SKS PROM.
921 *
922 * @param keyHandle_p       RW: A N8_SKSKeyHandle_t pointer.
923 *
924 * @par Externals:
925 *    None
926 *
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.
932 *
933 * @par Assumptions:
934 *    That the key handle pointer is valid.
935 *****************************************************************************/
936N8_Status_t N8_SKSFree(N8_SKSKeyHandle_t* keyHandle_p)
937{
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];
944
945   DBG(("SKS Free\n"));
946
947   ret = N8_preamble();
948   if (ret != N8_STATUS_OK)
949   {
950      return ret;
951   }
952   if (keyHandle_p == NULL)
953   {
954      ret = N8_INVALID_KEY;
955      return ret;
956   }
957
958#ifdef N8DEBUG
959   n8_printSKSKeyHandle(keyHandle_p);
960#endif
961
962   if ((keyHandle_p->key_type) == N8_RSA_VERSION_1_KEY)
963   {
964      words_to_free = SKS_RSA_DATA_LENGTH(keyHandle_p->key_length);
965      key_type = "RSA";
966   }
967   else if (keyHandle_p->key_type == N8_DSA_VERSION_1_KEY)
968   {
969      words_to_free = SKS_DSA_DATA_LENGTH(keyHandle_p->key_length);
970      key_type = "DSA";
971   }
972   else
973   {
974      DBG(("Unknown key type.\n"));
975      return N8_INVALID_KEY;
976   }
977
978   DBG(("Zeroing out the key in the SKS PROM.\n"));
979
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++)
984   {
985      ret = n8_SKSWrite(keyHandle_p->unitID, &zero, 1, i, FALSE);
986      if (ret != N8_STATUS_OK)
987      {
988         DBG(("Error writing to SKS in N8_SKSFree.  (%s)\n",
989              N8_Status_t_text(ret)));
990         return ret;
991      }
992   }
993
994   n8_SKSsetStatus(keyHandle_p, SKS_FREE);
995
996   sprintf(fullFileName, "%s%d/%s",
997           SKS_KEY_NODE_PATH,
998           keyHandle_p->unitID,
999           keyHandle_p->entry_name);
1000
1001   /* request N8 userspace daemon to delete the specfied file */
1002   n8_daemon_sks_delete(fullFileName);
1003
1004   return N8_STATUS_OK;
1005
1006} /* N8_SKSFree */
1007
1008
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.
1014 *
1015 * @param systemKeyNode     RW: A char pointer, the named key entry.
1016 * @param keyHandle_p       WO: A N8_SKSKeyHandle_t pointer.
1017 *
1018 * @par Externals:
1019 *    SKS_initialized_g     RW: A boolean value that indicates whether 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.
1025 *
1026 *****************************************************************************/
1027N8_Status_t N8_SKSGetKeyHandle(const N8_Buffer_t* keyEntryName,
1028                               N8_SKSKeyHandle_t* keyHandle_p)
1029{
1030
1031   N8_Status_t ret = N8_STATUS_OK;
1032   char fullFileName[1024];
1033   int numberSKS;
1034   int i;
1035   int found;
1036
1037   DBG(("Get KeyHandle : \n"));
1038
1039   ret = N8_preamble();
1040   if (ret != N8_STATUS_OK)
1041   {
1042      return ret;
1043   }
1044
1045   if ((keyEntryName == NULL) || (keyHandle_p == NULL))
1046   {
1047      return N8_INVALID_OBJECT;
1048   }
1049
1050   /* get the number of units */
1051   numberSKS = n8_getNumUnits();
1052
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. */
1056
1057   if ((strlen(SKS_KEY_NODE_PATH) + strlen(keyEntryName) + 4) >=
1058       sizeof(fullFileName))
1059   {
1060      return N8_UNEXPECTED_ERROR;
1061   }
1062   found = -1;
1063   for (i = 0; i < numberSKS; i++)
1064   {
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
1068       */
1069      ret = n8_daemon_sks_read(keyHandle_p, fullFileName);
1070      if (ret == N8_STATUS_OK)
1071      {
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;
1079      }
1080   }
1081   if (found == -1)
1082   {
1083      ret = N8_INVALID_KEY;
1084   }
1085
1086   return ret;
1087} /* N8_SKSGetKeyHandle */
1088
1089/*****************************************************************************
1090 * N8_SKSReset
1091 *****************************************************************************/
1092/** @ingroup n8_sks
1093 * @brief Obliterates all data within an SKS PROM.
1094 *
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.
1098 *
1099 * @param targetSKS       RW: A int, the target SKS PROM.
1100 *
1101 * @par Externals:
1102 *    None
1103 *
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.
1109 *
1110 *****************************************************************************/
1111N8_Status_t N8_SKSReset(N8_Unit_t targetSKS)
1112{
1113   int i;
1114   N8_Status_t ret = N8_STATUS_OK;
1115   N8_Unit_t firstSKS, lastSKS;
1116   int numberSKS;
1117
1118   DBG(("N8_SKSReset: entering...\n"));
1119
1120   ret = N8_preamble();
1121   if (ret != N8_STATUS_OK)
1122   {
1123      return ret;
1124   }
1125
1126   /* get the number of units */
1127   numberSKS = n8_getNumUnits();
1128
1129   if (targetSKS == N8_ANY_UNIT)
1130   {
1131      firstSKS = 0;
1132      lastSKS = numberSKS-1;
1133   }
1134   else if (targetSKS >= 0 &&
1135            targetSKS < numberSKS)
1136   {
1137      firstSKS = lastSKS = targetSKS;
1138   }
1139   else
1140   {
1141      ret = N8_INVALID_VALUE;
1142      return ret;
1143   }
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++)
1147   {
1148
1149      ret = n8_SKSResetUnit(i);
1150      if (ret != N8_STATUS_OK)
1151      {
1152         return ret;
1153      }
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
1158       */
1159      ret = n8_daemon_sks_reset(i);
1160      if (ret != N8_STATUS_OK)
1161      {
1162         DBG(("Error resetting SKS files: %d\n", ret));
1163         return N8_FILE_ERROR;
1164      }
1165   }
1166   DBG(("N8_SKSReset: leaving...\n"));
1167
1168
1169   return ret;
1170} /* N8_SKSReset */
1171
1172/*****************************************************************************
1173 * N8_SKSVerifyRSA
1174 *****************************************************************************/
1175N8_Status_t N8_SKSVerifyRSA(N8_SKSKeyHandle_t* keyHandle_p,
1176                            N8_Buffer_t* input_p,
1177                            N8_Buffer_t* result_p)
1178{
1179   N8_RSAKeyObject_t privateKey;
1180   N8_Buffer_t* decryptBuffer_p;
1181   N8_Status_t ret;
1182
1183   DBG(("Verify RSA Key.\n"));
1184
1185   ret = N8_preamble();
1186   if (ret != N8_STATUS_OK)
1187   {
1188      return ret;
1189   }
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)
1193   {
1194      DBG(("Could not initialize RSA private key from SKS. (%s)\n",
1195           N8_Status_t_text(ret)));
1196      return ret;
1197   }
1198
1199   decryptBuffer_p = (N8_Buffer_t *) N8_UMALLOC(privateKey.privateKeyLength);
1200   if (decryptBuffer_p == NULL)
1201   {
1202      DBG(("Could not allocate %i bytes for decrypt buffer.\n",
1203           privateKey.privateKeyLength));
1204      return N8_MALLOC_FAILED;
1205   }
1206
1207   ret = N8_RSADecrypt(&privateKey, input_p,
1208                       privateKey.privateKeyLength,
1209                       decryptBuffer_p, NULL);
1210   if (ret != N8_STATUS_OK)
1211   {
1212      DBG(("Could not complete RSA decrypt using SKS private key. (%s)\n",
1213           N8_Status_t_text(ret)));
1214      return ret;
1215   }
1216
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)
1219   {
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;
1223   }
1224
1225   DBG(("RSA Decrypt good: SKS private key is valid.\n"));
1226
1227   return N8_STATUS_OK;
1228} /* N8_SKSVerifyRSA */
1229
1230/*****************************************************************************
1231 * N8_SKSVerifyDSA
1232 *****************************************************************************/
1233
1234N8_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)
1238{
1239   N8_DSAKeyObject_t privateKey;
1240   N8_Buffer_t* signRValueBuffer_p, *signSValueBuffer_p;
1241   N8_Status_t ret;
1242   DBG(("Verify DSA Key.\n"));
1243
1244   ret = N8_preamble();
1245   if (ret != N8_STATUS_OK)
1246   {
1247      return ret;
1248   }
1249
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)
1253   {
1254      DBG(("Could not initialize DSA private key from SKS. (%s)\n",
1255           N8_Status_t_text(ret)));
1256      return ret;
1257   }
1258
1259   /* !!!!!! Is there a #define for the S and R value byte lengths?!?!?!! */
1260   if ((signRValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0)
1261   {
1262      DBG(("Could not allocate %i bytes for DSA sign R value buffer.\n",
1263           privateKey.modulusLength));
1264      return N8_MALLOC_FAILED;
1265   }
1266
1267   if ((signSValueBuffer_p = (N8_Buffer_t *) N8_UMALLOC(20)) != 0)
1268   {
1269      DBG(("Could not allocate %i bytes for DSA sign S value buffer.\n",
1270           privateKey.modulusLength));
1271      return N8_MALLOC_FAILED;
1272   }
1273
1274   ret = N8_DSASign(&privateKey, inputHash_p, signRValueBuffer_p,
1275                    signSValueBuffer_p, NULL);
1276   if (ret != N8_STATUS_OK)
1277   {
1278      DBG(("Could not complete DSA sign using SKS private key. (%s)\n",
1279           N8_Status_t_text(ret)));
1280      return ret;
1281   }
1282
1283   /* Compare the buffers. If they are different, then indicate this in the return code. */
1284   if (memcmp(resultRValue_p, signRValueBuffer_p, 20) != 0)
1285   {
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;
1289   }
1290
1291   if (memcmp(resultSValue_p, signSValueBuffer_p, 20) != 0)
1292   {
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;
1296   }
1297
1298   DBG(("DSA Sign good: SKS private key is valid.\n"));
1299
1300   return N8_STATUS_OK;
1301
1302} /* N8_SKSVerifyDSA */
1303
1304
1305