1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
|
/*-
* Copyright (C) 2001-2003 by NBMK Encryption Technologies.
* All rights reserved.
*
* NBMK Encryption Technologies provides no support of any kind for
* this software. Questions or concerns about it may be addressed to
* the members of the relevant open-source community at
* <tech-crypto@netbsd.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
static char const n8_id[] = "$Id: n8_contextM.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
/*****************************************************************************/
/** @file n8_contextM.c
* @brief Contains Crypto Context management Interface.
*
* Managing the context memory is left to the user.
* SAPI provides interfaces to allocate and initialize a context entry, and to
* free an entry. The user must allocate and initialize a context entry before
* it can be used (presumably when an SSL connection is opened), specify which
* context entry to use in the calls that require context memory, and finally
* free the context entry when finished (presumably when an SSL connection is
* closed). Limited error checking is done, and if the user makes errors such as
* specifying the wrong context entry for a call (e.g., specifying a context
* entry containing an ARC4 key for encrypting an SSL packet on a connection
* established with DES in the cipher suite), incorrect results will be
* produced without a warning or error occurring.
*
*****************************************************************************/
/*****************************************************************************
* Revision history:
* 05/20/03 brr Remove obsolete functions resultHandlerFreeContext &
* n8_numCommandsToLoadContext
* 05/20/02 brr Free the request for all error conditions.
* 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
* 03/29/02 hml Now validate the unit and the context in
* N8_Read/WriteContext. (BUGS 657, 658).
* 03/26/02 hml Enhanced N8_AllocateContext and N8_FreeContext to retrieve
* the status from the lower level calls. (Bugs 637,642).
* 03/26/02 brr Allocate the data buffer as part of the API request.
* 03/22/02 hml Removed unneeded sessionID param from call to
* N8_ContextMemAlloc.
* 03/18/02 brr Removed obsolete references to queue_p & validateContextHandle.
* 02/28/02 brr Do not include any QMgr include files.
* 02/18/02 brr Support queue selection.
* 02/15/02 brr Moved context memory management to the driver.
* 01/25/02 bac Changed allocation search algorithm to always start at the
* index after the one last assigned. This should be a much
* better search than simply starting at the beginning every
* time, which clusters the allocated contexts from 0..n.
* 01/22/02 bac Added function n8_numCommandsToLoadContext.
* 01/22/02 bac Conditionally removed the clearing of context memory when
* N8_FreeContext is called.
* 12/07/01 brr Removed userID to reduce memory consumption until supported.
* 12/07/01 mel Fixed bug #404: added checks for aligned address.
* 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
* 11/12/01 hml Fixed bug for freeing lock not held.
* 11/08/01 mel Fixed bug #289 : by passing unitID parameter
* 11/08/01 mel Fixed comments (bug #292).
* 11/08/01 mel Fixed bug #299 : N8_ReadContext does not check length parameter.
* Fixed bug #300 : N8_WriteContext does not check length parameter.
* 11/07/01 hml Ensured that validateContextHandle only release a semaphore
* if it has acquired it (BUG 236).
* 11/05/01 hml Added some error checking and the structure verification.
* 10/11/01 brr Fixed memory leak in N8_ReadContext.
* 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
* 10/01/01 hml Completed multichip support.
* 09/20/01 hml Added multichip support.
* 09/20/01 bac The interface to the command block generators changed and now
* accept the command block buffer. All calls to cb_ea methods
* changed herein.
* 09/18/01 bac Reformat to standardize, changed interaction with cb_ea
* functions.
* 09/13/01 mel Added event parameter to N8_FreeContext.
* 08/29/01 mel Fixed bug #191 : bad DBG print statement.
* 08/27/01 mel Added Write/Read context APIs.
* 08/20/01 hml Fixed bug in allocate context getting wrong semaphore.
* 08/08/01 hml Added use of semaphore to protect the context table.
* 08/06/01 bac Fixed a bug in the result handler where it was freeing a
* request though it should not.
* 07/31/01 bac Added call to N8_preamble for all public interfaces.
* 07/30/01 bac Pass chip id to createEARequestBuffer.
* 06/25/01 bac Small bug fix for allocationg ccm_register_gp.
* 06/20/01 mel Corrected use of kernel memory.
* 05/21/01 bac Converted to use N8_ContextHandle_t.
* 05/04/01 bac Removed include of n8_define as it duplicated n8_util
* definitions.
* 04/16/01 mel Original version.
****************************************************************************/
/** @defgroup Context Context Management
*/
#include "n8_cb_ea.h" /* contains encryption/authentication qeueu declarations */
#include "n8_util.h"
#include "n8_API_Initialize.h"
#include "n8_common.h"
#include "n8_malloc_common.h"
/*****************************************************************************
* N8_AllocateContext
*****************************************************************************/
/** @ingroup Context
* @brief Allocates a context entry for future use.
*
* The context index of the allocated context memory entry is returned in
* contextIndex. The context memory entry must then be initialized by a call
* to Encrypt Initialize or Packet Initialize before it can be used in
* encrypt/decrypt or packet level operations. This call can fail if all
* context entries have been allocated. To avoid running out of context entries,
* N8_FreeContext should be called when a context entry is no longer needed.
*
* @param contextHandle_p WO: Unsigned integer >= 0 and less than
* 2 power of 18 specifying the context entry in context memory allocated to
* the caller and whose contents are initialized with Context.
*
* @return
* contextHandler_p - context entry in allocated context memory.
* ret - returns N8_STATUS_OK if successful or Error value.
*
* @par Locks:
* This function acquires the context list semaphore from the queue structure.
*
* @par Errors:
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
* for allocation. The call may succeed at a later
* time if context entries are freed.
* N8_MALLOC_FAILED - for some reasons malloc is failed
*
*****************************************************************************/
N8_Status_t N8_AllocateContext(N8_ContextHandle_t *contextHandle_p,
N8_Unit_t unitID)
{
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
unsigned int index;
N8_Unit_t validatedUnit = unitID;
DBG(("N8_AllocateContext\n"));
do
{
ret = N8_preamble();
CHECK_RETURN(ret);
CHECK_OBJECT(contextHandle_p, ret);
ret = N8_ContextMemAlloc(&validatedUnit, &index);
if (ret == N8_STATUS_OK)
{
contextHandle_p->index = index; /* return allocated context index */
contextHandle_p->inUse = N8_TRUE;
contextHandle_p->unitID = validatedUnit;
/* set the structure pointer to the correct state */
contextHandle_p->structureID = N8_CONTEXT_STRUCT_ID;
DBG(("Context index %d\n", index));
}
} while(FALSE);
DBG(("N8_AllocateContext - FINISHED\n"));
return ret;
} /* N8_AllocateContext */
/*****************************************************************************
* N8_FreeContext
*****************************************************************************/
/** @ingroup Context
* @brief Frees previously allocated context entry and allows for its later re-use.
*
* ContextIndex specifies the context memory entry to be deallocated. The contents
* of the entry are cleared to zero when this call is made. Any further calls made
* with this ContextIndex value will fail (until the entry is re-allocated by an
* N8_AllocateContext call). Context memory entries must be freed when no
* longer needed to avoid exhausting the supply. Note that by adding the
* MEMORY_IN_PROGRESS state we are able to avoid having to use the context
* lock in the callback function.
*
* @param ctxHndl RO: A previously allocated context entry value as returned
* from N8_AllocateContext that is to be freed.
*
* @return
* ret - returns N8_STATUS_OK if successful or Error value.
*
* @par Errors:
* N8_INVALID_PARAMETER - The value of contextIndex is less than 0 or more
* than (2 power of 18) - 1.
* N8_UNALLOCATED_CONTEXT - contextIndex does not specify an allocated context
* entry index.
*
* @par Locks:
* This function acquires the context list semaphore from the queue structure.
* Note that we make sure the lock is released before we queue the request.
*
* @par Assumptions:
* Limited error checking is done, and if the user makes errors such as
* specifying the wrong context entry for a call (e.g., specifying a context
* entry containing an ARC4 key for encrypting an SSL packet on a connection
* established with DES in the cipher suite), incorrect results will be
* produced without a warning or error occurring
*****************************************************************************/
N8_Status_t N8_FreeContext(N8_ContextHandle_t ctxHndl,
N8_Event_t *event_p)
{
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
DBG(("N8_FreeContext\n"));
do
{
ret = N8_preamble();
CHECK_RETURN(ret);
if (ctxHndl.inUse != N8_TRUE)
{
ret = N8_UNALLOCATED_CONTEXT;
break;
}
if (ctxHndl.structureID != N8_CONTEXT_STRUCT_ID)
{
ret = N8_INVALID_PARAMETER;
break;
}
ret = N8_ContextMemFree(ctxHndl.unitID, ctxHndl.index);
DBG(("ctxHndl.index = %d\n", ctxHndl.index));
} while(FALSE);
if (event_p != NULL)
{
N8_SET_EVENT_FINISHED(event_p, N8_EA);
}
DBG(("N8_FreeContext - FINISHED\n"));
return ret;
} /* N8_FreeContext */
/*****************************************************************************
* N8_WriteContext
*****************************************************************************/
/** @ingroup Context
* @brief Writes a context entry for future use.
*
* Writes ContextLength number of bytes from Context into the crypto controller
* context memory entry denoted by ContextHandle. Up to 512 bytes may be loaded
* into a context entry; if less than 512 bytes are supplied the remaining bytes
* will be set to bytes of 0. The content / format of the bytes depends on the
* intended use, and is specified in the Crypto Controller specification [CCH].
* However this routine simply treats them as uninterpreted values; no checking
* or processing of the bytes written to the context entry is done. All previous
* contents of the context entry are overwritten and lost. It is important to note
* that the context information is treated by the hardware as a sequence of 32-bit
* values; the byte values written to a hardware context by this call are written
* by the hardware as a series of 32-bit quantities, and these 32-bit values must
* be in the appropriate big endian or little endian format depending on the byte
* order of the host processor. A context read from the hardware via N8_ReadContext
* is read in this same way, and is always in the proper format to be written back
* via N8_WriteContext
*
* @param contextHandle RO: The handle of a previously allocated context
* entry as returned by N8_AllocateContext.
* @param context_p RO: The bytes to be written to the context entry
* @param contextLength RO: Length of Context in bytes, from 0 to 512
* bytes inclusive. A length of 0 is legal,
* but no bytes will actually be written
* @param event_p RW: On input, if null the call is synchronous
* and no event is returned. The operation is
* complete when the call returns. If non-null,
* then the call is asynchronous; an event is
* returned that can be used to determine when
* the operation completes
*
*
* @return
* ret - returns N8_STATUS_OK if successful or Error value.
*
* @par Locks:
* This function acquires the context list semaphore from the queue structure.
*
* @par Errors:
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
* for allocation. The call may succeed at a later
* time if context entries are freed.
* N8_MALLOC_FAILED - for some reasons malloc is failed
* N8_INVALID_INPUT_SIZE - context length is more than 512
* N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
*
*****************************************************************************/
N8_Status_t N8_WriteContext(N8_ContextHandle_t contextHandle,
N8_Buffer_t *context_p,
uint32_t contextLength,
N8_Event_t *event_p )
{
N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
API_Request_t *req_p = NULL; /* request buffer */
N8_Boolean_t unitValid;
DBG(("N8_WriteContext\n"));
do
{
ret = N8_preamble();
CHECK_RETURN(ret);
CHECK_OBJECT(context_p, ret);
if ((int)context_p % 4)
{
ret = N8_UNALIGNED_ADDRESS;
break;
}
if (contextLength > EA_CTX_Record_Byte_Length)
{
ret = N8_INVALID_INPUT_SIZE;
break;
}
CHECK_STRUCTURE(contextHandle.structureID,
N8_CONTEXT_STRUCT_ID,
ret);
unitValid = n8_validateUnit(contextHandle.unitID);
if (!unitValid)
{
ret= N8_INVALID_UNIT;
break;
}
ret = N8_ContextMemValidate(contextHandle.unitID, contextHandle.index);
CHECK_RETURN(ret);
/* allocate request buffer */
ret = createEARequestBuffer(&req_p,
contextHandle.unitID,
N8_CB_EA_WRITECONTEXT_NUMCMDS,
resultHandlerGeneric,
CONTEXT_ENTRY_SIZE);
CHECK_RETURN(ret);
/* create "write buffer to context memory" command */
ret = cb_ea_writeContext(req_p,
req_p->EA_CommandBlock_ptr,
contextHandle.index,
context_p,
contextLength);
CHECK_RETURN(ret);
/* nothing needs to be done in the result handler. it will be called only
* to print a debug messag if an error occurs. */
/* send command to write to specified context memory */
QUEUE_AND_CHECK(event_p, req_p, ret);
HANDLE_EVENT(event_p, req_p, ret);
} while(FALSE);
DBG(("N8_WriteContext - FINISHED\n"));
/*
* Deallocate the request if we arrived from an error condition.
*/
if (ret != N8_STATUS_OK)
{
freeRequest(req_p);
}
return ret;
} /* N8_WriteContext */
/*****************************************************************************
* N8_ReadContext
*****************************************************************************/
/** @ingroup Context
* @brief Reads a context entry.
*
* Copies ContextLength number of bytes from the crypto controller context
* memory context entry specified by ContextHandle into Context. The contents
* of the context memory entry are unchanged. Up to 512 bytes [This value should
* really be some sort of configuration constant or value defined that the user
* can determine at run time.] may be read from a context entry. If the
* specified context entry has not previously been initialized with
* N8_EncryptInitialize or N8_PacketInitialize or written with an N8_WriteContext
* call, then the bytes returned are undefined. The actual content / format of
* the bytes returned depends on how the context entry was used, and is
* specified in the Crypto Controller specification [CCH]. However
* N8_ReadContext simply treats them as uninterpreted values, suitable for
* reloading at a later time using N8_WriteContext. No checking or processing
* of the bytes read from the context entry is done. It is important to note
* that the context information is treated by the hardware as a sequence of
* 32-bit values; the byte values read from a hardware context and returned
* by this call are returned as a series of 32-bit quantities, and these
* 32-bit values will be returned in either big endian or little endian format
* depending on the byte order of the host processor.
*
* @param contextHandle RO: The handle of a previously allocated context
* entry as returned by N8_AllocateContext.
* @param context_p RO: The bytes to be written to the context entry
* @param contextLength RO: Length of Context in bytes, from 0 to 512
* bytes inclusive. A length of 0 is legal,
* but no bytes will actually be written
* @param event_p RW: On input, if null the call is synchronous
* and no event is returned. The operation is
* complete when the call returns. If non-null,
* then the call is asynchronous; an event is
* returned that can be used to determine when
* the operation completes
*
* @return
* ret - returns N8_STATUS_OK if successful or Error value.
*
* @par Locks:
* This function acquires the context list semaphore from the queue structure.
*
* @par Errors:
* N8_NO_MORE_RESOURCE - There are no more context memory entries available
* for allocation. The call may succeed at a later
* time if context entries are freed.
* N8_MALLOC_FAILED - for some reasons malloc is failed
* N8_INVALID_INPUT_SIZE - context length is more than 512
* N8_UNALIGNED_ADDRESS - passed address (context_p) is not 32-bit aligned
*
*****************************************************************************/
N8_Status_t N8_ReadContext(N8_ContextHandle_t contextHandle,
N8_Buffer_t *context_p,
uint32_t contextLength,
N8_Event_t *event_p )
{
N8_Status_t ret = N8_STATUS_OK; /* return status*/
API_Request_t *req_p = NULL; /* request buffer */
N8_Buffer_t *contextMemory_p = NULL;
uint32_t contextMemory_a;
N8_Boolean_t unitValid;
DBG(("N8_ReadContext\n"));
do
{
ret = N8_preamble();
CHECK_RETURN(ret);
CHECK_OBJECT(context_p, ret);
if ((int)context_p % 4)
{
ret = N8_UNALIGNED_ADDRESS;
break;
}
if (contextLength > EA_CTX_Record_Byte_Length)
{
ret = N8_INVALID_INPUT_SIZE;
break;
}
CHECK_STRUCTURE(contextHandle.structureID,
N8_CONTEXT_STRUCT_ID,
ret);
unitValid = n8_validateUnit(contextHandle.unitID);
if (!unitValid)
{
ret= N8_INVALID_UNIT;
break;
}
ret = N8_ContextMemValidate(contextHandle.unitID, contextHandle.index);
CHECK_RETURN(ret);
/* allocate request buffer */
ret = createEARequestBuffer(&req_p,
contextHandle.unitID,
N8_CB_EA_READCONTEXT_NUMCMDS,
resultHandlerGeneric,
CONTEXT_ENTRY_SIZE);
CHECK_RETURN(ret);
contextMemory_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
contextMemory_a = req_p->qr.physicalAddress + req_p->dataoffset;
req_p->copyBackTo_p = context_p;
req_p->copyBackFrom_p = contextMemory_p;
req_p->copyBackSize = contextLength;
/* create "write buffer to context memory" command */
ret = cb_ea_readContext(req_p,
req_p->EA_CommandBlock_ptr,
contextHandle.index,
contextMemory_a,
contextLength);
CHECK_RETURN(ret);
/* send command to write to specified context memory */
QUEUE_AND_CHECK(event_p, req_p, ret);
HANDLE_EVENT(event_p, req_p, ret);
} while(FALSE);
DBG(("N8_ReadContext - FINISHED\n"));
/*
* Deallocate the request if we arrived from an error condition.
*/
if (ret != N8_STATUS_OK)
{
freeRequest(req_p);
}
return ret;
} /* N8_ReadContext */
|