📄 ipsec_inbound_sa_spec.c
字号:
/* ipsec_inbound_sa_spec.c - WindNet IPsec and IKE - IPsec SA spec code *//* * Copyright (c) 2000-2006 Wind River Systems, Inc. * * The right to copy, distribute, modify or otherwise make use * of this software may be licensed only pursuant to the terms * of an applicable Wind River license agreement. *//*modification history--------------------03l,13jan06,djp removed rwos dependencies03k,08nov05,rlm Removed references to rw_packet routines.03j,10aug05,rlm Mods for single-pass encryption/HMAC with hardware acceleration.03i,13apr05,djp Fixed include paths03h,04Aug03,rks(teamf1) changes in inbound_ah_sa_spec_process. Freeing ipsec_ah_message in error cases.03g,12jun03,rparkhil added support for STACK_NAME03f,24Apr03,sam(teamf1) renamed ipsec_ipv6_extns_find_transport_protocol to ipsecIpv6ExtnsTransportProtocolFind03e,18Mar03,rks(teamf1) removed wncrypto crypto_if.h.03b,17Dec02,mhb(teamf1) Fixed compilation warnings03a,20Sep02,rks(teamf1) modification for IPv602b,27mar02,rpt changed "AH/ESP inbound process" function definitions to integrate with enhanced crypto interface "crypto_if.h"02a,19mar02,rpt changed func declarations to use IP_VI_MESSAGE instead of IP_MESSAGE. 01a,19mar02,rpt extracted from WindNet IPSec 1.1, added modification history*//******************************************************************************/#include <vxWorks.h>#include <stdlib.h>#include <string.h>#include <netinet/in.h>#include "../common/wrSecCommon.h"#include "../sadb/sadb_if.h"#include "../crypto/ipsecDOItoCCI.h"#include "../crypto/cipher.h"#ifdef IPSEC_VERBOSE_PACKET_DEBUGGING#include "../ike/ike_print_routines.h"#endif#include "ipsec_if.h"#include "packetBuf.h"#include "ipsec_print_routines.h"#include "ipsec_ah_message.h"#include "ipsec_esp_message.h"#include "ipsec_tunnel_utilities.h"#if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6)#include "ipsec_ipv6_utilities.h"#endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) *//* forward declarations */LOCAL BOOL inbound_ipsec_sa_spec_check_if_sequence_number_is_valid ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec, UINT sequence_number, IPSEC_AUTH_ALGORITHM_ID authentication_type );LOCAL void inbound_ipsec_sa_spec_update_receive_window ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec, UINT sequence_number );LOCAL BOOL inbound_ipsec_sa_spec_is_anti_replay_enabled ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec );/******************************************************************************/LOCAL BOOL inbound_ipsec_sa_spec_check_if_sequence_number_is_valid ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec, UINT sequence_number, IPSEC_AUTH_ALGORITHM_ID authentication_type ) { UINT difference; UINT bit_position; if (sequence_number == 0) { return (FALSE); } else if ((authentication_type != AUTH_ALGORITHM_RESERVED) && (inbound_ipsec_sa_spec_is_anti_replay_enabled ((INBOUND_IPSEC_SA_SPEC *)sptr_inbound_ipsec_sa_spec) == TRUE)) { if (sequence_number > sptr_inbound_ipsec_sa_spec->last_sequence_number) { return (TRUE); } else { difference = sptr_inbound_ipsec_sa_spec->last_sequence_number - sequence_number; if (difference >= sptr_inbound_ipsec_sa_spec->anti_replay_window_size) { return (FALSE); } bit_position = 1 << difference; if (sptr_inbound_ipsec_sa_spec->replay_bit_map & bit_position) { return (FALSE); } return (TRUE); } } else { return (TRUE); } }/******************************************************************************/LOCAL void inbound_ipsec_sa_spec_update_receive_window ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec, UINT sequence_number ) { UINT difference; UINT bit_position; if (sequence_number > sptr_inbound_ipsec_sa_spec->last_sequence_number) { difference = sequence_number - sptr_inbound_ipsec_sa_spec->last_sequence_number; if (difference < sptr_inbound_ipsec_sa_spec->anti_replay_window_size) { sptr_inbound_ipsec_sa_spec->replay_bit_map <<= difference; sptr_inbound_ipsec_sa_spec->replay_bit_map |= 1; } else { sptr_inbound_ipsec_sa_spec->replay_bit_map = 1; } sptr_inbound_ipsec_sa_spec->last_sequence_number = sequence_number; } else { difference = sptr_inbound_ipsec_sa_spec->last_sequence_number - sequence_number; bit_position = 1 << difference; sptr_inbound_ipsec_sa_spec->replay_bit_map |= bit_position; } }/******************************************************************************/LOCAL BOOL inbound_ipsec_sa_spec_is_anti_replay_enabled ( INBOUND_IPSEC_SA_SPEC *sptr_inbound_ipsec_sa_spec ) { return (sptr_inbound_ipsec_sa_spec->anti_replay_enabled); }/******************************************************************************/SA_SPEC_RET_TYPES inbound_ah_sa_spec_process ( SA_SPEC *sptr_sa_spec, IP_VI_MESSAGE *p_ip_message, SA_BUNDLE *sptr_bundle ) { INBOUND_AH_SA_SPEC *sptr_ib_ah_sa_spec; IPSEC_AH_MESSAGE ipsec_ah_message; BOOL return_value = FALSE; IP_VERSION_NUMBER ip_version; PARAMETER_NOT_USED (sptr_bundle); sptr_ib_ah_sa_spec = (INBOUND_AH_SA_SPEC *)sptr_sa_spec; return_value = ipsec_ah_message_construct (&ipsec_ah_message, sptr_ib_ah_sa_spec->authentication_type); if (return_value == FALSE) { return (SA_SPEC_FAIL); } if (ipsec_ah_message_deserialize (&ipsec_ah_message, p_ip_message->pPayload) == FALSE) { return_value = SA_SPEC_FAIL; goto inbound_ah_sa_spec_process_error; } if (ipsec_ah_message.spi != sptr_ib_ah_sa_spec->parent.spi) { return_value = SA_SPEC_FAIL; goto inbound_ah_sa_spec_process_error; } if (inbound_ipsec_sa_spec_check_if_sequence_number_is_valid ( (INBOUND_IPSEC_SA_SPEC *)sptr_ib_ah_sa_spec, ipsec_ah_message.sequence_number, sptr_ib_ah_sa_spec->authentication_type) == FALSE) { return_value = AH_SEQUENCE_ERROR; goto inbound_ah_sa_spec_process_error; } /* Get the context handle*/ if (sptr_ib_ah_sa_spec->context == 0) { ipsec_printf (IPSEC_WARNING_PRINTF, "IPsec: Invalid context handle in SA spec\n"); return_value = SA_SPEC_FAIL; goto inbound_ah_sa_spec_process_error; } #ifdef IPSEC_VERBOSE_PACKET_DEBUGGING ike_debug_printf_bytes ( IKE_ERROR_PRINTF, "<ah_inbound_sa_spec_process: payload before authentication>\n", packetBufDataGet(p_ip_message->pPayload), packetBufDataSizeGet(p_ip_message->pPayload)); #endif if (ipsec_ah_message_verify (&ipsec_ah_message, p_ip_message, sptr_ib_ah_sa_spec->context) == FALSE) { ipsec_printf (IPSEC_ERROR_PRINTF, "IPsec: Failed Authentication !!\n"); return_value = AH_AUTHENTICATION_ERROR; goto inbound_ah_sa_spec_process_error; } if ((sptr_ib_ah_sa_spec->authentication_type != AUTH_ALGORITHM_RESERVED) && (inbound_ipsec_sa_spec_is_anti_replay_enabled ((INBOUND_IPSEC_SA_SPEC *)sptr_ib_ah_sa_spec) == TRUE)) { inbound_ipsec_sa_spec_update_receive_window ( (INBOUND_IPSEC_SA_SPEC *)sptr_ib_ah_sa_spec, ipsec_ah_message.sequence_number); } /* update IP message */ ip_version = p_ip_message->version; if (ip_version == IP_V4) { ((IP_V4_MESSAGE *)p_ip_message)->transport_protocol = ipsec_ah_message.next_header; } #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) else if (ip_version == IP_V6) { #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) UCHAR *bptr_data; #endif ((IP_V6_MESSAGE *)p_ip_message)->next_header = ipsec_ah_message.next_header; ((IP_V6_MESSAGE *)p_ip_message)->transport_protocol = ipsec_ah_message.next_header; #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) bptr_data = packetBufDataGet(p_ip_message->pPayload); ((IP_V6_MESSAGE *)p_ip_message)->transport_protocol = ipsecIpv6ExtnsTransportProtocolFind (ipsec_ah_message.next_header, bptr_data); #endif } #endif /* STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) */ else { ipsec_printf (IPSEC_WARNING_PRINTF, "IPsec: IP Message: INVALID_VERSION\n"); } return_value = SA_SPEC_SUCCESS; inbound_ah_sa_spec_process_error: ipsec_ah_message_destruct (&ipsec_ah_message); return (return_value); } /* end inbound_ah_sa_spec_process() *//******************************************************************************/SA_SPEC_RET_TYPES inbound_esp_sa_spec_process ( SA_SPEC *sptr_sa_spec, IP_VI_MESSAGE *p_ip_message, SA_BUNDLE *sptr_bundle ) { INBOUND_ESP_SA_SPEC * sptr_ib_esp_sa_spec; IPSEC_ESP_MESSAGE ipsec_esp_message; IP_VERSION_NUMBER ip_version; SA_SPEC_RET_TYPES espFailReason; CIPHER * cipher; PARAMETER_NOT_USED (sptr_bundle); sptr_ib_esp_sa_spec = (INBOUND_ESP_SA_SPEC *)sptr_sa_spec; ipsec_esp_message_construct (&ipsec_esp_message); ipsec_esp_message_get_spi_and_sequence_number (&ipsec_esp_message, p_ip_message); #if defined(IPSEC_VERBOSE_PACKET_DEBUGGING) printf("====| INCOMING SPI:0x%08x\n", ipsec_esp_message.spi); printf("====| INCOMING SEQ:0x%08x\n", ipsec_esp_message.esp_sequence_number); #endif if (sptr_ib_esp_sa_spec->parent.spi != ipsec_esp_message.spi) { return (SA_SPEC_FAIL); } if (inbound_ipsec_sa_spec_check_if_sequence_number_is_valid ( (INBOUND_IPSEC_SA_SPEC *)sptr_ib_esp_sa_spec, ipsec_esp_message.esp_sequence_number, sptr_ib_esp_sa_spec->authentication_type) == FALSE) { return (ESP_SEQUENCE_ERROR); } ipsec_esp_message_set_crypto_algorithm (&ipsec_esp_message, sptr_ib_esp_sa_spec->crypto_algorithm); cipher = (CIPHER *) & (sptr_ib_esp_sa_spec->localCipher); if(ipsec_esp_message_decrypt_and_deserialize_trailer (&ipsec_esp_message, p_ip_message->pPayload, cipher, &espFailReason) != TRUE) { return (espFailReason); } if (ipsec_esp_message_deserialize_header (&ipsec_esp_message, p_ip_message->pPayload) == FALSE) { return (ESP_DECRYPTION_ERROR); } if ((sptr_ib_esp_sa_spec->authentication_type != AUTH_ALGORITHM_RESERVED) && (inbound_ipsec_sa_spec_is_anti_replay_enabled((INBOUND_IPSEC_SA_SPEC *)sptr_ib_esp_sa_spec) == TRUE)) { inbound_ipsec_sa_spec_update_receive_window ( (INBOUND_IPSEC_SA_SPEC *)sptr_ib_esp_sa_spec, ipsec_esp_message.esp_sequence_number); } ip_version = p_ip_message->version; if (ip_version == IP_V4) { ((IP_V4_MESSAGE *)p_ip_message)->transport_protocol = ipsec_esp_message.next_header; } else if (ip_version == IP_V6) { #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) UCHAR *bptr_data; #endif ((IP_V6_MESSAGE *)p_ip_message)->next_header = ipsec_esp_message.next_header; ((IP_V6_MESSAGE *)p_ip_message)->transport_protocol = ipsec_esp_message.next_header; #if STACK_NAME == STACK_NAME_V4_V6 && defined (INET6) bptr_data = packetBufDataGet(p_ip_message->pPayload); ((IP_V6_MESSAGE *)p_ip_message)->transport_protocol = ipsecIpv6ExtnsTransportProtocolFind (ipsec_esp_message.next_header, bptr_data); #endif } else { ipsec_printf (IPSEC_WARNING_PRINTF, "IPsec: IP Message: INVALID_VERSION\n"); } ipsec_esp_message_destruct (&ipsec_esp_message); return (SA_SPEC_SUCCESS); } /* end inbound_esp_sa_spec_process() *//******************************************************************************/SA_SPEC_RET_TYPES inbound_tunnel_sa_spec_process ( SA_SPEC *sptr_sa_spec, IP_VI_MESSAGE *p_ip_message, SA_BUNDLE *sptr_bundle ) { /* ** RFC2401 ** ============================================== ** Section 5.2 Processing Inbound IP Traffic ** ** Section 5.2.1 Selecting and Using an SA or SA Bundle ** ==================================================== ** Mapping the IP datagram to the appropriate SA is simplified because ** of the presence of the SPI in the AH or ESP header. Note that the ** selector checks are made on the inner headers not the outer (tunnel) ** headers. The steps followed are: ** ** 1. Use the packet's destination address (outer IP header), ** IPsec protocol, and SPI to look up the SA in the SAD. If ** the SA lookup fails, drop the packet and log/report the ** error. ** ** 2. Use the SA found in (1) to do the IPsec processing, e.g., ** authenticate and decrypt. This step includes matching the ** packet's (Inner Header if tunneled) selectors to the ** selectors in the SA. Local policy determines the ** specificity of the SA selectors (single value, list, ** range, wildcard). In general, a packet's source address ** MUST match the SA selector value. However, an ICMP packet ** received on a tunnel mode SA may have a source address ** other than that bound to the SA and thus such packets ** should be permitted as exceptions to this check. For an ** ICMP packet, the selectors from the enclosed problem ** packet (the source and destination addresses and ports ** should be swapped) should be checked against the selectors ** for the SA. Note that some or all of these selectors may ** be inaccessible because of limitations on how many bits of ** the problem packet the ICMP packet is allowed to carry or ** due to encryption. See Section 6. */ PARAMETER_NOT_USED (sptr_bundle); if (ipsec_deserialize_tunnel_message (sptr_sa_spec, p_ip_message) == FALSE) { return (SA_SPEC_FAIL); } return (SA_SPEC_SUCCESS); }/******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -