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_contextM.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_contextM.c
38 * @brief Contains Crypto Context management Interface.
40 * Managing the context memory is left to the user.
41 * SAPI provides interfaces to allocate and initialize a context entry, and to
42 * free an entry. The user must allocate and initialize a context entry before
43 * it can be used (presumably when an SSL connection is opened), specify which
44 * context entry to use in the calls that require context memory, and finally
45 * free the context entry when finished (presumably when an SSL connection is
46 * closed). Limited error checking is done, and if the user makes errors such as
47 * specifying the wrong context entry for a call (e.g., specifying a context
48 * entry containing an ARC4 key for encrypting an SSL packet on a connection
49 * established with DES in the cipher suite), incorrect results will be
50 * produced without a warning or error occurring.
52 *****************************************************************************/
54 /*****************************************************************************
56 * 05/20/03 brr Remove obsolete functions resultHandlerFreeContext &
57 * n8_numCommandsToLoadContext
58 * 05/20/02 brr Free the request for all error conditions.
59 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
60 * 03/29/02 hml Now validate the unit and the context in
61 * N8_Read/WriteContext. (BUGS 657, 658).
62 * 03/26/02 hml Enhanced N8_AllocateContext and N8_FreeContext to retrieve
63 * the status from the lower level calls. (Bugs 637,642).
64 * 03/26/02 brr Allocate the data buffer as part of the API request.
65 * 03/22/02 hml Removed unneeded sessionID param from call to
67 * 03/18/02 brr Removed obsolete references to queue_p & validateContextHandle.
68 * 02/28/02 brr Do not include any QMgr include files.
69 * 02/18/02 brr Support queue selection.
70 * 02/15/02 brr Moved context memory management to the driver.
71 * 01/25/02 bac Changed allocation search algorithm to always start at the
72 * index after the one last assigned. This should be a much
73 * better search than simply starting at the beginning every
74 * time, which clusters the allocated contexts from 0..n.
75 * 01/22/02 bac Added function n8_numCommandsToLoadContext.
76 * 01/22/02 bac Conditionally removed the clearing of context memory when
77 * N8_FreeContext is called.
78 * 12/07/01 brr Removed userID to reduce memory consumption until supported.
79 * 12/07/01 mel Fixed bug #404: added checks for aligned address.
80 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
81 * 11/12/01 hml Fixed bug for freeing lock not held.
82 * 11/08/01 mel Fixed bug #289 : by passing unitID parameter
83 * 11/08/01 mel Fixed comments (bug #292).
84 * 11/08/01 mel Fixed bug #299 : N8_ReadContext does not check length parameter.
85 * Fixed bug #300 : N8_WriteContext does not check length parameter.
86 * 11/07/01 hml Ensured that validateContextHandle only release a semaphore
87 * if it has acquired it (BUG 236).
88 * 11/05/01 hml Added some error checking and the structure verification.
89 * 10/11/01 brr Fixed memory leak in N8_ReadContext.
90 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
91 * 10/01/01 hml Completed multichip support.
92 * 09/20/01 hml Added multichip support.
93 * 09/20/01 bac The interface to the command block generators changed and now
94 * accept the command block buffer. All calls to cb_ea methods
96 * 09/18/01 bac Reformat to standardize, changed interaction with cb_ea
98 * 09/13/01 mel Added event parameter to N8_FreeContext.
99 * 08/29/01 mel Fixed bug #191 : bad DBG print statement.
100 * 08/27/01 mel Added Write/Read context APIs.
101 * 08/20/01 hml Fixed bug in allocate context getting wrong semaphore.
102 * 08/08/01 hml Added use of semaphore to protect the context table.
103 * 08/06/01 bac Fixed a bug in the result handler where it was freeing a
104 * request though it should not.
105 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
106 * 07/30/01 bac Pass chip id to createEARequestBuffer.
107 * 06/25/01 bac Small bug fix for allocationg ccm_register_gp.
108 * 06/20/01 mel Corrected use of kernel memory.
109 * 05/21/01 bac Converted to use N8_ContextHandle_t.
110 * 05/04/01 bac Removed include of n8_define as it duplicated n8_util
112 * 04/16/01 mel Original version.
113 ****************************************************************************/
114 /** @defgroup Context Context Management
118 #include "n8_cb_ea.h" /* contains encryption/authentication qeueu declarations */
121 #include "n8_API_Initialize.h"
122 #include "n8_common.h"
123 #include "n8_malloc_common.h"
126 /*****************************************************************************
128 *****************************************************************************/
130 * @brief Allocates a context entry for future use.
132 * The context index of the allocated context memory entry is returned in
133 * contextIndex. The context memory entry must then be initialized by a call
134 * to Encrypt Initialize or Packet Initialize before it can be used in
135 * encrypt/decrypt or packet level operations. This call can fail if all
136 * context entries have been allocated. To avoid running out of context entries,
137 * N8_FreeContext should be called when a context entry is no longer needed.
139 * @param contextHandle_p WO: Unsigned integer >= 0 and less than
140 * 2 power of 18 specifying the context entry in context memory allocated to
141 * the caller and whose contents are initialized with Context.
144 * contextHandler_p - context entry in allocated context memory.
145 * ret - returns N8_STATUS_OK if successful or Error value.
148 * This function acquires the context list semaphore from the queue structure.
151 * N8_NO_MORE_RESOURCE - There are no more context memory entries available
152 * for allocation. The call may succeed at a later
153 * time if context entries are freed.
154 * N8_MALLOC_FAILED - for some reasons malloc is failed
156 *****************************************************************************/
157 N8_Status_t
N8_AllocateContext(N8_ContextHandle_t
*contextHandle_p
,
162 N8_Status_t ret
= N8_STATUS_OK
; /* the return status: OK or ERROR */
164 N8_Unit_t validatedUnit
= unitID
;
166 DBG(("N8_AllocateContext\n"));
173 CHECK_OBJECT(contextHandle_p
, ret
);
175 ret
= N8_ContextMemAlloc(&validatedUnit
, &index
);
177 if (ret
== N8_STATUS_OK
)
179 contextHandle_p
->index
= index
; /* return allocated context index */
180 contextHandle_p
->inUse
= N8_TRUE
;
181 contextHandle_p
->unitID
= validatedUnit
;
182 /* set the structure pointer to the correct state */
183 contextHandle_p
->structureID
= N8_CONTEXT_STRUCT_ID
;
185 DBG(("Context index %d\n", index
));
189 DBG(("N8_AllocateContext - FINISHED\n"));
192 } /* N8_AllocateContext */
195 /*****************************************************************************
197 *****************************************************************************/
199 * @brief Frees previously allocated context entry and allows for its later re-use.
201 * ContextIndex specifies the context memory entry to be deallocated. The contents
202 * of the entry are cleared to zero when this call is made. Any further calls made
203 * with this ContextIndex value will fail (until the entry is re-allocated by an
204 * N8_AllocateContext call). Context memory entries must be freed when no
205 * longer needed to avoid exhausting the supply. Note that by adding the
206 * MEMORY_IN_PROGRESS state we are able to avoid having to use the context
207 * lock in the callback function.
209 * @param ctxHndl RO: A previously allocated context entry value as returned
210 * from N8_AllocateContext that is to be freed.
213 * ret - returns N8_STATUS_OK if successful or Error value.
216 * N8_INVALID_PARAMETER - The value of contextIndex is less than 0 or more
217 * than (2 power of 18) - 1.
218 * N8_UNALLOCATED_CONTEXT - contextIndex does not specify an allocated context
222 * This function acquires the context list semaphore from the queue structure.
223 * Note that we make sure the lock is released before we queue the request.
226 * Limited error checking is done, and if the user makes errors such as
227 * specifying the wrong context entry for a call (e.g., specifying a context
228 * entry containing an ARC4 key for encrypting an SSL packet on a connection
229 * established with DES in the cipher suite), incorrect results will be
230 * produced without a warning or error occurring
231 *****************************************************************************/
232 N8_Status_t
N8_FreeContext(N8_ContextHandle_t ctxHndl
,
236 N8_Status_t ret
= N8_STATUS_OK
; /* the return status: OK or ERROR */
238 DBG(("N8_FreeContext\n"));
245 if (ctxHndl
.inUse
!= N8_TRUE
)
247 ret
= N8_UNALLOCATED_CONTEXT
;
251 if (ctxHndl
.structureID
!= N8_CONTEXT_STRUCT_ID
)
253 ret
= N8_INVALID_PARAMETER
;
257 ret
= N8_ContextMemFree(ctxHndl
.unitID
, ctxHndl
.index
);
259 DBG(("ctxHndl.index = %d\n", ctxHndl
.index
));
265 N8_SET_EVENT_FINISHED(event_p
, N8_EA
);
268 DBG(("N8_FreeContext - FINISHED\n"));
272 } /* N8_FreeContext */
274 /*****************************************************************************
276 *****************************************************************************/
278 * @brief Writes a context entry for future use.
280 * Writes ContextLength number of bytes from Context into the crypto controller
281 * context memory entry denoted by ContextHandle. Up to 512 bytes may be loaded
282 * into a context entry; if less than 512 bytes are supplied the remaining bytes
283 * will be set to bytes of 0. The content / format of the bytes depends on the
284 * intended use, and is specified in the Crypto Controller specification [CCH].
285 * However this routine simply treats them as uninterpreted values; no checking
286 * or processing of the bytes written to the context entry is done. All previous
287 * contents of the context entry are overwritten and lost. It is important to note
288 * that the context information is treated by the hardware as a sequence of 32-bit
289 * values; the byte values written to a hardware context by this call are written
290 * by the hardware as a series of 32-bit quantities, and these 32-bit values must
291 * be in the appropriate big endian or little endian format depending on the byte
292 * order of the host processor. A context read from the hardware via N8_ReadContext
293 * is read in this same way, and is always in the proper format to be written back
294 * via N8_WriteContext
296 * @param contextHandle RO: The handle of a previously allocated context
297 * entry as returned by N8_AllocateContext.
299 * @param context_p RO: The bytes to be written to the context entry
300 * @param contextLength RO: Length of Context in bytes, from 0 to 512
301 * bytes inclusive. A length of 0 is legal,
302 * but no bytes will actually be written
303 * @param event_p RW: On input, if null the call is synchronous
304 * and no event is returned. The operation is
305 * complete when the call returns. If non-null,
306 * then the call is asynchronous; an event is
307 * returned that can be used to determine when
308 * the operation completes
312 * ret - returns N8_STATUS_OK if successful or Error value.
315 * This function acquires the context list semaphore from the queue structure.
318 * N8_NO_MORE_RESOURCE - There are no more context memory entries available
319 * for allocation. The call may succeed at a later
320 * time if context entries are freed.
321 * N8_MALLOC_FAILED - for some reasons malloc is failed
322 * N8_INVALID_INPUT_SIZE - context length is more than 512
323 * N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
325 *****************************************************************************/
326 N8_Status_t
N8_WriteContext(N8_ContextHandle_t contextHandle
,
327 N8_Buffer_t
*context_p
,
328 uint32_t contextLength
,
329 N8_Event_t
*event_p
)
333 N8_Status_t ret
= N8_STATUS_OK
; /* the return status: OK or ERROR */
334 API_Request_t
*req_p
= NULL
; /* request buffer */
335 N8_Boolean_t unitValid
;
337 DBG(("N8_WriteContext\n"));
344 CHECK_OBJECT(context_p
, ret
);
346 if ((int)context_p
% 4)
348 ret
= N8_UNALIGNED_ADDRESS
;
352 if (contextLength
> EA_CTX_Record_Byte_Length
)
354 ret
= N8_INVALID_INPUT_SIZE
;
358 CHECK_STRUCTURE(contextHandle
.structureID
,
359 N8_CONTEXT_STRUCT_ID
,
362 unitValid
= n8_validateUnit(contextHandle
.unitID
);
365 ret
= N8_INVALID_UNIT
;
369 ret
= N8_ContextMemValidate(contextHandle
.unitID
, contextHandle
.index
);
372 /* allocate request buffer */
373 ret
= createEARequestBuffer(&req_p
,
374 contextHandle
.unitID
,
375 N8_CB_EA_WRITECONTEXT_NUMCMDS
,
376 resultHandlerGeneric
,
380 /* create "write buffer to context memory" command */
381 ret
= cb_ea_writeContext(req_p
,
382 req_p
->EA_CommandBlock_ptr
,
387 /* nothing needs to be done in the result handler. it will be called only
388 * to print a debug messag if an error occurs. */
390 /* send command to write to specified context memory */
391 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
392 HANDLE_EVENT(event_p
, req_p
, ret
);
396 DBG(("N8_WriteContext - FINISHED\n"));
399 * Deallocate the request if we arrived from an error condition.
401 if (ret
!= N8_STATUS_OK
)
406 } /* N8_WriteContext */
409 /*****************************************************************************
411 *****************************************************************************/
413 * @brief Reads a context entry.
415 * Copies ContextLength number of bytes from the crypto controller context
416 * memory context entry specified by ContextHandle into Context. The contents
417 * of the context memory entry are unchanged. Up to 512 bytes [This value should
418 * really be some sort of configuration constant or value defined that the user
419 * can determine at run time.] may be read from a context entry. If the
420 * specified context entry has not previously been initialized with
421 * N8_EncryptInitialize or N8_PacketInitialize or written with an N8_WriteContext
422 * call, then the bytes returned are undefined. The actual content / format of
423 * the bytes returned depends on how the context entry was used, and is
424 * specified in the Crypto Controller specification [CCH]. However
425 * N8_ReadContext simply treats them as uninterpreted values, suitable for
426 * reloading at a later time using N8_WriteContext. No checking or processing
427 * of the bytes read from the context entry is done. It is important to note
428 * that the context information is treated by the hardware as a sequence of
429 * 32-bit values; the byte values read from a hardware context and returned
430 * by this call are returned as a series of 32-bit quantities, and these
431 * 32-bit values will be returned in either big endian or little endian format
432 * depending on the byte order of the host processor.
434 * @param contextHandle RO: The handle of a previously allocated context
435 * entry as returned by N8_AllocateContext.
437 * @param context_p RO: The bytes to be written to the context entry
438 * @param contextLength RO: Length of Context in bytes, from 0 to 512
439 * bytes inclusive. A length of 0 is legal,
440 * but no bytes will actually be written
441 * @param event_p RW: On input, if null the call is synchronous
442 * and no event is returned. The operation is
443 * complete when the call returns. If non-null,
444 * then the call is asynchronous; an event is
445 * returned that can be used to determine when
446 * the operation completes
449 * ret - returns N8_STATUS_OK if successful or Error value.
452 * This function acquires the context list semaphore from the queue structure.
455 * N8_NO_MORE_RESOURCE - There are no more context memory entries available
456 * for allocation. The call may succeed at a later
457 * time if context entries are freed.
458 * N8_MALLOC_FAILED - for some reasons malloc is failed
459 * N8_INVALID_INPUT_SIZE - context length is more than 512
460 * N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
462 *****************************************************************************/
463 N8_Status_t
N8_ReadContext(N8_ContextHandle_t contextHandle
,
464 N8_Buffer_t
*context_p
,
465 uint32_t contextLength
,
466 N8_Event_t
*event_p
)
470 N8_Status_t ret
= N8_STATUS_OK
; /* return status*/
471 API_Request_t
*req_p
= NULL
; /* request buffer */
472 N8_Buffer_t
*contextMemory_p
= NULL
;
473 uint32_t contextMemory_a
;
474 N8_Boolean_t unitValid
;
476 DBG(("N8_ReadContext\n"));
483 CHECK_OBJECT(context_p
, ret
);
485 if ((int)context_p
% 4)
487 ret
= N8_UNALIGNED_ADDRESS
;
491 if (contextLength
> EA_CTX_Record_Byte_Length
)
493 ret
= N8_INVALID_INPUT_SIZE
;
497 CHECK_STRUCTURE(contextHandle
.structureID
,
498 N8_CONTEXT_STRUCT_ID
,
501 unitValid
= n8_validateUnit(contextHandle
.unitID
);
504 ret
= N8_INVALID_UNIT
;
508 ret
= N8_ContextMemValidate(contextHandle
.unitID
, contextHandle
.index
);
511 /* allocate request buffer */
512 ret
= createEARequestBuffer(&req_p
,
513 contextHandle
.unitID
,
514 N8_CB_EA_READCONTEXT_NUMCMDS
,
515 resultHandlerGeneric
,
519 contextMemory_p
= (N8_Buffer_t
*) ((int)req_p
+ req_p
->dataoffset
);
520 contextMemory_a
= req_p
->qr
.physicalAddress
+ req_p
->dataoffset
;
522 req_p
->copyBackTo_p
= context_p
;
523 req_p
->copyBackFrom_p
= contextMemory_p
;
524 req_p
->copyBackSize
= contextLength
;
526 /* create "write buffer to context memory" command */
527 ret
= cb_ea_readContext(req_p
,
528 req_p
->EA_CommandBlock_ptr
,
534 /* send command to write to specified context memory */
535 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
536 HANDLE_EVENT(event_p
, req_p
, ret
);
540 DBG(("N8_ReadContext - FINISHED\n"));
543 * Deallocate the request if we arrived from an error condition.
545 if (ret
!= N8_STATUS_OK
)
550 } /* N8_ReadContext */