| |
| |
| conftest - an IKEv2 conformance testing framework |
| ================================================= |
| |
| |
| 1. Introduction |
| --------------- |
| |
| conftest is a conformance testing framework for IKEv2 and related protocols, |
| based on the strongSwan IKEv2 daemon charon. It uses a specialized configuration |
| and control front-end, but links against the mainstream strongSwan IKEv2 stack. |
| |
| The conftest framework can test other implementations of IKEv2 and related |
| standards. It can inject or mangle packets to test the behavior of other |
| implementations under certain conditions. |
| |
| 2. Test suites |
| -------------- |
| |
| The framework can use different sets of conformance tests, called test suites. |
| Each test suite contains a global suite configuration file, usually named |
| suite.conf. It contains the global settings for all tests in this suite, mostly |
| credentials and connection definitions. |
| |
| A test suite consists of several test cases. Each test has its own configuration |
| file, often called test.conf. The test configuration file may contain test |
| specific credentials and connection definitions, but primarily defines actions |
| and hooks. Actions trigger certain protocol specific operations, such as |
| initiating or terminating a tunnel. Hooks are used to change the behavior of |
| the IKE stack, most likely to stress some factors of the IKE protocol and |
| provoke unintended behavior in the tested platform. |
| |
| 3. Configuration syntax |
| ----------------------- |
| |
| Both the suite and the test specific configuration file use the same syntax. |
| It is the same as used by the strongswan.conf file used to configure the |
| strongSwan software suite. |
| |
| The syntax is as follows: |
| |
| settings := (section|keyvalue)* |
| section := name { settings } |
| keyvalue := key = value\n |
| |
| Settings contain zero or more sub-sections or key/value pairs. A section |
| consists of a name, followed by curly open and close brackets. The value in the |
| key/value pair starts after the equal sign and is terminated by the end of the |
| line. |
| |
| The test specific configuration is merged to the suite configuration, resulting |
| in a unified configuration. Sections are merged, keys in the test configuration |
| overwrite existing identical keys in the suite configuration. |
| |
| 4. Logging |
| ---------- |
| |
| Logging verbosity can be controlled in the log section of a suite/test |
| configuration. The stdout subsection takes logging facility/verbosity key |
| value pairs, the different facility types are defined in debug_lower_names at |
| src/libstrongswan/debug.c. |
| Any other sub-section in the log section is considered as a file name to log |
| to. Each section takes the same facility/verbosity keys as the special stdout |
| section. |
| |
| 5. Connections |
| -------------- |
| |
| Both the suite and test configuration may contain connection definitions under |
| the configs section. Each IKE_SA configuration has a sub-section. Each IKE_SA |
| sub-section contains one or more CHILD_SA configuration sub-sections: |
| |
| configs { |
| ike-a { |
| # ... ike options |
| child-a1 { |
| # ... child options |
| } |
| child-a2 { |
| # ... |
| } |
| } |
| } |
| |
| Configuration names can be chosen arbitrary, but should be unique within the |
| same file. |
| |
| The IKE_SA configuration uses the following options (as key/value pairs): |
| |
| lhost: Address (IP or Hostname) of this host |
| rhost: Address (IP or Hostname) of tested host |
| lid: IKEv2 identifier of this host |
| rid: IKEv2 identifier of tested host |
| proposal: IKE_SA proposal list, comma separated, e.g.: |
| aes128-sha1-modp2048,3des-md5-sha1-modp1024-modp1536 |
| Supported algorithm names are defined under |
| src/libstrongswan/crypt/proposal/proposal_keywords.txt |
| fake_nat: Fake the NAT_DETECTION_*_IP payloads to simulate a NAT |
| scenario |
| rsa_strength: Connection requires a trustchain with RSA keys of given bits |
| ecdsa_strength: Connection requires a trustchain with ECDSA keys of given bits |
| cert_policy: Connection requires a certificate with the given OID policy |
| named_pool: Name of an IP pool defined e.g. in a database backend |
| |
| The following CHILD_SA specific configuration options are supported: |
| |
| lts: Local side traffic selectors, comma separated CIDR subnets |
| rts: Remote side traffic selectors, comma separated CIDR subnets |
| transport: Propose IPsec transport mode instead of tunnel mode |
| tfc_padding: Inject Traffic Flow Confidentiality bytes to align packets to the |
| given length |
| proposal: CHILD_SA proposal list, same syntax as IKE_SA proposal list |
| |
| 6. Credentials |
| -------------- |
| |
| Credentials may be defined globally in the suite or locally in the test specific |
| configuration file. Certificates files are defined in the certs section, either |
| in the trusted or in the untrusted section. Trusted certificates are trust |
| anchors, usually root CA certificates. Untrusted certificates do not build a |
| trust anchor and usually contain intermediate or end entity certificates. |
| |
| Certificates files are loaded relative to the configuration file path and may |
| be encoded either in plain ASN.1 DER or in PEM format. The prefix of the |
| key/value pair is used to specify the type of the certificate, usually x509 or |
| crl. |
| |
| Private keys can be defined in the suite or test config file under the keys |
| section. The prefix of the key/value pair must be either rsa or ecdsa, the |
| specified file may be encoded in ASN.1 DER or unencrypted PEM. |
| |
| certs { |
| trusted { |
| x509-a-ca = ca.pem |
| } |
| untrusted { |
| x509-me = /path/to/cert.pem |
| crl-from-ca = /path/to/crl.pem |
| } |
| } |
| keys { |
| ecdsa-me = /path/to/key.pem |
| } |
| |
| 7. Actions |
| ---------- |
| |
| The actions section in the test specific configuration file defines |
| the IKEv2 protocol actions to trigger. Currently, the following actions |
| are supported and take these arguments (as key/value pairs): |
| |
| initiate: Initiate an IKE- and CHILD_SA |
| config: name of the CHILD_SA configuration to initiate |
| delay: Delay to trigger action after startup |
| rekey_ike: Rekey an IKE_SA |
| config: name of originating IKE_SA configuration |
| delay: Delay to trigger action after startup |
| rekey_child: Rekey an CHILD_SA |
| config: name of originating CHILD_SA configuration |
| delay: Delay to trigger action after startup |
| liveness: Do a liveness check (DPD) on the IKE_SA |
| config: name of originating IKE_SA configuration |
| delay: Delay to trigger action after startup |
| close_ike: Close an IKE_SA |
| config: name of originating IKE_SA configuration |
| delay: Delay to trigger action after startup |
| close_child: Close a CHILD_SA |
| config: name of originating IKE_SA configuration |
| delay: Delay to trigger action after startup |
| |
| To trigger the same action multiple times, the action sections must be named |
| uniquely. Append an arbitrary string to the action name. The following example |
| initiates a connection and rekeys it twice: |
| |
| actions { |
| initiate { |
| config = child-a1 |
| } |
| rekey_ike-1 { |
| config = ike-a |
| delay = 3 |
| } |
| rekey_ike-2 { |
| config = ike-a |
| delay = 6 |
| } |
| } |
| |
| 8. Hooks |
| -------- |
| |
| The hooks section section in the test configuration defines different hooks |
| to use to mangle packets or trigger other protocol modifications. These |
| hook functions are implemented in the hooks folder of conftest. |
| |
| Currently, the following hooks are defined with the following options: |
| |
| add_notify: Add a notify to a message |
| request: yes to include in request, no in response |
| id: IKEv2 message identifier of message to add notify |
| type: notify type to add, names defined in notify_type_names |
| under src/libcharon/encoding/payloads/notify_payload.c |
| data: notification data to add, prepend 0x to interpret the |
| string as hex string |
| spi: SPI to use in notify |
| esp: yes to send an ESP protocol notify, no for IKE |
| add_payload: Add an arbitrary payload to a message |
| request: yes to include in request, no in response |
| id: IKEv2 message identifier of message to add payload |
| type: type of the payload to add, names defined in |
| payload_type_short_names in payload.c |
| data: data to append after generic payload header, use 0x |
| prefix for hex encoded data |
| critical: yes to set payload critical bit |
| replace: yes to replace an existing payload of the same type |
| custom_proposal: set a custom proposal value in the SA payload |
| request: yes to include in request, no in response |
| id: IKEv2 message identifier of message to add notify |
| The hook takes subsections with numerical names, each |
| defining a proposal substructure. The substructure |
| takes key/value pairs, where key defines the type, value |
| the specific algorithm. |
| force_cookie: Reject IKE_SA_INIT requests with a COOKIE |
| ignore_message: Ignore a specific message, simulating packet loss |
| inbound: yes to ignore incoming, no for outgoing messages |
| request: yes to ignore requests, no for responses |
| id: IKEv2 message identifier of message to ignore |
| ike_auth_fill: Fill up IKE_AUTH message to a given size using a CERT |
| payload. |
| request: yes to fill requests messages, no for responses |
| id: IKEv2 message identifier of message to fill up |
| bytes: number of bytes the final IKE_AUTH message should have |
| log_id: Comfortably log received ID payload contents |
| log_ke: Comfortably log received KE payload DH groups |
| log_proposal: Comfortably log all proposals received in SA payloads |
| log_ts: Comfortably log all received TS payloads |
| pretend_auth: magically reconstruct IKE_AUTH response even if |
| AUTHENTICATION_FAILED received |
| rebuild_auth: rebuild AUTH payload, i.e. if ID payload changed |
| reset_seq: Reset sequence numbers of an ESP SA |
| delay: Seconds to delay reset after SA established |
| oseq: Sequence number to set, default is 0 |
| set_critical: Set critical bit on existing payloads: |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle payloads |
| payloads: space separated payload list to set critical bit on |
| set_ike_initiator: toggle IKE initiator flag in IKE header |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| set_ike_request: toggle IKE request flag in IKE header |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| set_ike_spi: set the IKE SPIs in IKE header |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| spii: initiator SPI to set (as decimal integer) |
| spir: responder SPI to set |
| set_ike_version: set version fields in IKE header |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| major: major version to set |
| minor: minor version to set |
| higher: yes to set Higher Version Supported flag |
| set_length: set the length in a payload header |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| type: payload type to mangle |
| diff: difference to add/remove from real length (+1,-3 etc.) |
| set_proposal_number:Change the number of a proposal in a SA payload |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| from: proposal number to mangle |
| to: new proposal number to set instead of from |
| set_reserved: set arbitrary reserved bits/bytes in payloads |
| request: yes to set in request, no in response |
| id: IKEv2 message identifier of message to mangle |
| The hook takes a list of subsection, each named as payload |
| type. Each section takes a bits and a bytes key, the |
| value is a comma separated list of decimal numbers of |
| bits/bytes to mangle (1 is the first reserved bit/byte |
| in the payload). The byteval key defines to which value |
| set mangled bytes in the byte list. |
| unencrypted_notify: Send an unencrypted message with a notify after |
| establishing an IKE_SA |
| id: IKEv2 message identifier of message to send |
| type: notify type to add, names defined in notify_type_names |
| under src/libcharon/encoding/payloads/notify_payload.c |
| data: notification data to add, prepend 0x to interpret the |
| string as hex string |
| spi: SPI to use in notify |
| esp: yes to send an ESP protocol notify, no for IKE |
| unsort_message: reorder the payloads in a message |
| request: yes to reorder requests messages, no for responses |
| id: IKEv2 message identifier of message to reorder |
| order: payload order, space separated payload names as defined |
| in payload_type_short_names under |
| src/libcharon/encoding/payloads/payload.c |
| |
| 9. Invoking |
| ----------- |
| |
| Compile time options required depend on the test suite. A minimalistic |
| strongSwan build with the OpenSSL crypto backend can be configured with: |
| |
| ./configure --sysconfdir=/etc --disable-pluto --disable-scripts \ |
| --disable-scepclient --disable-aes --disable-des --disable-md5 \ |
| --disable-sha1 --disable-sha2 --disable-fips-prf --disable-gmp \ |
| --disable-pubkey --disable-pgp --disable-dnskey --disable-updown \ |
| --disable-attr --disable-resolve --enable-openssl --enable-conftest \ |
| --enable-gcm --enable-ccm --enable-ctr |
| |
| The conftest utility is installed by default under /usr/local/libexec/ipsec/, |
| but can be invoked with the ipsec helper script. It takes a suite specific |
| configuration file after the --suite option and a test specific file with |
| the --test option: |
| |
| ipsec conftest --suite suite.conf --test 1.1.1/test.conf |