Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / pci / n8 / common / api / n8_ssltls.c
blob891bc69f3f02237f90f8e5b4d1f082dfb5122ca7
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_ssltls.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
37 /** @file n8_ssltls.c
38 * @brief SSL 3.0 Packet Level Interfaces
40 * Implementation of functions for SSL 3.0 Packet Level Interfaces. Functions
41 * include:
42 * N8_SSLEncryptAuthenticate
43 * N8_SSLDecryptVerify
45 *****************************************************************************/
47 /*****************************************************************************
48 * Revision history:
50 * 08/18/03 brr Combine Encrypt/Decrypt command block generators for SSL,
51 * TLS, & IPsec.
52 * 07/28/03 brr Removed obsolete #ifdefs. (Bug 918)
53 * 07/01/03 brr Added option to use no hashing algorithm.
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 Modified N8_PacketInitialize to setup function pointers &
57 * lengths used in the Encrypt/Decrypt operations. Eliminated
58 * several switch statements from Encrypt/Decrypt operations.
59 * 11/01/02 jpw If the computedMAC_p parameter from N8_EA_DV is NULL
60 * then don't copy back the MAC value.
61 * 08/02/02 arh Fix N8_SSLTLSEncryptAuthenticate & N8_SSLTLSDecryptVerify
62 * to check packet object ptr before storing mode in it,
63 * preventing segmentation faults if passed ptr is null.
64 * This check got lost when N8_*Memory routines added.
65 * 07/16/02 arh Fix Bug #815: Make the N8_*Memory routines check for
66 * legal values for the mode in the packet object.
67 * 07/14/02 bac Simplified the calculation of the physical address for kernel
68 * buffers. Consolidated logic for kernel buffer requests.
69 * 06/14/02 hml Added the new N8_SSLTLS*Memory calls. The old calls are
70 * still supported.
71 * 06/10/02 hml Handle the new request pools.
72 * 05/20/02 brr Free the request for all error conditions.
73 * 05/07/02 msz New interface for QUEUE_AND_CHECK for new synchronous support.
74 * 03/29/02 hml Works correctly with user allocated kernel buffers.
75 * 03/26/02 brr Allocate the data buffer as part of the API request.
76 * 02/27/02 hml Correctly handles the propagation of the IV.
77 * 02/07/02 bac Deferred loading of the context caused the result handler to
78 * not copy the computed mac back from the correct command.
79 * 01/31/02 brr Eliminated the memory allocation for postProcessingData.
80 * 01/22/02 bac Added code to use software to do SSL and HMAC precomputes.
81 * 01/22/02 bac Added deferred loading of context until the first use.
82 * 01/21/02 bac Changes to support new kernel allocation scheme.
83 * 12/11/01 mel Fixed bug #397: addBlockToFree(postData_p..) and deleted
84 * freeing postData_p from result handlers.
85 * 11/24/01 brr Removed include of obsolete EA & PK specifice Queue files.
86 * 11/12/01 hml Added structure verification and changed PI_PROTOCOL_*
87 * to N8_PROTOCOL_*.
88 * 11/05/01 bac Added missing check of return code after KMALLOC.
89 * 10/11/01 brr Remove warnings exposed when optimization turned up.
90 * 10/02/01 bac Added use of RESULT_HANDLER_WARNING in all result handlers.
91 * 09/26/01 hml Get chip number out of the packet object.
92 * 09/20/01 bac The interface to the command block generators changed and now
93 * accept the command block buffer. All calls to cb_ea methods
94 * changed herein.
95 * 09/14/01 bac Fixed a bug where CHECK_RETURN was not being called in the
96 * correct spot. BUG #208.
97 * 09/12/01 bac Corrected the decrement of the sequence number upon failure of
98 * DES operations that do not use the context memory. The
99 * affected the methods resultHandlerSSLTLSDecrypt and
100 * resultHandlerSSLTLSEncrypt. BUG #195.
101 * 09/06/01 bac Added include of <string.h> to silence warning.
102 * 07/31/01 bac Added call to N8_preamble for all public interfaces.
103 * 07/30/01 bac Pass chip id to createEARequestBuffer.
104 * 06/28/01 bac Major fixes to get the encrypt and return packet lengths
105 * correct, removed 'freeRequest' from the result handlers as it
106 * now resides in the EventCheck routine.
107 * 06/25/01 bac Changes for kernel memory management.
108 * 06/14/01 bac Changes per code review: free requests upon error on enqueue,
109 * use define for N8_DES_BLOCK_MULTIPLE, correct use of
110 * N8_SSLTLS_MAX_DATA_SIZE_DECRYPT and
111 * N8_SSLTLS_MAX_DATA_SIZE_ENCRYPT
112 * 06/05/01 bac Changes to not rely on N8_SSLTLSPacket_t being packed (Bug
113 * #31).
114 * 05/30/01 bac Improved documentation of structures and return types (bug
115 * #27). Removed reference to API Request pointer in the
116 * QUEUE_AND_CHECK macro as the pointer will have already been
117 * freed (bug #17).
118 * 05/22/01 bac Changes to have N8_SSLTLSEncryptAuthenticate and
119 * N8_SSLTLSDecryptVerify take and return N8_SSLTLSPacket_t.
120 * Also, now calculate and return the packet lengths in the
121 * packet.
122 * 05/21/01 bac Removed unused resultHandler. Converted to
123 * N8_ContextHandler_t.
124 * 05/19/01 bac Free postProcessingData in resultHandlers when required.
125 * 05/18/01 bac Converted to N8_xMALLOC and N8_xFREE
126 * 05/18/01 bac Added support for Decrypt commands.
127 * 05/02/01 bac Original version.
128 ****************************************************************************/
129 /** @defgroup n8_ssltls Simon SSL/TLS Functions
132 #include "n8_enqueue_common.h"
133 #include "n8_util.h"
134 #include "n8_common.h"
135 #include "n8_ssltls.h"
136 #include "n8_cb_ea.h"
137 #include "n8_OS_intf.h"
138 #include "n8_pub_request.h"
140 /* local prototypes */
141 static void resultHandlerSSLTLSEncrypt(API_Request_t* req_p);
142 static void resultHandlerSSLTLSDecrypt(API_Request_t* req_p);
145 * Local structure used to pass data to the result handler. It is hooked to the
146 * API Request in order to be available in the callback.
148 typedef struct
150 N8_Buffer_t *computedMAC_p;
151 N8_SSLTLSPacket_t *resultPacket_p;
152 N8_Packet_t *packetObj_p;
153 N8_Boolean_t *verify_p;
154 int macLength;
155 int encryptedLength;
156 int copyData;
157 unsigned char nextIV[8];
158 } N8_SSL_Post_Decrypt_Data_t;
161 /* macro defines */
163 /* exported functions */
165 /*****************************************************************************
166 * N8_SSLTLSEncryptAuthenticate
167 *****************************************************************************/
168 /** @ingroup n8_ssltls
169 * @brief Encrypt/Authenticate an SSL or TLS message
171 * An entire SSL or TLS record is encrypted/authenticated.
173 * @param packetObj_p RW: Pointer to a packet object which was
174 * previously initialized for SSL or TLS
175 * @param packet_p RO: Pointer to packet
176 * @param result_p RW: Pointer to pre-allocated buffer where the
177 * results will be stored.
178 * @param request RW: Kernel request buffer used when mode =
179 * N8_PACKETMEMORY_REQUEST.
180 * @param event_p RW: Asynchronous event pointer.
182 * @par Externals
183 * None
185 * @return
186 * Error condition if raised.
188 * @par Errors
189 * None
191 * @par Assumptions
192 * None
193 *****************************************************************************/
194 N8_Status_t
195 N8_SSLTLSEncryptAuthenticateMemory(N8_Packet_t *packetObj_p,
196 const N8_SSLTLSPacket_t *packet_p,
197 N8_SSLTLSPacket_t *result_p,
198 N8_RequestHandle_t request,
199 N8_Event_t *event_p)
202 N8_Status_t ret = N8_STATUS_OK;
203 API_Request_t *req_p = NULL;
204 EA_CMD_BLOCK_t *next_cb_p = NULL;
205 uint16_t length;
206 short int encLen;
207 short int packetLen;
208 N8_Buffer_t *res_p = NULL;
209 uint32_t res_a;
210 N8_Buffer_t *input_p = NULL;
211 uint32_t input_a;
212 N8_Buffer_t *ctx_p = NULL;
213 uint32_t ctx_a = 0;
214 int nBytes;
215 unsigned int numCommands = 0;
216 unsigned int numCtxBytes = 0;
217 N8_MemoryHandle_t *request_p;
218 n8_ctxLoadFcn_t ctxLoadFcn;
219 n8_SSLTLSFcn_t encryptFcn;
223 /* verify the pointers passed in are not null */
224 CHECK_OBJECT(packetObj_p, ret);
225 CHECK_STRUCTURE(packetObj_p->structureID, N8_PACKET_STRUCT_ID, ret);
226 CHECK_OBJECT(packet_p, ret);
227 CHECK_OBJECT(result_p, ret);
229 request_p = (N8_MemoryHandle_t *) request;
231 /* Check that request_p & mode are consistent */
232 if (request_p == NULL)
234 if (packetObj_p->mode != N8_PACKETMEMORY_NONE)
236 /* No request_p means mode should be "none" */
237 ret = N8_INCONSISTENT;
238 break;
241 else if (packetObj_p->mode != N8_PACKETMEMORY_REQUEST)
243 /* They said they would give us a request and they didn't */
244 ret = N8_INCONSISTENT;
245 break;
249 * convert the length from network order to host order
251 length = SSLTLS_EXTRACT_LENGTH(packet_p);
252 /* check to see the data length is within range
253 * [0..N8_SSLTLS_MAX_DATA_SIZE_ENCRYPT]
255 if (length > N8_SSLTLS_MAX_DATA_SIZE_ENCRYPT)
257 ret = N8_INVALID_INPUT_SIZE;
258 break;
261 numCommands = packetObj_p->encCommands;
262 if (packetObj_p->contextLoadNeeded == N8_TRUE)
264 numCommands += packetObj_p->ctxLoadCmds;
265 numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX));
268 /* create a kernel memory structure for temporarily storing the results */
269 /* compute the lengths for the result packet */
270 encLen = N8_ComputeEncryptedLength(length,
271 packetObj_p->hashPacket.hashSize,
272 packetObj_p->packetCipher);
273 packetLen = encLen + SSLTLS_HEADER_LEN;
275 /* compute the total number of bytes in kernel space we need to allocate.
276 * note we round up to the next word boundary. */
277 /* Note that if the in packet is NULL, we don't check the out packet */
278 if (request_p == NULL)
280 nBytes = (NEXT_WORD_SIZE(length) + /* input */
281 NEXT_WORD_SIZE(encLen) + /* output */
282 numCtxBytes); /* size of context, if needed */
283 /* create an API request buffer */
284 ret = createEARequestBuffer(&req_p,
285 packetObj_p->unitID,
286 numCommands,
287 resultHandlerSSLTLSEncrypt,
288 nBytes);
289 CHECK_RETURN(ret);
290 /* User has not provided a request buffer */
291 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
292 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
294 input_p = res_p + NEXT_WORD_SIZE(length);
295 input_a = res_a + NEXT_WORD_SIZE(length);
297 ctx_p = input_p + NEXT_WORD_SIZE(encLen);
298 ctx_a = input_a + NEXT_WORD_SIZE(encLen);
300 else
302 /* The user has given us a request structure. We just need to
303 initialize it. */
304 req_p = (API_Request_t *) request_p->VirtualAddress;
305 initializeEARequestBuffer(req_p,
306 request_p,
307 packetObj_p->unitID,
308 numCommands,
309 resultHandlerSSLTLSEncrypt,
310 N8_TRUE);
312 /* User has provided a request packet, which must contain enough
313 space for the input and output packets. The user may
314 reuse the input pointer for the output. */
315 input_p = (N8_Buffer_t *)((unsigned long) packet_p + SSLTLS_DATA_OFFSET);
316 input_a = N8_VirtToPhys(input_p);
318 res_p = (N8_Buffer_t *)((unsigned long) result_p + SSLTLS_DATA_OFFSET);
319 res_a = N8_VirtToPhys(res_p);
320 /* If we are loading context memory, we load it at the last
321 N8_CTX_BYTES before the data section */
322 if (numCtxBytes > 0)
324 ctx_p = (N8_Buffer_t *)((unsigned long) req_p + sizeof(API_Request_t) + N8_COMMAND_BLOCK_BYTES);
325 ctx_a = N8_VirtToPhys(ctx_p);
329 next_cb_p = req_p->EA_CommandBlock_ptr;
331 /* generate the command blocks necessary to load the context, if required */
332 if (packetObj_p->contextLoadNeeded == N8_TRUE)
334 /* Generate the command blocks for the Context Load */
335 ctxLoadFcn = (n8_ctxLoadFcn_t)packetObj_p->ctxLoadFcn;
336 ret = ctxLoadFcn(req_p,
337 next_cb_p,
338 packetObj_p,
339 &packetObj_p->cipherInfo,
340 packetObj_p->packetHashAlgorithm,
341 ctx_p,
342 ctx_a,
343 &next_cb_p);
344 CHECK_RETURN(ret);
345 packetObj_p->contextLoadNeeded = N8_FALSE;
348 req_p->copyBackFrom_p = res_p;
349 req_p->postProcessingData_p = (void *) packetObj_p;
350 /* This sets up the offset for the start of the copy back of the IV */
351 req_p->postProcessBuffer[0] = encLen - N8_DES_KEY_LENGTH;
353 if (request_p == NULL)
355 memcpy(input_p, &packet_p[SSLTLS_DATA_OFFSET], length);
356 req_p->copyBackTo_p = &result_p[SSLTLS_DATA_OFFSET];
357 req_p->copyBackSize = encLen;
359 else
361 req_p->copyBackSize = 0;
364 /* Generate the command blocks for the Encrypt */
365 encryptFcn = (n8_SSLTLSFcn_t)packetObj_p->SSLTLScmdFcn;
366 ret = encryptFcn(next_cb_p,
367 packetObj_p,
368 packet_p,
369 input_a,
370 res_a,
371 packetObj_p->encOpCode);
372 CHECK_RETURN(ret);
374 /* set up the return packet. note that this can be done before the
375 * command is executed as it is only constant header information. */
376 memcpy(&result_p[SSLTLS_TYPE_OFFSET],
377 &packet_p[SSLTLS_TYPE_OFFSET],
378 sizeof(uint8_t) + sizeof(uint16_t));
379 SSLTLS_SET_LENGTH(result_p, encLen);
381 QUEUE_AND_CHECK(event_p, req_p, ret);
382 HANDLE_EVENT(event_p, req_p, ret);
383 } while (FALSE);
385 /* clean up if necessary. note that if there is no error condition, the
386 * request will be de-allocated in the result handler. */
387 if (ret != N8_STATUS_OK)
389 freeRequest(req_p);
391 return ret;
393 } /* N8_SSLEncryptAuthenticateMemory */
395 /*****************************************************************************
396 * N8_SSLTLSEncryptAuthenticate
397 *****************************************************************************/
398 /** @ingroup n8_ssltls
399 * @brief Encrypt/Authenticate an SSL or TLS message
401 * An entire SSL or TLS record is encrypted/authenticated. Note that this call
402 * is now supported as a front end to N8_SSLTLSEncryptAuthenticateMemory.
404 * @param packetObj_p RW: Pointer to a packet object which was
405 * previously initialized for SSL or TLS
406 * @param packet_p RO: Pointer to packet
407 * @param result_p RW: Pointer to pre-allocated buffer where the
408 * results will be stored.
409 * @param event_p RW: Asynchronous event pointer.
411 * @par Externals
412 * None
414 * @return
415 * Error condition if raised.
417 * @par Errors
418 * None
420 * @par Assumptions
421 * None
422 *****************************************************************************/
423 N8_Status_t N8_SSLTLSEncryptAuthenticate(N8_Packet_t *packetObj_p,
424 const N8_SSLTLSPacket_t *packet_p,
425 N8_SSLTLSPacket_t *result_p,
426 N8_Event_t *event_p)
428 N8_Status_t retCode;
429 N8_PacketMemoryMode_t saveMode;
433 CHECK_OBJECT(packetObj_p, retCode);
435 /* save the existing mode and set it */
436 saveMode = packetObj_p->mode;
437 packetObj_p->mode = N8_PACKETMEMORY_NONE;
439 retCode = N8_SSLTLSEncryptAuthenticateMemory(packetObj_p,
440 packet_p,
441 result_p,
442 NULL,
443 event_p);
444 /* reset the mode */
445 packetObj_p->mode = saveMode;
447 } while (FALSE);
449 return retCode;
452 /*****************************************************************************
453 * N8_SSLTLSDecryptVerifyMemory
454 *****************************************************************************/
455 /** @ingroup n8_ssltls
456 * @brief Decrypt and verify an entire SSL or TLS message.
458 * Decrypt an verify a SSL or TLS message. If the verification fails, it will
459 * be noted in the return value.
461 * @param packetObj_p RW: Pre-initialized packet object.
462 * @param packet_p RO: A complete, encrypted SSL or TLS packet
463 * including the header.
464 * @param computedMAC_p RW: Pointer to result space for the MAC
465 * computation output.
466 * @param verify_p: WO: Pointer to a verify flag. If the MAC's
467 * match, the verify flag will be set to N8_TRUE.
468 * @param result_p RW: Pointer to result space for the decrypted
469 * result.
470 * @param request RW: Kernel request buffer used when mode =
471 * N8_PACKETMEMORY_REQUEST.
472 * @param event_p RW: Asynchronous event pointer.
474 * @par Externals
475 * None
477 * @return
478 * Error condition if raised.
480 * @par Errors
481 * N8_MALLOC_FAILED<br>
482 * N8_INVALID_INPUT_SIZE - the value in the packet header is too large or too
483 * small.<br>
484 * N8_INCONSISTENT - the version number in the packet header does not
485 * match the designation in the packet object.<br>
486 * N8_INVALID_OBJECT - packet object is not a valid object initialized
487 * for SSL or TLS<br>
488 * N8_INVALID_VALUE - the value of the type field in the packet header
489 * is not one of the legal values for SSL or TLS.<br>
491 * @par Assumptions
492 * The result_p and computedMAC_p pointers refer to pre-allocated space of
493 * sufficient size. The calling program retains responsibility for freeing this
494 * memory.
495 *****************************************************************************/
496 N8_Status_t
497 N8_SSLTLSDecryptVerifyMemory(N8_Packet_t *packetObj_p,
498 const N8_SSLTLSPacket_t *packet_p,
499 N8_Buffer_t *computedMAC_p,
500 N8_Boolean_t *verify_p,
501 N8_SSLTLSPacket_t *result_p,
502 N8_RequestHandle_t request,
503 N8_Event_t *event_p)
506 N8_Status_t ret = N8_STATUS_OK;
507 API_Request_t *req_p = NULL;
508 EA_CMD_BLOCK_t *next_cb_p = NULL;
509 N8_SSL_Post_Decrypt_Data_t *postData_p = NULL;
510 uint16_t length;
511 short int encLen;
512 int nBytes;
513 N8_Buffer_t *res_p = NULL;
514 uint32_t res_a;
515 N8_Buffer_t *input_p = NULL;
516 uint32_t input_a;
517 N8_Buffer_t *ctx_p = NULL;
518 uint32_t ctx_a = 0;
519 unsigned int numCommands = 0;
520 unsigned int numCtxBytes = 0;
521 N8_MemoryHandle_t *request_p;
522 n8_ctxLoadFcn_t ctxLoadFcn;
523 n8_SSLTLSFcn_t decryptFcn;
526 /* ensure none of the pointers we're given are null */
527 CHECK_OBJECT(packetObj_p, ret);
528 CHECK_STRUCTURE(packetObj_p->structureID, N8_PACKET_STRUCT_ID, ret);
529 CHECK_OBJECT(packet_p, ret);
530 #ifdef N8_MAC_COPYBACK
531 CHECK_OBJECT(computedMAC_p, ret);
532 #endif
533 CHECK_OBJECT(result_p, ret);
535 request_p = (N8_MemoryHandle_t *) request;
537 /* Check that request_p & mode are consistent */
538 if (request_p == NULL)
540 if (packetObj_p->mode != N8_PACKETMEMORY_NONE)
542 /* No request_p means mode should be "none" */
543 ret = N8_INCONSISTENT;
544 break;
547 else if (packetObj_p->mode != N8_PACKETMEMORY_REQUEST)
549 /* They said they would give us a request and they didn't */
550 ret = N8_INCONSISTENT;
551 break;
555 * convert the length from network order to host order
557 length = ntohs(*((uint16_t *) &packet_p[SSLTLS_LENGTH_OFFSET]));
559 /* verify the length is not greater than the max */
560 if (length > N8_SSLTLS_MAX_DATA_SIZE_DECRYPT)
562 ret = N8_INVALID_INPUT_SIZE;
563 break;
566 numCommands = packetObj_p->decCommands;
567 if (packetObj_p->contextLoadNeeded == N8_TRUE)
569 numCommands += packetObj_p->ctxLoadCmds;
570 numCtxBytes = NEXT_WORD_SIZE(sizeof(EA_ARC4_CTX));
573 encLen = N8_ComputeEncryptedLength(length,
574 packetObj_p->hashPacket.hashSize,
575 packetObj_p->packetCipher);
577 /* kernel space is needed for the data portion of the incoming packet plus
578 * the hash and padding. the exact amount is needed for the return
579 * packet. */
580 /* Note that if the in packet is NULL, we don't check the out packet */
581 if (request_p == NULL)
583 nBytes = NEXT_WORD_SIZE(length) * 2 + numCtxBytes;
584 /* create an API request buffer */
585 ret = createEARequestBuffer(&req_p,
586 packetObj_p->unitID,
587 numCommands,
588 resultHandlerSSLTLSDecrypt,
589 nBytes);
590 CHECK_RETURN(ret);
591 /* User has not provided any buffers */
592 res_p = (N8_Buffer_t *) ((int)req_p + req_p->dataoffset);
593 res_a = req_p->qr.physicalAddress + req_p->dataoffset;
595 input_p = res_p + NEXT_WORD_SIZE(length);
596 input_a = res_a + NEXT_WORD_SIZE(length);
598 ctx_p = input_p + NEXT_WORD_SIZE(encLen);
599 ctx_a = input_a + NEXT_WORD_SIZE(encLen);
601 else
603 /* User has provided a request packet, which must contain enough
604 space for the input and output packets. The user may
605 reuse the input pointer for the output. */
607 /* The user has given us a request structure. We just need to
608 initialize it. */
609 req_p = (API_Request_t *) request_p->VirtualAddress;
610 initializeEARequestBuffer(req_p,
611 request_p,
612 packetObj_p->unitID,
613 numCommands,
614 resultHandlerSSLTLSDecrypt,
615 N8_TRUE);
617 /* Initialize input_p and input_a to the beginning of
618 data area in the request */
619 input_p = (N8_Buffer_t *)((unsigned long) packet_p + SSLTLS_DATA_OFFSET);
620 input_a = N8_VirtToPhys(input_p);
623 res_p = result_p + SSLTLS_DATA_OFFSET;
624 res_a = N8_VirtToPhys(res_p);
626 /* If we are loading context memory, we load it at the last
627 N8_CTX_BYTES before the data section */
628 if (numCtxBytes > 0)
630 ctx_p = (N8_Buffer_t *)((unsigned long) req_p + sizeof(API_Request_t) + N8_COMMAND_BLOCK_BYTES);
631 ctx_a = N8_VirtToPhys(ctx_p);
635 next_cb_p = req_p->EA_CommandBlock_ptr;
637 /* generate the command blocks necessary to load the context, if required */
638 if (packetObj_p->contextLoadNeeded == N8_TRUE)
640 /* Generate the command blocks for the Context Load */
641 ctxLoadFcn = (n8_ctxLoadFcn_t)packetObj_p->ctxLoadFcn;
642 ret = ctxLoadFcn(req_p,
643 req_p->EA_CommandBlock_ptr,
644 packetObj_p,
645 &packetObj_p->cipherInfo,
646 packetObj_p->packetHashAlgorithm,
647 ctx_p,
648 ctx_a,
649 &next_cb_p);
650 CHECK_RETURN(ret);
651 packetObj_p->contextLoadNeeded = N8_FALSE;
654 /* copy the data portion of the incoming packet into the input kernel
655 * buffer */
656 if (request_p == NULL)
658 memcpy(input_p, &packet_p[SSLTLS_DATA_OFFSET], length);
661 /* use the post processing structure in the API Request */
662 postData_p = (N8_SSL_Post_Decrypt_Data_t *)&req_p->postProcessBuffer;
664 /* now check the length */
665 if (length < packetObj_p->minLength)
667 ret = N8_INVALID_INPUT_SIZE;
668 break;
671 /* if des, ensure the length is a multiple of N8_DES_BLOCK_MULTIPLE */
672 if ((packetObj_p->packetCipher == N8_CIPHER_DES) &&
673 ((length % N8_DES_BLOCK_MULTIPLE) != 0))
675 ret = N8_INVALID_INPUT_SIZE;
676 break;
679 /* set up the copy back for the result packet. we only copy back the data
680 * portion which we get from the kernel buffer. */
681 req_p->copyBackTo_p = &result_p[SSLTLS_DATA_OFFSET];
682 req_p->copyBackFrom_p = res_p;
683 /* the length the decrypted data is not known until after the operation is
684 * run. we will calculate it in the resultHandler. set the copyBackSize
685 * to zero as a safe thing to do.*/
686 req_p->copyBackSize = 0;
688 if (packetObj_p->contextHandle.inUse == N8_FALSE)
690 /* This sets up the offset for the start of the copy back of the IV.
691 This case can only occur if the cipher is DES, not ARC4 */
692 memcpy(&postData_p->nextIV,
693 &(packet_p[5 - N8_DES_KEY_LENGTH + length]),
694 N8_DES_KEY_LENGTH);
697 /* set up the post processing data */
698 postData_p->macLength = packetObj_p->macLength;
699 postData_p->computedMAC_p = computedMAC_p;
700 postData_p->packetObj_p = packetObj_p;
701 postData_p->verify_p = verify_p;
702 postData_p->encryptedLength = length;
703 if (request_p == NULL)
705 postData_p->copyData = N8_TRUE;
707 else
709 postData_p->copyData = N8_FALSE;
711 postData_p->resultPacket_p = result_p;
713 /* tell the Queue Manager to copy back the command block results */
714 req_p->copyBackCommandBlock = N8_TRUE;
715 req_p->postProcessingData_p = (void *) postData_p;
717 /* Generate the command blocks for the Decrypt */
718 decryptFcn = (n8_SSLTLSFcn_t)packetObj_p->SSLTLScmdFcn;
719 ret = decryptFcn(next_cb_p,
720 packetObj_p,
721 packet_p,
722 input_a,
723 res_a,
724 packetObj_p->decOpCode);
725 CHECK_RETURN(ret);
727 /* set up the return packet
728 * again, recall we cannot set the length in the result packet now and
729 * will have to do it in the result handler. */
730 memcpy(&result_p[SSLTLS_TYPE_OFFSET],
731 &packet_p[SSLTLS_TYPE_OFFSET],
732 sizeof(uint8_t) + sizeof(uint16_t));
734 QUEUE_AND_CHECK(event_p, req_p, ret);
735 HANDLE_EVENT(event_p, req_p, ret);
736 } while (FALSE);
738 /* clean up if necessary. note that if there is no error condition, the post
739 * data and request will be de-allocated in the result handler. */
740 if (ret != N8_STATUS_OK)
742 freeRequest(req_p);
744 return ret;
745 } /* N8_SSLTLSDecryptVerify */
747 /*****************************************************************************
748 * N8_SSLTLSDecryptVerify
749 *****************************************************************************/
750 /** @ingroup n8_ssltls
751 * @brief Decrypt and verify an entire SSL or TLS message.
753 * Decrypt an verify a SSL or TLS message. If the verification fails, it will
754 * be noted in the return value. Note that this call is now supported as a front
755 * end to N8_SSLTLSDecryptVerifyMemory.
757 * @param packetObj_p RW: Pre-initialized packet object.
758 * @param packet_p RO: A complete, encrypted SSL or TLS packet
759 * including the header.
760 * @param computedMAC_p RW: Pointer to result space for the MAC
761 * computation output.
762 * @param verify_p: WO: Pointer to a verify flag. If the MAC's
763 * match, the verify flag will be set to N8_TRUE.
764 * @param result_p RW: Pointer to result space for the decrypted
765 * result.
766 * @param request RW: Kernel request buffer used when mode =
767 * N8_PACKETMEMORY_REQUEST.
768 * @param event_p RW: Asynchronous event pointer.
770 * @par Externals
771 * None
773 * @return
774 * Error condition if raised.
776 * @par Errors
777 * N8_MALLOC_FAILED<br>
778 * N8_INVALID_INPUT_SIZE - the value in the packet header is too large or too
779 * small.<br>
780 * N8_INCONSISTENT - the version number in the packet header does not
781 * match the designation in the packet object.<br>
782 * N8_INVALID_OBJECT - packet object is not a valid object initialized
783 * for SSL or TLS<br>
784 * N8_INVALID_VALUE - the value of the type field in the packet header
785 * is not one of the legal values for SSL or TLS.<br>
787 * @par Assumptions
788 * The result_p and computedMAC_p pointers refer to pre-allocated space of
789 * sufficient size. The calling program retains responsibility for freeing this
790 * memory.
791 *****************************************************************************/
792 N8_Status_t
793 N8_SSLTLSDecryptVerify(N8_Packet_t *packetObj_p,
794 const N8_SSLTLSPacket_t *packet_p,
795 N8_Buffer_t *computedMAC_p,
796 N8_Boolean_t *verify_p,
797 N8_SSLTLSPacket_t *result_p,
798 N8_Event_t *event_p)
800 N8_Status_t retCode;
801 N8_PacketMemoryMode_t saveMode;
805 CHECK_OBJECT(packetObj_p, retCode);
806 /* save the existing mode and set it */
807 saveMode = packetObj_p->mode;
808 packetObj_p->mode = N8_PACKETMEMORY_NONE;
810 retCode = N8_SSLTLSDecryptVerifyMemory(packetObj_p,
811 packet_p,
812 computedMAC_p,
813 verify_p,
814 result_p,
815 NULL,
816 event_p);
817 /* reset the mode */
818 packetObj_p->mode = saveMode;
820 } while (FALSE);
822 return retCode;
824 /*****************************************************************************
825 * N8_GetHashLen
826 *****************************************************************************/
827 /** @ingroup n8_ssltls
828 * @brief Compute the length of a hash.
830 * For a specified type of hash, return the length of the generated hash.
832 * @param hash RO: Hash to be used
834 * @par Externals
835 * None
837 * @return
838 * Length of the hash. Returns -1 if the hash is not supported.
840 * @par Errors
841 * See above.
843 * @par Assumptions
844 * None
845 *****************************************************************************/
846 short int N8_GetHashLength(N8_HashAlgorithm_t hash)
848 switch (hash)
850 case N8_MD5:
851 case N8_HMAC_MD5:
852 return MD5_HASH_RESULT_LENGTH;
853 case N8_SHA1:
854 case N8_HMAC_SHA1:
855 return SHA1_HASH_RESULT_LENGTH;
856 case N8_HMAC_MD5_96:
857 case N8_HMAC_SHA1_96:
858 return HMAC_96_HASH_RESULT_LENGTH;
859 case N8_HASH_NONE:
860 return 0;
861 default:
862 return -1;
864 } /* N8_GetHashLength */
865 /*****************************************************************************
866 * N8_ComputeEncryptedLength
867 *****************************************************************************/
868 /** @ingroup n8_ssltls
869 * @brief For a given message size, hash length and cipher, compute the
870 * length of the encrypted message including padding.
872 * @param size RO: size of the message
873 * @param hashLen RO: length of the hash
874 * @param cipher RO: cipher to use
876 * @par Externals
877 * None
879 * @return
880 * Length of the encrypted message (size + hash length + padding).
881 * Returns -1 if the cipher is not recognized.
882 * @par Errors
883 * None
885 * @par Assumptions
886 * None
887 *****************************************************************************/
888 short int N8_ComputeEncryptedLength(int size, int hashLen, N8_Cipher_t cipher)
890 int el = -1;
891 switch (cipher)
893 case N8_CIPHER_DES:
894 el = (size + hashLen + 8) & ~0x07;
895 break;
896 case N8_CIPHER_ARC4:
897 el = size + hashLen;
898 break;
899 default:
900 break;
902 return el;
903 } /* N8_ComputeEncryptedLength */
905 /* local functions */
906 /**********************************************************************
907 * resultHandlerSSLTLSEncrypt
909 * Description:
910 * This function is called by the Public Key Request Queue handler when
911 * either the request is completed successfully and all the commands
912 * copied back to the command blocks allocated by the API, or when
913 * the Simon has encountered an error with one of the commands such
914 * that the Simon has locked up.
916 * Note this function will have to be NON-BLOCKING or it will lock up the
917 * queue handler!
920 **********************************************************************/
921 static void resultHandlerSSLTLSEncrypt(API_Request_t* req_p)
923 N8_Packet_t *packetObj_p = NULL;
924 char *title = "resultHandlerSSLTLSEncrypt";
926 /* get the packet object pointer from the request */
927 packetObj_p = (N8_Packet_t *) req_p->postProcessingData_p;
928 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
930 DBG(("%s call-back with success\n", title));
931 /* copy the results back */
932 if (req_p->copyBackFrom_p != NULL &&
933 req_p->copyBackTo_p != NULL &&
934 req_p->copyBackSize != 0)
936 memcpy(req_p->copyBackTo_p,
937 req_p->copyBackFrom_p,
938 req_p->copyBackSize);
941 /* Reload the IV in the cipher info if needed */
942 if (packetObj_p->contextHandle.inUse == N8_FALSE)
944 int IVOffset = req_p->postProcessBuffer[0];
945 memcpy(&(packetObj_p->cipherInfo.IV),
946 &(req_p->copyBackFrom_p[IVOffset]),
947 N8_DES_KEY_LENGTH);
950 else
952 /* an error has occured. roll back the sequence number if we are not
953 * using context memory. */
955 /* if we are not using the context */
956 if (packetObj_p->contextHandle.inUse == N8_FALSE)
958 /* decrement the sequence number to return it to its previous value */
959 if (packetObj_p->cipherInfo.sequence_number[1] == 0)
961 /* decrement the sequence number ms */
962 packetObj_p->cipherInfo.sequence_number[0]--;
964 /* decrement the sequence number ls */
965 packetObj_p->cipherInfo.sequence_number[1]--;
967 RESULT_HANDLER_WARNING(title, req_p);
969 /* do not free the postProcessingData_p as it is a the packetObject
970 * controlled by the user */
972 /* do not free the request in the result handler. it is done by the event
973 * processor. */
975 } /* resultHandlerSSLTLSEncrypt */
978 /**********************************************************************
979 * resultHandlerSSLTLSDecrypt
981 * Description:
982 * This function is called by the Public Key Request Queue handler when
983 * either the request is completed successfully and all the commands
984 * copied back to the command blocks allocated by the API, or when
985 * the Simon has encountered an error with one of the commands such
986 * that the Simon has locked up.
988 * Note this function will have to be NON-BLOCKING or it will lock up the
989 * queue handler!
992 **********************************************************************/
993 static void resultHandlerSSLTLSDecrypt(API_Request_t* req_p)
995 char *title = "resultHandlerSSLTLSDecrypt";
996 N8_Packet_t *packetObj_p = NULL;
997 N8_SSL_Post_Decrypt_Data_t *postData_p = NULL;
998 N8_SSLTLSPacket_t *resultPacket_p;
999 EA_SSL30_DECRYPT_RESULT_CMD_BLOCK_t *cmd_p;
1000 int i;
1001 short int originalLength;
1002 N8_Buffer_t *buf_p;
1003 char padLength=0;
1004 char *data_p;
1006 postData_p =
1007 (N8_SSL_Post_Decrypt_Data_t *) req_p->postProcessingData_p;
1008 packetObj_p = postData_p->packetObj_p;
1009 if (req_p->qr.requestError == N8_QUEUE_REQUEST_OK)
1011 DBG(("%s call-back with success\n", title));
1012 /* get the packet object pointer from the request */
1013 resultPacket_p = postData_p->resultPacket_p;
1014 /* copy back the computed mac */
1015 /* isolate the command block */
1016 cmd_p = (EA_SSL30_DECRYPT_RESULT_CMD_BLOCK_t *)
1017 req_p->EA_CommandBlock_ptr;
1019 /* the copy back should come from the last command block */
1020 cmd_p = &cmd_p[req_p->numNewCmds - 1];
1022 /* If the computedMAC_p parameter from N8_EA_DV is NULL */
1023 /* then don't copy back the MAC value as the user doesn't want it */
1024 if (postData_p->computedMAC_p != NULL ) {
1025 buf_p = postData_p->computedMAC_p;
1026 for (i = 0; i < postData_p->macLength / sizeof(uint32_t); i++)
1028 uint32_to_BE(cmd_p->mac[i], &buf_p[i*4]);
1031 /* check the mac mismatch flag and set the verify value */
1032 *(postData_p->verify_p) =
1033 ((cmd_p->mismatch & EA_Result_MAC_Mismatch) == 0) ?
1034 N8_TRUE : N8_FALSE;
1036 /* set the length in the return packet. */
1037 /* data_p = (char *) &resultPacket_p[SSLTLS_DATA_OFFSET]; */
1038 data_p = (char *) req_p->copyBackFrom_p;
1039 if (packetObj_p->packetCipher != N8_CIPHER_ARC4)
1041 padLength = data_p[postData_p->encryptedLength - 1] + 1;
1043 originalLength = postData_p->encryptedLength - postData_p->macLength -
1044 padLength;
1045 /* postData_p->returnLength = htons(originalLength); */
1046 SSLTLS_SET_LENGTH(resultPacket_p, originalLength);
1047 /* copy the results back */
1048 /* memcpy(req_p->copyBackTo_p, req_p->copyBackFrom_p,
1049 * req_p->copyBackSize); */
1050 if (postData_p->copyData == N8_TRUE)
1052 memcpy(req_p->copyBackTo_p,
1053 req_p->copyBackFrom_p,
1054 postData_p->encryptedLength);
1057 /* Reload the IV in the cipher info if needed */
1058 if (packetObj_p->contextHandle.inUse == N8_FALSE)
1060 memcpy(&(packetObj_p->cipherInfo.IV),
1061 &(postData_p->nextIV),
1062 N8_DES_KEY_LENGTH);
1065 else
1067 /* an error has occured. roll back the sequence number if we are not
1068 * using context memory. */
1070 /* if we are not using the context */
1071 if (packetObj_p->contextHandle.inUse == N8_FALSE)
1073 /* decrement the sequence number to return it to its previous value */
1074 if (packetObj_p->cipherInfo.sequence_number[1] == 0)
1076 /* decrement the sequence number ms */
1077 packetObj_p->cipherInfo.sequence_number[0]--;
1079 /* decrement the sequence number ls */
1080 packetObj_p->cipherInfo.sequence_number[1]--;
1082 RESULT_HANDLER_WARNING(title, req_p);
1085 /* free the post processing data holder */
1086 /*N8_UFREE(req_p->postProcessingData_p);*/
1087 /* do not free the request in the result handler. it is done by the event
1088 * processor. */
1089 } /* resultHandlerSSLTLSDecrypt */