Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_pk_ops.c
blob0c6e7c03016745bccf5e9625ddf4646ae2cec20f
1 /*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
5 * NBMK Encryption Technologies provides no support of any kind for
6 * this software. Questions or concerns about it may be addressed to
7 * the members of the relevant open-source community at
8 * <tech-crypto@netbsd.org>.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions are
12 * met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above
18 * copyright notice, this list of conditions and the following
19 * disclaimer in the documentation and/or other materials provided
20 * with the distribution.
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 static char const n8_id[] = "$Id: n8_pk_ops.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_pk_ops.c
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:
42 * N8_ModAdd
43 * N8_ModSubtract
44 * N8_ModMultiply
45 * N8_Modulus
46 * N8_ModAdditiveInverse
47 * N8_ModMultiplicativeInverse
48 * N8_ModR
49 * N8_ModExponentiation
50 *****************************************************************************/
51 /*****************************************************************************
52 * Revision history:
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"
68 #include "n8_util.h"
70 /* Static methods */
72 /*****************************************************************************
73 * stripLeadingZeros
74 *****************************************************************************/
75 /** @ingroup pkops
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
85 * @par Externals
86 * None
89 * @par Errors
90 * None
92 * @par Assumptions
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)
98 int i;
99 out_p->lengthBytes = in_p->lengthBytes;
100 out_p->value_p = in_p->value_p;
102 i = 0;
103 while ((in_p->value_p[i] == 0x0) && (i < in_p->lengthBytes))
105 i++;
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;
113 else
115 out_p->lengthBytes = in_p->lengthBytes - i;
116 out_p->value_p = &(in_p->value_p[i]);
118 } /* stripLeadingZeros */
120 /*****************************************************************************
121 * verifyParameter
122 *****************************************************************************/
123 /** @ingroup pkops
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
132 * @par Externals
133 * None
135 * @return
136 * Status
138 * @par Errors
139 * N8_INVALID_OBJECT if operand is null<br>
140 * N8_INVALID_INPUT_SIZE if length is out of bounds
142 * @par Assumptions
143 * None
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;
155 break;
157 if (op_p->lengthBytes < minLength)
159 ret = N8_INVALID_INPUT_SIZE;
160 break;
162 if (op_p->lengthBytes > maxLength)
164 ret = N8_INVALID_INPUT_SIZE;
165 break;
167 if (op_p->lengthBytes > N8_PK_MAX_SIZE)
169 ret = N8_INVALID_INPUT_SIZE;
170 break;
172 } while (N8_FALSE);
174 return ret;
175 } /* verifyParameter */
177 /*****************************************************************************
178 * verify_x_lt_y
179 *****************************************************************************/
180 /** @ingroup pkops
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
188 * @par Externals
189 * None
191 * @return
192 * Status of comparison
194 * @par Errors
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)
199 * @par Assumptions
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;
214 break;
216 if (y_p == NULL || y_p->value_p == NULL)
218 ret = N8_INVALID_OBJECT;
219 break;
221 if (x_p->lengthBytes == 0)
223 ret = N8_INVALID_INPUT_SIZE;
224 break;
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;
234 break;
236 if (stripped_x.lengthBytes > stripped_y.lengthBytes)
238 ret = N8_INVALID_VALUE;
239 break;
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);
247 if (cmp < 0)
249 ret = N8_STATUS_OK; /* x < y */
251 else
253 ret = N8_INVALID_VALUE; /* x >= y */
256 } while (N8_FALSE);
258 return ret;
259 } /* verify_x_lt_y */
261 /*****************************************************************************
262 * n8_pk_gen_command
263 *****************************************************************************/
264 /** @ingroup pkops
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
269 * operands, e.g.
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
283 * elsewhere.
284 * @param event_p RW: event
286 * @par Externals
287 * None
289 * @return
290 * Status. N8_STATUS_OK if successful. Error condition otherwise.
292 * @par Errors
293 * None generated directly.
295 * @par Assumptions
296 * None
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,
304 N8_Event_t *event_p)
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;
314 uint32_t k_a_op_a;
315 uint32_t k_b_op_a;
316 uint32_t k_modulus_a;
317 uint32_t k_result_a;
319 unsigned int nBytes;
320 unsigned int numCommands;
321 unsigned int a_length_bytes;
322 unsigned int b_length_bytes;
323 unsigned int max_length_bytes;
327 ret = N8_preamble();
328 CHECK_RETURN(ret);
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);
332 CHECK_RETURN(ret);
333 ret = verifyParameter(result_p, modulus_p->lengthBytes, N8_PK_MAX_SIZE);
334 CHECK_RETURN(ret);
336 /* set the length of the result to the length of the modulus */
337 result_p->lengthBytes = modulus_p->lengthBytes;
338 if (a_p != NULL)
340 max_length_bytes = N8_MAX(modulus_p->lengthBytes, a_p->lengthBytes);
342 else
344 max_length_bytes = modulus_p->lengthBytes;
347 nBytes = NEXT_WORD_SIZE(max_length_bytes) * 4;
349 numCommands = N8_CB_PK_OP_NUMCMDS;
350 if (b_p == NULL)
352 numCommands--;
354 if (a_p == NULL)
356 numCommands--;
358 /* allocate user-space buffer */
359 ret = createPKRequestBuffer(&req_p,
360 unitID,
361 numCommands,
362 resultHandlerGeneric,
363 nBytes);
364 CHECK_RETURN(ret);
365 /* set the components of the kernel memory allocated:
366 * k_a_op_p
367 * k_b_op_p
368 * k_modulus_p
369 * k_result_p
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);
389 if (a_p != NULL)
391 memcpy(k_a_op_p, a_p->value_p, a_p->lengthBytes);
392 a_length_bytes = a_p->lengthBytes;
394 else
396 k_a_op_a = 0x0;
397 a_length_bytes = 0;
399 if (b_p != NULL)
401 memcpy(k_b_op_p, b_p->value_p, b_p->lengthBytes);
402 b_length_bytes = b_p->lengthBytes;
404 else
406 k_b_op_a = 0x0;
407 b_length_bytes = 0;
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 */
423 CHECK_RETURN(ret);
424 QUEUE_AND_CHECK(event_p, req_p, ret);
425 HANDLE_EVENT(event_p, req_p, ret);
427 } while (N8_FALSE);
430 * Clean up if we arrived from an error condition.
432 if (ret != N8_STATUS_OK)
434 freeRequest(req_p);
437 return ret;
439 } /* n8_pk_gen_command */
442 /* Public methods */
444 /*****************************************************************************
445 * Two operand operations
446 *****************************************************************************/
448 /*****************************************************************************
449 * N8_ModAdd
450 *****************************************************************************/
451 /** @ingroup pkops
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
463 * @par Externals
464 * None
466 * @return
467 * Status. N8_STATUS_OK if successful. Error condition otherwise.
469 * @par Errors
470 * None generated directly.
472 * @par Assumptions
473 * None
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,
480 N8_Event_t *event_p)
482 N8_Status_t ret = N8_STATUS_OK;
485 ret = verify_x_lt_y(a_p, modulus_p);
486 CHECK_RETURN(ret);
487 ret = verify_x_lt_y(b_p, modulus_p);
488 CHECK_RETURN(ret);
489 ret = n8_pk_gen_command(a_p, b_p, modulus_p, result_p, unitID,
490 PK_Cmd_A_Plus_B_Mod_M,
491 event_p);
492 } while (N8_FALSE);
493 return ret;
494 } /* N8_ModAdd */
496 /*****************************************************************************
497 * N8_ModSubtract
498 *****************************************************************************/
499 /** @ingroup pkops
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
511 * @par Externals
512 * None
514 * @return
515 * Status. N8_STATUS_OK if successful. Error condition otherwise.
517 * @par Errors
518 * None generated directly.
520 * @par Assumptions
521 * None
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,
528 N8_Event_t *event_p)
530 N8_Status_t ret = N8_STATUS_OK;
533 ret = verify_x_lt_y(a_p, modulus_p);
534 CHECK_RETURN(ret);
535 ret = verify_x_lt_y(b_p, modulus_p);
536 CHECK_RETURN(ret);
537 ret = n8_pk_gen_command(a_p, b_p, modulus_p, result_p, unitID,
538 PK_Cmd_A_Minus_B_Mod_M,
539 event_p);
540 } while (N8_FALSE);
541 return ret;
542 } /* N8_ModSubtract */
545 /*****************************************************************************
546 * N8_ModMultiply
547 *****************************************************************************/
548 /** @ingroup pkops
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
560 * @par Externals
561 * None
563 * @return
564 * Status. N8_STATUS_OK if successful. Error condition otherwise.
566 * @par Errors
567 * None generated directly.
569 * @par Assumptions
570 * None
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,
577 N8_Event_t *event_p)
579 N8_Status_t ret = N8_STATUS_OK;
583 ret = verify_x_lt_y(a_p, modulus_p);
584 CHECK_RETURN(ret);
585 ret = verify_x_lt_y(b_p, modulus_p);
586 CHECK_RETURN(ret);
587 ret = n8_pk_gen_command(a_p, b_p, modulus_p, result_p, unitID,
588 PK_Cmd_AB_Mod_M,
589 event_p);
590 } while (N8_FALSE);
591 return ret;
593 } /* N8_ModMultiply */
595 /*****************************************************************************
596 * N8_Modulus
597 *****************************************************************************/
598 /** @ingroup pkops
599 * @brief Calculate a mod m
601 * result = 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
609 * @par Externals
610 * None
612 * @return
613 * Status. N8_STATUS_OK if successful. Error condition otherwise.
615 * @par Errors
616 * None generated directly.
618 * @par Assumptions
619 * None
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,
625 N8_Event_t *event_p)
627 N8_Status_t ret = N8_STATUS_OK;
631 ret = verifyParameter(a_p, 1, N8_PK_MAX_SIZE);
632 CHECK_RETURN(ret);
633 ret = n8_pk_gen_command(a_p, NULL, modulus_p, result_p, unitID,
634 PK_Cmd_A_Mod_M,
635 event_p);
636 } while (N8_FALSE);
637 return ret;
638 } /* N8_Modulus */
640 /*****************************************************************************
641 * N8_ModAdditiveInverse
642 *****************************************************************************/
643 /** @ingroup pkops
644 * @brief Calculate the additive inverse of a mod m.
646 * result = -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
654 * @par Externals
655 * None
657 * @return
658 * Status. N8_STATUS_OK if successful. Error condition otherwise.
660 * @par Errors
661 * None generated directly.
663 * @par Assumptions
664 * None
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,
670 N8_Event_t *event_p)
672 N8_Status_t ret = N8_STATUS_OK;
675 ret = verify_x_lt_y(a_p, modulus_p);
676 CHECK_RETURN(ret);
677 ret = n8_pk_gen_command(a_p, NULL, modulus_p, result_p, unitID,
678 PK_Cmd_Minus_A_Mod_M,
679 event_p);
680 } while (N8_FALSE);
681 return ret;
683 } /* N8_ModAdditiveInverse */
685 /*****************************************************************************
686 * N8_ModMultiplicativeInverse
687 *****************************************************************************/
688 /** @ingroup pkops
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
699 * @par Externals
700 * None
702 * @return
703 * Status. N8_STATUS_OK if successful. Error condition otherwise.
705 * @par Errors
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.
710 * @par Assumptions
711 * None
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,
717 N8_Event_t *event_p)
719 N8_Status_t ret = N8_STATUS_OK;
722 ret = verify_x_lt_y(a_p, modulus_p);
723 CHECK_RETURN(ret);
724 ret = n8_pk_gen_command(a_p, NULL, modulus_p, result_p, unitID,
725 PK_Cmd_Inverse_A_Mod_M,
726 event_p);
727 } while (N8_FALSE);
728 return ret;
730 } /* N8_ModMultiplicativeInverse */
732 /*****************************************************************************
733 * N8_ModR
734 *****************************************************************************/
735 /** @ingroup pkops
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
746 * @par Externals
747 * None
749 * @return
750 * Status. N8_STATUS_OK if successful. Error condition otherwise.
752 * @par Errors
753 * None generated directly
755 * @par Assumptions
756 * None
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,
761 N8_Event_t *event_p)
763 N8_Status_t ret = N8_STATUS_OK;
764 ret = n8_pk_gen_command(NULL, NULL, modulus_p, result_p, unitID,
765 PK_Cmd_R_Mod_M,
766 event_p);
767 return ret;
768 } /* N8_ModR */
770 /*****************************************************************************
771 * N8_ModExponentiate
772 *****************************************************************************/
773 /** @ingroup pkops
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
785 * @par Externals
786 * None
788 * Status. N8_STATUS_OK if successful. Error condition otherwise.
790 * @par Errors
791 * None generated directly
793 * @par Assumptions
794 * None
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,
801 N8_Event_t *event_p)
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;
811 uint32_t k_a_op_a;
812 uint32_t k_b_op_a;
813 uint32_t k_modulus_a;
814 uint32_t k_result_a;
816 unsigned int nBytes;
817 unsigned int b_length_bytes;
818 char *p;
821 ret = N8_preamble();
822 CHECK_RETURN(ret);
824 ret = verify_x_lt_y(a_p, modulus_p);
825 CHECK_RETURN(ret);
826 ret = verifyParameter(b_p, 1, N8_PK_MAX_SIZE);
827 CHECK_RETURN(ret);
828 ret = verifyParameter(modulus_p, 1, modulus_p->lengthBytes);
829 CHECK_RETURN(ret);
830 ret = verifyParameter(result_p, modulus_p->lengthBytes, N8_PK_MAX_SIZE);
831 CHECK_RETURN(ret);
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,
839 unitID,
840 N8_CB_EXPONENTIATE_NUMCMDS,
841 resultHandlerGeneric,
842 nBytes);
843 CHECK_RETURN(ret);
844 /* set the components of the kernel memory allocated:
845 * k_a_op_p
846 * k_b_op_p
847 * k_modulus_p
848 * k_result_p
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
869 * zeros. */
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
880 * modulus */
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
885 * results */
886 req_p->PK_CommandBlock_ptr, /* pointer to command
887 * block area */
888 unitID); /* unit specifier */
889 CHECK_RETURN(ret);
890 QUEUE_AND_CHECK(event_p, req_p, ret);
891 HANDLE_EVENT(event_p, req_p, ret);
893 } while (N8_FALSE);
896 * Clean up if we arrived from an error condition.
898 if (ret != N8_STATUS_OK)
900 freeRequest(req_p);
903 return ret;
904 } /* N8_ModExponentiate */