2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id
[] = "$Id: n8_dsa.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
38 * @brief Public DSA functions.
40 * Implementation of all public DSA functions.
42 *****************************************************************************/
44 /*****************************************************************************
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
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"
131 #include "n8_pk_common.h"
132 #include "n8_enqueue_common.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 */
161 N8_Buffer_t
*rFrom_p
;
162 N8_Buffer_t
*sFrom_p
;
165 } dsaSignPostDataStruct_t
;
167 /* structure for toting around buffers to be compared and result destination in
168 * result handler for N8_DSAVerify */
171 N8_Buffer_t
*computed_p
;
172 N8_Buffer_t
*expected_p
;
174 N8_Boolean_t
*verify_p
;
175 } dsaVerifyPostDataStruct_t
;
177 /**********************************************************************
178 * resultHandlerDSAVerify
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
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
;
211 RESULT_HANDLER_WARNING("n8_dsa::resultHandlerDSAVerify",
215 /* do not free the request. it is freed by the event processor. */
218 /**********************************************************************
219 * resultHandlerDSASign
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
233 **********************************************************************/
234 static void resultHandlerDSASign(API_Request_t
* req_p
)
236 dsaSignPostDataStruct_t
*postData_p
= NULL
;
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
244 skipLength
= PK_DSA_R_Byte_Length
- DSA_SIGN_LENGTH
;
245 memcpy(postData_p
->rTo_p
,
246 postData_p
->rFrom_p
+ skipLength
,
248 skipLength
= PK_DSA_S_Byte_Length
- DSA_SIGN_LENGTH
;
249 memcpy(postData_p
->sTo_p
,
250 postData_p
->sFrom_p
+ skipLength
,
255 RESULT_HANDLER_WARNING("n8_dsa::resultHandlerDSASign",
259 /* do not free the request. it is freed by the event processor. */
260 } /* resultHandlerDSASign */
262 /*****************************************************************************
263 * n8_testValueInUpperRange
264 *****************************************************************************/
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
274 * @param p RO: Pointer to the sized buffer to be checked.
280 * Status of comparison: N8_STATUS_OK or N8_INVALID_KEY.
287 *****************************************************************************/
288 static N8_Status_t
n8_testValueInUpperRange(const N8_SizedBuffer_t
*p
)
290 N8_Status_t ret
= N8_INVALID_KEY
;
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. */
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. */
314 } /* n8_testValueInUpperRange */
315 /*****************************************************************************
317 *****************************************************************************/
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
331 * Status of validation.
334 * N8_STATUS_OK, N8_INVALID_KEY, or N8_INVALID_KEY_SIZE
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
;
347 /* ensure we have all of the correct parameters for the key type */
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
);
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
);
366 ret
= N8_INVALID_ENUM
;
372 * check the modulus, p
375 /* first check the length */
376 ret
= checkModulusLength(material_p
->p
.lengthBytes
);
379 /* for a p of length L bits, p > 2**(L-1) */
380 ret
= n8_testValueInUpperRange(&material_p
->p
);
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
;
394 value_cmp
= n8_sizedBufferCmp(&material_p
->g
, &material_p
->p
);
397 ret
= N8_INVALID_KEY
;
402 * check q, a prime divisor of (p - 1)
406 if (material_p
->q
.lengthBytes
!= N8_DSA_PRIVATE_KEY_LENGTH
)
408 ret
= N8_INVALID_KEY_SIZE
;
411 /* for a q of length L bits, q > 2**(L-1) */
412 ret
= n8_testValueInUpperRange(&material_p
->q
);
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
;
423 /* private key < q */
424 value_cmp
= n8_sizedBufferCmp(&material_p
->privateKey
, &material_p
->q
);
427 ret
= N8_INVALID_KEY
;
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
;
440 value_cmp
= n8_sizedBufferCmp(&material_p
->publicKey
, &material_p
->p
);
443 ret
= N8_INVALID_KEY
;
452 } /* n8_DSAValidateKey */
454 /**********************************************************************
455 * N8_DSAInitializeKey
456 ***********************************************************************/
458 * @brief Initializes the specified DSAKeyObject so that it can be used
459 * in DSA sign / verify operations.
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.
483 * ret - returns N8_STATUS_OK if successful or Error value.
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.
494 **********************************************************************/
495 N8_Status_t
N8_DSAInitializeKey(N8_DSAKeyObject_t
*key_p
,
497 N8_DSAKeyMaterial_t
*material_p
,
500 N8_Status_t ret
= N8_STATUS_OK
;
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 */
517 key_p
->unitID
= material_p
->unitID
;
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
));
530 ret
= N8_INVALID_ENUM
;
535 * Verify parameters if this is not SKS call
537 if (type
!= N8_PRIVATE_SKS
)
539 ret
= n8_DSAValidateKey(material_p
, type
);
543 key_p
->keyType
= type
;
547 ret
= initDSAPublicKey(key_p
, material_p
, event_p
);
551 ret
= initDSAPrivateKey(key_p
, material_p
, event_p
);
554 ret
= initDSAPrivateSKSKey(key_p
, material_p
, event_p
);
557 ret
= N8_INVALID_ENUM
;
564 if (ret
== N8_STATUS_OK
)
566 /* Set the structure ID */
567 key_p
->structureID
= N8_DSA_STRUCT_ID
;
570 } /* N8_DSAInitializeKey */
572 /**********************************************************************
574 ***********************************************************************/
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].
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.
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;
601 * @param rValue_p WO: The DSA r value. This is always 20 bytes
603 * @param sValue_p WO: The DSA s value. This is always 20 bytes
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.
613 * ret - returns N8_STATUS_OK if successful or Error value.
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.
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
,
629 N8_Status_t ret
= N8_STATUS_OK
;
630 API_Request_t
*req_p
= NULL
;
637 N8_Buffer_t
*paramBlock_p
;
642 uint32_t paramBlock_a
;
643 dsaSignPostDataStruct_t
*postData_p
= NULL
;
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
)
664 ret
= N8_INVALID_KEY
;
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.
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
,
689 N8_CB_DSA_SIGN_NUMCMDS(key_p
),
690 resultHandlerDSASign
, nBytes
);
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
),
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
);
712 if (key_p
->keyType
!= N8_PRIVATE_SKS
)
715 + NEXT_WORD_SIZE(PK_DSA_N_Byte_Length
);
717 + NEXT_WORD_SIZE(PK_DSA_N_Byte_Length
);
720 PK_DSA_Param_Byte_Length(modulusDigits
));
727 /* create a post-processing data object for returning the calculated R and
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
);
741 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
742 HANDLE_EVENT(event_p
, req_p
, ret
);
747 * Clean up if we arrived from an error condition.
749 if (ret
!= N8_STATUS_OK
)
758 /**********************************************************************
760 ***********************************************************************/
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]
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:
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
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.
806 * ret - returns N8_STATUS_OK if successful or Error value.
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.
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
,
824 N8_Status_t ret
= N8_STATUS_OK
;
826 API_Request_t
*req_p
= NULL
;
831 int rValueNonZero
= FALSE
;
832 int sValueNonZero
= FALSE
;
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
;
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
;
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
);
878 ret
= N8_INVALID_VALUE
;
881 vq_cmp
= memcmp(sValue_p
, key_p
->q
+ skipBytes
, DSA_SIGN_LENGTH
);
884 ret
= N8_INVALID_VALUE
;
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
) )
909 if ( (!rValueNonZero
) || (!sValueNonZero
) )
911 ret
= N8_INVALID_VALUE
;
915 modulusDigits
= BYTES_TO_PKDIGITS(key_p
->modulusLength
);
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
,
932 N8_CB_DSA_VERIFY_NUMCMDS
,
933 resultHandlerDSAVerify
, nBytes
);
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
));
963 NEXT_WORD_SIZE(PK_DSA_Y_Byte_Length(modulusDigits
));
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
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
,
1000 req_p
->PK_CommandBlock_ptr
);
1003 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1004 HANDLE_EVENT(event_p
, req_p
, ret
);
1005 DBG(("Verified\n"));
1010 * Clean up if we arrived from an error condition.
1012 if (ret
!= N8_STATUS_OK
)
1017 } /* N8_DSAVerify */
1019 /**********************************************************************
1021 ***********************************************************************/
1023 * @brief Frees the specified DSAKeyObject and all associated resources
1024 * so that they can be reused.
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.
1034 * @param key_p RO: The previously initialized DSAKeyObject containing the DSA key
1035 * materials to be used.
1038 * ret - returns N8_STATUS_OK if successful or Error value.
1041 * N8_INVALID_KEY - The DSAKeyObject is not a valid key object
1042 * for this operation.
1046 **********************************************************************/
1047 N8_Status_t
N8_DSAFreeKey (N8_DSAKeyObject_t
*key_p
)
1050 N8_Status_t ret
= N8_STATUS_OK
;
1054 ret
= N8_preamble();
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;
1068 } /* N8_DSAFreeKey */
1072 /**********************************************************************
1074 ***********************************************************************/
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
1089 * ret - returns N8_STATUS_OK if successful or Error value.
1092 * N8_MALLOC_FAILED - memory allocation failed<BR>
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
);
1116 /* create the request buffer */
1117 ret
= createPKRequestBuffer(&req_p
,
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);
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.
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
);
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
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
);
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
);
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
);
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
,
1204 req_p
->PK_CommandBlock_ptr
,
1208 ret
= cb_computeCX(req_p
, pKey
.p
, pKey
.cp
,
1209 key_p
->modulusLength
,
1216 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1217 HANDLE_EVENT(event_p
, req_p
, ret
);
1222 * Clean up if we arrived from an error condition.
1224 if (ret
!= N8_STATUS_OK
)
1227 if (key_p
->kmem_p
!= NULL
)
1229 N8_KFREE(key_p
->kmem_p
);
1230 key_p
->kmem_p
= NULL
;
1234 } /* initDSAPublicKey */
1236 /**********************************************************************
1238 ***********************************************************************/
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
1253 * ret - returns N8_STATUS_OK if successful or Error value.
1256 * N8_MALLOC_FAILED - memory allocation failed<BR>
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
;
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
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
,
1290 N8_CB_COMPUTE_GRMODX_NUMCMDS
1291 + N8_CB_COMPUTE_CX_NUMCMDS
,
1292 resultHandlerGeneric
, 0);
1296 pq_cmp
= n8_sizedBufferCmp(&material_p
->privateKey
, &material_p
->q
);
1300 ret
= N8_INVALID_KEY
;
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.
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
;
1329 * set the pointers in the key object to the correct address in the
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
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
);
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
);
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
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
));
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
);
1381 ret
= cb_computeCX(req_p
,
1384 key_p
->modulusLength
,
1391 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1392 HANDLE_EVENT(event_p
, req_p
, ret
);
1396 * Clean up if we arrived from an error condition.
1398 if (ret
!= N8_STATUS_OK
)
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
;
1413 } /* initDSAPrivateKey */
1414 /**********************************************************************
1416 ***********************************************************************/
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
1431 * ret - returns N8_STATUS_OK if successful or Error value.
1434 * N8_MALLOC_FAILED - memory allocation failed<BR>
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
;
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
;
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
);
1492 } /* initDSAPrivateSKS */
1494 /*****************************************************************************
1495 * checkModulusLength
1496 *****************************************************************************/
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
1509 * N8_STATUS_OK if the length is valid<br>
1510 * N8_INVALID_KEY_SIZE if the length is invalid<br>
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
||
1527 ret
= N8_INVALID_KEY_SIZE
;
1530 } /* checkModulusLength */