No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / commands / n8_cb_dh.c
blob45481bf6f7c97659ffbf5923ec55d2404e792267
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_cb_dh.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
40 * Generates all command blocks for DSA-related functions.
42 *****************************************************************************/
44 /*****************************************************************************
45 * Revision history:
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
58 * code review.
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
64 * pointers.
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"
73 #include "n8_cb_dh.h"
74 #include "n8_util.h"
76 /*****************************************************************************
77 * cb_precomputeDHValues
78 *****************************************************************************/
79 /** @ingroup cb_dh
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
87 * b = x
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
101 * @par Externals
102 * None
104 * @return
105 * Status code
107 * @par Errors
108 * TBD
110 * @par Assumptions
111 * All result areas are of sufficient size.
112 *****************************************************************************/
113 N8_Status_t cb_precomputeDHValues(const API_Request_t *req_p,
114 const uint32_t g_a,
115 const uint32_t p_a,
116 const uint32_t RmodP_a,
117 const uint32_t gRmodP_a,
118 const uint32_t cp_a,
119 const unsigned int modulusLengthBytes,
120 PK_CMD_BLOCK_t *cmdBuf_p,
121 const N8_Unit_t unitID)
123 N8_Status_t ret;
124 unsigned int index;
125 PK_CMD_BLOCK_t *math_wr_ptr;
126 PK_LDST_CMD_BLOCK_t *ldst_wr_ptr;
127 unsigned int slot[4];
128 unsigned int i;
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
136 the key length */
137 for (i = 0; i < sizeof(slot)/sizeof(unsigned int); i++)
139 slot[i] = i * keyDigits;
142 /* 1) compute cp */
143 index = 0;
144 ret = cb_computeCX(req_p, p_a, cp_a, modulusLengthBytes, &cmdBuf_p[index], &nextCommandBlock,
145 unitID,
146 N8_FALSE);
147 CHECK_RETURN(ret);
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);
153 CHECK_RETURN(ret);
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 */
166 ldst_wr_ptr++;
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 */
173 ldst_wr_ptr++;
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
180 * slot 0 */
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);
198 } while (FALSE);
200 return ret;
201 } /* cb_precomputeDHValues */
203 /*****************************************************************************
204 * cb_computeGXmodp_long
205 *****************************************************************************/
206 /** @ingroup cb_dh
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
212 * following:
213 * a = (g * (r mod p)) mod p
214 * b = x
215 * c = cp
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
230 * @par Externals
231 * None
233 * @return
234 * Status of command. N8_STATUS_OK upon success.
236 * @par Errors
237 * N8_MALLOC
239 * @par Assumptions
240 * <description of assumptions><br>
241 *****************************************************************************/
242 N8_Status_t cb_computeGXmodp_long(const API_Request_t *req_p,
243 const uint32_t g_a,
244 const uint32_t x_a,
245 const uint32_t p_a,
246 const uint32_t cp_a,
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;
255 unsigned int i;
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
267 the key length */
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 */
282 ldst_wr_ptr++;
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 */
289 ldst_wr_ptr++;
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
296 * slot 0 */
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 */
313 ldst_wr_ptr++;
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
320 * slot 4 */
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);
339 } while (FALSE);
341 return ret;
342 } /* compute GXmodp (long) */
344 /*****************************************************************************
345 * cb_computeGXmodp_short
346 *****************************************************************************/
347 /** @ingroup cb_dh
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
350 * acceleration.
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
354 * following:
355 * a = (g * (r mod p)) mod p
356 * b = x
357 * c = cp
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
370 * @par Externals
371 * None
373 * @return
374 * Status of command. N8_STATUS_OK upon success.
376 * @par Errors
377 * N8_MALLOC
379 * @par Assumptions
380 * <description of assumptions><br>
381 *****************************************************************************/
382 N8_Status_t cb_computeGXmodp_short(const API_Request_t *req_p,
383 const uint32_t x_a,
384 const uint32_t p_a,
385 const uint32_t cp_a,
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;
394 unsigned int i;
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
406 the key length */
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 */
420 ldst_wr_ptr++;
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 */
427 ldst_wr_ptr++;
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 */
434 ldst_wr_ptr++;
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
441 * slot 4 */
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);
460 } while (FALSE);
462 return ret;
463 } /* compute GXmodp (short) */