Better than Nothing Security                                     M. Komu
Internet-Draft                                                   Tarkoma
Intended status: Standards Track      Helsinki Institute for Information
Expires: September 7, 2007                                    Technology
                                                           March 6, 2007


                IPsec Application Programming Interfaces
                         draft-komu-btns-api-01

Status of this Memo

   By submitting this Internet-Draft, each author represents that any
   applicable patent or other IPR claims of which he or she is aware
   have been or will be disclosed, and any of which he or she becomes
   aware will be disclosed, in accordance with Section 6 of BCP 79.
   This document may not be modified, and derivative works of it may not
   be created, except to publish it as an RFC and to translate it into
   languages other than English.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF), its areas, and its working groups.  Note that
   other groups may also distribute working documents as Internet-
   Drafts.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   The list of current Internet-Drafts can be accessed at
   http://www.ietf.org/ietf/1id-abstracts.txt.

   The list of Internet-Draft Shadow Directories can be accessed at
   http://www.ietf.org/shadow.html.

   This Internet-Draft will expire on September 7, 2007.

Copyright Notice

   Copyright (C) The IETF Trust (2007).

Abstract

   IPsec based security is usually transparent for applications and and
   they h have no common mechanism for gathering information about
   protected network connections and being aware of underlying security
   mechanisms.  This document specifies an API that increases the



Komu & Tarkoma          Expires September 7, 2007               [Page 1]


Internet-Draft                 IPsec APIs                     March 2007


   visibility of IPsec to applications.  The API allows applications to
   use the Stand-alone BTNS mode, control the channel bindigs, and
   control also other network security properties related to IPsec.


Table of Contents

   1.  Introduction . . . . . . . . . . . . . . . . . . . . . . . . .  3
   2.  IPsec APIs . . . . . . . . . . . . . . . . . . . . . . . . . .  4
     2.1.  IPsec Policies . . . . . . . . . . . . . . . . . . . . . .  5
       2.1.1.  Policy Creation  . . . . . . . . . . . . . . . . . . .  5
       2.1.2.  Policy Attributes  . . . . . . . . . . . . . . . . . .  6
       2.1.3.  Connection Oriented Communications . . . . . . . . . .  7
       2.1.4.  Datagram Oriented Communications . . . . . . . . . . .  7
       2.1.5.  Other Policy Related Functions . . . . . . . . . . . .  8
     2.2.  Channel Bindings . . . . . . . . . . . . . . . . . . . . .  8
       2.2.1.  Channel Creation . . . . . . . . . . . . . . . . . . .  8
       2.2.2.  Channel Attributes . . . . . . . . . . . . . . . . . .  9
       2.2.3.  Connection Oriented Communications . . . . . . . . . . 10
       2.2.4.  Datagram Oriented Communications . . . . . . . . . . . 10
       2.2.5.  Other Channel Related Function . . . . . . . . . . . . 11
   3.  Security Considerations  . . . . . . . . . . . . . . . . . . . 12
   4.  IANA Considerations  . . . . . . . . . . . . . . . . . . . . . 12
   5.  Acknowledgements . . . . . . . . . . . . . . . . . . . . . . . 12
   Appendix A.   Appendix . . . . . . . . . . . . . . . . . . . . . . 12
   Appendix A.1. Code Examples  . . . . . . . . . . . . . . . . . . . 12
   6.  References . . . . . . . . . . . . . . . . . . . . . . . . . . 19
     6.1.  Normative References . . . . . . . . . . . . . . . . . . . 19
     6.2.  Informative References . . . . . . . . . . . . . . . . . . 19
   Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . . 19
   Intellectual Property and Copyright Statements . . . . . . . . . . 21




















Komu & Tarkoma          Expires September 7, 2007               [Page 2]


Internet-Draft                 IPsec APIs                     March 2007


