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_dh.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
38 * @brief DSA Command Block Generator
40 * Generates all command blocks for DSA-related functions.
42 *****************************************************************************/
44 /*****************************************************************************
46 * 05/16/03 brr Eliminate obsolete include file.
47 * 09/10/02 brr Set command complete bit on last command block.
48 * 08/01/02 bac Fixed a bug where the incorrect lengths were being used in the
49 * data loads and stores. The exact length of p should be used,
50 * not the full length of the required BNC digits (i.e. should
51 * not be multiples of 16 bytes).
52 * 02/20/02 brr Removed references to the queue structure.
53 * 11/08/01 mel Added unit ID parameter to commend block calls (bug #289).
54 * 09/14/01 bac Added computation of gRmodP in cb_precomputeDHValues.
55 * Changed cb_computeGXmodp to be cb_computeGXmodp_short and
56 * cb_computeGXmodp_long. The former uses the precomputed value
57 * for gRmodP and the latter computes it. Other changes from the
59 * 09/05/01 bac cb_computeCX signature changed.
60 * 08/24/01 bac Revamp the two public routines for complete implementation.
61 * 08/01/01 bac Added queue_p to length calculations.
62 * 07/19/01 bac Fixed non-compilation problems.
63 * 07/12/01 bac Changed signatures for cb_computeGXmodp to accept uint32_t not
65 * 05/22/01 mel Original version.
66 ****************************************************************************/
67 /** @defgroup cb_dh Diffie-Hellman Command Block Generator
70 #include "n8_common.h"
71 #include "n8_pk_common.h"
72 #include "n8_pub_errors.h"
76 /*****************************************************************************
77 * cb_precomputeDHValues
78 *****************************************************************************/
80 * @brief Generate precompute values for Diffie-Hellman
82 * A series of DH computations can be made using the shared insecure values g
83 * and n. For each new DH computation a random large integer x is chosen. The
84 * DH computation is R= g^x mod p. In order to do an exponentiation in the
85 * NSP2000 hardware, the values presented are:
86 * a = g*(R mod p) mod p
88 * c = cp (as computed by cb_computeCX).
90 * To facilitate the easy computation of g**x mod n, the values for a and c are
91 * precomputed and stored in the DH Object for re-use.
93 * @param req_p RO: pointer to the request structure
94 * @param g_a RO: physical address for the g value
95 * @param p_a RO: physical address for the p value
96 * @param gRmodP_a RO: physical address for the result gRmodP (a)
97 * @param RmodP_a RO: physical address for the result gRmodP (a)
98 * @param cp_a RO: physical address for the result cp
99 * @param modulusLength RO: length of p in bytes
100 * @param cmdBuf_p RW: pointer to command buffer to be generated
111 * All result areas are of sufficient size.
112 *****************************************************************************/
113 N8_Status_t
cb_precomputeDHValues(const API_Request_t
*req_p
,
116 const uint32_t RmodP_a
,
117 const uint32_t gRmodP_a
,
119 const unsigned int modulusLengthBytes
,
120 PK_CMD_BLOCK_t
*cmdBuf_p
,
121 const N8_Unit_t unitID
)
125 PK_CMD_BLOCK_t
*math_wr_ptr
;
126 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
;
127 unsigned int slot
[4];
129 uint32_t keyDigits
= BYTES_TO_PKDIGITS(modulusLengthBytes
);
131 PK_CMD_BLOCK_t
*nextCommandBlock
= NULL
;
134 /* Initialize the slot values. These are to address temporary
135 storage in the BNC. The slots accomodate operand sizes up to
137 for (i
= 0; i
< sizeof(slot
)/sizeof(unsigned int); i
++)
139 slot
[i
] = i
* keyDigits
;
144 ret
= cb_computeCX(req_p
, p_a
, cp_a
, modulusLengthBytes
, &cmdBuf_p
[index
], &nextCommandBlock
,
150 /* 2) compute R mod P */
151 index
+= N8_CB_COMPUTE_CX_NUMCMDS
;
152 ret
= cb_computeRmodX(req_p
, p_a
, RmodP_a
, modulusLengthBytes
, &cmdBuf_p
[index
], &nextCommandBlock
, FALSE
);
155 /* 3) compute g R mod P */
156 index
+= N8_CB_COMPUTE_RMODX_NUMCMDS
;
158 /* 3.1) Construct a command to load R mod p to slot 1 */
159 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) &cmdBuf_p
[index
];
160 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
161 ldst_wr_ptr
->r_offset
= slot
[1];
162 ldst_wr_ptr
->data_addr_ls
= RmodP_a
;
163 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
165 /* 3.2) Construct a command to load g to slot 2 */
167 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
168 ldst_wr_ptr
->r_offset
= slot
[2];
169 ldst_wr_ptr
->data_addr_ls
= g_a
;
170 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
172 /* 3.3) Construct a command to load p to slot 3 */
174 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
175 ldst_wr_ptr
->r_offset
= slot
[3];
176 ldst_wr_ptr
->data_addr_ls
= p_a
;
177 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
179 /* 3.4) Construct a command for the operation (g * Rmodp) mod p and place in
181 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
182 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
183 math_wr_ptr
->r_offset
= slot
[0];
184 math_wr_ptr
->m_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[3];
185 math_wr_ptr
->a_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[1];
186 math_wr_ptr
->b_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[2];
188 /* 3.5) Construct a command to store the result */
189 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
190 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
191 ldst_wr_ptr
->r_offset
= slot
[0];
192 ldst_wr_ptr
->data_addr_ls
= gRmodP_a
;
193 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
195 DBG_PRINT_PK_CMD_BLOCKS("Precompute DH Values",
196 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
197 N8_CB_PRECOMPUTE_DHVALUES_NUMCMDS
);
201 } /* cb_precomputeDHValues */
203 /*****************************************************************************
204 * cb_computeGXmodp_long
205 *****************************************************************************/
207 * @brief Creates the command blocks for the computation of G**X mod p. This
208 * version <b>does not</b> use the precomputes for the stored value of g.
210 * Creates the command blocks to compute the value for g^x mod p. We are given
211 * g, x, p, cp, and r mod p. To perform the exponentiation we need the
213 * a = (g * (r mod p)) mod p
216 * So, the first thing we need to do is compute (g * (r mod p)) mod p given g
217 * and (r mod p). Once this is done, we simply need to construct the
218 * exponentiation command.
220 * @param req_p RO: Pointer to the API request.
221 * @param g_a RO: Physical address of g.
222 * @param x_a RO: Physical address of x.
223 * @param p_a RO: Physical address of p.
224 * @param cp_a RO: Physical address of cp.
225 * @param RmodP_a RO: Physical address of R mod P.
226 * @param result_a RO: Physical address of the result buffer.
227 * @param modulusLengthBytes RO: Length of the modulus in bytes.
228 * @param cmdBuf_p RW: Pointer to command buffer to be generated
234 * Status of command. N8_STATUS_OK upon success.
240 * <description of assumptions><br>
241 *****************************************************************************/
242 N8_Status_t
cb_computeGXmodp_long(const API_Request_t
*req_p
,
247 const uint32_t RmodP_a
,
248 const uint32_t result_a
,
249 const unsigned int modulusLengthBytes
,
250 PK_CMD_BLOCK_t
*cmdBuf_p
)
252 PK_CMD_BLOCK_t
*math_wr_ptr
= NULL
;
253 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
= NULL
;
256 unsigned int slot
[5];
257 uint32_t keyDigits
= BYTES_TO_PKDIGITS(modulusLengthBytes
);
259 N8_Status_t ret
= N8_STATUS_OK
;
263 CHECK_OBJECT(req_p
, ret
);
265 /* Initialize the slot values. These are to address temporary
266 storage in the BNC. The slots accomodate operand sizes up to
268 for (i
= 0; i
< sizeof(slot
)/sizeof(int); i
++)
270 slot
[i
] = i
* keyDigits
;
273 /* Compute g R mod p */
274 /* 1) Construct a command to load R mod p to slot 1 */
275 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
;
276 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
277 ldst_wr_ptr
->r_offset
= slot
[1];
278 ldst_wr_ptr
->data_addr_ls
= RmodP_a
;
279 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
281 /* 2) Construct a command to load g to slot 2 */
283 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
284 ldst_wr_ptr
->r_offset
= slot
[2];
285 ldst_wr_ptr
->data_addr_ls
= g_a
;
286 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
288 /* 3) Construct a command to load p to slot 3 */
290 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
291 ldst_wr_ptr
->r_offset
= slot
[3];
292 ldst_wr_ptr
->data_addr_ls
= p_a
;
293 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
295 /* 4) Construct a command for the operation (g * Rmodp) mod p and place in
297 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
298 math_wr_ptr
->opcode_si
= PK_Cmd_AB_Mod_M
;
299 math_wr_ptr
->r_offset
= slot
[0];
300 math_wr_ptr
->m_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[3];
301 math_wr_ptr
->a_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[1];
302 math_wr_ptr
->b_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[2];
305 /* 5) Construct a command to load x to slot 1 */
306 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
307 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
308 ldst_wr_ptr
->r_offset
= slot
[1];
309 ldst_wr_ptr
->data_addr_ls
= x_a
;
310 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
312 /* 6) Construct a command to load cp to slot 2 */
314 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
315 ldst_wr_ptr
->r_offset
= slot
[2];
316 ldst_wr_ptr
->data_addr_ls
= cp_a
;
317 ldst_wr_ptr
->data_length
= PK_DH_CP_Byte_Length
;
319 /* 7) Construct a command for the operation g^x mod p and leave in
321 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
322 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
323 math_wr_ptr
->r_offset
= slot
[4];
324 math_wr_ptr
->m_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[3];
325 math_wr_ptr
->a_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[0];
326 math_wr_ptr
->b_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[1];
327 math_wr_ptr
->c_offset
= slot
[2];
329 /* 8) Construct a command to store the result */
330 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
331 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
332 ldst_wr_ptr
->r_offset
= slot
[4];
333 ldst_wr_ptr
->data_addr_ls
= result_a
;
334 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
336 DBG_PRINT_PK_CMD_BLOCKS("Compute GX mod p (long)\n",
337 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
338 N8_CB_COMPUTE_G_XMODP_NUMCMDS_LONG
);
342 } /* compute GXmodp (long) */
344 /*****************************************************************************
345 * cb_computeGXmodp_short
346 *****************************************************************************/
348 * @brief Creates the command blocks for the computation of G**X mod p. This
349 * version uses the precomputed value of gRmodp for simplification and
352 * Creates the command blocks to compute the value for g^x mod p. We are given
353 * x, p, cp, and g R mod p. To perform the exponentiation we need the
355 * a = (g * (r mod p)) mod p
358 * Since we are using the precomputed value for g R mod p, we simply need to
359 * load it and the other values and then call the exponentiation routine.
361 * @param req_p RO: Pointer to the API request.
362 * @param x_a RO: Physical address of x.
363 * @param p_a RO: Physical address of p.
364 * @param cp_a RO: Physical address of cp.
365 * @param gRmodP_a RO: Physical address of g R mod P.
366 * @param result_a RO: Physical address of the result buffer.
367 * @param modulusLengthBytes RO: Length of the modulus in bytes.
368 * @param cmdBuf_p RW: Pointer to command buffer to be generated
374 * Status of command. N8_STATUS_OK upon success.
380 * <description of assumptions><br>
381 *****************************************************************************/
382 N8_Status_t
cb_computeGXmodp_short(const API_Request_t
*req_p
,
386 const uint32_t gRmodP_a
,
387 const uint32_t result_a
,
388 const unsigned int modulusLengthBytes
,
389 PK_CMD_BLOCK_t
*cmdBuf_p
)
391 PK_CMD_BLOCK_t
*math_wr_ptr
= NULL
;
392 PK_LDST_CMD_BLOCK_t
*ldst_wr_ptr
= NULL
;
395 unsigned int slot
[5];
396 uint32_t keyDigits
= BYTES_TO_PKDIGITS(modulusLengthBytes
);
398 N8_Status_t ret
= N8_STATUS_OK
;
402 CHECK_OBJECT(req_p
, ret
);
404 /* Initialize the slot values. These are to address temporary
405 storage in the BNC. The slots accomodate operand sizes up to
407 for (i
= 0; i
< sizeof(slot
)/sizeof(int); i
++)
409 slot
[i
] = i
* keyDigits
;
412 /* 1) Load the precomputed g R mod p into slot 0 */
413 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
;
414 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
415 ldst_wr_ptr
->r_offset
= slot
[0];
416 ldst_wr_ptr
->data_addr_ls
= gRmodP_a
;
417 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
419 /* 2) Construct a command to load x to slot 1 */
421 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
422 ldst_wr_ptr
->r_offset
= slot
[1];
423 ldst_wr_ptr
->data_addr_ls
= x_a
;
424 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
426 /* 3) Construct a command to load cp to slot 2 */
428 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
429 ldst_wr_ptr
->r_offset
= slot
[2];
430 ldst_wr_ptr
->data_addr_ls
= cp_a
;
431 ldst_wr_ptr
->data_length
= PK_DH_CP_Byte_Length
;
433 /* 4) Construct a command to load p to slot 3 */
435 ldst_wr_ptr
->opcode_si
= PK_Cmd_Load_R
;
436 ldst_wr_ptr
->r_offset
= slot
[3];
437 ldst_wr_ptr
->data_addr_ls
= p_a
;
438 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
440 /* 5) Construct a command for the operation g^x mod p and leave in
442 math_wr_ptr
= (PK_CMD_BLOCK_t
*) (ldst_wr_ptr
+ 1);
443 math_wr_ptr
->opcode_si
= PK_Cmd_Exp_G_Mod_M
;
444 math_wr_ptr
->r_offset
= slot
[4];
445 math_wr_ptr
->m_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[3];
446 math_wr_ptr
->a_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[0];
447 math_wr_ptr
->b_length_offset
= (keyDigits
<< PK_Cmd_Length_Shift
) | slot
[1];
448 math_wr_ptr
->c_offset
= slot
[2];
450 /* 6) Construct a command to store the result */
451 ldst_wr_ptr
= (PK_LDST_CMD_BLOCK_t
*) (math_wr_ptr
+ 1);
452 ldst_wr_ptr
->opcode_si
= PK_Cmd_Store_R
| PK_Cmd_SI_Mask
;
453 ldst_wr_ptr
->r_offset
= slot
[4];
454 ldst_wr_ptr
->data_addr_ls
= result_a
;
455 ldst_wr_ptr
->data_length
= modulusLengthBytes
;
457 DBG_PRINT_PK_CMD_BLOCKS("Compute GX mod p (short)\n",
458 (PK_CMD_BLOCK_t
*) req_p
->PK_CommandBlock_ptr
,
459 N8_CB_COMPUTE_G_XMODP_NUMCMDS_SHORT
);
463 } /* compute GXmodp (short) */