#!/usr/bin/perl
#
# Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
# Yokogawa Electric Corporation.
# All rights reserved.
# 
# Redistribution and use of this software in source and binary
# forms, with or without modification, are permitted provided that
# the following conditions and disclaimer are agreed and accepted
# by the user:
# 
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in
#    the documentation and/or other materials provided with
#    the distribution.
# 
# 3. Neither the names of the copyrighters, the name of the project
#    which is related to this software (hereinafter referred to as
#    "project") nor the names of the contributors may be used to
#    endorse or promote products derived from this software without
#    specific prior written permission.
# 
# 4. No merchantable use may be permitted without prior written
#    notification to the copyrighters.
# 
# 5. The copyrighters, the project and the contributors may prohibit
#    the use of this software at any time.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHTERS, THE PROJECT AND
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING
# BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.  IN NO EVENT SHALL THE
# COPYRIGHTERS, THE PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
# INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# $Id: IKEv2-EN-I-1-1-6-10-A.seq,v 1.3 2008/11/28 10:16:18 doo Exp $
#
################################################################

BEGIN
{
	push(@INC, '..');
}

END {}



use IKEv2;
use strict;



my $remote	= 'common_remote_index';
my $selector	= 'common_selector_index_outbound';

my $session	= undef;
my $ret	= undef;
my $str = undef;
my $expected_ike_sa_init_request	= undef;
my $ike_sa_init_req_param = undef;
my $ike_sa_init_resp_param = undef;
my $ike_auth_req_param = undef;
my $ike_auth_resp_param = undef;
my $material	= undef;
my $child_sa_material	= undef;



kLogHTML('<FONT COLOR="#FF0000" SIZE="+1"><U><B>TEST SETUP</B></U></FONT>');

my $tn = 'EN';
my $nut = 'EN';

#------------------------------#
# register IKEv2.pm            #
#------------------------------#
unless(IKEv2initialize($nut, $tn)) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">IKEv2 module initializing failure</FONT>');
}



#------------------------------#
# configure TN                 #
#------------------------------#
unless(IKEv2setupTN()) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">TN setup failure</FONT>');
}



#------------------------------#
# configure NUT                #
#------------------------------#
unless(IKEv2setupNUT()) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">NUT setup failure</FONT>');
}



kLogHTML('<FONT COLOR="#FF0000" SIZE="+1"><U><B>TEST PROCEDURE</B></U></FONT>');



#------------------------------#
# prepare session handler      #
#------------------------------#
$session = IKEv2create_session($remote);
unless(defined($session)) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">IKEv2 session creation failure</FONT>');
}



#--------------------------------------#
# invoke IKE_SA_INIT request by NUT    #
#--------------------------------------#
unless(IKEv2initiateNUT($selector)) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">NUT initiation failure</FONT>');
}



#--------------------------------------#
# receive IKE_SA_INIT request by NUT   #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |-------------->| IKE_SA_INIT request (HDR, SAi1, KEi, Ni)\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);


$ike_sa_init_req_param = devel_IKEv2receive_IKE_SA_INIT_request($session, $remote);
unless(defined($ike_sa_init_req_param)) {
	kLogHTML(kDump_Common_Error());
	kLogHTML('<FONT COLOR="#ff0000">Can\'t observe IKE_SA_INIT request.</FONT>');
	IKEv2exitFail();
}



#--------------------------------------#
# send IKE_SA_INIT response            #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |<--------------| IKE_SA_INIT response (HDR, SAr1, KEr, Nr)\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);



$ike_sa_init_resp_param = devel_IKEv2send_IKE_SA_INIT_response($session, $remote, $ike_sa_init_req_param);
unless(defined($ike_sa_init_resp_param)) {
	kLogHTML(kDump_Common_Error());
	IKEv2exitFatal('<FONT COLOR="#ff0000">Can\'t send IKE_SA_INIT response.</FONT>');
}



#--------------------------------------#
# generate keying material             #
#--------------------------------------#
$material = devel_IKEv2gen_keymat(0, # Responder
				  $ike_sa_init_req_param,
				  $ike_sa_init_resp_param);