1.  Introduction

   The "better than nothing" (BTNS) extensions are intended to protect
   network traffic on their own (Stand Alone BTNS, or SAB), and may be
   useful in providing network layer security that can be authenticated
   by higher layers in the protocol stack, called Channel Bound BTNS
   (CBB).  The motivation for SAB is to remove the need to deploy
   authentication information altogether.  The motivation for CBB is to
   remove the need for redundant authentication at multiple layers.
   This document defines BTNS related APIs.

   The network communications of applications are usually secured
   explicitly with TLS on transport layer [RFC4346], or using even
   higher layer interfaces such as GSS [RFC2744] or SASL [RFC4422] APIs.
   However, such interfaces do not exist for IPsec because it operates
   on lower layers and is mostly transparent to applications.  Using
   IPsec to protect existing applications is therefore easier than with,
   for example, TLS because IPsec does not require changes in the
   application.  However, it is difficult for an application to detect
   when network connections are secured using IPsec.  IPsec can be used
   as "all or nothing" security measure, which can be problematic in
   early deployments when the number of IPsec enabled machines is small.
   An alternative approach could be to use IPsec in "use when peer
   supports" fashion.  However, the application or the user may not have
   any knowledge that the communications was actually protected in this
   case.  Finally, it is more efficient to remove redundant
   authentications when IPsec and TLS are being used for the same
   connection.

   In this document, we attempt to increase the visibility of the IPsec
   layer to the applications and to fulfil the BTNS requirements
   presented in [I-D.ietf-btns-ipsec-apireq].  The APIs defined in this
   document are based on the sockets API [POSIX] or similar APIs that
   provide socket descriptors for applications.

   The documents defines an explicit way of enabling IPsec in
   applications.  This API allows the dual use of both IPsec and higher
   layer security mechanisms simultaneously.  The security and
   performance related benefits of this are described in more detail in
   [I-D.ietf-btns-prob-and-applic].











Komu & Tarkoma          Expires September 7, 2007               [Page 3]


Internet-Draft                 IPsec APIs                     March 2007


                   +---------+---------+---------+---------+
                   | App # 1 | App # 2 | App # 3 | App #4  |
                   +-----+---+-----+---+---+-----+----+----+
                         |         |       |           |
                         |     +---v-------v--+        |
                         |     | TLS/GSS/SASL |        |
                   +-----v-----+-------+------+        |
   Appl. Layer     |   IPsec APIs      |   |           |
                   +-----+---------+---+   |           |
                         |         |       |           |
                   +-----v---------v-------v-----------v---+
   Sockets Layer   |           IPv4 and IPv6 APIs          |
                   +-----------+--------------+------------+
   Transport Layer |    SCTP   |      TCP     |    UDP     |
                   +-----------+--------------+------------+
   IPsec Layer     |                  IPsec                |
                   +--------------------+------------------+
   Network Layer   |        IPv4        |      IPv6        |
                   +--------------------+------------------+
   Link Layer      |        Ethernet    |         Etc      |
                   +--------------------+------------------+

                          Figure 1: API Layering

   Figure 1 illustrates four different applications.  The first
   application is using only the IPsec APIs based on either IKE based
   authentication or Stand-alone BTNS.  The second application is using
   both TLS (or other similar APIs) and IPsec APIs.  In this case, the
   application can skip IKE authentication because of it is already
   provided by TLS.  On the other hand, the application can avoid the
   use of TLS altogether when IKE authentication is available.'The third
   application is using only TLS and the fourth one is using neither
   IPsec or TLS APIs.

   In the first three cases, the application is explicitly modified to
   use either TLS or IPsec.  In contrast, the fourth application is not
   using either TLS or IPsec explicitly, but it may be using IPsec
   implicitly.  This document covers the use of applications one and
   two.


2.  IPsec APIs

   This section defines constants, data structures and functions for
   manipulating IPsec policies and channel bindings.  The definitions
   are based on C-language.

   An application creates first a policy and attaches some attributes



Komu & Tarkoma          Expires September 7, 2007               [Page 4]


Internet-Draft                 IPsec APIs                     March 2007


   for it.  For example, the application can define in the attributes
   that it wants to use CBB mode for a certain socket.  After this, the
   application can require certain channel bindings from the socket (to
   implement ACLs, for example) and try to communicate with a peer
   through the socket.  Alternatively, the application can do a leap of
   faith with first time communication with the peer and store the
   channel bindings for later use.  See Appendix A.1 for code examples
   on how to use the APIs in practise.

2.1.  IPsec Policies

   This section defines functions that manage application policies.  The
   policies are used to control the key management software or the IPsec
   module of a host.  The two main policy attributes are the following:
   controlling BTNS standalone mode and requiring channel bindings.  The
   former prevents IPSec authentication, and the latter allows channel
   creation and management.

