1/*-
2 * Copyright (C) 2001-2003 by NBMK Encryption Technologies.
3 * All rights reserved.
4 *
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:
13 *
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 *
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.
21 *
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.
33 */
34
35static char const n8_id[] = "$Id: n8_cb_dsa.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36/*****************************************************************************/
37/** @file n8_cb_dsa.c
38 *  @brief DSA Command Block Generator
39 *
40 * Generates all command blocks for DSA-related functions.
41 *
42 *****************************************************************************/
43
44/*****************************************************************************
45 * Revision history:
46 * 09/10/02 brr   Set command complete bit on last command block.
47 * 02/20/02 brr   Removed references to the queue structure.
48 * 11/12/01 hml   Fixed some debugging code.
49 * 10/31/01 bac   Added support for SKS.
50 * 09/14/01 bac   Use new DBG_PRINT_PK_CMD_BLOCKS macros.
51 * 08/24/01 bac   Changed all methods to accept the pre-allocated command
52 *                buffer.
53 * 07/30/01 bac   Pass queue pointer to all length calculation macros.
54 * 07/12/01 bac   Removed unused variables.
55 * 07/13/01 mel   Fixed bug in cb_dsaVerify:
56 *                command loaded wrong number of gR_mod_p bytes.
57 * 06/28/01 mel   Fixed bug (kernel memory usage).
58 *                Added comments.
59 * 06/28/01 bac   Minor typo corrections.
60 * 06/26/01 bac   Even more on conversion to use physical memory.
61 * 06/25/01 bac   More on conversion to use physical memory.
62 * 06/20/01 mel   Corrected use of kernel memory.
63 * 05/22/01 mel   Original version.
64 ****************************************************************************/
65/** @defgroup cb_dsa DSA Command Block Generator
66 */
67
68#include "n8_common.h"
69#include "n8_pk_common.h"
70#include "n8_pub_errors.h"
71#include "n8_cb_dsa.h"
72#include "n8_util.h"
73
74/* #define ZERO_CMD_BLOCK(X) memset((X), 0, sizeof(PK_CMD_BLOCK_t)) */
75#define ZERO_CMD_BLOCK(X)
76
77/*****************************************************************************
78 * cb_computeGRmodX
79 *****************************************************************************/
80/** @ingroup cb_dsa
81 * @brief  Creates the command blocks to compute the value for gR mod X
82 *
83 *
84 *  @param req_p                    RW:  Pointer to command
85 *                                       blocks.
86 *  @param key                      RO:  pointer to phisical addresses of DSAObject.
87 *  @param modulusDigits            RO:  number of digits in modulus p.
88 *
89 * @return
90 *    ret - returns N8_STATUS_OK if successful or Error value.
91 *
92 * @par Errors
93 *          N8_INVALID_OBJECT   -   command block pointer is NULL<BR>
94 *          N8_MALLOC_FAILED    -   memory allocation failed<BR>
95 *
96 * @par Assumptions
97 *    None.<br>
98 *****************************************************************************/
99
100N8_Status_t cb_computeGRmodX(API_Request_t *req_p,
101                             const int modulusDigits,
102                             uint32_t g_a,
103                             uint32_t X_a,
104                             uint32_t res_a,
105                             PK_CMD_BLOCK_t *cmdBuf_p,
106                             PK_CMD_BLOCK_t **next_cmdBuf_p)
107{
108   PK_CMD_BLOCK_t         *math_wr_ptr = NULL;
109   PK_LDST_CMD_BLOCK_t    *ldst_wr_ptr = NULL;
110
111   uint32_t             slot0, slot1, slot2, slot3;
112
113   N8_Status_t ret = N8_STATUS_OK;
114
115   do
116   {
117      CHECK_OBJECT(req_p, ret);
118
119      /* Initialize the slot values.  These are to address temporary
120         storage in the BNC.  The slots accomodate operand sizes up to
121         the key length */
122      slot0 = 0;
123      slot1 = modulusDigits;
124      slot2 = modulusDigits * 2;
125      slot3 = modulusDigits * 3;
126
127      /* Compute gR mod p */
128      /* 1) Construct a command to load p */
129      /*
130       * slot0    slot1   slot2   slot3
131       *            p
132       */
133      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) cmdBuf_p;
134      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
135      ldst_wr_ptr->r_offset = slot1;
136      ldst_wr_ptr->data_addr_ls = X_a;
137      ldst_wr_ptr->data_length = PK_DSA_P_Byte_Length(modulusDigits);
138
139      /* 2) Construct a command to load g */
140      /*
141       * slot0    slot1   slot2   slot3
142       *            p       g
143       */
144      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
145      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
146      ldst_wr_ptr->r_offset = slot2;
147      ldst_wr_ptr->data_addr_ls = g_a;
148      ldst_wr_ptr->data_length = PK_DSA_G_Byte_Length(modulusDigits);
149
150      /* 3) Construct a command for the operation R mod p */
151      /*
152       * slot0    slot1   slot2   slot3
153       *            p       g      R mod p
154       */
155      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
156      math_wr_ptr->opcode_si = PK_Cmd_R_Mod_M;
157      math_wr_ptr->r_offset = slot3;
158      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
159                                      PK_Cmd_Length_Shift) | slot1;
160
161      /* 4) Construct a command for the operation g * Rmodp mod p */
162      /*
163       * slot0    slot1   slot2   slot3
164       * gRmodp     p       g      R mod p
165       */
166      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
167      math_wr_ptr->opcode_si = PK_Cmd_AB_Mod_M;
168      math_wr_ptr->r_offset = slot0;
169      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
170                                      PK_Cmd_Length_Shift) | slot1;
171      math_wr_ptr->a_length_offset = (PK_DSA_G_BNC_Length(modulusDigits) <<
172                                      PK_Cmd_Length_Shift) | slot2;
173      math_wr_ptr->b_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
174                                      PK_Cmd_Length_Shift) | slot3;
175
176      /* 5) Construct a command to store gR mod p  */
177      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
178      ldst_wr_ptr->opcode_si = PK_Cmd_Store_R;
179      ldst_wr_ptr->r_offset = slot0;
180      ldst_wr_ptr->data_addr_ls = res_a;
181      ldst_wr_ptr->data_length = PK_DSA_GR_MOD_P_Byte_Length(modulusDigits);
182
183      /* save next address for future use */
184      *next_cmdBuf_p = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
185
186      DBG(("Compute gR mod X\n"));
187/*      DBG_PRINT_CMD_BLOCKS("Compute gR mod X",
188                           (PK_CMD_BLOCK_t *) req_p->PK_CommandBlock_ptr,
189                           N8_CB_COMPUTE_GRMODX_NUMCMDS);  */
190   } while (FALSE);
191
192   return ret;
193} /* computeGRmodX */
194
195/*****************************************************************************
196 * cb_dsaSign
197 *****************************************************************************/
198/** @ingroup cb_dsa
199 * @brief  Creates the command blocks to compute DSA signature
200 *
201 *
202 *  @param req_p        RW:  Pointer to command
203 *                           blocks.
204 *  @param key          RO:  The previously initialized DSAKeyObject
205 *                           containing the DSA key
206 *                           materials to be used.
207 *  @param n_a          RO:  Physical address of random number n.
208 *  @param paramBlock_a RO:  Physical address of parameters block.
209 *  @param msgHash_a    RO:  Physical address of hash.
210 *  @param rValue_a     RO:  Physical address of r value.
211 *  @param sValue_a     RO:  Physical address of s value.
212 *
213 * @return
214 *    ret - returns N8_STATUS_OK if successful or Error value.
215 *
216 * @par Errors
217 *          N8_INVALID_OBJECT   -   command block pointer is NULL<BR>
218 *          N8_MALLOC_FAILED    -   memory allocation failed<BR>
219 *
220 * @par Assumptions
221 *    None.<br>
222 *****************************************************************************/
223N8_Status_t cb_dsaSign(API_Request_t *req_p,
224                       const N8_DSAKeyObject_t *key_p,
225                       uint32_t n_a,
226                       uint32_t paramBlock_a,
227                       uint32_t msgHash_a,
228                       uint32_t rValue_a,
229                       uint32_t sValue_a,
230                       PK_CMD_BLOCK_t *cmdBuf_p)
231{
232   PK_RSA_CMD_BLOCK_t     *math_wr_ptr = NULL;
233   PK_LDST_CMD_BLOCK_t    *ldst_wr_ptr = NULL;
234   uint32_t                modulusDigits;
235   uint32_t                sks_word;
236   N8_Status_t             ret = N8_STATUS_OK;
237
238   do
239   {
240      CHECK_OBJECT(req_p, ret);
241      CHECK_OBJECT(key_p, ret);
242
243      modulusDigits = BYTES_TO_PKDIGITS(key_p->modulusLength);
244
245      DBG(("constructing sign command blocks\n"));
246
247      /*  1) Construct a command to load random number n */
248      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) cmdBuf_p;
249      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
250      ldst_wr_ptr->r_offset = PK_DSA_N_BNC_Offset;
251      ldst_wr_ptr->data_addr_ls = n_a;
252      ldst_wr_ptr->data_length = PK_DSA_N_Byte_Length;
253
254      /* 2) Construct a command to load hash e1 */
255      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
256      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
257      ldst_wr_ptr->r_offset = PK_DSA_E1_BNC_Offset;
258      ldst_wr_ptr->data_addr_ls = msgHash_a;
259      ldst_wr_ptr->data_length = PK_DSA_E1_Byte_Length;
260
261      if (key_p->keyType == N8_PRIVATE_SKS)
262      {
263         /* we are using the sks.  set the sks_word variable to the correct
264          * offset.  We do not need to load the DSA parameter block as it is
265          * already in the SKS. */
266         sks_word = key_p->SKSKeyHandle.sks_offset;
267      }
268      else
269      {
270         /* 3) Construct a command to load the DSA parameter block */
271         ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
272         ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
273         ldst_wr_ptr->r_offset = PK_DSA_P_BNC_Offset;
274         ldst_wr_ptr->data_addr_ls = paramBlock_a;
275         ldst_wr_ptr->data_length = PK_DSA_Param_Byte_Length(modulusDigits);
276
277         sks_word = PK_Cmd_N_Mask;
278      }
279
280      /* 4) Construct a command for the DSA operation */
281      math_wr_ptr = (PK_RSA_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
282      math_wr_ptr->opcode_si = PK_Cmd_DSA_Sign_Op;
283      math_wr_ptr->sks = sks_word | (modulusDigits << PK_Cmd_Key_Length_Shift);
284
285      /* 5) Construct a command to store r */
286      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
287      ldst_wr_ptr->opcode_si = PK_Cmd_Store_R;
288      ldst_wr_ptr->r_offset = PK_DSA_R_BNC_Offset;
289      ldst_wr_ptr->data_addr_ls = rValue_a;
290      ldst_wr_ptr->data_length = PK_DSA_R_Byte_Length;
291
292      /* 6) Construct a command to store s */
293      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
294      ldst_wr_ptr->opcode_si = PK_Cmd_Store_R | PK_Cmd_SI_Mask;
295      ldst_wr_ptr->r_offset = PK_DSA_S_BNC_Offset;
296      ldst_wr_ptr->data_addr_ls = sValue_a;
297      ldst_wr_ptr->data_length = PK_DSA_S_Byte_Length;
298
299
300      DBG_PRINT_PK_CMD_BLOCKS("DSA sign",
301                              req_p->PK_CommandBlock_ptr,
302                              N8_CB_DSA_SIGN_NUMCMDS(key_p));
303   } while (FALSE);
304   return ret;
305}
306
307/*****************************************************************************
308 * cb_dsaVerify
309 *****************************************************************************/
310/** @ingroup cb_dsa
311 * @brief  Creates the command blocks to perform DSA verify operation
312 *
313 *                   1) Compute e = e1 mod q
314 *                   2) Compute invs = s^1 mod q
315 *                   3) Compute u1 = invs * e mod q
316 *                   4) Compute u2 = invs * r mod q
317 *                   5) Compute v1 = g^u1 mod p
318 *                   6) Compute w = y^u2 mod p
319 *                   7) Compute v3 = v1 * w mod p
320 *                   8) Compute v = v3 mod q
321 *
322 *
323 *                         Big Number Cache slot allocation
324 *
325 *               1       2       3       4       5       6       7       8
326 *   -------------------------------------------------------------------------
327 *   step 1)     q               e1
328 *               .                       e
329 *   step 2)     .               s
330 *               .      invs
331 *   step 3)     .       .               u1
332 *   step 4)     .       .       r       .
333 *               .       .       u2      .
334 *   step 5)     .      p[0]     .       .     2^128
335 *               .      p[0]^-1  .       .       .
336 *               .     -p[0]^-1  .       .       .
337 *               .       .       .       .       p                       g
338 *               .       .       .       .       .             Rmodp     .
339 *               .       .       .       .       .    gRmodp             .
340 *               .       .       .       .       .              v1
341 *   step 6)     .       .       .               .     Rmodp     .       y
342 *               .       .       .               .    yRmodp     .
343 *               .       .       .               .               .       w
344 *   step 7)     .                               .              v3
345 *   step 8)     v
346 *
347 *
348 *
349 *  @param req_p        RW:  Pointer to command
350 *                           blocks.
351 *  @param key          RO:  The previously initialized DSAKeyObject
352 *                           containing the DSA key
353 *                           materials to be used.
354 *  @param q_a          RO:  Physical address of q value.
355 *  @param cp_a         RO:  Physical address of computed cp.
356 *  @param gR_mod_p_a   RO:  Physical address of computed gRmodp.
357 *  @param p_a          RO:  Physical address of p value.
358 *  @param publicKey_a  RO:  Physical address of public key.
359 *  @param mh_a         RO:  Physical address of hash.
360 *  @param r_a          RO:  Physical address of r value.
361 *  @param s_a          RO:  Physical address of s value.
362 *  @param res_a        WO:  Physical address of result.
363 *
364 * @return
365 *    ret - returns N8_STATUS_OK if successful or Error value.
366 *
367 * @par Errors
368 *          N8_INVALID_OBJECT   -   command block pointer is NULL<BR>
369 *          N8_MALLOC_FAILED    -   memory allocation failed<BR>
370 *
371 * @par Assumptions
372 *    None.<br>
373 *****************************************************************************/
374N8_Status_t cb_dsaVerify(API_Request_t *req_p,
375                         const N8_DSAKeyObject_t *key_p,
376                         uint32_t q_a,
377                         uint32_t cp_a,
378                         uint32_t gR_mod_p_a,
379                         uint32_t p_a,
380                         uint32_t publicKey_a,
381                         uint32_t mh_a,
382                         uint32_t r_a,
383                         uint32_t s_a,
384                         uint32_t res_a,
385                         PK_CMD_BLOCK_t *cmdBuf_p)
386{
387   PK_CMD_BLOCK_t       *math_wr_ptr = NULL;
388   PK_LDST_CMD_BLOCK_t  *ldst_wr_ptr = NULL;
389
390   uint32_t             modulusDigits;
391   uint32_t             slot1, slot2, slot3, slot4;
392   uint32_t             slot5, slot6, slot7, slot8;
393
394   N8_Status_t          ret = N8_STATUS_OK;
395
396   do
397   {
398      CHECK_OBJECT(req_p, ret);
399
400      modulusDigits = BYTES_TO_PKDIGITS(key_p->modulusLength);
401
402      /* Initialize the slot values.  These are to address temporary
403         storage in the BNC.  Slots 1-4 hold 2-digit operands.
404         Slots 5-8 hold operands up to the key size in length. */
405      slot1 = 0;                                               /* q */
406      slot2 = slot1 + PK_DSA_N_BNC_Length;  /* invs */
407      slot3 = slot2 + PK_DSA_N_BNC_Length;  /* e1 */
408      slot4 = slot3 + PK_DSA_N_BNC_Length;  /*  */
409      slot5 = slot4 + modulusDigits;
410      slot6 = slot5 + modulusDigits;
411      slot7 = slot6 + modulusDigits;
412      slot8 = slot7 + modulusDigits;
413
414      /*
415       Compute e = e1 mod q
416       */
417      /* 1) Construct a command to load q */
418      /*      1       2       3       4       5       6       7       8
419
420      */
421      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) cmdBuf_p;
422      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
423      ldst_wr_ptr->r_offset = slot1;
424      ldst_wr_ptr->data_addr_ls = (unsigned int) q_a;
425      ldst_wr_ptr->data_length = PK_DSA_Q_Byte_Length;
426
427
428      /* 2)Construct a command to load e1 */
429      /*      1       2       3       4       5       6       7       8
430              q
431      */
432      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
433      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
434      ldst_wr_ptr->r_offset = slot3;
435      ldst_wr_ptr->data_addr_ls = mh_a;
436      ldst_wr_ptr->data_length = PK_DSA_E1_Byte_Length;
437
438      /* 3) Construct a command for the operation e1 mod q */
439      /*      1       2       3       4       5       6       7       8
440              q              e1
441      */
442      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
443      math_wr_ptr->opcode_si = PK_Cmd_A_Mod_M;
444      math_wr_ptr->r_offset = slot4;
445      math_wr_ptr->m_length_offset = (PK_DSA_Q_BNC_Length <<
446                                      PK_Cmd_Length_Shift) | slot1;
447      math_wr_ptr->a_length_offset = (PK_DSA_E1_BNC_Length <<
448                                      PK_Cmd_Length_Shift) | slot3;
449
450      /* Compute invs = s^-1 mod q */
451      /* 4) Construct a command to load s */
452      /*      1       2       3       4       5       6       7       8
453              q               e1   e1 mod q
454      */
455      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) math_wr_ptr + 1;
456      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
457      ldst_wr_ptr->r_offset = slot3;
458      ldst_wr_ptr->data_addr_ls = s_a;
459      ldst_wr_ptr->data_length = PK_DSA_S_Byte_Length;
460
461      /* 5) Construct a command for the operation invs = s^-1 mod q */
462      /*      1       2       3       4       5       6       7       8
463              q               s    e1 mod q
464      */
465      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
466      math_wr_ptr->opcode_si = PK_Cmd_Inverse_A_Mod_M;
467      math_wr_ptr->r_offset = slot2;
468      math_wr_ptr->m_length_offset = (PK_DSA_Q_BNC_Length <<
469                                      PK_Cmd_Length_Shift) | slot1;
470      math_wr_ptr->a_length_offset = (PK_DSA_S_BNC_Length <<
471                                      PK_Cmd_Length_Shift) | slot3;
472
473      /* Compute u1 = invs * e mod q */
474      /* 6) Construct a command for the operation u1 = invs * e mod q */
475      /*      1       2       3       4       5       6       7       8
476              q      invs     s    e1 mod q
477      */
478      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
479      math_wr_ptr->opcode_si = PK_Cmd_AB_Mod_M;
480      math_wr_ptr->r_offset = slot4;
481      math_wr_ptr->m_length_offset = (PK_DSA_Q_BNC_Length <<
482                                      PK_Cmd_Length_Shift) | slot1;
483      math_wr_ptr->a_length_offset = (PK_DSA_Q_BNC_Length <<
484                                      PK_Cmd_Length_Shift) | slot2;
485      math_wr_ptr->b_length_offset = (PK_DSA_Q_BNC_Length <<
486                                      PK_Cmd_Length_Shift) | slot4;
487
488      /* Compute u2 = invs * r mod q */
489      /* 7) Construct a command to load r */
490      /*      1       2       3       4       5       6       7       8
491              q      invs     s       u1
492      */
493      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
494      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
495      ldst_wr_ptr->r_offset = slot3;
496      ldst_wr_ptr->data_addr_ls = r_a;
497      ldst_wr_ptr->data_length = PK_DSA_R_Byte_Length;
498
499      /* 8) Construct a command for the operation u2 = invs * r mod q */
500      /*      1       2       3       4       5       6       7       8
501              q      invs     r       u1
502      */
503      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
504      math_wr_ptr->opcode_si = PK_Cmd_AB_Mod_M;
505      math_wr_ptr->r_offset = slot3;
506      math_wr_ptr->m_length_offset = (PK_DSA_Q_BNC_Length <<
507                                      PK_Cmd_Length_Shift) | slot1;
508      math_wr_ptr->a_length_offset = (PK_DSA_Q_BNC_Length <<
509                                      PK_Cmd_Length_Shift) | slot2;
510      math_wr_ptr->b_length_offset = (PK_DSA_R_BNC_Length <<
511                                      PK_Cmd_Length_Shift) | slot3;
512
513      /* Compute v1 = g^u1 mod p */
514
515      /* 9) Construct a command to load cp = -t mod 2^128 */
516      /*      1       2       3       4       5       6       7       8
517              q      invs     u2      u1
518      */
519      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
520      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
521      ldst_wr_ptr->r_offset = slot2;
522      ldst_wr_ptr->data_addr_ls = (unsigned int) cp_a;
523      ldst_wr_ptr->data_length = PK_DSA_CP_Byte_Length;
524
525      /* 10) Construct a command to load g * R mod p */
526      /*      1       2       3       4       5       6       7       8
527              q      cp       u2      u1
528      */
529      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
530      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
531      ldst_wr_ptr->r_offset = slot6;
532      ldst_wr_ptr->data_addr_ls = gR_mod_p_a;
533      ldst_wr_ptr->data_length = PK_DSA_GR_MOD_P_Byte_Length(modulusDigits);
534
535      /* 11) Construct a command to load p */
536      /*      1       2       3       4       5       6       7       8
537              q      cp       u2      u1           gR_mod_p
538      */
539      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
540      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
541      ldst_wr_ptr->r_offset = slot5;
542      ldst_wr_ptr->data_addr_ls = (unsigned int) p_a;
543      ldst_wr_ptr->data_length = PK_DSA_P_Byte_Length(modulusDigits);
544
545      /* 12) Construct a command for the operation v1 = g^u1 mod p */
546      /*      1       2       3       4       5       6       7       8
547              q      cp       u2      u1      p     gR_mod_p
548      */
549      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
550      math_wr_ptr->opcode_si = PK_Cmd_Exp_G_Mod_M;
551      math_wr_ptr->r_offset = slot7;
552      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
553                                      PK_Cmd_Length_Shift) | slot5;
554      math_wr_ptr->a_length_offset = (PK_DSA_GR_MOD_P_BNC_Length(modulusDigits) <<
555                                      PK_Cmd_Length_Shift) | slot6;
556      math_wr_ptr->b_length_offset = (PK_DSA_Q_BNC_Length <<
557                                      PK_Cmd_Length_Shift) | slot4;
558      math_wr_ptr->c_offset = slot2;
559
560
561      /* Compute w = y^u2 mod p */
562      /* 13) Construct a command to load y */
563      /*      1       2       3       4       5       6       7       8
564              q      cp       u2      u1      p     gR_mod_p  v1
565      */
566      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
567      ldst_wr_ptr->opcode_si = PK_Cmd_Load_R;
568      ldst_wr_ptr->r_offset = slot8;
569      ldst_wr_ptr->data_addr_ls = (unsigned int) publicKey_a;
570      ldst_wr_ptr->data_length = PK_DSA_Y_Byte_Length(modulusDigits);
571
572      /* 14) Construct a command for the operation R mod p */
573      /*      1       2       3       4       5       6       7       8
574              q      cp       u2      u1      p     gR_mod_p  v1    publicKey
575      */
576      math_wr_ptr = (PK_CMD_BLOCK_t *) (ldst_wr_ptr + 1);
577      math_wr_ptr->opcode_si = PK_Cmd_R_Mod_M;
578      math_wr_ptr->r_offset = slot6;
579      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
580                                      PK_Cmd_Length_Shift) | slot5;
581
582      /* 15) Construct a command for the operation yR mod p */
583      /*      1       2       3       4       5       6      7       8
584              q      cp       u2      u1      p     R_mod_p  v1    publicKey(y)
585      */
586      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
587      math_wr_ptr->opcode_si = PK_Cmd_AB_Mod_M;
588      math_wr_ptr->r_offset = slot6;
589      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
590                                      PK_Cmd_Length_Shift) | slot5;
591      math_wr_ptr->a_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
592                                      PK_Cmd_Length_Shift) | slot8;
593      math_wr_ptr->b_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
594                                      PK_Cmd_Length_Shift) | slot6;
595
596      /* 16) Construct a command for the operation w = y^u2 mod p */
597      /*      1       2       3       4       5       6       7       8
598              q      cp       u2      u1      p     yR_mod_p  v1    publicKey(y)
599      */
600      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
601      math_wr_ptr->opcode_si = PK_Cmd_Exp_G_Mod_M;
602      math_wr_ptr->r_offset = slot8;
603      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
604                                      PK_Cmd_Length_Shift) | slot5;
605      math_wr_ptr->a_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
606                                      PK_Cmd_Length_Shift) | slot6;
607      math_wr_ptr->b_length_offset = (PK_DSA_Q_BNC_Length <<
608                                      PK_Cmd_Length_Shift) | slot3;
609      math_wr_ptr->c_offset = slot2;
610
611      /* Compute v3 = v1 * w mod p */
612      /* 17) Construct a command for the operation v3 = v1 * w mod p */
613      /*      1       2       3       4       5       6       7       8
614              q      cp       u2      u1      p     yR_mod_p  v1      w
615      */
616      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
617      math_wr_ptr->opcode_si = PK_Cmd_AB_Mod_M;
618      math_wr_ptr->r_offset = slot7;
619      math_wr_ptr->m_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
620                                      PK_Cmd_Length_Shift) | slot5;
621      math_wr_ptr->a_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
622                                      PK_Cmd_Length_Shift) | slot7;
623      math_wr_ptr->b_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
624                                      PK_Cmd_Length_Shift) | slot8;
625
626      /* Compute v = v3 mod q */
627      /* 18) Construct a command for the operation v = v3 mod q */
628      /*      1       2       3       4       5       6       7       8
629              q      cp       u2      u1      p     yR_mod_p  v3      w
630      */
631      math_wr_ptr = (PK_CMD_BLOCK_t *) (math_wr_ptr + 1);
632      math_wr_ptr->opcode_si = PK_Cmd_A_Mod_M;
633      math_wr_ptr->r_offset = slot1;
634      math_wr_ptr->m_length_offset = (PK_DSA_Q_BNC_Length <<
635                                      PK_Cmd_Length_Shift) | slot1;
636      math_wr_ptr->a_length_offset = (PK_DSA_P_BNC_Length(modulusDigits) <<
637                                      PK_Cmd_Length_Shift) | slot7;
638
639      /* 19) Construct a command to store v  */
640      /*      1       2       3       4       5       6       7       8
641              v      cp       u2      u1      p     yR_mod_p  v3      w
642      */
643      ldst_wr_ptr = (PK_LDST_CMD_BLOCK_t *) (math_wr_ptr + 1);
644      ldst_wr_ptr->opcode_si = PK_Cmd_Store_R | PK_Cmd_SI_Mask;
645      ldst_wr_ptr->r_offset = slot1;
646      ldst_wr_ptr->data_addr_ls = res_a;
647      ldst_wr_ptr->data_length = PK_DSA_Q_Byte_Length;
648
649
650      DBG_PRINT_PK_CMD_BLOCKS("DSA verify",
651                              (PK_CMD_BLOCK_t *) req_p->PK_CommandBlock_ptr,
652                              N8_CB_DSA_VERIFY_NUMCMDS);
653   } while (FALSE);
654
655   return ret;
656
657} /* cb_dsaVerify */
658
659/*****************************************************************************
660 * cb_DSASignOperations
661 *****************************************************************************/
662/** @ingroup cb_rsa
663 * @brief Calculate the number of operations required for an DSA Sign.
664 *
665 * The operations used to perform an DSA Sign depend upon the key type.  If the
666 * type is N8_PRIVATE_SKS, then the DSA Sign Operation will use the parameter
667 * block taken from the SKS, saving a load.  If it is not SKS then the parameter
668 * block must be manually loaded and used.
669 *
670 *  @param key_p               RO:  Pointer to the key object.
671 *
672 * @par Externals
673 *    None
674 *
675 * @return
676 *    number of commands necessary
677 *
678 * @par Errors
679 *    None
680 *
681 * @par Assumptions
682 *    The key pointer is valid.  We assume this has been checked by the API.
683 *****************************************************************************/
684unsigned int cb_DSASignOperations(const N8_DSAKeyObject_t *key_p)
685{
686   unsigned int ret = 0;
687   const int NOT_USING_SKS_NUM_COMMANDS = 6;
688
689   if (key_p->keyType == N8_PRIVATE_SKS)
690   {
691      ret = NOT_USING_SKS_NUM_COMMANDS - 1;
692   }
693   else
694   {
695      ret = NOT_USING_SKS_NUM_COMMANDS;
696   }
697   return ret;
698} /* cb_RSADecryptOperations */
699
700