Expand PMF_FN_* macros.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_packet_IPSec.c
blob625250bb38b4604597d85a21e024cd0a231f31b4
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_packet_IPSec.c,v 1.1 2008/10/30 12:02:14 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_packet_IPSec.c
38 * @brief Contains IPSec packet level interface functions.
40 * Functions:
41 * N8_IPSecEncryptAuthenticate - Encrypt and authenticate an entire
42 * IPSec record.
44 * N8_IPSecDecryptVerify - Decrypt and verify an entire IPSec
45 * record.
48 *****************************************************************************/
50 /*****************************************************************************
51 * Revision history:
52 * 08/18/03 brr Combine Encrypt/Decrypt command block generators for SSL,
53 * TLS, & IPsec.
54 * 07/28/03 brr Removed obsolete #ifdefs. (Bug 918)
55 * 07/01/03 brr Added option to use no hashing algorithm.
56 * 05/27/03 brr Removed N8_preamble call since N8_PacketInitialize must be
57 * called prior to Encrypt/Decrypt operations.
58 * 05/20/03 brr Modified N8_PacketInitialize to setup function pointers &
59 * lengths used in the Encrypt/Decrypt operations. Eliminated
60 * several switch statements from Encrypt/Decrypt operations.
61 * 02/23/03 jpw Don't copy computedHMAC_p if ptr is NULL. Yields better
62 * memory and CPU utilization.
63 * 03/04/03 brr Added support for N8_PACKETMEMORY_REQUEST mode which avoids
64 * copying the packet into a kernel buffer.
65 * 08/05/02 bac Cosmetic changes to enhance readability.
66 * 05/20/02 brr Free the request for all error conditions.
67 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
68 * 04/19/02 bac Use IPSEC_DATA_BLOCK_SIZE instead of IPSEC_DATA_LENGTH_MIN,
69 * where checking the data length. Fixes BUG #716.
70 * 04/01/02 brr Validate computedHMAC_p before use in N8_IPSecDecryptVerify.
71 * 03/26/02 brr Allocate the data buffer as part of the API request.
72 * 02/28/02 brr Do not include any QMgr include files.
73 * 01/31/02 brr Eliminated the memory allocation for postProcessingData.
74 * 01/23/02 bac Deferred loading of contexts.
75 * 12/11/01 mel Fixed bug #397: addBlockToFree(postData_p..) and deleted
76 * freeing postData_p from result handlers.
77 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
78 * 11/12/01 hml Added structure verification (bug 261).
79 * 10/30/01 bac Trivial changes to spell IPsec as preferred.
80 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
81 * 10/01/01 hml Added multiunit functionality.
82 * 09/20/01 bac The interface to the command block generators changed and now
83 * accept the command block buffer. All calls to cb_ea methods
84 * changed herein.
85 * 09/06/01 bac Added include of <string.h> to silence warning.
86 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
87 * 07/30/01 bac Pass chip id to createEARequestBuffer.
88 * 07/11/01 mel Added use of NEXT_WORD_SIZE to ensure split kernel memory is
89 * word-aligned.
90 * 06/25/01 bac Kernel mem mgt changes. Standardization.
91 * 05/30/01 bac Removed unused variable.
92 * 05/23/01 bac Fixed verify argument so the value can be returned.
93 * 05/08/01 mel Original version.
94 ****************************************************************************/
95 /** @defgroup ipsec_packet Packet-level routines for IPSec
98 #include "n8_common.h" /* common definitions */
99 #include "n8_pub_errors.h" /* Errors definition */
100 #include "n8_enqueue_common.h" /* common definitions for enqueue */
101 #include "n8_cb_ea.h"
102 #include "n8_util.h"
103 #include "n8_packet.h"
104 #include "n8_util.h"
106 /* structure for toting around buffers to be compared and result destination in
107 * result handler for N8_IPSecDecryptVerify */
108 typedef struct
110 N8_Buffer_t *computedHMAC_p;
111 N8_Buffer_t *data_p;
112 N8_Buffer_t *res_p;
113 int dataLength;
114 N8_Boolean_t *verify_p;
115 N8_HashAlgorithm_t hashAlgorithm;
116 } ipsecVerifyPostDataStruct_t;
118 /**********************************************************************
119 * resultHandlerIPSecVerify
120 **********************************************************************/
121 static void resultHandlerIPSecVerify(API_Request_t* req_p)
123 ipsecVerifyPostDataStruct_t *postData_p = NULL;
124 EA_IPSEC_CMD_BLOCK_t *cmd_ptr = NULL;
125 char *title = "resultHandlerIPSecVerify";
126 unsigned int actualDataLength;
128 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
130 DBG(("%s call-back with success\n", title));
131 cmd_ptr = (EA_IPSEC_CMD_BLOCK_t *) req_p->EA_CommandBlock_ptr;
132 postData_p = (ipsecVerifyPostDataStruct_t *) req_p->postProcessingData_p;
134 /* assign the actual data length to skip over the HMAC */
135 actualDataLength = postData_p->dataLength - HMAC_LENGTH;
137 /* No copy is necessary when res_p is NULL since the chip wrote the */
138 /* results directly to the caller's buffer. */
139 if (postData_p->res_p != NULL)
141 memcpy(postData_p->data_p, postData_p->res_p, actualDataLength);
144 if (postData_p->hashAlgorithm != N8_HASH_NONE )
147 if (postData_p->computedHMAC_p != NULL ) {
148 /* copy computed HMAC */
149 /* return it network byte order */
150 uint32_to_BE(cmd_ptr->opad[2],
151 postData_p->computedHMAC_p + sizeof(uint32_t) * 0);
152 uint32_to_BE(cmd_ptr->opad[3],
153 postData_p->computedHMAC_p + sizeof(uint32_t) * 1);
154 uint32_to_BE(cmd_ptr->opad[4],
155 postData_p->computedHMAC_p + sizeof(uint32_t) * 2);
158 uint32_to_BE(cmd_ptr->opad[2],
159 postData_p->data_p + actualDataLength + sizeof(uint32_t) * 0);
160 uint32_to_BE(cmd_ptr->opad[3],
161 postData_p->data_p + actualDataLength + sizeof(uint32_t) * 1);
162 uint32_to_BE(cmd_ptr->opad[4],
163 postData_p->data_p + actualDataLength + sizeof(uint32_t) * 2);
165 if ((cmd_ptr->result & EA_IPSec_MAC_Mismatch) == 0)
167 *(postData_p->verify_p) = N8_TRUE;
170 else
172 *(postData_p->verify_p) = N8_TRUE;
175 else
177 RESULT_HANDLER_WARNING(title, req_p);
179 } /* resultHandlerIPSecVerify */
180 /*****************************************************************************
181 * N8_IPSecEncryptAuthenticate
182 *****************************************************************************/
183 /** @ingroup ipsec_packet
184 * @brief Encrypt and authenticate an entire IPSec record.
186 * Encrypt and authenticate an entire IPSec record. PacketObject is a packet
187 * object previously initialized by a call to N8_PacketInitialize specifying
188 * IPSec as the packet protocol to use. PacketObject provides encryption and
189 * authentication information to be used in the call. The decryption algorithm
190 * can only be DES as specified when PacketObject was initialized. The
191 * authentication algorithm can be HMAC-MD5-96 or HMACSHA-1-96 as specified
192 * when PacketObject was initialized. Thus, two combinations of
193 * encryption/authentication can be performed: DES/HMAC-MD5-96 and
194 * DES/HMAC-SHA-1-96. The SPI parameter specifies the IPSec Security Parameter
195 * Index of the message. The SPI is used along with the sequence number and
196 * the DES initialization vector (taken from information specified in the
197 * PacketObject) in the authentication computation. The message contents of the
198 * IPSec packet is given in Data; its length in bytes must be specified in
199 * packetLength. Note that Data must include all of the information to be
200 * encrypted according to the IPSec specification; this includes the TCP and
201 * IP headers if present (the IP header is only present in tunnel mode) and must
202 * also include the terminating pad, pad length and next header fields.
203 * The byte length of Data is specified in packetLength and must also include all
204 * of these fields. packetLength must be a multiple of 8. The fully encrypted and
205 * authenticated Data is returned in Result, including the encrypted data
206 * followed by the HMAC-MD5-96 or HMAC-SHA-1-96 authentication value.
208 * @param packetObject_p RW: The object denoting the decryption and
209 * verification computation to be done. PacketObject
210 * must have been initialized for use with IPSec.
211 * The state in PacketObject will be updated if
212 * necessary as part of the call. <BR>
213 * @param packet_p RO: The ESP packet beginning with the Security
214 * Parameter Index, Sequence Number and data payload
215 * including DES initialization vector and ending
216 * with the pad, pad length, and next header fields
217 * as specified by the IPSec protocol.<BR>
218 * @param packetLength RO: The length of Data, in bytes, from 8 bytes - 17 KBytes
219 * inclusive. A length < 8 or not a multiple of 8 is
220 * illegal and results in an error.<BR>
221 * @param result_p WO: The encrypted / authenticated data, complete with
222 * authentication data. Result must be of sufficient
223 * size to hold the fully encrypted & authenticated
224 * message; its size must be at least packetLength +
225 * IPSEC_AUTHENTICATION_DATA_LENGTH
226 * (hash size for all hash algorithms).<BR>
227 * @param event_p RW: On input, if null the call is synchronous and no
228 * event is returned. The operation is complete when
229 * the call returns. If non-null, then the call is
230 * asynchronous; an event is returned that can be used
231 * to determine when the operation completes.
234 * @return
235 * packetObject_p - The state in PacketObject will be updated if necessary as
236 * part of the call.
237 * result_p - The encrypted / authenticated data, complete with
238 * authentication data.
239 * ret - returns N8_STATUS_OK if successful or Error value.
241 * @par Errors:
242 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
243 * address<BR>
244 * N8_INVALID_INPUT_SIZE - The value of packetLength is less then 8 or bigger
245 * then 17 KBytes or is not a multiple of 8.
246 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
247 * N8_HARDWARE_ERROR - couldn't write to context memory
250 * @par Assumptions:
251 * packetObject_p was initialized and all parameters checked.<BR>
252 * For IPSec, the authentication data is always
253 * 12 (IPSEC_AUTHENTICATION_DATA_LENGTH) bytes (the 12 most
254 * significant bytes of the standard 16 byte MD5 or 20 byte SHA-1 value) and
255 * is not encrypted. Result is always packetLength + 12 bytes in length.
256 * The caller is responsible for ensuring that Result is this size.
257 *****************************************************************************/
258 N8_Status_t N8_IPSecEncryptAuthenticate(N8_Packet_t *packetObject_p,
259 N8_IPSecPacket_t *packet_p,
260 int packetLength,
261 N8_IPSecPacket_t *result_p,
262 N8_Event_t *event_p )
264 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
266 API_Request_t *req_p = NULL; /* request buffer */
267 EA_CMD_BLOCK_t *next_cb_p = NULL;
268 int dataLength;
269 unsigned long pack_a;
270 N8_Buffer_t *pack_p = NULL;
271 unsigned long res_a;
272 N8_Buffer_t *res_p = NULL;
273 N8_Buffer_t *ctx_p = NULL;
274 uint32_t ctx_a;
275 int nBytes;
276 int numCommands;
277 int numCtxBytes = 0;
278 void *callbackFcn = NULL;
279 n8_ctxLoadFcn_t ctxLoadFcn;
280 DBG(("N8_IPSecEncryptAuthenticate\n"));
283 /* verify data length */
284 if ((packetLength < IPSEC_DATA_LENGTH_MIN) || (packetLength > IPSEC_DATA_LENGTH_MAX))
286 DBG(("Data length is out of range\n"));
287 ret = N8_INVALID_INPUT_SIZE;
288 break;
291 if (packetLength % IPSEC_DATA_BLOCK_SIZE)
293 DBG(("Data length is not a multiple of %d\n", IPSEC_DATA_BLOCK_SIZE));
294 ret = N8_INVALID_INPUT_SIZE;
295 break;
298 /* verify packet object */
299 CHECK_OBJECT(packetObject_p, ret);
300 CHECK_STRUCTURE(packetObject_p->structureID, N8_PACKET_STRUCT_ID, ret);
301 /* verify data object */
302 CHECK_OBJECT(packet_p, ret);
303 /* verify result object */
304 CHECK_OBJECT(result_p, ret);
306 dataLength = packetLength - IPSEC_PACKET_HEADER_LENGTH;
307 numCommands = N8_CB_EA_IPSECENCRYPTAUTHENTICATE_NUMCMDS;
308 if (packetObject_p->contextLoadNeeded == N8_TRUE)
310 numCommands += packetObject_p->ctxLoadCmds;
311 numCtxBytes = NEXT_WORD_SIZE(EA_CTX_Record_Byte_Length);
314 /* compute the space needed for the size of context load, if required */
315 nBytes = NEXT_WORD_SIZE(HMAC_LENGTH) + numCtxBytes;
317 /* If the data must be copied to a kernel before the chip can operate */
318 /* on it, compute the additional space required and setup the callback */
319 /* function to copy the result once the operation has completed. */
320 if (packetObject_p->mode == N8_PACKETMEMORY_NONE)
322 nBytes += NEXT_WORD_SIZE(dataLength) + /* packet data length pack_p */
323 NEXT_WORD_SIZE(packetLength);/* result packet length res_p */
324 callbackFcn = resultHandlerGeneric;
327 /* create request buffer */
328 ret = createEARequestBuffer(&req_p,
329 packetObject_p->unitID,
330 numCommands,
331 callbackFcn,
332 nBytes);
333 CHECK_RETURN(ret);
335 /* Compute the context memory pointers. */
336 ctx_a = req_p->qr.physicalAddress + req_p->dataoffset;
337 ctx_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
339 /* Compute the addresses for the packet and result buffer. */
340 if (packetObject_p->mode == N8_PACKETMEMORY_NONE)
342 /* The data must be copied to this kernel before the chip can operate */
343 /* on it, compute the addresses within the kernel buffer and copy in */
344 /* the packet. */
345 pack_a = ctx_a + numCtxBytes;
346 pack_p = ctx_p + numCtxBytes;
348 res_a = pack_a + NEXT_WORD_SIZE(dataLength);
349 res_p = pack_p + NEXT_WORD_SIZE(dataLength);
351 memcpy(pack_p, &packet_p[IPSEC_DATA_OFFSET], dataLength);
354 else
356 /* The chip can access the data directly, compute the */
357 /* physical addresses of the packet & result buffer. */
358 pack_a = N8_VirtToPhys(&packet_p[IPSEC_DATA_OFFSET]);
359 res_a = N8_VirtToPhys(&result_p[IPSEC_DATA_OFFSET]);
363 next_cb_p = req_p->EA_CommandBlock_ptr;
365 memcpy(result_p, packet_p, IPSEC_PACKET_HEADER_LENGTH);
367 packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number =
368 IPSEC_EXTRACT_SEQUENCE_NIMBER(packet_p);
370 /* generate the command blocks necessary to load the context, if required */
371 if (packetObject_p->contextLoadNeeded == N8_TRUE)
373 /* Generate the command blocks for the Context Load */
374 ctxLoadFcn = (n8_ctxLoadFcn_t)packetObject_p->ctxLoadFcn;
375 ret = ctxLoadFcn(req_p,
376 next_cb_p,
377 packetObject_p,
378 &packetObject_p->cipherInfo,
379 packetObject_p->packetHashAlgorithm,
380 ctx_p,
381 ctx_a,
382 &next_cb_p);
383 CHECK_RETURN(ret);
385 packetObject_p->contextLoadNeeded = N8_FALSE;
388 memcpy(&packetObject_p->cipherInfo.IV[0], packet_p+IPSEC_IV_OFFSET,
389 N8_DES_KEY_LENGTH);
391 cb_ea_IPsec(next_cb_p,
392 packetObject_p,
393 pack_a,
394 res_a,
395 dataLength,
396 IPSEC_EXTRACT_SPI(packet_p),
397 packetObject_p->encOpCode);
400 req_p->copyBackTo_p = result_p + IPSEC_DATA_OFFSET;
401 req_p->copyBackFrom_p = res_p;
402 req_p->copyBackSize = dataLength + HMAC_LENGTH;
404 QUEUE_AND_CHECK(event_p, req_p, ret)
405 HANDLE_EVENT(event_p, req_p, ret);
406 } while (FALSE);
408 if (ret != N8_STATUS_OK)
410 freeRequest(req_p);
412 DBG(("N8_IPSecEncryptAuthenticate - FINISHED\n"));
413 return ret;
414 } /* N8_IPSecEncryptAuthenticate */
418 /*****************************************************************************
419 * N8_IPSecDecryptVerify
420 *****************************************************************************/
421 /** @ingroup ipsec_packet
422 * @brief Decrypt and verify an entire IPSec record.
424 * Decrypt and verify an entire IPSec record. PacketObject is a packet object
425 * previously initialized by a call to N8_PacketInitialize specifying IPSec
426 * as the packet protocol to use. PacketObject provides encryption and
427 * authentication information to be used in the call. The decryption algorithm
428 * can only be DES as specified when PacketObject was initialized. The
429 * authentication algorithm can be HMAC-MD5-96 or HMAC-SHA-1-96 as specified
430 * when PacketObject was initialized. Thus, two combinations of
431 * decryption/verification can be performed: DES/HMAC-MD5-96 and DES/HMAC-SHA-1-96.
432 * The SPI parameter specifies the IPSec Security Parameter Index of the message.
433 * The SPI is used along with the sequence number and the DES initialization
434 * vector (taken from PacketObject) in the authentication computation. The
435 * message contents of the encrypted and authenticated IPSec packet is given
436 * in EncryptedData; its length in bytes must be specified in encryptedPacketLength.
437 * Note that EncryptedData must end with the unencrypted12-byte authentication
438 * value as required by the IPSec specification. The byte length of EncryptedData
439 * including the 12 byte authentication value is specified in encryptedPacketLength.
440 * encryptedPacketLength must be at least 20 (i.e., EncryptedData must consist of
441 * at least one DES block to be decrypted plus the mandatory 12 byte
442 * authentication value), and must be of the form 12 + n*8 for n > 0. The decrypted
443 * EncryptedData is returned in Result, including the decrypted data followed by
444 * the 12 bytes of authentication data. Result is always encryptedPacketLength
445 * bytes in length. The caller is responsible for ensuring that Result is at
446 * least this size. This call also calculates the authentication value on the
447 * EncryptedData and compares this calculated value to the value at the end of
448 * EncryptedData. If these two values are equal, the verification succeeds and
449 * True is returned in Verify, otherwise False is returned in Verify.
452 * @param packetObject_p RW: The object denoting the decryption and
453 * verification computation to be done. PacketObject
454 * must have been initialized for use with IPSec.
455 * The state in PacketObject will be updated if
456 * necessary as part of the call. <BR>
457 * @param encryptedPacket_p RO: The message portion / contents of the IPSec packet.<BR>
458 * @param encryptedPacketLength RO: The length of EncryptedData, in bytes,
459 * from 20 bytes - 18 KBytes inclusive. A length
460 * less than 20 or not of the form 12+n*8 is illegal
461 * and results in an error.<BR>
462 * @param Verify WO: Returned as True if the computed authentication
463 * value on EncryptedData matches the authentication
464 * value contained at the end of EncryptedData;
465 * otherwise False is returned. If Verify is False,
466 * the contents of Result may be gibberish and/or
467 * have been altered.<BR>
468 * @param result_p WO: The decrypted / authenticated data, complete
469 * with authentication data. Result must be of
470 * sufficient size to hold the decrypted &
471 * authenticated message; its size must be at least
472 * EncryptedDataLeng.<BR>
473 * @param event_p RW: On input, if null the call is synchronous and no
474 * event is returned. The operation is complete when
475 * the call returns. If non-null, then the call is
476 * asynchronous; an event is returned that can be used
477 * to determine when the operation completes.
480 * @return
481 * packetObject_p - The state in PacketObject will be updated if necessary as
482 * part of the call.
483 * result_p - The encrypted / authenticated data, complete with
484 * authentication data.
485 * ret - returns N8_STATUS_OK if successful or Error value.
487 * @par Errors:
488 * N8_INVALID_OBJECT - packet object is zero, couldn't write to unspecified
489 * address<BR>
490 * N8_INVALID_INPUT_SIZE - The value of packetLength is < 20 or > 18 KBytes or
491 * is not of the form 12 + n*8; no operation is
492 * performed and no result is returned.
493 * N8_UNIMPLEMENTED_FUNCTION - not supported protocol configuration requested
494 * N8_HARDWARE_ERROR - couldn't write to context memory
497 * @par Assumptions:
498 * packetObject_p was initialized and all parameters checked.
499 *****************************************************************************/
500 N8_Status_t N8_IPSecDecryptVerify( N8_Packet_t *packetObject_p,
501 N8_IPSecPacket_t *encryptedPacket_p,
502 int encryptedPacketLength,
503 N8_Buffer_t *computedHMAC_p,
504 N8_Boolean_t *verify_p,
505 N8_IPSecPacket_t *result_p,
506 N8_Event_t *event_p )
508 N8_Status_t ret = N8_STATUS_OK; /* the return status: OK or ERROR */
510 API_Request_t *req_p = NULL; /* request buffer */
511 EA_CMD_BLOCK_t *next_cb_p = NULL;
512 int dataLength;
513 unsigned long pack_a;
514 N8_Buffer_t *pack_p = NULL;
515 unsigned long res_a;
516 N8_Buffer_t *res_p = NULL;
517 N8_Buffer_t *ctx_p = NULL;
518 uint32_t ctx_a;
519 int nBytes;
520 int numCommands;
521 int numCtxBytes = 0;
522 ipsecVerifyPostDataStruct_t *postData_p = NULL;
523 n8_ctxLoadFcn_t ctxLoadFcn;
525 DBG(("N8_IPSecDecryptVerify\n"));
528 *verify_p = N8_FALSE;
529 /* verify data length */
530 if ((encryptedPacketLength < IPSEC_DECRYPTED_DATA_LENGTH_MIN) ||
531 (encryptedPacketLength > IPSEC_DATA_LENGTH_MAX))
533 DBG(("Data length is out of range\n"));
534 ret = N8_INVALID_INPUT_SIZE;
535 break;
538 if ((encryptedPacketLength - IPSEC_AUTHENTICATION_DATA_LENGTH) % IPSEC_DATA_BLOCK_SIZE)
540 DBG(("Data length is not a multiple of %d\n", IPSEC_DATA_BLOCK_SIZE));
541 ret = N8_INVALID_INPUT_SIZE;
542 break;
544 /* verify packet object */
545 CHECK_OBJECT(packetObject_p, ret);
546 CHECK_STRUCTURE(packetObject_p->structureID, N8_PACKET_STRUCT_ID, ret);
547 /* verify encrypted data object */
548 CHECK_OBJECT(encryptedPacket_p, ret);
549 /* verify result object */
550 CHECK_OBJECT(result_p, ret);
551 #ifdef NO_MAC_COPYBACK
552 CHECK_OBJECT(computedHMAC_p, ret);
553 #endif
555 dataLength = encryptedPacketLength - IPSEC_PACKET_HEADER_LENGTH;
557 numCommands = N8_CB_EA_IPSECDECRYPTVERIFY_NUMCMDS;
558 if (packetObject_p->contextLoadNeeded == N8_TRUE)
560 numCommands += packetObject_p->ctxLoadCmds;
561 numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX));
564 /* compute the space needed for the chip to place the result */
565 nBytes = NEXT_WORD_SIZE(HMAC_LENGTH) + numCtxBytes; /* context to load */
566 if (packetObject_p->mode == N8_PACKETMEMORY_NONE)
568 nBytes += NEXT_WORD_SIZE(dataLength * 2);
571 /* create request buffer */
572 ret = createEARequestBuffer(&req_p,
573 packetObject_p->unitID,
574 numCommands,
575 resultHandlerIPSecVerify,
576 nBytes);
577 CHECK_RETURN(ret);
579 req_p->copyBackCommandBlock = N8_TRUE;
581 /* Compute the addresses for the context. */
582 ctx_a = req_p->qr.physicalAddress + req_p->dataoffset;
583 ctx_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
585 /* Compute the addresses for the packet and result buffer. */
586 if (packetObject_p->mode == N8_PACKETMEMORY_NONE)
588 /* The data must be copied to this kernel before the chip can operate */
589 /* on it, compute the addresses within the kernel buffer and copy in */
590 /* the packet. */
591 pack_a = ctx_a + numCtxBytes;
592 pack_p = ctx_p + numCtxBytes;
594 res_a = pack_a + NEXT_WORD_SIZE(dataLength);
595 res_p = pack_p + NEXT_WORD_SIZE(dataLength);
597 memcpy(pack_p, encryptedPacket_p + IPSEC_DATA_OFFSET, dataLength);
600 else
602 /* The chip can access the data directly, compute the */
603 /* physical addresses of the packet & result buffer. */
604 pack_a = N8_VirtToPhys(encryptedPacket_p + IPSEC_DATA_OFFSET);
605 res_a = N8_VirtToPhys(result_p + IPSEC_DATA_OFFSET);
608 next_cb_p = req_p->EA_CommandBlock_ptr;
610 /* generate the command blocks necessary to load the context, if required */
611 if (packetObject_p->contextLoadNeeded == N8_TRUE)
613 /* Generate the command blocks for the Context Load */
614 ctxLoadFcn = (n8_ctxLoadFcn_t)packetObject_p->ctxLoadFcn;
615 ret = ctxLoadFcn(req_p,
616 next_cb_p,
617 packetObject_p,
618 &packetObject_p->cipherInfo,
619 packetObject_p->packetHashAlgorithm,
620 ctx_p,
621 ctx_a,
622 &next_cb_p);
623 CHECK_RETURN(ret);
625 packetObject_p->contextLoadNeeded = N8_FALSE;
628 memcpy(&packetObject_p->cipherInfo.IV[0], encryptedPacket_p+8,8);
629 packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number =
630 IPSEC_EXTRACT_SEQUENCE_NIMBER(encryptedPacket_p);
632 cb_ea_IPsec(next_cb_p,
633 packetObject_p,
634 pack_a,
635 res_a,
636 dataLength,
637 IPSEC_EXTRACT_SPI(encryptedPacket_p),
638 packetObject_p->decOpCode);
640 postData_p = (ipsecVerifyPostDataStruct_t *)req_p->postProcessBuffer;
641 postData_p->computedHMAC_p = computedHMAC_p;
642 postData_p->data_p = result_p + IPSEC_DATA_OFFSET;
643 postData_p->res_p = res_p;
644 postData_p->dataLength = dataLength;
645 postData_p->verify_p = verify_p;
646 postData_p->hashAlgorithm = packetObject_p->packetHashAlgorithm;
648 /* setup post processing buffer pointer */
649 req_p->postProcessingData_p = (void *) postData_p;
651 /* decrypt data */
652 QUEUE_AND_CHECK(event_p, req_p, ret)
653 HANDLE_EVENT(event_p, req_p, ret);
654 /* compare authentication values */
656 memcpy(result_p, encryptedPacket_p, IPSEC_PACKET_HEADER_LENGTH);
657 if (*verify_p == N8_TRUE)
659 packetObject_p->cipherInfo.key.IPsecKeyDES.sequence_number =
660 IPSEC_EXTRACT_SEQUENCE_NIMBER(encryptedPacket_p);
661 memcpy(&packetObject_p->cipherInfo.IV[0],
662 encryptedPacket_p+IPSEC_IV_OFFSET,
663 N8_DES_KEY_LENGTH);
667 } while (FALSE);
669 if (ret != N8_STATUS_OK)
671 freeRequest(req_p);
673 DBG(("N8_IPSecDecryptVerify - FINISHED\n"));
674 return ret;
675 } /* N8_IPSecDecryptVerify */