2.1.1.  Policy Creation

   The data structure that represents an application policy is contained
   in an opaque ipsec_policy structure.  The application MUST not alter
   the data structure contents directly, but rather use the accessor
   functions introduced in the following sections.  The application can
   use ipsec_policy_t typedef as a short hand for the policy structure.
   The typedef is shown in Figure 2.

   typedef ipsec_policy_t struct ipsec_policy;

                                 Figure 2

   The size of a policy is variable and applications MUST NOT declare
   them directly.  Instead, the application uses the constructor and
   destructor functions shown in Figure 3.

   ipsec_policy_t *ipsec_create_policy(uint32_t type);
   int ipsec_free_policy(ipsec_policy_t *policy);

                                 Figure 3

   Function ipsec_create_policy allocates memory for a policy and
   initializes it.  The function returns the created policy, or NULL
   upon failure.  The function takes one input argument that initializes
   the default policy type.  The different policy types are listed in
   Table 1.






Komu & Tarkoma          Expires September 7, 2007               [Page 5]


Internet-Draft                 IPsec APIs                     March 2007


                +----------------------+-----------------+
                | Policy Type          | Purpose         |
                +----------------------+-----------------+
                | IPSEC_DEFAULT_POLICY | System defaults |
                +----------------------+-----------------+

                                  Table 1

   Function ipsec_free_policy deinitializes and frees the memory
   allocated to a policy.  It returns zero on success, and non-zero upon
   failure.

2.1.2.  Policy Attributes

   Policies are opaque data structures that MUST NOT be manipulated
   directly.  Instead, the application uses the accessor functions shown
   in Figure 4.

   int ipsec_get_policy_attr(const ipsec_policy_t *policy,
                             uint32_t attr_type,
                             uint32_t *attr_len,
                             void **attr_val);
   int ipsec_set_policy_attr(ipsec_policy_t *policy,
                             uint32_t attr_type,
                             uint32_t attr_len,
                             const void *attr_val);

                                 Figure 4

   Function ipsec_get_policy_attr searches for the given attribute type
   (attr_type) from the policy.  It allocates memory into attr_val and
   copies the attribute into the allocated memory.  On successful
   operation, it sets the attribute length in attr_len.

   Function ipsec_set_policy_attr writes the attribute (attr_val) to the
   policy.  The type and length of the attribute must be set in
   attr_type and attr_len.

   The attribute types and their lengths are shown in Table 2.

   +----------------------------+----------+---------------------------+
   | Attribute Type             | Length   | Purpose                   |
   +----------------------------+----------+---------------------------+
   | IPSEC_BTNS_STANDALONE      | 4 octets | Allow BTNS standalone     |
   |                            |          | mode                      |
   | IPSEC_BTNS_CHANNEL_BINDING | 4 octets | Require channel bindings  |
   +----------------------------+----------+---------------------------+




Komu & Tarkoma          Expires September 7, 2007               [Page 6]


Internet-Draft                 IPsec APIs                     March 2007


                                  Table 2

   Both of the functions return zero for success and non-zero for
   failure.  XX FIX list error values here.

2.1.3.  Connection Oriented Communications

   Declaring a policy does not affect the networking communications of
   an application.  For connection oriented communications, the
   application must first attach the policy to socket before the policy
   is effective.  It is also possible to query for the policy attached
   to a socket as shown in Figure 5.

   int ipsec_set_socket_policy(int fd, const ipsec_policy_t *policy);
   int ipsec_get_socket_policy(int fd, ipsec_policy_t **policy);

                                 Figure 5

   Both functions input an socket descriptor as the first argument and a
   policy pointer as the second argument.  Function
   ipsec_set_socket_policy attaches the given policy pointer to the
   socket descriptor fd.  For ipsec_get_socket_policy, the policy is a
   double pointer because the function also allocates the memory for the
   queried policy.

   Both functions return zero upon success, and non-zero upon failure.
   XX FIX list error values here.