unless(defined($material)) {
	kLogHTML(kDump_Common_Error());
	IKEv2exitFatal('<FONT COLOR="#ff0000">Can\'t generate keying material.</FONT>');
}



#--------------------------------------#
# receive IKE_AUTH request by NUT      #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |-------------->| IKE_AUTH request (HDR, SK {IDi, AUTH, SAi2, TSi, TSr)\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);



$ike_auth_req_param = devel_IKEv2receive_IKE_AUTH_request($session,
							  $remote,
							  $ike_sa_init_req_param,
							  $ike_sa_init_resp_param,
							  $material);
unless(defined($ike_auth_req_param)) {
	kLogHTML(kDump_Common_Error());
	kLogHTML('<FONT COLOR="#ff0000">Can\'t observe IKE_AUTH request.</FONT>');
	IKEv2exitFail();
}



#--------------------------------------#
# prepare IKE_AUTH response            #
#--------------------------------------#
my $dummy_ike_auth_resp_param = devel_IKEv2send_IKE_AUTH_response($session,
								  $remote,
								  $ike_sa_init_req_param,
								  $ike_sa_init_resp_param,
								  $material,
								  0);
my $common_gen_ike_auth_resp = $gen_ike_auth_resp->{'common_remote_index'};
my @local_ike_auth_resp = @{$common_gen_ike_auth_resp};
foreach my $payload (@local_ike_auth_resp) {
	if ($payload->{'self'} eq 'SA') {
		foreach my $proposal (@{$payload->{'proposals'}}) {
			foreach my $transform (@{$proposal->{'transforms'}}) {
				if ($transform->{'type'} eq 'ENCR') {
					$transform->{'id'} = 'AES_CBC';
					my $attribute = {
						'af'	=> '1',
						'type'	=> 'Key Length',
						'value'	=> '128',
						'length'=> undef,
					};
					push(@{$transform->{'attributes'}}, $attribute);
				}
			}
		}
	}
}
my $index = 'resp_with_inconsistent_sa_proposal_CHILD_SA.1';
$gen_ike_auth_resp->{$index} = \@local_ike_auth_resp;



#--------------------------------------#
# send IKE_AUTH response               #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |<--------------| IKE_AUTH response (HDR, SK {IDr, AUTH, SAr2, TSi, TSr)\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);



$ike_auth_resp_param = devel_IKEv2send_IKE_AUTH_response($session,
							 $index,
							 $ike_sa_init_req_param,
							 $ike_sa_init_resp_param,
							 $material);
unless (defined($ike_auth_resp_param)) {
	kLogHTML(kDump_Common_Error());
	IKEv2exitFatal('<FONT COLOR="#ff0000">Can\'t send IKE_AUTH response.</FONT>');
}



#--------------------------------------#
# generate keying material (CHILD_SA)  #
#--------------------------------------#
$ike_auth_resp_param->{'encr'} = $dummy_ike_auth_resp_param->{'encr'};
$ike_auth_resp_param->{'encrAttr'} = $dummy_ike_auth_resp_param->{'encrAttr'};
$child_sa_material = devel_IKEv2gen_child_sa_keymat(1,  # Initial Exchanges
						    $material,
						    $ike_sa_init_req_param,
						    $ike_sa_init_resp_param,
						    $ike_auth_req_param,
						    $ike_auth_resp_param);



#--------------------------------------#
# set keying material                  #
#--------------------------------------#
$ret = IKEv2set_child_sa_keymat(0,  # Responder
				$child_sa_material,
				$ike_auth_req_param,
				$ike_auth_resp_param);
unless($ret) {
	kLogHTML(kDump_Common_Error());
	IKEv2exitFatal('<FONT COLOR="#ff0000">Can\'t set keying material.</FONT>');
}



#--------------------------------------#
# prepare ICMP session handler         #
#--------------------------------------#
my $icmp_session = ICMPcreate_session('TN1sendtoNUT');
unless(defined($icmp_session)) {
	IKEv2exitFatal('<FONT COLOR="#ff0000">ICMP session creation failure</FONT>');
}



#--------------------------------------#
# send Echo Reply                      #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |<==============| IPsec {Echo Request}\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);

