#!/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-SGW-I-1-3-1-1-A.seq,v 1.4 2009/06/09 05:05:50 akisada Exp $
#
################################################################

BEGIN
{
	push(@INC, '..');
	$ENV{'V6EVAL_WITH_KOI'} = 'TRUE';
}

END {}

use V6evalTool;
use IKEv2v6eval;
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 $informational_req_param = undef;

my $material	= undef;
my $child_sa_material	= undef;



#--------------------------------------#
# prepare IKE_AUTH request             #
#--------------------------------------#
my $common_exp_ike_auth_req = $exp_ike_auth_req->{'common_remote_index'};
my @my_exp_ike_auth_req = @{$common_exp_ike_auth_req};
foreach my $payload (@my_exp_ike_auth_req) {
	if ($payload->{'self'} eq 'E') {
		my @payloads = grep {
			my $ret = 0;
			if ($_->{'self'} ne 'N') { $ret = 1; }
			if ($_->{'type'} ne 'USE_TRANSPORT_MODE') { $ret = 1; }
			$ret;
		} @{$payload->{'innerPayloads'}};

		$payload->{'innerPayloads'} = \@payloads;
	}
}
# set correct nexttype
for (my $i = 0; $i < scalar(@my_exp_ike_auth_req); $i++) {
	my $payload = $my_exp_ike_auth_req[$i];

	if ($payload->{'self'} eq 'E') {
		for (my $j = 0; $j < scalar(@{$payload->{'innerPayloads'}}); $j++) {
			my $cur = $payload->{'innerPayloads'}->[$j];
			my $next = $payload->{'innerPayloads'}->[$j+1];
			unless (defined($next)) {
				$cur->{'nexttype'} = '0';
				next;
			}
			if ($cur->{'nexttype'} eq $next->{'self'}) {
				next;
			}
			$cur->{'nexttype'} = $next->{'self'};
		}

		next;
	}
}

my $exp_index = 'SGW-I-1-1-1-3.1';
$exp_ike_auth_req->{$exp_index} = \@my_exp_ike_auth_req;



#--------------------------------------#
# prepare IKE_AUTH response            #
#--------------------------------------#
my $common_gen_ike_auth_resp = $gen_ike_auth_resp->{'common_remote_index'};
my @my_gen_ike_auth_resp = @{$common_gen_ike_auth_resp};
# remove N(USE_TRANSPORT_MODE)
@my_gen_ike_auth_resp = grep {
		my $ret = 0;
		if ($_->{'self'} ne 'N') { $ret = 1; }
		if ($_->{'type'} ne 'USE_TRANSPORT_MODE') { $ret = 1; }
		$ret;
	} @my_gen_ike_auth_resp;

my $gen_index = 'SGW-I-1-1-1-3.2';
$gen_ike_auth_resp->{$gen_index} = \@my_gen_ike_auth_resp;



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



#------------------------------#
# register IKEv2.pm            #
#------------------------------#
unless(IKEv2initialize('SGW', 'SGW')) {
	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>');
}



$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);



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



#--------------------------------------#
# receive IKE_SA_INIT request          #
#--------------------------------------#
$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, $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             #
#--------------------------------------#
$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,
							  $exp_index,
							  $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();
}



#--------------------------------------#
# 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,
							 $gen_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)  #
#--------------------------------------#
$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>');
}



#-----------------------------------------#
# wait until receiving a liveness check   #
#                                         #
# receive INFORMATIONAL Request by NUT    #
#-----------------------------------------#
$str  = '<PRE>';
$str .= "    (I)             (R)\n";
$str .= "    NUT             TN1\n";
$str .= "     |               |\n";
$str .= "     |               * wait until receiving a liveness check\n";
$str .= "     |               |\n";
$str .= "     |-------------->| INFORMATIONAL Request (HDR, SK {})\n";
$str .= "     |               |\n";
$str .= "     V               V";
$str .= '</PRE>';

kLogHTML($str);


#------------------------------------------------------------------#
# set timer to liveness check                                      #
#------------------------------------------------------------------#
$session->timeout($config_pl->{'ikev2_nut_liveness_check_timer'});


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



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



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

=head1 Title

  Test IKEv2.SGW.I.1.3.1.1: Sending INFORMATIONAL Exchange
  Part A: IKE Header Format (BASIC) 
  Part B: Encrypted Payload Format (BASIC)

=head1 Purpose

  To verify an IKEv2 device checks whether the other endpoint is alive.

=head1 References

  * [RFC 4306] - Sections 2.1, 2.2 and 2.4