2.1.4.  Datagram Oriented Communications

   The previous section covered the use of connected sockets.  Datagram
   oriented communications based on sendmsg and recvmsg functions are
   supported in the API, but sendto and recvfrom are not supported.
   Datagram related functions are applicable both to incoming and
   outgoing packets.  The functions are shown in Figure 6.

   int ipsec_set_msg_policy(const struct msghdr *msg,
                            const ipsec_policy_t *policy);
   int ipsec_get_msg_policy(const struct msghdr *msg,
                            ipsec_policy_t **policy);

                                 Figure 6

   Function ipsec_set_msg_policy applies the given policy to the msg
   data structure.  The policy of a msg can be queried using
   ipsec_get_msg_policy.  It allocates the memory required for the
   policy and returns it to the caller in policy double pointer.




Komu & Tarkoma          Expires September 7, 2007               [Page 7]


Internet-Draft                 IPsec APIs                     March 2007


   Both functions return zero on success and non-zero on failure.  XX
   FIX list error values here.

2.1.5.  Other Policy Related Functions

   An application is not allowed to read or write to policies directly.
   The same restriction applies also to comparison and byte-wise copying
   of policies.  Theses operations have their own accessor functions
   that are shown in Figure 7.

   int ipsec_cmp_policy(ipsec_policy_t *p1, ipsec_policy_t *p2);
   int ipsec_dup_policy(ipsec_policy_t *p, ipsec_policy_t **p_dup);

                                 Figure 7

   Function ipsec_cmp_policy inputs two policies, p1 and p2, and returns
   zero if they are equal.  Otherwise it returns non-zero.

   Function ipsec_dup_policy duplicates given policy p and writes it to
   p_dup.  The function allocates the memory for duplicated policy that
   the caller is responsible of freeing.

   Return value is zero on success and non-zero on failure.  XX list
   error values here.

2.2.  Channel Bindings

   Channel bindings are handled locally at the host, i.e., they are not
   communicated with a peer host.  The channel bindings allow the
   application to replace network layer authentication with, e.g., TLS
   certificates.  In addition, application can store the channel binding
   information and use it to verify that it is still talking to the same
   host in subsequent communications.

2.2.1.  Channel Creation

   Similarly to policies, also channel related information is stored in
   an opaque structure.  An application MUST not read or write directly
   channel information data structures, but rather use the accessor
   functions introduce in the following sections.  Typedef for channel
   information is shown in Figure 8.

   typedef ipsec_channel_info_t struct ipsec_channel_info;

                                 Figure 8

   Channel information data structures are created and initialized using
   ipsec_create_channel_info function.  Deallocation is handled through



Komu & Tarkoma          Expires September 7, 2007               [Page 8]


Internet-Draft                 IPsec APIs                     March 2007


   ipsec_free_channel_info function.  The functions are shown in
   Figure 9.

   ipsec_channel_info_t *ipsec_create_channel_info();
   int ipsec_free_channel_info(*ipsec_channel_info_t *ci);

                                 Figure 9

   Function ipsec_create_channel_info allocated memory for the channel
   information and returns it to the caller.  Upon failure, it returns
   NULL.

   ipsec_free_channel_info deallocates the given channel information
   data structure ci.  It returns zero on success and non-zero on
   failure.

2.2.2.  Channel Attributes

   The details of the channel information can be queried and set using
   the functions shown in Figure 10.

   int ipsec_set_channel_attr(ipsec_channel_info_t *ci,
                              uint32_t attr_type,
                              uint32_t attr_len,
                              const void *attr_val);
   int ipsec_get_channel_attr(const ipsec_channel_info_t *ci,
                              uint32_t attr_type,
                              uint32_t *attr_len,
                              void **attr_val);

                                 Figure 10

   Function ipsec_set_channel_attr writes the given channel attribute
   attr_val to the channel information ci.  The length and type of the
   attribute are passed in attr_type and attr_len.

   Function ipsec_get_channel_attr reads the channel attribute from ci,
   allocates memory for the attribute and writes the queried attribute
   (attr_type) to attr_val.  The function writes the length of the
   attribute to attr_len.

   Different attribute types along with lengths are shown in Table 3.









Komu & Tarkoma          Expires September 7, 2007               [Page 9]


Internet-Draft                 IPsec APIs                     March 2007


                             +----+----+----+
                             | xx | xx | xx |
                             +----+----+----+
                             | xx | xx | xx |
                             +----+----+----+

                                  Table 3

   Both of the attribute functions return zero on success and non-zero
   on failure.  The error values are listed in Table 4.

                                +----+----+
                                | xx | xx |
                                +----+----+
                                | xx | xx |
                                +----+----+

                                  Table 4

