No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_dh.c
blob026662d1ffafb37a118538f63f94e6a9432f6645
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_dh.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_dh.c
38 * @brief Public DH functions.
40 * Implementation of all public DH functions.
42 *****************************************************************************/
44 /*****************************************************************************
45 * Revision history:
47 * 05/16/03 brr Fix Bug 902 by allocating a kernel buffer to hold key,
48 * modulus etc. to avoid copies in N8_DHCompute.
49 * 05/30/03 brr Set the structure ID in N8_DHInitializeKey when the key is set
50 * up so the error case frees memory correctly. (Bug 901)
51 * 05/20/02 brr Free the request for all error conditions.
52 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
53 * 04/09/02 bac A DH key was trying to be freed even though it wasn't
54 * allocated. BUG 686
55 * 04/01/02 brr Validate structureID in N8_DHFreeKey before deallocation.
56 * 03/26/02 brr Allocate the data buffer as part of the API request.
57 * 02/28/02 brr Do not include any QMgr include files.
58 * 02/25/02 brr Removed last references to validatedUnit.
59 * 02/20/02 brr Removed references to the queue structure.
60 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
61 * 11/08/01 mel Added unit ID parameter to commend block calls.
62 * 11/05/01 hml Added the structure verification.
63 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
64 * 10/01/01 hml Added multi-unit functionality.
65 * 09/14/01 bac Changes from code review. Added precomputation of gRmodP and
66 * the use of it.
67 * 09/13/01 mel Added event parameter to N8_DHInitializeKey.
68 * 08/29/01 bac Added N8_DHFreeKey method.
69 * 08/24/01 bac Re-worked to correctly initialize the pre-computed values
70 * and calculate the DHCompute correctly. Per (BUG #125),
71 * check valid modulus size at initialization.
72 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
73 * 07/23/01 bac Created new result handler for DHInit and DHCompute.
74 * 07/20/01 bac Changed calls to create__RequestBuffer to pass the chip id.
75 * 07/12/01 bac Added copyright notice.
76 * 07/12/01 bac General cleanup.
77 * 05/22/01 mel Original version.
78 ****************************************************************************/
79 /** @defgroup dh DH Functions.
82 #include "n8_common.h"
83 #include "n8_pub_errors.h"
84 #include "n8_pk_common.h"
85 #include "n8_enqueue_common.h"
86 #include "n8_util.h"
87 #include "n8_API_Initialize.h"
88 #include "n8_cb_dh.h"
91 /**********************************************************************
92 * N8_DHInitializeKey
93 ***********************************************************************/
94 /** @ingroup dh
95 * @brief Initializes the specified DHKeyObject so that it can be used
96 * in Diffie-Hellman operations. The KeyMaterial object (structure)
97 * contains the appropriate group generator g, modulus p, and modulus size.
99 * Description:
100 * This call pre-computes various constant values from the supplied
101 * parameters and initializes DHKeyObject with these values. By
102 * pre-computing these values, Diffie-Hellman computations can be done
103 * faster than if these constants must be computed on each operation.
104 * Once a DHKeyObject has been initialized, it can be used repeatedly
105 * in multiple DH operations. It does not ever need to be re-initialized,
106 * unless the actual key value(s) change (i.e., unless the key itself
107 * changes).
109 * @param key_p RW: The caller allocated DHKeyObject, initialized
110 * by this call with the appropriate DH key
111 * material and pre-computed DH constants
112 * depending on the value of the KeyType parameter
113 * @param material_p RO: Pointer to the key material to use in initializing
114 * DHKeyObject.
116 * @return
117 * ret - returns N8_STATUS_OK if successful or Error value.
119 * @par Errors:
120 * N8_INVALID_OBJECT - DH key or key material object is NULL<BR>
122 * @par Assumptions:
123 * None.
124 **********************************************************************/
125 N8_Status_t N8_DHInitializeKey(N8_DH_KeyObject_t *key_p,
126 N8_DH_KeyMaterial_t *material_p,
127 N8_Event_t *event_p)
129 N8_Status_t ret = N8_STATUS_OK;
130 int nBytes;
131 API_Request_t *req_p = NULL;
135 ret = N8_preamble();
136 CHECK_RETURN(ret);
138 CHECK_OBJECT(key_p, ret);
139 CHECK_OBJECT(material_p, ret);
141 key_p->unitID = material_p->unitID;
143 /* check the modulus size to ensure it is 1 <= ms <= 512. return
144 * N8_INVALID_SIZE if not. */
145 if (material_p->modulusSize < N8_DH_MIN_MODULUS_SIZE ||
146 material_p->modulusSize > N8_DH_MAX_MODULUS_SIZE)
148 ret = N8_INVALID_KEY_SIZE;
149 break;
152 /* Allocate space for the initialized key. we must compute 'R mod p' and 'cp'
153 * for use in subsequent DHComputes. */
154 key_p->modulusLength = material_p->modulusSize;
155 nBytes = (NEXT_WORD_SIZE(key_p->modulusLength) + /* g */
156 NEXT_WORD_SIZE(key_p->modulusLength) + /* p */
157 NEXT_WORD_SIZE(key_p->modulusLength) + /* R mod p */
158 NEXT_WORD_SIZE(key_p->modulusLength) + /* g R mod p */
159 NEXT_WORD_SIZE(PK_DH_CP_Byte_Length));/* cp */
161 /* Allocate a kernel buffer to hold data accessed by the NSP2000 */
162 key_p->kmem_p = N8_KMALLOC_PK(nBytes);
163 CHECK_OBJECT(key_p->kmem_p, ret);
164 memset(key_p->kmem_p->VirtualAddress, 0, nBytes);
166 /* Compute virtual addresses within the kernel buffer */
167 key_p->g = (N8_Buffer_t *) key_p->kmem_p->VirtualAddress;
168 key_p->p = key_p->g + NEXT_WORD_SIZE(key_p->modulusLength);
169 key_p->R_mod_p = key_p->p + NEXT_WORD_SIZE(key_p->modulusLength);
170 key_p->gR_mod_p = key_p->R_mod_p + NEXT_WORD_SIZE(key_p->modulusLength);
171 key_p->cp = key_p->gR_mod_p + NEXT_WORD_SIZE(key_p->modulusLength);
173 /* Compute physical addresses within the kernel buffer */
174 key_p->g_a = key_p->kmem_p->PhysicalAddress;
175 key_p->p_a = key_p->g_a + NEXT_WORD_SIZE(key_p->modulusLength);
176 key_p->RmodP_a = key_p->p_a + NEXT_WORD_SIZE(key_p->modulusLength);
177 key_p->gRmodP_a = key_p->RmodP_a + NEXT_WORD_SIZE(key_p->modulusLength);
178 key_p->cp_a = key_p->gRmodP_a + NEXT_WORD_SIZE(key_p->modulusLength);
180 /* Set up the memory for p and g and copy from the key material */
181 memcpy(key_p->p, material_p->p, material_p->modulusSize);
182 memcpy(key_p->g, material_p->g, material_p->modulusSize);
184 /* Set the structure ID */
185 key_p->structureID = N8_DH_STRUCT_ID;
187 /* allocate user-space command buffer */
188 ret = createPKRequestBuffer(&req_p, key_p->unitID,
189 N8_CB_PRECOMPUTE_DHVALUES_NUMCMDS,
190 NULL, 0);
192 CHECK_RETURN(ret);
194 ret = cb_precomputeDHValues(req_p, key_p->g_a, key_p->p_a,
195 key_p->RmodP_a, key_p->gRmodP_a, key_p->cp_a,
196 key_p->modulusLength,
197 req_p->PK_CommandBlock_ptr,
198 key_p->unitID);
199 CHECK_RETURN(ret);
200 QUEUE_AND_CHECK(event_p, req_p, ret);
201 HANDLE_EVENT(event_p, req_p, ret);
202 } while(FALSE);
205 * Deallocate the request if we arrived from an error condition.
207 if (ret != N8_STATUS_OK)
209 /* free the request */
210 freeRequest(req_p);
211 /* free the key also, if it has been allocated */
212 if (key_p != NULL)
214 /* ignore the return code as we want to return the original anyway */
215 (void) N8_DHFreeKey(key_p);
219 return ret;
220 } /* N8_DHInitializeKey */
222 /**********************************************************************
223 * N8_DHCompute
224 ***********************************************************************/
225 /** @ingroup dh
226 * @brief Computes a Diffie-Hellman exponentiation as required to compute
227 * Diffie-Hellman public values from a secret value and a Diffie-Hellman
228 * key (or group).
230 * Description:
231 * The key or group is specified by DHKeyObject which must have been
232 * previously initialized with the appropriate group generator g, modulus p,
233 * and modulus size by a call to N8_DHInitializeKey. The DH secret value
234 * used as the exponent is specified in XValue, and must be of the same
235 * size as the modulus size in DHKeyObject. GValue specifies the value
236 * to be exponentiated and must also be the same size as the modulus.
237 * GValue may be null, in which case the generator g from DHKeyObject is
238 * used as the GValue. The result of the calculation is returned in
239 * GXValue and is the same size as the modulus. The value computed is
240 * GXValue = ( GValue ** XValue ) mod p. Thus this routine computes a
241 * modular exponentiation.
242 * This call can be used to compute from a private x value the value
243 * X = g**x mod p that is the public X value sent to the other respondent
244 * in a Diffie-Hellman exchange. (In this case the GValue is set to null,
245 * and x is used for XValue.) When the respondent's corresponding Y value
246 * (Y = g**y mod p, y = the respondent's private y) is received, this call
247 * can then be used to compute the common shared secret XY = g**(xy) = YX by
248 * using X for the GValue and the received Y as the XValue.
250 * Parameters:
251 * @param key_p RO: The caller supplied DHKeyObject containing
252 * the appropriate Diffie-Hellman values
253 * and pre-computed DH constants.
254 * @param gValue RO: The value to be raised to a power.
255 * If null, then the generator g value from
256 * DHKeyObject is used. GValue must be the
257 * same size as the modulus p from DHKeyObject.
258 * @param xValue RO: The exponent. Must be supplied. XValue
259 * must be the same size as the
260 * modulus p from DHKeyObject
261 * @param gxValue WO: GValue raised to the XValue power, mod p.
262 * GXValue will be the same
263 * size as the modulus p from DHKeyObject.
264 * @param event_p RW: On input, if null the call is synchronous
265 * and no event is returned. The operation
266 * is complete when the call returns. If
267 * non-null, then the call is asynchronous;
268 * an event is returned that can be used to
269 * determine when the operation completes.
271 * @return
272 * ret - returns N8_STATUS_OK if successful or Error value.
274 * @par Errors:
275 * N8_INVALID_OBJECT - context request object is NULL<BR>
276 * N8_INVALID_KEY - The DHKeyObject is not a valid key
277 * object
278 * for this operation.
280 * @par Assumptions:
281 **********************************************************************/
282 N8_Status_t N8_DHCompute(N8_DH_KeyObject_t *key_p,
283 N8_Buffer_t *gValue_p,
284 N8_Buffer_t *xValue_p,
285 N8_Buffer_t *gxValue_p,
286 N8_Event_t *event_p)
288 N8_Status_t ret = N8_STATUS_OK;
289 API_Request_t *req_p = NULL;
290 unsigned int nBytes;
292 N8_Buffer_t *g_p;
293 N8_Buffer_t *x_p;
294 N8_Buffer_t *res_p;
296 uint32_t g_a;
297 uint32_t x_a;
298 uint32_t res_a;
300 unsigned int g_len;
301 unsigned int x_len;
302 unsigned int res_len;
304 N8_Boolean_t useShortCommandBlock = N8_FALSE;
307 ret = N8_preamble();
308 CHECK_RETURN(ret);
310 CHECK_OBJECT(key_p, ret);
311 CHECK_OBJECT(xValue_p, ret);
312 CHECK_OBJECT(gxValue_p, ret);
313 CHECK_STRUCTURE(key_p->structureID, N8_DH_STRUCT_ID, ret);
315 /* compute the lengths of all of the parameters as a convenience */
316 g_len = key_p->modulusLength;
317 x_len = key_p->modulusLength;
318 res_len = key_p->modulusLength;
320 nBytes = (NEXT_WORD_SIZE(x_len) +
321 NEXT_WORD_SIZE(res_len));
323 /* gValue_p is allowed to be NULL. if so, use the g from the key object. */
324 if (gValue_p == NULL)
326 useShortCommandBlock = N8_TRUE;
328 /* allocate user-space buffer */
329 ret = createPKRequestBuffer(&req_p,
330 key_p->unitID,
331 N8_CB_COMPUTE_G_XMODP_NUMCMDS_SHORT,
332 resultHandlerGeneric, nBytes);
334 else
336 nBytes += NEXT_WORD_SIZE(g_len);
338 /* allocate user-space buffer */
339 ret = createPKRequestBuffer(&req_p,
340 key_p->unitID,
341 N8_CB_COMPUTE_G_XMODP_NUMCMDS_LONG,
342 resultHandlerGeneric, nBytes);
345 CHECK_RETURN(ret);
347 /* set up the addressing for the pointers */
348 x_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
349 x_a = req_p->qr.physicalAddress + req_p->dataoffset;
350 res_p = x_p + NEXT_WORD_SIZE(x_len);
351 res_a = x_a + NEXT_WORD_SIZE(x_len);
353 memcpy(x_p, xValue_p, x_len);
355 req_p->copyBackSize = x_len;
356 req_p->copyBackFrom_p = res_p;
357 req_p->copyBackTo_p = gxValue_p;
359 if (useShortCommandBlock == N8_TRUE)
361 ret = cb_computeGXmodp_short(req_p,
362 x_a,
363 key_p->p_a,
364 key_p->cp_a,
365 key_p->gRmodP_a,
366 res_a,
367 key_p->modulusLength,
368 req_p->PK_CommandBlock_ptr);
370 else
372 /* gValue_p is not NULL, copy the user-space */
373 /* data into our kernel space buffers */
374 g_p = res_p + NEXT_WORD_SIZE(res_len);
375 g_a = res_a + NEXT_WORD_SIZE(res_len);
376 memcpy(g_p, gValue_p, g_len);
378 ret = cb_computeGXmodp_long(req_p,
379 g_a,
380 x_a,
381 key_p->p_a,
382 key_p->cp_a,
383 key_p->RmodP_a,
384 res_a,
385 key_p->modulusLength,
386 req_p->PK_CommandBlock_ptr);
389 CHECK_RETURN(ret);
391 QUEUE_AND_CHECK(event_p, req_p, ret);
392 HANDLE_EVENT(event_p, req_p, ret);
394 } while (FALSE);
395 DBG(("DH computed\n"));
398 * Deallocate the request if we arrived from an error condition.
400 if (ret != N8_STATUS_OK)
402 freeRequest(req_p);
405 return ret;
406 } /* N8_DHCompute */
409 /*****************************************************************************
410 * N8_DHFreeKey
411 *****************************************************************************/
412 /** @ingroup dh
413 * @brief Free an initialized Diffie-Hellman key object
415 * At initialization, the key object has several components allocated. This
416 * method will release those resources. This method should be called when the
417 * key is no longer used. It is the user's responsibility to avoid memory leaks
418 * by invoking this method.
420 * @param key_p RW: Pointer to key object to be freed.
422 * @par Externals
423 * None
425 * @return
426 * Status: N8_STATUS_OK -- no errors<br>
427 * N8_INVALID_KEY -- the key passed was not a valid key.
429 * @par Errors
430 * No errors are reported except as noted above.
432 * @par Assumptions
433 * None
434 *****************************************************************************/
435 N8_Status_t N8_DHFreeKey(N8_DH_KeyObject_t *key_p)
437 N8_Status_t ret = N8_STATUS_OK;
441 ret = N8_preamble();
442 CHECK_RETURN(ret);
444 if ((key_p == NULL) || (key_p->structureID != N8_DH_STRUCT_ID))
446 ret = N8_INVALID_KEY;
447 break;
449 if (key_p->kmem_p != NULL)
451 N8_KFREE(key_p->kmem_p);
452 key_p->kmem_p = NULL;
455 key_p->structureID = 0;
456 } while (FALSE);
457 return ret;
458 } /* N8_DHFreeKey */