Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_cryptographic.c
bloba68797bf0cbe54629b1bc5d21e34adeea1aca3ce
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_cryptographic.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_cryptographic.c
38 * @brief Contains packet functions.
40 * Functions:
41 * N8_EncryptInitialize - Initializes the encrypt object object.
42 * N8_EncryptPartial - Perform a partial encryption.
43 * N8_EncryptEnd - Complete an in-progress partial encryption.
44 * N8_Encrypt - Perform a complete encryption.
45 * N8_DecryptPartial - Perform a partial decryption.
46 * N8_DecryptEnd - Complete an in-progress partial decryption.
47 * N8_Decrypt - Perform a complete decryption.
49 *****************************************************************************/
51 /*****************************************************************************
52 * Revision history:
53 * 06/06/03 brr Move n8_enums to public include as n8_pub_enums.
54 * 05/27/03 brr Removed N8_preamble call since N8_PacketInitialize must be
55 * called prior to Encrypt/Decrypt operations.
56 * 05/20/03 brr Remove include of obsolete n8_contextM.h & n8_cryptographic.h.
57 * 09/23/02 bac Fixed bug #870 by initializing residualLength to zero.
58 * 06/18/02 bac When Encrypt and EncryptEnd were adding padding, the portion
59 * added was not being set to 0x0. (Bug #808)
60 * 06/15/02 brr Check message length ptr in N8_EncryptPartial & N8_EncryptEnd.
61 * 06/11/02 bac Check for null context in N8_EncryptInitialize when using
62 * ARC4. Return N8_UNALLOCATED_CONTEXT when the magic number is
63 * not correct. (Bug #776)
64 * 06/11/02 bac Check for invalid unit in N8_EncryptInitialize. (Bug #777)
65 * 06/10/02 bac Fixed N8_Decrypt and N8_DecryptEnd to return
66 * N8_INVALID_INPUT_SIZE instead of padding. (Bug #775)
67 * 05/22/02 brr Check message length ptr in N8_DecryptPartial & N8_DecryptEnd.
68 * 05/20/02 brr Free the request for all error conditions.
69 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
70 * 03/26/02 brr Allocate the data buffer as part of the API request.
71 * 02/28/02 brr Do not include any QMgr include files.
72 * 02/25/02 brr Removed last references to the QMgr.
73 * 01/31/02 brr Eliminated the memory allocation for postProcessingData.
74 * 12/18/01 mel Deleted illegal operations with contextHandle
75 * 11/28/01 mel Fixed bug #381: EncryptInitialize needs to force parity before
76 * DES weakkeys check.
77 * 11/27/01 bac Removed unnecessary CHECK_RETURNs after QUEUE_AND_CHECKs.
78 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
79 * 11/09/01 hml Added structure verification code.
80 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
81 * 09/28/01 bac Clean up regarding use of const in parameter lists.
82 * 09/28/01 bac Further development changes. Fixes to work for context use.
83 * 09/24/01 hml Added unit specifer for multi-chip.
84 * 09/21/01 bac Fixed bug to prevent request from being freed twice.
85 * 09/20/01 bac Continued development. Massive changes.
86 * 09/18/01 bac Substantial re-write to properly use kernel memory, event
87 * processing, and async support.
88 * 09/14/01 mel Added event parameter to N8_FreeContext.
89 * 09/06/01 bac Fixed doxygen groupings.
90 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
91 * 06/07/01 mel Original version.
92 ****************************************************************************/
93 /** @defgroup crypto Cryptographic API Packet-Level functions
96 #include "n8_common.h" /* common definitions */
97 #include "n8_pub_errors.h" /* Errors definition */
98 #include "n8_enqueue_common.h" /* common definitions for enqueue */
99 #include "n8_cb_ea.h"
100 #include "n8_util.h"
101 #include "n8_key_works.h"
102 #include "n8_packet.h"
103 #include "n8_API_Initialize.h"
104 #include "n8_pub_enums.h"
105 #include <opencrypto/cryptodev.h>
107 #define NO_CALLBACK_FCN NULL
110 * Local structures used only for transfering data to the call back functions.
112 typedef struct
114 unsigned int *encryptedMsgLen_p;
115 N8_EncryptObject_t *encryptObject_p;
116 uint32_t *nextIV_p;
117 } encryptData_t;
120 * Local functions
122 static N8_Status_t verifyInputLength(const unsigned int len)
124 N8_Status_t ret = N8_STATUS_OK;
125 if (len > N8_MAX_MESSAGE_LENGTH)
127 DBG(("Message length is out of range\n"));
128 ret = N8_INVALID_INPUT_SIZE;
130 return ret;
132 static N8_Status_t checkCipher(N8_Cipher_t cipher)
134 N8_Status_t ret = N8_STATUS_OK;
135 switch (cipher)
137 case N8_CIPHER_ARC4:
138 case N8_CIPHER_DES:
139 break;
140 default:
141 ret = N8_INVALID_CIPHER;
142 break;
144 return ret;
147 static void performCopyBack(API_Request_t* req_p)
149 if (req_p->copyBackSize > 0 &&
150 req_p->copyBackFrom_p != NULL &&
151 (req_p->copyBackTo_p != NULL || req_p->copyBackTo_uio != NULL))
153 #if N8DEBUG
154 DBG(("copyBackSize = %d\n", req_p->copyBackSize));
155 DBG(("results: "));
156 printN8Buffer((N8_Buffer_t *) req_p->copyBackFrom_p, req_p->copyBackSize);
157 #endif
158 if (req_p->copyBackTo_p != NULL) {
159 #if N8DEBUG
160 DBG(("memcpy\n"));
161 #endif
162 memcpy(req_p->copyBackTo_p,
163 req_p->copyBackFrom_p,
164 req_p->copyBackSize);
165 } else {
166 #if N8DEBUG
167 DBG(("cuio_copyback\n"));
168 #endif
169 cuio_copyback(req_p->copyBackTo_uio, 0,
170 req_p->copyBackSize,
171 req_p->copyBackFrom_p);
174 else
176 DBG(("no copy back given\n"));
180 static void resultHandler(API_Request_t* req_p)
182 char title[] = "N8_cryptographic result handler";
183 encryptData_t *callBackData_p = (encryptData_t *) req_p->postProcessingData_p;
185 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
187 DBG(("%s called with success\n", title));
188 performCopyBack(req_p);
189 if (callBackData_p != NULL)
191 N8_EncryptObject_t *encryptObject_p = callBackData_p->encryptObject_p;
192 /* update IVs for DES*/
193 if (encryptObject_p->cipher == N8_CIPHER_DES &&
194 callBackData_p->nextIV_p != NULL)
196 memcpy(encryptObject_p->cipherInfo.key.keyDES.IV,
197 callBackData_p->nextIV_p, N8_DES_BLOCK_LENGTH);
198 #if N8DEBUG
199 DBG(("IV[ms]: "));
200 printN8Buffer((N8_Buffer_t *) encryptObject_p->cipherInfo.key.keyDES.IV,
201 N8_DES_BLOCK_LENGTH);
202 #endif
204 /* set the returned value for the encrypted message length */
205 *(callBackData_p->encryptedMsgLen_p) = req_p->copyBackSize;
208 else
210 RESULT_HANDLER_WARNING(title, req_p);
212 } /* resultHandler */
216 * External functions
219 /*****************************************************************************
220 * N8_EncryptInitialize
221 *****************************************************************************/
222 /** @ingroup crypto
223 * @brief Initializes (makes ready for use in encrypt and decrypt operations)
224 * the encrypt object specified by EncryptObject.
226 * An encryption object can be initialized for use with ARC4 or DES encryption /
227 * decryption. The encryption algorithm is specified by the enumerated value
228 * Cipher. The two permissible values for Cipher are ARC4 and DES. If Cipher is
229 * ARC4, then EncryptObject is initialized for use with ARC4 encryption /
230 * decryption. ARC4 operations require context memory, so ContextHandle must
231 * specify a valid context entry allocated by N8_AllocateContext that will be
232 * made part of EncryptObject. CipherInfo specifies the ARC4 key to use. The
233 * context entry denoted by ContextHandle is loaded with this key and will be
234 * used in subsequent N8_Encrypt or N8_Decrypt calls made with EncryptObject.
235 * If Cipher is DES, then EncryptObject is initialized for use with DES
236 * encryption / decryption. DES operations do not require context memory.
237 * ContextHandle may be null or may specify a valid context entry allocated by
238 * N8_AllocateContext that will be made part of EncryptObject. CipherInfo
239 * specifies the DES key material to use (including the initialization
240 * vector). If ContextHandle is null, then EncryptObject is initialized with the
241 * key material and can be used in subsequent N8_Encrypt or N8_Decrypt calls. If
242 * ContextHandle is non-null and valid, the context entry denoted by
243 * ContextHandle is loaded with this key material and will be used in subsequent
244 * N8_Encrypt or N8_Decrypt calls made with EncryptObject. DES keys will be
245 * checked for weak and semi-weak keys and such keys will be rejected. DES keys
246 * will not be checked for correct parity; the parity bits are ignored. (Before
247 * use in the hardware the parity will be set correctly so that hardware
248 * generated parity errors do not occur.)
250 * @param encryptObject_p WO: The encrypt object to be initialized with the
251 * specified information. The returned object can
252 * be used in subsequent N8_Encrypt or N8_Decrypt *
253 * calls
255 * @param contextHandle_p RO: A valid context handle as returned by
256 * N8_AllocateContext, if Cipher = ARC4. Optional
257 * (may be null), if Cipher = DES. The
258 * corresponding context memory entry is loaded for
259 * use in subsequent N8_Encrypt of Decrypt calls.
261 * @param cipher RO: One of the values ARC4 or DES.
263 * @param cipherInfo_p RO: The specific information to be used in the
264 * initialization. Its type and contents depend on
265 * the value of ContextType, as specified above.
268 * @return
269 * encryptObject_p - initialized encrypt object.
270 * ret - returns N8_STATUS_OK if successful or Error value.
272 * @par Errors:
273 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
274 * address<BR>
275 * N8_INVALID_CIPHER - The value of Cipher is not one of the legal values
276 * ARC4 or DES.<BR>
277 * N8_INVALID_VALUE - The value of ContextIndex is not a valid context
278 * index, or ContextIndex is null but a context index
279 * is required because ARC4 is specified or the
280 * unit value specified is invalid.<BR>
281 * N8_UNALLOCATED_CONTEXT - ContextIndex denotes a context memory index that
282 * has not been allocated by N8_AllocateContext.<BR>
283 * N8_INVALID_KEY_SIZE - The size of the key specified in CipherInfo_p is
284 * outside the valid range for the encryption algorithm
285 * specified in Cipher, or the size of an HMAC key
286 * specified in CipherInfo_p is outside the valid range
287 * for the hash algorithm specified in HashAlgorithm.<BR>
288 * N8_INCONSISTENT - The information in CipherInfo_p and/or its type is
289 * different than or inconsistent with the type
290 * specified by Cipher or HashAlgorithm, or the
291 * combination of values specified by Protocol, Cipher,
292 * and HashAlgorithm is invalid (for example, SSL is
293 * specified with HMAC-MD5, or IPSec is specified with ARC4).<BR>
294 * N8_MALLOC_FAILED - memory allocation failed
295 * N8_HARDWARE_ERROR - couldn't write to context memory
298 * @par Assumptions:
299 * Context entries (and hence ContextHandles) can only be used to hold one
300 * context at a time. The context entry specified in this call should not
301 * be in use with any other current encrypt object or packet object. This
302 * condition is not checked for; incorrect / indeterminate and / or errors
303 * are likely in this situation.
304 *****************************************************************************/
305 N8_Status_t N8_EncryptInitialize(N8_EncryptObject_t *encryptObject_p,
306 const N8_ContextHandle_t *contextHandle_p,
307 const N8_Cipher_t cipher,
308 N8_EncryptCipher_t *cipherInfo_p,
309 N8_Event_t *event_p)
312 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or
313 * ERROR */
314 int i;
316 API_Request_t *req_p = NULL; /* request buffer */
317 key_cblock_t key1, key2, key3; /* keys to be checked */
319 DBG(("N8_EncryptInitialize\n"));
323 ret = N8_preamble();
324 CHECK_RETURN(ret);
326 /* verify packet object */
327 CHECK_OBJECT(encryptObject_p, ret);
329 /* verify cipher object */
330 CHECK_OBJECT(cipherInfo_p, ret);
332 /* since we are initializing the object, set the residual length to
333 * zero. */
334 encryptObject_p->residualLength = 0;
336 /* if we are given a context handle */
337 if (contextHandle_p != NULL)
339 /* Make sure the context struct is valid */
340 if (contextHandle_p->structureID != N8_CONTEXT_STRUCT_ID)
342 ret = N8_UNALLOCATED_CONTEXT;
343 break;
346 /* copy the contents into our encryption object and set the context in
347 * use flag to true */
348 memcpy(&encryptObject_p->contextHandle,
349 contextHandle_p,
350 sizeof(N8_ContextHandle_t));
351 encryptObject_p->unitID = contextHandle_p->unitID;
352 encryptObject_p->contextHandle.inUse = N8_TRUE;
354 else
356 encryptObject_p->contextHandle.inUse = N8_FALSE;
357 encryptObject_p->contextHandle.index = 0xFFFF;
358 encryptObject_p->unitID = cipherInfo_p->unitID;
361 /* validate the unit */
362 if (n8_validateUnit(encryptObject_p->unitID) == N8_FALSE)
364 return N8_INVALID_UNIT;
365 break;
368 /* verify cipher */
369 switch (cipher)
371 case N8_CIPHER_ARC4:
373 /* verify that a valid context has been passed */
374 if (contextHandle_p == NULL)
376 ret = N8_INVALID_OBJECT;
377 break;
380 /* verify key size */
381 if((cipherInfo_p->keySize < 1) ||
382 (cipherInfo_p->keySize > ARC4_KEY_SIZE_BYTES_MAX))
384 DBG(("Key size specified for ARC4 "
385 "is outside the valid range: %d\n",
386 cipherInfo_p->keySize));
387 DBG(("N8_EncryptInitialize - return Error\n"));
388 ret = N8_INVALID_KEY_SIZE;
389 break;
392 /* create request buffer */
393 ret = createEARequestBuffer(&req_p,
394 encryptObject_p->unitID,
395 N8_CB_EA_LOADARC4KEYONLY_NUMCMDS,
396 NO_CALLBACK_FCN,
397 sizeof(EA_SSL30_CTX));
398 CHECK_RETURN(ret);
400 /* Initialize for use with ARC4 encryption/decryption */
401 ret = cb_ea_loadARC4keyOnly(req_p,
402 req_p->EA_CommandBlock_ptr,
403 &(encryptObject_p->contextHandle),
404 cipherInfo_p);
406 break;
408 case N8_CIPHER_DES:
409 /* verify key size */
411 if(cipherInfo_p->keySize != DES_KEY_SIZE_BYTES)
413 DBG(("Key size specified for DES "
414 "is outside the valid range: %d\n",
415 cipherInfo_p->keySize));
416 DBG(("N8_EncryptInitialize - return Error\n"));
417 ret = N8_INVALID_KEY_SIZE;
418 break;
421 /* build keys for parity verification */
422 /* force key parity */
423 for (i=0 ; i < sizeof(key_cblock_t); i++)
425 key1[i] = cipherInfo_p->key.keyDES.key1[i];
426 key2[i] = cipherInfo_p->key.keyDES.key2[i];
427 key3[i] = cipherInfo_p->key.keyDES.key3[i];
430 if (checkKeyParity(&key1) == N8_FALSE)
432 forceParity(&key1);
433 for (i=0 ; i < sizeof(key_cblock_t); i++)
435 cipherInfo_p->key.keyDES.key1[i] = key1[i];
438 if (checkKeyParity(&key2) == N8_FALSE)
440 forceParity(&key2);
441 for (i=0 ; i < sizeof(key_cblock_t); i++)
443 cipherInfo_p->key.keyDES.key2[i] = key2[i];
446 if (checkKeyParity(&key3) == N8_FALSE)
448 forceParity(&key3);
449 for (i=0 ; i < sizeof(key_cblock_t); i++)
451 cipherInfo_p->key.keyDES.key3[i] = key3[i];
455 if (checkKeyForWeakness(&key1) ||
456 checkKeyForWeakness(&key2) ||
457 checkKeyForWeakness(&key3))
459 ret = N8_WEAK_KEY;
460 break;
462 if (contextHandle_p != NULL)
464 /* create request buffer */
465 ret = createEARequestBuffer(&req_p,
466 encryptObject_p->unitID,
467 N8_CB_EA_LOADDESKEYONLY_NUMCMDS,
468 NO_CALLBACK_FCN,
469 sizeof(EA_SSL30_CTX));
470 CHECK_RETURN(ret);
472 /* DES context memory */
473 ret = cb_ea_loadDESkeyOnly(req_p,
474 req_p->EA_CommandBlock_ptr,
475 &(encryptObject_p->contextHandle),
476 cipherInfo_p);
478 break;
480 default:
481 /* invalid cipher */
482 DBG(("Invalid cipher\n"));
483 DBG(("N8_EncryptInitialize - return Error\n"));
484 ret = N8_INVALID_CIPHER;
485 break;
487 CHECK_RETURN(ret);
488 /* finish initialize packet object with protocol related values */
489 /* cipher info */
490 memcpy(&encryptObject_p->cipherInfo, cipherInfo_p, sizeof(N8_EncryptCipher_t));
491 /* encryption algorithm */
492 encryptObject_p->cipher = cipher;
494 if (req_p != NULL)
496 QUEUE_AND_CHECK(event_p, req_p, ret);
497 HANDLE_EVENT(event_p, req_p, ret);
499 else
501 if (event_p != NULL)
503 N8_SET_EVENT_FINISHED(event_p, N8_EA);
506 } while(FALSE);
509 * Deallocate the request if we arrived from an error condition.
511 if (ret != N8_STATUS_OK)
513 /* free the request */
514 freeRequest(req_p);
517 else
519 /* set the structure pointer to the correct state */
520 encryptObject_p->structureID = N8_ENCRYPT_STRUCT_ID;
523 DBG(("N8_EncryptInitialize - FINISHED\n"));
524 return ret;
525 } /* N8_EncryptInitialize */
527 /******************************************************************************
528 * N8_Encrypt
529 *****************************************************************************/
530 /** @ingroup crypto
531 * @brief Encrypts message.
533 * Using the encryption algorithm and context (keys, etc.) contained in
534 * EncryptObject, encrypt the plain text bytes in Message whose length is
535 * MessageLength bytes, returning the resulting cipher text bytes (including
536 * any pad bytes added during encryption) in EncryptedMessage. The length of
537 * EncryptedMessage will depend on the encryption algorithm and the size of Message.
539 * @param encryptObject_p RW: The encryption object to use, defining the
540 * encryption algorithm (DES or ARC4), the keys, etc.
541 * The state in EncryptObject will be updated
542 * appropriately as part of the call.<BR>
543 * @param message_p RO: The bytes to be encrypted<BR>
544 * @param messageLength RO Length of Message in bytes, from 0 to 18 KBytes
545 * inclusive. A length of 0 is legal, but no bytes
546 * will actually be encrypted or returned in
547 * EncryptedMessage<BR>
548 * @param encryptedMessage_p WO: The result of encrypting the given Message
549 * with the specified encryption algorithm and keys
550 * etc in EncryptObject. This includes any pad bytes
551 * added by the encryption algorithm. (DES will pad
552 * as necessary, ARC4 never will.)<BR>
553 * @param event_p RW: On input, if null the call is synchronous and no
554 * event is returned. The operation is complete when
555 * the call returns. If non-null, then the call is
556 * asynchronous; an event is returned that can be used
557 * to determine when the operation completes.<BR>
559 * @return
560 * encryptObject_p - The state in PacketObject will be updated if necessary as
561 * part of the call.
562 * encryptedMessage_p - The encrypted data.
563 * ret - returns N8_STATUS_OK if successful or Error value.
565 * @par Errors:
566 * N8_INVALID_OBJECT - object is zero, couldn't write/read unspecified
567 * address<BR>
568 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
569 * then 18 KBytes.
570 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
571 * N8_HARDWARE_ERROR - couldn't write to context memory
574 * @par Assumptions:
575 * The caller must ensure that EncryptedMessage is of the required size.
576 * (This will never be more than MessageLength + 7 for
577 * DES, and will always be exactly MessageLength for ARC4.)
578 *****************************************************************************/
579 N8_Status_t N8_Encrypt(N8_EncryptObject_t *encryptObject_p,
580 const N8_Buffer_t *message_p,
581 const unsigned int messageLength,
582 N8_Buffer_t *encryptedMessage_p,
583 N8_Event_t *event_p )
585 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
587 API_Request_t *req_p = NULL; /* request buffer */
588 N8_Buffer_t *plain_p = NULL;
589 uint32_t plain_a;
590 N8_Buffer_t *res_p = NULL;
591 uint32_t res_a;
592 unsigned int paddedMessageLength;
593 unsigned int nBytes;
595 DBG(("N8_Encrypt\n"));
598 /* verify data length */
599 ret = verifyInputLength(messageLength);
600 CHECK_RETURN(ret);
602 /* verify objects */
603 CHECK_OBJECT(encryptObject_p, ret);
604 CHECK_OBJECT(message_p, ret);
605 CHECK_OBJECT(encryptedMessage_p, ret);
606 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
608 ret = checkCipher(encryptObject_p->cipher);
609 CHECK_RETURN(ret);
611 paddedMessageLength = messageLength;
613 if (encryptObject_p->cipher == N8_CIPHER_DES)
615 unsigned int remainder;
616 /* pad message if necessary. the message length must be a multiple of
617 * N8_DES_BLOCK_LENGTH */
618 if ((remainder = messageLength % N8_DES_BLOCK_LENGTH))
620 paddedMessageLength += N8_DES_BLOCK_LENGTH - remainder;
623 nBytes = 2 * NEXT_WORD_SIZE(paddedMessageLength);
625 /* create request buffer */
626 ret = createEARequestBuffer(&req_p, encryptObject_p->unitID,
627 N8_CB_EA_ENCRYPT_NUMCMDS,
628 resultHandler, nBytes);
629 CHECK_RETURN(ret);
631 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
632 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
634 plain_a = res_a + NEXT_WORD_SIZE(paddedMessageLength);
635 plain_p = res_p + NEXT_WORD_SIZE(paddedMessageLength);
637 /* copy the user message into the kernel memory buffer */
638 memcpy(plain_p, message_p, messageLength);
639 /* set the padding bytes to 0x0 */
640 memset(&plain_p[messageLength], 0x0, paddedMessageLength - messageLength);
642 req_p->copyBackFrom_p = res_p;
643 req_p->copyBackTo_p = encryptedMessage_p;
644 req_p->copyBackSize = paddedMessageLength;
646 ret = cb_ea_encrypt(req_p,
647 req_p->EA_CommandBlock_ptr,
648 encryptObject_p,
649 plain_a,
650 res_a,
651 paddedMessageLength);
653 CHECK_RETURN(ret);
654 QUEUE_AND_CHECK(event_p, req_p, ret);
655 HANDLE_EVENT(event_p, req_p, ret);
656 } while (FALSE);
659 * Deallocate the request if we arrived from an error condition.
661 if (ret != N8_STATUS_OK)
663 /* free the request */
664 freeRequest(req_p);
666 DBG(("N8_Encrypt - FINISHED\n"));
667 return ret;
668 } /* N8_Encrypt */
671 /* same as above, but for uio iovec i/o */
672 N8_Status_t N8_Encrypt_uio(N8_EncryptObject_t *encryptObject_p,
673 struct uio *message_p,
674 const unsigned int messageLength,
675 struct uio *encryptedMessage_p,
676 N8_Event_t *event_p )
678 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
680 API_Request_t *req_p = NULL; /* request buffer */
681 N8_Buffer_t *plain_p = NULL;
682 uint32_t plain_a;
683 N8_Buffer_t *res_p = NULL;
684 uint32_t res_a;
685 unsigned int paddedMessageLength;
686 unsigned int nBytes;
688 DBG(("N8_Encrypt\n"));
691 /* verify data length */
692 ret = verifyInputLength(messageLength);
693 CHECK_RETURN(ret);
695 /* verify objects */
696 CHECK_OBJECT(encryptObject_p, ret);
697 CHECK_OBJECT(message_p, ret);
698 CHECK_OBJECT(encryptedMessage_p, ret);
699 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
701 ret = checkCipher(encryptObject_p->cipher);
702 CHECK_RETURN(ret);
704 paddedMessageLength = messageLength;
706 if (encryptObject_p->cipher == N8_CIPHER_DES)
708 unsigned int remainder;
709 /* pad message if necessary. the message length must be a multiple of
710 * N8_DES_BLOCK_LENGTH */
711 if ((remainder = messageLength % N8_DES_BLOCK_LENGTH))
713 paddedMessageLength += N8_DES_BLOCK_LENGTH - remainder;
716 nBytes = 2 * NEXT_WORD_SIZE(paddedMessageLength);
718 /* create request buffer */
719 ret = createEARequestBuffer(&req_p, encryptObject_p->unitID,
720 N8_CB_EA_ENCRYPT_NUMCMDS,
721 resultHandler, nBytes);
722 CHECK_RETURN(ret);
724 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
725 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
727 plain_a = res_a + NEXT_WORD_SIZE(paddedMessageLength);
728 plain_p = res_p + NEXT_WORD_SIZE(paddedMessageLength);
730 /* copy the user message into the kernel memory buffer */
731 cuio_copydata(message_p, 0, messageLength, plain_p);
732 /* set the padding bytes to 0x0 */
733 memset(&plain_p[messageLength], 0x0, paddedMessageLength - messageLength);
735 req_p->copyBackFrom_p = res_p;
736 req_p->copyBackTo_p = NULL;
737 req_p->copyBackTo_uio = encryptedMessage_p;
738 req_p->copyBackSize = paddedMessageLength;
740 ret = cb_ea_encrypt(req_p,
741 req_p->EA_CommandBlock_ptr,
742 encryptObject_p,
743 plain_a,
744 res_a,
745 paddedMessageLength);
747 CHECK_RETURN(ret);
748 QUEUE_AND_CHECK(event_p, req_p, ret);
749 HANDLE_EVENT(event_p, req_p, ret);
750 } while (FALSE);
753 * Deallocate the request if we arrived from an error condition.
755 if (ret != N8_STATUS_OK)
757 /* free the request */
758 freeRequest(req_p);
760 DBG(("N8_Encrypt - FINISHED\n"));
761 return ret;
762 } /* N8_Encrypt */
763 /******************************************************************************
764 * N8_EncryptPartial
765 *****************************************************************************/
766 /** @ingroup crypto
767 * @brief Encrypts message.
769 * Using the encryption algorithm and context (keys, etc.) contained in
770 * EncryptObject, encrypt the plain text bytes in Message whose length is
771 * MessageLength bytes, returning the resulting cipher text bytes (including
772 * any pad bytes added during encryption) in EncryptedMessage. The length of
773 * EncryptedMessage will depend on the encryption algorithm and the size of Message.
775 * @param encryptObject_p WO: The encryption object to use, defining the
776 * encryption algorithm (DES or ARC4), the keys, etc.
777 * The state in EncryptObject will be updated
778 * appropriately as part of the call.<BR>
779 * @param message_p RO: The bytes to be encrypted<BR>
780 * @param messageLength RO Length of Message in bytes, from 0 to 18 KBytes
781 * inclusive. A length of 0 is legal, but no bytes
782 * will actually be encrypted or returned in
783 * EncryptedMessage<BR>
784 * @param encryptedMessage_p WO: The result of encrypting the given Message
785 * with the specified encryption algorithm and keys
786 * etc in EncryptObject. This includes any pad bytes
787 * added by the encryption algorithm. (DES will pad
788 * as necessary, ARC4 never will.)<BR>
789 * @param encryptedMsgLen_p WO: The length of the encrypted message.
790 * @param event_p RW: On input, if null the call is synchronous and no
791 * event is returned. The operation is complete when
792 * the call returns. If non-null, then the call is
793 * asynchronous; an event is returned that can be used
794 * to determine when the operation completes.<BR>
796 * @return
797 * packetObject_p - The state in PacketObject will be updated if necessary as
798 * part of the call.
799 * encryptedMessage_p - The encrypted data.
800 * ret - returns N8_STATUS_OK if successful or Error value.
802 * @par Errors:
803 * N8_INVALID_OBJECT - object is NULL, couldn't write/read unspecified
804 * address<BR>
805 * N8_INVALID_INPUT_SIZE - The value of messageLength is less than 0 or bigger
806 * then 18 KBytes.
807 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
808 * N8_HARDWARE_ERROR - couldn't write to context memory
811 * @par Assumptions:
812 * The caller must ensure that EncryptedMessage is of the required size.
813 * (This will never be more than MessageLength + 7 for
814 * DES, and will always be exactly MessageLength for ARC4.)
815 *****************************************************************************/
816 N8_Status_t N8_EncryptPartial(N8_EncryptObject_t *encryptObject_p,
817 const N8_Buffer_t *message_p,
818 const unsigned int messageLength,
819 N8_Buffer_t *encryptedMessage_p,
820 unsigned int *encryptedMsgLen_p,
821 N8_Event_t *event_p)
823 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
825 API_Request_t *req_p = NULL; /* request buffer */
826 N8_Buffer_t *plain_p = NULL; /* virtual address of message to be
827 * encrypted this time. */
828 N8_Buffer_t *res_p = NULL; /* virtual address of encrypted
829 * message. */
830 uint32_t plain_a; /* physical address of message to be
831 * encrypted. */
832 uint32_t res_a; /* physical address of encrypted
833 * message. */
834 unsigned int totalLength = 0; /* total length of this message plus
835 * any residual from previous
836 * calls. */
837 unsigned int msgLen = 0; /* the length of the message to be
838 * encrypted in this call. */
839 unsigned int nextResidualLength = 0; /* amount leftover from this
840 * call. */
841 unsigned int fromThisMessageLength = 0; /* amount of taken from this
842 * message */
843 unsigned int nBytes;
844 encryptData_t *callBackData_p = NULL;
846 DBG(("N8_EncryptPartial\n"));
849 /* verify data length */
850 ret = verifyInputLength(messageLength);
851 CHECK_RETURN(ret);
853 /* verify objects */
854 CHECK_OBJECT(encryptObject_p, ret);
855 CHECK_OBJECT(message_p, ret);
856 CHECK_OBJECT(encryptedMessage_p, ret);
857 CHECK_OBJECT(encryptedMsgLen_p, ret);
858 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
860 ret = checkCipher(encryptObject_p->cipher);
861 CHECK_RETURN(ret);
863 /* sanity check the residual length */
864 if (encryptObject_p->residualLength >= N8_DES_BLOCK_LENGTH)
866 ret = N8_INVALID_OBJECT;
867 break;
870 /* set the value for the returned encrypted message length to zero. it
871 * will be set finally in the callback at the completion of the call (sync
872 * or async). */
873 *encryptedMsgLen_p = 0;
874 if (encryptObject_p->cipher == N8_CIPHER_DES)
876 totalLength = encryptObject_p->residualLength + messageLength;
877 nextResidualLength = totalLength % N8_DES_BLOCK_LENGTH;
878 msgLen = totalLength - nextResidualLength;
879 fromThisMessageLength = messageLength - nextResidualLength;
881 else if (encryptObject_p->cipher == N8_CIPHER_ARC4)
883 fromThisMessageLength = msgLen = messageLength;
885 else
887 ret = N8_INVALID_CIPHER;
888 break;
891 /* check to ensure we actually have some message to encrypt this go
892 * round. */
893 if (msgLen == 0)
895 /* copy the input to the end of the residual */
896 memcpy(&encryptObject_p->residual_p[encryptObject_p->residualLength],
897 message_p,
898 messageLength);
899 encryptObject_p->residualLength += messageLength;
901 /* if this was an asynchronous call, set the status to finished */
902 if (event_p != NULL)
904 N8_SET_EVENT_FINISHED(event_p, N8_EA);
906 break;
909 nBytes = 2 * NEXT_WORD_SIZE(msgLen);
911 /* create request buffer */
912 ret = createEARequestBuffer(&req_p,
913 encryptObject_p->unitID,
914 N8_CB_EA_ENCRYPT_NUMCMDS,
915 resultHandler, nBytes);
916 CHECK_RETURN(ret);
918 plain_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
919 plain_a = req_p->qr.physicalAddress + req_p->dataoffset;
920 res_p = plain_p + NEXT_WORD_SIZE(msgLen);
921 res_a = plain_a + NEXT_WORD_SIZE(msgLen);
923 /* copy any previous residual to the m-t-b-e buffer */
924 if (encryptObject_p->residualLength > 0)
926 memcpy(plain_p,
927 encryptObject_p->residual_p,
928 encryptObject_p->residualLength);
929 /* advance the message pointer */
930 plain_p += encryptObject_p->residualLength;
933 /* copy the new message portion to the end of the m-t-b-e buffer */
934 if (fromThisMessageLength > 0)
936 memcpy(plain_p,
937 message_p,
938 fromThisMessageLength);
941 /* copy leftovers to the residual */
942 if (nextResidualLength > 0)
944 /* not necessary, but let's zero out the remaining message buffer */
945 memset(encryptObject_p->residual_p, 0x0,
946 N8_DES_BLOCK_LENGTH);
947 memcpy(encryptObject_p->residual_p,
948 &message_p[fromThisMessageLength],
949 nextResidualLength);
951 encryptObject_p->residualLength = nextResidualLength;
953 /* set the copy back parameters for returning the results to the user.
954 * the main data is represented by the copy back structures in the request
955 * and the extra data is in the post-processing data. */
956 callBackData_p = (encryptData_t *)&req_p->postProcessBuffer;
957 req_p->postProcessingData_p = (void *) callBackData_p;
959 callBackData_p->encryptedMsgLen_p = encryptedMsgLen_p;
960 callBackData_p->encryptObject_p = encryptObject_p;
961 if (encryptObject_p->contextHandle.inUse == N8_FALSE)
963 callBackData_p->nextIV_p = (uint32_t *) (res_p + msgLen -
964 N8_DES_BLOCK_LENGTH);
966 else
968 callBackData_p->nextIV_p = NULL;
970 req_p->copyBackSize = msgLen;
971 req_p->copyBackFrom_p = res_p;
972 req_p->copyBackTo_p = encryptedMessage_p;
973 ret = cb_ea_encrypt(req_p,
974 req_p->EA_CommandBlock_ptr,
975 encryptObject_p,
976 plain_a,
977 res_a,
978 msgLen);
979 CHECK_RETURN(ret);
980 QUEUE_AND_CHECK(event_p, req_p, ret);
981 HANDLE_EVENT(event_p, req_p, ret);
982 } while (FALSE);
985 * Deallocate the request if we arrived from an error condition.
987 if (ret != N8_STATUS_OK)
989 freeRequest(req_p);
991 DBG(("N8_EncryptPartial - FINISHED\n"));
992 return ret;
993 } /* N8_EncryptPartial */
995 /******************************************************************************
996 * N8_EncryptEnd
997 *****************************************************************************/
998 /** @ingroup crypto
999 * @brief Encrypts message.
1001 * Using the encryption algorithm and context (keys, etc.) contained in
1002 * EncryptObject, encrypt the plain text bytes in Message whose length is
1003 * MessageLength bytes, returning the resulting cipher text bytes (including
1004 * any pad bytes added during encryption) in EncryptedMessage. The length of
1005 * EncryptedMessage will depend on the encryption algorithm and the size of Message.
1007 * @param encryptObject_p WO: The encryption object to use, defining the
1008 * encryption algorithm (DES or ARC4), the keys, etc.
1009 * The state in EncryptObject will be updated
1010 * appropriately as part of the call.<BR>
1011 * @param message_p RO: The bytes to be encrypted<BR>
1012 * @param messageLength RO Length of Message in bytes, from 0 to 18 KBytes
1013 * inclusive. A length of 0 is legal, but no bytes
1014 * will actually be encrypted or returned in
1015 * EncryptedMessage<BR>
1016 * @param encryptedMessage_p WO: The result of encrypting the given Message
1017 * with the specified encryption algorithm and keys
1018 * etc in EncryptObject. This includes any pad bytes
1019 * added by the encryption algorithm. (DES will pad
1020 * as necessary, ARC4 never will.)<BR>
1021 * @param event_p RW: On input, if null the call is synchronous and no
1022 * event is returned. The operation is complete when
1023 * the call returns. If non-null, then the call is
1024 * asynchronous; an event is returned that can be used
1025 * to determine when the operation completes.<BR>
1028 * @return
1029 * packetObject_p - The state in PacketObject will be updated if necessary as
1030 * part of the call.
1031 * encryptedMessage_p - The encrypted data.
1032 * ret - returns N8_STATUS_OK if successful or Error value.
1034 * @par Errors:
1035 * N8_INVALID_OBJECT - object is zero, couldn't write/read unspecified
1036 * address<BR>
1037 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
1038 * N8_HARDWARE_ERROR - couldn't write to context memory
1041 * @par Assumptions:
1042 * The caller must ensure that EncryptedMessage is of the required size.
1043 * (This will never be more than MessageLength + 7 for
1044 * DES, and will always be exactly MessageLength for ARC4.)
1045 *****************************************************************************/
1046 N8_Status_t N8_EncryptEnd(N8_EncryptObject_t *encryptObject_p,
1047 N8_Buffer_t *encryptedMessage_p,
1048 unsigned int *encryptedMsgLen_p,
1049 N8_Event_t *event_p )
1051 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
1053 API_Request_t *req_p = NULL; /* request buffer */
1054 N8_Buffer_t *plain_p = NULL;
1055 uint32_t plain_a;
1056 N8_Buffer_t *res_p = NULL;
1057 uint32_t res_a;
1058 unsigned int paddedMessageLength = 0;
1059 unsigned int nBytes;
1060 encryptData_t *callBackData_p = NULL;
1062 DBG(("N8_EncryptEnd\n"));
1065 CHECK_OBJECT(encryptObject_p, ret);
1066 CHECK_OBJECT(encryptedMessage_p, ret);
1067 CHECK_OBJECT(encryptedMsgLen_p, ret);
1069 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
1071 ret = checkCipher(encryptObject_p->cipher);
1072 CHECK_RETURN(ret);
1074 /* sanity check the residual length */
1075 if (encryptObject_p->residualLength >= N8_DES_BLOCK_LENGTH)
1077 ret = N8_INVALID_OBJECT;
1078 break;
1081 *encryptedMsgLen_p = 0;
1082 /* check to see if there is no work to be done. */
1083 if (encryptObject_p->residualLength == 0)
1085 /* if this was an asynchronous call, set the status to finished */
1086 if (event_p != NULL)
1088 N8_SET_EVENT_FINISHED(event_p, N8_EA);
1090 break;
1093 paddedMessageLength = encryptObject_p->residualLength;
1095 if (encryptObject_p->cipher == N8_CIPHER_DES)
1097 /* pad message */
1098 paddedMessageLength =
1099 CEIL(encryptObject_p->residualLength, N8_DES_BLOCK_LENGTH) *
1100 N8_DES_BLOCK_LENGTH;
1103 nBytes = 2 * NEXT_WORD_SIZE(paddedMessageLength);
1105 /* create request buffer */
1106 ret = createEARequestBuffer(&req_p,
1107 encryptObject_p->unitID,
1108 N8_CB_EA_ENCRYPT_NUMCMDS,
1109 resultHandler, nBytes);
1110 CHECK_RETURN(ret);
1112 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
1113 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
1115 plain_a = res_a + NEXT_WORD_SIZE(paddedMessageLength);
1116 plain_p = res_p + NEXT_WORD_SIZE(paddedMessageLength);
1118 /* copy the residual message into the kernel memory buffer */
1119 memcpy(plain_p,
1120 encryptObject_p->residual_p,
1121 encryptObject_p->residualLength);
1122 /* set the padding bytes to 0x0 */
1123 memset(&plain_p[encryptObject_p->residualLength],
1124 0x0,
1125 paddedMessageLength - encryptObject_p->residualLength);
1127 /* set the copy back parameters for returning the results to the user.
1128 * the main data is represented by the copy back structures in the request
1129 * and the extra data is in the post-processing data. */
1130 callBackData_p = (encryptData_t *)&req_p->postProcessBuffer;
1131 req_p->postProcessingData_p = (void *) callBackData_p;
1132 callBackData_p->encryptedMsgLen_p = encryptedMsgLen_p;
1133 callBackData_p->encryptObject_p = encryptObject_p;
1134 callBackData_p->nextIV_p = NULL;
1135 req_p->copyBackSize = paddedMessageLength;
1136 req_p->copyBackFrom_p = res_p;
1137 req_p->copyBackTo_p = encryptedMessage_p;
1138 encryptObject_p->residualLength = 0;
1140 ret = cb_ea_encrypt(req_p,
1141 req_p->EA_CommandBlock_ptr,
1142 encryptObject_p,
1143 plain_a,
1144 res_a,
1145 paddedMessageLength);
1147 CHECK_RETURN(ret);
1148 QUEUE_AND_CHECK(event_p, req_p, ret);
1149 HANDLE_EVENT(event_p, req_p, ret);
1151 } while (FALSE);
1154 * Deallocate the request if we arrived from an error condition.
1156 if (ret != N8_STATUS_OK)
1158 freeRequest(req_p);
1160 DBG(("N8_EncryptEnd - FINISHED\n"));
1161 return ret;
1163 } /* N8_EncryptEnd */
1165 /******************************************************************************
1166 * N8_Decrypt
1167 *****************************************************************************/
1168 /** @ingroup crypto
1169 * @brief Decrypts message.
1171 * Using the algorithm and context (keys, etc.) contained in EncryptObject,
1172 * decrypt the cipher text bytes in EncryptedMessage whose length is
1173 * EncryptedMessageLength bytes, returning the resulting plain text bytes
1174 * (including any pad bytes added during encryption) in EncryptedMessage.
1175 * The length of Message will always be EncryptedMessageLength. Either DES
1176 * or ARC4 encryption can be specified in EncryptObject. DES encryption pads
1177 * if necessary so Message may contain pad bytes; ARC4 decrypted messages will
1178 * never contain pad bytes.
1180 * @param encryptObject_p WR: The encryption object to use, defining
1181 * the encryption algorithm (DES or
1182 * ARC4), the keys, etc. The state in
1183 * EncryptObject will be updated
1184 * appropriately as part of the call. For
1185 * example, an ARC4 object would
1186 * have its key information updated.<BR>
1187 * @param encryptedMessage_p RO: The bytes to be decrypted.<BR>
1188 * @param encryptedMsgLen_p RO: Length of EncryptedMessage in bytes,
1189 * from 0 to 18 KBytes inclusive. A
1190 * length of 0 is legal, but no bytes will
1191 * actually be decrypted or returned in
1192 * EncryptedMessage. For DES,
1193 * EncryptedMessageLength must be a
1194 * multiple of 8, the DES block size.
1195 * @param message_p WO: The result of decrypting the given
1196 * EncryptedMessage with the specified
1197 * algorithm and keys etc in EncryptObject.
1198 * This includes any pad bytes
1199 * added by the encryption algorithm.
1200 * (DES will pad as necessary, ARC4 never will.)
1201 * Thus Message is always of size MessageLength,
1202 * the caller must ensure that Message is of at
1203 * least this size.<BR>
1204 * @param event_p RW: On input, if null the call is synchronous and no
1205 * event is returned. The operation is complete when
1206 * the call returns. If non-null, then the call is
1207 * asynchronous; an event is returned that can be used
1208 * to determine when the operation completes.
1211 * @return
1212 * encryptObject_p - The state in PacketObject will be updated if necessary as
1213 * part of the call.
1214 * message_p - The encrypted data.
1215 * ret - returns N8_STATUS_OK if successful or Error value.
1217 * @par Errors:
1218 * N8_INVALID_OBJECT - encrypt object is zero, couldn't write to unspecified
1219 * address<BR>
1220 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
1221 * then 18 KBytes.
1222 * N8_HARDWARE_ERROR - couldn't decrypt
1224 * N8_MALLOC_FAILED - memory allocation failed
1226 * @par Assumptions:
1227 *****************************************************************************/
1228 N8_Status_t N8_Decrypt(N8_EncryptObject_t *encryptObject_p,
1229 const N8_Buffer_t *encryptedMessage_p,
1230 const unsigned int encryptedMsgLen,
1231 N8_Buffer_t *message_p,
1232 N8_Event_t *event_p )
1234 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
1235 API_Request_t *req_p = NULL; /* request buffer */
1236 N8_Buffer_t *enc_p = NULL;
1237 uint32_t enc_a;
1238 N8_Buffer_t *res_p = NULL;
1239 uint32_t res_a;
1240 unsigned int nBytes;
1242 DBG(("N8_Decrypt\n"));
1243 do {
1244 /* verify data length */
1245 ret = verifyInputLength(encryptedMsgLen);
1246 CHECK_RETURN(ret);
1248 /* verify objects */
1249 CHECK_OBJECT(encryptObject_p, ret);
1250 CHECK_OBJECT(message_p, ret);
1251 CHECK_OBJECT(encryptedMessage_p, ret);
1252 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
1254 ret = checkCipher(encryptObject_p->cipher);
1255 CHECK_RETURN(ret);
1257 if (encryptObject_p->cipher == N8_CIPHER_DES)
1259 /* Check to ensure the message length is a multiple of
1260 * N8_DES_BLOCK_LENGTH. Return an error if not.
1262 if (encryptedMsgLen % N8_DES_BLOCK_LENGTH)
1264 ret = N8_INVALID_INPUT_SIZE;
1265 break;
1269 nBytes = 2 * NEXT_WORD_SIZE(encryptedMsgLen);
1271 /* create request buffer */
1272 ret = createEARequestBuffer(&req_p,
1273 encryptObject_p->unitID,
1274 N8_CB_EA_DECRYPT_NUMCMDS,
1275 resultHandler, nBytes);
1276 CHECK_RETURN(ret);
1278 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
1279 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
1281 enc_a = res_a + NEXT_WORD_SIZE(encryptedMsgLen);
1282 enc_p = res_p + NEXT_WORD_SIZE(encryptedMsgLen);
1284 /* copy the encrypted message into the kernel memory buffer */
1285 memcpy(enc_p, encryptedMessage_p, encryptedMsgLen);
1287 req_p->copyBackFrom_p = res_p;
1288 req_p->copyBackTo_p = message_p;
1289 req_p->copyBackSize = encryptedMsgLen;
1291 ret = cb_ea_decrypt(req_p,
1292 req_p->EA_CommandBlock_ptr,
1293 encryptObject_p,
1294 enc_a,
1295 res_a,
1296 encryptedMsgLen);
1298 CHECK_RETURN(ret);
1299 QUEUE_AND_CHECK(event_p, req_p, ret);
1300 HANDLE_EVENT(event_p, req_p, ret);
1301 } while (FALSE);
1304 * Deallocate the request if we arrived from an error condition.
1306 if (ret != N8_STATUS_OK)
1308 /* free the request */
1309 freeRequest(req_p);
1311 DBG(("N8_Decrypt - FINISHED\n"));
1312 return ret;
1313 } /* N8_Decrypt */
1316 /* same as above, but for uio iovec i/o */
1317 N8_Status_t N8_Decrypt_uio(N8_EncryptObject_t *encryptObject_p,
1318 struct uio *encryptedMessage_p,
1319 const unsigned int encryptedMsgLen,
1320 struct uio *message_p,
1321 N8_Event_t *event_p )
1323 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
1324 API_Request_t *req_p = NULL; /* request buffer */
1325 N8_Buffer_t *enc_p = NULL;
1326 uint32_t enc_a;
1327 N8_Buffer_t *res_p = NULL;
1328 uint32_t res_a;
1329 unsigned int nBytes;
1331 DBG(("N8_Decrypt\n"));
1332 do {
1333 /* verify data length */
1334 ret = verifyInputLength(encryptedMsgLen);
1335 CHECK_RETURN(ret);
1337 /* verify objects */
1338 CHECK_OBJECT(encryptObject_p, ret);
1339 CHECK_OBJECT(message_p, ret);
1340 CHECK_OBJECT(encryptedMessage_p, ret);
1341 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
1343 ret = checkCipher(encryptObject_p->cipher);
1344 CHECK_RETURN(ret);
1346 if (encryptObject_p->cipher == N8_CIPHER_DES)
1348 /* Check to ensure the message length is a multiple of
1349 * N8_DES_BLOCK_LENGTH. Return an error if not.
1351 if (encryptedMsgLen % N8_DES_BLOCK_LENGTH)
1353 ret = N8_INVALID_INPUT_SIZE;
1354 break;
1358 nBytes = 2 * NEXT_WORD_SIZE(encryptedMsgLen);
1360 /* create request buffer */
1361 ret = createEARequestBuffer(&req_p,
1362 encryptObject_p->unitID,
1363 N8_CB_EA_DECRYPT_NUMCMDS,
1364 resultHandler, nBytes);
1365 CHECK_RETURN(ret);
1367 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
1368 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
1370 enc_a = res_a + NEXT_WORD_SIZE(encryptedMsgLen);
1371 enc_p = res_p + NEXT_WORD_SIZE(encryptedMsgLen);
1373 /* copy the encrypted message into the kernel memory buffer */
1374 cuio_copydata(encryptedMessage_p, 0, encryptedMsgLen, enc_p);
1376 req_p->copyBackFrom_p = res_p;
1377 req_p->copyBackTo_p = NULL;
1378 req_p->copyBackTo_uio = message_p;
1379 req_p->copyBackSize = encryptedMsgLen;
1381 ret = cb_ea_decrypt(req_p,
1382 req_p->EA_CommandBlock_ptr,
1383 encryptObject_p,
1384 enc_a,
1385 res_a,
1386 encryptedMsgLen);
1388 CHECK_RETURN(ret);
1389 QUEUE_AND_CHECK(event_p, req_p, ret);
1390 HANDLE_EVENT(event_p, req_p, ret);
1391 } while (FALSE);
1394 * Deallocate the request if we arrived from an error condition.
1396 if (ret != N8_STATUS_OK)
1398 /* free the request */
1399 freeRequest(req_p);
1401 DBG(("N8_Decrypt - FINISHED\n"));
1402 return ret;
1403 } /* N8_Decrypt */
1405 /******************************************************************************
1406 * N8_DecryptPartial
1407 *****************************************************************************/
1408 /** @ingroup crypto
1409 * @brief Decrypts partial message.
1410 * For stream decryption algorithms (ARC4), this function is identical to
1411 * N8_Decrypt called with the same parameters, with the additional output
1412 * parameter MessageLength always set equal to EncryptedMessageLength on return.
1414 * For block decryption algorithms (DES), this function starts or continues,
1415 * but does not complete, decrypting the bytes given in EncryptedMessage.
1416 * The partial message in EncryptedMessage can be any number of bytes from 0
1417 * to 18 KBytes inclusive, its size is specified in EncryptedMessageLength.
1418 * The EncryptObject specifies the decryption algorithm to use, and must have
1419 * been initialized by a call to N8_EncryptInitialize prior to the first call
1420 * to N8_DecryptPartial. If this is the first call to this routine since the
1421 * EncryptObject was initialized, then the call starts the decryption of a message.
1422 * Subsequent calls to N8_DecryptPartial with the same EncryptObject with additional
1423 * bytes in EncryptedMessage allow the decryption to be continued, and a final
1424 * call to N8_DecryptEnd finishes the computation and returns the final decrypted
1425 * result. Note that for block decryption algorithms, only whole message blocks
1426 * will be decrypted and returned to the caller on each call to N8_DecryptPartial.
1427 * Any message bytes left over (i.e., not forming a complete decryption block)
1428 * will be accumulated in the EncryptObject and added to the message bytes in
1429 * the next N8_DecryptPartial call. For this reason, the number of bytes
1430 * decrypted and returned in Message may be different than the number of input
1431 * bytes specified in EncryptedMessageLength. The actual number of bytes
1432 * decrypted will always be an integral multiple of the block size of the
1433 * encryption algorithm (8 bytes for DES) and is returned in MessageLength.
1434 * Note in particular that this value can be 0, and it can be larger than the
1435 * input length by as much as one less than the block size (8 - 1 = 7 for DES).
1436 * That is, the maximum result length is the next multiple of the block size
1437 * that is larger than EncryptedMessageLength-1
1438 * (maximum length = ((EncryptedMessageLength / block size) + 1) * block size).
1439 * The caller is responsible for ensuring that Message can hold a message
1440 * of the required size. Note that while this call does not require that
1441 * EncryptedMessageLength be a multiple of the block size, if the length of
1442 * the entire message to be decrypted over multiple calls is not a multiple
1443 * of the block size, an error will occur eventually
1445 * @param encryptObject_p RW: The encryption object to use, defining
1446 * the encryption algorithm (DES or
1447 * ARC4), the keys, etc. The state in
1448 * EncryptObject will be updated
1449 * appropriately as part of the call.
1450 * For example, an ARC4 object would have
1451 * its key information updated.
1452 * @param encryptedMessage_p RO: The bytes to be decrypted.
1453 * @param encryptedMsgLen_p RO: Length of EncryptedMessage in bytes,
1454 * from 0 to 18 KBytes inclusive. A
1455 * length of 0 is legal, but no bytes will
1456 * actually be decrypted or returned in
1457 * message.
1458 * @param message_p WO: The partial result of decrypting the
1459 * given EncryptedMessage with the
1460 * specified encryption algorithm and keys
1461 * etc in EncryptObject. The caller must
1462 * ensure that Message is of the required
1463 * size. (This will never be more than
1464 * EncryptedMessageLength + 7 for DES.
1465 * @param messageLength WO: The number of bytes encrypted by this call and
1466 * returned in Message. Always a multiple of
1467 * the block size (8 for DES). This value may
1468 * be 0 and may be as large as the next multiple
1469 * of the block size that is greater than
1470 * EncryptedMessageLength. For stream algorithms
1471 * this will always equal MessageLength and will
1472 * always be exactly MessageLength for * ARC4.)
1474 * @param event_p RW: On input, if null the call is synchronous and
1475 * no event is returned. The operation is
1476 * complete when the call returns. If
1477 * non-null, then the call is asynchronous; an
1478 * event is returned that can be used to
1479 * determine when the operation completes.<BR>
1481 * @return
1482 * Message WO: The partial result of decrypting the
1483 * given EncryptedMessage with the
1484 * specified encryption algorithm and keys
1485 * etc in EncryptObject.
1486 * MessageLength WO: The number of bytes encrypted by this call
1487 * and returned in Message.
1488 * @par Errors:
1489 * N8_INVALID_OBJECT - encrypt object is zero, couldn't write to unspecified
1490 * address<BR>
1491 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
1492 * then 18 KBytes.
1493 * N8_HARDWARE_ERROR - couldn't decrypt
1494 * N8_MALLOC_FAILED - memory allocation failed
1496 * @par Assumptions:
1497 *****************************************************************************/
1498 N8_Status_t N8_DecryptPartial(N8_EncryptObject_t *encryptObject_p,
1499 const N8_Buffer_t *encryptedMessage_p,
1500 const unsigned int encryptedMsgLen,
1501 N8_Buffer_t *message_p,
1502 unsigned int *messageLength_p,
1503 N8_Event_t *event_p)
1505 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
1507 API_Request_t *req_p = NULL; /* request buffer */
1508 N8_Buffer_t *enc_p = NULL;
1509 N8_Buffer_t *cipherText_p = NULL;
1510 uint32_t enc_a;
1511 N8_Buffer_t *res_p = NULL;
1512 uint32_t res_a;
1514 unsigned int totalLength = 0; /* total length of this message plus
1515 * any residual from previous
1516 * calls. */
1517 unsigned int msgLen = 0; /* the length of the message to be
1518 * encrypted in this call. */
1519 unsigned int nextResidualLength = 0; /* amount leftover from this
1520 * call. */
1521 unsigned int fromThisMessageLength = 0; /* amount of taken from this
1522 * message */
1523 encryptData_t *callBackData_p = NULL;
1524 unsigned int nBytes;
1526 DBG(("N8_DecryptPartial\n"));
1529 /* verify data length */
1530 ret = verifyInputLength(encryptedMsgLen);
1531 CHECK_RETURN(ret);
1533 /* verify objects */
1534 CHECK_OBJECT(encryptObject_p, ret);
1535 CHECK_OBJECT(message_p, ret);
1536 CHECK_OBJECT(messageLength_p, ret);
1537 CHECK_OBJECT(encryptedMessage_p, ret);
1538 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
1540 ret = checkCipher(encryptObject_p->cipher);
1541 CHECK_RETURN(ret);
1543 /* sanity check the residual length */
1544 if (encryptObject_p->residualLength >= N8_DES_BLOCK_LENGTH)
1546 ret = N8_INVALID_OBJECT;
1547 break;
1550 /* set the value for the returned decrypted message length to zero. it
1551 * will be set finally in the callback at the completion of the call (sync
1552 * or async). */
1553 *messageLength_p = 0;
1554 switch (encryptObject_p->cipher)
1556 case N8_CIPHER_DES:
1558 totalLength = encryptObject_p->residualLength + encryptedMsgLen;
1559 nextResidualLength = totalLength % N8_DES_BLOCK_LENGTH;
1560 msgLen = totalLength - nextResidualLength;
1561 fromThisMessageLength = encryptedMsgLen - nextResidualLength;
1562 break;
1564 case N8_CIPHER_ARC4:
1566 fromThisMessageLength = msgLen = encryptedMsgLen;
1567 break;
1571 /* check to ensure we actually have some message to encrypt this go
1572 * round. */
1573 if (msgLen == 0)
1575 /* copy the input to the end of the residual */
1576 memcpy(&encryptObject_p->residual_p[encryptObject_p->residualLength],
1577 encryptedMessage_p,
1578 encryptedMsgLen);
1579 encryptObject_p->residualLength += encryptedMsgLen;
1581 /* if this was an asynchronous call, set the status to finished */
1582 if (event_p != NULL)
1584 N8_SET_EVENT_FINISHED(event_p, N8_EA);
1586 break;
1589 nBytes = 2 * NEXT_WORD_SIZE(msgLen);
1590 ret = createEARequestBuffer(&req_p,
1591 encryptObject_p->unitID,
1592 N8_CB_EA_DECRYPT_NUMCMDS,
1593 resultHandler, nBytes);
1594 CHECK_RETURN(ret);
1596 enc_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
1597 enc_a = req_p->qr.physicalAddress + req_p->dataoffset;
1598 res_p = enc_p + NEXT_WORD_SIZE(msgLen);
1599 res_a = enc_a + NEXT_WORD_SIZE(msgLen);
1601 cipherText_p = enc_p;
1603 /* copy any previous residual to the m-t-b-e buffer */
1604 if (encryptObject_p->residualLength > 0)
1606 memcpy(cipherText_p,
1607 encryptObject_p->residual_p,
1608 encryptObject_p->residualLength);
1609 /* advance the message pointer */
1610 cipherText_p += encryptObject_p->residualLength;
1613 /* copy the new message portion to the end of the m-t-b-e buffer */
1614 if (fromThisMessageLength > 0)
1616 memcpy(cipherText_p,
1617 encryptedMessage_p,
1618 fromThisMessageLength);
1621 /* copy leftovers to the residual */
1622 if (nextResidualLength > 0)
1624 /* not necessary, but let's zero out the remaining message buffer */
1625 memset(encryptObject_p->residual_p, 0x0,
1626 N8_DES_BLOCK_LENGTH);
1627 memcpy(encryptObject_p->residual_p,
1628 &encryptedMessage_p[fromThisMessageLength],
1629 nextResidualLength);
1632 encryptObject_p->residualLength = nextResidualLength;
1634 /* set the copy back parameters for returning the results to the user.
1635 * the main data is represented by the copy back structures in the request
1636 * and the extra data is in the post-processing data. */
1637 callBackData_p = (encryptData_t *)&req_p->postProcessBuffer;
1638 req_p->postProcessingData_p = (void *) callBackData_p;
1640 callBackData_p->encryptedMsgLen_p = messageLength_p;
1641 callBackData_p->encryptObject_p = encryptObject_p;
1642 if (encryptObject_p->contextHandle.inUse == N8_FALSE)
1644 callBackData_p->nextIV_p = (uint32_t *) (enc_p + msgLen -
1645 N8_DES_BLOCK_LENGTH);
1647 else
1649 callBackData_p->nextIV_p = NULL;
1651 req_p->copyBackFrom_p = res_p;
1652 req_p->copyBackTo_p = message_p;
1653 req_p->copyBackSize = msgLen;
1654 ret = cb_ea_decrypt(req_p,
1655 req_p->EA_CommandBlock_ptr,
1656 encryptObject_p,
1657 enc_a,
1658 res_a,
1659 msgLen);
1661 CHECK_RETURN(ret);
1662 QUEUE_AND_CHECK(event_p, req_p, ret);
1663 HANDLE_EVENT(event_p, req_p, ret);
1664 } while (FALSE);
1667 * Deallocate the request if we arrived from an error condition.
1669 if (ret != N8_STATUS_OK)
1671 /* free the request */
1672 freeRequest(req_p);
1674 DBG(("N8_DecryptPartial - FINISHED\n"));
1675 return ret;
1676 } /* N8_DecryptPartial */
1678 /******************************************************************************
1679 * N8_DecryptEnd
1680 *****************************************************************************/
1681 /** @ingroup crypto
1682 * @brief Decrypts message.
1684 * Completes a sequence of partial decrypt operations by encrypting any residual
1685 * message bytes in EncryptObject, returning the resulting MessageLength bytes
1686 * in Message.
1687 * For stream encryption algorithms (ARC4), this function does nothing as there
1688 * will never be residual message bytes in EncryptObject after an
1689 * N8_DecryptPartial operation. MessageLength will be 0 on return and no
1690 * decrypted bytes will be returned in Message.
1691 * For block encryption algorithms (DES), this completes decrypting any message
1692 * bytes remaining in EncryptObject from previous N8_DecryptPartial calls.
1693 * The EncryptObject specifies the decryption algorithm to use, and must have
1694 * been initialized by a call to N8_EncryptInitialize prior to the first call
1695 * to N8_DecryptPartial; it may have been used in one or more N8_DecryptPartial
1696 * calls to process previous parts of the message. If this is the first call made
1697 * with EncryptObject since it was initialized, then the call does nothing; 0 is
1698 * returned in MessageLength and no bytes are written to Message. If previous
1699 * calls to N8_DecryptPartial with EncryptObject were made, then this final
1700 * call to N8_DecryptEnd finishes the computation and returns the final decrypted
1701 * result. Note that for block decryption algorithms, this final decryption must
1702 * result in a total length over all N8_DecryptPartial & N8_DecryptEnd calls that
1703 * is a multiple of the block size. This means that if there are any residual
1704 * message bytes accumulated in the EncryptObject as a result of previous
1705 * N8_DecryptPartial calls that the total length is not a multiple of the block
1706 * size, and an error will result. Thus, a successful call will never result in
1707 * any bytes being decrypted. The actual number of bytes decrypted will always be 0.
1708 * The caller is responsible for ensuring that Message can hold a message of this
1709 * required size.
1711 * @param encryptObject_p WR: The encryption object to use, defining
1712 * the encryption algorithm (DES or
1713 * ARC4), the keys, etc. The state in
1714 * EncryptObject will be updated
1715 * appropriately as part of the call. For
1716 * example, an ARC4 object would
1717 * have its key information updated.<BR>
1718 * @param MessageLength RO: The number of bytes decrypted by this call and
1719 * returned in Message. Should always a
1720 * multiple of the block size (8 for DES).
1721 * This value may be 0 and may be as large as
1722 * (EncryptedMessageLength + block size - 1)
1723 * mod (block size). For stream algorithms
1724 * this will always equal MessageLength
1725 * @param message_p WO: The result of decrypting the given
1726 * EncryptedMessage with the specified
1727 * algorithm and keys etc in EncryptObject.
1728 * This includes any pad bytes
1729 * added by the encryption algorithm.
1730 * (DES will pad as necessary, ARC4 never will.)
1731 * Thus Message is always of size MessageLength,
1732 * the caller must ensure that Message is of at
1733 * least this size.<BR>
1734 * @param event_p RW: On input, if null the call is synchronous and no
1735 * event is returned. The operation is complete when
1736 * the call returns. If non-null, then the call is
1737 * asynchronous; an event is returned that can be used
1738 * to determine when the operation completes.
1741 * @return
1742 * encryptObject_p - The state in encryptObject_p will be updated if necessary as
1743 * part of the call.
1744 * message_p - The decrypted data.
1745 * ret - returns N8_STATUS_OK if successful or Error value.
1747 * @par Errors:
1748 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
1749 * address<BR>
1750 * N8_MALLOC_FAILED - memory allocation failed
1751 * N8_HARDWARE_ERROR - couldn't write to context memory
1754 * @par Assumptions:
1755 * packetObject_p was initialized and all parameters checked.<BR>
1756 *****************************************************************************/
1757 N8_Status_t N8_DecryptEnd(N8_EncryptObject_t *encryptObject_p,
1758 N8_Buffer_t *message_p,
1759 unsigned int *messageLength_p,
1760 N8_Event_t *event_p )
1762 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
1764 API_Request_t *req_p = NULL; /* request buffer */
1765 N8_Buffer_t *enc_p = NULL;
1766 uint32_t enc_a;
1767 N8_Buffer_t *res_p = NULL;
1768 uint32_t res_a;
1769 unsigned int nBytes;
1770 encryptData_t *callBackData_p = NULL;
1772 DBG(("N8_DecryptEnd\n"));
1775 /* verify objects */
1776 CHECK_OBJECT(encryptObject_p, ret);
1777 CHECK_OBJECT(message_p, ret);
1778 CHECK_OBJECT(messageLength_p, ret);
1780 CHECK_STRUCTURE(encryptObject_p->structureID, N8_ENCRYPT_STRUCT_ID, ret);
1782 ret = checkCipher(encryptObject_p->cipher);
1783 CHECK_RETURN(ret);
1785 /* sanity check the residual length */
1786 if (encryptObject_p->residualLength >= N8_DES_BLOCK_LENGTH)
1788 ret = N8_INVALID_OBJECT;
1789 break;
1792 *messageLength_p = 0;
1793 /* check to see if there is no work to be done. */
1794 if (encryptObject_p->residualLength == 0)
1796 /* if this was an asynchronous call, set the status to finished */
1797 if (event_p != NULL)
1799 N8_SET_EVENT_FINISHED(event_p, N8_EA);
1801 break;
1804 if (encryptObject_p->cipher == N8_CIPHER_DES)
1806 if (encryptObject_p->residualLength % N8_DES_BLOCK_LENGTH)
1808 ret = N8_INVALID_INPUT_SIZE;
1809 break;
1814 /* create request buffer */
1815 nBytes = 2 * NEXT_WORD_SIZE(encryptObject_p->residualLength);
1816 ret = createEARequestBuffer(&req_p,
1817 encryptObject_p->unitID,
1818 N8_CB_EA_DECRYPT_NUMCMDS,
1819 resultHandler, nBytes);
1820 CHECK_RETURN(ret);
1822 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
1823 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
1825 enc_a = res_a + NEXT_WORD_SIZE(encryptObject_p->residualLength);
1826 enc_p = res_p + NEXT_WORD_SIZE(encryptObject_p->residualLength);
1828 /* copy the residual message into the kernel memory buffer */
1829 memcpy(enc_p,
1830 encryptObject_p->residual_p,
1831 encryptObject_p->residualLength);
1833 /* set the copy back parameters for returning the results to the user.
1834 * the main data is represented by the copy back structures in the request
1835 * and the extra data is in the post-processing data. */
1836 callBackData_p = (encryptData_t *)&req_p->postProcessBuffer;
1837 req_p->postProcessingData_p = (void *) callBackData_p;
1838 callBackData_p->encryptedMsgLen_p = messageLength_p;
1839 callBackData_p->encryptObject_p = encryptObject_p;
1840 callBackData_p->nextIV_p = NULL;
1841 req_p->copyBackSize = encryptObject_p->residualLength;
1842 req_p->copyBackFrom_p = res_p;
1843 req_p->copyBackTo_p = message_p;
1844 encryptObject_p->residualLength = 0;
1846 ret = cb_ea_decrypt(req_p,
1847 req_p->EA_CommandBlock_ptr,
1848 encryptObject_p,
1849 enc_a,
1850 res_a,
1851 encryptObject_p->residualLength);
1853 CHECK_RETURN(ret);
1854 QUEUE_AND_CHECK(event_p, req_p, ret);
1855 HANDLE_EVENT(event_p, req_p, ret);
1856 } while (FALSE);
1859 * Deallocate the request if we arrived from an error condition.
1861 if (ret != N8_STATUS_OK)
1863 freeRequest(req_p);
1865 DBG(("N8_DecryptEnd - FINISHED\n"));
1866 return ret;
1867 } /* N8_DecryptEnd */