2.2.3.  Connection Oriented Communications

   With connection oriented sockets, an application can attach channel
   information to a socket with ipsec_set_socket_channel_info function.
   The channel information can be e.g. a TLS certificate.  In turn,
   ipsec_get_socket_channel_info function can be used to query the
   channel information attached to a socket.  The application can use
   this information to e.g. verify that it is talking to the same host
   as before.  Figure Figure 11 shows the get and set functions.

   int ipsec_set_socket_channel_info(int fd,
                                     const ipsec_channel_info_t *ci);
   int ipsec_get_socket_channel_info(int fd,
                                     ipsec_channel_info_t **ci);

                                 Figure 11

   Both of the functions input a socket descriptor fd.  Function
   ipsec_set_socket_channel_info inputs the channel information to be
   set in ci.  Function ipsec_get_socket_channel_info allocates memory
   for channel information and outputs it to ci.

   The functions return zero on success and non-zero on failure.  XX fix
   list error values here.

2.2.4.  Datagram Oriented Communications

   When an application uses sendmsg or recvmsg calls for datagram
   oriented communications, it can use the functions shown in Figure 12.



Komu & Tarkoma          Expires September 7, 2007              [Page 10]


Internet-Draft                 IPsec APIs                     March 2007


   Functions recvfrom and sendto are not supported.

   int ipsec_set_msg_channel_info(const struct *msg_hdr,
                                  const ipsec_channel_info_t *ci);
   int ipsec_get_msg_channel_info(const struct *msg_hdr,
                                  ipsec_channel_info_t **ci);

                                 Figure 12

   Function ipsec_set_msg_channel_info attaches the channel information
   ci into the msg_hdr.  Function ipsec_get_msg_channel_info reads
   channel information from msg_hdr, allocates memory for it and returns
   it in ci.

   Both functions return zero on success and non-zero on failure.  XX
   FIX list error values here.

2.2.5.  Other Channel Related Function

   Channel information is opaque and must be operated through accessor
   functions.  Channel information comparison, duplication and
   conversion functions are shown in Figure 13.

   int ipsec_cmp_channel_info(const ipsec_channel_info_t *ci1,
                              const ipsec_channel_info_t *ci2);
   int ipsec_dup_channel_info(const ipsec_channel_info_t *ci,
                              ipsec_channel_info_t **ci_dup);
   int ipsec_openssl_to_channel_info(const SSL *ssl,
                                     const ipsec_policy_t *policy,
                                     ipsec_channel_info_t **ci);

                                 Figure 13

   Function ipsec_cmp_channel_info compares channel information ci1 and
   ci2.  It returns zero when they are equal or non-zero when they are
   different.

   Channel information is duplicated using ipsec_dup_channel_info.  It
   inputs channel information ci and outputs the duplicated ci_dup.  The
   function reserves memory for the duplicated channel information.

   Return value is zero on success and non-zero on failure.  XX FIX list
   error values here.

   Function ipsec_openssl_to_channel_info converts an OpenSSL data
   structure ssl to channel information ci according to the rules in the
   given policy.  The function reserves memory for the created channel
   information.



Komu & Tarkoma          Expires September 7, 2007              [Page 11]


Internet-Draft                 IPsec APIs                     March 2007


   The function returns zero on success and non-zero on failure.  XX FIX
   list error values here.


3.  Security Considerations

   The BTNS Stand Alone mode allows applications to omit network layer
   authentication.  In this case, an application is using a higher level
   security mechanism, such as TLS, and thus the required level of
   security is maintained.  The application has the control and
   duplicate security techniques are not applied.

   The channel bindings allow applications to create and manage security
   channels.  Given that applications omit higher layer security
   techniques based on information in an existing policy and channel
   binding, there is a possibility for a security channel downgrade
   attack.  In this attack, another application modifies the current
   application's channel binding in such a way that the application
   believes that an authenticated IPsec security channel to be active
   eventhough there is no such channel.  If the application omits TLS or
   other higher level security mechanism, then there will not be a
   secured channel and transmitted data is exposed.


4.  IANA Considerations

   TBD


5.  Acknowledgements

   Thanks for Michael Richardson, Love Hoernquist Aestrand, Nicolas
   Williams and Julien Laganier for feedback, ideas and discussion on
   the topic.


