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_cb_rsa.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
38 * @brief RSA Command Block Generator
40 * Generates all command blocks for RSA-related functions.
42 *****************************************************************************/
44 /*****************************************************************************
46 * 12/17/03 bac Added cb_rsaPublicDecrypt
47 * 09/10/02 brr Set command complete bit on last command block.
48 * 05/07/02 bac Fix Bug #758: command blocks generated were incorrect if the
49 * modulus length was less than 2 BNC digits. The commands
50 * blocks were restructured to behave correctly.
51 * 05/09/02 brr Modified allocateBNCConstants to use constant setup by driver.
52 * 04/08/02 bac Minor change to use precomputed key_p->pDigits and qDigits.
53 * 03/26/02 brr Allocate the data buffer as part of the API request.
54 * 02/21/02 brr Perform BNC constant initialization once upon startup.
55 * 02/20/02 brr Removed references to the queue structure.
56 * 12/12/01 bac Use precomputes for RSA encrypt. Created a new static method
57 * cb_exp_with_precomputes. Fixes Bug #371.
58 * 11/08/01 mel Fixed bug #289 : Some calls use N8_SINGLE_CHIP in the
60 * 10/19/01 bac Added support for SKS operations and RSA Decrypt for non-CRT.
61 * 10/28/01 msz Added locking allocateBNCConstants.
62 * 10/08/01 bac Changes for the case where len(p) != len(q) (BUG #180).
63 * Everywhere a data length was assumed to half the key length,
64 * it has been replaced with the specific dependency on the
66 * 09/14/01 bac Use new DBG_PRINT_PK_CMD_BLOCKS macros.
67 * 09/05/01 bac Minor formatting change.
68 * 08/24/01 bac Changed all methods to accept the pre-allocated command
70 * 08/16/01 mmd Now including n8_driver_api.h instead of simon_driver_api.h.
71 * 08/21/01 bac Fixes to allow the use of odd key lengths (Bug #174).
72 * 07/30/01 bac Pass queue pointer to all length calculation macros.
73 * 07/02/01 mel Fixed comments.
74 * 06/28/01 bac Changed size of load on computeCX as it did not work for 'n',
75 * changed the interface to cb_rsaEncrypt and cb_rsaDecrypt to
76 * take physical addresses not N8_MemoryHandle_t. Other minor
77 * naming/formatting fixes.
78 * 06/27/01 bac Removed calls to free request blocks on error. This is
79 * handled in the caller.
80 * 06/25/01 bac Added static allocation of BNC constants, more conversion to
82 * 06/19/01 bac Corrected use of kernel memory.
83 * 05/30/01 bac Fixed printCommandBlock to display pleasingly for little
85 * 05/03/01 bac Added include for string.h
86 * 04/30/01 bac Added support for rsaDecrypt use with non-PKH command generation.
87 * 04/24/01 bac Rearranged N8DEBUG fences
88 * 04/11/01 bac Standardization -- mainly support for _t suffix for types.
89 * 04/05/01 bac Changed return codes to be N8_Status instead of ints.
90 * 04/05/01 bac Removed unused debugging variable sz.
91 * 04/05/01 bac Changed all key length info to be in bytes, not digits.
92 * 03/01/01 bac Original version.
93 ****************************************************************************/
94 /** @defgroup cb_rsa RSA Command Block Generator
97 #include "n8_common.h"
98 #include "n8_pk_common.h"
99 #include "n8_pub_errors.h"
100 #include "n8_cb_rsa.h"
102 #include "n8_driver_api.h"
103 #include "n8_semaphore.h"
105 /* #define ZERO_CMD_BLOCK(X) memset((X), 0, sizeof(PK_CMD_BLOCK_t)) */
106 #define ZERO_CMD_BLOCK(X)
109 static uint32_t bnc_one_ga
;
110 static uint32_t bnc_2_D_ga
;
113 /* predeclarations */
114 static N8_Boolean_t
cb_RSAOperationSupported(const N8_RSAKeyObject_t
*key_p
);
116 /*****************************************************************************
118 *****************************************************************************/
120 * @brief Creates the command blocks to compute the value for u where
121 * u = (p^-1) mod q [ (multiplicative inverse of p) mod q ]
123 * @param req_p RW: Pointer to command
125 * @param p RO: Physical address of p.
126 * @param q RO: Physical address of q.
127 * @param p_length_bytes RO: Length of parameter p in bytes
128 * @param q_length_bytes RO: Length of parameter q in bytes
129 * @param result_a WO: Physical address of result
130 * @param key_length_bytes RO: Private key length.
133 * returnResult - returns N8_STATUS_OK if successful or Error value.
136 * N8_MALLOC_FAILED - memory allocation failed<BR>
140 *****************************************************************************/
141 N8_Status_t
cb_computeU(API_Request_t
*req_p
,
145 const int p_length_bytes
,
146 const int q_length_bytes
,
147 PK_CMD_BLOCK_t
*cb_p
,
148 PK_CMD_BLOCK_t
**next_cb_pp
)
151 PK_CMD_BLOCK_t
*math_wr_ptr
;
152 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
154 uint32_t p_length
= BYTES_TO_PKDIGITS(p_length_bytes
);
155 uint32_t q_length
= BYTES_TO_PKDIGITS(q_length_bytes
);
156 /* since p<q, then len(p) <= len(q). we want the offsets to be in units of
157 * the longer of the two, so we use q_length. */
158 unsigned int offset
[3];
160 N8_Status_t ret
= N8_STATUS_OK
;
171 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
173 offset
[i
] = i
* q_length
;
175 /* 1: Construct a command to load p */
176 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
178 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
179 ldst_wr_ptr
->r_offset
= offset
[0];
180 ldst_wr_ptr
->data_addr_ls
= p
;
181 ldst_wr_ptr
->data_length
= p_length_bytes
;
183 /* 2: Construct a command to load q */
185 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
186 ldst_wr_ptr
->r_offset
= offset
[1];
187 ldst_wr_ptr
->data_addr_ls
= q
;
188 ldst_wr_ptr
->data_length
= q_length_bytes
;
190 /* 3: Construct a command for the operation p^-1 mod q */
191 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
192 math_wr_ptr
->opcode_si
= PK_Cmd_Inverse_A_Mod_M
;
193 math_wr_ptr
->r_offset
= offset
[2];
194 math_wr_ptr
->m_length_offset
=
195 (q_length
<< PK_Cmd_Length_Shift
) | offset
[1]; /* q */
196 math_wr_ptr
->a_length_offset
=
197 (p_length
<< PK_Cmd_Length_Shift
) | offset
[0]; /* p */
200 * 4: Construct a command to store u
202 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
203 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
;
204 ldst_wr_ptr
->r_offset
= offset
[2];
205 ldst_wr_ptr
->data_addr_ls
= result_a
;
206 ldst_wr_ptr
->data_length
= q_length_bytes
;
208 /* save next address for future use */
209 *next_cb_pp
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
211 DBG_PRINT_PK_CMD_BLOCKS("Compute U",
212 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
213 N8_CB_COMPUTE_U_NUMCMDS
);
219 /*****************************************************************************
221 *****************************************************************************/
223 * @brief Creates the command blocks to compute the value for dX where
224 * dX = d mod ((X-1) mod X). This is used to compute dp and dq.
226 * since (X-1) = additive_inverse(1), it can be computed as:
228 * dX = d mod(additive_inverse(1) mod X), which is more
229 * straightforward to compute
232 * @param req_p RW: Pointer to command
234 * @param X RO: Physical address of X.
235 * @param d RO: Physical address of d.
236 * @param result_a WO: Physical address of result
237 * @param key_length_bytes RO: Private key length.
240 * returnResult - returns N8_STATUS_OK if successful or Error value.
243 * N8_MALLOC_FAILED - memory allocation failed<BR>
247 *****************************************************************************/
248 N8_Status_t
cb_computeDX(API_Request_t
*req_p
,
252 const int key_length_bytes
,
253 const int X_length_bytes
,
254 PK_CMD_BLOCK_t
*cb_p
,
255 PK_CMD_BLOCK_t
**next_cb_pp
,
258 PK_CMD_BLOCK_t
*math_wr_ptr
;
259 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
261 uint32_t key_length
= BYTES_TO_PKDIGITS(key_length_bytes
);
262 uint32_t X_length
= BYTES_TO_PKDIGITS(X_length_bytes
);
263 unsigned int offset
[5];
265 N8_Status_t ret
= N8_STATUS_OK
;
279 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
281 offset
[i
] = i
* key_length
;
284 /* Construct a command to load X */
285 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
287 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
288 ldst_wr_ptr
->r_offset
= offset
[1];
289 ldst_wr_ptr
->data_addr_ls
= X
;
290 ldst_wr_ptr
->data_length
= X_length_bytes
;
292 /* Construct a command to load a 1 into one BNC digit */
294 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
295 ldst_wr_ptr
->r_offset
= offset
[2];
296 ldst_wr_ptr
->data_addr_ls
= bnc_one_ga
;
297 ldst_wr_ptr
->data_length
= PK_Bytes_Per_BigNum_Digit
;
299 /* Construct a command to load d */
301 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
302 ldst_wr_ptr
->r_offset
= offset
[4];
303 ldst_wr_ptr
->data_addr_ls
= d
;
304 ldst_wr_ptr
->data_length
= key_length_bytes
;
307 * Construct a command for the operation (additive_inverse(1) mod X)
309 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
310 math_wr_ptr
->opcode_si
= PK_Cmd_Minus_A_Mod_M
;
311 math_wr_ptr
->r_offset
= offset
[3];
312 math_wr_ptr
->m_length_offset
=
313 (X_length
<< PK_Cmd_Length_Shift
) | offset
[1];
314 math_wr_ptr
->a_length_offset
= (1 << PK_Cmd_Length_Shift
) | offset
[2];
317 * Construct a command for the operation:
318 * d mod ((X-1) mod X)
321 math_wr_ptr
->opcode_si
= PK_Cmd_A_Mod_M
;
322 math_wr_ptr
->r_offset
= offset
[0];
323 math_wr_ptr
->m_length_offset
=
324 (X_length
<< PK_Cmd_Length_Shift
) | offset
[3];
325 math_wr_ptr
->a_length_offset
=
326 (key_length
<< PK_Cmd_Length_Shift
) | offset
[4];
330 * Construct a command to store dX
332 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
333 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
;
334 ldst_wr_ptr
->r_offset
= offset
[0];
335 ldst_wr_ptr
->data_addr_ls
= result_a
;
336 ldst_wr_ptr
->data_length
= X_length_bytes
;
338 /* save next address for future use */
339 *next_cb_pp
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
341 DBG_PRINT_PK_CMD_BLOCKS("Compute DX",
342 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
343 N8_CB_COMPUTE_DX_NUMCMDS
);
349 /*****************************************************************************
351 *****************************************************************************/
353 * @brief Creates the command blocks to compute the value for cX where
354 * cX = -X[0]^-1: the additive inverse of the multiplicative inverse
355 * of the least significant digit of X.
356 * This is used to compute cp and cq.
359 * @param req_p RW: Pointer to command
361 * @param X RO: Physical address of X.
362 * @param result_a WO: Physical address of result
363 * @param X_length_bytes RO: X length in bytes.
366 * returnResult - returns N8_STATUS_OK if successful or Error value.
369 * N8_INVALID_OBJECT - command block pointer is NULL<BR>
370 * N8_MALLOC_FAILED - memory allocation failed<BR>
374 *****************************************************************************/
375 N8_Status_t
cb_computeCX(const API_Request_t
*req_p
,
377 const uint32_t result_a
,
378 const int X_length_bytes
,
379 PK_CMD_BLOCK_t
*cb_p
,
380 PK_CMD_BLOCK_t
**next_cb_pp
,
381 const N8_Unit_t unitID
,
384 PK_CMD_BLOCK_t
*math_wr_ptr
;
385 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
387 uint32_t X_length
= BYTES_TO_PKDIGITS(X_length_bytes
);
388 unsigned int offset
[4];
390 N8_Status_t ret
= N8_STATUS_OK
;
395 * Initialize the offset values. These are to address temporary
396 * storage in the BNC. The offsets accomodate operand sizes up to
399 * The BNC layout will look like the following:
401 * -----------------------------------
402 * 0: results 2 digits
403 * -----------------------------------
404 * 1: t = p[0]^-1 2 digits
405 * -----------------------------------
407 * -----------------------------------
409 * -----------------------------------
411 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
415 /* Compute cX = -(p[0]^-1 mod 2^128) mod 2^128 */
417 /* Construct a command to load p[0] to Slot 3 */
418 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
420 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
421 ldst_wr_ptr
->r_offset
= offset
[3];
422 ldst_wr_ptr
->data_addr_ls
= X
;
423 ldst_wr_ptr
->data_length
= X_length_bytes
;
426 /* Construct a command to load a 2-digit 2^128 to Slot 2*/
428 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
429 ldst_wr_ptr
->r_offset
= offset
[2];
430 ldst_wr_ptr
->data_addr_ls
= bnc_2_D_ga
;
431 ldst_wr_ptr
->data_length
= PKDIGITS_TO_BYTES(2);
434 /* Construct a command for the operation t = p[0]^-1 mod 2^128 to Slot 1 */
435 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
436 math_wr_ptr
->opcode_si
= PK_Cmd_Inverse_A_Mod_M
;
437 math_wr_ptr
->r_offset
= offset
[1];
438 math_wr_ptr
->m_length_offset
=
439 (2 << PK_Cmd_Length_Shift
) | offset
[2];
440 math_wr_ptr
->a_length_offset
=
441 (1 << PK_Cmd_Length_Shift
) | (offset
[3] + X_length
- 1);
444 /* Construct a command for the operation cX = -t mod 2^128 to Slot 0 */
446 math_wr_ptr
->opcode_si
= PK_Cmd_Minus_A_Mod_M
;
447 math_wr_ptr
->r_offset
= offset
[0];
448 math_wr_ptr
->m_length_offset
=
449 (2 << PK_Cmd_Length_Shift
) | offset
[2];
450 math_wr_ptr
->a_length_offset
=
451 (1 << PK_Cmd_Length_Shift
) | (offset
[1] + 1);
454 /* Construct a command to store cX (second digit of previous result) */
455 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
456 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
;
457 if (lastCmdBlock
== N8_TRUE
)
459 ldst_wr_ptr
->opcode_si
|= PK_Cmd_SI_Mask
;
461 ldst_wr_ptr
->r_offset
= offset
[0] + 1;
462 ldst_wr_ptr
->data_addr_ls
= result_a
;
463 ldst_wr_ptr
->data_length
= PK_Bytes_Per_BigNum_Digit
;
465 /* save next address for future use */
466 *next_cb_pp
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
468 DBG_PRINT_PK_CMD_BLOCKS("Compute CX",
470 N8_CB_COMPUTE_CX_NUMCMDS
);
479 /*****************************************************************************
481 *****************************************************************************/
483 * @brief Creates the command blocks to compute the value for R mod X.
486 * @param req_p RW: Pointer to command
488 * @param X RO: Physical address of X.
489 * @param result_a WO: Physical address of result
490 * @param key_length_bytes RO: Length of X in bytes
493 * returnResult - returns N8_STATUS_OK if successful or Error value.
496 * N8_MALLOC_FAILED - memory allocation failed<BR>
500 *****************************************************************************/
501 N8_Status_t
cb_computeRmodX(const API_Request_t
*req_p
,
503 const uint32_t result_a
,
504 const unsigned int key_length_bytes
,
505 PK_CMD_BLOCK_t
*cb_p
,
506 PK_CMD_BLOCK_t
**next_cb_pp
,
509 PK_CMD_BLOCK_t
*math_wr_ptr
;
510 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
512 uint32_t key_length
= BYTES_TO_PKDIGITS(key_length_bytes
);
513 uint32_t offset0
= 0;
514 uint32_t offset1
= key_length
;
515 N8_Status_t ret
= N8_STATUS_OK
;
519 /* Compute R mod X */
520 /* 1: Construct a command to load X */
521 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
522 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
523 ldst_wr_ptr
->r_offset
= offset1
;
524 ldst_wr_ptr
->data_addr_ls
= X
;
525 ldst_wr_ptr
->data_length
= key_length_bytes
;
527 /* 2: Construct a command for the operation R mod X */
528 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
529 math_wr_ptr
->opcode_si
= PK_Cmd_R_Mod_M
;
530 math_wr_ptr
->r_offset
= offset0
;
531 math_wr_ptr
->m_length_offset
=
532 (key_length
<< PK_Cmd_Length_Shift
) | offset1
;
534 /* 3: Construct a command to store R mod p */
535 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
536 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
;
537 if (lastCmdBlock
== N8_TRUE
)
539 ldst_wr_ptr
->opcode_si
|= PK_Cmd_SI_Mask
;
541 ldst_wr_ptr
->r_offset
= offset0
;
542 ldst_wr_ptr
->data_addr_ls
= result_a
;
543 ldst_wr_ptr
->data_length
= key_length_bytes
;
545 /* save next address for future use */
546 *next_cb_pp
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
548 DBG_PRINT_PK_CMD_BLOCKS("Compute R mod X",
550 N8_CB_COMPUTE_RMODX_NUMCMDS
);
554 } /* compute RmodX */
556 N8_Status_t
cb_exponentiate(API_Request_t
*req_p
,
557 const uint32_t origMsg_a
,
558 const uint32_t modulus_a
,
559 const unsigned int modulus_length_bytes
,
560 const uint32_t exponent_a
,
561 const unsigned int exp_length_bytes
,
562 const uint32_t result_a
,
563 PK_CMD_BLOCK_t
*cb_p
,
564 const N8_Unit_t unitID
)
566 PK_CMD_BLOCK_t
*math_wr_ptr
;
567 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
568 uint32_t modulus_length_digits
;
569 uint32_t exp_length_digits
;
572 N8_Status_t ret
= N8_STATUS_OK
;
576 modulus_length_digits
= BYTES_TO_PKDIGITS(modulus_length_bytes
);
577 exp_length_digits
= BYTES_TO_PKDIGITS(exp_length_bytes
);
579 DBG(("constructing exponentiate command blocks\n"));
582 * Initialize the offset values. These are to address temporary
583 * storage in the BNC. The offsets accomodate operand sizes up to
586 * The BNC layout will look like the following:
588 * -----------------------------------
590 * -----------------------------------
591 * 1: R mod n , o * Rmodn mod n
592 * -----------------------------------
593 * 2: o (original message)
594 * -----------------------------------
596 * -----------------------------------
598 * -----------------------------------
600 * -----------------------------------
602 * -----------------------------------
604 * Slots 0-2 are of width |n|, the modulus length in BNC digits.
605 * Slot 3 is width |e|, the exponent length in BNC digits.
606 * Slots 4-6 are of width 2.
609 for (i
= 0; i
< 4; i
++)
611 offset
[i
] = i
* modulus_length_digits
;
613 for (i
= 0; i
< 3; i
++)
615 offset
[i
+4] = offset
[3] + exp_length_digits
+ i
* 2;
618 /* 1) Compute R mod n. */
620 /* Construct a command to load n to Slot 0 */
621 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
622 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
623 ldst_wr_ptr
->r_offset
= offset
[0];
624 ldst_wr_ptr
->data_addr_ls
= modulus_a
;
625 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
627 /* Construct a command for the operation R mod n to Slot 1 */
628 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
629 math_wr_ptr
->opcode_si
= PK_Cmd_R_Mod_M
;
630 math_wr_ptr
->r_offset
= offset
[1];
631 math_wr_ptr
->m_length_offset
= (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[0];
634 * 2) Compute cn = -(n[0]^-1 mod 2^128) mod 2^128
635 * n is already loaded in Slot 0
639 * Construct a command to load a
640 * 2-digit 2^128 to Slot 4
642 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
643 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
644 ldst_wr_ptr
->r_offset
= offset
[4];
645 ldst_wr_ptr
->data_addr_ls
= bnc_2_D_ga
;
646 ldst_wr_ptr
->data_length
= PKDIGITS_TO_BYTES(2);
648 /* Construct a command for the operation t = n[0]^-1 mod 2^128 to Slot 6 */
649 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
650 math_wr_ptr
->opcode_si
= PK_Cmd_Inverse_A_Mod_M
;
651 math_wr_ptr
->r_offset
= offset
[6];
652 math_wr_ptr
->m_length_offset
=
653 (2 << PK_Cmd_Length_Shift
) | offset
[4];
654 math_wr_ptr
->a_length_offset
=
655 (1 << PK_Cmd_Length_Shift
) | (offset
[0] + modulus_length_digits
- 1);
657 /* Construct a command for the operation cn = -t mod 2^128 to Slot 5*/
659 math_wr_ptr
->opcode_si
= PK_Cmd_Minus_A_Mod_M
;
660 math_wr_ptr
->r_offset
= offset
[5];
661 math_wr_ptr
->m_length_offset
=
662 (2 << PK_Cmd_Length_Shift
) | offset
[4];
663 math_wr_ptr
->a_length_offset
=
664 (1 << PK_Cmd_Length_Shift
) | (offset
[6] + 1);
667 * 3) Compute o * R mod n (mod n)
670 /* Construct a command to load the original message to Slot 2*/
671 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
672 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
673 ldst_wr_ptr
->r_offset
= offset
[2];
674 ldst_wr_ptr
->data_addr_ls
= origMsg_a
;
675 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
677 /* Construct a command for the operation o * Rmodn mod n to Slot 1*/
678 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
679 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
680 math_wr_ptr
->r_offset
= offset
[1];
681 math_wr_ptr
->m_length_offset
=
682 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[0]; /* n */
683 math_wr_ptr
->a_length_offset
=
684 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[2]; /* o */
685 math_wr_ptr
->b_length_offset
=
686 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1]; /* R mod n */
689 * 4) Compute o^e mod n
692 /* Construct a command to load e to Slot 3 */
693 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
694 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
695 ldst_wr_ptr
->r_offset
= offset
[3];
696 ldst_wr_ptr
->data_addr_ls
= exponent_a
;
697 ldst_wr_ptr
->data_length
= exp_length_bytes
;
699 /* Construct a command for the operation o^e mod n to Slot 0 */
700 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
701 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
702 math_wr_ptr
->r_offset
= offset
[0];
703 math_wr_ptr
->m_length_offset
=
704 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[0]; /* n */
705 math_wr_ptr
->a_length_offset
=
706 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1]; /* o * R mod n */
707 math_wr_ptr
->b_length_offset
= (exp_length_digits
<< PK_Cmd_Length_Shift
) | offset
[3]; /* exponent */
708 math_wr_ptr
->c_offset
= offset
[5] + 1; /* cn */
710 /* Construct a command to store o^e mod n */
711 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
712 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
713 ldst_wr_ptr
->r_offset
= offset
[0];
714 ldst_wr_ptr
->data_addr_ls
= result_a
;
715 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
717 DBG_PRINT_PK_CMD_BLOCKS("rsa exponentiate",
718 req_p
->PK_CommandBlock_ptr
,
719 N8_CB_EXPONENTIATE_NUMCMDS
);
722 } /* n8_cb_exponentiate */
724 static N8_Status_t
cb_exp_with_precomputes(API_Request_t
*req_p
,
725 const uint32_t origMsg_a
,
726 const uint32_t modulus_a
,
727 const unsigned int modulus_length_bytes
,
728 const uint32_t exponent_a
,
729 const unsigned int exp_length_bytes
,
731 const uint32_t R_mod_n_a
,
732 const uint32_t result_a
,
733 PK_CMD_BLOCK_t
*cb_p
,
734 const N8_Unit_t unitID
)
736 PK_CMD_BLOCK_t
*math_wr_ptr
;
737 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
738 uint32_t modulus_length_digits
;
739 uint32_t exp_length_digits
;
742 N8_Status_t ret
= N8_STATUS_OK
;
746 modulus_length_digits
= BYTES_TO_PKDIGITS(modulus_length_bytes
);
747 exp_length_digits
= BYTES_TO_PKDIGITS(exp_length_bytes
);
749 DBG(("constructing exponentiate with precomputes command blocks\n"));
752 * Initialize the offset values. These are to address temporary
753 * storage in the BNC. The offsets accomodate operand sizes up to
757 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
759 offset
[i
] = i
* modulus_length_digits
;
763 * 1) Construct a command to load n to offset[1]
765 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
766 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
767 ldst_wr_ptr
->r_offset
= offset
[1];
768 ldst_wr_ptr
->data_addr_ls
= modulus_a
;
769 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
772 * 2) Load R mod n to offset[2]
775 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
776 ldst_wr_ptr
->r_offset
= offset
[2];
777 ldst_wr_ptr
->data_addr_ls
= R_mod_n_a
;
778 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
781 * 3) Load cn to offset[3]
784 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
785 ldst_wr_ptr
->r_offset
= offset
[3];
786 ldst_wr_ptr
->data_addr_ls
= cn_a
;
787 ldst_wr_ptr
->data_length
= PK_RSA_CN_Byte_Length
;
790 * Compute o * R mod n (mod n)
794 * 4) Construct a command to load the original message to offset[5]
797 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
798 ldst_wr_ptr
->r_offset
= offset
[5];
799 ldst_wr_ptr
->data_addr_ls
= origMsg_a
;
800 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
803 * 5) Construct a command for the operation o * Rmodn mod n to offset[2]
805 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
806 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
807 math_wr_ptr
->r_offset
= offset
[2];
808 math_wr_ptr
->m_length_offset
=
809 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1];
810 math_wr_ptr
->a_length_offset
=
811 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[5];
812 math_wr_ptr
->b_length_offset
=
813 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[2];
820 * 6) Construct a command to load e to offset[4]
822 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
823 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
824 ldst_wr_ptr
->r_offset
= offset
[4];
825 ldst_wr_ptr
->data_addr_ls
= exponent_a
;
826 ldst_wr_ptr
->data_length
= exp_length_bytes
;
829 * 7) Construct a command for the operation o^e mod n to offset[0]
831 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
832 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
833 math_wr_ptr
->r_offset
= offset
[0];
834 math_wr_ptr
->m_length_offset
=
835 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1];
836 math_wr_ptr
->a_length_offset
=
837 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[2];
838 math_wr_ptr
->b_length_offset
= (exp_length_digits
<< PK_Cmd_Length_Shift
) | offset
[4];
839 math_wr_ptr
->c_offset
= offset
[3];
842 * 8) Construct a command to store o^e mod n from offset[0]
844 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
845 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
846 ldst_wr_ptr
->r_offset
= offset
[0];
847 ldst_wr_ptr
->data_addr_ls
= result_a
;
848 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
850 DBG_PRINT_PK_CMD_BLOCKS("rsa exponentiate with precomputes",
851 req_p
->PK_CommandBlock_ptr
,
852 N8_CB_RSA_ENCRYPT_NUMCMDS
);
855 } /* cb_exponentiate_with_precomputes */
857 /*****************************************************************************
859 *****************************************************************************/
861 * @brief Takes an incoming message and encrypts it via exponentiation with
864 * @param req_p RW: Pointer to command
866 * @param key RO: Key object with precomputed values for
867 * speedier computation
868 * @param origMsg RO: Physical address of original message.
869 * @param result_a WO: Physical address of result
872 * returnResult - returns N8_STATUS_OK if successful or Error value.
875 * N8_MALLOC_FAILED - memory allocation failed<BR>
879 *****************************************************************************/
880 N8_Status_t
cb_rsaEncrypt(API_Request_t
*req_p
,
881 const N8_RSAKeyObject_t
*key_p
,
882 const uint32_t origMsg_a
,
883 const uint32_t result_a
,
884 PK_CMD_BLOCK_t
*cb_p
,
885 const N8_Unit_t unitID
)
887 /* To compute an encryption of the plaintext using the recipients public key,
888 * a simple exponentiation is required.
889 * cipher_text = plain_text ** public_key mod n.
891 return cb_exp_with_precomputes(req_p
, /* API request pointer */
892 origMsg_a
, /* plain text */
893 key_p
->n
, /* modulus */
894 key_p
->privateKeyLength
, /* modulus length */
895 key_p
->key
, /* public key */
896 key_p
->publicKeyLength
, /* public key length */
897 key_p
->cn
, /* precomputed cn */
898 key_p
->R_mod_n
, /* precomputed R mod n */
899 result_a
, /* result buffer */
900 cb_p
, /* command block pointer */
901 unitID
); /* chip ID */
905 /*****************************************************************************
907 *****************************************************************************/
909 * @brief Takes an incoming message and decrypts it by using the PKE RSA
912 * @param req_p RW: Pointer to command
914 * @param key RO: Key object with precomputed values for
915 * speedier computation
916 * @param origMsg RO: Physical address of original message.
917 * @param result_a WO: Physical address of result
920 * returnResult - returns N8_STATUS_OK if successful or Error value.
923 * N8_MALLOC_FAILED - memory allocation failed<BR>
927 *****************************************************************************/
928 N8_Status_t
cb_rsaDecrypt(API_Request_t
*req_p
,
929 const N8_RSAKeyObject_t
*key_p
,
930 const uint32_t origMsg_a
,
931 const uint32_t result_a
,
932 PK_CMD_BLOCK_t
*cb_p
,
933 const N8_Unit_t unitID
)
935 PK_RSA_CMD_BLOCK_t
*rsa_wr_ptr
= NULL
;
936 PK_CMD_BLOCK_t
*math_wr_ptr
= NULL
;
937 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
= NULL
;
939 uint32_t half_key_length
;
940 uint32_t key_length_bytes
;
942 N8_Status_t ret
= N8_STATUS_OK
;
943 uint32_t paramBlockOffset
;
944 unsigned int offset
[3];
953 uint32_t rmodp_offset
;
954 uint32_t rmodq_offset
;
959 /* If the key type is N8_PRIVATE, we are to do a private decrypt without
960 * the knowledge of p and q, thus we cannot utilize the Chinese Remainder
961 * Theorem algorithm. Instead we must simply compute the plaintext using:
962 * plain = msg ** private_key mod n.
964 if (key_p
->keyType
== N8_PRIVATE
)
966 return cb_exponentiate(req_p
, /* API request pointer */
967 origMsg_a
, /* cipher text */
968 key_p
->n
, /* modulus */
969 key_p
->privateKeyLength
, /* modulus length */
970 key_p
->key
, /* private key */
971 key_p
->privateKeyLength
, /* private key length */
972 result_a
, /* result buffer */
973 cb_p
, /* command block pointer */
976 key_length_bytes
= key_p
->privateKeyLength
;
977 key_length
= BYTES_TO_PKDIGITS(key_length_bytes
);
978 half_key_length
= BYTES_TO_PKDIGITS(key_length_bytes
/2);
980 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
982 offset
[i
] = i
* key_length
;
984 /* set up the offsets */
985 paramBlockOffset
= offset
[2];
986 p_offset
= paramBlockOffset
+ PK_RSA_P_Param_Offset(key_p
);
987 q_offset
= paramBlockOffset
+ PK_RSA_Q_Param_Offset(key_p
);
988 n_offset
= paramBlockOffset
+ PK_RSA_N_Param_Offset(key_p
);
989 dp_offset
= paramBlockOffset
+ PK_RSA_DP_Param_Offset(key_p
);
990 dq_offset
= paramBlockOffset
+ PK_RSA_DQ_Param_Offset(key_p
);
991 cp_offset
= paramBlockOffset
+ PK_RSA_CP_Param_Offset(key_p
);
992 cq_offset
= paramBlockOffset
+ PK_RSA_CQ_Param_Offset(key_p
);
993 rmodp_offset
= paramBlockOffset
+ PK_RSA_R_MOD_P_Param_Offset(key_p
);
994 rmodq_offset
= paramBlockOffset
+ PK_RSA_R_MOD_Q_Param_Offset(key_p
);
995 u_offset
= paramBlockOffset
+ PK_RSA_U_Param_Offset(key_p
);
997 /* 1: Construct a command to load the original message */
998 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
999 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1000 ldst_wr_ptr
->r_offset
= offset
[0];
1001 ldst_wr_ptr
->data_addr_ls
= origMsg_a
;
1002 ldst_wr_ptr
->data_length
= key_length_bytes
;
1004 if (key_p
->keyType
!= N8_PRIVATE_SKS
)
1006 /* 2: Construct a command to load the RSA parameter block */
1008 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1009 ldst_wr_ptr
->r_offset
= paramBlockOffset
;
1010 ldst_wr_ptr
->data_addr_ls
= key_p
->paramBlock
;
1011 ldst_wr_ptr
->data_length
= PK_RSA_Param_Byte_Length(key_p
);
1012 sks_word
= PK_Cmd_N_Mask
;
1016 /* we are using the sks. set the sks_word variable to the correct
1018 sks_word
= key_p
->SKSKeyHandle
.sks_offset
;
1021 if (key_p
->keyType
== N8_PRIVATE_SKS
||
1022 cb_RSAOperationSupported(key_p
))
1024 /* 2: Construct a command for the RSA operation */
1025 rsa_wr_ptr
= (PK_RSA_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
1026 ZERO_CMD_BLOCK(rsa_wr_ptr
);
1027 rsa_wr_ptr
->opcode_si
= PK_Cmd_RSA_Private_Key_Op
;
1028 rsa_wr_ptr
->sks
= ((key_length
) << PK_Cmd_Key_Length_Shift
) | sks_word
;
1030 /* Set up the ldst pointer for the next command. */
1031 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (rsa_wr_ptr
+ 1);
1035 /* 3: o = i mod p */
1036 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
1037 math_wr_ptr
->opcode_si
= PK_Cmd_A_Mod_M
;
1038 math_wr_ptr
->r_offset
= offset
[1];
1039 math_wr_ptr
->m_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | p_offset
;
1040 math_wr_ptr
->a_length_offset
= (key_length
<< PK_Cmd_Length_Shift
) | offset
[0];
1042 /* 4: o = (o * R mod p) mod p */
1044 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
1045 math_wr_ptr
->r_offset
= offset
[1];
1046 math_wr_ptr
->m_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | p_offset
;
1047 math_wr_ptr
->a_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1048 math_wr_ptr
->b_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | rmodp_offset
;
1050 /* 5: dp = o ^ dp mod p */
1052 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
1053 math_wr_ptr
->r_offset
= dp_offset
;
1054 math_wr_ptr
->m_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | p_offset
;
1055 math_wr_ptr
->a_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1056 math_wr_ptr
->b_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | dp_offset
;
1057 math_wr_ptr
->c_offset
= cp_offset
;
1059 /* 6: o = i mod q */
1061 math_wr_ptr
->opcode_si
= PK_Cmd_A_Mod_M
;
1062 math_wr_ptr
->r_offset
= offset
[1];
1063 math_wr_ptr
->m_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | q_offset
;
1064 math_wr_ptr
->a_length_offset
= (key_length
<< PK_Cmd_Length_Shift
) | offset
[0];
1066 /* 7: o = o * R mod q (mod q) */
1068 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
1069 math_wr_ptr
->r_offset
= offset
[1];
1070 math_wr_ptr
->m_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | q_offset
;
1071 math_wr_ptr
->a_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1072 math_wr_ptr
->b_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | rmodq_offset
;
1074 /* 8: dq = o ^ dq mod q */
1076 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
1077 math_wr_ptr
->r_offset
= dq_offset
;
1078 math_wr_ptr
->m_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | q_offset
;
1079 math_wr_ptr
->a_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1080 math_wr_ptr
->b_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | dq_offset
;
1081 math_wr_ptr
->c_offset
= cq_offset
;
1083 /* 9: o = dq - dp mod q */
1085 math_wr_ptr
->opcode_si
= PK_Cmd_A_Minus_B_Mod_M
;
1086 math_wr_ptr
->r_offset
= offset
[1];
1087 math_wr_ptr
->m_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | q_offset
;
1088 math_wr_ptr
->a_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | dq_offset
;
1089 math_wr_ptr
->b_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | dp_offset
;
1091 /* 10: o = o * u mod q */
1093 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
1094 math_wr_ptr
->r_offset
= offset
[1];
1095 math_wr_ptr
->m_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | q_offset
;
1096 math_wr_ptr
->a_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1097 math_wr_ptr
->b_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | u_offset
;
1099 /* 11: o = o * p mod n */
1101 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
1102 math_wr_ptr
->r_offset
= offset
[1];
1103 math_wr_ptr
->m_length_offset
= (key_length
<< PK_Cmd_Length_Shift
) | n_offset
;
1104 math_wr_ptr
->a_length_offset
= (key_p
->qDigits
<< PK_Cmd_Length_Shift
) | offset
[1];
1105 math_wr_ptr
->b_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | p_offset
;
1107 /* 12: o = o + dp mod n */
1109 math_wr_ptr
->opcode_si
= PK_Cmd_A_Plus_B_Mod_M
;
1110 math_wr_ptr
->r_offset
= offset
[1];
1111 math_wr_ptr
->m_length_offset
= (key_length
<< PK_Cmd_Length_Shift
) | n_offset
;
1112 math_wr_ptr
->a_length_offset
= (key_length
<< PK_Cmd_Length_Shift
) | offset
[1];
1113 math_wr_ptr
->b_length_offset
= (key_p
->pDigits
<< PK_Cmd_Length_Shift
) | dp_offset
;
1115 /* Set up the ldst pointer for the next command. */
1116 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
1118 /* 3/13: Construct a command to store r */
1119 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
1120 ldst_wr_ptr
->r_offset
= offset
[1];
1121 ldst_wr_ptr
->data_addr_ls
= result_a
;
1122 ldst_wr_ptr
->data_length
= key_length_bytes
;
1124 DBG_PRINT_PK_CMD_BLOCKS("rsa decrypt",
1125 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
1126 N8_CB_RSA_DECRYPT_NUMCMDS(key_p
));
1134 /*****************************************************************************
1135 * cb_RSADecryptOperations
1136 *****************************************************************************/
1138 * @brief Calculate the number of operations required for an RSA Decrypt.
1140 * The operations used to perform an RSA Decrypt depend upon the key type and
1141 * the lengths of p, q, and the private key. If the type is N8_PRIVATE_SKS,
1142 * then the RSA Operation can be used and the data is taken from the SKS, saving
1143 * a load. If it is not SKS and len(p) == len(q) AND len(p) + len(q) ==
1144 * len(private key), then the RSA Operation can be used. If the above does not
1145 * hold, then this presents a situation where the RSA Operation does not work
1146 * and the command blocks must be generated by hand.
1148 * @param key_p RO: Pointer to the key object.
1154 * number of commands necessary
1160 * The key pointer is valid. We assume this has been checked by the API.
1161 *****************************************************************************/
1162 unsigned int cb_RSADecryptOperations(const N8_RSAKeyObject_t
*key_p
)
1164 unsigned int ret
= 0;
1165 const unsigned int USING_SKS_NUM_CMDS
= 3;
1166 const unsigned int USING_RSA_OPERATION_NUM_CMDS
= 4;
1167 const unsigned int USING_RSA_WORKAROUND_NUM_CMDS
= 13;
1169 if (key_p
->keyType
== N8_PRIVATE_SKS
)
1171 ret
= USING_SKS_NUM_CMDS
;
1173 else if (key_p
->keyType
== N8_PRIVATE
)
1175 ret
= N8_CB_EXPONENTIATE_NUMCMDS
;
1177 else if (cb_RSAOperationSupported(key_p
))
1179 ret
= USING_RSA_OPERATION_NUM_CMDS
;
1183 ret
= USING_RSA_WORKAROUND_NUM_CMDS
;
1186 } /* cb_RSADecryptOperations */
1188 /*****************************************************************************
1189 * cb_rsaPublicDecrypt
1190 *****************************************************************************/
1192 * @brief Creates the command blocks to compute a public decrypt for
1193 * openssl. This command computes the pre-computes ComputeCX and
1194 * ComputeRmodX and then performs the exponentiation
1196 * @param req_p RO: Pointer to request
1197 * @param modulus RO: modulus (n)
1198 * @param modulus_length_bytes RO: length of modulus in bytes
1199 * @param origMsg_a RO: Physical address of original message
1200 * @param result_a RO: Physical address of result buffer
1201 * @param exponent_a RO: Physical address of exponent (key)
1202 * @param exp_length_bytes RO: length of exponent in bytes
1203 * @param cb_p WO: command block pointer
1204 * @param unitID RO: execution unit identifier
1207 * returnResult - returns N8_STATUS_OK if successful or Error value.
1210 * N8_INVALID_OBJECT - command block pointer is NULL<BR>
1211 * N8_MALLOC_FAILED - memory allocation failed<BR>
1215 *****************************************************************************/
1216 N8_Status_t
cb_rsaPublicDecrypt(const API_Request_t
*req_p
,
1217 const uint32_t modulus
,
1218 const unsigned int modulus_length_bytes
,
1219 const uint32_t origMsg_a
,
1220 const uint32_t result_a
,
1221 const uint32_t exponent_a
,
1222 const unsigned int exp_length_bytes
,
1223 PK_CMD_BLOCK_t
*cb_p
,
1224 const N8_Unit_t unitID
)
1227 PK_CMD_BLOCK_t
*math_wr_ptr
;
1228 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
1230 uint32_t modulus_length_digits
;
1231 uint32_t exp_length_digits
;
1234 N8_Status_t ret
= N8_STATUS_OK
;
1239 * Initialize the offset values. These are to address temporary
1240 * storage in the BNC. The offsets accomodate operand sizes up to
1243 * The BNC layout will look like the following:
1245 * -----------------------------------
1246 * 0: results 2 digits
1247 * -----------------------------------
1248 * 1: t = p[0]^-1 2 digits
1249 * -----------------------------------
1250 * 2: 2**128 2 digits
1251 * -----------------------------------
1252 * 3: p modulus_length
1253 * -----------------------------------
1256 modulus_length_digits
= BYTES_TO_PKDIGITS(modulus_length_bytes
);
1257 exp_length_digits
= BYTES_TO_PKDIGITS(exp_length_bytes
);
1260 * Initialize the offset values. These are to address temporary
1261 * storage in the BNC. The offsets accomodate operand sizes up to
1264 for (i
= 0; i
< sizeof(offset
)/sizeof(unsigned int); i
++)
1266 offset
[i
] = i
* modulus_length_digits
;
1269 /* 1. Compute cX = -(p[0]^-1 mod 2^128) mod 2^128 */
1270 /* 2. Compute R mod X */
1271 /* 3. Compute o * Rmodn mod n */
1273 /*Note - offset and slot mean the same thing */
1277 * 1) Construct a command to load n to slot[1]
1279 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) cb_p
;
1280 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1281 ldst_wr_ptr
->r_offset
= offset
[1];
1282 ldst_wr_ptr
->data_addr_ls
= modulus
;
1283 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
1286 /* Construct a command to load a 2-digit 2^128 to Slot 2*/
1288 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1289 ldst_wr_ptr
->r_offset
= offset
[2];
1290 ldst_wr_ptr
->data_addr_ls
= bnc_2_D_ga
;
1291 ldst_wr_ptr
->data_length
= PKDIGITS_TO_BYTES(2);
1294 /* Construct a command for the operation t = n[0]^-1 mod 2^128 to Slot 3 */
1295 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
1296 math_wr_ptr
->opcode_si
= PK_Cmd_Inverse_A_Mod_M
;
1297 math_wr_ptr
->r_offset
= offset
[3];
1298 math_wr_ptr
->m_length_offset
=
1299 (2 << PK_Cmd_Length_Shift
) | offset
[2];
1300 math_wr_ptr
->a_length_offset
=
1301 (1 << PK_Cmd_Length_Shift
) | (offset
[1] + modulus_length_digits
- 1);
1304 /* Construct a command for the operation cX = -t mod 2^128 to Slot 3 */
1306 math_wr_ptr
->opcode_si
= PK_Cmd_Minus_A_Mod_M
;
1307 math_wr_ptr
->r_offset
= offset
[3];
1308 math_wr_ptr
->m_length_offset
=
1309 (2 << PK_Cmd_Length_Shift
) | offset
[2];
1310 math_wr_ptr
->a_length_offset
=
1311 (1 << PK_Cmd_Length_Shift
) | (offset
[3] + 1);
1313 /* 5: Construct a command for the operation R mod X */
1314 /* math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1); */
1316 math_wr_ptr
->opcode_si
= PK_Cmd_R_Mod_M
;
1317 math_wr_ptr
->r_offset
= offset
[2];
1318 math_wr_ptr
->m_length_offset
=
1319 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1];
1322 * Compute o * R mod n (mod n)
1326 * 6) Construct a command to load the original message to offset[0]
1328 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
1329 /* ldst_wr_ptr++; */
1330 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1331 ldst_wr_ptr
->r_offset
= offset
[0];
1332 ldst_wr_ptr
->data_addr_ls
= origMsg_a
;
1333 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
1336 * 7) Construct a command for the operation o * Rmodn mod n to offset[0]
1338 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
1339 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
1340 math_wr_ptr
->r_offset
= offset
[0];
1341 math_wr_ptr
->m_length_offset
=
1342 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1];
1343 math_wr_ptr
->a_length_offset
=
1344 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[0];
1345 math_wr_ptr
->b_length_offset
=
1346 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[2];
1353 * 8) Construct a command to load e to offset[4]
1355 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
1356 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
1357 ldst_wr_ptr
->r_offset
= offset
[4];
1358 ldst_wr_ptr
->data_addr_ls
= exponent_a
;
1359 ldst_wr_ptr
->data_length
= exp_length_bytes
;
1362 * 9) Construct a command for the operation o^e mod n to offset[0]
1364 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
1365 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
1366 math_wr_ptr
->r_offset
= offset
[0];
1367 math_wr_ptr
->m_length_offset
=
1368 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[1];
1369 math_wr_ptr
->a_length_offset
=
1370 (modulus_length_digits
<< PK_Cmd_Length_Shift
) | offset
[0];
1371 math_wr_ptr
->b_length_offset
= (exp_length_digits
<< PK_Cmd_Length_Shift
) | offset
[4];
1372 /* take the least significant digit of the cn result */
1373 math_wr_ptr
->c_offset
= offset
[3]+1;
1376 * 10) Construct a command to store o^e mod n from offset[0]
1378 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
1379 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
1380 ldst_wr_ptr
->r_offset
= offset
[0];
1381 ldst_wr_ptr
->data_addr_ls
= result_a
;
1382 ldst_wr_ptr
->data_length
= modulus_length_bytes
;
1384 DBG_PRINT_PK_CMD_BLOCKS("compute public precompute whaley-style",
1385 req_p
->PK_CommandBlock_ptr
,
1389 } /* cb_compute_public_decrypt */
1391 /**************************************************
1393 **************************************************/
1395 /*****************************************************************************
1396 * allocateBNCConstants
1397 *****************************************************************************/
1399 * @brief Sets addresses for constants allocated in kernel space that are
1400 * needed for various commands.
1402 * Some command need one of two constants to be loaded into the BNC. One is the
1403 * constant '1', in a single BNC digit. This is 'bnc_one'. The other is the
1404 * value 2^D where D is the size in bits of a BNC digit. This changes whether
1405 * the actual hardware or FPGA is in use. Note the values needed are:<br>
1406 * bnc_one = 0001 (for the case where D=4)<BR>
1407 * bnc_2_D = 0001 0000<BR>
1408 * We will take advantage of this by allocating two digits and setting the
1409 * values. In actuality, bnc_one and bnc_2_D will point to the same memory but
1410 * the length used will determine the value.
1412 * @param bncAddress RO: address of BNC constants allocated by
1418 * Return codes - N8_STATUS_OK
1423 *****************************************************************************/
1424 N8_Status_t
allocateBNCConstants(unsigned long bncAddress
)
1426 N8_Status_t ret
= N8_STATUS_OK
;
1428 bnc_one_ga
= bncAddress
;
1429 bnc_2_D_ga
= bncAddress
;
1432 } /* allocateBNCConstants */
1434 static N8_Boolean_t
cb_RSAOperationSupported(const N8_RSAKeyObject_t
*key_p
)
1436 N8_Boolean_t ret
= N8_FALSE
;
1438 if ((key_p
->pLength
== key_p
->qLength
) &&
1439 ((key_p
->pLength
+key_p
->qLength
) == key_p
->privateKeyLength
) &&
1440 ((key_p
->pDigits
+key_p
->qDigits
) == key_p
->privateKeyDigits
))
1445 } /* RSAOperationSupported */