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_ssltls.c,v 1.1 2008/10/30 12:02:15 darran Exp $";
36 /*****************************************************************************/
38 * @brief SSL 3.0 Packet Level Interfaces
40 * Implementation of functions for SSL 3.0 Packet Level Interfaces. Functions
42 * N8_SSLEncryptAuthenticate
45 *****************************************************************************/
47 /*****************************************************************************
50 * 08/18/03 brr Combine Encrypt/Decrypt command block generators for SSL,
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
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_*
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
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
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
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
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"
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.
150 N8_Buffer_t
*computedMAC_p
;
151 N8_SSLTLSPacket_t
*resultPacket_p
;
152 N8_Packet_t
*packetObj_p
;
153 N8_Boolean_t
*verify_p
;
157 unsigned char nextIV
[8];
158 } N8_SSL_Post_Decrypt_Data_t
;
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.
186 * Error condition if raised.
193 *****************************************************************************/
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
,
202 N8_Status_t ret
= N8_STATUS_OK
;
203 API_Request_t
*req_p
= NULL
;
204 EA_CMD_BLOCK_t
*next_cb_p
= NULL
;
208 N8_Buffer_t
*res_p
= NULL
;
210 N8_Buffer_t
*input_p
= NULL
;
212 N8_Buffer_t
*ctx_p
= NULL
;
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
;
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
;
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
;
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
,
287 resultHandlerSSLTLSEncrypt
,
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
);
302 /* The user has given us a request structure. We just need to
304 req_p
= (API_Request_t
*) request_p
->VirtualAddress
;
305 initializeEARequestBuffer(req_p
,
309 resultHandlerSSLTLSEncrypt
,
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 */
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
,
339 &packetObj_p
->cipherInfo
,
340 packetObj_p
->packetHashAlgorithm
,
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
;
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
,
371 packetObj_p
->encOpCode
);
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
);
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
)
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.
415 * Error condition if raised.
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
,
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
,
445 packetObj_p
->mode
= saveMode
;
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
470 * @param request RW: Kernel request buffer used when mode =
471 * N8_PACKETMEMORY_REQUEST.
472 * @param event_p RW: Asynchronous event pointer.
478 * Error condition if raised.
481 * N8_MALLOC_FAILED<br>
482 * N8_INVALID_INPUT_SIZE - the value in the packet header is too large or too
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
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>
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
495 *****************************************************************************/
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
,
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
;
513 N8_Buffer_t
*res_p
= NULL
;
515 N8_Buffer_t
*input_p
= NULL
;
517 N8_Buffer_t
*ctx_p
= NULL
;
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
);
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
;
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
;
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
;
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
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
,
588 resultHandlerSSLTLSDecrypt
,
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
);
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
609 req_p
= (API_Request_t
*) request_p
->VirtualAddress
;
610 initializeEARequestBuffer(req_p
,
614 resultHandlerSSLTLSDecrypt
,
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 */
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
,
645 &packetObj_p
->cipherInfo
,
646 packetObj_p
->packetHashAlgorithm
,
651 packetObj_p
->contextLoadNeeded
= N8_FALSE
;
654 /* copy the data portion of the incoming packet into the input kernel
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
;
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
;
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
]),
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
;
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
,
724 packetObj_p
->decOpCode
);
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
);
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
)
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
766 * @param request RW: Kernel request buffer used when mode =
767 * N8_PACKETMEMORY_REQUEST.
768 * @param event_p RW: Asynchronous event pointer.
774 * Error condition if raised.
777 * N8_MALLOC_FAILED<br>
778 * N8_INVALID_INPUT_SIZE - the value in the packet header is too large or too
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
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>
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
791 *****************************************************************************/
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
,
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
,
818 packetObj_p
->mode
= saveMode
;
824 /*****************************************************************************
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
838 * Length of the hash. Returns -1 if the hash is not supported.
845 *****************************************************************************/
846 short int N8_GetHashLength(N8_HashAlgorithm_t hash
)
852 return MD5_HASH_RESULT_LENGTH
;
855 return SHA1_HASH_RESULT_LENGTH
;
857 case N8_HMAC_SHA1_96
:
858 return HMAC_96_HASH_RESULT_LENGTH
;
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
880 * Length of the encrypted message (size + hash length + padding).
881 * Returns -1 if the cipher is not recognized.
887 *****************************************************************************/
888 short int N8_ComputeEncryptedLength(int size
, int hashLen
, N8_Cipher_t cipher
)
894 el
= (size
+ hashLen
+ 8) & ~0x07;
903 } /* N8_ComputeEncryptedLength */
905 /* local functions */
906 /**********************************************************************
907 * resultHandlerSSLTLSEncrypt
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
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
]),
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
975 } /* resultHandlerSSLTLSEncrypt */
978 /**********************************************************************
979 * resultHandlerSSLTLSDecrypt
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
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
;
1001 short int originalLength
;
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) ?
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
-
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
),
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
1089 } /* resultHandlerSSLTLSDecrypt */