Appendix A.  Appendix

Appendix A.1.  Code Examples

   This section shows code examples that illustrate the use of the APIs.
   Error value handling is not very verbose to keep the code length
   smaller.  In addition, the code snippets do not show e.g. address
   resolution at all.

int hello_conn_client(int domain,
                      int type,
                      int family,



Komu & Tarkoma          Expires September 7, 2007              [Page 12]


Internet-Draft                 IPsec APIs                     March 2007


                      const struct sockaddr *sockaddr,
                      socklen_t sockaddr_len,
                      ipsec_channel_info_t **old_channel)
{
    int sockfd = 0, err = 0, hello_len;
    unint32_t on = 1;
    ipsec_channel_info_t *channel_info = NULL;
    ipsec_policy_t *policy = NULL;
    char *hello = "hello world";
    ssize_t count;

    hello_len = strlen(hello);

    sockfd = socket(domain, type, family);
    if (sockfd < 0) {
        err = -1;
        goto out;
    }

    /* Set socket policy to allow btns in channel binding mode. This
       way, lower layer authentication can be omitted because we are
       using TLS with certificates for this connection */

    policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY);
    if (policy == 0)
        goto out_err;

    err = ipsec_set_policy_attr(policy, IPSEC_BTNS_STANDALONE,
                                sizeof(on), &on);
    if (err)
        goto out;

    err = ipsec_set_socket_policy(sockfd, policy);
    if (err)
        goto out;

    /* If we have contacted the peer before, we can ensure that the host
       is still the same by reusing the old channel binding */

    if (*old_channel) {
        err = ipsec_set_socket_channel_info(sockfd, *old_channel);
        if (err)
            goto out;
    }

    /* In the case of TCP, connect() triggers a TCP handshake that is
       protected by IPsec according to the policy */




Komu & Tarkoma          Expires September 7, 2007              [Page 13]


Internet-Draft                 IPsec APIs                     March 2007


    err = connect(sockfd, sockaddr, sockaddr_len);
    if (err)
        goto out;

    /* Store new channel bindings for subsequent communications */

    if (*old_channel == NULL) {
        /* Store channel information to the old_channel_info to check
           that the peer host is the still the same. */
        err = ipsec_dup_channel_info(channel_info, old_channel)
    }

    /* Send data protected using IPsec according to the policy. */

    count = send(sockfd, hello, hello_len, 0);
    if (count != hello_len) {
        err = -1;
        goto out;
    }

  out:
    if (channel_info)
        ipsec_free_channel_info(channel_info);
    if (sockfd)
        close(sockfd);
    if (policy)
        ipsec_free_policy(policy);

    return err;

}

               Figure 14: Connection Oriented Client Example


int hello_tls_conn_client(char *hostname,
                          int domain,
                          int type,
                          int family,
                          const struct sockaddr *sockaddr,
                          socklen_t sockaddr_len,
                          SSL_ctx *ctx,
                          ipsec_channel_info_t **old_channel)
{
    int sockfd = 0, err = 0, hello_len;
    unint32_t on = 1;
    ipsec_channel_info_t *channel_info = NULL;
    ipsec_policy_t *policy = NULL;



Komu & Tarkoma          Expires September 7, 2007              [Page 14]


Internet-Draft                 IPsec APIs                     March 2007


    char *hello = "hello world";
    SSL *ssl = NULL;
    BIO *bio = NULL;
    ssize_t count;

    hello_len = strlen(hello);

    sockfd = socket(domain, type, family);
    if (sockfd < 0) {
        err = -1;
        goto out;
    }

    /* Set socket policy to allow btns in channel binding mode. This
       way, lower layer authentication can be omitted because we are
       using TLS with certificates for this connection */
    policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY);
    if (policy == 0)
        goto out_err;

    err = ipsec_set_policy_attr(policy, IPSEC_BTNS_CHANNEL_BINDING,
                                sizeof(on), &on);
    if (err)
        goto out;

    err = ipsec_set_socket_policy(sockfd, policy);
    if (err)
        goto out;

    /* If we have contacted the peer before, we can ensure that the host
       is still the same by reusing the old channel binding */

    if (*old_channel) {
        err = ipsec_set_socket_channel_info(sockfd, *old_channel);
        if (err)
            goto out;
    }

    /* Do TCP handshake that is protected using IPsec according to the
       application's policy */

    err = connect(sockfd, sockaddr, sockaddr_len);
    if (err)
        goto out;

    /* Create ssl structure and associate sockfd to it. Do TLS
       handshake and verify server certificate. */




