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_rsa.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
38 * @brief Public RSA functions.
40 * Implementation of all public RSA functions.
42 *****************************************************************************/
44 /*****************************************************************************
46 * DON'T FORGET TO MAKE YOUR CHANGES OPTIMAL!
47 * 12/17/03 bac Added N8_RSAPublicDecrypt (as written by JPW).
48 * 04/07/03 bac Removed redundant CHECK_RETURN.
49 * 09/10/02 brr Set command complete bit on last command block.
50 * 05/20/02 brr Free the request for all error conditions.
51 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
52 * 05/01/02 brr Memset data segment after return from N8_KMALLOC.
53 * 04/08/02 bac Corrected a padding bug that produced incorrect results
54 * for decryption with keys with leading zeroes. (BUG 671).
55 * 04/05/02 bac Removed overly restrictive input tests for initialization.
57 * 04/01/02 brr Validate modulus, p, and q pointers before
58 * use in N8_RSAInitializeKey.
59 * 03/27/02 hml N8_RSAInitializeKey now calls n8_validateUnit (BUG 653)
60 * and N8_RSAFreeKey returns N8_INVALID_OBJECT with a NULL
62 * 03/26/02 hml Changed N8_INVALID_UNIT to N8_UNINITIALIZED unit.
63 * 03/25/02 spm Removed test for N8_PRIVATE_SKS key type in N8_RSAEncrypt
64 * (public key routine). Fixed SKS Round Robin unit binding
65 * so that a branch is not necessary when this feature is
67 * 03/26/02 brr Allocate the data buffer as part of the API request.
68 * 03/18/02 bac Added code to support SKS Round Robin.
69 * 03/07/02 brr Fix display functions, Don't use genericResultHandler when
71 * 02/28/02 brr Do not include any QMgr include files.
72 * 02/25/02 brr Removed last references to QMgr.
73 * 02/22/02 spm Converted printk's to DBG's.
74 * 02/20/02 brr Removed references to the queue structure.
75 * 01/17/02 hml Fix so previous delayed binding fix works with OpenSSL.
76 * 01/15/02 bac Re-arranged the late chip binding code to avoid problems in
78 * 01/14/02 hml RSA fixes to delay chip binding fro encrypt/decrypt.
79 * 12/11/01 mel Fixed bug #380: Added extra checks for RSAInitializeKey
80 * Fixed bug #412: Set SKS key length from SKS key material
81 * 12/05/01 mel Fixed bug #405: Changed check for private key length to
82 * modulus length check.
83 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
84 * 11/27/01 bac For public key initialization, get the private key length from
85 * the modulus length in the key material.
86 * 11/26/01 bac Fixed bug #338 by creating n8_RSAValidateKey to do key bounds
88 * 11/16/01 mel Fixed bug #333 : OpenSSL test rsa_test fails some padding
90 * 11/11/01 bac Removed BIGNUMS from key material.
91 * 11/09/01 mel Fixed bug #304 : N8_RSAInitializeKey does not check key
93 * 11/08/01 mel Added unit ID parameter to commend block calls (bug #289).
94 * 11/06/01 dkm Corrected error returns for invalid key values.
95 * 11/06/01 hml Added some error checking and the structure verification.
96 * 11/02/01 bac Cleaned up printf/scanf formats to silence compiler warnings.
97 * 10/31/01 bac Modified interface to initPrivateSKSKey.
98 * 10/19/01 bac Added support for RSA types N8_PRIVATE and N8_PRIVATE_SKS.
99 * 10/11/01 bac More correctons for BUG #180.
100 * 10/08/01 bac Changes for the case where len(p) != len(q) (BUG #180).
101 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
102 * 10/01/01 hml Added multi-chip functionality.
103 * 09/05/01 bac Globally changed to use 'req_p' for consistency.
104 * 08/24/01 bac Changed all interfaces to the cb commands to pre-allocate the
105 * command buffer space.
106 * 08/21/01 bac Fixes to allow the use of odd key lengths (Bug #174).
107 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
108 * 07/30/01 bac Use queue_p in all macro length calculations.
109 * 07/20/01 bac Changed calls to create__RequestBuffer to pass the chip id.
110 * 07/02/01 mel Fixed comments.
111 * 06/28/01 bac Changed use of cb_rsaEncrypt and cb_rsaDecrypt to take
112 * physical addresses not N8_MemoryHandle_t-s, convert final
113 * routines to use single KMALLOC, fixed final methods that
114 * weren't async-ready.
115 * 06/25/01 bac More mem mgt changes and lots of cleanup.
116 * 06/19/01 bac Correct use of kernel memory.
117 * 05/30/01 bac Doxygenation plus standardization.
118 * 05/30/01 bac Changes to support message lengths that are not multiples of
119 * 16 bytes for bug #16. Removed reference to data in
120 * QUEUE_AND_CHECK that is previously freed in the result
122 * 05/21/01 bac Converted to use N8_ContextHandle_t and N8_Packet_t
123 * with integrated cipher and hash packet.
124 * 05/21/01 bac Return unimplemented function for initialization with SKS
126 * 05/18/01 bac Changed to use memory mgmt macros. Removed unnecessary global
128 * 04/30/01 bac Changed BN display functions to N8_display*.
129 * 04/26/01 bac Changed interface to createRequestBuffer to remove
130 * num_commands as it was not used and confusing.
131 * 04/26/01 bac Added 'static' to resultHandler to avoid name clashes.
132 * 04/10/01 bac Extensive re-write to bring up to standards. Fixed
133 * 04/24/01 bac Extensive re-write to bring up to standards. Fixed
134 * various memory leaks.
135 * 04/05/01 bac Added error checking to all cb_* calls.
136 * 04/05/01 bac Changed all key length info to be in bytes, not digits.
137 * 04/04/01 bac Added ordering of p and q so that p < q and added
139 * 03/01/01 bac Original version.
140 ****************************************************************************/
141 /** @defgroup n8_rsa RSA Functions.
144 #include "n8_common.h"
145 #include "n8_pub_errors.h"
147 #include "n8_pk_common.h"
148 #include "n8_enqueue_common.h"
150 #include "n8_API_Initialize.h"
152 #include "n8_cb_rsa.h"
155 #define DBG_PARAM(__M, __P, __L) \
157 N8_print_rsa_parameters((__P), (__L));
159 #define DBG_PARAM(M,P,L)
163 * local predeclarations
165 static N8_Status_t
initPublicKey(N8_RSAKeyObject_t
*key_p
,
166 N8_RSAKeyMaterial_t
*material_p
,
167 N8_Event_t
*event_p
);
168 static N8_Status_t
initPrivateKey(N8_RSAKeyObject_t
*key_p
,
169 N8_RSAKeyMaterial_t
*material_p
,
170 N8_Event_t
*event_p
);
171 static N8_Status_t
initPrivateKeyCRT(N8_RSAKeyObject_t
*key_p
,
172 N8_RSAKeyMaterial_t
*material_p
,
173 N8_Event_t
*event_p
);
174 static N8_Status_t
initPrivateSKSKey(N8_RSAKeyObject_t
*key_p
,
175 N8_RSAKeyMaterial_t
*material_p
,
176 N8_Event_t
*event_p
);
178 /*****************************************************************************
180 *****************************************************************************/
182 * @brief Minimal bounds checking for RSA keys.
184 * Based upon the key type, test the key lengths for basic sanity.
186 * @param material_p RO: Pointer to RSA key material
187 * @param type RO: Key type
193 * Status of comparison. N8_STATUS_OK if fine.
196 * N8_INVALID_KEY_SIZE if invalid.<br>
197 * N8_INVALID_ENUM if type is invalid.
201 *****************************************************************************/
202 static N8_Status_t
n8_RSAValidateKey(const N8_RSAKeyMaterial_t
*material_p
,
203 const N8_KeyType_t type
)
205 N8_Status_t ret
= N8_STATUS_OK
;
206 /* perform bounds checking based upon type. */
210 /* ensure the required elements of the key material are present. for
211 * PUBLIC: publicKey and n */
212 CHECK_OBJECT(material_p
->publicKey
.value_p
, ret
);
213 CHECK_OBJECT(material_p
->n
.value_p
, ret
);
215 /* for a public key, bounds check modulus length and public key
216 * length from material. */
217 if ((material_p
->n
.lengthBytes
< N8_RSA_KEY_LENGTH_MIN
) ||
218 (material_p
->n
.lengthBytes
> N8_RSA_KEY_LENGTH_MAX
) ||
219 (material_p
->publicKey
.lengthBytes
< N8_RSA_KEY_LENGTH_MIN
) ||
220 (material_p
->publicKey
.lengthBytes
> N8_RSA_KEY_LENGTH_MAX
))
222 ret
= N8_INVALID_KEY_SIZE
;
226 /* ensure the required elements of the key material are present. for
227 * PRIVATE CRT: p and q in addition to those for PRIVATE */
228 CHECK_OBJECT(material_p
->p
.value_p
, ret
);
229 CHECK_OBJECT(material_p
->q
.value_p
, ret
);
230 /* NOTE case statement fall through */
232 /* ensure the required elements of the key material are present. for
233 * PRIVATE: privateKey and n */
234 CHECK_OBJECT(material_p
->privateKey
.value_p
, ret
);
235 CHECK_OBJECT(material_p
->n
.value_p
, ret
);
236 /* for private, non-SKS, bounds check the private key length
238 if ((material_p
->privateKey
.lengthBytes
< N8_RSA_KEY_LENGTH_MIN
) ||
239 (material_p
->privateKey
.lengthBytes
> N8_RSA_KEY_LENGTH_MAX
))
241 ret
= N8_INVALID_KEY_SIZE
;
245 /* for SKS, bounds check the key length in the SKS Key Handle
247 if (material_p
->SKSKeyHandle
.key_length
< N8_RSA_SKS_KEY_LENGTH_DIGITS_MIN
||
248 material_p
->SKSKeyHandle
.key_length
> N8_RSA_SKS_KEY_LENGTH_DIGITS_MAX
)
250 ret
= N8_INVALID_KEY_SIZE
;
254 ret
= N8_INVALID_ENUM
;
259 } /* n8_RSAValidateKey */
262 /*****************************************************************************
263 * N8_print_rsa_parameters
264 *****************************************************************************/
266 * @brief Print RSA parameters.
269 * @param p_block RO: pointer to the parameter's block to be
271 * @param key_p RO: pointer to key object
272 * @param key_length_bytes RO: key length
277 *****************************************************************************/
278 void N8_print_rsa_parameters(unsigned char *p_block
,
279 N8_RSAKeyObject_t
*key_p
)
283 uint32_t key_length_bytes
;
285 unsigned int pbLength
;
286 int paramByteLength
= PK_RSA_Param_Byte_Length(key_p
);
288 if (p_block
== NULL
|| key_p
== NULL
)
293 key_length_bytes
= key_p
->privateKeyLength
;
294 key_length
= BYTES_TO_PKDIGITS(key_length_bytes
);
295 N8_PRINT("\nRSA decrypt/sign parameters\n");
296 N8_PRINT("key length=%d (0x%08x)\n", key_length
, key_length
);
298 ptr
= p_block
+ PK_RSA_P_Param_Byte_Offset(key_p
);
299 n8_displayBuffer(ptr
,
300 PK_RSA_P_Byte_Length(key_p
),
303 ptr
= p_block
+ PK_RSA_Q_Param_Byte_Offset(key_p
);
304 n8_displayBuffer(ptr
, PK_RSA_Q_Byte_Length(key_p
), "q");
307 ptr
= p_block
+ PK_RSA_DP_Param_Byte_Offset(key_p
);
308 n8_displayBuffer(ptr
, PK_RSA_DP_Byte_Length(key_p
), "dp");
311 ptr
= p_block
+ PK_RSA_DQ_Param_Byte_Offset(key_p
);
312 n8_displayBuffer(ptr
, PK_RSA_DQ_Byte_Length(key_p
), "dq");
315 ptr
= p_block
+ PK_RSA_R_MOD_P_Param_Byte_Offset(key_p
);
316 n8_displayBuffer(ptr
, PK_RSA_R_MOD_P_Byte_Length(key_p
), "R mod p");
319 ptr
= p_block
+ PK_RSA_R_MOD_Q_Param_Byte_Offset(key_p
);
320 n8_displayBuffer(ptr
, PK_RSA_R_MOD_Q_Byte_Length(key_p
), "R mod q");
323 ptr
= p_block
+ PK_RSA_N_Param_Byte_Offset(key_p
);
324 n8_displayBuffer(ptr
, PK_RSA_N_Byte_Length(key_p
), "N");
327 ptr
= p_block
+ PK_RSA_U_Param_Byte_Offset(key_p
);
328 n8_displayBuffer(ptr
, PK_RSA_U_Byte_Length(key_p
), "u");
331 ptr
= p_block
+ PK_RSA_CP_Param_Byte_Offset(key_p
);
332 n8_displayBuffer(ptr
, PK_RSA_CP_Byte_Length
, "cp");
335 ptr
= p_block
+ PK_RSA_CQ_Param_Byte_Offset(key_p
);
336 n8_displayBuffer(ptr
, PK_RSA_CQ_Byte_Length
, "cq");
338 N8_PRINT("---------\n");
340 pbLength
= BYTES_TO_PKDIGITS(paramByteLength
);
341 for (j
= 0; j
< pbLength
; j
++)
343 for (i
= 0; i
< PK_Bytes_Per_BigNum_Digit
; i
++)
345 N8_PRINT("%02x", (*ptr
++) & 0xff);
350 N8_PRINT("---------\n");
351 } /* N8_print_rsa_parameters */
355 /*****************************************************************************
356 * N8_RSAInitializeKey
357 *****************************************************************************/
359 * @brief Initialize an RSA key object.
361 * Initializes the specified key object so that it can be used in
362 * subsequent RSA encrypt/decrypt operation. The key type specifies
363 * the manner in which the key object is to be interpreted.
365 * @param key_p RW: pointer to the key to be initialized
366 * @param type RO: key type
367 * @param material_p RO: pointer to key material with initialization
374 * Status. Error code if encountered.
377 * N8_UNIMPLEMENTED_FUNCTION - type of N8_PRIVATE or N8_PRIVATE_SKS used.<br>
378 * N8_INVALID_KEY - type passed is not recognized.<br>
383 *****************************************************************************/
384 N8_Status_t
N8_RSAInitializeKey(N8_RSAKeyObject_t
*key_p
,
386 N8_RSAKeyMaterial_t
*material_p
,
389 N8_Status_t ret
= N8_STATUS_OK
;
390 N8_Unit_t unit
= N8_UNINITIALIZED_UNIT
;
391 N8_Boolean_t unitValid
;
397 CHECK_OBJECT(key_p
, ret
);
398 CHECK_OBJECT(material_p
, ret
);
400 /* bounds test key lengths. */
401 ret
= n8_RSAValidateKey(material_p
, type
);
404 /* clear the contents of the key. */
405 memset(key_p
, 0, sizeof(N8_RSAKeyObject_t
));
407 /* The unit specifier is found in a different place depending on
408 the requested type */
414 unit
= material_p
->unitID
;
418 unit
= material_p
->SKSKeyHandle
.unitID
;
419 /* Copy all of the SKS data into the key */
420 memcpy((void *) &(key_p
->SKSKeyHandle
),
421 (const void *) &(material_p
->SKSKeyHandle
),
422 sizeof(N8_SKSKeyHandle_t
));
426 /* value has already been checked. */
430 /* Make sure the unit is valid */
431 unitValid
= n8_validateUnit(unit
);
434 ret
= N8_INVALID_UNIT
;
437 key_p
->unitID
= unit
;
439 key_p
->keyType
= type
;
444 * key material must contain public key e, modulus n, and their
447 CHECK_OBJECT(material_p
->publicKey
.value_p
, ret
);
448 ret
= initPublicKey(key_p
, material_p
, event_p
);
453 * key material must contain private key d, modulus n, and their
456 CHECK_OBJECT(material_p
->privateKey
.value_p
, ret
);
457 CHECK_OBJECT(material_p
->n
.value_p
, ret
);
458 ret
= initPrivateKey(key_p
, material_p
, event_p
);
461 /* used to perform private encryption with Chinese Remainder
462 * Theorem. key material must contain private key d, modulus n,
463 * and their sizes. also, p and q, factors of n, (i.e. n = p*q)
464 * shall be included. (the relation is assumed but not
467 CHECK_OBJECT(material_p
->privateKey
.value_p
, ret
);
468 CHECK_OBJECT(material_p
->n
.value_p
, ret
);
469 CHECK_OBJECT(material_p
->p
.value_p
, ret
);
470 CHECK_OBJECT(material_p
->q
.value_p
, ret
);
471 ret
= initPrivateKeyCRT(key_p
, material_p
, event_p
);
475 * used to perform private encryption but gets the key material
476 * from the Secure Key Storage
478 ret
= initPrivateSKSKey(key_p
, material_p
, event_p
);
481 ret
= N8_INVALID_KEY
;
487 if (ret
== N8_STATUS_OK
)
489 /* Set the structure ID */
490 key_p
->structureID
= N8_RSA_STRUCT_ID
;
492 /* Special code for RSA key object late-binding to an execution unit */
493 if (type
== N8_PUBLIC
|| type
== N8_PRIVATE_CRT
|| type
== N8_PRIVATE
)
495 /* Reset the unit to the unit from the material. The RSA Decrypt
496 will have to validate the unit again. This allows all of the
497 decrypt operations to be performed on different units. */
498 key_p
->unitID
= material_p
->unitID
;
503 } /* N8_RSAInitializeKey */
505 /*****************************************************************************
507 *****************************************************************************/
509 * @brief Perform an RSA encrypt on the message. This is also used to
510 * perform the verify function for authentication.
513 * @param key_p RW: pointer to the key to be initialized
514 * @param msgIn RO: incoming message to be encrypted
515 * @param msgLength RO: incoming message length
516 * @param msgOut RW: resulting encrypted message
517 * @param event_p RW: On input, if null the call is synchronous
518 * and no event is returned. The operation
519 * is complete when the call returns. If
520 * non-null, then the call is asynchronous;
521 * an event is returned that can be used to
522 * determine when the operation completes.
527 * Status. Error code if encountered.
530 * N8_MALLOC_FAILED - memory allocation failed<BR>
531 * N8_INVALID_OBJECT - object is NULL<BR>
535 *****************************************************************************/
536 N8_Status_t
N8_RSAEncrypt(N8_RSAKeyObject_t
*key_p
,
542 N8_Status_t ret
= N8_STATUS_OK
;
545 N8_Buffer_t
*kmsgIn_p
= NULL
;
546 N8_Buffer_t
*kmsgOut_p
= NULL
;
549 API_Request_t
*req_p
= NULL
;
556 CHECK_OBJECT(key_p
, ret
);
557 CHECK_OBJECT(msgIn
, ret
);
558 CHECK_OBJECT(msgOut
, ret
);
559 CHECK_STRUCTURE(key_p
->structureID
, N8_RSA_STRUCT_ID
, ret
);
561 if (key_p
== NULL
|| key_p
->keyType
!= N8_PUBLIC
)
563 ret
= N8_INVALID_KEY
;
567 if (msgLength
> key_p
->privateKeyLength
)
569 ret
= N8_INVALID_INPUT_SIZE
;
573 nBytes
= NEXT_WORD_SIZE(key_p
->privateKeyLength
) * 2;
575 /* allocate user-space buffer */
576 ret
= createPKRequestBuffer(&req_p
,
578 N8_CB_RSA_ENCRYPT_NUMCMDS
,
579 resultHandlerGeneric
, nBytes
);
582 kmsgIn_p
= (N8_Buffer_t
*) ((int)req_p
+ req_p
->dataoffset
);
583 kmsgIn_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
584 kmsgOut_p
= kmsgIn_p
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
585 kmsgOut_a
= kmsgIn_a
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
587 p
= kmsgIn_p
+ key_p
->privateKeyLength
- msgLength
;
588 memcpy(p
, msgIn
, msgLength
);
590 req_p
->copyBackTo_p
= msgOut
;
591 req_p
->copyBackFrom_p
= kmsgOut_p
+ key_p
->privateKeyLength
- msgLength
;
592 req_p
->copyBackSize
= msgLength
;
593 ret
= cb_rsaEncrypt(req_p
, key_p
, kmsgIn_a
, kmsgOut_a
,
594 req_p
->PK_CommandBlock_ptr
,
598 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
599 HANDLE_EVENT(event_p
, req_p
, ret
);
604 * Clean up if we arrived from an error condition.
606 if (ret
!= N8_STATUS_OK
)
612 } /* N8_RSAEncrypt */
615 /*****************************************************************************
617 *****************************************************************************/
619 * @brief Perform an RSA decrypt on the message. This is also used to
620 * perform the sign function for authentication.
623 * @param key RW: pointer to the key to be initialized
624 * @param msgIn RO: incoming message to be encrypted
625 * @param msgLength RO: incoming message length
626 * @param msgOut RW: resulting encrypted message
627 * @param event_p RW: On input, if null the call is synchronous
628 * and no event is returned. The operation
629 * is complete when the call returns. If
630 * non-null, then the call is asynchronous;
631 * an event is returned that can be used to
632 * determine when the operation completes.
637 * Status. Error code if encountered.
640 * N8_MALLOC_FAILED - memory allocation failed<BR>
641 * N8_INVALID_OBJECT - object is NULL<BR>
645 *****************************************************************************/
646 N8_Status_t
N8_RSADecrypt(N8_RSAKeyObject_t
*key_p
,
652 N8_Status_t ret
= N8_STATUS_OK
;
653 N8_Buffer_t
*kmsgIn_p
= NULL
;
654 N8_Buffer_t
*kmsgOut_p
= NULL
;
657 API_Request_t
*req_p
= NULL
;
660 N8_Unit_t unit
= N8_UNINITIALIZED_UNIT
;
666 CHECK_OBJECT(key_p
, ret
);
667 CHECK_OBJECT(msgIn
, ret
);
668 CHECK_OBJECT(msgOut
, ret
);
669 CHECK_STRUCTURE(key_p
->structureID
, N8_RSA_STRUCT_ID
, ret
);
672 (key_p
->keyType
!= N8_PRIVATE
&&
673 key_p
->keyType
!= N8_PRIVATE_CRT
&&
674 key_p
->keyType
!= N8_PRIVATE_SKS
))
676 ret
= N8_INVALID_KEY
;
680 #if N8_SKS_ROUND_ROBIN
681 if (key_p
->keyType
== N8_PRIVATE_SKS
)
683 unit
= key_p
->SKSKeyHandle
.unitID
;
687 unit
= key_p
->unitID
;
690 unit
= key_p
->unitID
;
693 if (msgLength
> key_p
->privateKeyLength
)
695 ret
= N8_INVALID_INPUT_SIZE
;
699 nBytes
= NEXT_WORD_SIZE(key_p
->privateKeyLength
) * 2;
701 /* allocate user-space buffer */
702 ret
= createPKRequestBuffer(&req_p
,
704 N8_CB_RSA_DECRYPT_NUMCMDS(key_p
),
705 resultHandlerGeneric
, nBytes
);
708 kmsgIn_p
= (N8_Buffer_t
*) ((int)req_p
+ req_p
->dataoffset
);
709 kmsgIn_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
710 kmsgOut_p
= (N8_Buffer_t
*) kmsgIn_p
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
711 kmsgOut_a
= kmsgIn_a
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
713 p
= kmsgIn_p
+ key_p
->privateKeyLength
- msgLength
;
714 memcpy(p
, msgIn
, msgLength
);
717 req_p
->copyBackTo_p
= msgOut
;
718 req_p
->copyBackFrom_p
= kmsgOut_p
+ key_p
->privateKeyLength
- msgLength
;
719 req_p
->copyBackSize
= msgLength
;
721 ret
= cb_rsaDecrypt(req_p
, key_p
, kmsgIn_a
, kmsgOut_a
,
722 req_p
->PK_CommandBlock_ptr
, unit
);
725 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
726 HANDLE_EVENT(event_p
, req_p
, ret
);
730 * Clean up if we arrived from an error condition.
732 if (ret
!= N8_STATUS_OK
)
738 } /* N8_RSADecrypt */
740 /*****************************************************************************
741 * N8_RSAPublicDecrypt
742 *****************************************************************************/
744 * @brief Perform an RSA public decrypt on the message. This is also used to
745 * perform the verify function for authentication.
748 * @param key_p RW: pointer to the key to be initialized
749 * @param msgIn RO: incoming message to be encrypted
750 * @param msgLength RO: incoming message length
751 * @param msgOut RW: resulting encrypted message
752 * @param event_p RW: On input, if null the call is synchronous
753 * and no event is returned. The operation
754 * is complete when the call returns. If
755 * non-null, then the call is asynchronous;
756 * an event is returned that can be used to
757 * determine when the operation completes.
762 * Status. Error code if encountered.
765 * N8_MALLOC_FAILED - memory allocation failed<BR>
766 * N8_INVALID_OBJECT - object is NULL<BR>
770 *****************************************************************************/
771 N8_Status_t
N8_RSAPublicDecrypt(N8_RSAKeyObject_t
*key_p
,
772 const N8_RSAKeyMaterial_t
*material_p
,
773 const N8_Buffer_t
*msgIn
,
778 N8_Status_t ret
= N8_STATUS_OK
;
781 N8_Buffer_t
*kmsgIn_p
= NULL
;
782 N8_Buffer_t
*kmsgOut_p
= NULL
;
785 API_Request_t
*req_p
= NULL
;
790 unsigned int pkDigitSize
= SIMON_BITS_PER_DIGIT
/ 8;
791 unsigned int padding
;
799 CHECK_OBJECT(key_p
, ret
);
800 CHECK_OBJECT(msgIn
, ret
);
801 CHECK_OBJECT(msgOut
, ret
);
803 /* From initPublicKey */
805 /* bounds test key lengths. */
806 ret
= n8_RSAValidateKey(material_p
, N8_PUBLIC
);
807 /* clear the contents of the key. */
808 memset(key_p
, 0, sizeof(N8_RSAKeyObject_t
));
810 unit
= material_p
->unitID
;
811 /* Make sure the unit is valid */
812 unitValid
= n8_validateUnit(unit
);
815 ret
= N8_INVALID_UNIT
;
818 key_p
->unitID
= unit
;
820 padding
= (pkDigitSize
-
821 (material_p
->publicKey
.lengthBytes
% pkDigitSize
));
822 key_p
->publicKeyLength
=
823 material_p
->publicKey
.lengthBytes
+ padding
;
824 /* the private key length is a bit of a misnomer. it is also the modulus
825 * length. for a public key we don't have the privateKey information
826 * filled in, so we get the key length from the modulus. */
827 key_p
->privateKeyLength
= material_p
->n
.lengthBytes
;
828 key_p
->publicKeyDigits
= BYTES_TO_PKDIGITS(key_p
->publicKeyLength
);
829 key_p
->privateKeyDigits
= BYTES_TO_PKDIGITS(key_p
->privateKeyLength
);
830 /* unintuitively, reassign the private key length to ensure it is rounded
831 * up if necessary. */
832 key_p
->privateKeyLength
= PKDIGITS_TO_BYTES(key_p
->privateKeyDigits
);
834 DBG(("initPublicKey\n"));
835 DBG(("public key length: %d\n", key_p
->publicKeyLength
));
836 DBG(("private key length: %d\n", key_p
->privateKeyLength
));
838 /* pre-allocate all of the kernel memory we need at once */
839 nBytes
= (NEXT_WORD_SIZE(key_p
->publicKeyLength
) + /* public key */
840 NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
)) + /* modulus */
841 2 * NEXT_WORD_SIZE(key_p
->privateKeyLength
)); /* msg in and out */
843 /* allocate PK Command block buffer in Kernel Space */
844 ret
= createPKRequestBuffer(&req_p
,
846 N8_CB_RSA_PUBLICDECRYPT_NUMCMDS
,
847 resultHandlerGeneric
, nBytes
);
850 /* there is no persistent kernel memory in the key object for this
852 kmsgIn_p
= (N8_Buffer_t
*) ((int)req_p
+ req_p
->dataoffset
);
853 kmsgIn_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
854 kmsgOut_p
= kmsgIn_p
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
855 kmsgOut_a
= kmsgIn_a
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
857 vAddr
= kmsgOut_p
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
858 pAddr
= kmsgOut_a
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
860 memset(kmsgIn_p
, 0, nBytes
);
865 * allocate space for the key. it is not a part of the parameter
869 /* copy the public key into the key object.
870 * this must be zero-filled to the left in order to fill an integral
871 * number of Big Number Cache digits.
873 * padding = digit_size - (pub_key_len % digit_size)
875 memcpy(&vAddr
[padding
],
876 material_p
->publicKey
.value_p
,
877 material_p
->publicKey
.lengthBytes
);
879 pAddr
+= NEXT_WORD_SIZE(key_p
->publicKeyLength
);
880 vAddr
+= NEXT_WORD_SIZE(key_p
->publicKeyLength
);
885 * allocate space for the modulus. it is not a part of the parameter
886 * block for a private key object.
889 padding
= (PK_RSA_N_Byte_Length(key_p
) - material_p
->n
.lengthBytes
);
890 memcpy(&vAddr
[padding
], material_p
->n
.value_p
, material_p
->n
.lengthBytes
);
891 pAddr
+= NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
));
892 vAddr
+= NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
));
894 /* End From initPublicKey */
896 /* Magic tag to note key has been initialized */
897 key_p
->structureID
= N8_RSA_STRUCT_ID
;
899 p
= kmsgIn_p
+ key_p
->privateKeyLength
- msgLength
;
900 memcpy(p
, msgIn
, msgLength
);
902 req_p
->copyBackTo_p
= msgOut
;
903 req_p
->copyBackFrom_p
= kmsgOut_p
+ key_p
->privateKeyLength
- msgLength
;
904 req_p
->copyBackSize
= msgLength
;
905 ret
= cb_rsaPublicDecrypt(req_p
,
906 key_p
->n
, /* modulus */
907 key_p
->privateKeyLength
, /* modulus length */
910 key_p
->key
, /* public key */
911 key_p
->publicKeyLength
, /* public key length */
912 req_p
->PK_CommandBlock_ptr
,
915 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
916 HANDLE_EVENT(event_p
, req_p
, ret
);
918 DBG(("N8_RSAPublic_Decrypt\n"));
921 * Clean up if we arrived from an error condition.
923 if (ret
!= N8_STATUS_OK
)
929 } /* N8_RSAPublic_Decrypt */
931 /**********************************************************************
933 ***********************************************************************/
935 * @brief Frees the specified RSAKeyObject_p and all associated resources
936 * so that they can be reused.
939 * When an application is finished using a previously initialized
940 * RSAKeyObject_p, it should be freed so that any API or system resources
941 * (including memory) can be freed. After this call returns, RSAKeyObject_p
942 * may no longer be used in N8_RSAEncrypt or N8_RSADecrypt calls.
946 * @param RSAKeyObject_p RO: The previously initialized RSAKeyObject containing the RSA key
947 * materials to be used.
950 * ret - returns N8_STATUS_OK if successful or Error value.
953 * N8_INVALID_KEY - The DSAKeyObject is not a valid key object
954 * for this operation.
958 **********************************************************************/
959 N8_Status_t
N8_RSAFreeKey (N8_RSAKeyObject_t
*key_p
)
962 N8_Status_t ret
= N8_STATUS_OK
;
971 ret
= N8_INVALID_OBJECT
;
974 CHECK_STRUCTURE(key_p
->structureID
, N8_RSA_STRUCT_ID
, ret
);
975 if (key_p
->kmem_p
!= NULL
)
977 N8_KFREE(key_p
->kmem_p
);
979 key_p
->structureID
= 0;
983 } /* N8_RSAFreeKey */
988 /*****************************************************************************
990 *****************************************************************************/
992 * @brief Initialize an RSA public key object.
995 * @param key RW: pointer to the key to be initialized
996 * @param material RO: pointer to key material with initialization
998 * @param paramBlock_pp WO: pointer parameter block pointer
1004 * Status. Error code if encountered.
1007 * N8_MALLOC_FAILED - memory allocation failed<BR>
1011 *****************************************************************************/
1012 static N8_Status_t
initPublicKey(N8_RSAKeyObject_t
*key_p
,
1013 N8_RSAKeyMaterial_t
*material_p
,
1014 N8_Event_t
*event_p
)
1018 * Tasks to be performed:
1019 * 1) Put public key, e, into the key object
1020 * 2) Put modulus, n, into the key object
1021 * 3) Compute cn and put into the key object
1022 * 4) Compute R mod n and put into the key object
1025 API_Request_t
*req_p
= NULL
;
1026 unsigned int nBytes
;
1027 unsigned int pkDigitSize
= SIMON_BITS_PER_DIGIT
/ 8;
1028 unsigned int padding
;
1029 unsigned long pAddr
;
1031 N8_Status_t ret
= N8_STATUS_OK
;
1032 PK_CMD_BLOCK_t
*nextCommandBlock
= NULL
;
1036 padding
= (pkDigitSize
-
1037 (material_p
->publicKey
.lengthBytes
% pkDigitSize
));
1038 key_p
->publicKeyLength
=
1039 material_p
->publicKey
.lengthBytes
+ padding
;
1040 /* the private key length is a bit of a misnomer. it is also the modulus
1041 * length. for a public key we don't have the privateKey information
1042 * filled in, so we get the key length from the modulus. */
1043 key_p
->privateKeyLength
= material_p
->n
.lengthBytes
;
1044 key_p
->publicKeyDigits
= BYTES_TO_PKDIGITS(key_p
->publicKeyLength
);
1045 key_p
->privateKeyDigits
= BYTES_TO_PKDIGITS(key_p
->privateKeyLength
);
1046 /* unintuitively, reassign the private key length to ensure it is rounded
1047 * up if necessary. */
1048 key_p
->privateKeyLength
= PKDIGITS_TO_BYTES(key_p
->privateKeyDigits
);
1050 DBG(("initPublicKey\n"));
1051 DBG(("public key length: %d\n", key_p
->publicKeyLength
));
1052 DBG(("private key length: %d\n", key_p
->privateKeyLength
));
1054 /* allocate user-space buffer */
1055 ret
= createPKRequestBuffer(&req_p
,
1057 N8_CB_COMPUTE_CX_NUMCMDS
+
1058 N8_CB_COMPUTE_RMODX_NUMCMDS
,
1062 /* pre-allocate all of the kernel memory we need at once */
1063 nBytes
= (NEXT_WORD_SIZE(key_p
->publicKeyLength
) +
1064 NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
)) +
1065 NEXT_WORD_SIZE(PK_RSA_CN_Byte_Length
) +
1066 NEXT_WORD_SIZE(PK_RSA_R_MOD_N_Byte_Length(key_p
)));
1068 /* the kernel memory allocated here is freed in the call to
1069 * N8_RSAFreeKey. DO NOT add it to the free list here. */
1070 key_p
->kmem_p
= N8_KMALLOC_PK(nBytes
);
1071 CHECK_OBJECT(key_p
->kmem_p
, ret
);
1073 pAddr
= key_p
->kmem_p
->PhysicalAddress
;
1074 vAddr
= (N8_Buffer_t
*) key_p
->kmem_p
->VirtualAddress
;
1075 memset(vAddr
, 0, nBytes
);
1079 * allocate space for the key. it is not a part of the parameter
1084 /* copy the public key into the key object.
1085 * this must be zero-filled to the left in order to fill an integral
1086 * number of Big Number Cache digits.
1088 * padding = digit_size - (pub_key_len % digit_size)
1090 memset(vAddr
, 0x0, padding
);
1091 memcpy(&vAddr
[padding
],
1092 material_p
->publicKey
.value_p
,
1093 material_p
->publicKey
.lengthBytes
);
1095 pAddr
+= NEXT_WORD_SIZE(key_p
->publicKeyLength
);
1096 vAddr
+= NEXT_WORD_SIZE(key_p
->publicKeyLength
);
1101 * allocate space for the modulus. it is not a part of the parameter
1102 * block for a private key object.
1105 padding
= (PK_RSA_N_Byte_Length(key_p
) - material_p
->n
.lengthBytes
);
1106 memcpy(&vAddr
[padding
], material_p
->n
.value_p
, material_p
->n
.lengthBytes
);
1107 pAddr
+= NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
));
1108 vAddr
+= NEXT_WORD_SIZE(PK_RSA_N_Byte_Length(key_p
));
1110 /* Task 3: Compute cn = -(n[0]^-1 mod 2^128) mod 2^128 and */
1111 /* put it in the key object. */
1114 ret
= cb_computeCX(req_p
, key_p
->n
, key_p
->cn
, PK_RSA_N_Byte_Length(key_p
),
1115 req_p
->PK_CommandBlock_ptr
, &nextCommandBlock
,
1116 key_p
->unitID
, N8_FALSE
);
1117 pAddr
+= NEXT_WORD_SIZE(PK_RSA_CN_Byte_Length
);
1118 vAddr
+= NEXT_WORD_SIZE(PK_RSA_CN_Byte_Length
);
1120 /* Task 4: Compute R mod n and put it in the key object. */
1121 key_p
->R_mod_n
= pAddr
;
1122 ret
= cb_computeRmodX(req_p
, key_p
->n
, key_p
->R_mod_n
,
1123 PK_RSA_N_Byte_Length(key_p
),
1124 nextCommandBlock
, &nextCommandBlock
, N8_TRUE
);
1126 QUEUE_AND_CHECK(event_p
, req_p
, ret
)
1127 HANDLE_EVENT(event_p
, req_p
, ret
);
1131 * Clean up if we arrived from an error condition.
1133 if (ret
!= N8_STATUS_OK
)
1139 } /* initPublicKey */
1141 static N8_Status_t
initPrivateKey(N8_RSAKeyObject_t
*key_p
,
1142 N8_RSAKeyMaterial_t
*material_p
,
1143 N8_Event_t
*event_p
)
1145 N8_Status_t ret
= N8_STATUS_OK
;
1146 unsigned int nBytes
;
1148 N8_Buffer_t
*privateKey_p
;
1149 unsigned int padding
;
1152 /* to initialize a key object for private non-CRT use only requires the
1153 * copying of the values for the key, the modulus and their sizes. No
1154 * precomputations are required.
1156 /* the length of the private key must be less than the length of the
1157 * modulus but we want to pad it out so they appear to be the same. thus,
1158 * figure out the length of the number of digits required for the modulus
1159 * and use that for the private key.
1161 key_p
->privateKeyDigits
= BYTES_TO_PKDIGITS(material_p
->n
.lengthBytes
);
1162 key_p
->publicKeyDigits
= BYTES_TO_PKDIGITS(material_p
->publicKey
.lengthBytes
);
1164 /* use the macros to recompute the lengths to use the rounding. a mere
1165 * assignment from material_p lengths is not sufficient. */
1166 key_p
->privateKeyLength
= PKDIGITS_TO_BYTES(key_p
->privateKeyDigits
);
1167 key_p
->publicKeyLength
= PKDIGITS_TO_BYTES(key_p
->publicKeyDigits
);
1169 DBG(("initPrivateKey\n"));
1170 DBG(("public key length: %d\n", key_p
->publicKeyLength
));
1171 DBG(("private key length: %d\n", key_p
->privateKeyLength
));
1173 /* allocate kernel memory space for n and the private key. */
1174 nBytes
= 2 * NEXT_WORD_SIZE(key_p
->privateKeyLength
);
1176 /* the kernel memory allocated here is freed in the call to
1177 * N8_RSAFreeKey. DO NOT add it to the free list here. */
1178 key_p
->kmem_p
= N8_KMALLOC_PK(nBytes
);
1179 CHECK_OBJECT(key_p
->kmem_p
, ret
);
1181 mod_p
= (N8_Buffer_t
*) key_p
->kmem_p
->VirtualAddress
;
1182 memset(mod_p
, 0, nBytes
);
1183 privateKey_p
= mod_p
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
1184 key_p
->n
= key_p
->kmem_p
->PhysicalAddress
;
1185 key_p
->key
= key_p
->n
+ NEXT_WORD_SIZE(key_p
->privateKeyLength
);
1186 /* copy the value of the modulus to the key structure */
1187 padding
= (PK_RSA_N_Byte_Length(key_p
) - material_p
->n
.lengthBytes
);
1188 memcpy(&mod_p
[padding
],
1189 material_p
->n
.value_p
,
1190 material_p
->n
.lengthBytes
);
1191 padding
= (PK_RSA_FULL_LENGTH(key_p
->privateKeyDigits
) - material_p
->privateKey
.lengthBytes
);
1192 memcpy(&privateKey_p
[padding
],
1193 material_p
->privateKey
.value_p
,
1194 material_p
->privateKey
.lengthBytes
);
1195 /* initializing for non-CRT private key requires no further processing.
1196 * set the event status to finished if called asynchronously. */
1197 if (event_p
!= NULL
)
1199 N8_SET_EVENT_FINISHED(event_p
, N8_PKP
);
1205 } /* initPrivateKey */
1206 /*****************************************************************************
1208 *****************************************************************************/
1210 * @brief Initialize an RSA private key object for Chinese Remainder Theorem.
1212 * Use of the CRT requires several values to be pre-computed and requires the
1213 * knowledge of the values p and q. Performing RSA Decrypt with CRT is much
1214 * faster than using the standard exponentiation method.
1217 * @param key RW: pointer to the key to be initialized
1218 * @param material RO: pointer to key material with initialization
1225 * Status. Error code if encountered.
1228 * N8_MALLOC_FAILED - memory allocation failed<BR>
1232 *****************************************************************************/
1233 static N8_Status_t
initPrivateKeyCRT(N8_RSAKeyObject_t
*key_p
,
1234 N8_RSAKeyMaterial_t
*material_p
,
1235 N8_Event_t
*event_p
)
1237 API_Request_t
*req_p
= NULL
;
1238 N8_Status_t ret
= N8_STATUS_OK
;
1239 int pq_cmp
; /* result of cmp(p,q) */
1240 unsigned int nBytes
;
1241 unsigned int padding
;
1242 unsigned long pAddr
;
1244 N8_RSAKeyObjectVirtual_t vKey
;
1245 PK_CMD_BLOCK_t
*nextCommandBlock_p
= NULL
;
1246 N8_Buffer_t
*pb
= NULL
;
1248 * key material must contain public key e, modulus n, and their
1251 * Tasks to be performed:
1252 * 0) Allocate the parameter block where the data will live
1253 * 0.5) p = min(p',q')
1254 * 0.6) q = max(p',q')
1255 * 1) Put p into the key object.
1256 * 2) Put q into the key object.
1257 * 2a)Put the private key into the key object
1258 * 3) Put N into the key object.
1259 * 4) Compute u and put into the key object.
1260 * 5) Compute dp = d mod ((p-1) mod p) and put it in
1262 * 6) Compute dq = d mod ((q-1) mod q) and put it in
1264 * 7) Compute cp = -(p[0]^-1 mod 2^128) mod 2^128 and
1265 * put it into the key object.
1266 * 8) Compute cq = -(q[0]^-1 mod 2^128) mod 2^128 and
1267 * put it into the key object.
1268 * 9) Compute R mod p and put it into the key object.
1269 * 10) Compute R mod q and put it into the key object.
1274 key_p
->privateKeyDigits
=
1275 BYTES_TO_PKDIGITS(material_p
->privateKey
.lengthBytes
);
1276 key_p
->publicKeyDigits
=
1277 BYTES_TO_PKDIGITS(material_p
->publicKey
.lengthBytes
);
1279 /* use the macros to recompute the lengths to use the rounding. a mere
1280 * assignment from material_p lengths is not sufficient. */
1281 key_p
->publicKeyLength
= PKDIGITS_TO_BYTES(key_p
->publicKeyDigits
);
1282 key_p
->privateKeyLength
= PKDIGITS_TO_BYTES(key_p
->privateKeyDigits
);
1284 DBG(("initPrivateKeyCRT\n"));
1285 DBG(("public key length: %d\n", key_p
->publicKeyLength
));
1286 DBG(("private key length: %d\n", key_p
->privateKeyLength
));
1288 /* allocate user-space buffer */
1289 ret
= createPKRequestBuffer(&req_p
,
1291 N8_CB_COMPUTE_U_NUMCMDS
+
1292 N8_CB_COMPUTE_DX_NUMCMDS
+
1293 N8_CB_COMPUTE_DX_NUMCMDS
+
1294 N8_CB_COMPUTE_CX_NUMCMDS
+
1295 N8_CB_COMPUTE_CX_NUMCMDS
+
1296 N8_CB_COMPUTE_RMODX_NUMCMDS
+
1297 N8_CB_COMPUTE_RMODX_NUMCMDS
,
1301 /* if p < q, use them in order */
1302 pq_cmp
= n8_sizedBufferCmp(&material_p
->p
, &material_p
->q
);
1305 /* p < q. use them in order. */
1306 key_p
->pLength
= material_p
->p
.lengthBytes
;
1307 key_p
->qLength
= material_p
->q
.lengthBytes
;
1309 else if (pq_cmp
> 0)
1311 /* p > q. swap them. */
1312 key_p
->pLength
= material_p
->q
.lengthBytes
; /* swapped! */
1313 key_p
->qLength
= material_p
->p
.lengthBytes
; /* swapped! */
1317 /* p == q. error! */
1318 ret
= N8_INVALID_PARAMETER
;
1321 key_p
->pDigits
= BYTES_TO_PKDIGITS(key_p
->pLength
);
1322 key_p
->qDigits
= BYTES_TO_PKDIGITS(key_p
->qLength
);
1324 /* calculate the left padding for p and q */
1325 key_p
->pPad
= PKDIGITS_TO_BYTES(key_p
->pDigits
) - key_p
->pLength
;
1326 key_p
->qPad
= PKDIGITS_TO_BYTES(key_p
->qDigits
) - key_p
->qLength
;
1328 padding
= PK_RSA_N_Byte_Length(key_p
) - material_p
->n
.lengthBytes
;
1330 /* Task 0: Allocate parameter block. This block will contain all
1331 * of the parameters for an RSA operation in the correct form for
1332 * direct load into the Big Num Cache.
1334 nBytes
= (NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
)) + /* parameter block */
1335 NEXT_WORD_SIZE(PKDIGITS_TO_BYTES(key_p
->privateKeyDigits
))); /* private Key */
1337 /* the kernel memory allocated here is freed in the call to
1338 * N8_RSAFreeKey. DO NOT add it to the free list here. */
1339 key_p
->kmem_p
= N8_KMALLOC_PK(nBytes
);
1340 CHECK_OBJECT(key_p
->kmem_p
, ret
);
1342 pAddr
= key_p
->kmem_p
->PhysicalAddress
;
1343 vAddr
= (N8_Buffer_t
*) key_p
->kmem_p
->VirtualAddress
;
1344 memset(vAddr
, 0, nBytes
);
1345 key_p
->paramBlock
= pAddr
;
1346 vKey
.paramBlock
= (N8_Buffer_t
*) vAddr
;
1348 pAddr
+= NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
));
1349 vAddr
+= NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
));
1353 * set the pointers in the key object to the correct address in the
1357 key_p
->p
= key_p
->paramBlock
+ PK_RSA_P_Param_Byte_Offset(key_p
);
1358 key_p
->q
= key_p
->paramBlock
+ PK_RSA_Q_Param_Byte_Offset(key_p
);
1359 key_p
->n
= key_p
->paramBlock
+ PK_RSA_N_Param_Byte_Offset(key_p
);
1360 key_p
->u
= key_p
->paramBlock
+ PK_RSA_U_Param_Byte_Offset(key_p
);
1361 key_p
->dp
= key_p
->paramBlock
+ PK_RSA_DP_Param_Byte_Offset(key_p
);
1362 key_p
->dq
= key_p
->paramBlock
+ PK_RSA_DQ_Param_Byte_Offset(key_p
);
1363 key_p
->R_mod_p
= key_p
->paramBlock
+ PK_RSA_R_MOD_P_Param_Byte_Offset(key_p
);
1364 key_p
->R_mod_q
= key_p
->paramBlock
+ PK_RSA_R_MOD_Q_Param_Byte_Offset(key_p
);
1365 key_p
->cp
= key_p
->paramBlock
+ PK_RSA_CP_Param_Byte_Offset(key_p
);
1366 key_p
->cq
= key_p
->paramBlock
+ PK_RSA_CQ_Param_Byte_Offset(key_p
);
1368 pb
= vKey
.paramBlock
;
1369 vKey
.p
= pb
+ PK_RSA_P_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1370 vKey
.q
= pb
+ PK_RSA_Q_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1371 vKey
.n
= pb
+ PK_RSA_N_Param_Byte_Offset(key_p
) + padding
;
1372 vKey
.u
= pb
+ PK_RSA_U_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1373 vKey
.dp
= pb
+ PK_RSA_DP_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1374 vKey
.dq
= pb
+ PK_RSA_DQ_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1375 vKey
.R_mod_p
= pb
+ PK_RSA_R_MOD_P_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1376 vKey
.R_mod_q
= pb
+ PK_RSA_R_MOD_Q_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1377 vKey
.cp
= pb
+ PK_RSA_CP_Param_Byte_Offset(key_p
);
1378 vKey
.cq
= pb
+ PK_RSA_CQ_Param_Byte_Offset(key_p
);
1381 * convert the material from BIGNUM to binary byte buffer and copy
1382 * to the key's parameter block
1385 /* if p < q, use them in order */
1388 /* p < q. use them in order. */
1389 memcpy(vKey
.p
, material_p
->p
.value_p
, key_p
->pLength
);
1390 memcpy(vKey
.q
, material_p
->q
.value_p
, key_p
->qLength
);
1392 else if (pq_cmp
> 0)
1394 /* p > q. swap them. */
1395 DBG(("p > q: swapping\n"));
1396 memcpy(vKey
.p
, material_p
->q
.value_p
, key_p
->pLength
); /* swapped */
1397 memcpy(vKey
.q
, material_p
->p
.value_p
, key_p
->qLength
); /* swapped */
1401 /* p == q. error! */
1402 ret
= N8_INVALID_PARAMETER
;
1405 memcpy(vKey
.n
, material_p
->n
.value_p
, material_p
->n
.lengthBytes
);
1407 DBG_PARAM("input only\n", vKey
.paramBlock
, key_p
);
1409 * allocate space for the key. it is not a part of the parameter
1413 /* we need to round up to an integral number of digits */
1414 /* recompute amount of padding for the private key */
1415 padding
= PK_RSA_N_Byte_Length(key_p
) - material_p
->privateKey
.lengthBytes
;
1417 memcpy(vAddr
+ padding
, material_p
->privateKey
.value_p
,
1418 material_p
->privateKey
.lengthBytes
);
1420 /* Task 4: compute u = (p^-1) mod q */
1421 ret
= cb_computeU(req_p
, key_p
->p
, key_p
->q
, key_p
->u
,
1422 PK_RSA_P_Byte_Length(key_p
),
1423 PK_RSA_Q_Byte_Length(key_p
),
1424 req_p
->PK_CommandBlock_ptr
, &nextCommandBlock_p
);
1427 /* Task 5: compute dp = mod((p-1) mod p) */
1428 ret
= cb_computeDX(req_p
, key_p
->p
, key_p
->key
, key_p
->dp
,
1429 key_p
->privateKeyLength
,
1430 PK_RSA_P_Byte_Length(key_p
),
1431 nextCommandBlock_p
, &nextCommandBlock_p
,
1435 /* Task 6: compute dq = mod((q-1) mod q) */
1436 ret
= cb_computeDX(req_p
, key_p
->q
, key_p
->key
, key_p
->dq
,
1437 key_p
->privateKeyLength
,
1438 PK_RSA_Q_Byte_Length(key_p
),
1439 nextCommandBlock_p
, &nextCommandBlock_p
,
1443 /* Task 7: Compute cp = -(p[0]^-1 mod 2^128) mod 2^128 and */
1444 /* put it into the key object. */
1445 ret
= cb_computeCX(req_p
, key_p
->p
, key_p
->cp
,
1446 PK_RSA_P_Byte_Length(key_p
),
1447 nextCommandBlock_p
, &nextCommandBlock_p
,
1452 /* Task 8: Compute cq = -(q[0]^-1 mod 2^128) mod 2^128 and */
1453 /* put it into the key object. */
1454 ret
= cb_computeCX(req_p
, key_p
->q
, key_p
->cq
,
1455 PK_RSA_Q_Byte_Length(key_p
),
1456 nextCommandBlock_p
, &nextCommandBlock_p
,
1461 /* Task 9: Compute R mod p and put it into the key object. */
1462 ret
= cb_computeRmodX(req_p
, key_p
->p
, key_p
->R_mod_p
,
1463 PK_RSA_P_Byte_Length(key_p
),
1464 nextCommandBlock_p
, &nextCommandBlock_p
, FALSE
);
1467 /* Task 10: Compute R mod q and put it into the key object. */
1468 ret
= cb_computeRmodX(req_p
, key_p
->q
, key_p
->R_mod_q
,
1469 PK_RSA_Q_Byte_Length(key_p
),
1470 nextCommandBlock_p
, &nextCommandBlock_p
, TRUE
);
1472 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1473 HANDLE_EVENT(event_p
, req_p
, ret
);
1475 if ((N8_Buffer_t
*) vKey
.paramBlock
!= NULL
)
1478 n8_displayBuffer(material_p
->privateKey
.value_p
,
1479 key_p
->privateKeyLength
, "d -- private key");
1481 DBG_PARAM("Computed Parameter Block:\n", vKey
.paramBlock
, key_p
);
1486 * Clean up if we arrived from an error condition.
1488 if (ret
!= N8_STATUS_OK
)
1494 } /* initPrivateKeyCRT */
1497 /* Open Crypto key setup for MOD EXP CRT (RSA MOD EXP) */
1498 /* dP, dQ, and qinv are supplied.,
1499 * but the public and private keys are not...
1501 * The N8 claims to require N!!! (the public key, = pq).
1502 * That throws a bit of a wrench in the works...
1504 static N8_Status_t
initPrivateKeyCRT_OC(N8_RSAKeyObject_t
*key_p
,
1505 N8_RSAKeyMaterial_t
*material_p
,
1506 N8_SizedBuffer_t
*dp_p
;
1507 N8_SizedBuffer_t
*dq_p
;
1508 N8_Event_t
*event_p
)
1510 API_Request_t
*req_p
= NULL
;
1511 N8_Status_t ret
= N8_STATUS_OK
;
1512 int pq_cmp
; /* result of cmp(p,q) */
1513 unsigned int nBytes
;
1514 unsigned int padding
;
1515 unsigned long pAddr
;
1517 N8_RSAKeyObjectVirtual_t vKey
;
1518 PK_CMD_BLOCK_t
*nextCommandBlock_p
= NULL
;
1519 N8_Buffer_t
*pb
= NULL
;
1521 * key material must contain public key e, modulus n, and their
1524 * Tasks to be performed:
1525 * 0) Allocate the parameter block where the data will live
1526 * 0.5) p = min(p',q')
1527 * 0.6) q = max(p',q')
1528 * 1) Put p into the key object.
1529 * 2) Put q into the key object.
1530 * 3) Compute u and put into the key object.
1531 * 4) Put dp (=d mod ((p-1) mod p)) in the key object.
1532 * 5) Put dq (= d mod ((q-1) mod q)) the key object.
1533 * 6) Compute cp = -(p[0]^-1 mod 2^128) mod 2^128 and
1534 * put it into the key object.
1535 * 7) Compute cq = -(q[0]^-1 mod 2^128) mod 2^128 and
1536 * put it into the key object.
1537 * 8) Compute R mod p and put it into the key object.
1538 * 9) Compute R mod q and put it into the key object.
1543 /* allocate user-space buffer */
1544 ret
= createPKRequestBuffer(&req_p
,
1546 N8_CB_COMPUTE_U_NUMCMDS
+
1547 N8_CB_COMPUTE_CX_NUMCMDS
+
1548 N8_CB_COMPUTE_CX_NUMCMDS
+
1549 N8_CB_COMPUTE_RMODX_NUMCMDS
+
1550 N8_CB_COMPUTE_RMODX_NUMCMDS
,
1554 /* if p < q, use them in order */
1555 pq_cmp
= n8_sizedBufferCmp(&material_p
->p
, &material_p
->q
);
1558 /* p < q. use them in order. */
1559 key_p
->pLength
= material_p
->p
.lengthBytes
;
1560 key_p
->qLength
= material_p
->q
.lengthBytes
;
1562 else if (pq_cmp
> 0)
1564 /* p > q. swap them. */
1565 key_p
->pLength
= material_p
->q
.lengthBytes
; /* swapped! */
1566 key_p
->qLength
= material_p
->p
.lengthBytes
; /* swapped! */
1570 /* p == q. error! */
1571 ret
= N8_INVALID_PARAMETER
;
1574 key_p
->pDigits
= BYTES_TO_PKDIGITS(key_p
->pLength
);
1575 key_p
->qDigits
= BYTES_TO_PKDIGITS(key_p
->qLength
);
1577 /* calculate the left padding for p and q */
1578 key_p
->pPad
= PKDIGITS_TO_BYTES(key_p
->pDigits
) - key_p
->pLength
;
1579 key_p
->qPad
= PKDIGITS_TO_BYTES(key_p
->qDigits
) - key_p
->qLength
;
1581 padding
= PK_RSA_N_Byte_Length(key_p
) - material_p
->n
.lengthBytes
;
1583 /* Task 0: Allocate parameter block. This block will contain all
1584 * of the parameters for an RSA operation in the correct form for
1585 * direct load into the Big Num Cache.
1587 nBytes
= NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
)); /* parameter block */
1589 /* the kernel memory allocated here is freed in the call to
1590 * N8_RSAFreeKey. DO NOT add it to the free list here. */
1591 key_p
->kmem_p
= N8_KMALLOC_PK(nBytes
);
1592 CHECK_OBJECT(key_p
->kmem_p
, ret
);
1594 pAddr
= key_p
->kmem_p
->PhysicalAddress
;
1595 vAddr
= (N8_Buffer_t
*) key_p
->kmem_p
->VirtualAddress
;
1596 memset(vAddr
, 0, nBytes
);
1597 key_p
->paramBlock
= pAddr
;
1598 vKey
.paramBlock
= (N8_Buffer_t
*) vAddr
;
1600 pAddr
+= NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
));
1601 vAddr
+= NEXT_WORD_SIZE(PK_RSA_Param_Byte_Length(key_p
));
1605 * set the pointers in the key object to the correct address in the
1609 key_p
->p
= key_p
->paramBlock
+ PK_RSA_P_Param_Byte_Offset(key_p
);
1610 key_p
->q
= key_p
->paramBlock
+ PK_RSA_Q_Param_Byte_Offset(key_p
);
1611 key_p
->n
= key_p
->paramBlock
+ PK_RSA_N_Param_Byte_Offset(key_p
);
1612 key_p
->u
= key_p
->paramBlock
+ PK_RSA_U_Param_Byte_Offset(key_p
);
1613 key_p
->dp
= key_p
->paramBlock
+ PK_RSA_DP_Param_Byte_Offset(key_p
);
1614 key_p
->dq
= key_p
->paramBlock
+ PK_RSA_DQ_Param_Byte_Offset(key_p
);
1615 key_p
->R_mod_p
= key_p
->paramBlock
+ PK_RSA_R_MOD_P_Param_Byte_Offset(key_p
);
1616 key_p
->R_mod_q
= key_p
->paramBlock
+ PK_RSA_R_MOD_Q_Param_Byte_Offset(key_p
);
1617 key_p
->cp
= key_p
->paramBlock
+ PK_RSA_CP_Param_Byte_Offset(key_p
);
1618 key_p
->cq
= key_p
->paramBlock
+ PK_RSA_CQ_Param_Byte_Offset(key_p
);
1620 pb
= vKey
.paramBlock
;
1621 vKey
.p
= pb
+ PK_RSA_P_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1622 vKey
.q
= pb
+ PK_RSA_Q_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1623 vKey
.n
= pb
+ PK_RSA_N_Param_Byte_Offset(key_p
) + padding
;
1624 vKey
.u
= pb
+ PK_RSA_U_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1625 vKey
.dp
= pb
+ PK_RSA_DP_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1626 vKey
.dq
= pb
+ PK_RSA_DQ_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1627 vKey
.R_mod_p
= pb
+ PK_RSA_R_MOD_P_Param_Byte_Offset(key_p
) + key_p
->pPad
;
1628 vKey
.R_mod_q
= pb
+ PK_RSA_R_MOD_Q_Param_Byte_Offset(key_p
) + key_p
->qPad
;
1629 vKey
.cp
= pb
+ PK_RSA_CP_Param_Byte_Offset(key_p
);
1630 vKey
.cq
= pb
+ PK_RSA_CQ_Param_Byte_Offset(key_p
);
1633 * convert the material from BIGNUM to binary byte buffer and copy
1634 * to the key's parameter block
1637 /* if p < q, use them in order */
1640 /* p < q. use them in order. */
1641 memcpy(vKey
.p
, material_p
->p
.value_p
, key_p
->pLength
);
1642 memcpy(vKey
.q
, material_p
->q
.value_p
, key_p
->qLength
);
1644 else if (pq_cmp
> 0)
1646 /* p > q. swap them. */
1647 DBG(("p > q: swapping\n"));
1648 memcpy(vKey
.p
, material_p
->q
.value_p
, key_p
->pLength
); /* swapped */
1649 memcpy(vKey
.q
, material_p
->p
.value_p
, key_p
->qLength
); /* swapped */
1653 /* p == q. error! */
1654 ret
= N8_INVALID_PARAMETER
;
1658 DBG_PARAM("input only\n", vKey
.paramBlock
, key_p
);
1660 /* Task 3: compute u = (p^-1) mod q */
1661 ret
= cb_computeU(req_p
, key_p
->p
, key_p
->q
, key_p
->u
,
1662 PK_RSA_P_Byte_Length(key_p
),
1663 PK_RSA_Q_Byte_Length(key_p
),
1664 req_p
->PK_CommandBlock_ptr
, &nextCommandBlock_p
);
1667 /* Task 4: compute dp = mod((p-1) mod p) */
1668 memcpy(vKey
.dp
, dp_p
->value_p
, dp_p
->lengthBytes
);
1670 /* Task 5: compute dq = mod((q-1) mod q) */
1671 memcpy(vKey
.dq
, dq_p
->value_p
, dq_p
->lengthBytes
);
1673 /* Task 6: Compute cp = -(p[0]^-1 mod 2^128) mod 2^128 and */
1674 /* put it into the key object. */
1675 ret
= cb_computeCX(req_p
, key_p
->p
, key_p
->cp
,
1676 PK_RSA_P_Byte_Length(key_p
),
1677 nextCommandBlock_p
, &nextCommandBlock_p
,
1682 /* Task 7: Compute cq = -(q[0]^-1 mod 2^128) mod 2^128 and */
1683 /* put it into the key object. */
1684 ret
= cb_computeCX(req_p
, key_p
->q
, key_p
->cq
,
1685 PK_RSA_Q_Byte_Length(key_p
),
1686 nextCommandBlock_p
, &nextCommandBlock_p
,
1691 /* Task 8: Compute R mod p and put it into the key object. */
1692 ret
= cb_computeRmodX(req_p
, key_p
->p
, key_p
->R_mod_p
,
1693 PK_RSA_P_Byte_Length(key_p
),
1694 nextCommandBlock_p
, &nextCommandBlock_p
, FALSE
);
1697 /* Task 9: Compute R mod q and put it into the key object. */
1698 ret
= cb_computeRmodX(req_p
, key_p
->q
, key_p
->R_mod_q
,
1699 PK_RSA_Q_Byte_Length(key_p
),
1700 nextCommandBlock_p
, &nextCommandBlock_p
, TRUE
);
1702 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1703 HANDLE_EVENT(event_p
, req_p
, ret
);
1705 if ((N8_Buffer_t
*) vKey
.paramBlock
!= NULL
)
1707 DBG_PARAM("Computed Parameter Block:\n", vKey
.paramBlock
, key_p
);
1712 * Clean up if we arrived from an error condition.
1714 if (ret
!= N8_STATUS_OK
)
1720 } /* initPrivateKeyCRT_OC */
1723 /*****************************************************************************
1725 *****************************************************************************/
1727 * @brief Initialize an RSA private key object.
1729 * <More detailed description of the function including any unusual algorithms
1730 * or suprising details.>
1732 * @param key_p RW: pointer to the key to be initialized
1733 * @param material_p RW: pointer to key material with initialization
1735 * @param event_p RW: pointer to event structure
1741 * Statue. Error code if encountered.
1748 *****************************************************************************/
1749 static N8_Status_t
initPrivateSKSKey(N8_RSAKeyObject_t
*key_p
,
1750 N8_RSAKeyMaterial_t
*material_p
,
1751 N8_Event_t
*event_p
)
1753 N8_Status_t ret
= N8_STATUS_OK
;
1757 /* verify the required parameters are not null */
1758 CHECK_OBJECT(key_p
, ret
);
1759 CHECK_OBJECT(material_p
, ret
);
1760 /* verify the SKS type is correct */
1761 if (material_p
->SKSKeyHandle
.key_type
!= N8_RSA_VERSION_1_KEY
)
1763 ret
= N8_INCONSISTENT
;
1766 key_p
->publicKeyLength
= PKDIGITS_TO_BYTES(material_p
->SKSKeyHandle
.key_length
);
1767 key_p
->privateKeyLength
= PKDIGITS_TO_BYTES(material_p
->SKSKeyHandle
.key_length
);
1768 /* key_p->publicKeyLength = material_p->publicKey.lengthBytes;
1769 key_p->privateKeyLength = material_p->privateKey.lengthBytes;*/
1770 /* copy the SKS key handle from the key material to the key object */
1771 memcpy(&key_p
->SKSKeyHandle
,
1772 &material_p
->SKSKeyHandle
,
1773 sizeof(N8_SKSKeyHandle_t
));
1774 /* initializing for SKS requires no further processing. set the event
1775 * status to finished if called asynchronously. */
1776 if (event_p
!= NULL
)
1778 N8_SET_EVENT_FINISHED(event_p
, N8_PKP
);
1782 } /* initPrivateSKSKey */