=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
  (SGW)                (SGW)
    |                    |
    |------------------->| 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, SAi2, TSi, TSr})
    |                    | (Judgement #2)
    |<-------------------| IKE_AUTH Response (HDR, SK {IDr, AUTH, SAr2, TSi, TSr})
    |                    | (Packet #2)
    |                    |
    |                    * wait until receiving liveness check 
    |                    |
    |------------------->| INFORMATIONAL request (HDR, SK {}) 
    |                    | (Judgement #3)
    |                    |
    V                    V<br>

</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 Common Packet #4</TT></TD>
</TR>
</TABLE>
</BLOCKQUOTE>

=end html

  Part A: IKE Header Format (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. After reception of IKE_AUTH request from the NUT, TN1 responds with an IKE_AUTH
        response to the NUT.
     6. TN1 waits for receiving an INFORMATIONAL request with no payloads.
     7. Observe the messages transmitted on Link A.

  Part B: Encrypted Payload Format (BASIC)
     8. NUT starts to negotiate with TN1 by sending IKE_SA_INIT request.
     9. Observe the messages transmitted on Link A.
    10. TN1 responds with an IKE_SA_INIT response to the NUT.
    11. Observe the messages transmitted on Link A.
    12. After reception of IKE_AUTH request from the NUT, TN1 responds with an IKE_AUTH
        response to the NUT.
    13. TN1 waits for receiving an INFORMATIONAL request with no payloads.
    14. 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_3DES",
       "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 transmits an INFORMATIONAL request including properly formatted IKE Header
       containing following values:

=begin html

<BLOCKQUOTE>
<PRE>
                      1                   2                   3
  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 !                      IKE_SA Initiator s SPI                   ! 
 !                                                               !
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 !                      IKE_SA responder s SPI                   !
 !                                                               !
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 !  Next Payload ! MjVer ! MnVer ! Exchange Type !     Flags     !
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 !                            Message ID                         !
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 !                              Length                           !
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br>
                     Figure 131 Header format<br>

</PRE>
</BLOCKQUOTE>

=end html

    * An IKE_SA Initiator's SPI field is set to same as the IKE_SA_INIT request's IKE_SA
      Initiator's SPI field value.
    * An IKE_SA Responder's SPI field is set to same as the IKE_SA_INIT response's
      IKE_SA Responder's SPI field value.
    * A Next Payload field is set to Encrypted Payload (46).
    * A Major Version field is set to 2.
    * A Minor Version field is set to zero.
    * An Exchange Type field is set to INFORMATIONAL (37).
    * A Flags field is set to (00010000)2 = (16)10.
    * A Message ID field is set to the value incremented the previous IKE message's
      Message ID by one.
    * A Length field is set to the length of the message (header + payloads) in octets.

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

       Step 1: 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 14: Judgment #3
       The NUT transmits an INFORMATIONAL request including properly formatted Encrypted
       Payload containing following values:

=begin html

<BLOCKQUOTE>
<PRE>

                           1                   2                   3
       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      ! Next Payload  !C!  RESERVED   !         Payload Length        !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !                     Initialization Vector                     !
      !         (length is block size for encryption algorithm)       !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      ~                    Encrypted IKE Payloads                     ~
      +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      !               !             Padding (0-255 octets)            !
      +-+-+-+-+-+-+-+-+                               --+-+-+-+-+-+-+-+
      !                                               !  Pad Length   !
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
      ~                    Integrity Checksum Data                    ~   
      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+<br>
                        Figure 132 Encrypted payload<br>

</PRE>
</BLOCKQUOTE>

=end html

    * A Next Payload field is set to zero.
    * A Critical field is set to zero.
    * A RESERVED field is set to zero.
    * A Payload Length field is set to length in octets of the header, IV, Encrypted
      IKE Payloads, Padding, Pad Length, and Integrity Check sum Data.
    * An Initialization Vector field is set to a randomly chosen value whose length is
      equal to the block length of the underlying encryption algorithm. It is 64 bits
      length in ENCR_3DES case.
    * An Encrypted IKE Payloads field is set to subsequent payloads encrypted by
      ENCR_3DES.
    * A Padding field is set to any value which to be a multiple of the encryption
      block size. It is 64 bits length in ENCR_3DES case.
    * A Pad Length field is set to the length of the Padding field.
    * An Integrity Checksum Data set to the cryptographic checksum of the entire
      message. It is 96 bits length in AUTH_HMAC_SHA1_96 case. The checksum
      must be valid by calculation according to the manner described in RFC.

=head1 Possible Problems

  * none.

=cut


