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_cryptographic.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_cryptographic.c
38 * @brief Contains packet 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 /*****************************************************************************
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
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 */
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.
114 unsigned int *encryptedMsgLen_p
;
115 N8_EncryptObject_t
*encryptObject_p
;
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
;
132 static N8_Status_t
checkCipher(N8_Cipher_t cipher
)
134 N8_Status_t ret
= N8_STATUS_OK
;
141 ret
= N8_INVALID_CIPHER
;
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
))
154 DBG(("copyBackSize = %d\n", req_p
->copyBackSize
));
156 printN8Buffer((N8_Buffer_t
*) req_p
->copyBackFrom_p
, req_p
->copyBackSize
);
158 if (req_p
->copyBackTo_p
!= NULL
) {
162 memcpy(req_p
->copyBackTo_p
,
163 req_p
->copyBackFrom_p
,
164 req_p
->copyBackSize
);
167 DBG(("cuio_copyback\n"));
169 cuio_copyback(req_p
->copyBackTo_uio
, 0,
171 req_p
->copyBackFrom_p
);
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
);
200 printN8Buffer((N8_Buffer_t
*) encryptObject_p
->cipherInfo
.key
.keyDES
.IV
,
201 N8_DES_BLOCK_LENGTH
);
204 /* set the returned value for the encrypted message length */
205 *(callBackData_p
->encryptedMsgLen_p
) = req_p
->copyBackSize
;
210 RESULT_HANDLER_WARNING(title
, req_p
);
212 } /* resultHandler */
219 /*****************************************************************************
220 * N8_EncryptInitialize
221 *****************************************************************************/
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 *
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.
269 * encryptObject_p - initialized encrypt object.
270 * ret - returns N8_STATUS_OK if successful or Error value.
273 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
275 * N8_INVALID_CIPHER - The value of Cipher is not one of the legal values
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
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
,
312 N8_Status_t ret
= N8_STATUS_OK
; /* the return status: OK or
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"));
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
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
;
346 /* copy the contents into our encryption object and set the context in
347 * use flag to true */
348 memcpy(&encryptObject_p
->contextHandle
,
350 sizeof(N8_ContextHandle_t
));
351 encryptObject_p
->unitID
= contextHandle_p
->unitID
;
352 encryptObject_p
->contextHandle
.inUse
= N8_TRUE
;
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
;
373 /* verify that a valid context has been passed */
374 if (contextHandle_p
== NULL
)
376 ret
= N8_INVALID_OBJECT
;
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
;
392 /* create request buffer */
393 ret
= createEARequestBuffer(&req_p
,
394 encryptObject_p
->unitID
,
395 N8_CB_EA_LOADARC4KEYONLY_NUMCMDS
,
397 sizeof(EA_SSL30_CTX
));
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
),
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
;
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
)
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
)
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
)
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
))
462 if (contextHandle_p
!= NULL
)
464 /* create request buffer */
465 ret
= createEARequestBuffer(&req_p
,
466 encryptObject_p
->unitID
,
467 N8_CB_EA_LOADDESKEYONLY_NUMCMDS
,
469 sizeof(EA_SSL30_CTX
));
472 /* DES context memory */
473 ret
= cb_ea_loadDESkeyOnly(req_p
,
474 req_p
->EA_CommandBlock_ptr
,
475 &(encryptObject_p
->contextHandle
),
482 DBG(("Invalid cipher\n"));
483 DBG(("N8_EncryptInitialize - return Error\n"));
484 ret
= N8_INVALID_CIPHER
;
488 /* finish initialize packet object with protocol related values */
490 memcpy(&encryptObject_p
->cipherInfo
, cipherInfo_p
, sizeof(N8_EncryptCipher_t
));
491 /* encryption algorithm */
492 encryptObject_p
->cipher
= cipher
;
496 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
497 HANDLE_EVENT(event_p
, req_p
, ret
);
503 N8_SET_EVENT_FINISHED(event_p
, N8_EA
);
509 * Deallocate the request if we arrived from an error condition.
511 if (ret
!= N8_STATUS_OK
)
513 /* free the request */
519 /* set the structure pointer to the correct state */
520 encryptObject_p
->structureID
= N8_ENCRYPT_STRUCT_ID
;
523 DBG(("N8_EncryptInitialize - FINISHED\n"));
525 } /* N8_EncryptInitialize */
527 /******************************************************************************
529 *****************************************************************************/
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>
560 * encryptObject_p - The state in PacketObject will be updated if necessary as
562 * encryptedMessage_p - The encrypted data.
563 * ret - returns N8_STATUS_OK if successful or Error value.
566 * N8_INVALID_OBJECT - object is zero, couldn't write/read unspecified
568 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
570 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
571 * N8_HARDWARE_ERROR - couldn't write to context memory
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
;
590 N8_Buffer_t
*res_p
= NULL
;
592 unsigned int paddedMessageLength
;
595 DBG(("N8_Encrypt\n"));
598 /* verify data length */
599 ret
= verifyInputLength(messageLength
);
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
);
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
);
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
,
651 paddedMessageLength
);
654 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
655 HANDLE_EVENT(event_p
, req_p
, ret
);
659 * Deallocate the request if we arrived from an error condition.
661 if (ret
!= N8_STATUS_OK
)
663 /* free the request */
666 DBG(("N8_Encrypt - FINISHED\n"));
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
;
683 N8_Buffer_t
*res_p
= NULL
;
685 unsigned int paddedMessageLength
;
688 DBG(("N8_Encrypt\n"));
691 /* verify data length */
692 ret
= verifyInputLength(messageLength
);
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
);
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
);
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
,
745 paddedMessageLength
);
748 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
749 HANDLE_EVENT(event_p
, req_p
, ret
);
753 * Deallocate the request if we arrived from an error condition.
755 if (ret
!= N8_STATUS_OK
)
757 /* free the request */
760 DBG(("N8_Encrypt - FINISHED\n"));
763 /******************************************************************************
765 *****************************************************************************/
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>
797 * packetObject_p - The state in PacketObject will be updated if necessary as
799 * encryptedMessage_p - The encrypted data.
800 * ret - returns N8_STATUS_OK if successful or Error value.
803 * N8_INVALID_OBJECT - object is NULL, couldn't write/read unspecified
805 * N8_INVALID_INPUT_SIZE - The value of messageLength is less than 0 or bigger
807 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
808 * N8_HARDWARE_ERROR - couldn't write to context memory
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
,
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
830 uint32_t plain_a
; /* physical address of message to be
832 uint32_t res_a
; /* physical address of encrypted
834 unsigned int totalLength
= 0; /* total length of this message plus
835 * any residual from previous
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
841 unsigned int fromThisMessageLength
= 0; /* amount of taken from this
844 encryptData_t
*callBackData_p
= NULL
;
846 DBG(("N8_EncryptPartial\n"));
849 /* verify data length */
850 ret
= verifyInputLength(messageLength
);
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
);
863 /* sanity check the residual length */
864 if (encryptObject_p
->residualLength
>= N8_DES_BLOCK_LENGTH
)
866 ret
= N8_INVALID_OBJECT
;
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
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
;
887 ret
= N8_INVALID_CIPHER
;
891 /* check to ensure we actually have some message to encrypt this go
895 /* copy the input to the end of the residual */
896 memcpy(&encryptObject_p
->residual_p
[encryptObject_p
->residualLength
],
899 encryptObject_p
->residualLength
+= messageLength
;
901 /* if this was an asynchronous call, set the status to finished */
904 N8_SET_EVENT_FINISHED(event_p
, N8_EA
);
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
);
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)
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)
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
],
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
);
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
,
980 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
981 HANDLE_EVENT(event_p
, req_p
, ret
);
985 * Deallocate the request if we arrived from an error condition.
987 if (ret
!= N8_STATUS_OK
)
991 DBG(("N8_EncryptPartial - FINISHED\n"));
993 } /* N8_EncryptPartial */
995 /******************************************************************************
997 *****************************************************************************/
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>
1029 * packetObject_p - The state in PacketObject will be updated if necessary as
1031 * encryptedMessage_p - The encrypted data.
1032 * ret - returns N8_STATUS_OK if successful or Error value.
1035 * N8_INVALID_OBJECT - object is zero, couldn't write/read unspecified
1037 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
1038 * N8_HARDWARE_ERROR - couldn't write to context memory
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
;
1056 N8_Buffer_t
*res_p
= NULL
;
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
);
1074 /* sanity check the residual length */
1075 if (encryptObject_p
->residualLength
>= N8_DES_BLOCK_LENGTH
)
1077 ret
= N8_INVALID_OBJECT
;
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
);
1093 paddedMessageLength
= encryptObject_p
->residualLength
;
1095 if (encryptObject_p
->cipher
== N8_CIPHER_DES
)
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
);
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 */
1120 encryptObject_p
->residual_p
,
1121 encryptObject_p
->residualLength
);
1122 /* set the padding bytes to 0x0 */
1123 memset(&plain_p
[encryptObject_p
->residualLength
],
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
,
1145 paddedMessageLength
);
1148 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1149 HANDLE_EVENT(event_p
, req_p
, ret
);
1154 * Deallocate the request if we arrived from an error condition.
1156 if (ret
!= N8_STATUS_OK
)
1160 DBG(("N8_EncryptEnd - FINISHED\n"));
1163 } /* N8_EncryptEnd */
1165 /******************************************************************************
1167 *****************************************************************************/
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.
1212 * encryptObject_p - The state in PacketObject will be updated if necessary as
1214 * message_p - The encrypted data.
1215 * ret - returns N8_STATUS_OK if successful or Error value.
1218 * N8_INVALID_OBJECT - encrypt object is zero, couldn't write to unspecified
1220 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
1222 * N8_HARDWARE_ERROR - couldn't decrypt
1224 * N8_MALLOC_FAILED - memory allocation failed
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
;
1238 N8_Buffer_t
*res_p
= NULL
;
1240 unsigned int nBytes
;
1242 DBG(("N8_Decrypt\n"));
1244 /* verify data length */
1245 ret
= verifyInputLength(encryptedMsgLen
);
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
);
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
;
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
);
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
,
1299 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1300 HANDLE_EVENT(event_p
, req_p
, ret
);
1304 * Deallocate the request if we arrived from an error condition.
1306 if (ret
!= N8_STATUS_OK
)
1308 /* free the request */
1311 DBG(("N8_Decrypt - FINISHED\n"));
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
;
1327 N8_Buffer_t
*res_p
= NULL
;
1329 unsigned int nBytes
;
1331 DBG(("N8_Decrypt\n"));
1333 /* verify data length */
1334 ret
= verifyInputLength(encryptedMsgLen
);
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
);
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
;
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
);
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
,
1389 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1390 HANDLE_EVENT(event_p
, req_p
, ret
);
1394 * Deallocate the request if we arrived from an error condition.
1396 if (ret
!= N8_STATUS_OK
)
1398 /* free the request */
1401 DBG(("N8_Decrypt - FINISHED\n"));
1405 /******************************************************************************
1407 *****************************************************************************/
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
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>
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.
1489 * N8_INVALID_OBJECT - encrypt object is zero, couldn't write to unspecified
1491 * N8_INVALID_INPUT_SIZE - The value of message length is less than 0 or bigger
1493 * N8_HARDWARE_ERROR - couldn't decrypt
1494 * N8_MALLOC_FAILED - memory allocation failed
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
;
1511 N8_Buffer_t
*res_p
= NULL
;
1514 unsigned int totalLength
= 0; /* total length of this message plus
1515 * any residual from previous
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
1521 unsigned int fromThisMessageLength
= 0; /* amount of taken from this
1523 encryptData_t
*callBackData_p
= NULL
;
1524 unsigned int nBytes
;
1526 DBG(("N8_DecryptPartial\n"));
1529 /* verify data length */
1530 ret
= verifyInputLength(encryptedMsgLen
);
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
);
1543 /* sanity check the residual length */
1544 if (encryptObject_p
->residualLength
>= N8_DES_BLOCK_LENGTH
)
1546 ret
= N8_INVALID_OBJECT
;
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
1553 *messageLength_p
= 0;
1554 switch (encryptObject_p
->cipher
)
1558 totalLength
= encryptObject_p
->residualLength
+ encryptedMsgLen
;
1559 nextResidualLength
= totalLength
% N8_DES_BLOCK_LENGTH
;
1560 msgLen
= totalLength
- nextResidualLength
;
1561 fromThisMessageLength
= encryptedMsgLen
- nextResidualLength
;
1564 case N8_CIPHER_ARC4
:
1566 fromThisMessageLength
= msgLen
= encryptedMsgLen
;
1571 /* check to ensure we actually have some message to encrypt this go
1575 /* copy the input to the end of the residual */
1576 memcpy(&encryptObject_p
->residual_p
[encryptObject_p
->residualLength
],
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
);
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
);
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
,
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
);
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
,
1662 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1663 HANDLE_EVENT(event_p
, req_p
, ret
);
1667 * Deallocate the request if we arrived from an error condition.
1669 if (ret
!= N8_STATUS_OK
)
1671 /* free the request */
1674 DBG(("N8_DecryptPartial - FINISHED\n"));
1676 } /* N8_DecryptPartial */
1678 /******************************************************************************
1680 *****************************************************************************/
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
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
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.
1742 * encryptObject_p - The state in encryptObject_p will be updated if necessary as
1744 * message_p - The decrypted data.
1745 * ret - returns N8_STATUS_OK if successful or Error value.
1748 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
1750 * N8_MALLOC_FAILED - memory allocation failed
1751 * N8_HARDWARE_ERROR - couldn't write to context memory
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
;
1767 N8_Buffer_t
*res_p
= NULL
;
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
);
1785 /* sanity check the residual length */
1786 if (encryptObject_p
->residualLength
>= N8_DES_BLOCK_LENGTH
)
1788 ret
= N8_INVALID_OBJECT
;
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
);
1804 if (encryptObject_p
->cipher
== N8_CIPHER_DES
)
1806 if (encryptObject_p
->residualLength
% N8_DES_BLOCK_LENGTH
)
1808 ret
= N8_INVALID_INPUT_SIZE
;
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
);
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 */
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
,
1851 encryptObject_p
->residualLength
);
1854 QUEUE_AND_CHECK(event_p
, req_p
, ret
);
1855 HANDLE_EVENT(event_p
, req_p
, ret
);
1859 * Deallocate the request if we arrived from an error condition.
1861 if (ret
!= N8_STATUS_OK
)
1865 DBG(("N8_DecryptEnd - FINISHED\n"));
1867 } /* N8_DecryptEnd */