No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_rng.c
blob6be4cda44de2a950448bd6d38cf7371121385407
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_rng.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_rng.c
38 * @brief Contains Random Number Generator interface functions
40 * Functions:
41 * N8_SetRNGParameters - Sets the operating parameters for the
42 * Random Number Generator.
43 * N8_GetRNGParameters - Gets the operating parameters for the
44 * Random Number Generator.
45 * N8_GetRandomBytes - Gets requested number of random bytes.
47 *****************************************************************************/
49 /*****************************************************************************
50 * Revision history:
51 * 07/28/03 brr Removed obsolete #ifdefs. (Bug 918)
52 * 05/19/03 brr Clean up include files.
53 * 05/15/03 brr Eliminated obsolete n8_rng.h & updated constants.
54 * 11/25/02 brr Use new define N8_RNG_UNIT to set/get RNG parameters.
55 * 05/15/02 brr Rework RNG queue such that ioctl returns the bytes requested.
56 * 04/04/02 msz Fix for BUG 685 (INCONSISTANT not INVALID OBJECT)
57 * 04/02/02 msz Fix for BUG 503 (not catching weak key of all zeros - check
58 * key after setting parity.)
59 * 03/26/02 msz Fix for BUG 506 (external clock w/o seed source external)
60 * Fix for BUG 507 (check seed source)
61 * Fix for BUG 509 (null pointer on get random bytes)
62 * 03/20/02 msz Fix for BUG 508 (check for request of 0 bytes.)
63 * 03/08/02 msz Request Handler callback is optional.
64 * 02/28/02 msz Request Handler callback is back.
65 * 02/28/02 brr Do not include any QMgr include files.
66 * 02/18/02 msz No longer need Request Handler callback. No longer need
67 * references to the queue control structure. No longer need
68 * current_RNGparms_gp. No longer need initRNGParameters
69 * 02/15/02 brr Correct DBG print for requestStatus.
70 * 02/06/02 bac Added error checking to functions even in the temporary
71 * USE_OS_RNG path so that QA tests behave as expected.
72 * 01/29/02 bac Changed Get/Set parameters to do nothing if using
73 * OS rand function.
74 * 01/29/02 bac Changed N8_GetRandomBytes to use rand() instead of the
75 * behavioral model. This is a temporary measure until the
76 * NSP2000 hardware fix is effected.
77 * 11/13/01 brr Removed references to shared_resource.
78 * 11/10/01 brr Modified to support static allocations of persistant data
79 * by the driver.
80 * 11/07/01 mel Fixed Bugs #187 , #188 , #189 - cosmetic changes
81 * 10/05/01 msz Added slightly more protection around current_RNGparms_gp.
82 * 10/05/01 msz Added support for mulitple RNG execution units.
83 * 10/04/01 msz Added internal initRNGParameters.
84 * 10/02/01 msz Continued merging, use n8_get_shared_resource
85 * 09/25/01 msz Removed bufferLen_log2 from N8_RNG_Parameter_t.
86 * Ask QMgr if hardware has been already initialized before
87 * initializing it. Put current parameters in shared memory.
88 * 09/20/01 bac Changed Key_cblock to key_cblock_t to follow coding stds.
89 * 09/17/01 bac Removed occurence of buffer_source in a DBG statement.
90 * 09/14/01 bac Removed buffer_source from RNG parameters. It will always be
91 * X917. Also removed reference to enums for seed source and use
92 * the new bit-pattern macros instead.
93 * 09/07/01 bac Changed the return code to N8_INVALID_OBJECT if
94 * N8_SetRNGParameters includes a buffer size that is too large
95 * -- as listed in the API Programmer Reference. (BUG #157)
96 * 09/07/01 bac Added a return code check after calling set parameters.
97 * (BUG #156).
98 * 09/11/01 msz Adjusted N8_RNG_Parameter_t parameters
99 * 09/04/01 bac Fixed BUG #56 by editting comments.
100 * 08/27/01 msz Renamed fcnToCallbackWhenRequestIsFilled to callback
101 * 08/08/01 msz Use internal seed, external does not work on FPGA.
102 * 08/08/01 msz Include n8_semaphore.h directly.
103 * 08/07/01 hml Added Locks section to appropriate comment block.
104 * 08/07/01 hml Added protection of globals with a process level semaphore.
105 * 08/03/01 msz Added a test for request_p not zero before de-referencing
106 * it in N8_GetRandomBytes.
107 * 08/02/01 bac Changed the default to set seed source to internal. Also
108 * fixed a bug when freeing a request.
109 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
110 * 07/31/01 bac Check to ensure a request to get random bytes is not for more
111 * than RNG_MAX_REQUEST as required by the specification.
112 * 07/30/01 bac Set the queue pointer in the request.
113 * 07/12/01 bac Deleted unused variables.
114 * 06/28/01 bac Changes to hook-up callback function and get event handling to
115 * work properly.
116 * 06/25/01 bac Substantial changes to support QMgr v 1.0.1 and new kernel
117 * memory management. Added event to the GetRandomBytes call.
118 * 06/20/01 mel Corrected use of kernel memory.
119 * 05/30/01 mel Deleted checkKeyForWeakness and checkKeyParity.
120 * Added forcing parity on key.
121 * 05/21/01 bac Converted to use N8_ContextHandle_t.
122 * 05/18/01 bac Memory management macros.
123 * 05/03/01 bac Replaced integer use of NULL with 0.
124 * 04/30/01 bac Fixed problem with resultHandler to eliminate compiler
125 * warnings. Warning that resultHandler is defined but not
126 * used still exists as this problem needs to be resolved.
127 * 04/12/01 mel Original version.
128 ****************************************************************************/
129 /** @defgroup RNG Random Number Methods
131 #include "n8_common.h" /* common definitions */
132 #include "n8_pub_errors.h" /* Errors definition */
133 #include "n8_pub_types.h" /* Some type definitions. */
134 #include "n8_enqueue_common.h" /* common definitions for enqueue */
135 #include "n8_util.h" /* definitions for CHECK_RETURN and other macros */
136 #include "n8_key_works.h" /* definitions for functions that work with key */
137 #include "n8_API_Initialize.h"
138 #include "n8_semaphore.h"
139 #include "n8_rand.h"
141 /*****************************************************************************
142 * N8_SetRNGParameters
143 *****************************************************************************/
144 /** @ingroup RNG
145 * @brief Sets the operating parameters for Random Number Generator.
147 * Sets the operating parameters for the Random Number Generator to the
148 * values contained in the N8_RNG_Parameter_t object. These parameters
149 * include the base address of the host memory buffer into which the RNG
150 * will write random values, the size of this buffer (in terms of entries,
151 * where each entry is a 64-bit random value), the seed source to use, etc.
152 * as defined in the RNG specification. Once this call returns, all values
153 * returned by N8_GetRandomBytes will be values generated using the parameters
154 * specified in this call (up until a subsequent call to N8_SetRNGParameters).
155 * A call to N8_SetRNGParameters must be made before N8_GetRandomBytes can
156 * return any random values.
158 * Currently this code will set parameters on all RNG units the same way.
159 * Thus, when we go to set parameters, we will tell RN code to set parameters
160 * on all units.
162 * @param p RO: Pointer to N8_RNG_Parameter_t
165 * @return
166 * ret - returns N8_STATUS_OK if successful or Error value.
168 * @par Errors:
169 * N8_INVALID_OBJECT - one or more values specified in
170 * N8_RNG_Parameter_t are outside its
171 * permitted range <BR>
172 * N8_INCONSISTENT - the values specified in
173 * N8_RNG_Parameter_t are not
174 * consistent with one another <BR>
175 * N8_WEAK_KEY - key1 or key2 or both - weak key(s) <BR>
176 * N8_INVALID_ENUM - buffer/seed type is invalid <BR>
177 * N8_INVALID_INPUT_SIZE - invalid size of the kernel-space
178 * buffer <BR>
179 * N8_INVALID_KEY - key's parity check failed
181 * @par Locks:
182 * None.
184 * @par Assumptions:
185 * None.
187 *****************************************************************************/
189 #define TOD_MIN 100
191 N8_Status_t N8_SetRNGParameters(N8_RNG_Parameter_t *p)
193 N8_Status_t ret = N8_STATUS_OK;
194 key_cblock_t key1, key2; /* Keys to be checked */
195 uint32_t i;
197 DBG(("N8_SetRNGParameters(N8_RNG_Parameter_t *p)\n"));
201 ret = N8_preamble();
202 CHECK_RETURN(ret);
204 /* verify RNG parameter object */
205 CHECK_OBJECT(p, ret);
208 * 1. verify parameters for range and consistency
212 /* verify the consistency of the Time of the Day parameters */
213 if ((p->set_TOD_counter == N8_TRUE) && (p->TOD_prescale < TOD_MIN))
215 DBG(("TOD_prescale is out of range: %d\n", p->TOD_prescale));
216 DBG(("N8_SetRNGParameters - return Error\n"));
217 ret = N8_INCONSISTENT;
218 break;
221 /* build keys for weakness and parity verification */
222 for ( i = 0; i < N8_DES_KEY_LENGTH; i++ )
224 key1[i] = p->key1[i];
225 key2[i] = p->key2[i];
229 /* check key1 and key2 for parity and force parity if needed*/
230 if (checkKeyParity(&key1) == N8_FALSE)
232 forceParity(&key1);
233 for ( i = 0; i < N8_DES_KEY_LENGTH; i++ )
235 p->key1[i] = key1[i];
239 if(checkKeyParity(&key2) == N8_FALSE)
241 forceParity(&key2);
242 for ( i = 0; i < N8_DES_KEY_LENGTH; i++ )
244 p->key2[i] = key2[i];
248 /* check key1 and key2 for weakness */
249 if (checkKeyForWeakness(&key1) == N8_TRUE ||
250 checkKeyForWeakness(&key2) == N8_TRUE)
252 DBG(("Weak key\nN8_SetRNGParameters - return Error\n"));
253 ret = N8_WEAK_KEY;
254 break;
258 CHECK_RETURN(ret);
260 /* verify iteration_count. */
261 if ((p->iteration_count < 1) || (p->iteration_count > 256))
263 DBG(("Iteration count is out of range\n"));
264 DBG(("N8_SetRNGParameters - return Error\n"));
265 /* iteration count is out of range */
266 ret = N8_INVALID_OBJECT;
267 break;
271 /* Check seed souce */
272 if ( (p->seed_source != N8_RNG_SEED_INTERNAL) /* &&
273 (p->seed_source != N8_RNG_SEED_EXTERNAL) &&
274 (p->seed_source != N8_RNG_SEED_HOST) */ )
276 DBG(("Invalid seed source\n"));
277 DBG(("N8_SetRNGParameters - return Error\n"));
278 ret = N8_INVALID_VALUE;
279 break;
282 /* Check for use of external clock without seed being seed external */
283 if ((p->use_external_clock == N8_TRUE) &&
284 (p->seed_source != N8_RNG_SEED_EXTERNAL))
286 DBG(("External clock set without seed source external\n"));
287 DBG(("N8_SetRNGParameters - return Error\n"));
288 ret = N8_INCONSISTENT;
289 break;
294 * 2. set parameters in queue manager
297 /* Initialize parameters in queue manager. All RNG units are */
298 /* initialized the same way. */
299 /* if queue was not able to set parameters return invalid object error */
300 ret = RN_SetParameters(p, N8_RNG_UNIT);
301 if (ret != N8_STATUS_OK)
303 DBG(("Queue was not able to set parameters\n"));
304 DBG(("N8_SetRNGParameters - return Error\n"));
305 N8_PRINT("N8_SetRNGParameters - return %d\n", ret);
306 ret = N8_INVALID_OBJECT;
307 break;
311 DBG(("N8_SetRNGParameters - FINISHED\n"));
313 } while (FALSE);
316 return ret;
317 } /* N8_SetRNGParameters */
319 /*****************************************************************************
320 * N8_GetRNGParameters
321 *****************************************************************************/
322 /** @ingroup RNG
323 * @brief Gets the current operating parameters for RNG.
325 * Gets the current operating parameters for the Random Number Generator and
326 * returns their values in the N8_RNG_Parameter_t object. These parameters
327 * include the size of this buffer (in terms of entries, where each entry is a
328 * 64-bit random value), the seed source to use, etc. as defined in the RNG
329 * specification. This call has no effect on the operation of the RNG. A call
330 * to N8_GetRNGParameters made before any call to N8_SetRNGParameters will
331 * return whatever values are in the RNG's registers at the time of the call.
333 * We currently set all RNG units up the same way. So for the most part
334 * all parameters are the same on each unit. However, when we look at
335 * hardware specific parameters, we need to tell RN code to get parameters
336 * from all units. The RN code will handle any specific manipulation of
337 * the individual units to present one overall view.
339 * @param p WO: Pointer to N8_RNG_Parameter_t
341 * @return
342 * ret - returns N8_STATUS_OK if successful or Error value.
344 * @par Errors:
345 * N8_INVALID_OBJECT - Pointer to N8_RNG_Parameter_t is NULL<BR>
346 * N8_NOT_INITIALIZED - RNG wasn't initialized<BR>
348 * @par Locks:
349 * None.
351 * @par Assumptions:
352 * Assumes hardware is or will be initialized.
353 *****************************************************************************/
354 N8_Status_t N8_GetRNGParameters(N8_RNG_Parameter_t *p)
357 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
359 DBG(("N8_GetRNGParameters(N8_RNG_Parameter_t *p)\n"));
363 ret = N8_preamble();
364 CHECK_RETURN(ret);
366 /* verify RNG parameter object */
367 CHECK_OBJECT(p, ret);
369 /* QMgr keeps the copy of what the RNG Parameters look like. It */
370 /* will fill in the parameters */
371 ret = RN_GetParameters(p, N8_RNG_UNIT);
372 if (ret != N8_STATUS_OK)
374 DBG(("Queue was not able to get parameters\n"));
375 DBG(("N8_GetRNGParameters - return Error\n"));
376 ret = N8_INVALID_OBJECT;
377 break;
380 /* Set set_TOD_counter to N8_FALSE, as that is what is claimed to */
381 /* be done in n8_rn_common.h's documentation. */
382 p->set_TOD_counter = N8_FALSE;
384 DBG(("todEnable = %s\n",
385 (p->todEnable == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
386 DBG(("use_external_clock = %s\n",
387 (p->use_external_clock == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
388 DBG(("seed_source = %d\n", p->seed_source));
389 DBG(("iteration_count = %d\n", p->iteration_count));
390 DBG(("TOD_prescale = %x\n", p->TOD_prescale));
391 DBG(("set_TOD_counter = %s\n",
392 (p->set_TOD_counter == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
394 /* Note - These DBG lines assume N8_DES_KEY_LENGTH is 8 */
395 DBG(("key1 = %02x%02x%02x%02x%02x%02x%02x%02x\n",
396 p->key1[0],p->key1[1],p->key1[2],p->key1[3],
397 p->key1[4],p->key1[5],p->key1[6],p->key1[7]));
398 DBG(("key1 = %02x%02x%02x%02x%02x%02x%02x%02x\n",
399 p->key2[0],p->key2[1],p->key2[2],p->key2[3],
400 p->key2[4],p->key2[5],p->key2[6],p->key2[7]));
401 DBG(("hostSeed = %02x%02x%02x%02x%02x%02x%02x%02x\n",
402 p->hostSeed[0],p->hostSeed[1],p->hostSeed[2],p->hostSeed[3],
403 p->hostSeed[4],p->hostSeed[5],p->hostSeed[6],p->hostSeed[7]));
405 DBG(("initial_TOD_seconds = %x\n", p->initial_TOD_seconds));
406 DBG(("externalClockScaler = %x\n", p->externalClockScaler));
407 DBG(("hostSeedValid = %s\n",
408 (p->hostSeedValid == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
409 DBG(("seedErrorFlag = %s\n",
410 (p->seedErrorFlag == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
411 DBG(("x9_17_errorFlag = %s\n",
412 (p->x9_17_errorFlag == N8_TRUE) ? "N8_TRUE" : "N8_FALSE"));
413 DBG(("seedValue_ms = %08x\n", p->seedValue_ms));
414 DBG(("seedValue_ls = %08x\n", p->seedValue_ls));
416 DBG(("N8_GetRNGParameters - FINISHED\n"));
418 } while(FALSE);
420 return ret;
421 } /* N8_GetRNGParameters */
423 /*****************************************************************************
424 * N8_GetRandomBytes
425 *****************************************************************************/
426 /** @ingroup RNG
427 * @brief Gets random bytes generated by the RNG.
429 * Gets reqvested number of random bytes generated by the RNG and returns
430 * them in the buffer, which must be at least as big as number of random bytes
431 * reqvested. Up to 8 K random bytes can be returned in a single call. A call
432 * to N8_SetRNGParameters must be made before N8_GetRandomBytes can return
433 * any values.
435 * We currently pick a unit (next available) to get the parameters.
436 * This is ok, as all RNG units are set up the same way.
438 * @param num_bytes RO: The number of random bytes desired
439 * @param buf WO: The buffer for returned random bytes
440 * @param event_p RW: On input, if null the call is synchronous
441 * and no event is returned. The operation
442 * is complete when the call returns. If
443 * non-null, then the call is asynchronous;
444 * an event is returned that can be used to
445 * determine when the operation completes.
448 * @return
449 * ret - returns N8_STATUS_OK if successful or Error value.
450 * buf - the returned random bytes<BR>
452 * @par Errors:
453 * N8_NOT_INITIALIZED - the RNG has not been initialized<BR>
454 * N8_INVALID_INPUT_SIZE - num_bytes is less than 0
455 * or more than 8 KBytes<BR>
457 * @par Assumptions:
458 * Buffer is pre-allocated and is large enough.
459 *****************************************************************************/
461 N8_Status_t N8_GetRandomBytes(int num_bytes, char *buf_p, N8_Event_t *event_p)
463 RN_Request_t rn_request; /* RNG request structure */
464 N8_Status_t ret;
465 DBG(("N8_GetRandomBytes\n"));
469 /* check the buffer */
470 CHECK_OBJECT(buf_p, ret);
472 /* check the number of bytes requested
473 it can't be less or equal to 0 or more than N8_RNG_MAX_REQUEST. */
474 if ((num_bytes <= 0) || (num_bytes > N8_RNG_MAX_REQUEST))
476 DBG(("Number of bytes requested is out of range : %d\n", num_bytes));
477 DBG(("N8_GetRandomBytes - return Error\n"));
478 ret = N8_INVALID_INPUT_SIZE;
479 break;
482 ret = N8_preamble();
483 CHECK_RETURN(ret);
485 rn_request.userRequest = N8_FALSE;
486 rn_request.userBuffer_p = buf_p;
487 rn_request.numBytesRequested = num_bytes;
489 /* we have a valid request. queue it up. */
490 ret = Queue_RN_request(&rn_request);
491 CHECK_RETURN(ret);
493 if (event_p != NULL)
495 N8_SET_EVENT_FINISHED(event_p, N8_RNG);
497 } while (FALSE);
499 return ret;
501 } /* N8_GetRandomBytes */