No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_dsa.c
blobdebf6e7239849311dcee977d8df2b0a4cb477716
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_dsa.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_dsa.c
38 * @brief Public DSA functions.
40 * Implementation of all public DSA functions.
42 *****************************************************************************/
44 /*****************************************************************************
45 * Revision history:
46 * 04/11/03 brr Modified initDSAPrivateKey to overwrite the generic hardware
47 * error returned by HANDLE_EVENT with INVALID_KEY. (BUG 761)
48 * 09/10/02 brr Set command complete bit on last command block.
49 * 05/20/02 brr Free the request for all error conditions.
50 * 05/15/02 brr Reworked to remove chain request, RNG now returns random bytes.
51 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
52 * 05/01/02 brr Memset structures after KMALLOC.
53 * 04/05/02 bac Moved the checking of parameters for initialization to the
54 * validation routine for correct operation. (BUG 513)
55 * 04/01/02 brr Validate modulus, divisor, and generator pointers before
56 * use in N8_DSAInitializeKey.
57 * 03/26/02 brr Allocate the data buffer as part of the API request.
58 * 03/08/02 msz Get random bytes using a direct physical address.
59 * 02/28/02 brr Do not include any QMgr include files.
60 * 02/25/02 brr Remove unused variables.
61 * 02/20/02 brr Removed references to the queue structure.
62 * 01/29/02 bac Changed DSASign to use N8_GetRandomBytes directly if we are
63 * using the underlying OS random number generator (not our
64 * hardware or behavioral model).
65 * 01/31/02 brr Eliminated the memory allocation for postProcessingData.
66 * 12/11/01 mel Fixed bug #420: There is a new requirement (to appear in rev
67 * J of the API Spec) that states for a DSA key to be eligible
68 * for use in the SKS the modulus length must either be an
69 * even multiple of 16 -OR- an even multiple of 16 minus 8. Added
70 * check for SKS key.
71 * Fixed bug #412: Set SKS key length from SKS key material
72 * 12/11/01 mel Fixed bug #380: Added extra checks for DSAInitializeKey
73 * 11/30/01 msz Fixed bug #377 : Added check structure in N8_DSAFreeKey
74 * 11/30/01 mel Fixed bug #396 : N8_DSAInitializeKey segfaults when private
75 * key information not needed.
76 * 11/29/01 msz Fixed bug #374 : Check that r and q are non zero.
77 * also free postProcessingData_p in freeRequest so there is
78 * no memory leak in error cases.
79 * 11/28/01 mel Fixed bug #372 : DSAInitializeKey should return
80 * N8_INVALID_KEY when x>=q.
81 * 11/19/01 bac Corrected checking of DSA constraints. Bug #169.
82 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
83 * 11/15/01 mel Fixed bug #317 : No SKS support for DSA keys.
84 * 11/08/01 mel Added unit ID parameter to commend block calls (bug #289).
85 * 11/06/01 dkm Corrected error return for invalid key enum.
86 * 11/06/01 hml Added the structure verification.
87 * 10/31/01 bac Added initDSAPrivateSKSKey and support for it.
88 * 10/30/01 dkm Cleaned up minor error condition bugs.
89 * 10/18/01 hml Removed several redundant calls to AddMemoryStructToFree.
90 * 10/11/01 bac Rearranged some code for proper memory freeing.
91 * 10/10/01 brr Fixed memory leaks from N8_KMALLOC.
92 * 10/04/01 brr Removed warnings exposed when optimization turned on.
93 * 10/02/01 bac Changed N8_CCM_ enums to #defines as they define masks.
94 * 10/01/01 hml Added multi-unit support.
95 * 09/21/01 mel Cleaned.
96 * 09/17/01 mel Changed command block strategy. Instead of queuing every
97 * time we built command block, put all command blocks together
98 * and queue them once.
99 * 09/10/01 bac Test for public key and modulus lengths in
100 * N8_DSAInitializeKey (BUG #129).
101 * 09/14/01 mel Added event parameter to N8_DSAInitializeKey.
102 * 09/05/01 bac Minor formatting changes.
103 * 08/24/01 bac Changed all interfaces to the cb commands to pre-allocate the
104 * command buffer space.
105 * 08/10/01 bac Fixed bug in N8_DSASign where the value of the random number N
106 * was compared to q. This check is done in the hardware and was
107 * removed from the API code.
108 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
109 * 07/30/01 bac Use queue_p in all macro length calculations.
110 * 07/20/01 bac Changed calls to create__RequestBuffer to pass the chip id.
111 * 07/12/01 bac Deleted unused variables.
112 * 07/13/01 mel Fixed public Key initialization and added verification to
113 * key initialization.
114 * 06/29/01 mel Fixed comments.
115 * 06/28/01 bac Added back some changes lost in the merge to round up to the
116 * next word size for memory allocation.
117 * 06/26/01 bac Bug fixes for computation of 'n' random value. Also moved
118 * copy backs to result handlers for async compatibility.
119 * 06/25/01 bac Lots of changes to affect functionality with the v1.0.1 QMgr
120 * 06/22/01 bac More kernel memory fixes.
121 * 06/20/01 mel Corrected use of kernel memory.
122 * 05/22/01 mel Original version.
123 ****************************************************************************/
124 /** @defgroup dsa DSA Functions.
128 #include "n8_common.h"
129 #include "n8_pub_errors.h"
130 #include "n8_dsa.h"
131 #include "n8_pk_common.h"
132 #include "n8_enqueue_common.h"
133 #include "n8_util.h"
134 #include "n8_API_Initialize.h"
135 #include "n8_malloc_common.h"
137 #include "n8_cb_dsa.h"
138 #include "n8_cb_rsa.h"
142 * local predeclarations
144 static N8_Status_t initDSAPublicKey(N8_DSAKeyObject_t *key_p,
145 N8_DSAKeyMaterial_t *material_p,
146 N8_Event_t *event_p);
148 static N8_Status_t initDSAPrivateKey(N8_DSAKeyObject_t *key_p,
149 N8_DSAKeyMaterial_t *material_p,
150 N8_Event_t *event_p);
151 static N8_Status_t initDSAPrivateSKSKey(N8_DSAKeyObject_t *key_p,
152 N8_DSAKeyMaterial_t *material_p,
153 N8_Event_t *event_p);
155 static N8_Status_t checkModulusLength(unsigned int length);
157 /* structure for toting around destination result buffers for copy in result
158 * handler for N8_DSASign */
159 typedef struct
161 N8_Buffer_t *rFrom_p;
162 N8_Buffer_t *sFrom_p;
163 N8_Buffer_t *rTo_p;
164 N8_Buffer_t *sTo_p;
165 } dsaSignPostDataStruct_t;
167 /* structure for toting around buffers to be compared and result destination in
168 * result handler for N8_DSAVerify */
169 typedef struct
171 N8_Buffer_t *computed_p;
172 N8_Buffer_t *expected_p;
173 int size;
174 N8_Boolean_t *verify_p;
175 } dsaVerifyPostDataStruct_t;
177 /**********************************************************************
178 * resultHandlerDSAVerify
180 * Description:
181 * This function is called by the Public Key Request Queue handler when
182 * either the request is completed successfully and all the commands
183 * copied back to the command blocks allocated by the API, or when
184 * the Simon has encountered an error with one of the commands such
185 * that the Simon has locked up.
187 * Note this function will have to be NON-BLOCKING or it will lock up the
188 * queue handler!
190 * jke
192 **********************************************************************/
193 static void resultHandlerDSAVerify(API_Request_t* req_p)
195 dsaVerifyPostDataStruct_t *postData_p = NULL;
197 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
199 DBG(("resultHandlerDSAVerify call-back with success\n"));
201 postData_p = (dsaVerifyPostDataStruct_t *) req_p->postProcessingData_p;
202 if (memcmp(postData_p->expected_p,
203 postData_p->computed_p,
204 postData_p->size) == 0)
206 *(postData_p->verify_p) = N8_TRUE;
209 else
211 RESULT_HANDLER_WARNING("n8_dsa::resultHandlerDSAVerify",
212 req_p);
215 /* do not free the request. it is freed by the event processor. */
218 /**********************************************************************
219 * resultHandlerDSASign
221 * Description:
222 * This function is called by the Public Key Request Queue handler when
223 * either the request is completed successfully and all the commands
224 * copied back to the command blocks allocated by the API, or when
225 * the Simon has encountered an error with one of the commands such
226 * that the Simon has locked up.
228 * Note this function will have to be NON-BLOCKING or it will lock up the
229 * queue handler!
231 * jke
233 **********************************************************************/
234 static void resultHandlerDSASign(API_Request_t* req_p)
236 dsaSignPostDataStruct_t *postData_p = NULL;
237 int skipLength;
238 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
240 DBG(("resultHandlerDSASign call-back with success\n"));
241 postData_p = (dsaSignPostDataStruct_t *) req_p->postProcessingData_p;
242 /* Only copy back the last NUMBER_OF_BYTES_IN_VALUE as the rest are not
243 * meaningful */
244 skipLength = PK_DSA_R_Byte_Length - DSA_SIGN_LENGTH;
245 memcpy(postData_p->rTo_p,
246 postData_p->rFrom_p + skipLength,
247 DSA_SIGN_LENGTH);
248 skipLength = PK_DSA_S_Byte_Length - DSA_SIGN_LENGTH;
249 memcpy(postData_p->sTo_p,
250 postData_p->sFrom_p + skipLength,
251 DSA_SIGN_LENGTH);
253 else
255 RESULT_HANDLER_WARNING("n8_dsa::resultHandlerDSASign",
256 req_p);
259 /* do not free the request. it is freed by the event processor. */
260 } /* resultHandlerDSASign */
262 /*****************************************************************************
263 * n8_testValueInUpperRange
264 *****************************************************************************/
265 /** @ingroup dsa
266 * @brief Test that a given value is in the upper range.
268 * For some cryptographic quantities, a restriction exists that the value must
269 * be greater than 2**(L-1) where L is the length in bits. Basically, this
270 * means the value must greater than the mid-point of the range of values.
271 * Specifically, the high-order bit must be 1 and at least one subsequent bit
272 * must be 1.
274 * @param p RO: Pointer to the sized buffer to be checked.
276 * @par Externals
277 * None
279 * @return
280 * Status of comparison: N8_STATUS_OK or N8_INVALID_KEY.
282 * @par Errors
283 * None
285 * @par Assumptions
286 * None
287 *****************************************************************************/
288 static N8_Status_t n8_testValueInUpperRange(const N8_SizedBuffer_t *p)
290 N8_Status_t ret = N8_INVALID_KEY;
291 int i;
295 /* test to see if the uppermost bit is set. if so, the value will be in
296 * the range (0x8 - 0xF). */
297 if (p->value_p[0] < 0x8)
299 /* an error exists. keep the error return code and break. */
300 break;
302 for (i = 0; i < p->lengthBytes; i++)
304 if (p->value_p[i] != 0)
306 /* at least one bit has been found set. return N8_STATUS_OK. */
307 ret = N8_STATUS_OK;
308 break;
311 } while (FALSE);
313 return ret;
314 } /* n8_testValueInUpperRange */
315 /*****************************************************************************
316 * n8_DSAValidateKey
317 *****************************************************************************/
318 /** @ingroup dsa
319 * @brief Test to see if input in N8_DSAKeyMaterial_t is valid.
321 * The requirements for a valid set of values for a DSA key are checked. If any
322 * of the constraints are violated an error is returned
324 * @param keyMaterial_p RO: Pointer to key material.
325 * @param type RO: Type of key
327 * @par Externals
328 * None
330 * @return
331 * Status of validation.
333 * @par Errors
334 * N8_STATUS_OK, N8_INVALID_KEY, or N8_INVALID_KEY_SIZE
336 * @par Assumptions
337 * None
338 *****************************************************************************/
339 N8_Status_t n8_DSAValidateKey(const N8_DSAKeyMaterial_t *material_p,
340 const N8_KeyType_t type)
342 N8_Status_t ret = N8_STATUS_OK;
343 int value_cmp;
347 /* ensure we have all of the correct parameters for the key type */
348 switch(type)
350 case N8_PUBLIC:
351 CHECK_OBJECT(material_p->publicKey.value_p, ret);
352 CHECK_OBJECT(material_p->p.value_p, ret);
353 CHECK_OBJECT(material_p->q.value_p, ret);
354 CHECK_OBJECT(material_p->g.value_p, ret);
355 break;
357 case N8_PRIVATE:
358 CHECK_OBJECT(material_p->privateKey.value_p, ret);
359 CHECK_OBJECT(material_p->p.value_p, ret);
360 CHECK_OBJECT(material_p->q.value_p, ret);
361 CHECK_OBJECT(material_p->g.value_p, ret);
362 break;
363 case N8_PRIVATE_SKS:
364 break;
365 default:
366 ret = N8_INVALID_ENUM;
367 break;
369 CHECK_RETURN(ret);
372 * check the modulus, p
375 /* first check the length */
376 ret = checkModulusLength(material_p->p.lengthBytes);
377 CHECK_RETURN(ret);
379 /* for a p of length L bits, p > 2**(L-1) */
380 ret = n8_testValueInUpperRange(&material_p->p);
381 CHECK_RETURN(ret);
384 * check the generator, g
387 /* len(g) == len(p) */
388 if (material_p->g.lengthBytes != material_p->p.lengthBytes)
390 ret = N8_INVALID_KEY_SIZE;
391 break;
393 /* g < p */
394 value_cmp = n8_sizedBufferCmp(&material_p->g, &material_p->p);
395 if (value_cmp >= 0)
397 ret = N8_INVALID_KEY;
398 break;
402 * check q, a prime divisor of (p - 1)
405 /* len(q) == 20 */
406 if (material_p->q.lengthBytes != N8_DSA_PRIVATE_KEY_LENGTH)
408 ret = N8_INVALID_KEY_SIZE;
409 break;
411 /* for a q of length L bits, q > 2**(L-1) */
412 ret = n8_testValueInUpperRange(&material_p->q);
413 CHECK_RETURN(ret);
415 if (type == N8_PRIVATE)
417 /* check the private key */
418 if (material_p->privateKey.lengthBytes != N8_DSA_PRIVATE_KEY_LENGTH)
420 ret = N8_INVALID_KEY_SIZE;
421 break;
423 /* private key < q */
424 value_cmp = n8_sizedBufferCmp(&material_p->privateKey, &material_p->q);
425 if (value_cmp >= 0)
427 ret = N8_INVALID_KEY;
428 break;
431 else /* the type is pre-screened and must be N8_PUBLIC at this point. */
433 /* check the public key */
434 if (material_p->publicKey.lengthBytes != material_p->p.lengthBytes)
436 ret = N8_INVALID_KEY_SIZE;
437 break;
439 /* public key < p */
440 value_cmp = n8_sizedBufferCmp(&material_p->publicKey, &material_p->p);
441 if (value_cmp >= 0)
443 ret = N8_INVALID_KEY;
444 break;
448 } while (FALSE);
450 return ret;
452 } /* n8_DSAValidateKey */
454 /**********************************************************************
455 * N8_DSAInitializeKey
456 ***********************************************************************/
457 /** @ingroup dsa
458 * @brief Initializes the specified DSAKeyObject so that it can be used
459 * in DSA sign / verify operations.
461 * Description:
462 * The KeyMaterial object (structure) contains the appropriate key
463 * (x or y), modulus p, q and g values depending on the type of key
464 * being initialized. The enumeration parameter KeyType specifies what
465 * kind of key is being set up and thus which fields in the KeyMaterial
466 * object must be valid. There are 3 legal values for KeyType: "Public",
467 * "Private", and "SKS Private".
470 * @param key_p RW: The caller allocated DSAKeyObject, initialized
471 * by this call with the appropriate DSA key
472 * material and pre-computed DSA constants
473 * depending on the value of the KeyType parameter.
474 * @param type RO: An enumeration value specifying the type of
475 * key to initialize. Valid values are: Public,
476 * Private, and SKSPrivate.
477 * @param material_p RO: Pointer to the key material to use in initializing
478 * DSAKeyObject. The valid information that must be
479 * supplied depends on the value of of KeyType.
482 * @return
483 * ret - returns N8_STATUS_OK if successful or Error value.
485 * @par Errors:
486 * N8_INVALID_OBJECT - DSA key or key material object is NULL<BR>
487 * N8_INVALID_ENUM - The value of KeyType is not one of
488 * the values Public, Private, or SKSPrivate.
489 * N8_UNIMPLEMENTED_FUNCTION - means that PRIVATE SKS protocol not
490 * implemented in this release.
492 * @par Assumptions:
493 * None.
494 **********************************************************************/
495 N8_Status_t N8_DSAInitializeKey(N8_DSAKeyObject_t *key_p,
496 N8_KeyType_t type,
497 N8_DSAKeyMaterial_t *material_p,
498 N8_Event_t *event_p)
500 N8_Status_t ret = N8_STATUS_OK;
504 ret = N8_preamble();
505 CHECK_RETURN(ret);
507 CHECK_OBJECT(key_p, ret);
508 CHECK_OBJECT(material_p, ret);
509 memset(key_p, 0x0, sizeof(N8_DSAKeyObject_t));
511 /* The unit specifier is found in a different place depending on
512 the requested type */
513 switch (type)
515 case N8_PUBLIC:
516 case N8_PRIVATE:
517 key_p->unitID = material_p->unitID;
518 break;
520 case N8_PRIVATE_SKS:
521 key_p->unitID = material_p->SKSKeyHandle.unitID,
523 /* Copy all of the SKS data into the key */
524 memcpy((void *) &(key_p->SKSKeyHandle),
525 (const void *) &(material_p->SKSKeyHandle),
526 sizeof(N8_SKSKeyHandle_t));
527 break;
529 default:
530 ret = N8_INVALID_ENUM;
531 break;
535 * Verify parameters if this is not SKS call
537 if (type != N8_PRIVATE_SKS)
539 ret = n8_DSAValidateKey(material_p, type);
540 CHECK_RETURN(ret);
543 key_p->keyType = type;
544 switch(type)
546 case N8_PUBLIC:
547 ret = initDSAPublicKey(key_p, material_p, event_p);
548 break;
550 case N8_PRIVATE:
551 ret = initDSAPrivateKey(key_p, material_p, event_p);
552 break;
553 case N8_PRIVATE_SKS:
554 ret = initDSAPrivateSKSKey(key_p, material_p, event_p);
555 break;
556 default:
557 ret = N8_INVALID_ENUM;
558 break;
560 CHECK_RETURN(ret);
562 } while(FALSE);
564 if (ret == N8_STATUS_OK)
566 /* Set the structure ID */
567 key_p->structureID = N8_DSA_STRUCT_ID;
569 return ret;
570 } /* N8_DSAInitializeKey */
572 /**********************************************************************
573 * N8_DSASign
574 ***********************************************************************/
575 /** @ingroup dsa
576 * @brief Digitally signs the message whose SHA-1 hash value is MessageHash
577 * using the Digital Signature Algorithm (DSA) as defined by the Digital
578 * Signature Standard [DSS].
580 * Description:
581 * Digitally signs the message whose SHA-1 hash value is MessageHash
582 * using the Digital Signature Algorithm (DSA) as defined by the Digital
583 * Signature Standard [DSS]. MessageHash is the 20 byte SHA-1 hash value
584 * of the message being signed (for example, as computed by
585 * N8_HashCompleteMessage).
586 * The two DSA defined signature values, r and s, are returned in RValue
587 * and SValue respectively.
588 * r = (gN mod p) mod q
589 * s = (N-1 * (h + x*r) ) mod q
590 * where N = a random value (supplied by the system), h = the SHA-1 hash
591 * value MessageHash, and x, g, p, and q are the DSA key parameters defined
592 * by DSAKeyObject. DSAKeyObject must have been previously initialized via
593 * an appropriate call to N8_DSAInitializeKey.
596 * Parameters:
597 * @param key_p RO: The previously initialized DSAKeyObject
598 * containing the DSA key materials to be used.
599 * @param msgHash_p RO: The SHA-1 hash of the message being signed;
600 * always 20 bytes.
601 * @param rValue_p WO: The DSA r value. This is always 20 bytes
602 * in length.
603 * @param sValue_p WO: The DSA s value. This is always 20 bytes
604 * in length.
605 * @param event_p RW: On input, if null the call is synchronous
606 * and no event is returned. The operation
607 * is complete when the call returns. If
608 * non-null, then the call is asynchronous;
609 * an event is returned that can be used to
610 * determine when the operation completes.
612 * @return
613 * ret - returns N8_STATUS_OK if successful or Error value.
615 * @par Errors:
616 * N8_INVALID_OBJECT - context request object is NULL<BR>
617 * N8_INVALID_KEY - The DSAKeyObject is not a valid key object
618 * for this operation.
621 * @par Assumptions:
622 **********************************************************************/
623 N8_Status_t N8_DSASign(N8_DSAKeyObject_t *key_p,
624 N8_Buffer_t *msgHash_p,
625 N8_Buffer_t *rValue_p,
626 N8_Buffer_t *sValue_p,
627 N8_Event_t *event_p)
629 N8_Status_t ret = N8_STATUS_OK;
630 API_Request_t *req_p = NULL;
631 int nBytes;
632 int modulusDigits;
633 N8_Buffer_t *r_p;
634 N8_Buffer_t *s_p;
635 N8_Buffer_t *mh_p;
636 N8_Buffer_t *n_p;
637 N8_Buffer_t *paramBlock_p;
638 uint32_t r_a;
639 uint32_t s_a;
640 uint32_t mh_a;
641 uint32_t n_a;
642 uint32_t paramBlock_a;
643 dsaSignPostDataStruct_t *postData_p = NULL;
648 ret = N8_preamble();
649 CHECK_RETURN(ret);
651 CHECK_OBJECT(key_p, ret);
652 CHECK_OBJECT(msgHash_p, ret);
653 CHECK_OBJECT(rValue_p, ret);
654 CHECK_OBJECT(sValue_p, ret);
655 CHECK_STRUCTURE(key_p->structureID, N8_DSA_STRUCT_ID, ret);
657 /* sign operation can be performed only with private or SKS private key*/
658 switch (key_p->keyType)
660 case N8_PRIVATE:
661 case N8_PRIVATE_SKS:
662 break;
663 default:
664 ret = N8_INVALID_KEY;
665 break;
667 CHECK_RETURN(ret);
669 modulusDigits = BYTES_TO_PKDIGITS(key_p->modulusLength);
671 /* The parameter will be taken solely from the SKS. All other entries
672 * need to be created.
674 nBytes =
675 (NEXT_WORD_SIZE(PK_DSA_R_Byte_Length) + /* R */
676 NEXT_WORD_SIZE(PK_DSA_S_Byte_Length) + /* S */
677 NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length) + /* hash */
678 NEXT_WORD_SIZE(PK_DSA_N_Byte_Length)); /* random number */
679 if (key_p->keyType != N8_PRIVATE_SKS)
682 /* for parameter block */
683 nBytes += NEXT_WORD_SIZE(PK_DSA_Param_Byte_Length(modulusDigits));
686 /* allocate user-space buffer */
687 ret = createPKRequestBuffer(&req_p,
688 key_p->unitID,
689 N8_CB_DSA_SIGN_NUMCMDS(key_p),
690 resultHandlerDSASign, nBytes);
691 CHECK_RETURN(ret);
693 r_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
694 r_a = req_p->qr.physicalAddress + req_p->dataoffset;
695 s_p = r_p + NEXT_WORD_SIZE(PK_DSA_R_Byte_Length);
696 s_a = r_a + NEXT_WORD_SIZE(PK_DSA_R_Byte_Length);
697 mh_p = s_p + NEXT_WORD_SIZE(PK_DSA_S_Byte_Length);
698 mh_a = s_a + NEXT_WORD_SIZE(PK_DSA_S_Byte_Length);
699 n_p = mh_p + NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length);
700 n_a = mh_a + NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length);
702 /* copy the user-space data into our kernel space buffers */
703 memcpy(mh_p + (PK_DSA_E1_Byte_Length - DSA_SIGN_LENGTH),
704 msgHash_p,
705 DSA_SIGN_LENGTH);
707 /* get random number N. Note that the chip will enforce the relationship
708 * N < q, so we don't have to do anything here. */
709 ret = N8_GetRandomBytes(DSA_SIGN_LENGTH, n_p, NULL);
710 CHECK_RETURN(ret);
712 if (key_p->keyType != N8_PRIVATE_SKS)
714 paramBlock_p = n_p
715 + NEXT_WORD_SIZE(PK_DSA_N_Byte_Length);
716 paramBlock_a = n_a
717 + NEXT_WORD_SIZE(PK_DSA_N_Byte_Length);
718 memcpy(paramBlock_p,
719 key_p->paramBlock,
720 PK_DSA_Param_Byte_Length(modulusDigits));
722 else
724 paramBlock_a = 0;
727 /* create a post-processing data object for returning the calculated R and
728 * S results */
729 postData_p = (dsaSignPostDataStruct_t *)&req_p->postProcessBuffer;
730 postData_p->rTo_p = rValue_p;
731 postData_p->sTo_p = sValue_p;
732 postData_p->rFrom_p = r_p;
733 postData_p->sFrom_p = s_p;
735 req_p->postProcessingData_p = (void *) postData_p;
736 ret = cb_dsaSign(req_p, key_p, n_a, paramBlock_a, mh_a,
737 r_a, s_a, req_p->PK_CommandBlock_ptr);
739 CHECK_RETURN(ret);
741 QUEUE_AND_CHECK(event_p, req_p, ret);
742 HANDLE_EVENT(event_p, req_p, ret);
743 } while (FALSE);
744 DBG(("Signed\n"));
747 * Clean up if we arrived from an error condition.
749 if (ret != N8_STATUS_OK)
751 freeRequest(req_p);
754 return ret;
755 } /* N8_DSASign */
758 /**********************************************************************
759 * N8_DSAVerify
760 ***********************************************************************/
761 /** @ingroup dsa
762 * @brief Verifies the digital signature of the message whose SHA-1 hash
763 * value is MessageHash using the Digital Signature Algorithm (DSA) as
764 * defined by the Digital Signature Standard [DSS]
766 * Description:
767 * MessageHash is the 20 byte SHA-1 hash value of the message being
768 * signed (for example, as computed by N8_HashCompleteMessage). The two
769 * DSA defined signature values, r and s, which constitute the signature
770 * to be verified, are specified in RValue and SValue respectively. The
771 * DSA key parameters to use in the verification are taken from DSAKeyObject.
772 * DSAKeyObject must have been previously initialized via an appropriate
773 * call to N8_DSAInitializeKey.
774 * This call first checks that 0 < RValue < q and 0 < SValue < q where q
775 * is as defined by DSAKeyObject. If either of these conditions is false,
776 * verification fails and the Verify return flag is set to False. Otherwise,
777 * the function computes the value v defined by DSA and compares v to RValue.
778 * If they are not equal, verification fails and the Verify return flag is
779 * set to False. If they are equal, verification succeeds and the Verify
780 * return flag is set to True.
781 * The value v is computed as follows:
782 * w = s-1 mod q
783 * u1 = h * w mod q
784 * u2 = r * w mod q
785 * v = (gu1 * yu2 mod p) mod q
786 * where r = the provided signature value RValue, s = the provided signature
787 * value SValue, h = the SHA-1 hash value MessageHash, and y, g, p, and q
788 * are the DSA key parameters defined by DSAKeyObject
791 * Parameters:
792 * @param key_p RO: The previously initialized DSAKeyObject containing the DSA key
793 * materials to be used.
794 * @param msgHash_p RO: The SHA-1 hash of the message being signed; always 20 bytes.
795 * @param rValue_p RO: The DSA r value. This is always 20 bytes in length.
796 * @param sValue_p RO: The DSA s value. This is always 20 bytes in length.
797 * @param verify WO: The return boolean value; True if the signature
798 * verifies correctly and False otherwise
799 * @param event_p RW: On input, if null the call is synchronous and no event
800 * is returned. The operation is complete when the call
801 * returns. If non-null, then the call is asynchronous;
802 * an event is returned that can be used to determine when
803 * the operation completes.
805 * @return
806 * ret - returns N8_STATUS_OK if successful or Error value.
808 * @par Errors:
809 * N8_INVALID_OBJECT - context request object is NULL<BR>
810 * N8_MALLOC_FAILED - memory allocation failed<BR>
811 * N8_INVALID_KEY - The DSAKeyObject is not a valid key object
812 * for this operation.
815 * @par Assumptions:
816 **********************************************************************/
817 N8_Status_t N8_DSAVerify(const N8_DSAKeyObject_t *key_p,
818 const N8_Buffer_t *msgHash_p,
819 const N8_Buffer_t *rValue_p,
820 const N8_Buffer_t *sValue_p,
821 N8_Boolean_t *verify_p,
822 N8_Event_t *event_p)
824 N8_Status_t ret = N8_STATUS_OK;
825 int modulusDigits;
826 API_Request_t *req_p = NULL;
827 int vq_cmp;
828 int nBytes;
829 int skipBytes;
830 int i;
831 int rValueNonZero = FALSE;
832 int sValueNonZero = FALSE;
833 uint32_t r_a;
834 uint32_t s_a;
835 uint32_t mh_a;
836 uint32_t result_a;
837 uint32_t q_a;
838 uint32_t cp_a;
839 uint32_t gR_mod_p_a;
840 uint32_t p_a;
841 uint32_t publicKey_a;
842 N8_Buffer_t *r_p = NULL;
843 N8_Buffer_t *s_p = NULL;
844 N8_Buffer_t *mh_p = NULL;
845 N8_Buffer_t *result_p = NULL;
846 N8_Buffer_t *q_p = NULL;
847 N8_Buffer_t *cp_p = NULL;
848 N8_Buffer_t *gR_mod_p_p = NULL;
849 N8_Buffer_t *p_p = NULL;
850 N8_Buffer_t *publicKey_p = NULL;
851 dsaVerifyPostDataStruct_t *postData_p = NULL;
854 ret = N8_preamble();
855 CHECK_RETURN(ret);
857 CHECK_OBJECT(key_p, ret);
858 CHECK_OBJECT(msgHash_p, ret);
859 CHECK_OBJECT(rValue_p, ret);
860 CHECK_OBJECT(sValue_p, ret);
861 CHECK_OBJECT(verify_p, ret);
862 CHECK_STRUCTURE(key_p->structureID, N8_DSA_STRUCT_ID, ret);
863 if (key_p->keyType != N8_PUBLIC)
865 ret = N8_INVALID_KEY;
866 break;
869 *verify_p = N8_FALSE;
871 /* sizes of S, R, hash are the same */
872 skipBytes = PK_DSA_S_Byte_Length - DSA_SIGN_LENGTH;
874 /* check that r < q and s < q */
875 vq_cmp = memcmp(rValue_p, key_p->q + skipBytes, DSA_SIGN_LENGTH);
876 if (vq_cmp >= 0)
878 ret = N8_INVALID_VALUE;
879 break;
881 vq_cmp = memcmp(sValue_p, key_p->q + skipBytes, DSA_SIGN_LENGTH);
882 if (vq_cmp >= 0)
884 ret = N8_INVALID_VALUE;
885 break;
888 /* check that 0 < r and 0 < s */
890 /* for this test, we simply need to check that r and s are not zero
891 * as they cannot be negative. */
893 for ( i = 0; i < DSA_SIGN_LENGTH; i++ )
895 if (rValue_p[i] != 0x00)
897 rValueNonZero = TRUE;
899 if (sValue_p[i] != 0x00)
901 sValueNonZero = TRUE;
903 if ( (rValueNonZero) && (sValueNonZero) )
905 break;
909 if ( (!rValueNonZero) || (!sValueNonZero) )
911 ret = N8_INVALID_VALUE;
912 break;
915 modulusDigits = BYTES_TO_PKDIGITS(key_p->modulusLength);
917 nBytes =
918 (NEXT_WORD_SIZE(PK_DSA_R_Byte_Length) + /* for R */
919 NEXT_WORD_SIZE(PK_DSA_S_Byte_Length) + /* for S */
920 NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length) + /* for hash */
921 NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length) + /* for recalculated value to verify */
922 NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length) + /* for q */
923 NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length) + /* for cp */
924 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits)) + /* for gR_mod_p */
925 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits)) + /* for public key */
926 NEXT_WORD_SIZE(PK_DSA_P_Byte_Length(modulusDigits)) /* for p */
929 /* allocate user-space buffer */
930 ret = createPKRequestBuffer(&req_p,
931 key_p->unitID,
932 N8_CB_DSA_VERIFY_NUMCMDS,
933 resultHandlerDSAVerify, nBytes);
934 CHECK_RETURN(ret);
936 r_a = req_p->qr.physicalAddress + req_p->dataoffset;
937 r_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
939 s_a = r_a + NEXT_WORD_SIZE(PK_DSA_R_Byte_Length);
940 s_p = r_p + NEXT_WORD_SIZE(PK_DSA_R_Byte_Length);
942 mh_a = s_a + NEXT_WORD_SIZE(PK_DSA_S_Byte_Length);
943 mh_p = s_p + NEXT_WORD_SIZE(PK_DSA_S_Byte_Length);
945 result_a = mh_a + NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length);
946 result_p = mh_p + NEXT_WORD_SIZE(PK_DSA_E1_Byte_Length);
948 q_a = result_a + NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
949 q_p = result_p + NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
951 cp_a = q_a + NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
952 cp_p = q_p + NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
954 gR_mod_p_a = cp_a + NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length);
955 gR_mod_p_p = cp_p + NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length);
957 publicKey_p = gR_mod_p_p +
958 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits));
959 publicKey_a = gR_mod_p_a +
960 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits));
962 p_p = publicKey_p +
963 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits));
964 p_a = publicKey_a +
965 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits));
967 /* Only the last DSA_SIGN_LENGTH are useful for the hash, R and S
968 * values.
970 memcpy(r_p + skipBytes, rValue_p, DSA_SIGN_LENGTH);
971 memcpy(s_p + skipBytes, sValue_p, DSA_SIGN_LENGTH);
972 memcpy(mh_p + skipBytes, msgHash_p, DSA_SIGN_LENGTH);
974 memcpy(q_p, key_p->q, PK_DSA_Q_Byte_Length);
975 memcpy(cp_p, key_p->cp, PK_DSA_CP_Byte_Length);
976 memcpy(gR_mod_p_p, key_p->gR_mod_p, PK_DSA_GR_MOD_P_Byte_Length(modulusDigits));
977 memcpy(publicKey_p, key_p->publicKey, PK_DSA_Y_Byte_Length(modulusDigits));
978 memcpy(p_p, key_p->p, PK_DSA_P_Byte_Length(modulusDigits));
980 /* create a post-processing data object for comparing the computed results
981 * with the expected results and set the verify flag */
982 postData_p = (dsaVerifyPostDataStruct_t *)&req_p->postProcessBuffer;
983 postData_p->computed_p = result_p;
984 postData_p->expected_p = r_p;
985 postData_p->size = PK_DSA_R_Byte_Length;
986 postData_p->verify_p = verify_p;
987 req_p->postProcessingData_p = (void *) postData_p;
989 ret = cb_dsaVerify(req_p,
990 key_p,
991 q_a,
992 cp_a,
993 gR_mod_p_a,
994 p_a,
995 publicKey_a,
996 mh_a,
997 r_a,
998 s_a,
999 result_a,
1000 req_p->PK_CommandBlock_ptr);
1001 CHECK_RETURN(ret);
1003 QUEUE_AND_CHECK(event_p, req_p, ret);
1004 HANDLE_EVENT(event_p, req_p, ret);
1005 DBG(("Verified\n"));
1007 } while (FALSE);
1010 * Clean up if we arrived from an error condition.
1012 if (ret != N8_STATUS_OK)
1014 freeRequest(req_p);
1016 return ret;
1017 } /* N8_DSAVerify */
1019 /**********************************************************************
1020 * N8_DSAFreeKey
1021 ***********************************************************************/
1022 /** @ingroup dsa
1023 * @brief Frees the specified DSAKeyObject and all associated resources
1024 * so that they can be reused.
1026 * Description:
1027 * When an application is finished using a previously initialized
1028 * DSAKeyObject, it should be freed so that any API or system resources
1029 * (including memory) can be freed. After this call returns, DSAKeyObject
1030 * may no longer be used in N8_DSAEncrypt or N8_DSADecrypt calls.
1033 * Parameters:
1034 * @param key_p RO: The previously initialized DSAKeyObject containing the DSA key
1035 * materials to be used.
1037 * @return
1038 * ret - returns N8_STATUS_OK if successful or Error value.
1040 * @par Errors:
1041 * N8_INVALID_KEY - The DSAKeyObject is not a valid key object
1042 * for this operation.
1045 * @par Assumptions:
1046 **********************************************************************/
1047 N8_Status_t N8_DSAFreeKey (N8_DSAKeyObject_t *key_p)
1050 N8_Status_t ret = N8_STATUS_OK;
1054 ret = N8_preamble();
1055 CHECK_RETURN(ret);
1057 CHECK_OBJECT(key_p, ret);
1058 CHECK_STRUCTURE(key_p->structureID, N8_DSA_STRUCT_ID, ret);
1060 if (key_p->kmem_p != NULL)
1062 N8_KFREE(key_p->kmem_p);
1064 key_p->structureID = 0;
1066 }while(FALSE);
1067 return ret;
1068 } /* N8_DSAFreeKey */
1070 * Local functions
1072 /**********************************************************************
1073 * initDSAPublicKey
1074 ***********************************************************************/
1075 /** @ingroup dsa
1076 * @brief Initializes public key.
1079 * @param key_p RW: The caller allocated DSAKeyObject, initialized
1080 * by this call with the appropriate DSA key
1081 * material and pre-computed DSA constants
1082 * depending on the value of the KeyType parameter
1083 * @param material_p RO: The key material to use in initializing DSAKeyObject.
1084 * The valid information that must be supplied
1085 * depends on the value of of KeyType
1088 * @return
1089 * ret - returns N8_STATUS_OK if successful or Error value.
1091 * @par Errors:
1092 * N8_MALLOC_FAILED - memory allocation failed<BR>
1094 * @par Assumptions:
1095 * None.
1096 **********************************************************************/
1097 static N8_Status_t initDSAPublicKey(N8_DSAKeyObject_t *key_p,
1098 N8_DSAKeyMaterial_t *material_p,
1099 N8_Event_t *event_p)
1101 unsigned int modulusDigits;
1102 API_Request_t *req_p = NULL;
1103 N8_Status_t ret = N8_STATUS_OK;
1104 N8_DSAKeyObjectPhysical_t pKey;
1105 unsigned int nBytes;
1106 unsigned int padding;
1108 PK_CMD_BLOCK_t *nextCommandBlock = NULL;
1112 /* first, test the length of the public key/modulus */
1113 ret = checkModulusLength(material_p->p.lengthBytes);
1114 CHECK_RETURN(ret);
1116 /* create the request buffer */
1117 ret = createPKRequestBuffer(&req_p,
1118 key_p->unitID,
1119 N8_CB_COMPUTE_GRMODX_NUMCMDS /* size for GRmodX command block */
1120 + N8_CB_COMPUTE_CX_NUMCMDS, /* size for CX command block */
1121 resultHandlerGeneric, 0);
1122 CHECK_RETURN(ret);
1124 modulusDigits = BYTES_TO_PKDIGITS(material_p->p.lengthBytes);
1125 key_p->modulusLength = material_p->p.lengthBytes;
1126 DBG(("initDSAPublicKey\n"));
1128 /* Allocate parameter block. This block will contain all
1129 * of the parameters for an DSA operation in the correct form for
1130 * direct load into the Big Num Cache.
1132 nBytes =
1133 (NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length) +
1134 NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length) +
1135 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits)) +
1136 NEXT_WORD_SIZE(PK_DSA_P_Byte_Length(modulusDigits)) +
1137 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits)) +
1138 NEXT_WORD_SIZE(PK_DSA_G_Byte_Length(modulusDigits))
1141 key_p->kmem_p = N8_KMALLOC_PK(nBytes);
1142 CHECK_OBJECT(key_p->kmem_p, ret);
1143 memset(key_p->kmem_p->VirtualAddress, 0, nBytes);
1145 key_p->q = (N8_Buffer_t *) key_p->kmem_p->VirtualAddress;
1146 pKey.q = key_p->kmem_p->PhysicalAddress;
1148 key_p->cp = key_p->q +
1149 NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
1150 pKey.cp = pKey.q +
1151 NEXT_WORD_SIZE(PK_DSA_Q_Byte_Length);
1153 key_p->gR_mod_p = key_p->cp +
1154 NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length);
1155 pKey.gR_mod_p = pKey.cp +
1156 NEXT_WORD_SIZE(PK_DSA_CP_Byte_Length);
1158 key_p->p = key_p->gR_mod_p +
1159 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits));
1160 pKey.p = pKey.gR_mod_p +
1161 NEXT_WORD_SIZE(PK_DSA_GR_MOD_P_Byte_Length(modulusDigits));
1163 key_p->publicKey = key_p->p +
1164 NEXT_WORD_SIZE(PK_DSA_P_Byte_Length(modulusDigits));
1165 pKey.publicKey = pKey.p +
1166 NEXT_WORD_SIZE(PK_DSA_P_Byte_Length(modulusDigits));
1168 key_p->g = key_p->publicKey +
1169 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits));
1170 pKey.g = pKey.publicKey +
1171 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits));
1174 * convert the material_p from BIGNUM to binary byte buffer and copy
1175 * to the key's parameter block
1178 /* q */
1179 padding = PK_DSA_Q_Byte_Length - material_p->q.lengthBytes;
1180 memcpy(&key_p->q[padding],
1181 material_p->q.value_p,
1182 material_p->q.lengthBytes);
1183 /* p */
1184 padding = PK_DSA_P_Byte_Length(modulusDigits) -
1185 material_p->p.lengthBytes;
1186 memcpy(&key_p->p[padding],
1187 material_p->p.value_p,
1188 material_p->p.lengthBytes);
1189 /* publicKey */
1190 padding = (PK_DSA_Y_Byte_Length(modulusDigits) -
1191 material_p->publicKey.lengthBytes);
1192 memcpy(&key_p->publicKey[padding],
1193 material_p->publicKey.value_p,
1194 material_p->publicKey.lengthBytes);
1195 /* g */
1196 padding = (PK_DSA_G_Byte_Length(modulusDigits) -
1197 material_p->g.lengthBytes);
1198 memcpy(&key_p->g[padding],
1199 material_p->g.value_p,
1200 material_p->g.lengthBytes);
1201 /* Compute gR mod p and put it into the key object. */
1202 ret = cb_computeGRmodX(req_p, modulusDigits, pKey.g, pKey.p,
1203 pKey.gR_mod_p,
1204 req_p->PK_CommandBlock_ptr,
1205 &nextCommandBlock);
1206 CHECK_RETURN(ret);
1208 ret = cb_computeCX(req_p, pKey.p, pKey.cp,
1209 key_p->modulusLength,
1210 nextCommandBlock,
1211 &nextCommandBlock,
1212 key_p->unitID,
1213 N8_TRUE);
1214 CHECK_RETURN(ret);
1216 QUEUE_AND_CHECK(event_p, req_p, ret);
1217 HANDLE_EVENT(event_p, req_p, ret);
1219 } while(FALSE);
1222 * Clean up if we arrived from an error condition.
1224 if (ret != N8_STATUS_OK)
1226 freeRequest(req_p);
1227 if (key_p->kmem_p != NULL)
1229 N8_KFREE(key_p->kmem_p);
1230 key_p->kmem_p = NULL;
1233 return ret;
1234 } /* initDSAPublicKey */
1236 /**********************************************************************
1237 * initDSAPrivateKey
1238 ***********************************************************************/
1239 /** @ingroup dsa
1240 * @brief Initializes private key.
1243 * @param key_p RW: The caller allocated DSAKeyObject, initialized
1244 * by this call with the appropriate DSA key
1245 * material and pre-computed DSA constants
1246 * depending on the value of the KeyType parameter
1247 * @param material_p RO: The key material to use in initializing DSAKeyObject.
1248 * The valid information that must be supplied
1249 * depends on the value of of KeyType
1252 * @return
1253 * ret - returns N8_STATUS_OK if successful or Error value.
1255 * @par Errors:
1256 * N8_MALLOC_FAILED - memory allocation failed<BR>
1258 * @par Assumptions:
1259 * None.
1260 **********************************************************************/
1261 static N8_Status_t initDSAPrivateKey(N8_DSAKeyObject_t *key_p,
1262 N8_DSAKeyMaterial_t *material_p,
1263 N8_Event_t *event_p)
1265 API_Request_t *req_p = NULL;
1266 int modulusDigits;
1267 N8_Status_t ret = N8_STATUS_OK;
1268 N8_DSAKeyObjectPhysical_t pKey;
1269 unsigned int nBytes;
1270 PK_CMD_BLOCK_t *nextCommandBlock = NULL;
1271 unsigned int padding;
1272 int pq_cmp; /* result of cmp(x,q) */
1274 * key material must contain public key, e, modulus n, and their
1275 * sizes
1277 * Tasks to be performed:
1278 * 1) Put p in the parameter block.
1279 * 2) Put q in the Parameter block.
1280 * 3) Put privateKey in the parameter block.
1281 * 4) Compute gR mod p and put it in the parameter block.
1282 * 5) Compute cp = -(p[0]^-1 mod 2^128 and
1283 * put it in the parameter block.
1287 /* create the request buffer */
1288 ret = createPKRequestBuffer(&req_p,
1289 key_p->unitID,
1290 N8_CB_COMPUTE_GRMODX_NUMCMDS
1291 + N8_CB_COMPUTE_CX_NUMCMDS,
1292 resultHandlerGeneric, 0);
1293 CHECK_RETURN(ret);
1296 pq_cmp = n8_sizedBufferCmp(&material_p->privateKey, &material_p->q);
1298 if (pq_cmp >= 0)
1300 ret = N8_INVALID_KEY;
1301 break;
1303 modulusDigits = BYTES_TO_PKDIGITS(material_p->p.lengthBytes);
1305 key_p->modulusLength = material_p->p.lengthBytes;
1306 DBG(("initDSAPrivateKey\n"));
1307 DBG(("modulus length: %d\n", key_p->modulusLength));
1309 /* Allocate parameter block. This block will contain all
1310 * of the parameters for an DSA operation in the correct form for
1311 * direct load into the Big Num Cache.
1313 nBytes =
1314 (NEXT_WORD_SIZE(PK_DSA_Param_Byte_Length(modulusDigits)) + /* paramBlock */
1315 NEXT_WORD_SIZE(PK_DSA_G_Byte_Length(modulusDigits)) /* generator g */
1318 key_p->kmem_p = N8_KMALLOC_PK(nBytes);
1319 CHECK_OBJECT(key_p->kmem_p, ret);
1320 memset(key_p->kmem_p->VirtualAddress, 0, nBytes);
1322 key_p->paramBlock = (N8_Buffer_t *) key_p->kmem_p->VirtualAddress;
1323 pKey.paramBlock = key_p->kmem_p->PhysicalAddress;
1326 /* Tasks 1-3 */
1329 * set the pointers in the key object to the correct address in the
1330 * parameter block
1332 key_p->p = key_p->paramBlock + PK_DSA_P_Param_Offset;
1333 key_p->gR_mod_p = key_p->paramBlock + PK_DSA_GR_MOD_P_Param_Offset(modulusDigits);
1334 key_p->q = key_p->paramBlock + PK_DSA_Q_Param_Offset(modulusDigits);
1335 key_p->privateKey = key_p->paramBlock + PK_DSA_X_Param_Offset(modulusDigits);
1336 key_p->cp = key_p->paramBlock + PK_DSA_CP_Param_Offset(modulusDigits);
1338 pKey.p = pKey.paramBlock + PK_DSA_P_Param_Offset;
1339 pKey.gR_mod_p = pKey.paramBlock + PK_DSA_GR_MOD_P_Param_Offset(modulusDigits);
1340 pKey.q = pKey.paramBlock + PK_DSA_Q_Param_Offset(modulusDigits);
1341 pKey.privateKey = pKey.paramBlock + PK_DSA_X_Param_Offset(modulusDigits);
1342 pKey.cp = pKey.paramBlock + PK_DSA_CP_Param_Offset(modulusDigits);
1345 * convert the material from BIGNUM to binary byte buffer and copy
1346 * to the key's parameter block
1349 /* q */
1350 padding = PK_DSA_Q_Byte_Length - material_p->q.lengthBytes;
1351 memcpy(&key_p->q[padding],
1352 material_p->q.value_p,
1353 material_p->q.lengthBytes);
1354 /* p */
1355 padding = PK_DSA_P_Byte_Length(modulusDigits) - material_p->p.lengthBytes;
1356 memcpy(&key_p->p[padding],
1357 material_p->p.value_p,
1358 material_p->p.lengthBytes);
1359 /* publicKey */
1360 padding = PK_DSA_X_Byte_Length - material_p->privateKey.lengthBytes;
1361 memcpy(&key_p->privateKey[padding],
1362 material_p->privateKey.value_p,
1363 material_p->privateKey.lengthBytes);
1365 * allocate space for the generator. it is not a part of the parameter
1366 * block
1369 key_p->g = key_p->paramBlock + NEXT_WORD_SIZE(PK_DSA_Param_Byte_Length(modulusDigits));
1370 pKey.g = pKey.paramBlock + NEXT_WORD_SIZE(PK_DSA_Param_Byte_Length(modulusDigits));
1372 /* g */
1373 memcpy(key_p->g, material_p->g.value_p, material_p->g.lengthBytes);
1375 /* Compute gR mod p and put it into the key object. */
1376 /* note that we already have a req_p from the initial create */
1377 ret = cb_computeGRmodX(req_p, modulusDigits, pKey.g, pKey.p,
1378 pKey.gR_mod_p, req_p->PK_CommandBlock_ptr, &nextCommandBlock);
1379 CHECK_RETURN(ret);
1381 ret = cb_computeCX(req_p,
1382 pKey.p,
1383 pKey.cp,
1384 key_p->modulusLength,
1385 nextCommandBlock,
1386 &nextCommandBlock,
1387 key_p->unitID,
1388 N8_TRUE);
1389 CHECK_RETURN(ret);
1391 QUEUE_AND_CHECK(event_p, req_p, ret);
1392 HANDLE_EVENT(event_p, req_p, ret);
1393 } while (FALSE);
1396 * Clean up if we arrived from an error condition.
1398 if (ret != N8_STATUS_OK)
1400 freeRequest(req_p);
1401 if (key_p->kmem_p != NULL)
1403 N8_KFREE(key_p->kmem_p);
1404 key_p->kmem_p = NULL;
1407 /* The hardware detected a problem with the key, overwrite */
1408 /* the generic hardware error with INVALID_KEY. */
1409 ret = N8_INVALID_KEY;
1412 return ret;
1413 } /* initDSAPrivateKey */
1414 /**********************************************************************
1415 * initDSAPrivateSKS
1416 ***********************************************************************/
1417 /** @ingroup dsa
1418 * @brief Initializes private key.
1421 * @param key_p RW: The caller allocated DSAKeyObject, initialized
1422 * by this call with the appropriate DSA key
1423 * material and pre-computed DSA constants
1424 * depending on the value of the KeyType parameter
1425 * @param material_p RO: The key material to use in initializing DSAKeyObject.
1426 * The valid information that must be supplied
1427 * depends on the value of of KeyType
1430 * @return
1431 * ret - returns N8_STATUS_OK if successful or Error value.
1433 * @par Errors:
1434 * N8_MALLOC_FAILED - memory allocation failed<BR>
1436 * @par Assumptions:
1437 * None.
1438 **********************************************************************/
1439 static N8_Status_t initDSAPrivateSKSKey(N8_DSAKeyObject_t *key_p,
1440 N8_DSAKeyMaterial_t *material_p,
1441 N8_Event_t *event_p)
1443 N8_Status_t ret = N8_STATUS_OK;
1444 unsigned int validateSKSkeyLength;
1447 * From the key material we only need the SKSKeyHandle. All information is
1448 * precomputed and placed in the SKS for us.
1453 /* verify the required parameters are not null */
1454 CHECK_OBJECT(key_p, ret);
1455 CHECK_OBJECT(material_p, ret);
1456 /* verify the SKS type is correct */
1457 if (material_p->SKSKeyHandle.key_type != N8_DSA_VERSION_1_KEY)
1459 ret = N8_INCONSISTENT;
1460 break;
1463 validateSKSkeyLength = PKDIGITS_TO_BYTES(material_p->SKSKeyHandle.key_length) % 16;
1464 if (validateSKSkeyLength != 0)
1466 if ((validateSKSkeyLength - 8) !=0)
1468 ret = N8_INVALID_KEY_SIZE;
1469 break;
1472 /* set the modulus length */
1473 /* key_p->modulusLength = material_p->p.lengthBytes; */
1474 key_p->modulusLength = PKDIGITS_TO_BYTES(material_p->SKSKeyHandle.key_length);
1476 DBG(("initDSAPrivateSKS\n"));
1477 DBG(("modulus length: %d\n", key_p->modulusLength));
1479 /* copy the SKS key handle from the key material to the key object */
1480 memcpy(&key_p->SKSKeyHandle,
1481 &material_p->SKSKeyHandle,
1482 sizeof(N8_SKSKeyHandle_t));
1483 /* initializing for SKS requires no further processing. set the event
1484 * status to finished if called asynchronously. */
1485 if (event_p != NULL)
1487 N8_SET_EVENT_FINISHED(event_p, N8_PKP);
1489 } while (FALSE);
1491 return ret;
1492 } /* initDSAPrivateSKS */
1494 /*****************************************************************************
1495 * checkModulusLength
1496 *****************************************************************************/
1497 /** @ingroup dsa
1498 * @brief Check the modulus length to ensure it is proper.
1500 * The modulus length must be between 64 bytes and 512 bytes and must be a
1501 * multiple of 8 bytes.
1503 * @param length RO: The length to be verified
1505 * @par Externals
1506 * None
1508 * @return
1509 * N8_STATUS_OK if the length is valid<br>
1510 * N8_INVALID_KEY_SIZE if the length is invalid<br>
1512 * @par Errors
1513 * None
1515 * @par Assumptions
1516 * None
1517 *****************************************************************************/
1518 static N8_Status_t checkModulusLength(unsigned int length)
1520 N8_Status_t ret = N8_STATUS_OK;
1522 /* The length must be a multiple of 8 bytes between 64 and 512 */
1523 if (length < N8_DSA_PUBLIC_KEY_LENGTH_MIN ||
1524 length > N8_DSA_PUBLIC_KEY_LENGTH_MAX ||
1525 (length % 8 != 0))
1527 ret = N8_INVALID_KEY_SIZE;
1529 return ret;
1530 } /* checkModulusLength */