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_pk_ops.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
38 * @brief Implementation of PKP Base Operations
40 * The set of routines implemented here allow direct user access to PKP
41 * operations on the chip. They include:
46 * N8_ModAdditiveInverse
47 * N8_ModMultiplicativeInverse
49 * N8_ModExponentiation
50 *****************************************************************************/
51 /*****************************************************************************
53 * 06/11/02 bac Changed return codes to be N8_INVALID_VALUE when (a >= b)
54 * instead of N8_INVALID_INPUT_SIZE. (Bug #794)
55 * 05/20/02 brr Free the request for all error conditions.
56 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
57 * 05/07/02 bac Original version.
58 ****************************************************************************/
59 /** @defgroup pkops PKP Base Operations
63 #include "n8_pub_pk.h"
64 #include "n8_cb_pk_ops.h"
65 #include "n8_cb_rsa.h"
66 #include "n8_enqueue_common.h"
67 #include "n8_API_Initialize.h"
72 /*****************************************************************************
74 *****************************************************************************/
76 * @brief Given a N8_SizedBuffer_t whose value may or may not have leading
77 * zeros, return one guaranteed not to have leading zeros.
79 * <More detailed description of the function including any unusual algorithms
80 * or suprising details.>
82 * @param in_p RO: Pointer to original buffer
83 * @param out_p RW: Pointer to output buffer
93 * in_p and out_p are non-null
94 *****************************************************************************/
95 static void stripLeadingZeros(const N8_SizedBuffer_t
*in_p
,
96 N8_SizedBuffer_t
*out_p
)
99 out_p
->lengthBytes
= in_p
->lengthBytes
;
100 out_p
->value_p
= in_p
->value_p
;
103 while ((in_p
->value_p
[i
] == 0x0) && (i
< in_p
->lengthBytes
))
107 if (i
>= in_p
->lengthBytes
)
109 /* all of the input was zero. return a single byte of zero. */
110 out_p
->lengthBytes
= 1;
111 out_p
->value_p
= in_p
->value_p
;
115 out_p
->lengthBytes
= in_p
->lengthBytes
- i
;
116 out_p
->value_p
= &(in_p
->value_p
[i
]);
118 } /* stripLeadingZeros */
120 /*****************************************************************************
122 *****************************************************************************/
124 * @brief Preliminary checking of parameter
126 * Ensures parameter is non-null and the length is within bounds.
128 * @param op_p RO: pointer to operand
129 * @param minLength RO: minimum length
130 * @param maxLength RO: maximum length
139 * N8_INVALID_OBJECT if operand is null<br>
140 * N8_INVALID_INPUT_SIZE if length is out of bounds
144 *****************************************************************************/
145 static N8_Status_t
verifyParameter(const N8_SizedBuffer_t
*op_p
,
146 unsigned int minLength
,
147 unsigned int maxLength
)
149 N8_Status_t ret
= N8_STATUS_OK
;
152 if (op_p
== NULL
|| op_p
->value_p
== NULL
)
154 ret
= N8_INVALID_OBJECT
;
157 if (op_p
->lengthBytes
< minLength
)
159 ret
= N8_INVALID_INPUT_SIZE
;
162 if (op_p
->lengthBytes
> maxLength
)
164 ret
= N8_INVALID_INPUT_SIZE
;
167 if (op_p
->lengthBytes
> N8_PK_MAX_SIZE
)
169 ret
= N8_INVALID_INPUT_SIZE
;
175 } /* verifyParameter */
177 /*****************************************************************************
179 *****************************************************************************/
181 * @brief Verify that the value of x is less than that of y.
183 * Test to ensure the value of operand x is less than operand y.
185 * @param x_p RO: pointer to operand x
186 * @param y_p RO: pointer to operand y
192 * Status of comparison
195 * N8_STATUS_OK if the relation x < y is true
196 * N8_INVALID_OBJECT if x or y are null
197 * N8_INVALID_INPUT_SIZE if not (x < y)
200 * <description of assumptions><br>
201 *****************************************************************************/
202 static N8_Status_t
verify_x_lt_y(const N8_SizedBuffer_t
*x_p
,
203 const N8_SizedBuffer_t
*y_p
)
205 N8_Status_t ret
= N8_STATUS_OK
;
206 N8_SizedBuffer_t stripped_x
;
207 N8_SizedBuffer_t stripped_y
;
211 if (x_p
== NULL
|| x_p
->value_p
== NULL
)
213 ret
= N8_INVALID_OBJECT
;
216 if (y_p
== NULL
|| y_p
->value_p
== NULL
)
218 ret
= N8_INVALID_OBJECT
;
221 if (x_p
->lengthBytes
== 0)
223 ret
= N8_INVALID_INPUT_SIZE
;
226 /* Either x or y could have leading zeros. In order to correctly compare
227 * them, we must strip off the leading zeros before proceeding. */
228 stripLeadingZeros(x_p
, &stripped_x
);
229 stripLeadingZeros(y_p
, &stripped_y
);
231 if (stripped_x
.lengthBytes
> N8_PK_MAX_SIZE
)
233 ret
= N8_INVALID_INPUT_SIZE
;
236 if (stripped_x
.lengthBytes
> stripped_y
.lengthBytes
)
238 ret
= N8_INVALID_VALUE
;
241 /* if the lengths x and y are equal, ensure x < y */
242 if (stripped_x
.lengthBytes
== stripped_y
.lengthBytes
)
244 int cmp
= memcmp(stripped_x
.value_p
, stripped_y
.value_p
,
245 stripped_x
.lengthBytes
);
249 ret
= N8_STATUS_OK
; /* x < y */
253 ret
= N8_INVALID_VALUE
; /* x >= y */
259 } /* verify_x_lt_y */
261 /*****************************************************************************
263 *****************************************************************************/
265 * @brief Perform modular arithmetic. The actual operation is specified by the
266 * shifted_opcode argument.
268 * This command generator may be used for operations requiring zero, one, or two
270 * result = R mod m (zero operands)
271 * result = a mod m (one operand)
272 * result = (a <operation> b) mod m (two operands)
274 * @param a_p RO: a operand
275 * @param b_p RO: b operand
276 * @param modulus_p RO: modulus
277 * @param result_p RW: results
278 * @param unitID RO: unit (chip) specifier
279 * @param shifted_opcode RO: opcode for the operation to be used. The
280 * opcode is to be shifted left appropriate for
281 * insertion into command block as is. This
282 * allows the use of the #defines already used
284 * @param event_p RW: event
290 * Status. N8_STATUS_OK if successful. Error condition otherwise.
293 * None generated directly.
297 *****************************************************************************/
298 static N8_Status_t
n8_pk_gen_command(const N8_SizedBuffer_t
*a_p
,
299 const N8_SizedBuffer_t
*b_p
,
300 const N8_SizedBuffer_t
*modulus_p
,
301 N8_SizedBuffer_t
*result_p
,
302 const N8_Unit_t unitID
,
303 const uint32_t shifted_opcode
,
306 N8_Status_t ret
= N8_STATUS_OK
;
307 API_Request_t
*req_p
= NULL
;
309 N8_Buffer_t
*k_a_op_p
= NULL
;
310 N8_Buffer_t
*k_b_op_p
= NULL
;
311 N8_Buffer_t
*k_modulus_p
= NULL
;
312 N8_Buffer_t
*k_result_p
= NULL
;
316 uint32_t k_modulus_a
;
320 unsigned int numCommands
;
321 unsigned int a_length_bytes
;
322 unsigned int b_length_bytes
;
323 unsigned int max_length_bytes
;
329 /* ensure the modulus_p is not null before accessing it. */
330 CHECK_OBJECT(modulus_p
, ret
);
331 ret
= verifyParameter(modulus_p
, 1, modulus_p
->lengthBytes
);
333 ret
= verifyParameter(result_p
, modulus_p
->lengthBytes
, N8_PK_MAX_SIZE
);
336 /* set the length of the result to the length of the modulus */
337 result_p
->lengthBytes
= modulus_p
->lengthBytes
;
340 max_length_bytes
= N8_MAX(modulus_p
->lengthBytes
, a_p
->lengthBytes
);
344 max_length_bytes
= modulus_p
->lengthBytes
;
347 nBytes
= NEXT_WORD_SIZE(max_length_bytes
) * 4;
349 numCommands
= N8_CB_PK_OP_NUMCMDS
;
358 /* allocate user-space buffer */
359 ret
= createPKRequestBuffer(&req_p
,
362 resultHandlerGeneric
,
365 /* set the components of the kernel memory allocated:
371 k_a_op_p
= (N8_Buffer_t
*) ((int) req_p
+ req_p
->dataoffset
);
372 k_a_op_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
374 k_b_op_p
= k_a_op_p
+ NEXT_WORD_SIZE(max_length_bytes
);
375 k_b_op_a
= k_a_op_a
+ NEXT_WORD_SIZE(max_length_bytes
);
377 k_modulus_p
= k_b_op_p
+ NEXT_WORD_SIZE(max_length_bytes
);
378 k_modulus_a
= k_b_op_a
+ NEXT_WORD_SIZE(max_length_bytes
);
380 k_result_p
= k_modulus_p
+ NEXT_WORD_SIZE(max_length_bytes
);
381 k_result_a
= k_modulus_a
+ NEXT_WORD_SIZE(max_length_bytes
);
383 req_p
->copyBackTo_p
= result_p
->value_p
;
384 req_p
->copyBackFrom_p
= k_result_p
;
385 req_p
->copyBackSize
= modulus_p
->lengthBytes
;
387 /* copy the data into the kernel buffers */
388 memcpy(k_modulus_p
, modulus_p
->value_p
, modulus_p
->lengthBytes
);
391 memcpy(k_a_op_p
, a_p
->value_p
, a_p
->lengthBytes
);
392 a_length_bytes
= a_p
->lengthBytes
;
401 memcpy(k_b_op_p
, b_p
->value_p
, b_p
->lengthBytes
);
402 b_length_bytes
= b_p
->lengthBytes
;
410 ret
= cb_pk_op(req_p
, /* request pointer */
411 shifted_opcode
, /* opcode, pre-shifted */
412 k_a_op_a
, /* physical address of A */
413 a_length_bytes
, /* A length */
414 k_b_op_a
, /* physical address of B */
415 b_length_bytes
, /* B length */
416 k_modulus_a
, /* physical address of modulus */
417 modulus_p
->lengthBytes
, /* modulus length */
418 max_length_bytes
, /* max operand or modulus length */
419 k_result_a
, /* physical address of results */
420 req_p
->PK_CommandBlock_ptr
, /* pointer to command block area */
421 NULL
); /* return pointer of next
422 * command block area, or NULL */
424 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
425 HANDLE_EVENT(event_p
, req_p
, ret
);
430 * Clean up if we arrived from an error condition.
432 if (ret
!= N8_STATUS_OK
)
439 } /* n8_pk_gen_command */
444 /*****************************************************************************
445 * Two operand operations
446 *****************************************************************************/
448 /*****************************************************************************
450 *****************************************************************************/
452 * @brief Perform modular addition.
454 * result = (a + b) mod m
456 * @param a_p RO: a operand
457 * @param b_p RO: b operand
458 * @param modulus_p RO: modulus
459 * @param result_p RW: results
460 * @param unitID RO: unit (chip) specifier
461 * @param event_p RW: event
467 * Status. N8_STATUS_OK if successful. Error condition otherwise.
470 * None generated directly.
474 *****************************************************************************/
475 N8_Status_t
N8_ModAdd(const N8_SizedBuffer_t
*a_p
,
476 const N8_SizedBuffer_t
*b_p
,
477 const N8_SizedBuffer_t
*modulus_p
,
478 N8_SizedBuffer_t
*result_p
,
479 const N8_Unit_t unitID
,
482 N8_Status_t ret
= N8_STATUS_OK
;
485 ret
= verify_x_lt_y(a_p
, modulus_p
);
487 ret
= verify_x_lt_y(b_p
, modulus_p
);
489 ret
= n8_pk_gen_command(a_p
, b_p
, modulus_p
, result_p
, unitID
,
490 PK_Cmd_A_Plus_B_Mod_M
,
496 /*****************************************************************************
498 *****************************************************************************/
500 * @brief Perform modular subtraction.
502 * result = (a - b) mod m
504 * @param a_p RO: a operand
505 * @param b_p RO: b operand
506 * @param modulus_p RO: modulus
507 * @param result_p RW: results
508 * @param unitID RO: unit (chip) specifier
509 * @param event_p RW: event
515 * Status. N8_STATUS_OK if successful. Error condition otherwise.
518 * None generated directly.
522 *****************************************************************************/
523 N8_Status_t
N8_ModSubtract(const N8_SizedBuffer_t
*a_p
,
524 const N8_SizedBuffer_t
*b_p
,
525 const N8_SizedBuffer_t
*modulus_p
,
526 N8_SizedBuffer_t
*result_p
,
527 const N8_Unit_t unitID
,
530 N8_Status_t ret
= N8_STATUS_OK
;
533 ret
= verify_x_lt_y(a_p
, modulus_p
);
535 ret
= verify_x_lt_y(b_p
, modulus_p
);
537 ret
= n8_pk_gen_command(a_p
, b_p
, modulus_p
, result_p
, unitID
,
538 PK_Cmd_A_Minus_B_Mod_M
,
542 } /* N8_ModSubtract */
545 /*****************************************************************************
547 *****************************************************************************/
549 * @brief Perform modular multiplication.
551 * result = (a * b) mod m
553 * @param a_p RO: a operand
554 * @param b_p RO: b operand
555 * @param modulus_p RO: modulus
556 * @param result_p RW: results
557 * @param unitID RO: unit (chip) specifier
558 * @param event_p RW: event
564 * Status. N8_STATUS_OK if successful. Error condition otherwise.
567 * None generated directly.
571 *****************************************************************************/
572 N8_Status_t
N8_ModMultiply(const N8_SizedBuffer_t
*a_p
,
573 const N8_SizedBuffer_t
*b_p
,
574 const N8_SizedBuffer_t
*modulus_p
,
575 N8_SizedBuffer_t
*result_p
,
576 const N8_Unit_t unitID
,
579 N8_Status_t ret
= N8_STATUS_OK
;
583 ret
= verify_x_lt_y(a_p
, modulus_p
);
585 ret
= verify_x_lt_y(b_p
, modulus_p
);
587 ret
= n8_pk_gen_command(a_p
, b_p
, modulus_p
, result_p
, unitID
,
593 } /* N8_ModMultiply */
595 /*****************************************************************************
597 *****************************************************************************/
599 * @brief Calculate a mod m
603 * @param a_p RO: a operand
604 * @param modulus_p RO: modulus
605 * @param result_p RW: results
606 * @param unitID RO: unit (chip) specifier
607 * @param event_p RW: event
613 * Status. N8_STATUS_OK if successful. Error condition otherwise.
616 * None generated directly.
620 *****************************************************************************/
621 N8_Status_t
N8_Modulus(const N8_SizedBuffer_t
*a_p
,
622 const N8_SizedBuffer_t
*modulus_p
,
623 N8_SizedBuffer_t
*result_p
,
624 const N8_Unit_t unitID
,
627 N8_Status_t ret
= N8_STATUS_OK
;
631 ret
= verifyParameter(a_p
, 1, N8_PK_MAX_SIZE
);
633 ret
= n8_pk_gen_command(a_p
, NULL
, modulus_p
, result_p
, unitID
,
640 /*****************************************************************************
641 * N8_ModAdditiveInverse
642 *****************************************************************************/
644 * @brief Calculate the additive inverse of a mod m.
648 * @param a_p RO: a operand
649 * @param modulus_p RO: modulus
650 * @param result_p RW: results
651 * @param unitID RO: unit (chip) specifier
652 * @param event_p RW: event
658 * Status. N8_STATUS_OK if successful. Error condition otherwise.
661 * None generated directly.
665 *****************************************************************************/
666 N8_Status_t
N8_ModAdditiveInverse(const N8_SizedBuffer_t
*a_p
,
667 const N8_SizedBuffer_t
*modulus_p
,
668 N8_SizedBuffer_t
*result_p
,
669 const N8_Unit_t unitID
,
672 N8_Status_t ret
= N8_STATUS_OK
;
675 ret
= verify_x_lt_y(a_p
, modulus_p
);
677 ret
= n8_pk_gen_command(a_p
, NULL
, modulus_p
, result_p
, unitID
,
678 PK_Cmd_Minus_A_Mod_M
,
683 } /* N8_ModAdditiveInverse */
685 /*****************************************************************************
686 * N8_ModMultiplicativeInverse
687 *****************************************************************************/
689 * @brief Calculate the multiplicative inverse of a mod m.
691 * result = a**-1 mod m
693 * @param a_p RO: a operand
694 * @param modulus_p RO: modulus
695 * @param result_p RW: results
696 * @param unitID RO: unit (chip) specifier
697 * @param event_p RW: event
703 * Status. N8_STATUS_OK if successful. Error condition otherwise.
706 * No test is performed to ensure a and the modulus are relatively prime.
707 * The request will be submitted to the hardware. If they are not relatively
708 * prime, a N8_HARDWARE_ERROR will be generated and returned.
712 *****************************************************************************/
713 N8_Status_t
N8_ModMultiplicativeInverse(const N8_SizedBuffer_t
*a_p
,
714 const N8_SizedBuffer_t
*modulus_p
,
715 N8_SizedBuffer_t
*result_p
,
716 const N8_Unit_t unitID
,
719 N8_Status_t ret
= N8_STATUS_OK
;
722 ret
= verify_x_lt_y(a_p
, modulus_p
);
724 ret
= n8_pk_gen_command(a_p
, NULL
, modulus_p
, result_p
, unitID
,
725 PK_Cmd_Inverse_A_Mod_M
,
730 } /* N8_ModMultiplicativeInverse */
732 /*****************************************************************************
734 *****************************************************************************/
736 * @brief Perform R mod m
738 * Calculate the value R mod m where R is 2 ** (128 * digit_length(m)).
739 * The value of R is calculated by the hardware
741 * @param modulus_p RO: modulus
742 * @param result_p RW: results
743 * @param unitID RO: unit (chip) specifier
744 * @param event_p RW: event
750 * Status. N8_STATUS_OK if successful. Error condition otherwise.
753 * None generated directly
757 *****************************************************************************/
758 N8_Status_t
N8_ModR(const N8_SizedBuffer_t
*modulus_p
,
759 N8_SizedBuffer_t
*result_p
,
760 const N8_Unit_t unitID
,
763 N8_Status_t ret
= N8_STATUS_OK
;
764 ret
= n8_pk_gen_command(NULL
, NULL
, modulus_p
, result_p
, unitID
,
770 /*****************************************************************************
772 *****************************************************************************/
774 * @brief Perform modular expontiation.
776 * Results = a ** b mod m. Uses Montgomery's algorithm.
778 * @param a_p RO: a operand
779 * @param b_p RO: b operand
780 * @param modulus_p RO: modulus
781 * @param result_p RW: results
782 * @param unitID RO: chip specifier
783 * @param event_p RW: event structure
788 * Status. N8_STATUS_OK if successful. Error condition otherwise.
791 * None generated directly
795 *****************************************************************************/
796 N8_Status_t
N8_ModExponentiate(const N8_SizedBuffer_t
*a_p
,
797 const N8_SizedBuffer_t
*b_p
,
798 const N8_SizedBuffer_t
*modulus_p
,
799 N8_SizedBuffer_t
*result_p
,
800 const N8_Unit_t unitID
,
803 N8_Status_t ret
= N8_STATUS_OK
;
804 API_Request_t
*req_p
= NULL
;
806 N8_Buffer_t
*k_a_op_p
= NULL
;
807 N8_Buffer_t
*k_b_op_p
= NULL
;
808 N8_Buffer_t
*k_modulus_p
= NULL
;
809 N8_Buffer_t
*k_result_p
= NULL
;
813 uint32_t k_modulus_a
;
817 unsigned int b_length_bytes
;
824 ret
= verify_x_lt_y(a_p
, modulus_p
);
826 ret
= verifyParameter(b_p
, 1, N8_PK_MAX_SIZE
);
828 ret
= verifyParameter(modulus_p
, 1, modulus_p
->lengthBytes
);
830 ret
= verifyParameter(result_p
, modulus_p
->lengthBytes
, N8_PK_MAX_SIZE
);
833 /* set the length of the result to the length of the modulus */
834 result_p
->lengthBytes
= modulus_p
->lengthBytes
;
835 nBytes
= NEXT_WORD_SIZE(modulus_p
->lengthBytes
) * 4;
837 /* allocate user-space buffer */
838 ret
= createPKRequestBuffer(&req_p
,
840 N8_CB_EXPONENTIATE_NUMCMDS
,
841 resultHandlerGeneric
,
844 /* set the components of the kernel memory allocated:
850 k_a_op_p
= (N8_Buffer_t
*) ((int) req_p
+ req_p
->dataoffset
);
851 k_a_op_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
853 k_b_op_p
= k_a_op_p
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
854 k_b_op_a
= k_a_op_a
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
856 k_modulus_p
= k_b_op_p
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
857 k_modulus_a
= k_b_op_a
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
859 k_result_p
= k_modulus_p
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
860 k_result_a
= k_modulus_a
+ NEXT_WORD_SIZE(modulus_p
->lengthBytes
);
862 req_p
->copyBackTo_p
= result_p
->value_p
;
863 req_p
->copyBackFrom_p
= k_result_p
;
864 req_p
->copyBackSize
= modulus_p
->lengthBytes
;
866 /* copy the data into the kernel buffers */
867 memcpy(k_modulus_p
, modulus_p
->value_p
, modulus_p
->lengthBytes
);
868 /* create a buffer that is modulus length long and filled with leading
870 memset(k_a_op_p
, 0, modulus_p
->lengthBytes
);
871 p
= k_a_op_p
+ modulus_p
->lengthBytes
- a_p
->lengthBytes
;
872 memcpy(p
, a_p
->value_p
, a_p
->lengthBytes
);
874 memcpy(k_b_op_p
, b_p
->value_p
, b_p
->lengthBytes
);
875 b_length_bytes
= b_p
->lengthBytes
;
877 ret
= cb_exponentiate(req_p
, /* request pointer */
878 k_a_op_a
, /* physical address of A */
879 k_modulus_a
, /* physical address of
881 modulus_p
->lengthBytes
, /* modulus length */
882 k_b_op_a
, /* physical address of B */
883 b_length_bytes
, /* B length */
884 k_result_a
, /* physical address of
886 req_p
->PK_CommandBlock_ptr
, /* pointer to command
888 unitID
); /* unit specifier */
890 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
891 HANDLE_EVENT(event_p
, req_p
, ret
);
896 * Clean up if we arrived from an error condition.
898 if (ret
!= N8_STATUS_OK
)
904 } /* N8_ModExponentiate */