Komu & Tarkoma          Expires September 7, 2007              [Page 15]


Internet-Draft                 IPsec APIs                     March 2007


    ssl = SSL_new(ctx);
    if (ssl == NULL)
        goto out;

    bio = BIO_new_socket(sockfd, BIO_NOCLOSE);
    if (bio == NULL)
        goto out;

    SSL_set_bio(ssl, bio, bio);

    if (SSL_connect(ssl) &#65533;= 0)
        goto out;

    if (verify_server_cert(ssl, hostname))
        goto out;

    /* First connection attempt to the peer host. Get channel binding
       info from ssl according to the policy rules (the policy selects
       e.g. the certificate). Store it to verify subsequent
       communications */
    if (*old_channel == NULL) {
        err = ipsec_openssl_to_channel_info(ssl, policy, &channel_info);
        if (err)
            goto out;
        err = ipsec_dup_channel_info(channel_info, old_channel)
        if (err)
            goto out;
    }

    /* Encrypt and send the data. For simplicity, a for loop is
       omitted here that would ensure all bytes were sent */
    count = SSL_write(ssl, hello, hello_len);
    if (count != hello_len) {
        err = -1;
        goto out;
    }

  out:
    if (channel_info)
        ipsec_free_channel_info(channel_info);
    if (bio)
        BIO_free(bio)
    if (ssl)
        SSL_free(ssl);
    if (sockfd)
        close(sockfd);
    if (policy)
        ipsec_free_policy(policy);



Komu & Tarkoma          Expires September 7, 2007              [Page 16]


Internet-Draft                 IPsec APIs                     March 2007


    return err;

}

             Figure 15: Connection Oriented TLS Client Example


int hello_msg_client(int domain,
                     int type,
                     int family,
                     const struct msg_hdr *hello_msg,
                     ssize_t hello_len,
                     socklen_t sockaddr_len,
                     ipsec_channel_info_t **old_channel)
{
    int sockfd = 0, err = 0, hello_len;
    unint32_t on = 1;
    ipsec_channel_info_t *channel_info = NULL;
    ipsec_policy_t *policy = NULL;
    ssize_t count;

    sockfd = socket(domain, type, family);
    if (sockfd < 0) {
        err = -1;
        goto out;
    }

    /* Set socket policy to allow btns in channel binding mode. This
       way, lower layer authentication can be omitted because we are
       using TLS with certificates for this connection */

    policy = ipsec_new_policy(IPSEC_DEFAULT_POLICY);
    if (policy == 0)
        goto out_err;

    err = ipsec_set_policy_attr(policy, IPSEC_BTNS_STANDALONE,
                                sizeof(on), &on);
    if (err)
        goto out;

    /* Send data to the peer. Data and peer are both defined in the
       msg header. If a previous channel binding is provided, use it
       to ensure that we are still talking to the same host */

    if (*old_channel != NULL ) {
        err = ipsec_set_msg_policy(hello_msg, policy);
        if (err)
            goto out_err;



Komu & Tarkoma          Expires September 7, 2007              [Page 17]


Internet-Draft                 IPsec APIs                     March 2007


        err = ipsec_set_msg_channel_info(hello_msg, *old_channel);
        if (err)
            goto out_err;
    }

    count = sendmsg(sockfd, hello_msg, 0);
    if (count != hello_len) {
        err = -1;
        goto out;
    }

    /* If we just communicated with the peer for the first time, let's
       query and store the channel info for subsequent communications */

    if (*old_channel == NULL) {
        err = ipsec_get_msg_channel_info(hello_msg, &channel_info);
        if (err)
            goto out_err;
        err = ipsec_dup_channel_info(channel_info, old_channel);
    }

    /* Let's receive a message from the peer. Apply IPsec policy and
       reuse the previous channel binding to ensure that we are still
       talking to the same host. */

    err = ipsec_set_msg_policy(hello_msg, policy);
    if (err)
        goto out_err;

    err = ipsec_set_msg_channel_info(hello_msg, channel_info);
    if (err)
        goto out_err;

    count = recvmsg(sockfd, hello_msg, 0);
    if (count != hello_len) {
        err = -1;
        goto out;
    }

  out:
    if (channel_info)
        ipsec_free_channel_info(channel_info);
    if (sockfd)
        close(sockfd);
    if (policy)
        ipsec_free_policy(policy);

    return err;



Komu & Tarkoma          Expires September 7, 2007              [Page 18]


Internet-Draft                 IPsec APIs                     March 2007


}

                Figure 16: Datagram Oriented Client Example