$ret = ICMPsend($icmp_session, 'echo_request');
unless (defined($ret)) {
	kLogHTML(kDump_Common_Error());
	IKEv2exitFatal('<FONT COLOR="#ff0000">Can send ICMP packet.</FONT>');
}



#--------------------------------------#
# receive Echo Reply                   #
#--------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |========X      | IPsec {Echo Reply}\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);

$ret = ICMPreceive($icmp_session);
if (defined($ret)) {
	my $strerror = kDump_Common_Error();
	kLogHTML('<FONT COLOR="#ff0000">Can\'t observe ICMP packet.</FONT>');
	IKEv2exitFail();
}



#--------------------------------------#
# exit with cleanup                    #
#--------------------------------------#
IKEv2exitPass();



#
# perldoc
#
########################################################################
__END__

=head1 Title

  Test IKEv2.EN.I.1.1.6.10: Response with inconsistent proposal for CHILD_SA
  Part A: (BASIC)

=head1 Purpose

  To verify an IKEv2 device properly handles a response with a SA payload which is
  inconsistent with one of its proposals.

=head1 References

  * [RFC 4306] - Sections 2.7 and 3.3

=head1 Test Setup

  * Network Topology
      Connect the devices according to the Common Topology.
  * Configuration
      In each part, configure the devices according to the Common Configuration.
  * Pre-Sequence and Cleanup Sequence
      IKEv2 on the NUT is disabled after each part.

=head1 Procedure

=begin html

<BLOCKQUOTE>
<PRE>

   NUT                  TN1
(End-Node)           (End-Node)
    |                    |
    |------------------->| IKE_SA_INIT request (HDR, SAi1, KEi, Ni)
    |                    | (Judgement #1)
    |<-------------------| IKE_SA_INIT Response (HDR, SAr1, KEr, Nr)
    |                    | (Packet #1)
    |                    |
    |------------------->| IKE_AUTH request (HDR, SK {IDi, AUTH, N, SAi2, TSi, TSr})
    |                    | (Judgement #2)
    |<-------------------| IKE_AUTH Response (HDR, SK {IDr, AUTH, N, SAr2, TSi, TSr})
    |                    | (Packet #2)
    |                    |
    |<-------------------| IPSec {Echo Request}
    |                    | (Packet #3)
    |----------X         | IPSec {Echo Reply}
    |                    | (Judgement #3)
    |                    |
    V                    V
  
 N: USE_TRANSPORT_MODE
</PRE>
</BLOCKQUOTE>

<BLOCKQUOTE>
<TABLE BORDER>
<TR>
<TD><TT>Packet #1</TT></TD>
<TD><TT>See Common Packet #2</TT></TD>
</TR>
<TR>
<TD><TT>Packet #2</TT></TD>
<TD><TT>See below</TT></TD>
</TR>
<TR>
<TD><TT>Packet #3</TT></TD>
<TD><TT>See Common Packet #19</TT></TD>
</TR>
</TABLE>
</BLOCKQUOTE>

<BLOCKQUOTE>
Packet #1: IKE_SA_INIT response
<TABLE BORDER>
<TR>
<TD>IPv6 Header</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>UDP Header</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>IKEv2 Header</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>E Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>IDr Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>AUTH Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>N Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>SA Payload</TD>
<TD>See below</TD>
</TR>
<TR>
<TD>TSi Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
<TR>
<TD>TSr Payload</TD>
<TD>Same as the Common Packet #4</TD>
</TR>
</TABLE>
</BLOCKQUOTE>

<br>
<BLOCKQUOTE>
<TABLE BORDER>
<TR>
<TD rowspan="24">SA Payload</TD>
<TD colspan="4">Next Payload</TD>
<TD>44 (TSi)</TD>
</TR>
<TR>
<TD colspan="4">Critical</TD>
<TD>0</TD>
</TR>
<TR>
<TD colspan="4">Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD colspan="4">Payload Length</TD>
<TD>44</TD>
</TR>
<TR>
<TD rowspan="20">Proposal #1</TD>
<TD rowspan="20">SA Proposal</TD>
<TD colspan="2">Next Payload</TD>
<TD>0 (last)</TD>
</TR>
<TR>
<TD colspan="2">Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD colspan="2">Proposal Length</TD>
<TD>40</TD>
</TR>
<TR>
<TD colspan="2">Proposal #</TD>
<TD>1</TD>
</TR>
<TR>
<TD colspan="2">Protocol ID</TD>
<TD>3 (ESP)</TD>
</TR>
<TR>
<TD colspan="2">SPI Size</TD>
<TD>4</TD>
</TR>
<TR>
<TD colspan="2"># of Transforms</TD>
<TD>3</TD>
</TR>
<TR>
<TD>SA Transform</TD>
<TD colspan="2">See below</TD>
</TR>
<TR>
<TD rowspan="6">SA Transform</TD>
<TD>Next Payload</TD>
<TD>3 (more)</TD>
</TR>
<TR>
<TD>Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD>Transform Length</TD>
<TD>8</TD>
</TR>
<TR>
<TD>Transform Type</TD>
<TD>3 (INTEG)</TD>
</TR>
<TR>
<TD>Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD>Transform ID</TD>
<TD>2 (HMAC_SHA1_96)</TD>
</TR>
<TR>
<TD rowspan="6">SA Transform</TD>
<TD>Next Payload</TD>
<TD>0 (last)</TD>
</TR>
<TR>
<TD>Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD>Transform Length</TD>
<TD>8</TD>
</TR>
<TR>
<TD>Transform Type</TD>
<TD>5 (Extended Sequence Number)</TD>
</TR>
<TR>
<TD>Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD>Transform ID</TD>
<TD>0 (No Extended Sequence Number)</TD>
</TR>
</TABLE>
</BLOCKQUOTE>

<BLOCKQUOTE>
<TABLE BORDER>
<TR>
<TD rowspan="8">SA Transform</TD>
<TD colspan="2">Next Payload</TD>
<TD>3 (more)</TD>
</TR>
<TR>
<TD colspan="2">Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD colspan="2">Transform Length</TD>
<TD>12</TD>
</TR>
<TR>
<TD colspan="2">Transform Type</TD>
<TD>1 (ENCR)</TD>
</TR>
<TR>
<TD colspan="2">Reserved</TD>
<TD>0</TD>
</TR>
<TR>
<TD colspan="2">Transform ID</TD>
<TD>12 (AES_CBC)</TD>
</TR>
<TR>
<TD rowspan="2">SA Attribute</TD>
<TD>Attribute Type</TD>
<TD>14 (Key Length)</TD>
</TR>
<TR>
<TD>Attribute Value</TD>
<TD>128</TD>
</TR>
</TABLE>
</BLOCKQUOTE>

=end html

  Part A: (BASIC)
     1. NUT starts to negotiate with TN1 by sending IKE_SA_INIT request.
     2. Observe the messages transmitted on Link A.
     3. TN1 responds with an IKE_SA_INIT response to the NUT.
     4. Observe the messages transmitted on Link A.
     5. TN1 responds with an IKE_AUTH response to the NUT. But the response includes a SA
         payload which has a different Transform ID from the proposed one.
     6. TN1 transmits an Echo Request with IPsec ESP using ENCR_AES_CBC and
         AUTH_HMAC_SHA1_96.
     7. Observe the messages transmitted on Link A.


=head1 Observable Result

  Part A
       Step 2: Judgment #1
       The NUT transmits an IKE_SA_INIT request including "ENCR_AES_CBC",
       "PRF_HMAC_SHA1", "AUTH_HMAC_SHA1_96" and "D-H group 2" as proposed
       algorithms.

       Step 4: Judgment #2
       The NUT transmits an IKE_AUTH request including "ENCR_3DES",
       "AUTH_HMAC_SHA1_96" and "No Extended Sequence Numbers" as proposed algorithms.

       Step 7: Judgment #3
       The NUT never transmits an Echo Reply with IPsec ESP using ENCR_AES_CBC and
       AUTH_HMAC_SHA1_96.


=head1 Possible Problems

  * Step 7
    The NUT may transmit or retransmit an IKE_AUTH request. And the NUT may notify
    INVALID_SPI.

=cut