6.  References

6.1.  Normative References

   [I-D.ietf-btns-ipsec-apireq]
              Richardson, M. and B. Sommerfeld, "Requirements for an
              IPsec API", draft-ietf-btns-ipsec-apireq-00 (work in
              progress), April 2006.

   [I-D.ietf-btns-prob-and-applic]
              Touch, J., "Problem and Applicability Statement for Better
              Than Nothing Security  (BTNS)",
              draft-ietf-btns-prob-and-applic-05 (work in progress),
              February 2007.

   [POSIX]    Institute of Electrical and Electronics Engineers, "IEEE
              Std. 1003.1-2001 Standard for Information Technology -
              Portable Operating System Interface (POSIX)", Dec 2001.

6.2.  Informative References

   [RFC2744]  Wray, J., "Generic Security Service API Version 2 :
              C-bindings", RFC 2744, January 2000.

   [RFC4346]  Dierks, T. and E. Rescorla, "The Transport Layer Security
              (TLS) Protocol Version 1.1", RFC 4346, April 2006.

   [RFC4422]  Melnikov, A. and K. Zeilenga, "Simple Authentication and
              Security Layer (SASL)", RFC 4422, June 2006.

















Komu & Tarkoma          Expires September 7, 2007              [Page 19]


Internet-Draft                 IPsec APIs                     March 2007


Authors' Addresses

   Miika Komu
   Helsinki Institute for Information Technology
   Tammasaarenkatu 3
   Helsinki
   Finland

   Phone: +358503841531
   Fax:   +35896949768
   Email: miika@iki.fi
   URI:   http://www.iki.fi/miika/


   Sasu Tarkoma
   Helsinki Institute for Information Technology
   Tammasaarenkatu 3
   Helsinki
   Finland

   Phone: +358503841517
   Fax:   +35896949768
   Email: sasu.tarkoma@hiit.fi
   URI:   http://www.cs.helsinki.fi/u/starkoma/



























Komu & Tarkoma          Expires September 7, 2007              [Page 20]


Internet-Draft                 IPsec APIs                     March 2007


Full Copyright Statement

   Copyright (C) The IETF Trust (2007).

   This document is subject to the rights, licenses and restrictions
   contained in BCP 78, and except as set forth therein, the authors
   retain all their rights.

   This document and the information contained herein are provided on an
   "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS
   OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY, THE IETF TRUST AND
   THE INTERNET ENGINEERING TASK FORCE DISCLAIM ALL WARRANTIES, EXPRESS
   OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF
   THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED
   WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.


Intellectual Property

   The IETF takes no position regarding the validity or scope of any
   Intellectual Property Rights or other rights that might be claimed to
   pertain to the implementation or use of the technology described in
   this document or the extent to which any license under such rights
   might or might not be available; nor does it represent that it has
   made any independent effort to identify any such rights.  Information
   on the procedures with respect to rights in RFC documents can be
   found in BCP 78 and BCP 79.

   Copies of IPR disclosures made to the IETF Secretariat and any
   assurances of licenses to be made available, or the result of an
   attempt made to obtain a general license or permission for the use of
   such proprietary rights by implementers or users of this
   specification can be obtained from the IETF on-line IPR repository at
   http://www.ietf.org/ipr.

   The IETF invites any interested party to bring to its attention any
   copyrights, patents or patent applications, or other proprietary
   rights that may cover technology that may be required to implement
   this standard.  Please address the information to the IETF at
   ietf-ipr@ietf.org.


Acknowledgment

   Funding for the RFC Editor function is provided by the IETF
   Administrative Support Activity (IASA).





Komu & Tarkoma          Expires September 7, 2007              [Page 21]