gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_3_1_0-40-gaa5afd1


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_3_1_0-40-gaa5afd1
Date: Thu, 30 Aug 2012 20:24:07 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=aa5afd19f79e4a45935e3db82ae5ffb4d4465f6c

The branch, master has been updated
       via  aa5afd19f79e4a45935e3db82ae5ffb4d4465f6c (commit)
       via  ca0c752397d8ae57ac832a7646d0abfde652753c (commit)
       via  a3d34117ed20f668ecf7024b6c63b9d6cb674beb (commit)
       via  0937303160d1e305eb5988363631af6757aa69a1 (commit)
       via  3f2e9a0d1231f2555626305b752f73c87afbe6f2 (commit)
       via  23934e9fe103c3026491b25255467637cc1df89f (commit)
       via  523d1d44a58e828552f0f2b6f71a1b0c3146b0cb (commit)
       via  fe33394de4ae9bd8cabbd5ef7666211ab5293a10 (commit)
       via  9c1536d514dd8332e724cfd5a722bd81e56a6b62 (commit)
      from  fb39830546a65c757f3aa473357098f9877dba87 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit aa5afd19f79e4a45935e3db82ae5ffb4d4465f6c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 22:19:52 2012 +0200

    Some small optimizations in heartbeat handling and regeneration of src/ 
args files.

commit ca0c752397d8ae57ac832a7646d0abfde652753c
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 20:21:16 2012 +0200

    removed unneeded test

commit a3d34117ed20f668ecf7024b6c63b9d6cb674beb
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 20:14:56 2012 +0200

    removed unneeded test.

commit 0937303160d1e305eb5988363631af6757aa69a1
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 20:10:20 2012 +0200

    BUFFER_APPEND_PFX is no more. Replaced with BUFFER_APPEND_PFX4

commit 3f2e9a0d1231f2555626305b752f73c87afbe6f2
Author: Olga <address@hidden>
Date:   Tue Aug 28 00:12:56 2012 +0200

    Added Heartbeat extension support.
    
    Signed-off-by: Nikos Mavrogiannopoulos <address@hidden>

commit 23934e9fe103c3026491b25255467637cc1df89f
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 20:02:18 2012 +0200

    corrected deinitialization of wmnaf cache.

commit 523d1d44a58e828552f0f2b6f71a1b0c3146b0cb
Author: Ilya Tumaykin <address@hidden>
Date:   Thu Aug 30 11:36:34 2012 +0400

    wMNAF-based multiplication
    
    Signed-off-by: Nikos Mavrogiannopoulos <address@hidden>

commit fe33394de4ae9bd8cabbd5ef7666211ab5293a10
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 19:50:24 2012 +0200

    Added extension in TODO list

commit 9c1536d514dd8332e724cfd5a722bd81e56a6b62
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Thu Aug 30 19:46:06 2012 +0200

    On Linux with /proc/sys/net/ipv6/bindv6only == 0 (which is now the
    default), gnutls-serv cannot listen on ipv6. Patch by Bernhard R. Link.

-----------------------------------------------------------------------

Summary of changes:
 doc/TODO                                 |    1 +
 doc/cha-internals.texi                   |   25 ++
 doc/cha-intro-tls.texi                   |   26 ++
 doc/manpages/Makefile.am                 |    1 +
 doc/protocol/rfc6520.txt                 |  507 +++++++++++++++++++++++++
 lib/debug.c                              |    2 +
 lib/ext/Makefile.am                      |    2 +-
 lib/ext/heartbeat.c                      |  464 +++++++++++++++++++++++
 lib/ext/heartbeat.h                      |   52 +++
 lib/ext/server_name.c                    |    2 +-
 lib/ext/session_ticket.c                 |    2 +-
 lib/ext/srp.c                            |    4 +-
 lib/gnutls_buffers.c                     |    6 +-
 lib/gnutls_errors.c                      |    5 +-
 lib/gnutls_extensions.c                  |    5 +
 lib/gnutls_global.c                      |    1 +
 lib/gnutls_global.h                      |    1 +
 lib/gnutls_int.h                         |    9 +-
 lib/gnutls_record.c                      |   22 +-
 lib/gnutls_record.h                      |    1 -
 lib/gnutls_session_pack.c                |   30 +-
 lib/gnutls_state.c                       |    3 +
 lib/gnutls_str.h                         |   28 ++-
 lib/includes/gnutls/gnutls.h.in          |   13 +
 lib/libgnutls.map                        |    5 +
 lib/nettle/Makefile.am                   |    8 +-
 lib/nettle/ecc.h                         |   45 ++-
 lib/nettle/ecc_make_key.c                |   13 +-
 lib/nettle/ecc_mulmod_wmnaf.c            |  165 +++++++++
 lib/nettle/ecc_mulmod_wmnaf_cached.c     |  457 +++++++++++++++++++++++
 lib/nettle/ecc_projective_add_point.c    |   41 ++-
 lib/nettle/ecc_projective_add_point_ng.c |  462 +++++++++++++++++++++++
 lib/nettle/ecc_projective_dbl_point_3.c  |  226 +++++++-----
 lib/nettle/ecc_projective_isneutral.c    |   81 ++++
 lib/nettle/ecc_projective_negate_point.c |   56 +++
 lib/nettle/ecc_shared_secret.c           |    2 +-
 lib/nettle/ecc_sign_hash.c               |    6 +-
 lib/nettle/ecc_verify_hash.c             |    9 +-
 lib/nettle/init.c                        |   12 +-
 lib/nettle/pk.c                          |   18 +-
 lib/nettle/wmnaf.c                       |  154 ++++++++
 src/cli-args.c                           |  593 ++++++++++++++++--------------
 src/cli-args.def                         |    7 +
 src/cli-args.h                           |  128 ++++----
 src/cli.c                                |    5 +-
 src/common.c                             |   21 +-
 src/serv-args.c                          |  413 +++++++++++----------
 src/serv-args.def                        |    7 +
 src/serv-args.h                          |   92 +++---
 src/serv.c                               |  276 ++++++++------
 src/socket.c                             |    4 +
 src/tests.c                              |   22 ++
 src/tests.h                              |    1 +
 src/tls_test.c                           |    1 +
 54 files changed, 3652 insertions(+), 890 deletions(-)
 create mode 100644 doc/protocol/rfc6520.txt
 create mode 100644 lib/ext/heartbeat.c
 create mode 100644 lib/ext/heartbeat.h
 create mode 100644 lib/nettle/ecc_mulmod_wmnaf.c
 create mode 100644 lib/nettle/ecc_mulmod_wmnaf_cached.c
 create mode 100644 lib/nettle/ecc_projective_add_point_ng.c
 create mode 100644 lib/nettle/ecc_projective_isneutral.c
 create mode 100644 lib/nettle/ecc_projective_negate_point.c
 create mode 100644 lib/nettle/wmnaf.c

diff --git a/doc/TODO b/doc/TODO
index 13764a8..bcb3199 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -5,6 +5,7 @@ in order to avoid having people working on the same thing.
 Current list:
 * When importing a PKCS #11 certificate, check for its issuers to generate a
   chain (e.g. use the DN to retrieve possible signers).
+* Added support for Certificate Status Request (OCSP) extension (RFC6066)
 * Improve AES assembly. AES in nettle can be improved in x86, arm and
   x86-64.
 * Add support for RSA-PSS. This signature algorithm is seen in some
diff --git a/doc/cha-internals.texi b/doc/cha-internals.texi
index 69ac8fa..e6a01a4 100644
--- a/doc/cha-internals.texi
+++ b/doc/cha-internals.texi
@@ -421,6 +421,31 @@ typedef enum
 @} gnutls_supplemental_data_format_type_t;
 @end example
 
address@hidden Heartbeat extension.
+
+One such extension is HeartBeat protocol (RFC6520:
address@hidden://tools.ietf.org/html/rfc6520}) implementation. To enable
+it use option --heartbeat with example client and server supplied with
+gnutls:
+
address@hidden
+./doc/credentials/gnutls-http-serv --priority "NORMAL:-CIPHER-ALL:+NULL" -d 
100 --heartbeat --echo
+./src/gnutls-cli --priority "NORMAL:-CIPHER-ALL:+NULL" -d 100 localhost -p 
5556 --insecure --heartbeat
address@hidden example
+
+After that pasting
address@hidden
+**HEARTBEAT**
address@hidden example
+command into gnutls-cli will trigger corresponding command on the server and 
it will send HeartBeat Request with random length to client.
+
+Another way is to run capabilities check with:
+
address@hidden
+./doc/credentials/gnutls-http-serv -d 100 --heartbeat
+./src/gnutls-cli-debug localhost -p 5556
address@hidden example
+
 @node Cryptographic Backend
 @section Cryptographic Backend
 Today most new processors, either for embedded or desktop systems
diff --git a/doc/cha-intro-tls.texi b/doc/cha-intro-tls.texi
index 3ab1d65..1f56ec5 100644
--- a/doc/cha-intro-tls.texi
+++ b/doc/cha-intro-tls.texi
@@ -379,6 +379,7 @@ in @acronym{GnuTLS} are:
 @item Maximum fragment length negotiation
 @item Server name indication
 @item Session tickets
address@hidden HeartBeat
 @item Safe Renegotiation
 @end itemize
 
@@ -388,6 +389,7 @@ and they will be discussed in the subsections that follow.
 * Maximum fragment length negotiation::
 * Server name indication::
 * Session tickets::
+* HeartBeat::
 * Safe renegotiation::
 @end menu
 
@@ -436,6 +438,30 @@ and authenticated with a key only known to the server and 
then sent to the
 client. The Session Tickets in RFC 5077 @xcite{TLSTKT}, describe this 
 idea, which is implemented in GnuTLS.
 
address@hidden HeartBeat
address@hidden HeartBeat
address@hidden TLS extensions
address@hidden heartbeat
+
+The TLS extension which allows to request response from the peer in a
+way similar to ping command described in @xcite{RFC6520}. This
+extension is disabled by default - user have to call
address@hidden to enable it. Note: this will set
+local policy affecting HeartBeat messages coming from the peer - the policy
+could be checked via @funcref{gnutls_heartbeat_enabled_local}. The
+same policy set by the peer for our messages could be checked via
address@hidden The requests coming from
+peer are answered automatically (if policy permits) inside
address@hidden, requests to peer could be send via
address@hidden or
address@hidden Each request triggers timeout
+which could be checked and manipulated with @funcref{gnutls_heartbeat_timeout}.
+
+Policy-related functions:
address@hidden,gnutls_heartbeat_deny}, 
@showfuncB{gnutls_heartbeat_enabled_local,gnutls_heartbeat_enabled_remote}
+Operational functions:
address@hidden,@showfuncB{gnutls_heartbeat_ping,gnutls_heartbeat_ping_rnd}
+
 @node Safe renegotiation
 @subsection Safe renegotiation
 @cindex renegotiation
diff --git a/doc/manpages/Makefile.am b/doc/manpages/Makefile.am
index d1572ef..5049254 100644
--- a/doc/manpages/Makefile.am
+++ b/doc/manpages/Makefile.am
@@ -281,6 +281,7 @@ APIMANS += gnutls_prf.3
 APIMANS += gnutls_prf_raw.3
 APIMANS += gnutls_server_name_set.3
 APIMANS += gnutls_server_name_get.3
+APIMANS += gnutls_heartbeat_policy_set.3
 APIMANS += gnutls_safe_renegotiation_status.3
 APIMANS += gnutls_supplemental_get_name.3
 APIMANS += gnutls_session_ticket_key_generate.3
diff --git a/doc/protocol/rfc6520.txt b/doc/protocol/rfc6520.txt
new file mode 100644
index 0000000..19329da
--- /dev/null
+++ b/doc/protocol/rfc6520.txt
@@ -0,0 +1,507 @@
+
+
+
+
+
+
+Internet Engineering Task Force (IETF)                     R. Seggelmann
+Request for Comments: 6520                                     M. Tuexen
+Category: Standards Track               Muenster Univ. of Appl. Sciences
+ISSN: 2070-1721                                              M. Williams
+                                                   GWhiz Arts & Sciences
+                                                           February 2012
+
+
+                   Transport Layer Security (TLS) and
+      Datagram Transport Layer Security (DTLS) Heartbeat Extension
+
+Abstract
+
+   This document describes the Heartbeat Extension for the Transport
+   Layer Security (TLS) and Datagram Transport Layer Security (DTLS)
+   protocols.
+
+   The Heartbeat Extension provides a new protocol for TLS/DTLS allowing
+   the usage of keep-alive functionality without performing a
+   renegotiation and a basis for path MTU (PMTU) discovery for DTLS.
+
+Status of This Memo
+
+   This is an Internet Standards Track document.
+
+   This document is a product of the Internet Engineering Task Force
+   (IETF).  It represents the consensus of the IETF community.  It has
+   received public review and has been approved for publication by the
+   Internet Engineering Steering Group (IESG).  Further information on
+   Internet Standards is available in Section 2 of RFC 5741.
+
+   Information about the current status of this document, any errata,
+   and how to provide feedback on it may be obtained at
+   http://www.rfc-editor.org/info/rfc6520.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 1]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+Copyright Notice
+
+   Copyright (c) 2012 IETF Trust and the persons identified as the
+   document authors.  All rights reserved.
+
+   This document is subject to BCP 78 and the IETF Trust's Legal
+   Provisions Relating to IETF Documents
+   (http://trustee.ietf.org/license-info) in effect on the date of
+   publication of this document.  Please review these documents
+   carefully, as they describe your rights and restrictions with respect
+   to this document.  Code Components extracted from this document must
+   include Simplified BSD License text as described in Section 4.e of
+   the Trust Legal Provisions and are provided without warranty as
+   described in the Simplified BSD License.
+
+Table of Contents
+
+   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . . . 2
+   2.  Heartbeat Hello Extension . . . . . . . . . . . . . . . . . . . 3
+   3.  Heartbeat Protocol  . . . . . . . . . . . . . . . . . . . . . . 4
+   4.  Heartbeat Request and Response Messages . . . . . . . . . . . . 5
+   5.  Use Cases . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
+   6.  IANA Considerations . . . . . . . . . . . . . . . . . . . . . . 7
+   7.  Security Considerations . . . . . . . . . . . . . . . . . . . . 7
+   8.  Acknowledgments . . . . . . . . . . . . . . . . . . . . . . . . 7
+   9.  References  . . . . . . . . . . . . . . . . . . . . . . . . . . 7
+
+1.  Introduction
+
+1.1.  Overview
+
+   This document describes the Heartbeat Extension for the Transport
+   Layer Security (TLS) and Datagram Transport Layer Security (DTLS)
+   protocols, as defined in [RFC5246] and [RFC6347] and their
+   adaptations to specific transport protocols described in [RFC3436],
+   [RFC5238], and [RFC6083].
+
+   DTLS is designed to secure traffic running on top of unreliable
+   transport protocols.  Usually, such protocols have no session
+   management.  The only mechanism available at the DTLS layer to figure
+   out if a peer is still alive is a costly renegotiation, particularly
+   when the application uses unidirectional traffic.  Furthermore, DTLS
+   needs to perform path MTU (PMTU) discovery but has no specific
+   message type to realize it without affecting the transfer of user
+   messages.
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 2]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+   TLS is based on reliable protocols, but there is not necessarily a
+   feature available to keep the connection alive without continuous
+   data transfer.
+
+   The Heartbeat Extension as described in this document overcomes these
+   limitations.  The user can use the new HeartbeatRequest message,
+   which has to be answered by the peer with a HeartbeartResponse
+   immediately.  To perform PMTU discovery, HeartbeatRequest messages
+   containing padding can be used as probe packets, as described in
+   [RFC4821].
+
+1.2.  Conventions
+
+   The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
+   "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
+   document are to be interpreted as described in [RFC2119].
+
+2.  Heartbeat Hello Extension
+
+   The support of Heartbeats is indicated with Hello Extensions.  A peer
+   cannot only indicate that its implementation supports Heartbeats, it
+   can also choose whether it is willing to receive HeartbeatRequest
+   messages and respond with HeartbeatResponse messages or only willing
+   to send HeartbeatRequest messages.  The former is indicated by using
+   peer_allowed_to_send as the HeartbeatMode; the latter is indicated by
+   using peer_not_allowed_to_send as the Heartbeat mode.  This decision
+   can be changed with every renegotiation.  HeartbeatRequest messages
+   MUST NOT be sent to a peer indicating peer_not_allowed_to_send.  If
+   an endpoint that has indicated peer_not_allowed_to_send receives a
+   HeartbeatRequest message, the endpoint SHOULD drop the message
+   silently and MAY send an unexpected_message Alert message.
+
+   The format of the Heartbeat Hello Extension is defined by:
+
+   enum {
+      peer_allowed_to_send(1),
+      peer_not_allowed_to_send(2),
+      (255)
+   } HeartbeatMode;
+
+   struct {
+      HeartbeatMode mode;
+   } HeartbeatExtension;
+
+   Upon reception of an unknown mode, an error Alert message using
+   illegal_parameter as its AlertDescription MUST be sent in response.
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 3]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+3.  Heartbeat Protocol
+
+   The Heartbeat protocol is a new protocol running on top of the Record
+   Layer.  The protocol itself consists of two message types:
+   HeartbeatRequest and HeartbeatResponse.
+
+   enum {
+      heartbeat_request(1),
+      heartbeat_response(2),
+      (255)
+   } HeartbeatMessageType;
+
+   A HeartbeatRequest message can arrive almost at any time during the
+   lifetime of a connection.  Whenever a HeartbeatRequest message is
+   received, it SHOULD be answered with a corresponding
+   HeartbeatResponse message.
+
+   However, a HeartbeatRequest message SHOULD NOT be sent during
+   handshakes.  If a handshake is initiated while a HeartbeatRequest is
+   still in flight, the sending peer MUST stop the DTLS retransmission
+   timer for it.  The receiving peer SHOULD discard the message
+   silently, if it arrives during the handshake.  In case of DTLS,
+   HeartbeatRequest messages from older epochs SHOULD be discarded.
+
+   There MUST NOT be more than one HeartbeatRequest message in flight at
+   a time.  A HeartbeatRequest message is considered to be in flight
+   until the corresponding HeartbeatResponse message is received, or
+   until the retransmit timer expires.
+
+   When using an unreliable transport protocol like the Datagram
+   Congestion Control Protocol (DCCP) or UDP, HeartbeatRequest messages
+   MUST be retransmitted using the simple timeout and retransmission
+   scheme DTLS uses for flights as described in Section 4.2.4 of
+   [RFC6347].  In particular, after a number of retransmissions without
+   receiving a corresponding HeartbeatResponse message having the
+   expected payload, the DTLS connection SHOULD be terminated.  The
+   threshold used for this SHOULD be the same as for DTLS handshake
+   messages.  Please note that after the timer supervising a
+   HeartbeatRequest messages expires, this message is no longer
+   considered in flight.  Therefore, the HeartbeatRequest message is
+   eligible for retransmission.  The retransmission scheme, in
+   combination with the restriction that only one HeartbeatRequest is
+   allowed to be in flight, ensures that congestion control is handled
+   appropriately in case of the transport protocol not providing one,
+   like in the case of DTLS over UDP.
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 4]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+   When using a reliable transport protocol like the Stream Control
+   Transmission Protocol (SCTP) or TCP, HeartbeatRequest messages only
+   need to be sent once.  The transport layer will handle
+   retransmissions.  If no corresponding HeartbeatResponse message has
+   been received after some amount of time, the DTLS/TLS connection MAY
+   be terminated by the application that initiated the sending of the
+   HeartbeatRequest message.
+
+4.  Heartbeat Request and Response Messages
+
+   The Heartbeat protocol messages consist of their type and an
+   arbitrary payload and padding.
+
+   struct {
+      HeartbeatMessageType type;
+      uint16 payload_length;
+      opaque payload[HeartbeatMessage.payload_length];
+      opaque padding[padding_length];
+   } HeartbeatMessage;
+
+   The total length of a HeartbeatMessage MUST NOT exceed 2^14 or
+   max_fragment_length when negotiated as defined in [RFC6066].
+
+   type:  The message type, either heartbeat_request or
+      heartbeat_response.
+
+   payload_length:  The length of the payload.
+
+   payload:  The payload consists of arbitrary content.
+
+   padding:  The padding is random content that MUST be ignored by the
+      receiver.  The length of a HeartbeatMessage is TLSPlaintext.length
+      for TLS and DTLSPlaintext.length for DTLS.  Furthermore, the
+      length of the type field is 1 byte, and the length of the
+      payload_length is 2.  Therefore, the padding_length is
+      TLSPlaintext.length - payload_length - 3 for TLS and
+      DTLSPlaintext.length - payload_length - 3 for DTLS.  The
+      padding_length MUST be at least 16.
+
+   The sender of a HeartbeatMessage MUST use a random padding of at
+   least 16 bytes.  The padding of a received HeartbeatMessage message
+   MUST be ignored.
+
+   If the payload_length of a received HeartbeatMessage is too large,
+   the received HeartbeatMessage MUST be discarded silently.
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 5]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+   When a HeartbeatRequest message is received and sending a
+   HeartbeatResponse is not prohibited as described elsewhere in this
+   document, the receiver MUST send a corresponding HeartbeatResponse
+   message carrying an exact copy of the payload of the received
+   HeartbeatRequest.
+
+   If a received HeartbeatResponse message does not contain the expected
+   payload, the message MUST be discarded silently.  If it does contain
+   the expected payload, the retransmission timer MUST be stopped.
+
+5.  Use Cases
+
+   Each endpoint sends HeartbeatRequest messages at a rate and with the
+   padding required for the particular use case.  The endpoint should
+   not expect its peer to send HeartbeatRequests.  The directions are
+   independent.
+
+5.1.  Path MTU Discovery
+
+   DTLS performs path MTU discovery as described in Section 4.1.1.1 of
+   [RFC6347].  A detailed description of how to perform path MTU
+   discovery is given in [RFC4821].  The necessary probe packets are the
+   HeartbeatRequest messages.
+
+   This method of using HeartbeatRequest messages for DTLS is similar to
+   the one for the Stream Control Transmission Protocol (SCTP) using the
+   padding chunk (PAD-chunk) defined in [RFC4820].
+
+5.2.  Liveliness Check
+
+   Sending HeartbeatRequest messages allows the sender to make sure that
+   it can reach the peer and the peer is alive.  Even in the case of
+   TLS/TCP, this allows a check at a much higher rate than the TCP keep-
+   alive feature would allow.
+
+   Besides making sure that the peer is still reachable, sending
+   HeartbeatRequest messages refreshes the NAT state of all involved
+   NATs.
+
+   HeartbeatRequest messages SHOULD only be sent after an idle period
+   that is at least multiple round-trip times long.  This idle period
+   SHOULD be configurable up to a period of multiple minutes and down to
+   a period of one second.  A default value for the idle period SHOULD
+   be configurable, but it SHOULD also be tunable on a per-peer basis.
+
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 6]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+6.  IANA Considerations
+
+   IANA has assigned the heartbeat content type (24) from the "TLS
+   ContentType Registry" as specified in [RFC5246].  The reference is to
+   RFC 6520.
+
+   IANA has created and now maintains a new registry for Heartbeat
+   Message Types.  The message types are numbers in the range from 0 to
+   255 (decimal).  IANA has assigned the heartbeat_request (1) and the
+   heartbeat_response (2) message types.  The values 0 and 255 should be
+   reserved.  This registry uses the Expert Review policy as described
+   in [RFC5226].  The reference is to RFC 6520.
+
+   IANA has assigned the heartbeat extension type (15) from the TLS
+   "ExtensionType Values" registry as specified in [RFC5246].  The
+   reference is to RFC 6520.
+
+   IANA has created and now maintains a new registry for Heartbeat
+   Modes.  The modes are numbers in the range from 0 to 255 (decimal).
+   IANA has assigned the peer_allowed_to_send (1) and the
+   peer_not_allowed_to_send (2) modes.  The values 0 and 255 should be
+   reserved.  This registry uses the Expert Review policy as described
+   in [RFC5226].  The reference is to RFC 6520.
+
+7.  Security Considerations
+
+   The security considerations of [RFC5246] and [RFC6347] apply to this
+   document.  This document does not introduce any new security
+   considerations.
+
+8.  Acknowledgments
+
+   The authors wish to thank Pasi Eronen, Adrian Farrel, Stephen
+   Farrell, Adam Langley, Nikos Mavrogiannopoulos, Tom Petch, Eric
+   Rescorla, Peter Saint-Andre, and Juho Vaehae-Herttua for their
+   invaluable comments.
+
+9.  References
+
+9.1.  Normative References
+
+   [RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
+              Requirement Levels", BCP 14, RFC 2119, March 1997.
+
+   [RFC5226]  Narten, T. and H. Alvestrand, "Guidelines for Writing an
+              IANA Considerations Section in RFCs", BCP 26, RFC 5226,
+              May 2008.
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 7]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+   [RFC5246]  Dierks, T. and E. Rescorla, "The Transport Layer Security
+              (TLS) Protocol Version 1.2", RFC 5246, August 2008.
+
+   [RFC6066]  Eastlake, D., "Transport Layer Security (TLS) Extensions:
+              Extension Definitions", RFC 6066, January 2011.
+
+   [RFC6347]  Rescorla, E. and N. Modadugu, "Datagram Transport Layer
+              Security Version 1.2", RFC 6347, January 2012.
+
+9.2.  Informative References
+
+   [RFC3436]  Jungmaier, A., Rescorla, E., and M. Tuexen, "Transport
+              Layer Security over Stream Control Transmission Protocol",
+              RFC 3436, December 2002.
+
+   [RFC4820]  Tuexen, M., Stewart, R., and P. Lei, "Padding Chunk and
+              Parameter for the Stream Control Transmission Protocol
+              (SCTP)", RFC 4820, March 2007.
+
+   [RFC4821]  Mathis, M. and J. Heffner, "Packetization Layer Path MTU
+              Discovery", RFC 4821, March 2007.
+
+   [RFC5238]  Phelan, T., "Datagram Transport Layer Security (DTLS) over
+              the Datagram Congestion Control Protocol (DCCP)",
+              RFC 5238, May 2008.
+
+   [RFC6083]  Tuexen, M., Seggelmann, R., and E. Rescorla, "Datagram
+              Transport Layer Security (DTLS) for Stream Control
+              Transmission Protocol (SCTP)", RFC 6083, January 2011.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 8]
+
+RFC 6520              TLS/DTLS Heartbeat Extension         February 2012
+
+
+Authors' Addresses
+
+   Robin Seggelmann
+   Muenster University of Applied Sciences
+   Stegerwaldstr. 39
+   48565 Steinfurt
+   DE
+
+   EMail: address@hidden
+
+
+   Michael Tuexen
+   Muenster University of Applied Sciences
+   Stegerwaldstr. 39
+   48565 Steinfurt
+   DE
+
+   EMail: address@hidden
+
+
+   Michael Glenn Williams
+   GWhiz Arts & Sciences
+   2885 Denise Court
+   Newbury Park, CA, 91320
+   USA
+
+   EMail: address@hidden
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Seggelmann, et al.           Standards Track                    [Page 9]
+
diff --git a/lib/debug.c b/lib/debug.c
index 1e5b0c6..4a8a13d 100644
--- a/lib/debug.c
+++ b/lib/debug.c
@@ -56,6 +56,8 @@ _gnutls_packet2str (content_type_t packet)
       return "Handshake";
     case GNUTLS_APPLICATION_DATA:
       return "Application Data";
+    case GNUTLS_HEARTBEAT:
+      return "HeartBeat";
     default:
       return "Unknown Packet";
     }
diff --git a/lib/ext/Makefile.am b/lib/ext/Makefile.am
index 0062d49..48a635e 100644
--- a/lib/ext/Makefile.am
+++ b/lib/ext/Makefile.am
@@ -38,4 +38,4 @@ libgnutls_ext_la_SOURCES = max_record.c cert_type.c \
        server_name.c signature.c safe_renegotiation.c \
        max_record.h cert_type.h server_name.h srp.h \
        session_ticket.h signature.h safe_renegotiation.h \
-       session_ticket.c srp.c ecc.c ecc.h
+       session_ticket.c srp.c ecc.c ecc.h heartbeat.c heartbeat.h
diff --git a/lib/ext/heartbeat.c b/lib/ext/heartbeat.c
new file mode 100644
index 0000000..677a91d
--- /dev/null
+++ b/lib/ext/heartbeat.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ *
+ * Author: Olga Smolenchuk
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <gnutls_errors.h>
+#include <gnutls_int.h>
+#include <gnutls_dtls.h>
+#include <gnutls_record.h>
+#include <ext/heartbeat.h>
+#include <gnutls_extensions.h>
+#include <random.h>
+
+/**
+  * gnutls_heartbeat_enable:
+  * @session: is a #gnutls_session_t structure.
+  * @type: one of %GNUTLS_HB_*
+  *
+  * This function will allow heartbeat messages to be
+  * received.
+  **/
+void
+gnutls_heartbeat_enable (gnutls_session_t session, unsigned int type)
+{
+  extension_priv_data_t epriv;
+
+  epriv.num = type;
+  _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_HEARTBEAT,
+                                epriv);
+}
+
+/*-
+ * Convenience helper:
+ *
+ * Returns:
+ * textual policy description or NULL.
+ -*/
+static inline const char *
+_gnutls_heartbeat (unsigned policy)
+{
+  if (policy & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
+    return "PEER ALLOWED TO SEND";
+  else if (policy & GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND)
+    return "PEER NOT ALLOWED TO SEND";
+  return "Unknown policy";
+}
+
+/**
+  * gnutls_heartbeat_allowed:
+  * @session: is a #gnutls_session_t structure.
+  * @type: non zero is for sending, and zero for receiving
+  *
+  * This function will check whether heartbeats are allowed
+  * in this session.
+  *
+  * Returns: Non zero if heartbeats are allowed.
+  *
+  **/
+int
+gnutls_heartbeat_allowed (gnutls_session_t session, unsigned int type)
+{
+  extension_priv_data_t epriv;
+
+  if (_gnutls_ext_get_session_data
+      (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
+    return 0;                   /* Not enabled */
+
+  if (type != 0)
+    {
+      if (epriv.num & LOCAL_ALLOWED_TO_SEND)
+        return 1;
+    }
+  else if (epriv.num & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
+    return 1;
+    
+  return 0;
+}
+
+static int
+heartbeat_allow_recv (gnutls_session_t session)
+{
+  return gnutls_heartbeat_allowed(session, 0);
+}
+
+static int
+heartbeat_allow_send (gnutls_session_t session)
+{
+  return gnutls_heartbeat_allowed(session, 1);
+}
+
+/**
+ * _gnutls_heartbeat_send_data:
+ * @session: is a #gnutls_session_t structure.
+ * @data: contains the data to send.
+ * @data_size: is the length of the data.
+ * @request: true if Request message is about to be send.
+ *
+ * This function has the similar semantics with gnutls_record_send() The only
+ * difference is that it uses GNUTLS_HEARTBEAT content type.
+ *
+ * This function send either HeartBeat request or response message
+ * with proper padding. It set timeout and timestamp without check - it's up to
+ * caller to make sure no messages are already in-flight and handle timeout 
expiration.
+ *
+ * Returns: The number of bytes sent, or a negative error code.  The
+ *   number of bytes sent might be less than @data_size.  The maximum
+ *   number of bytes this function can send in a single call depends
+ *   on the negotiated maximum record size.
+ **/
+ssize_t
+_gnutls_heartbeat_send_data (gnutls_session_t session, const void *data,
+                             size_t data_size, int request)
+{
+  int ret;
+  char pr[128];
+  gnutls_buffer_st response;
+  uint8_t payload[16];
+  uint8_t type = request ? HEARTBEAT_REQUEST : HEARTBEAT_RESPONSE;
+  _gnutls_buffer_init (&response);
+
+  ret = gnutls_rnd (GNUTLS_RND_RANDOM, payload, 16);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  BUFFER_APPEND (&response, &type, 1);
+  BUFFER_APPEND_PFX2 (&response, data, data_size);
+
+  BUFFER_APPEND (&response, payload, 16);
+  ret = _gnutls_send_int (session, GNUTLS_HEARTBEAT, -1,
+                          EPOCH_WRITE_CURRENT, response.data,
+                          response.length, MBUFFER_FLUSH);
+  if (request)
+    {
+      if (ret >= 0)
+        {
+          _gnutls_record_log
+              ("REC[%p]: HB %zu bytes sent OK [%d in packet], saved for 
response verification:%s\n",
+               session, data_size, ret, _gnutls_bin2hex ((uint8_t *) data,
+                                                         data_size, pr,
+                                                         sizeof (pr),
+                                                         NULL));
+          session->internals.dtls.heartbeat_timeout = HEARTBEAT_TIMEOUT;
+          gettime (&session->internals.dtls.heartbeat_sent);
+          _gnutls_buffer_reset (&session->internals.heartbeat_payload);
+          BUFFER_APPEND (&session->internals.heartbeat_payload, data,
+                         data_size);
+        }
+    }
+  _gnutls_record_log ("REC[%p]: HB sent: %d\n", session, ret);
+
+  _gnutls_buffer_clear (&response);
+  return gnutls_assert_val (ret);
+}
+
+/**
+ * gnutls_heartbeat_ping:
+ * @session: is a #gnutls_session_t structure.
+ * @data_size: is the length of the random data.
+ * @wait_for_it: wait for pong or timeout instead of returning
+ * immediately.
+ *
+ * This function has the similar semantics with gnutls_record_send().
+ * The only difference is that it uses GNUTLS_HEARTBEAT content type
+ * and auto-generate data to send.
+ *
+ * This function send HeartBeat request message with proper padding.
+ *
+ *
+ * Returns: The number of bytes sent, or a negative error code. The
+ *   number of bytes sent might be less than @data_size.  The maximum
+ *   number of bytes this function can send in a single call depends
+ *   on the negotiated maximum record size. GNUTLS_E_HEARTBEAT_FLIGHT
+ *   is returned if HB Request is alredy in flight.
+ **/
+ssize_t
+gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size)
+{
+  int ret = GNUTLS_E_HEARTBEAT_FLIGHT;
+
+  if (data_size > MAX_HEARTBEAT_LENGTH)
+    return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+  if (!heartbeat_allow_send (session))
+    return GNUTLS_E_INVALID_REQUEST;
+
+  _gnutls_record_log
+      ("REC[%p]: sending HB_REQUEST with length: %zu to peer\n",
+       session, data_size);
+
+  if (gnutls_heartbeat_timeout (session, 1) == GNUTLS_E_ILLEGAL_PARAMETER)
+    {
+      uint8_t data[data_size];
+      ret = _gnutls_rnd (GNUTLS_RND_NONCE, data, data_size);
+      if (ret >= 0)
+        ret = _gnutls_heartbeat_send_data (session, data, data_size, 1);
+    }
+  else
+    _gnutls_record_log
+        ("REC[%p]: HB_REQUEST with length %zu already in-flight: %d\n",
+         session, data_size, gnutls_heartbeat_timeout (session, 1));
+
+  return ret;
+}
+
+/**
+ * simple wrapper for ping with random length
+ **/
+ssize_t
+gnutls_heartbeat_ping_rnd (gnutls_session_t session)
+{
+  uint8_t rnd;
+  int ret;
+  
+  ret = gnutls_rnd (GNUTLS_RND_NONCE, &rnd, 1);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+  
+  return gnutls_heartbeat_ping (session, rnd + 1);
+}
+
+/**
+ * Process HB message in buffer.
+ * @bufel: the (suspected) HeartBeat message (TLV+padding)
+ *
+ * Returns:
+ * processing result
+ * GNUTLS_E_AGAIN if processed OK
+ * GNUTLS_E_HEARTBEAT_PONG_FAILED on response send failure for request message
+ * GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER on payload mismatch for response message
+ **/
+int
+_gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel)
+{
+  char pr[128];
+  uint8_t *msg = _mbuffer_get_udata_ptr (bufel);
+  size_t hb_len, len = _mbuffer_get_udata_size (bufel);
+
+  if (!heartbeat_allow_recv (session))
+    return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET);
+
+  if (len < 4)
+    return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+  hb_len = _gnutls_read_uint16 (msg + 1);
+  if (hb_len > len - 3)
+    return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET);
+
+  switch (msg[0])
+    {
+    case HEARTBEAT_REQUEST:
+      _gnutls_record_log
+          ("REC[%p]: received HEARTBEAT_REQUEST, responding...\n",
+           session);
+      if (_gnutls_heartbeat_send_data (session, msg + 3, hb_len, 0) >= 0)
+        return GNUTLS_E_AGAIN;  /* HB responded, no APP_DATA so needs to be 
called again */
+      else
+        {                       /* immediate response failed, TBD: save 
received data somewhere and let upper layers handle it, loosing single ping is 
non-critical for HB */
+          return GNUTLS_E_HEARTBEAT_PONG_FAILED;
+        }
+      break;
+
+    case HEARTBEAT_RESPONSE:
+
+      if (session->internals.heartbeat_payload.length != hb_len)
+        return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+      if (memcmp (msg + 3, session->internals.heartbeat_payload.data,
+                  hb_len) != 0)
+        {
+          _gnutls_record_log ("REC[%p]: HB: %s - received\n", session,
+                              _gnutls_bin2hex (msg + 3, hb_len, pr,
+                                               sizeof (pr), NULL));
+          _gnutls_record_log ("REC[%p]: HB: %s - expected\n", session,
+                              _gnutls_bin2hex (session->internals.
+                                               heartbeat_payload.data,
+                                               hb_len, pr, sizeof (pr),
+                                               NULL));
+          return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+        }
+      _gnutls_record_log
+          ("REC[%p]: HB: %zu response bytes received OK (%d msec. left before 
timeout)\n",
+           session, hb_len, gnutls_heartbeat_timeout (session, 1));
+
+      session->internals.dtls.heartbeat_timeout = HEARTBEAT_TIMEOUT;
+      _gnutls_buffer_reset (&session->internals.heartbeat_payload);
+      return GNUTLS_E_AGAIN;
+
+    default:
+      _gnutls_record_log
+          ("REC[%p]: HB: received unknown type %u\n",
+           session, msg[0]);
+      return gnutls_assert_val (GNUTLS_E_UNEXPECTED_PACKET);
+    }
+
+  return gnutls_assert_val (GNUTLS_E_INTERNAL_ERROR);
+}
+
+/**
+ * Update HB timeouts: should be called on retransmit to set new timeout.
+ * @check_only: guarantees lack of side-effects (no variables are written)
+ *
+ * Returns:
+ * number of milliseconds left before timeout expiration OR
+ * GNUTLS_E_TIMEDOUT if timeout expired
+ * GNUTLS_E_SUCCESS if timeout updated
+ * GNUTLS_E_ILLEGAL_PARAMETER if no HB message is in-flight
+ **/
+int
+gnutls_heartbeat_timeout (gnutls_session_t session, int check_only)
+{
+  struct timespec now;
+  unsigned int ms;
+  if (session->internals.heartbeat_payload.length)
+    {
+      _gnutls_debug_log
+          ("HB: %zu bytes are in-flight already: %u msec timeout.\n",
+           session->internals.heartbeat_payload.length,
+           (unsigned int) session->internals.dtls.heartbeat_timeout);
+      gettime (&now);
+      ms = _dtls_timespec_sub_ms (&now,
+                                  &session->internals.dtls.heartbeat_sent);
+      if (ms > session->internals.dtls.heartbeat_timeout)
+        {
+          if (check_only)
+            return GNUTLS_E_TIMEDOUT;
+          _gnutls_buffer_reset (&session->internals.heartbeat_payload);
+
+          if (session->internals.dtls.heartbeat_timeout * 2 >
+              MAX_HEARTBEAT_TIMEOUT)
+            {                   /* update impossible */
+              session->internals.dtls.heartbeat_timeout =
+                  HEARTBEAT_TIMEOUT;
+              return GNUTLS_E_TIMEDOUT;
+            }
+          else
+            {
+              session->internals.dtls.heartbeat_timeout *= 2;
+              gettime (&session->internals.dtls.heartbeat_sent);
+              return GNUTLS_E_SUCCESS;
+            }
+        }
+      else
+        {
+          return ms;
+        }
+    }
+  return GNUTLS_E_ILLEGAL_PARAMETER;
+}
+
+static int
+_gnutls_heartbeat_recv_params (gnutls_session_t session,
+                               const uint8_t * data, size_t _data_size)
+{
+  heartbeat_policy_t pol;
+  extension_priv_data_t epriv;
+
+  if (_gnutls_ext_get_session_data
+      (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
+    {
+      if (session->security_parameters.entity == GNUTLS_CLIENT)
+        return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+      return 0; /* Not enabled */
+    }
+
+  if (_data_size == 0)
+    return GNUTLS_E_UNEXPECTED_PACKET_LENGTH;
+
+  _gnutls_debug_log ("HB: received parameter %u (%zu bytes)\n",
+                     (unsigned)data[0], _data_size);
+
+  pol = epriv.num;
+
+  switch (data[0])
+    {
+    case 1:
+      pol |= LOCAL_ALLOWED_TO_SEND;
+      break;
+    case 2:
+      pol |= LOCAL_NOT_ALLOWED_TO_SEND;
+      break;
+    default:
+      return gnutls_assert_val (GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
+    }
+
+  epriv.num = pol;
+  _gnutls_ext_set_session_data (session, GNUTLS_EXTENSION_HEARTBEAT,
+                                epriv);
+
+  return 0;
+}
+
+static int
+_gnutls_heartbeat_send_params (gnutls_session_t session,
+                               gnutls_buffer_st * extdata)
+{
+  extension_priv_data_t epriv;
+  uint8_t p;
+
+  if (_gnutls_ext_get_session_data
+      (session, GNUTLS_EXTENSION_HEARTBEAT, &epriv) < 0)
+    return 0; /* nothing to send - not enabled */
+
+  if (epriv.num & GNUTLS_HB_PEER_ALLOWED_TO_SEND)
+    p = 1;
+  else if (epriv.num & GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND)
+    p = 2;
+
+  _gnutls_debug_log ("HB: sending parameter %u\n", (unsigned)p);
+  if (_gnutls_buffer_append_data (extdata, &p, 1) < 0)
+    return gnutls_assert_val (GNUTLS_E_MEMORY_ERROR);
+
+  return 1; /* number of bytes added for sending */
+}
+
+static int
+_gnutls_heartbeat_pack (extension_priv_data_t _priv, gnutls_buffer_st * ps)
+{
+  int ret;
+  BUFFER_APPEND_NUM (ps, _priv.num);
+  return GNUTLS_E_SUCCESS;
+}
+
+static int
+_gnutls_heartbeat_unpack (gnutls_buffer_st * ps,
+                          extension_priv_data_t * _priv)
+{
+  int ret;
+  extension_priv_data_t epriv;
+  BUFFER_POP_NUM (ps, epriv.num);
+  *_priv = epriv;
+  ret = 0;
+error:
+  return ret;
+}
+
+
+extension_entry_st ext_mod_heartbeat = {
+  .name = "HEARTBEAT",
+  .type = GNUTLS_EXTENSION_HEARTBEAT,
+  .parse_type = GNUTLS_EXT_TLS,
+
+  .recv_func = _gnutls_heartbeat_recv_params,
+  .send_func = _gnutls_heartbeat_send_params,
+  .pack_func = _gnutls_heartbeat_pack,
+  .unpack_func = _gnutls_heartbeat_unpack,
+  .deinit_func = NULL
+};
diff --git a/lib/ext/heartbeat.h b/lib/ext/heartbeat.h
new file mode 100644
index 0000000..7c4b299
--- /dev/null
+++ b/lib/ext/heartbeat.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2002-2012 Free Software Foundation, Inc.
+ *
+ * Author: Olga Smolenchuk
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#ifndef EXT_HEARTBEAT_H
+#define EXT_HEARTBEAT_H
+
+#include <gnutls_extensions.h>
+
+#define HEARTBEAT_REQUEST 1
+#define HEARTBEAT_RESPONSE 2
+
+#define MAX_HEARTBEAT_LENGTH 16384
+#define HEARTBEAT_TIMEOUT 1000
+#define MAX_HEARTBEAT_TIMEOUT 60000
+
+#define LOCAL_ALLOWED_TO_SEND (1<<2)
+#define LOCAL_NOT_ALLOWED_TO_SEND (1<<3)
+
+#define HEARTBEAT_DEFAULT_POLICY PEER_NOT_ALLOWED_TO_SEND
+
+extern extension_entry_st ext_mod_heartbeat;
+
+typedef uint8_t heartbeat_policy_t;
+
+int _gnutls_heartbeat_handle (gnutls_session_t session, mbuffer_st * bufel);
+ssize_t _gnutls_heartbeat_send_data (gnutls_session_t session,
+                                     const void *data, size_t data_size,
+                                     int request);
+ssize_t gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size);
+ssize_t gnutls_heartbeat_ping_rnd (gnutls_session_t session);
+int _gnutls_heartbeat_enabled (gnutls_session_t session, int local);
+int gnutls_heartbeat_timeout (gnutls_session_t session, int check_only);
+#endif
diff --git a/lib/ext/server_name.c b/lib/ext/server_name.c
index 91f5e88..005d80b 100644
--- a/lib/ext/server_name.c
+++ b/lib/ext/server_name.c
@@ -424,7 +424,7 @@ _gnutls_server_name_pack (extension_priv_data_t epriv, 
gnutls_buffer_st * ps)
   for (i = 0; i < priv->server_names_size; i++)
     {
       BUFFER_APPEND_NUM (ps, priv->server_names[i].type);
-      BUFFER_APPEND_PFX (ps, priv->server_names[i].name,
+      BUFFER_APPEND_PFX4 (ps, priv->server_names[i].name,
                          priv->server_names[i].name_length);
     }
   return 0;
diff --git a/lib/ext/session_ticket.c b/lib/ext/session_ticket.c
index 626c976..c94242c 100644
--- a/lib/ext/session_ticket.c
+++ b/lib/ext/session_ticket.c
@@ -422,7 +422,7 @@ session_ticket_pack (extension_priv_data_t epriv, 
gnutls_buffer_st * ps)
   session_ticket_ext_st *priv = epriv.ptr;
   int ret;
 
-  BUFFER_APPEND_PFX (ps, priv->session_ticket, priv->session_ticket_len);
+  BUFFER_APPEND_PFX4 (ps, priv->session_ticket, priv->session_ticket_len);
   BUFFER_APPEND_NUM (ps, priv->session_ticket_enable);
 
   return 0;
diff --git a/lib/ext/srp.c b/lib/ext/srp.c
index 54929ca..d8a3aae 100644
--- a/lib/ext/srp.c
+++ b/lib/ext/srp.c
@@ -226,8 +226,8 @@ _gnutls_srp_pack (extension_priv_data_t epriv, 
gnutls_buffer_st * ps)
   if (priv->password)
     password_len = strlen (priv->password);
 
-  BUFFER_APPEND_PFX (ps, priv->username, username_len);
-  BUFFER_APPEND_PFX (ps, priv->password, password_len);
+  BUFFER_APPEND_PFX4 (ps, priv->username, username_len);
+  BUFFER_APPEND_PFX4 (ps, priv->password, password_len);
 
   return 0;
 }
diff --git a/lib/gnutls_buffers.c b/lib/gnutls_buffers.c
index 973fb1c..c714519 100644
--- a/lib/gnutls_buffers.c
+++ b/lib/gnutls_buffers.c
@@ -61,8 +61,8 @@
  */
 #define MAX_QUEUE 32
 
-/* Buffers received packets of type APPLICATION DATA and
- * HANDSHAKE DATA.
+/* Buffers received packets of type APPLICATION DATA,
+ * HANDSHAKE DATA and HEARTBEAT.
  */
 int
 _gnutls_record_buffer_put (gnutls_session_t session,
@@ -132,7 +132,7 @@ mbuffer_st* bufel;
 
   memcpy(data, msg.data, length);
   _mbuffer_head_remove_bytes(&session->internals.record_buffer, length);
-  
+
   return length;
 }
 
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index d41ef2c..b43771f 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -93,7 +93,10 @@ static const gnutls_error_entry error_algorithms[] = {
                GNUTLS_E_NO_CERTIFICATE_FOUND, 1),
   ERROR_ENTRY (N_("The given DSA key is incompatible with the selected TLS 
protocol."),
                GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL, 1),
-
+  ERROR_ENTRY (N_("HeartBeat Response to Request has failed for some reason: 
pong dropped."),
+               GNUTLS_E_HEARTBEAT_PONG_FAILED, 1),
+  ERROR_ENTRY (N_("HeartBeat message is already in-flight."),
+               GNUTLS_E_HEARTBEAT_FLIGHT, 1),
   ERROR_ENTRY (N_("There is already a crypto algorithm with lower priority."),
                GNUTLS_E_CRYPTO_ALREADY_REGISTERED, 1),
 
diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c
index 42857d0..eb07d28 100644
--- a/lib/gnutls_extensions.c
+++ b/lib/gnutls_extensions.c
@@ -32,6 +32,7 @@
 #include <ext/cert_type.h>
 #include <ext/server_name.h>
 #include <ext/srp.h>
+#include <ext/heartbeat.h>
 #include <ext/session_ticket.h>
 #include <ext/safe_renegotiation.h>
 #include <ext/signature.h>
@@ -329,6 +330,10 @@ _gnutls_ext_init (void)
     return ret;
 #endif
 
+  ret = _gnutls_ext_register (&ext_mod_heartbeat);
+  if (ret != GNUTLS_E_SUCCESS)
+    return ret;
+
   ret = _gnutls_ext_register (&ext_mod_session_ticket);
   if (ret != GNUTLS_E_SUCCESS)
     return ret;
diff --git a/lib/gnutls_global.c b/lib/gnutls_global.c
index 3a71eae..8b84f46 100644
--- a/lib/gnutls_global.c
+++ b/lib/gnutls_global.c
@@ -295,6 +295,7 @@ gnutls_global_deinit (void)
   if (_gnutls_init == 1)
     {
       gl_sockets_cleanup ();
+      gnutls_crypto_deinit();
       _gnutls_rnd_deinit ();
       _gnutls_ext_deinit ();
       asn1_delete_structure (&_gnutls_gnutls_asn);
diff --git a/lib/gnutls_global.h b/lib/gnutls_global.h
index f92d321..4be3ca1 100644
--- a/lib/gnutls_global.h
+++ b/lib/gnutls_global.h
@@ -42,6 +42,7 @@ extern gnutls_log_func _gnutls_log_func;
 extern gnutls_audit_log_func _gnutls_audit_log_func;
 extern int _gnutls_log_level;
 extern int gnutls_crypto_init (void);
+extern void gnutls_crypto_deinit (void);
 void _gnutls_priority_prefer_aes_gcm(void);
 
 #endif
diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h
index 8da6978..8e1a811 100644
--- a/lib/gnutls_int.h
+++ b/lib/gnutls_int.h
@@ -246,6 +246,7 @@ typedef enum extensions_t
   GNUTLS_EXTENSION_SUPPORTED_ECC_PF = 11,
   GNUTLS_EXTENSION_SRP = 12,
   GNUTLS_EXTENSION_SIGNATURE_ALGORITHMS = 13,
+  GNUTLS_EXTENSION_HEARTBEAT = 15,
   GNUTLS_EXTENSION_SESSION_TICKET = 35,
   GNUTLS_EXTENSION_SAFE_RENEGOTIATION = 65281   /* aka: 0xff01 */
 } extensions_t;
@@ -261,6 +262,7 @@ typedef enum content_type_t
 {
   GNUTLS_CHANGE_CIPHER_SPEC = 20, GNUTLS_ALERT,
   GNUTLS_HANDSHAKE, GNUTLS_APPLICATION_DATA,
+  GNUTLS_HEARTBEAT
 } content_type_t;
 
 
@@ -648,7 +650,10 @@ typedef struct
    * has terminated. Required to handle retransmissions.
    */
   time_t async_term;
-  
+
+  struct timespec heartbeat_sent; /* timestamp: when last HeartBeat Request 
was sent*/
+  time_t heartbeat_timeout; /* current timeout, in milliseconds*/
+
   /* last retransmission triggered by record layer */
   struct timespec last_retransmit;
   unsigned int packets_dropped;
@@ -883,6 +888,8 @@ typedef struct
   unsigned int handshake_endtime; /* end time in seconds */
   unsigned int handshake_timeout_ms; /* timeout in milliseconds */
 
+  gnutls_buffer_st heartbeat_payload; /* store in-flight payload for heartbeat 
extension*/
+
   /* If you add anything here, check _gnutls_handshake_internal_state_clear().
    */
 } internals_st;
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 396a800..2a61633 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -46,9 +46,11 @@
 #include "gnutls_datum.h"
 #include "gnutls_constate.h"
 #include "ext/max_record.h"
+#include <ext/heartbeat.h>
 #include <gnutls_state.h>
 #include <gnutls_dtls.h>
 #include <gnutls_dh.h>
+#include <random.h>
 
 struct tls_record_st {
   uint16_t header_size;
@@ -485,6 +487,7 @@ check_recv_type (gnutls_session_t session, content_type_t 
recv_type)
     case GNUTLS_CHANGE_CIPHER_SPEC:
     case GNUTLS_ALERT:
     case GNUTLS_HANDSHAKE:
+    case GNUTLS_HEARTBEAT:
     case GNUTLS_APPLICATION_DATA:
       return 0;
     default:
@@ -505,6 +508,7 @@ check_buffers (gnutls_session_t session, content_type_t 
type,
 {
   if ((type == GNUTLS_APPLICATION_DATA ||
        type == GNUTLS_HANDSHAKE ||
+       type == GNUTLS_HEARTBEAT ||
        type == GNUTLS_CHANGE_CIPHER_SPEC)
       && _gnutls_record_buffer_get_size (session) > 0)
     {
@@ -587,6 +591,7 @@ record_add_to_buffers (gnutls_session_t session,
   if ((recv->type == type)
       && (type == GNUTLS_APPLICATION_DATA ||
           type == GNUTLS_CHANGE_CIPHER_SPEC ||
+         type == GNUTLS_HEARTBEAT ||
           type == GNUTLS_HANDSHAKE))
     {
       _gnutls_record_buffer_put (session, type, seq, bufel);
@@ -650,6 +655,11 @@ record_add_to_buffers (gnutls_session_t session,
           _gnutls_record_buffer_put (session, recv->type, seq, bufel);
 
           break;
+
+        case GNUTLS_HEARTBEAT:
+           ret = _gnutls_heartbeat_handle (session, bufel);
+           goto cleanup;
+
         case GNUTLS_APPLICATION_DATA:
           if (session->internals.initial_negotiation_completed == 0)
             {
@@ -683,6 +693,7 @@ record_add_to_buffers (gnutls_session_t session,
             }
 
           break;
+
         case GNUTLS_HANDSHAKE:
           /* In DTLS we might receive a handshake replay from the peer to 
indicate
            * the our last TLS handshake messages were not received.
@@ -747,8 +758,8 @@ record_add_to_buffers (gnutls_session_t session,
         default:
 
           _gnutls_record_log
-            ("REC[%p]: Received Unknown packet %d expecting %d\n",
-             session, recv->type, type);
+            ("REC[%p]: Received unexpected packet %d (%s) expecting %d (%s)\n",
+             session, recv->type, _gnutls_packet2str(recv->type), type, 
_gnutls_packet2str(type));
 
           gnutls_assert ();
           ret = GNUTLS_E_UNEXPECTED_PACKET;
@@ -1237,7 +1248,6 @@ _gnutls_recv_int (gnutls_session_t session, 
content_type_t type,
   return check_buffers (session, type, data, data_size, seq);
 }
 
-
 /**
  * gnutls_record_send:
  * @session: is a #gnutls_session_t structure.
@@ -1302,10 +1312,8 @@ gnutls_record_send (gnutls_session_t session, const void 
*data,
  * The number of bytes received might be less than the requested @data_size.
  **/
 ssize_t
-gnutls_record_recv (gnutls_session_t session, void *data, size_t data_size)
-{
-  return _gnutls_recv_int (session, GNUTLS_APPLICATION_DATA, -1, data,
-                           data_size, NULL);
+gnutls_record_recv (gnutls_session_t session, void *data, size_t data_size) {
+    return _gnutls_recv_int (session, GNUTLS_APPLICATION_DATA, -1, data, 
data_size, NULL);
 }
 
 /**
diff --git a/lib/gnutls_record.h b/lib/gnutls_record.h
index b171591..4151673 100644
--- a/lib/gnutls_record.h
+++ b/lib/gnutls_record.h
@@ -33,7 +33,6 @@ ssize_t _gnutls_send_int (gnutls_session_t session, 
content_type_t type,
 ssize_t _gnutls_recv_int (gnutls_session_t session, content_type_t type,
                           gnutls_handshake_description_t, uint8_t * data,
                           size_t sizeofdata, void* seq);
-
 int _gnutls_get_max_decrypted_data(gnutls_session_t session);
 
 #endif
diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c
index 2588873..9982622 100644
--- a/lib/gnutls_session_pack.c
+++ b/lib/gnutls_session_pack.c
@@ -311,20 +311,20 @@ pack_certificate_auth_info (gnutls_session_t session, 
gnutls_buffer_st * ps)
     {
 
       BUFFER_APPEND_NUM (ps, info->dh.secret_bits);
-      BUFFER_APPEND_PFX (ps, info->dh.prime.data, info->dh.prime.size);
-      BUFFER_APPEND_PFX (ps, info->dh.generator.data,
+      BUFFER_APPEND_PFX4 (ps, info->dh.prime.data, info->dh.prime.size);
+      BUFFER_APPEND_PFX4 (ps, info->dh.generator.data,
                          info->dh.generator.size);
-      BUFFER_APPEND_PFX (ps, info->dh.public_key.data,
+      BUFFER_APPEND_PFX4 (ps, info->dh.public_key.data,
                          info->dh.public_key.size);
-      BUFFER_APPEND_PFX (ps, info->rsa_export.modulus.data,
+      BUFFER_APPEND_PFX4 (ps, info->rsa_export.modulus.data,
                          info->rsa_export.modulus.size);
-      BUFFER_APPEND_PFX (ps, info->rsa_export.exponent.data,
+      BUFFER_APPEND_PFX4 (ps, info->rsa_export.exponent.data,
                          info->rsa_export.exponent.size);
 
       BUFFER_APPEND_NUM (ps, info->ncerts);
 
       for (i = 0; i < info->ncerts; i++)
-        BUFFER_APPEND_PFX (ps, info->raw_certificate_list[i].data,
+        BUFFER_APPEND_PFX4 (ps, info->raw_certificate_list[i].data,
                            info->raw_certificate_list[i].size);
     }
 
@@ -443,7 +443,7 @@ pack_srp_auth_info (gnutls_session_t session, 
gnutls_buffer_st * ps)
   BUFFER_APPEND_NUM (ps, 0);
   cur_size = ps->length;
 
-  BUFFER_APPEND_PFX (ps, info->username, len);
+  BUFFER_APPEND_PFX4 (ps, info->username, len);
 
   /* write the real size */
   _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset);
@@ -522,10 +522,10 @@ pack_anon_auth_info (gnutls_session_t session, 
gnutls_buffer_st * ps)
   if (info)
     {
       BUFFER_APPEND_NUM (ps, info->dh.secret_bits);
-      BUFFER_APPEND_PFX (ps, info->dh.prime.data, info->dh.prime.size);
-      BUFFER_APPEND_PFX (ps, info->dh.generator.data,
+      BUFFER_APPEND_PFX4 (ps, info->dh.prime.data, info->dh.prime.size);
+      BUFFER_APPEND_PFX4 (ps, info->dh.generator.data,
                          info->dh.generator.size);
-      BUFFER_APPEND_PFX (ps, info->dh.public_key.data,
+      BUFFER_APPEND_PFX4 (ps, info->dh.public_key.data,
                          info->dh.public_key.size);
     }
 
@@ -629,13 +629,13 @@ pack_psk_auth_info (gnutls_session_t session, 
gnutls_buffer_st * ps)
   BUFFER_APPEND_NUM (ps, 0);
   cur_size = ps->length;
 
-  BUFFER_APPEND_PFX (ps, info->username, username_len);
-  BUFFER_APPEND_PFX (ps, info->hint, hint_len);
+  BUFFER_APPEND_PFX4 (ps, info->username, username_len);
+  BUFFER_APPEND_PFX4 (ps, info->hint, hint_len);
 
   BUFFER_APPEND_NUM (ps, info->dh.secret_bits);
-  BUFFER_APPEND_PFX (ps, info->dh.prime.data, info->dh.prime.size);
-  BUFFER_APPEND_PFX (ps, info->dh.generator.data, info->dh.generator.size);
-  BUFFER_APPEND_PFX (ps, info->dh.public_key.data, info->dh.public_key.size);
+  BUFFER_APPEND_PFX4 (ps, info->dh.prime.data, info->dh.prime.size);
+  BUFFER_APPEND_PFX4 (ps, info->dh.generator.data, info->dh.generator.size);
+  BUFFER_APPEND_PFX4 (ps, info->dh.public_key.data, info->dh.public_key.size);
 
   /* write the real size */
   _gnutls_write_uint32 (ps->length - cur_size, ps->data + size_offset);
diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c
index c868d48..1009a8c 100644
--- a/lib/gnutls_state.c
+++ b/lib/gnutls_state.c
@@ -324,6 +324,7 @@ gnutls_init (gnutls_session_t * session, unsigned int flags)
 
   /* Initialize buffers */
   _gnutls_buffer_init (&(*session)->internals.handshake_hash_buffer);
+  _gnutls_buffer_init (&(*session)->internals.heartbeat_payload);
 
   _mbuffer_head_init (&(*session)->internals.record_buffer);
   _mbuffer_head_init (&(*session)->internals.record_send_buffer);
@@ -438,6 +439,8 @@ gnutls_deinit (gnutls_session_t session)
       }
 
   _gnutls_buffer_clear (&session->internals.handshake_hash_buffer);
+  _gnutls_buffer_clear (&session->internals.heartbeat_payload);
+
   _mbuffer_head_clear (&session->internals.record_buffer);
   _mbuffer_head_clear (&session->internals.record_recv_buffer);
   _mbuffer_head_clear (&session->internals.record_send_buffer);
diff --git a/lib/gnutls_str.h b/lib/gnutls_str.h
index a0fb44e..f8671c2 100644
--- a/lib/gnutls_str.h
+++ b/lib/gnutls_str.h
@@ -123,7 +123,8 @@ int _gnutls_hostname_compare (const char *certname, size_t 
certnamesize,
         } \
     }
 
-#define BUFFER_APPEND_PFX(b, x, s) { \
+/* append data prefixed with 4-bytes length field*/
+#define BUFFER_APPEND_PFX4(b, x, s) { \
         ret = _gnutls_buffer_append_data_prefix(b, 32, x, s); \
         if (ret < 0) { \
             gnutls_assert(); \
@@ -131,6 +132,30 @@ int _gnutls_hostname_compare (const char *certname, size_t 
certnamesize,
         } \
     }
 
+#define BUFFER_APPEND_PFX3(b, x, s) { \
+        ret = _gnutls_buffer_append_data_prefix(b, 24, x, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
+#define BUFFER_APPEND_PFX2(b, x, s) { \
+        ret = _gnutls_buffer_append_data_prefix(b, 16, x, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
+#define BUFFER_APPEND_PFX1(b, x, s) { \
+        ret = _gnutls_buffer_append_data_prefix(b, 8, x, s); \
+        if (ret < 0) { \
+            gnutls_assert(); \
+            return ret; \
+        } \
+    }
+
 #define BUFFER_APPEND_NUM(b, s) { \
         ret = _gnutls_buffer_append_prefix(b, 32, s); \
         if (ret < 0) { \
@@ -139,7 +164,6 @@ int _gnutls_hostname_compare (const char *certname, size_t 
certnamesize,
         } \
     }
 
-
 #define BUFFER_POP(b, x, s) { \
         size_t is = s; \
         _gnutls_buffer_pop_data(b, x, &is); \
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index ec67403..53cdfa9 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -856,6 +856,8 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t 
session);
 
 /* Record layer functions.
  */
+  ssize_t gnutls_heartbeat_ping (gnutls_session_t session, size_t data_size);
+  ssize_t gnutls_heartbeat_ping_rnd (gnutls_session_t session);
   ssize_t gnutls_record_send (gnutls_session_t session, const void *data,
                               size_t data_size);
   ssize_t gnutls_record_recv (gnutls_session_t session, void *data,
@@ -906,6 +908,14 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t 
session);
                               void *data, size_t * data_length,
                               unsigned int *type, unsigned int indx);
 
+#define GNUTLS_HB_PEER_ALLOWED_TO_SEND (1)
+#define GNUTLS_HB_PEER_NOT_ALLOWED_TO_SEND (1<<1)
+
+    /* Heartbeat */
+    void gnutls_heartbeat_enable (gnutls_session_t session, unsigned int type);
+    int gnutls_heartbeat_allowed (gnutls_session_t session, unsigned int type);
+    int gnutls_heartbeat_timeout (gnutls_session_t session, int check_only);
+
   /* Safe renegotiation */
   int gnutls_safe_renegotiation_status (gnutls_session_t session);
 
@@ -1966,6 +1976,9 @@ typedef int (*gnutls_pin_callback_t) (void *userdata, int 
attempt,
 #define GNUTLS_E_OPENPGP_PREFERRED_KEY_ERROR -215
 #define GNUTLS_E_INCOMPAT_DSA_KEY_WITH_TLS_PROTOCOL -216
 
+#define GNUTLS_E_HEARTBEAT_FLIGHT -298
+#define GNUTLS_E_HEARTBEAT_PONG_FAILED -299
+
 /* PKCS11 related */
 #define GNUTLS_E_PKCS11_ERROR -300
 #define GNUTLS_E_PKCS11_LOAD_ERROR -301
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index 50a6872..0bac577 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -301,6 +301,8 @@ GNUTLS_1_4
     gnutls_record_recv;
     gnutls_record_send;
     gnutls_record_set_max_size;
+    gnutls_heartbeat_ping;
+    gnutls_heartbeat_ping_rnd;
     gnutls_rehandshake;
     gnutls_rsa_export_get_modulus_bits;
     gnutls_rsa_export_get_pubkey;
@@ -333,6 +335,9 @@ GNUTLS_1_4
     gnutls_sign_get_id;
     gnutls_sign_get_name;
     gnutls_sign_list;
+    gnutls_heartbeat_enable;
+    gnutls_heartbeat_allowed;
+    gnutls_heartbeat_timeout;
     gnutls_srp_1024_group_generator;
     gnutls_srp_1024_group_prime;
     gnutls_srp_1536_group_generator;
diff --git a/lib/nettle/Makefile.am b/lib/nettle/Makefile.am
index 71d7802..313a69d 100644
--- a/lib/nettle/Makefile.am
+++ b/lib/nettle/Makefile.am
@@ -34,7 +34,9 @@ endif
 noinst_LTLIBRARIES = libcrypto.la
 
 libcrypto_la_SOURCES = pk.c mpi.c mac.c cipher.c rnd.c init.c egd.c egd.h \
-       multi.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \
-       ecc_map.c ecc_mulmod.c ecc_points.c ecc_projective_dbl_point_3.c \
-       ecc_projective_add_point.c ecc_projective_check_point.c \
+       multi.c wmnaf.c ecc_free.c ecc.h ecc_make_key.c ecc_shared_secret.c \
+       ecc_map.c ecc_mulmod.c ecc_mulmod_wmnaf.c ecc_mulmod_wmnaf_cached.c \
+       ecc_points.c ecc_projective_dbl_point_3.c ecc_projective_isneutral.c \
+       ecc_projective_check_point.c ecc_projective_negate_point.c \
+       ecc_projective_add_point.c ecc_projective_add_point_ng.c \
        ecc_sign_hash.c ecc_verify_hash.c gnettle.h ecc_mulmod_timing.c
diff --git a/lib/nettle/ecc.h b/lib/nettle/ecc.h
index 0925216..44adffb 100644
--- a/lib/nettle/ecc.h
+++ b/lib/nettle/ecc.h
@@ -42,6 +42,13 @@
 /* max private key size */
 #define ECC_MAXSIZE  66
 
+/* wMNAF window size */
+#define WMNAF_WINSIZE 4
+
+/* length of a single array of precomputed values for wMNAF
+ * we have two such arrays for positive and negative multipliers */
+#define WMNAF_PRECOMPUTED_LENGTH (1 << (WMNAF_WINSIZE - 1))
+
 /** Structure defines a NIST GF(p) curve */
 typedef struct {
    /** The size of the curve in octets */
@@ -61,10 +68,10 @@ typedef struct {
 
    /** The order of the curve (hex) */
    const char *order;
-  
+
    /** The x co-ordinate of the base point on the curve (hex) */
    const char *Gx;
- 
+
    /** The y co-ordinate of the base point on the curve (hex) */
    const char *Gy;
 } ecc_set_type;
@@ -103,36 +110,56 @@ typedef struct {
 void ecc_sizes(int *low, int *high);
 int  ecc_get_size(ecc_key *key);
 
-int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, 
const ecc_set_type *dp);
-int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, 
mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy, int timing_res);
+int ecc_make_key(void *random_ctx, nettle_random_func random, ecc_key *key, 
const ecc_set_type *dp, gnutls_ecc_curve_t id);
+int ecc_make_key_ex(void *random_ctx, nettle_random_func random, ecc_key *key, 
mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t Gy, 
gnutls_ecc_curve_t id, int timing_res);
 void ecc_free(ecc_key *key);
 
-int  ecc_shared_secret(ecc_key *private_key, ecc_key *public_key, 
+int  ecc_shared_secret(ecc_key *private_key, ecc_key *public_key,
                        unsigned char *out, unsigned long *outlen);
 
-int ecc_sign_hash(const unsigned char *in,  unsigned long inlen, 
+int ecc_sign_hash(const unsigned char *in,  unsigned long inlen,
                         struct dsa_signature *signature,
-                        void *random_ctx, nettle_random_func random, ecc_key 
*key);
+                        void *random_ctx, nettle_random_func random,
+                        ecc_key *key, gnutls_ecc_curve_t id);
 
 int  ecc_verify_hash(struct dsa_signature * signature,
-                     const unsigned char *hash, unsigned long hashlen, 
-                     int *stat, ecc_key *key);
+                     const unsigned char *hash, unsigned long hashlen,
+                     int *stat, ecc_key *key, gnutls_ecc_curve_t id);
 
 /* low level functions */
 ecc_point *ecc_new_point(void);
 void       ecc_del_point(ecc_point *p);
 
 /* point ops (mp == montgomery digit) */
+/* R = -P */
+int ecc_projective_negate_point(ecc_point *P, ecc_point *R, mpz_t modulus);
+
 /* R = 2P */
 int ecc_projective_dbl_point(ecc_point *P, ecc_point *R, mpz_t a,  mpz_t 
modulus);
 
 /* R = P + Q */
 int ecc_projective_add_point(ecc_point *P, ecc_point *Q, ecc_point *R, mpz_t 
A, mpz_t modulus);
+int ecc_projective_add_point_ng(ecc_point *P, ecc_point *Q, ecc_point *R, 
mpz_t A, mpz_t modulus);
+int ecc_projective_madd (ecc_point* P, ecc_point* Q, ecc_point* R, mpz_t a, 
mpz_t modulus);
 
 /* R = kG */
 int ecc_mulmod(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t modulus, 
int map);
 int ecc_mulmod_timing(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t 
modulus, int map);
 
+/* wMNAF-based mulmod */
+signed char* ecc_wMNAF(mpz_t x, size_t *ret_len);
+int ecc_mulmod_wmnaf(mpz_t k, ecc_point *G, ecc_point *R, mpz_t a, mpz_t 
modulus, int map);
+
+/* cache-enabled wMNAF-based mulmod */
+int  ecc_wmnaf_cache_init(void);
+void ecc_wmnaf_cache_free(void);
+int ecc_mulmod_wmnaf_cached (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R, 
mpz_t a, mpz_t modulus, int map);
+int ecc_mulmod_wmnaf_cached_timing (mpz_t k, gnutls_ecc_curve_t id, ecc_point 
* R, mpz_t a, mpz_t modulus, int map);
+int ecc_mulmod_wmnaf_cached_lookup (mpz_t k, ecc_point *G, ecc_point *R, mpz_t 
a, mpz_t modulus, int map);
+
+/* check if the given point is neutral point */
+int ecc_projective_isneutral(ecc_point *P, mpz_t modulus);
+
 /* map P to affine from projective */
 int ecc_map(ecc_point *P, mpz_t modulus);
 
diff --git a/lib/nettle/ecc_make_key.c b/lib/nettle/ecc_make_key.c
index 6886846..8c777da 100644
--- a/lib/nettle/ecc_make_key.c
+++ b/lib/nettle/ecc_make_key.c
@@ -38,6 +38,7 @@
   @param A            The "a" parameter of the curve
   @param Gx           The x coordinate of the base point
   @param Gy           The y coordinate of the base point
+  @param curve_id     The id of the curve we are working with
   @timing_res         If non zero the function will try to return in constant 
time.
   @return 0 if successful, upon error all allocated memory will be freed
 */
@@ -45,7 +46,7 @@
 int
 ecc_make_key_ex (void *random_ctx, nettle_random_func random, ecc_key * key,
                  mpz_t prime, mpz_t order, mpz_t A, mpz_t B, mpz_t Gx, mpz_t 
Gy,
-                 int timing_res)
+                 gnutls_ecc_curve_t curve_id, int timing_res)
 {
   int err;
   ecc_point *base;
@@ -92,7 +93,7 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func random, 
ecc_key * key,
   mpz_set (base->x, key->Gx);
   mpz_set (base->y, key->Gy);
   mpz_set_ui (base->z, 1);
-  
+
   nettle_mpz_set_str_256_u (key->k, keysize, buf);
 
   /* the key should be smaller than the order of base point */
@@ -102,9 +103,9 @@ ecc_make_key_ex (void *random_ctx, nettle_random_func 
random, ecc_key * key,
     }
   /* make the public key */
   if (timing_res)
-    err = ecc_mulmod_timing (key->k, base, &key->pubkey, key->A, key->prime, 
1);
+    err = ecc_mulmod_wmnaf_cached_timing (key->k, curve_id, &key->pubkey, 
key->A, key->prime, 1);
   else
-    err = ecc_mulmod (key->k, base, &key->pubkey, key->A, key->prime, 1);
+    err = ecc_mulmod_wmnaf_cached (key->k, curve_id, &key->pubkey, key->A, 
key->prime, 1);
 
   if (err != 0)
     goto errkey;
@@ -127,7 +128,7 @@ ERR_BUF:
 
 int
 ecc_make_key (void *random_ctx, nettle_random_func random, ecc_key * key,
-              const ecc_set_type * dp)
+              const ecc_set_type * dp, gnutls_ecc_curve_t curve_id)
 {
   mpz_t prime, order, Gx, Gy, A, B;
   int err;
@@ -146,7 +147,7 @@ ecc_make_key (void *random_ctx, nettle_random_func random, 
ecc_key * key,
   mpz_set_str (A, (char *) dp->A, 16);
   mpz_set_str (B, (char *) dp->B, 16);
 
-  err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy, 
0);
+  err = ecc_make_key_ex (random_ctx, random, key, prime, order, A, B, Gx, Gy, 
curve_id, 0);
 
   mp_clear_multi (&prime, &order, &A, &B, &Gx, &Gy, NULL);
 cleanup:
diff --git a/lib/nettle/ecc_mulmod_wmnaf.c b/lib/nettle/ecc_mulmod_wmnaf.c
new file mode 100644
index 0000000..87d6a38
--- /dev/null
+++ b/lib/nettle/ecc_mulmod_wmnaf.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "ecc.h"
+
+
+/*
+   Perform a point multiplication using wMNAF representation
+   @param k    The scalar to multiply by
+   @param G    The base point
+   @param R    [out] Destination for kG
+   @param a        The curve's A value
+   @param modulus  The modulus of the field the ECC curve is in
+   @param map      Boolean whether to map back to affine or not (1 == map, 0 
== leave in projective)
+   @return     GNUTLS_E_SUCCESS on success
+*/
+int
+ecc_mulmod_wmnaf (mpz_t k, ecc_point * G, ecc_point * R, mpz_t a,
+                  mpz_t modulus, int map)
+{
+  ecc_point *pos[WMNAF_PRECOMPUTED_LENGTH], *neg[WMNAF_PRECOMPUTED_LENGTH];
+  int i, j, err;
+
+  signed char *wmnaf = NULL;
+  size_t wmnaf_len;
+  signed char digit;
+
+  if (k == NULL || G == NULL || R == NULL || modulus == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* alloc ram for precomputed values */
+  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
+    {
+      pos[i] = ecc_new_point ();
+      neg[i] = ecc_new_point ();
+      if (pos[i] == NULL || neg[i] == NULL)
+        {
+          for (j = 0; j < i; ++j)
+            {
+              ecc_del_point (pos[j]);
+              ecc_del_point (neg[j]);
+            }
+
+          return GNUTLS_E_MEMORY_ERROR;
+        }
+    }
+
+  /* fill in pos and neg arrays with precomputed values
+   * pos holds kG for k ==  1, 3, 5, ..., (2^w - 1)
+   * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1)
+   */
+
+  /* pos[0] == 2G for a while, later it will be set to the expected 1G */
+  if ((err = ecc_projective_dbl_point (G, pos[0], a, modulus)) != 0)
+    goto done;
+
+  /* pos[1] == 3G */
+  if ((err =
+       ecc_projective_add_point_ng (pos[0], G, pos[1], a, modulus)) != 0)
+    goto done;
+
+  /* fill in kG for k = 5, 7, ..., (2^w - 1) */
+  for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
+    {
+      if ((err =
+           ecc_projective_add_point_ng (pos[j - 1], pos[0], pos[j], a,
+                                        modulus)) != 0)
+        goto done;
+    }
+
+  /* set pos[0] == 1G as expected
+   * after this step we don't need G at all 
+   * and can change it without worries even if R == G */
+  mpz_set (pos[0]->x, G->x);
+  mpz_set (pos[0]->y, G->y);
+  mpz_set (pos[0]->z, G->z);
+
+  /* neg[i] == -pos[i] */
+  for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
+    {
+      if ((err = ecc_projective_negate_point (pos[j], neg[j], modulus)) != 0)
+        goto done;
+    }
+
+  /* calculate wMNAF */
+  wmnaf = ecc_wMNAF (k, &wmnaf_len);
+  if (!wmnaf)
+    {
+      err = GNUTLS_E_INTERNAL_ERROR;
+      goto done;
+    }
+
+  /* actual point computation */
+
+  /* set R to neutral */
+  mpz_set_ui (R->x, 1);
+  mpz_set_ui (R->y, 1);
+  mpz_set_ui (R->z, 0);
+
+  /* perform ops */
+  for (j = wmnaf_len - 1; j >= 0; --j)
+    {
+      if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0)
+        goto done;
+
+      digit = wmnaf[j];
+
+      if (digit)
+        {
+          if (digit > 0)
+            {
+              if ((err =
+                   ecc_projective_add_point_ng (R, pos[(digit / 2)], R, a,
+                                                modulus)) != 0)
+                goto done;
+            }
+          else
+            {
+              if ((err =
+                   ecc_projective_add_point_ng (R, neg[(-digit / 2)], R, a,
+                                                modulus)) != 0)
+                goto done;
+            }
+        }
+    }
+
+
+  /* map R back from projective space */
+  if (map)
+    {
+      err = ecc_map (R, modulus);
+    }
+  else
+    {
+      err = GNUTLS_E_SUCCESS;
+    }
+done:
+  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
+    {
+      ecc_del_point (pos[i]);
+      ecc_del_point (neg[i]);
+    }
+  if (wmnaf)
+    free (wmnaf);
+  return err;
+}
diff --git a/lib/nettle/ecc_mulmod_wmnaf_cached.c 
b/lib/nettle/ecc_mulmod_wmnaf_cached.c
new file mode 100644
index 0000000..e75b884
--- /dev/null
+++ b/lib/nettle/ecc_mulmod_wmnaf_cached.c
@@ -0,0 +1,457 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+/* needed for gnutls_* types */
+#include <gnutls_int.h>
+#include <algorithms.h>
+
+#include "ecc.h"
+
+
+/* per-curve cache structure */
+typedef struct
+{
+  /* curve's id */
+  gnutls_ecc_curve_t id;
+
+    /** The array of positive multipliers of G */
+  ecc_point *pos[WMNAF_PRECOMPUTED_LENGTH];
+
+    /** The array of negative multipliers of G */
+  ecc_point *neg[WMNAF_PRECOMPUTED_LENGTH];
+} gnutls_ecc_curve_cache_entry_t;
+
+/* global cache */
+static gnutls_ecc_curve_cache_entry_t *ecc_wmnaf_cache = NULL;
+
+/* free single cache entry */
+static void
+_ecc_wmnaf_cache_entry_free (gnutls_ecc_curve_cache_entry_t * p)
+{
+  int i;
+
+  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
+    {
+      ecc_del_point (p->pos[i]);
+      ecc_del_point (p->neg[i]);
+    }
+}
+
+/* free curves caches */
+void
+ecc_wmnaf_cache_free (void)
+{
+  gnutls_ecc_curve_cache_entry_t *p = ecc_wmnaf_cache;
+  if (p)
+    {
+      for (; p->id != GNUTLS_ECC_CURVE_INVALID; ++p)
+        {
+          _ecc_wmnaf_cache_entry_free (p);
+        }
+
+      free (ecc_wmnaf_cache);
+    }
+}
+
+/* initialize single cache entry
+ * for a curve with the given id */
+static int
+_ecc_wmnaf_cache_entry_init (gnutls_ecc_curve_cache_entry_t * p,
+                             gnutls_ecc_curve_t id)
+{
+  int i, j, err;
+  ecc_point *G;
+  mpz_t a, modulus;
+
+  const gnutls_ecc_curve_entry_st *st = NULL;
+
+  if (p == NULL || id == 0)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  G = ecc_new_point ();
+  if (G == NULL)
+    {
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  st = _gnutls_ecc_curve_get_params (id);
+  if (st == NULL)
+    {
+      err = GNUTLS_E_INTERNAL_ERROR;
+      goto done;
+    }
+
+  if ((err = mp_init_multi (&a, &modulus, NULL) != 0))
+    return err;
+
+  /* set id */
+  p->id = id;
+
+  /* set modulus */
+  mpz_set_str (modulus, st->prime, 16);
+
+  /* get generator point */
+  mpz_set_str (G->x, st->Gx, 16);
+  mpz_set_str (G->y, st->Gy, 16);
+  mpz_set_ui (G->z, 1);
+
+  /* set A */
+  mpz_set_str (a, st->A, 16);
+
+  /* alloc ram for precomputed values */
+  for (i = 0; i < WMNAF_PRECOMPUTED_LENGTH; ++i)
+    {
+      p->pos[i] = ecc_new_point ();
+      p->neg[i] = ecc_new_point ();
+      if (p->pos[i] == NULL || p->neg[i] == NULL)
+        {
+          for (j = 0; j < i; ++j)
+            {
+              ecc_del_point (p->pos[j]);
+              ecc_del_point (p->neg[j]);
+            }
+
+          err = GNUTLS_E_MEMORY_ERROR;
+          goto done;
+        }
+    }
+
+  /* fill in pos and neg arrays with precomputed values
+   * pos holds kG for k ==  1, 3, 5, ..., (2^w - 1)
+   * neg holds kG for k == -1,-3,-5, ...,-(2^w - 1)
+   */
+
+  /* pos[0] == 2G for a while, later it will be set to the expected 1G */
+  if ((err = ecc_projective_dbl_point (G, p->pos[0], a, modulus)) != 0)
+    goto done;
+
+  /* pos[1] == 3G */
+  if ((err =
+       ecc_projective_add_point_ng (p->pos[0], G, p->pos[1], a,
+                                    modulus)) != 0)
+    goto done;
+
+  /* fill in kG for k = 5, 7, ..., (2^w - 1) */
+  for (j = 2; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
+    {
+      if ((err =
+           ecc_projective_add_point_ng (p->pos[j - 1], p->pos[0], p->pos[j],
+                                        a, modulus)) != 0)
+        goto done;
+    }
+
+  /* set pos[0] == 1G as expected
+   * after this step we don't need G at all */
+  mpz_set (p->pos[0]->x, G->x);
+  mpz_set (p->pos[0]->y, G->y);
+  mpz_set (p->pos[0]->z, G->z);
+
+  /* map to affine all elements in pos
+   * this will allow to use ecc_projective_madd later
+   * set neg[i] == -pos[i] */
+  for (j = 0; j < WMNAF_PRECOMPUTED_LENGTH; ++j)
+    {
+      if ((err = ecc_map (p->pos[j], modulus)) != 0)
+        goto done;
+
+      if ((err =
+           ecc_projective_negate_point (p->pos[j], p->neg[j], modulus)) != 0)
+        goto done;
+    }
+
+  err = 0;
+done:
+  ecc_del_point (G);
+  mp_clear_multi (&a, &modulus, NULL);
+
+  return err;
+}
+
+/* initialize curves caches */
+int
+ecc_wmnaf_cache_init (void)
+{
+  int j, err;
+
+  gnutls_ecc_curve_cache_entry_t *ret;
+
+  const gnutls_ecc_curve_t *p;
+
+  ret = (gnutls_ecc_curve_cache_entry_t *)
+    malloc (MAX_ALGOS * sizeof (gnutls_ecc_curve_cache_entry_t));
+  if (ret == NULL)
+    return GNUTLS_E_MEMORY_ERROR;
+
+  /* get supported curves' ids */
+  p = gnutls_ecc_curve_list ();
+
+  for (j = 0; *p; ++p, ++j)
+    {
+      if ((err = _ecc_wmnaf_cache_entry_init (ret + *p - 1, *p)) != 0)
+        goto done;
+    }
+
+  /* nullify last cache entry id */
+  ret[j].id = GNUTLS_ECC_CURVE_INVALID;
+
+  err = GNUTLS_E_SUCCESS;
+
+  ecc_wmnaf_cache = ret;
+done:
+  if (err)
+    {
+      int i;
+      for (i = 0; i < j; ++i)
+        {
+          _ecc_wmnaf_cache_entry_free (ret + i);
+        }
+
+      free (ret);
+      ecc_wmnaf_cache = NULL;
+    }
+  return err;
+}
+
+
+/*
+   Perform a point wMNAF-multiplication utilizing cache
+   @param k    The scalar to multiply by
+   @param id   The curve's id
+   @param R    [out] Destination for kG
+   @param a        The curve's A value
+   @param modulus  The modulus of the field the ECC curve is in
+   @param map      Boolean whether to map back to affine or not (1 == map, 0 
== leave in projective)
+   @return     GNUTLS_E_SUCCESS on success
+*/
+int
+ecc_mulmod_wmnaf_cached (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R,
+                         mpz_t a, mpz_t modulus, int map)
+{
+  int j, err;
+
+  gnutls_ecc_curve_cache_entry_t *cache = NULL;
+  signed char *wmnaf = NULL;
+  size_t wmnaf_len;
+  signed char digit;
+
+  if (k == NULL || R == NULL || modulus == NULL || id == 0)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* calculate wMNAF */
+  wmnaf = ecc_wMNAF (k, &wmnaf_len);
+  if (!wmnaf)
+    {
+      err = GNUTLS_E_INTERNAL_ERROR;
+      goto done;
+    }
+
+  /* set R to neutral */
+  mpz_set_ui (R->x, 1);
+  mpz_set_ui (R->y, 1);
+  mpz_set_ui (R->z, 0);
+
+  /* do cache lookup */
+  cache = ecc_wmnaf_cache + id - 1;
+
+  /* perform ops */
+  for (j = wmnaf_len - 1; j >= 0; --j)
+    {
+      if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0)
+        goto done;
+
+      digit = wmnaf[j];
+
+      if (digit)
+        {
+          if (digit > 0)
+            {
+              if ((err =
+                   ecc_projective_madd (R, cache->pos[(digit / 2)], R, a,
+                                        modulus)) != 0)
+                goto done;
+            }
+          else
+            {
+              if ((err =
+                   ecc_projective_madd (R, cache->neg[(-digit / 2)], R, a,
+                                        modulus)) != 0)
+                goto done;
+            }
+        }
+    }
+
+
+  /* map R back from projective space */
+  if (map)
+    {
+      err = ecc_map (R, modulus);
+    }
+  else
+    {
+      err = GNUTLS_E_SUCCESS;
+    }
+done:
+  if (wmnaf)
+    free (wmnaf);
+  return err;
+}
+
+/*
+   Perform a point wMNAF-multiplication utilizing cache
+   This version tries to be timing resistant
+   @param k    The scalar to multiply by
+   @param id   The curve's id
+   @param R    [out] Destination for kG
+   @param a        The curve's A value
+   @param modulus  The modulus of the field the ECC curve is in
+   @param map      Boolean whether to map back to affine or not (1 == map, 0 
== leave in projective)
+   @return     GNUTLS_E_SUCCESS on success
+*/
+int
+ecc_mulmod_wmnaf_cached_timing (mpz_t k, gnutls_ecc_curve_t id, ecc_point * R,
+                                mpz_t a, mpz_t modulus, int map)
+{
+  int j, err;
+
+  gnutls_ecc_curve_cache_entry_t *cache = NULL;
+  signed char *wmnaf = NULL;
+  size_t wmnaf_len;
+  signed char digit;
+  /* point for throttle */
+  ecc_point *T;
+
+  if (k == NULL || R == NULL || modulus == NULL || id == 0)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* prepare T point */
+  T = ecc_new_point ();
+  if (T == NULL)
+    return GNUTLS_E_MEMORY_ERROR;
+
+  /* calculate wMNAF */
+  wmnaf = ecc_wMNAF (k, &wmnaf_len);
+  if (!wmnaf)
+    {
+      err = GNUTLS_E_INTERNAL_ERROR;
+      goto done;
+    }
+
+  /* set R to neutral */
+  mpz_set_ui (R->x, 1);
+  mpz_set_ui (R->y, 1);
+  mpz_set_ui (R->z, 0);
+
+  /* set T to neutral */
+  mpz_set_ui (T->x, 1);
+  mpz_set_ui (T->y, 1);
+  mpz_set_ui (T->z, 0);
+
+  /* do cache lookup */
+  cache = ecc_wmnaf_cache + id - 1;
+
+  /* perform ops */
+  for (j = wmnaf_len - 1; j >= 0; --j)
+    {
+      if ((err = ecc_projective_dbl_point (R, R, a, modulus)) != 0)
+        goto done;
+
+      digit = wmnaf[j];
+
+      if (digit)
+        {
+          if (digit > 0)
+            {
+              if ((err =
+                   ecc_projective_madd (R, cache->pos[(digit / 2)], R, a,
+                                        modulus)) != 0)
+                goto done;
+            }
+          else
+            {
+              if ((err =
+                   ecc_projective_madd (R, cache->neg[(-digit / 2)], R, a,
+                                        modulus)) != 0)
+                goto done;
+            }
+        }
+      else
+        {
+          /* we add middle element of pos array as a general case
+           * there is no real difference between using pos and neg */
+          if ((err =
+               ecc_projective_madd (R,
+                                    cache->
+                                    pos[(WMNAF_PRECOMPUTED_LENGTH / 2)], T, a,
+                                    modulus)) != 0)
+            goto done;
+        }
+    }
+
+
+  /* map R back from projective space */
+  if (map)
+    {
+      err = ecc_map (R, modulus);
+    }
+  else
+    {
+      err = GNUTLS_E_SUCCESS;
+    }
+done:
+  ecc_del_point (T);
+  if (wmnaf)
+    free (wmnaf);
+  return err;
+}
+
+/*
+   Perform a point wMNAF-multiplication utilizing cache
+   This function will lookup for an apropriate curve first
+   This function's definition allows in-place substitution instead of 
ecc_mulmod
+   @param k    The scalar to multiply by
+   @param id   The curve's id
+   @param R    [out] Destination for kG
+   @param a        The curve's A value
+   @param modulus  The modulus of the field the ECC curve is in
+   @param map      Boolean whether to map back to affine or not (1 == map, 0 
== leave in projective)
+   @return     GNUTLS_E_SUCCESS on success
+*/
+int
+ecc_mulmod_wmnaf_cached_lookup (mpz_t k, ecc_point * G, ecc_point * R,
+                                mpz_t a, mpz_t modulus, int map)
+{
+  int i, id;
+
+  if (k == NULL || G == NULL || R == NULL || modulus == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  for (i = 0; (id = ecc_wmnaf_cache[i].id); ++i)
+    {
+      if (!(mpz_cmp (G->x, ecc_wmnaf_cache[i].pos[0]->x)) &&
+          !(mpz_cmp (G->y, ecc_wmnaf_cache[i].pos[0]->y)))
+        {
+          break;
+        }
+    }
+
+  return ecc_mulmod_wmnaf_cached (k, id, R, a, modulus, map);
+}
diff --git a/lib/nettle/ecc_projective_add_point.c 
b/lib/nettle/ecc_projective_add_point.c
index 89c96e5..586f116 100644
--- a/lib/nettle/ecc_projective_add_point.c
+++ b/lib/nettle/ecc_projective_add_point.c
@@ -36,25 +36,52 @@
    @param R        [out] The destination of the double
    @param a        Curve's a value
    @param modulus  The modulus of the field the ECC curve is in
-   @return 0 on success
+   @return         GNUTLS_E_SUCCESS on success
 */
 int
 ecc_projective_add_point (ecc_point * P, ecc_point * Q, ecc_point * R,
                               mpz_t a, mpz_t modulus)
 {
+  /* Using "(m)add-2004-hmv" algorithm
+   * It costs 12M + 4S + half. */
   mpz_t t1, t2, x, y, z;
   int err;
 
   if (P == NULL || Q == NULL || R == NULL || modulus == NULL)
-    return -1;
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* check for neutral points */
+  if ( (err = ecc_projective_isneutral(Q, modulus)) == 0 ) {
+    /* P + Q = P + neutral = P */
+
+    mpz_set (R->x, P->x);
+    mpz_set (R->y, P->y);
+    mpz_set (R->z, P->z);
+
+    return GNUTLS_E_SUCCESS;
+  } else if (err < 0) {
+    return err;
+  }
+
+  if ( (err = ecc_projective_isneutral(P, modulus)) == 0 ) {
+    /* P + Q = neutral + Q = Q */
+
+    mpz_set (R->x, Q->x);
+    mpz_set (R->y, Q->y);
+    mpz_set (R->z, Q->z);
+
+    return GNUTLS_E_SUCCESS;
+  } else if (err < 0) {
+    return err;
+  }
 
   if ((err = mp_init_multi (&t1, &t2, &x, &y, &z, NULL)) != 0)
     {
       return err;
     }
 
-  /* Check if P == Q and do doubling in that case 
-   * If Q == -P then P+Q=point at infinity
+  /* Check if P == Q and do doubling in that case
+   * If Q == -P then P + Q = neutral element
    */
   if ((mpz_cmp (P->x, Q->x) == 0) &&
       (mpz_cmp (P->z, Q->z) == 0))
@@ -66,7 +93,7 @@ ecc_projective_add_point (ecc_point * P, ecc_point * Q, 
ecc_point * R,
           mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
           return ecc_projective_dbl_point (P, R, a, modulus);
         }
-      
+
       mpz_sub (t1, modulus, Q->y);
       if (mpz_cmp (P->y, t1) == 0)
         {
@@ -74,7 +101,7 @@ ecc_projective_add_point (ecc_point * P, ecc_point * Q, 
ecc_point * R,
           mpz_set_ui(R->x, 1);
           mpz_set_ui(R->y, 1);
           mpz_set_ui(R->z, 0);
-          return 0;
+          return GNUTLS_E_SUCCESS;
         }
     }
 
@@ -217,7 +244,7 @@ ecc_projective_add_point (ecc_point * P, ecc_point * Q, 
ecc_point * R,
   mpz_set (R->y, y);
   mpz_set (R->z, z);
 
-  err = 0;
+  err = GNUTLS_E_SUCCESS;
 
   mp_clear_multi (&t1, &t2, &x, &y, &z, NULL);
   return err;
diff --git a/lib/nettle/ecc_projective_add_point_ng.c 
b/lib/nettle/ecc_projective_add_point_ng.c
new file mode 100644
index 0000000..72a7e7c
--- /dev/null
+++ b/lib/nettle/ecc_projective_add_point_ng.c
@@ -0,0 +1,462 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "ecc.h"
+
+/* We use two algorithms for different cases.
+ * See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html
+ *
+ * The algorithm used for general case is "add-1998-cmo-2"
+ * It costs 12M + 4S.
+ *
+ * If Z2 = 1 we use "madd". It costs 8M + 3S.
+ *
+ * The original versions use a lot of vars:
+ * Z1Z1, Z2Z2, U1, U2, S1, S2, H, I, HHH, r, V, etc.
+ * We use only the needed minimum:
+ * S1, H, HHH(J), r, V.
+ * The rest of the vars are not needed for final
+ * computation, so we calculate them, but don't store.
+ * Follow the comments.
+ */
+
+
+#define __WITH_EXTENDED_CHECKS
+/* Check if H == 0
+ * In this case P + Q = neutral element.
+ *
+ * In all of the cases below when H == 0 then Z == 0
+ * and the resulting point lies at infinity.
+ *
+ * And the only point on the curve with Z == 0 MUST be
+ * the neutral point.
+ *
+ * Of course, if there wasn't a mistake somewhere before.
+ * We will be gullible and won't do any checks and simply
+ * return neutral point in that case.
+ */
+
+
+/*
+   Add two ECC points
+   @param P        The point to add
+   @param Q        The point to add
+   @param R        [out] The destination of the double
+   @param a        Curve's a value
+   @param modulus  The modulus of the field the ECC curve is in
+   @return         GNUTLS_E_SUCCESS on success
+
+   Note: this function WILL work when a != -3.
+   It will work in general case without a change.
+*/
+int
+ecc_projective_add_point_ng (ecc_point * P, ecc_point * Q, ecc_point * R,
+                             mpz_t a, mpz_t modulus)
+{
+  mpz_t t0, t1, S1, H, HHH, r, V;
+  int err;
+
+  if (P == NULL || Q == NULL || R == NULL || modulus == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* check all special cases first */
+
+  /* check for neutral points */
+  if ((err = ecc_projective_isneutral (Q, modulus)) == 0)
+    {
+      /* P + Q = P + neutral = P */
+
+      mpz_set (R->x, P->x);
+      mpz_set (R->y, P->y);
+      mpz_set (R->z, P->z);
+
+      return GNUTLS_E_SUCCESS;
+    }
+  else if (err < 0)
+    {
+      return err;
+    }
+
+  if ((err = ecc_projective_isneutral (P, modulus)) == 0)
+    {
+      /* P + Q = neutral + Q = Q */
+
+      mpz_set (R->x, Q->x);
+      mpz_set (R->y, Q->y);
+      mpz_set (R->z, Q->z);
+
+      return GNUTLS_E_SUCCESS;
+    }
+  else if (err < 0)
+    {
+      return err;
+    }
+
+  if ((err = mp_init_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL)) != 0)
+    return err;
+
+  /* Check if P == Q and do doubling in that case
+   * If Q == -P then P + Q = neutral element */
+  if ((mpz_cmp (P->x, Q->x) == 0) && (mpz_cmp (P->z, Q->z) == 0))
+    {
+
+      /* x and z coordinates match.
+       * Check if P->y = Q->y, or P->y = -Q->y */
+
+      if (mpz_cmp (P->y, Q->y) == 0)
+        {
+          mp_clear_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL);
+          return ecc_projective_dbl_point (P, R, a, modulus);
+        }
+
+      mpz_sub (t1, modulus, Q->y);
+      if (mpz_cmp (P->y, t1) == 0)
+        {
+          mp_clear_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL);
+          mpz_set_ui (R->x, 1);
+          mpz_set_ui (R->y, 1);
+          mpz_set_ui (R->z, 0);
+          return GNUTLS_E_SUCCESS;
+        }
+    }
+
+
+  /* check if Z2 == 1 and do "madd" in that case */
+  if ((mpz_cmp_ui (Q->z, 1) == 0))
+    {
+      mp_clear_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL);
+      return ecc_projective_madd (P, Q, R, a, modulus);
+    }
+
+  /* no special cases occured
+   * do general routine */
+
+  /* t1 = Z1 * Z1 */
+  /* it is the original Z1Z1 */
+  mpz_mul (t1, P->z, P->z);
+  mpz_mod (t1, t1, modulus);
+
+  /* t0 = Z1 * Z1Z1 */
+  mpz_mul (t0, t1, P->z);
+  mpz_mod (t0, t0, modulus);
+
+  /* H = X2 * Z1Z1 */
+  /* it is the original U2 */
+  mpz_mul (H, t1, Q->x);
+  mpz_mod (H, H, modulus);
+
+  /* r = Y2 * Z1 * Z1Z1 */
+  /* it is the original S2 */
+  mpz_mul (r, t0, Q->y);
+  mpz_mod (r, r, modulus);
+
+  /* S1 = Z2 * Z2 */
+  /* it is the original Z2Z2 */
+  mpz_mul (S1, Q->z, Q->z);
+  mpz_mod (S1, S1, modulus);
+
+  /* t0 = X1 * Z2Z2 */
+  /* it is the original U1 */
+  mpz_mul (t0, S1, P->x);
+  mpz_mod (t0, t0, modulus);
+
+  /* H = U2 - U1 = H - t0 */
+  mpz_sub (H, H, t0);
+#ifdef __WITH_EXTENDED_CHECKS
+  err = mpz_cmp_ui (H, 0);
+  if (err < 0)
+    {
+      mpz_add (H, H, modulus);
+    }
+  else if (!err)
+    {
+      mpz_set_ui (R->x, 1);
+      mpz_set_ui (R->y, 1);
+      mpz_set_ui (R->z, 0);
+      mp_clear_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL);
+
+      return GNUTLS_E_SUCCESS;
+    }
+#else
+  if (mpz_cmp_ui (H, 0) < 0)
+    mpz_add (H, H, modulus);
+#endif
+  /* t1 = H^2 */
+  /* it is the original HH */
+  mpz_mul (t1, H, H);
+  mpz_mod (t1, t1, modulus);
+  /* HHH = H * HH */
+  mpz_mul (HHH, t1, H);
+  mpz_mod (HHH, HHH, modulus);
+
+  /* V = U1 * HH = t0 * t1 */
+  mpz_mul (V, t1, t0);
+  mpz_mod (V, V, modulus);
+
+  /* t0 = Z2 * Z2Z2 */
+  mpz_mul (t0, S1, Q->z);
+  mpz_mod (t0, t0, modulus);
+  /* S1 = Y1 * Z2 * Z2Z2 */
+  mpz_mul (S1, t0, P->y);
+  mpz_mod (S1, S1, modulus);
+
+  /* r = S2 - S1 = r - S1 */
+  mpz_sub (r, r, S1);
+  if (mpz_cmp_ui (r, 0) < 0)
+    mpz_add (r, r, modulus);
+
+  /* we've calculated all needed vars:
+   * S1, H, HHH, r, V
+   * now, we will calculate the coordinates */
+
+  /* t0 = (r)^2 */
+  mpz_mul (t0, r, r);
+  mpz_mod (t0, t0, modulus);
+  /* t0 = t0 - HHH */
+  mpz_sub (t0, t0, HHH);
+  if (mpz_cmp_ui (t0, 0) < 0)
+    mpz_add (t0, t0, modulus);
+  /* t1 = 2V */
+  mpz_add (t1, V, V);
+  if (mpz_cmp (t1, modulus) >= 0)
+    mpz_sub (t1, t1, modulus);
+  /* X = r^2 - HHH - 2V = t0 - t1 */
+  mpz_sub (R->x, t0, t1);
+  if (mpz_cmp_ui (R->x, 0) < 0)
+    mpz_add (R->x, R->x, modulus);
+
+
+  /* t1 = V - X */
+  mpz_sub (t1, V, R->x);
+  if (mpz_cmp_ui (t1, 0) < 0)
+    mpz_add (t1, t1, modulus);
+  /* t0 = r * t1 */
+  mpz_mul (t0, r, t1);
+  mpz_mod (t0, t0, modulus);
+  /* t1 = S1 * HHH */
+  mpz_mul (t1, S1, HHH);
+  mpz_mod (t1, t1, modulus);
+  /* Y = r*(V - X) - S1*HHH = t0 - t1 */
+  mpz_sub (R->y, t0, t1);
+  if (mpz_cmp_ui (R->y, 0) < 0)
+    mpz_add (R->y, R->y, modulus);
+
+
+  /* t1 = Z1 * Z2 */
+  mpz_mul (t1, P->z, Q->z);
+  mpz_mod (t1, t1, modulus);
+  /* Z = Z1 * Z2 * H = t1 * H */
+  mpz_mul (R->z, t1, H);
+  mpz_mod (R->z, R->z, modulus);
+
+  mp_clear_multi (&S1, &H, &HHH, &r, &V, &t0, &t1, NULL);
+
+  return GNUTLS_E_SUCCESS;
+}
+
+/*
+   Add two ECC points, when it is known that Z2 == 1
+   @param P        The point to add
+   @param Q        The point with Z == 1 to add
+   @param R        [out] The destination of the double
+   @param a        Curve's a value
+   @param modulus  The modulus of the field the ECC curve is in
+   @return         GNUTLS_E_SUCCESS on success
+
+   Note: this function will work when a != -3.
+   It will work in general case without a change.
+*/
+int
+ecc_projective_madd (ecc_point * P, ecc_point * Q, ecc_point * R,
+                     mpz_t a, mpz_t modulus)
+{
+  mpz_t t0, t1, H, J, r, V;
+  int err;
+
+  if (P == NULL || Q == NULL || R == NULL || modulus == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /* check all special cases first */
+
+  /* check for neutral points */
+  /* Q is guaranteed not to be neutral since it has Z == 1 */
+  if ((err = ecc_projective_isneutral (P, modulus)) == 0)
+    {
+      /* P + Q = neutral + Q = Q */
+
+      mpz_set (R->x, Q->x);
+      mpz_set (R->y, Q->y);
+      mpz_set (R->z, Q->z);
+
+      return GNUTLS_E_SUCCESS;
+    }
+  else if (err < 0)
+    {
+      return err;
+    }
+
+  if ((err = mp_init_multi (&H, &J, &r, &V, &t0, &t1, NULL)) != 0)
+    return err;
+
+  /* Check if P == Q and do doubling in that case
+   * If Q == -P then P + Q = neutral element */
+  if ((mpz_cmp (P->x, Q->x) == 0) && (mpz_cmp (P->z, Q->z) == 0))
+    {
+
+      /* x and z coordinates match.
+       * Check if P->y = Q->y, or P->y = -Q->y */
+
+      if (mpz_cmp (P->y, Q->y) == 0)
+        {
+          mp_clear_multi (&H, &J, &r, &V, &t0, &t1, NULL);
+          return ecc_projective_dbl_point (P, R, a, modulus);
+        }
+
+      mpz_sub (t1, modulus, Q->y);
+      if (mpz_cmp (P->y, t1) == 0)
+        {
+          mp_clear_multi (&H, &J, &r, &V, &t0, &t1, NULL);
+          mpz_set_ui (R->x, 1);
+          mpz_set_ui (R->y, 1);
+          mpz_set_ui (R->z, 0);
+          return GNUTLS_E_SUCCESS;
+        }
+    }
+
+  /* no special cases occured
+   * do madd */
+
+  /* t1 = Z1 * Z1 */
+  /* it is the original Z1Z1 */
+  mpz_mul (t1, P->z, P->z);
+  mpz_mod (t1, t1, modulus);
+
+  /* t0 = Z1 * Z1Z1 */
+  mpz_mul (t0, t1, P->z);
+  mpz_mod (t0, t0, modulus);
+
+  /* r = Y2 * Z1 * Z1Z1 */
+  /* it is the original S2 */
+  mpz_mul (r, t0, Q->y);
+  mpz_mod (r, r, modulus);
+  /* r = S2 - Y1 = r - Y1 */
+  mpz_sub (r, r, P->y);
+  if (mpz_cmp_ui (r, 0) < 0)
+    mpz_add (r, r, modulus);
+  /* r = 2 * (S2 - Y1) */
+  mpz_add (r, r, r);
+  if (mpz_cmp (r, modulus) >= 0)
+    mpz_sub (r, r, modulus);
+
+  /* H = X2 * Z1Z1 */
+  /* it is the original U2 */
+  mpz_mul (H, t1, Q->x);
+  mpz_mod (H, H, modulus);
+  /* H = U2 - X1  = H - X1 */
+  mpz_sub (H, H, P->x);
+#ifdef __WITH_EXTENDED_CHECKS
+  err = mpz_cmp_ui (H, 0);
+  if (err < 0)
+    {
+      mpz_add (H, H, modulus);
+    }
+  else if (!err)
+    {
+      mpz_set_ui (R->x, 1);
+      mpz_set_ui (R->y, 1);
+      mpz_set_ui (R->z, 0);
+      mp_clear_multi (&H, &J, &r, &V, &t0, &t1, NULL);
+
+      return GNUTLS_E_SUCCESS;
+    }
+#else
+  if (mpz_cmp_ui (H, 0) < 0)
+    mpz_add (H, H, modulus);
+#endif
+
+  /* t0 = 2H */
+  mpz_add (t0, H, H);
+  if (mpz_cmp (t0, modulus) >= 0)
+    mpz_sub (t0, t0, modulus);
+  /* t1 = (2H)^2 */
+  /* it is the original I */
+  mpz_mul (t1, t0, t0);
+  mpz_mod (t1, t1, modulus);
+
+  /* J = H * I = H * t1 */
+  mpz_mul (J, t1, H);
+  mpz_mod (J, J, modulus);
+
+  /* V = X1 * I = X1 * t1 */
+  mpz_mul (V, t1, P->x);
+  mpz_mod (V, V, modulus);
+
+  /* we've calculated all needed vars:
+   * H, J, r, V
+   * now, we will calculate the coordinates */
+
+  /* Z = 2 * Z1 * H = Z1 * t0 */
+  mpz_mul (R->z, P->z, t0);
+  mpz_mod (R->z, R->z, modulus);
+
+
+  /* t0 = (r)^2 */
+  mpz_mul (t0, r, r);
+  mpz_mod (t0, t0, modulus);
+  /* t0 = t0 - J */
+  mpz_sub (t0, t0, J);
+  if (mpz_cmp_ui (t0, 0) < 0)
+    mpz_add (t0, t0, modulus);
+  /* t1 = 2V */
+  mpz_add (t1, V, V);
+  if (mpz_cmp (t1, modulus) >= 0)
+    mpz_sub (t1, t1, modulus);
+  /* X = r^2 - J - 2V = t0 - t1 */
+  mpz_sub (R->x, t0, t1);
+  if (mpz_cmp_ui (R->x, 0) < 0)
+    mpz_add (R->x, R->x, modulus);
+
+
+  /* t1 = V - X */
+  mpz_sub (t1, V, R->x);
+  if (mpz_cmp_ui (t1, 0) < 0)
+    mpz_add (t1, t1, modulus);
+  /* t0 = r * t1 */
+  mpz_mul (t0, r, t1);
+  mpz_mod (t0, t0, modulus);
+  /* t1 = Y1 * J */
+  mpz_mul (t1, J, P->y);
+  mpz_mod (t1, t1, modulus);
+  /* t1 = 2 * t1 */
+  mpz_add (t1, t1, t1);
+  if (mpz_cmp (t1, modulus) >= 0)
+    mpz_sub (t1, t1, modulus);
+  /* Y = r * (V - X) - 2 * Y1 * J = t0 - t1 */
+  mpz_sub (R->y, t0, t1);
+  if (mpz_cmp_ui (R->y, 0) < 0)
+    mpz_add (R->y, R->y, modulus);
+
+
+  mp_clear_multi (&H, &J, &r, &V, &t0, &t1, NULL);
+
+  return GNUTLS_E_SUCCESS;
+}
diff --git a/lib/nettle/ecc_projective_dbl_point_3.c 
b/lib/nettle/ecc_projective_dbl_point_3.c
index 1b376fe..53b2db5 100644
--- a/lib/nettle/ecc_projective_dbl_point_3.c
+++ b/lib/nettle/ecc_projective_dbl_point_3.c
@@ -27,126 +27,150 @@
 /*
   @file ecc_projective_dbl_point.c
   ECC Crypto, Tom St Denis
-*/  
+*/
 
 #ifdef ECC_SECP_CURVES_ONLY
 
 /*
    Double an ECC point
-   @param P   The point to double
+   @param P         The point to double
    @param R   [out] The destination of the double
-   @param modulus  The modulus of the field the ECC curve is in
-   @param mp       The "b" value from montgomery_setup()
-   @return 0 on success
+   @param a         Curve's a value
+   @param modulus   The modulus of the field the ECC curve is in
+   @return          GNUTLS_E_SUCCESS on success
 */
 int
-ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a /* a is -3 */,
+ecc_projective_dbl_point (ecc_point * P, ecc_point * R, mpz_t a,
                               mpz_t modulus)
 {
+   /* Using "dbl-2004-hmv" algorithm.
+    * It costs 4M + 4S + half. */
    mpz_t t1, t2;
-   int   err;
+   int err;
 
    if (P == NULL || R == NULL || modulus == NULL)
-     return -1;
+     return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
 
-   if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
-      return err;
-   }
+   if ( (err = ecc_projective_isneutral(P, modulus)) == 1 ) {
 
-   if (P != R) {
-      mpz_set(R->x, P->x);
-      mpz_set(R->y, P->y);
-      mpz_set(R->z, P->z);
-   }
+     if ((err = mp_init_multi(&t1, &t2, NULL)) != 0) {
+        return err;
+     }
 
-   /* t1 = Z * Z */
-   mpz_mul(t1, R->z, R->z);
-   mpz_mod(t1, t1, modulus);
-   /* Z = Y * Z */
-   mpz_mul(R->z, R->y, R->z);
-   mpz_mod(R->z, R->z, modulus);
-   /* Z = 2Z */
-   mpz_add(R->z, R->z, R->z);
-   if (mpz_cmp(R->z, modulus) >= 0) {
-      mpz_sub(R->z, R->z, modulus);
-   }
-   
-   /* T2 = X - T1 */
-   mpz_sub(t2, R->x, t1);
-   if (mpz_cmp_ui(t2, 0) < 0) {
-      mpz_add(t2, t2, modulus);
-   }
-   /* T1 = X + T1 */
-   mpz_add(t1, t1, R->x);
-   if (mpz_cmp(t1, modulus) >= 0) {
-      mpz_sub(t1, t1, modulus);
-   }
-   /* T2 = T1 * T2 */
-   mpz_mul(t2, t1, t2);
-   mpz_mod(t2, t2, modulus);
-   /* T1 = 2T2 */
-   mpz_add(t1, t2, t2);
-   if (mpz_cmp(t1, modulus) >= 0) {
-      mpz_sub(t1, t1, modulus);
-   }
-   /* T1 = T1 + T2 */
-   mpz_add(t1, t1, t2);
-   if (mpz_cmp(t1, modulus) >= 0) {
-      mpz_sub(t1, t1, modulus);
-   }
+     if (P != R) {
+       mpz_set(R->x, P->x);
+       mpz_set(R->y, P->y);
+       mpz_set(R->z, P->z);
+     }
 
-   /* Y = 2Y */
-   mpz_add(R->y, R->y, R->y);
-   if (mpz_cmp(R->y, modulus) >= 0) {
-      mpz_sub(R->y, R->y, modulus);
-   }
-   /* Y = Y * Y */
-   mpz_mul(R->y, R->y, R->y);
-   mpz_mod(R->y, R->y, modulus);
-   /* T2 = Y * Y */
-   mpz_mul(t2, R->y, R->y);
-   mpz_mod(t2, t2, modulus);
-   /* T2 = T2/2 */
-   if (mpz_odd_p(t2)) {
-      mpz_add(t2, t2, modulus);
-   }
-   mpz_divexact_ui(t2, t2, 2);
-   /* Y = Y * X */
-   mpz_mul(R->y, R->y, R->x);
-   mpz_mod(R->y, R->y, modulus);
-
-   /* X  = T1 * T1 */
-   mpz_mul(R->x, t1, t1);
-   mpz_mod(R->x, R->x, modulus);
-   /* X = X - Y */
-   mpz_sub(R->x, R->x, R->y);
-   if (mpz_cmp_ui(R->x, 0) < 0) {
-      mpz_add(R->x, R->x, modulus);
-   }
-   /* X = X - Y */
-   mpz_sub(R->x, R->x, R->y);
-   if (mpz_cmp_ui(R->x, 0) < 0) {
-      mpz_add(R->x, R->x, modulus);
-   }
+     if (mpz_cmp_ui (P->z, 1) != 0) {
+         /* t1 = Z * Z */
+         mpz_mul(t1, R->z, R->z);
+         mpz_mod(t1, t1, modulus);
+         /* Z = Y * Z */
+         mpz_mul(R->z, R->y, R->z);
+         mpz_mod(R->z, R->z, modulus);
+         /* Z = 2Z */
+         mpz_add(R->z, R->z, R->z);
+         if (mpz_cmp(R->z, modulus) >= 0) {
+            mpz_sub(R->z, R->z, modulus);
+         }
+     } else {
+         /* t1 = 1 */
+         mpz_set(t1, P->z);
+         /* Z = 2Y */
+         mpz_add(R->z, R->y, R->y);
+         if (mpz_cmp(R->z, modulus) >= 0) {
+            mpz_sub(R->z, R->z, modulus);
+         }
+     }
 
-   /* Y = Y - X */     
-   mpz_sub(R->y, R->y, R->x);
-   if (mpz_cmp_ui(R->y, 0) < 0) {
-      mpz_add(R->y, R->y, modulus);
-   }
-   /* Y = Y * T1 */
-   mpz_mul(R->y, R->y, t1);
-   mpz_mod(R->y, R->y, modulus);
-   /* Y = Y - T2 */
-   mpz_sub(R->y, R->y, t2);
-   if (mpz_cmp_ui(R->y, 0) < 0) {
-      mpz_add( R->y, R->y, modulus);
-   }
- 
-   err = 0;
+     /* T2 = X - T1 */
+     mpz_sub(t2, R->x, t1);
+     if (mpz_cmp_ui(t2, 0) < 0) {
+        mpz_add(t2, t2, modulus);
+     }
+     /* T1 = X + T1 */
+     mpz_add(t1, t1, R->x);
+     if (mpz_cmp(t1, modulus) >= 0) {
+        mpz_sub(t1, t1, modulus);
+     }
+     /* T2 = T1 * T2 */
+     mpz_mul(t2, t1, t2);
+     mpz_mod(t2, t2, modulus);
+     /* T1 = 2T2 */
+     mpz_add(t1, t2, t2);
+     if (mpz_cmp(t1, modulus) >= 0) {
+        mpz_sub(t1, t1, modulus);
+     }
+     /* T1 = T1 + T2 */
+     mpz_add(t1, t1, t2);
+     if (mpz_cmp(t1, modulus) >= 0) {
+        mpz_sub(t1, t1, modulus);
+     }
+
+     /* Y = 2Y */
+     mpz_add(R->y, R->y, R->y);
+     if (mpz_cmp(R->y, modulus) >= 0) {
+        mpz_sub(R->y, R->y, modulus);
+     }
+     /* Y = Y * Y */
+     mpz_mul(R->y, R->y, R->y);
+     mpz_mod(R->y, R->y, modulus);
+     /* T2 = Y * Y */
+     mpz_mul(t2, R->y, R->y);
+     mpz_mod(t2, t2, modulus);
+     /* T2 = T2/2 */
+     if (mpz_odd_p(t2)) {
+        mpz_add(t2, t2, modulus);
+     }
+     mpz_divexact_ui(t2, t2, 2);
+     /* Y = Y * X */
+     mpz_mul(R->y, R->y, R->x);
+     mpz_mod(R->y, R->y, modulus);
 
-   mp_clear_multi(&t1, &t2, NULL);
-   return err;
+     /* X  = T1 * T1 */
+     mpz_mul(R->x, t1, t1);
+     mpz_mod(R->x, R->x, modulus);
+     /* X = X - Y */
+     mpz_sub(R->x, R->x, R->y);
+     if (mpz_cmp_ui(R->x, 0) < 0) {
+        mpz_add(R->x, R->x, modulus);
+     }
+     /* X = X - Y */
+     mpz_sub(R->x, R->x, R->y);
+     if (mpz_cmp_ui(R->x, 0) < 0) {
+        mpz_add(R->x, R->x, modulus);
+     }
+
+     /* Y = Y - X */
+     mpz_sub(R->y, R->y, R->x);
+     if (mpz_cmp_ui(R->y, 0) < 0) {
+        mpz_add(R->y, R->y, modulus);
+     }
+     /* Y = Y * T1 */
+     mpz_mul(R->y, R->y, t1);
+     mpz_mod(R->y, R->y, modulus);
+     /* Y = Y - T2 */
+     mpz_sub(R->y, R->y, t2);
+     if (mpz_cmp_ui(R->y, 0) < 0) {
+        mpz_add( R->y, R->y, modulus);
+     }
+
+     err = GNUTLS_E_SUCCESS;
+
+     mp_clear_multi(&t1, &t2, NULL);
+     return err;
+   } else if (err == 0) {
+     /* 2*neutral = neutral */
+     mpz_set_ui(R->x, 1);
+     mpz_set_ui(R->y, 1);
+     mpz_set_ui(R->z, 0);
+
+     return GNUTLS_E_SUCCESS;
+   } else {
+     return err;
+   }
 }
 #endif
 /* $Source: /cvs/libtom/libtomcrypt/src/pk/ecc/ecc_projective_dbl_point.c,v $ 
*/
diff --git a/lib/nettle/ecc_projective_isneutral.c 
b/lib/nettle/ecc_projective_isneutral.c
new file mode 100644
index 0000000..742ae5f
--- /dev/null
+++ b/lib/nettle/ecc_projective_isneutral.c
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "ecc.h"
+
+/*
+   Check if the given point is the neutral point
+   @param P        The point to check
+   @param modulus  The modulus of the field the ECC curve is in
+   @return         0 if given point is a neutral point
+   @return         1 if given point is not a neutral point
+   @return         negative value in case of error
+*/
+int
+ecc_projective_isneutral (ecc_point * P, mpz_t modulus)
+{
+  mpz_t t1, t2;
+  int err;
+
+  if (P == NULL || modulus == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  /*
+   * neutral point is a point with projective
+   * coordinates (x,y,0) such that y^2 == x^3
+   * excluding point (0,0,0)
+   */
+  if (mpz_sgn (P->z))
+    /* Z != 0 */
+    return 1;
+
+  if ((err = mp_init_multi (&t1, &t2, NULL)) != 0)
+    {
+      return err;
+    }
+
+  /* t1 == x^3 */
+  mpz_mul (t1, P->x, P->x);
+  mpz_mod (t1, t1, modulus);
+  mpz_mul (t1, t1, P->x);
+  mpz_mod (t1, t1, modulus);
+  /* t2 == y^2 */
+  mpz_mul (t2, P->y, P->y);
+  mpz_mod (t2, t2, modulus);
+
+  if ((!mpz_cmp (t1, t2)) && (mpz_sgn (t1)))
+    {
+      /* Z == 0 and X^3 == Y^2 != 0
+       * it is neutral */
+      err = 0;
+      goto done;
+    }
+
+  /* Z == 0 and X^3 != Y^2 or
+   * Z == X == Y == 0
+   * this should never happen */
+  err = GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+  goto done;
+done:
+  mp_clear_multi (&t1, &t2, NULL);
+  return err;
+}
diff --git a/lib/nettle/ecc_projective_negate_point.c 
b/lib/nettle/ecc_projective_negate_point.c
new file mode 100644
index 0000000..0021e05
--- /dev/null
+++ b/lib/nettle/ecc_projective_negate_point.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include "ecc.h"
+
+/*
+   Negate an ECC point
+   @param P        The point to negate
+   @param R        [out] The destination of the negate
+   @param modulus  The modulus of the field the ECC curve is in
+   @return         GNUTLS_E_SUCCESS on success
+*/
+int
+ecc_projective_negate_point (ecc_point * P, ecc_point * R, mpz_t modulus)
+{
+
+  if (P == NULL || R == NULL)
+    return GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER;
+
+  if (ecc_projective_isneutral (P, modulus))
+    {
+      /* we set R.y to (modulus - P.y) to avoid negative coordinates */
+      mpz_set (R->x, P->x);
+      mpz_sub (R->y, modulus, P->y);
+      mpz_mod (R->y, R->y, modulus);
+      mpz_set (R->z, P->z);
+    }
+  else
+    {
+      /* -neutral = neutral */
+      mpz_set_ui (R->x, 1);
+      mpz_set_ui (R->y, 1);
+      mpz_set_ui (R->z, 0);
+    }
+
+  return GNUTLS_E_SUCCESS;
+}
diff --git a/lib/nettle/ecc_shared_secret.c b/lib/nettle/ecc_shared_secret.c
index c9ed006..74466ed 100644
--- a/lib/nettle/ecc_shared_secret.c
+++ b/lib/nettle/ecc_shared_secret.c
@@ -63,7 +63,7 @@ ecc_shared_secret (ecc_key * private_key, ecc_key * 
public_key,
     }
 
   if ((err =
-       ecc_mulmod (private_key->k, &public_key->pubkey, result,
+       ecc_mulmod_wmnaf (private_key->k, &public_key->pubkey, result,
                        private_key->A, private_key->prime, 1)) != 0)
     {
       goto done;
diff --git a/lib/nettle/ecc_sign_hash.c b/lib/nettle/ecc_sign_hash.c
index bd78da0..2adc7a2 100644
--- a/lib/nettle/ecc_sign_hash.c
+++ b/lib/nettle/ecc_sign_hash.c
@@ -38,12 +38,14 @@
   @param prng      An active PRNG state
   @param wprng     The index of the PRNG you wish to use
   @param key       A private ECC key
+  @param curve_id  The id of the curve we are working with
   @return 0 if successful
 */
 int
 ecc_sign_hash (const unsigned char *in, unsigned long inlen,
                struct dsa_signature *sig,
-               void *random_ctx, nettle_random_func random, ecc_key * key)
+               void *random_ctx, nettle_random_func random,
+               ecc_key * key, gnutls_ecc_curve_t curve_id)
 {
   ecc_key pubkey;
   mpz_t e;
@@ -72,7 +74,7 @@ ecc_sign_hash (const unsigned char *in, unsigned long inlen,
     {
       if ((err =
            ecc_make_key_ex (random_ctx, random, &pubkey, key->prime,
-                            key->order, key->A, key->B, key->Gx, key->Gy, 1)) 
!= 0)
+                            key->order, key->A, key->B, key->Gx, key->Gy, 
curve_id, 1)) != 0)
         {
           goto errnokey;
         }
diff --git a/lib/nettle/ecc_verify_hash.c b/lib/nettle/ecc_verify_hash.c
index e7ebc23..fc31735 100644
--- a/lib/nettle/ecc_verify_hash.c
+++ b/lib/nettle/ecc_verify_hash.c
@@ -46,12 +46,13 @@
    @param hashlen     The length of the hash (octets)
    @param stat        Result of signature, 1==valid, 0==invalid
    @param key         The corresponding public ECC key
+   @param curve_id    The id of the curve we are working with
    @return 0 if successful (even if the signature is not valid)
 */
 int
 ecc_verify_hash (struct dsa_signature *signature,
                  const unsigned char *hash, unsigned long hashlen,
-                 int *stat, ecc_key * key)
+                 int *stat, ecc_key * key, gnutls_ecc_curve_t curve_id)
 {
   ecc_point *mG, *mQ;
   mpz_t v, w, u1, u2, e;
@@ -111,18 +112,18 @@ ecc_verify_hash (struct dsa_signature *signature,
   mpz_set (mQ->z, key->pubkey.z);
 
   /* compute u1*mG + u2*mQ = mG */
-  if ((err = ecc_mulmod (u1, mG, mG, key->A, key->prime, 0)) != 0)
+  if ((err = ecc_mulmod_wmnaf_cached (u1, curve_id, mG, key->A, key->prime, 
0)) != 0)
     {
       goto error;
     }
-  if ((err = ecc_mulmod (u2, mQ, mQ, key->A, key->prime, 0)) != 0)
+  if ((err = ecc_mulmod_wmnaf (u2, mQ, mQ, key->A, key->prime, 0)) != 0)
     {
       goto error;
     }
 
   /* add them */
   if ((err =
-       ecc_projective_add_point (mQ, mG, mG, key->A, key->prime)) != 0)
+       ecc_projective_add_point_ng (mQ, mG, mG, key->A, key->prime)) != 0)
     {
       goto error;
     }
diff --git a/lib/nettle/init.c b/lib/nettle/init.c
index 34db731..bc89e40 100644
--- a/lib/nettle/init.c
+++ b/lib/nettle/init.c
@@ -24,6 +24,7 @@
 #include <gnutls_errors.h>
 #include <gnutls_num.h>
 #include <gnutls_mpi.h>
+#include "ecc.h"
 
 /* Functions that refer to the initialization of the nettle library.
  */
@@ -31,5 +32,14 @@
 int
 gnutls_crypto_init (void)
 {
-  return 0;
+  return ecc_wmnaf_cache_init();
+}
+
+/* Functions that refer to the deinitialization of the nettle library.
+ */
+
+void
+gnutls_crypto_deinit (void)
+{
+  ecc_wmnaf_cache_free();
 }
diff --git a/lib/nettle/pk.c b/lib/nettle/pk.c
index 41a0fb1..c54d83b 100644
--- a/lib/nettle/pk.c
+++ b/lib/nettle/pk.c
@@ -327,6 +327,10 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
       {
         ecc_key priv;
         struct dsa_signature sig;
+        int curve_id = pk_params->flags;
+
+        if (is_supported_curve(curve_id) == 0)
+          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
 
         _ecc_params_to_privkey(pk_params, &priv);
 
@@ -340,8 +344,8 @@ _wrap_nettle_pk_sign (gnutls_pk_algorithm_t algo,
             hash_len = vdata->size;
           }
 
-        ret = ecc_sign_hash(vdata->data, hash_len, 
-                            &sig, NULL, rnd_func, &priv);
+        ret = ecc_sign_hash(vdata->data, hash_len,
+                            &sig, NULL, rnd_func, &priv, curve_id);
         if (ret != 0)
           {
             gnutls_assert ();
@@ -468,6 +472,10 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
         ecc_key pub;
         struct dsa_signature sig;
         int stat;
+        int curve_id = pk_params->flags;
+
+        if (is_supported_curve(curve_id) == 0)
+          return gnutls_assert_val(GNUTLS_E_ECC_UNSUPPORTED_CURVE);
 
         ret = _gnutls_decode_ber_rs (signature, &tmp[0], &tmp[1]);
         if (ret < 0)
@@ -484,7 +492,7 @@ _wrap_nettle_pk_verify (gnutls_pk_algorithm_t algo,
         if (hash_len > vdata->size)
           hash_len = vdata->size;
 
-        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub);
+        ret = ecc_verify_hash(&sig, vdata->data, hash_len, &stat, &pub, 
curve_id);
         if (ret != 0 || stat != 1)
           {
             gnutls_assert();
@@ -709,7 +717,7 @@ rsa_fail:
         tls_ecc_set.A = st->A;
         tls_ecc_set.B = st->B;
 
-        ret = ecc_make_key(NULL, rnd_func, &key, &tls_ecc_set);
+        ret = ecc_make_key(NULL, rnd_func, &key, &tls_ecc_set, st->id);
         if (ret != 0)
           return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 
@@ -889,7 +897,7 @@ dsa_cleanup:
         memcpy(&zero.z, ecc_priv.pubkey.z, sizeof(mpz_t)); /* z = 1 */
 
         /* verify that k*(Gx,Gy)=(x,y) */
-        ret = ecc_mulmod(ecc_priv.k, &zero, R, TOMPZ(params->params[ECC_A]), 
TOMPZ(params->params[ECC_PRIME]), 1);
+        ret = ecc_mulmod_wmnaf_cached(ecc_priv.k, curve, R, 
TOMPZ(params->params[ECC_A]), TOMPZ(params->params[ECC_PRIME]), 1);
         if (ret != 0)
           {
             ret = gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER);
diff --git a/lib/nettle/wmnaf.c b/lib/nettle/wmnaf.c
new file mode 100644
index 0000000..778518a
--- /dev/null
+++ b/lib/nettle/wmnaf.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (C) 2011-2012 Free Software Foundation, Inc.
+ *
+ * Author: Ilya Tumaykin
+ *
+ * This file is part of GNUTLS.
+ *
+ * The GNUTLS library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <gmp.h>
+
+#include "ecc.h"
+
+/* needed constants */
+#define BASEW   (1 << WMNAF_WINSIZE)    /* 2^w */
+#define BASEWW  (1 << (WMNAF_WINSIZE + 1))      /* 2^(w+1) */
+#define WBITS   (BASEWW - 1)
+
+#define ABS(x) ((x) >= 0 ? (x) : -(x))
+
+/*
+ * A local replacement for mpz_tstbit.
+ * It is needed because for negative numbers original mpz_tstbit
+ * returns an infinite number of `1`s after all bits of input number.
+ * For positive numbers it returns zeros after all bits of input number.
+ * This function mimics mpz_tstbit behavior for positive numbers in both cases.
+ */
+static int
+mpz_unitstbit (mpz_srcptr u, mp_bitcnt_t bit_index)
+  __GMP_NOTHROW
+{
+  mp_srcptr u_ptr = (u)->_mp_d;
+  mp_size_t size = (u)->_mp_size;
+  unsigned abs_size = ABS (size);
+  mp_size_t limb_index = bit_index / GMP_NUMB_BITS;
+  mp_srcptr p = u_ptr + limb_index;
+  mp_limb_t limb;
+
+  if (limb_index >= abs_size)
+    return (size < 0);
+
+  limb = *p;
+
+  return (limb >> (bit_index % GMP_NUMB_BITS)) & 1;
+}
+
+/*
+ * Return an array with wMNAF representation together with its length.
+ * The result is the array with elements from the set {0, +-1, +-3, +-5, ..., 
+-(2^w - 1)}
+ * such that at most one of any (w + 1) consecutive digits is non-zero
+ * with exception for the the most significant (w + 1) bits.
+ * With the last property it is modified version of wNAF.
+ * Overview of this algorithm can be found, for exmaple, in
+ * Bodo Moller, Improved Techniques for Fast Exponentiation.
+ * Information Security and Cryptology – ICISC 2002, Springer-Verlag LNCS 
2587, pp. 298–312
+ */
+/*
+   @param x        The number to get wMNAF for
+   @param len      [out] Destination for the length of wMNAF
+   @return         array with wMNAF representation
+   @return         NULL in case of errors
+ */
+signed char *
+ecc_wMNAF (mpz_t x, size_t * wmnaf_len)
+{
+  int b, c;
+  char sign = 1;
+  size_t i, len;
+
+  signed char *ret = NULL;
+
+  if (!(sign = mpz_sgn (x)))
+    {
+      /* x == 0 */
+      ret = malloc (1);
+      if (ret == NULL)
+        goto done;
+
+      ret[0] = 0;
+      *wmnaf_len = 1;
+      goto done;
+    }
+
+  /* total number of bits */
+  len = mpz_sizeinbase (x, 2);
+
+  /* wMNAF is at most (len + 1) bits long */
+  ret = malloc (len + 1);
+  if (ret == NULL)
+    goto done;
+
+  /* get (w + 1) Least Significant Bits */
+  c = (mpz_getlimbn (x, 0)) & WBITS;
+
+  /* how many bits we've already processed */
+  i = 0;
+
+  while ((c != 0) || (i + WMNAF_WINSIZE + 1 < len))
+    {
+      if (c & 1)
+        {
+          /* LSB == 1 */
+          if (c >= BASEW)
+            {
+              b = c - BASEWW;
+            }
+          else
+            {
+              b = c;
+            }
+
+          c -= b;
+        }
+      else
+        {
+          b = 0;
+        }
+
+      ret[i++] = sign * b;
+
+      /* fill c with next LSB */
+      c >>= 1;
+      c += BASEW * mpz_unitstbit (x, i + WMNAF_WINSIZE);
+    }
+
+  *wmnaf_len = i--;
+
+  /* do modified wNAF
+   * check if wNAF starts with 1 and
+   * (w + 1)th bit is negative */
+  if ((ret[i] == 1) && (ret[i - (WMNAF_WINSIZE + 1)] < 0))
+    {
+      ret[i - (WMNAF_WINSIZE + 1)] += BASEW;
+      ret[i - 1] = 1;
+      *wmnaf_len = i;
+    }
+done:
+  return ret;
+}
diff --git a/src/cli-args.c b/src/cli-args.c
index 09e65e5..b4f0501 100644
--- a/src/cli-args.c
+++ b/src/cli-args.c
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (cli-args.c)
  *  
- *  It has been AutoGen-ed  June  6, 2012 at 09:09:25 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  August 30, 2012 at 09:58:04 PM by AutoGen 5.16
  *  From the definitions    cli-args.def
  *  and the template file   options
  *
@@ -67,7 +67,7 @@ extern FILE * option_usage_fp;
 /*
  *  gnutls-cli option static const strings
  */
-static char const gnutls_cli_opt_strs[3491] =
+static char const gnutls_cli_opt_strs[3538] =
 /*     0 */ "gnutls-cli @address@hidden"
             "Copyright (C) 2000-2012 Free Software Foundation, all rights 
reserved.\n"
             "This is free software. It is licensed for use, modification and\n"
@@ -100,119 +100,122 @@ static char const gnutls_cli_opt_strs[3491] =
 /*  1063 */ "Establish a session and resume\0"
 /*  1094 */ "RESUME\0"
 /*  1101 */ "resume\0"
-/*  1108 */ "Establish a session and rehandshake\0"
-/*  1144 */ "REHANDSHAKE\0"
-/*  1156 */ "rehandshake\0"
-/*  1168 */ "Don't accept session tickets\0"
-/*  1197 */ "NOTICKET\0"
-/*  1206 */ "noticket\0"
-/*  1215 */ "Connect, establish a plain session and start TLS.\0"
-/*  1265 */ "STARTTLS\0"
-/*  1274 */ "starttls\0"
-/*  1283 */ "Use DTLS (datagram TLS) over UDP\0"
-/*  1316 */ "UDP\0"
-/*  1320 */ "udp\0"
-/*  1324 */ "Set MTU for datagram TLS\0"
-/*  1349 */ "MTU\0"
-/*  1353 */ "mtu\0"
-/*  1357 */ "Send CR LF instead of LF\0"
-/*  1382 */ "CRLF\0"
-/*  1387 */ "crlf\0"
-/*  1392 */ "Use DER format for certificates to read from\0"
-/*  1437 */ "X509FMTDER\0"
-/*  1448 */ "x509fmtder\0"
-/*  1459 */ "Send the openpgp fingerprint, instead of the key\0"
-/*  1508 */ "FINGERPRINT\0"
-/*  1520 */ "fingerprint\0"
-/*  1532 */ "Disable all the TLS extensions\0"
-/*  1563 */ "DISABLE_EXTENSIONS\0"
-/*  1582 */ "disable-extensions\0"
-/*  1601 */ "Print peer's certificate in PEM format\0"
-/*  1640 */ "PRINT_CERT\0"
-/*  1651 */ "print-cert\0"
-/*  1662 */ "The maximum record size to advertize\0"
-/*  1699 */ "RECORDSIZE\0"
-/*  1710 */ "recordsize\0"
-/*  1721 */ "The minimum number of bits allowed for DH\0"
-/*  1763 */ "DH_BITS\0"
-/*  1771 */ "dh-bits\0"
-/*  1779 */ "Priorities string\0"
-/*  1797 */ "PRIORITY\0"
-/*  1806 */ "priority\0"
-/*  1815 */ "Certificate file or PKCS #11 URL to use\0"
-/*  1855 */ "X509CAFILE\0"
-/*  1866 */ "x509cafile\0"
-/*  1877 */ "CRL file to use\0"
-/*  1893 */ "X509CRLFILE\0"
-/*  1905 */ "x509crlfile\0"
-/*  1917 */ "PGP Key file to use\0"
-/*  1937 */ "PGPKEYFILE\0"
-/*  1948 */ "pgpkeyfile\0"
-/*  1959 */ "PGP Key ring file to use\0"
-/*  1984 */ "PGPKEYRING\0"
-/*  1995 */ "pgpkeyring\0"
-/*  2006 */ "PGP Public Key (certificate) file to use\0"
-/*  2047 */ "PGPCERTFILE\0"
-/*  2059 */ "pgpcertfile\0"
-/*  2071 */ "X.509 key file or PKCS #11 URL to use\0"
-/*  2109 */ "X509KEYFILE\0"
-/*  2121 */ "x509keyfile\0"
-/*  2133 */ "X.509 Certificate file or PKCS #11 URL to use\0"
-/*  2179 */ "X509CERTFILE\0"
-/*  2192 */ "x509certfile\0"
-/*  2205 */ "PGP subkey to use (hex or auto)\0"
-/*  2237 */ "PGPSUBKEY\0"
-/*  2247 */ "pgpsubkey\0"
-/*  2257 */ "SRP username to use\0"
-/*  2277 */ "SRPUSERNAME\0"
-/*  2289 */ "srpusername\0"
-/*  2301 */ "SRP password to use\0"
-/*  2321 */ "SRPPASSWD\0"
-/*  2331 */ "srppasswd\0"
-/*  2341 */ "PSK username to use\0"
-/*  2361 */ "PSKUSERNAME\0"
-/*  2373 */ "pskusername\0"
-/*  2385 */ "PSK key (in hex) to use\0"
-/*  2409 */ "PSKKEY\0"
-/*  2416 */ "pskkey\0"
-/*  2423 */ "The port or service to connect to\0"
-/*  2457 */ "PORT\0"
-/*  2462 */ "port\0"
-/*  2467 */ "Don't abort program if server certificate can't be validated\0"
-/*  2528 */ "INSECURE\0"
-/*  2537 */ "insecure\0"
-/*  2546 */ "Benchmark individual ciphers\0"
-/*  2575 */ "BENCHMARK_CIPHERS\0"
-/*  2593 */ "benchmark-ciphers\0"
-/*  2611 */ "Benchmark individual software ciphers (no hw acceleration)\0"
-/*  2670 */ "BENCHMARK_SOFT_CIPHERS\0"
-/*  2693 */ "benchmark-soft-ciphers\0"
-/*  2716 */ "Benchmark TLS key exchange methods\0"
-/*  2751 */ "BENCHMARK_TLS_KX\0"
-/*  2768 */ "benchmark-tls-kx\0"
-/*  2785 */ "Benchmark TLS ciphers\0"
-/*  2807 */ "BENCHMARK_TLS_CIPHERS\0"
-/*  2829 */ "benchmark-tls-ciphers\0"
-/*  2851 */ "Print a list of the supported algorithms and modes\0"
-/*  2902 */ "LIST\0"
-/*  2907 */ "list\0"
-/*  2912 */ "Display extended usage information and exit\0"
-/*  2956 */ "help\0"
-/*  2961 */ "Extended usage information passed thru pager\0"
-/*  3006 */ "more-help\0"
-/*  3016 */ "Output version information and exit\0"
-/*  3052 */ "version\0"
-/*  3060 */ "GNUTLS_CLI\0"
-/*  3071 */ "gnutls-cli - GnuTLS client - Ver. @address@hidden"
+/*  1108 */ "Activate heartbeat support\0"
+/*  1135 */ "HEARTBEAT\0"
+/*  1145 */ "heartbeat\0"
+/*  1155 */ "Establish a session and rehandshake\0"
+/*  1191 */ "REHANDSHAKE\0"
+/*  1203 */ "rehandshake\0"
+/*  1215 */ "Don't accept session tickets\0"
+/*  1244 */ "NOTICKET\0"
+/*  1253 */ "noticket\0"
+/*  1262 */ "Connect, establish a plain session and start TLS.\0"
+/*  1312 */ "STARTTLS\0"
+/*  1321 */ "starttls\0"
+/*  1330 */ "Use DTLS (datagram TLS) over UDP\0"
+/*  1363 */ "UDP\0"
+/*  1367 */ "udp\0"
+/*  1371 */ "Set MTU for datagram TLS\0"
+/*  1396 */ "MTU\0"
+/*  1400 */ "mtu\0"
+/*  1404 */ "Send CR LF instead of LF\0"
+/*  1429 */ "CRLF\0"
+/*  1434 */ "crlf\0"
+/*  1439 */ "Use DER format for certificates to read from\0"
+/*  1484 */ "X509FMTDER\0"
+/*  1495 */ "x509fmtder\0"
+/*  1506 */ "Send the openpgp fingerprint, instead of the key\0"
+/*  1555 */ "FINGERPRINT\0"
+/*  1567 */ "fingerprint\0"
+/*  1579 */ "Disable all the TLS extensions\0"
+/*  1610 */ "DISABLE_EXTENSIONS\0"
+/*  1629 */ "disable-extensions\0"
+/*  1648 */ "Print peer's certificate in PEM format\0"
+/*  1687 */ "PRINT_CERT\0"
+/*  1698 */ "print-cert\0"
+/*  1709 */ "The maximum record size to advertize\0"
+/*  1746 */ "RECORDSIZE\0"
+/*  1757 */ "recordsize\0"
+/*  1768 */ "The minimum number of bits allowed for DH\0"
+/*  1810 */ "DH_BITS\0"
+/*  1818 */ "dh-bits\0"
+/*  1826 */ "Priorities string\0"
+/*  1844 */ "PRIORITY\0"
+/*  1853 */ "priority\0"
+/*  1862 */ "Certificate file or PKCS #11 URL to use\0"
+/*  1902 */ "X509CAFILE\0"
+/*  1913 */ "x509cafile\0"
+/*  1924 */ "CRL file to use\0"
+/*  1940 */ "X509CRLFILE\0"
+/*  1952 */ "x509crlfile\0"
+/*  1964 */ "PGP Key file to use\0"
+/*  1984 */ "PGPKEYFILE\0"
+/*  1995 */ "pgpkeyfile\0"
+/*  2006 */ "PGP Key ring file to use\0"
+/*  2031 */ "PGPKEYRING\0"
+/*  2042 */ "pgpkeyring\0"
+/*  2053 */ "PGP Public Key (certificate) file to use\0"
+/*  2094 */ "PGPCERTFILE\0"
+/*  2106 */ "pgpcertfile\0"
+/*  2118 */ "X.509 key file or PKCS #11 URL to use\0"
+/*  2156 */ "X509KEYFILE\0"
+/*  2168 */ "x509keyfile\0"
+/*  2180 */ "X.509 Certificate file or PKCS #11 URL to use\0"
+/*  2226 */ "X509CERTFILE\0"
+/*  2239 */ "x509certfile\0"
+/*  2252 */ "PGP subkey to use (hex or auto)\0"
+/*  2284 */ "PGPSUBKEY\0"
+/*  2294 */ "pgpsubkey\0"
+/*  2304 */ "SRP username to use\0"
+/*  2324 */ "SRPUSERNAME\0"
+/*  2336 */ "srpusername\0"
+/*  2348 */ "SRP password to use\0"
+/*  2368 */ "SRPPASSWD\0"
+/*  2378 */ "srppasswd\0"
+/*  2388 */ "PSK username to use\0"
+/*  2408 */ "PSKUSERNAME\0"
+/*  2420 */ "pskusername\0"
+/*  2432 */ "PSK key (in hex) to use\0"
+/*  2456 */ "PSKKEY\0"
+/*  2463 */ "pskkey\0"
+/*  2470 */ "The port or service to connect to\0"
+/*  2504 */ "PORT\0"
+/*  2509 */ "port\0"
+/*  2514 */ "Don't abort program if server certificate can't be validated\0"
+/*  2575 */ "INSECURE\0"
+/*  2584 */ "insecure\0"
+/*  2593 */ "Benchmark individual ciphers\0"
+/*  2622 */ "BENCHMARK_CIPHERS\0"
+/*  2640 */ "benchmark-ciphers\0"
+/*  2658 */ "Benchmark individual software ciphers (no hw acceleration)\0"
+/*  2717 */ "BENCHMARK_SOFT_CIPHERS\0"
+/*  2740 */ "benchmark-soft-ciphers\0"
+/*  2763 */ "Benchmark TLS key exchange methods\0"
+/*  2798 */ "BENCHMARK_TLS_KX\0"
+/*  2815 */ "benchmark-tls-kx\0"
+/*  2832 */ "Benchmark TLS ciphers\0"
+/*  2854 */ "BENCHMARK_TLS_CIPHERS\0"
+/*  2876 */ "benchmark-tls-ciphers\0"
+/*  2898 */ "Print a list of the supported algorithms and modes\0"
+/*  2949 */ "LIST\0"
+/*  2954 */ "list\0"
+/*  2959 */ "Display extended usage information and exit\0"
+/*  3003 */ "help\0"
+/*  3008 */ "Extended usage information passed thru pager\0"
+/*  3053 */ "more-help\0"
+/*  3063 */ "Output version information and exit\0"
+/*  3099 */ "version\0"
+/*  3107 */ "GNUTLS_CLI\0"
+/*  3118 */ "gnutls-cli - GnuTLS client - Ver. @address@hidden"
             "USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]... 
[hostname]\n\0"
-/*  3184 */ "address@hidden"
-/*  3203 */ "\n\n\0"
-/*  3206 */ "\n"
+/*  3231 */ "address@hidden"
+/*  3250 */ "\n\n\0"
+/*  3253 */ "\n"
             "Simple client program to set up a TLS connection to some other 
computer.  It\n"
             "sets up a TLS connection and forwards data from the standard 
input to the\n"
             "secured socket and vice versa.\n\0"
-/*  3390 */ "gnutls-cli @address@hidden"
-/*  3411 */ "Usage: gnutls-cli [options] hostname\n"
+/*  3437 */ "gnutls-cli @address@hidden"
+/*  3458 */ "Usage: gnutls-cli [options] hostname\n"
             "gnutls-cli --help for usage instructions.\n";
 
 /*
@@ -261,286 +264,294 @@ static char const gnutls_cli_opt_strs[3491] =
 #define RESUME_FLAGS     (OPTST_DISABLED)
 
 /*
+ *  heartbeat option description:
+ */
+#define HEARTBEAT_DESC      (gnutls_cli_opt_strs+1108)
+#define HEARTBEAT_NAME      (gnutls_cli_opt_strs+1135)
+#define HEARTBEAT_name      (gnutls_cli_opt_strs+1145)
+#define HEARTBEAT_FLAGS     (OPTST_DISABLED)
+
+/*
  *  rehandshake option description:
  */
-#define REHANDSHAKE_DESC      (gnutls_cli_opt_strs+1108)
-#define REHANDSHAKE_NAME      (gnutls_cli_opt_strs+1144)
-#define REHANDSHAKE_name      (gnutls_cli_opt_strs+1156)
+#define REHANDSHAKE_DESC      (gnutls_cli_opt_strs+1155)
+#define REHANDSHAKE_NAME      (gnutls_cli_opt_strs+1191)
+#define REHANDSHAKE_name      (gnutls_cli_opt_strs+1203)
 #define REHANDSHAKE_FLAGS     (OPTST_DISABLED)
 
 /*
  *  noticket option description:
  */
-#define NOTICKET_DESC      (gnutls_cli_opt_strs+1168)
-#define NOTICKET_NAME      (gnutls_cli_opt_strs+1197)
-#define NOTICKET_name      (gnutls_cli_opt_strs+1206)
+#define NOTICKET_DESC      (gnutls_cli_opt_strs+1215)
+#define NOTICKET_NAME      (gnutls_cli_opt_strs+1244)
+#define NOTICKET_name      (gnutls_cli_opt_strs+1253)
 #define NOTICKET_FLAGS     (OPTST_DISABLED)
 
 /*
  *  starttls option description:
  */
-#define STARTTLS_DESC      (gnutls_cli_opt_strs+1215)
-#define STARTTLS_NAME      (gnutls_cli_opt_strs+1265)
-#define STARTTLS_name      (gnutls_cli_opt_strs+1274)
+#define STARTTLS_DESC      (gnutls_cli_opt_strs+1262)
+#define STARTTLS_NAME      (gnutls_cli_opt_strs+1312)
+#define STARTTLS_name      (gnutls_cli_opt_strs+1321)
 #define STARTTLS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  udp option description:
  */
-#define UDP_DESC      (gnutls_cli_opt_strs+1283)
-#define UDP_NAME      (gnutls_cli_opt_strs+1316)
-#define UDP_name      (gnutls_cli_opt_strs+1320)
+#define UDP_DESC      (gnutls_cli_opt_strs+1330)
+#define UDP_NAME      (gnutls_cli_opt_strs+1363)
+#define UDP_name      (gnutls_cli_opt_strs+1367)
 #define UDP_FLAGS     (OPTST_DISABLED)
 
 /*
  *  mtu option description:
  */
-#define MTU_DESC      (gnutls_cli_opt_strs+1324)
-#define MTU_NAME      (gnutls_cli_opt_strs+1349)
-#define MTU_name      (gnutls_cli_opt_strs+1353)
+#define MTU_DESC      (gnutls_cli_opt_strs+1371)
+#define MTU_NAME      (gnutls_cli_opt_strs+1396)
+#define MTU_name      (gnutls_cli_opt_strs+1400)
 #define MTU_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  crlf option description:
  */
-#define CRLF_DESC      (gnutls_cli_opt_strs+1357)
-#define CRLF_NAME      (gnutls_cli_opt_strs+1382)
-#define CRLF_name      (gnutls_cli_opt_strs+1387)
+#define CRLF_DESC      (gnutls_cli_opt_strs+1404)
+#define CRLF_NAME      (gnutls_cli_opt_strs+1429)
+#define CRLF_name      (gnutls_cli_opt_strs+1434)
 #define CRLF_FLAGS     (OPTST_DISABLED)
 
 /*
  *  x509fmtder option description:
  */
-#define X509FMTDER_DESC      (gnutls_cli_opt_strs+1392)
-#define X509FMTDER_NAME      (gnutls_cli_opt_strs+1437)
-#define X509FMTDER_name      (gnutls_cli_opt_strs+1448)
+#define X509FMTDER_DESC      (gnutls_cli_opt_strs+1439)
+#define X509FMTDER_NAME      (gnutls_cli_opt_strs+1484)
+#define X509FMTDER_name      (gnutls_cli_opt_strs+1495)
 #define X509FMTDER_FLAGS     (OPTST_DISABLED)
 
 /*
  *  fingerprint option description:
  */
-#define FINGERPRINT_DESC      (gnutls_cli_opt_strs+1459)
-#define FINGERPRINT_NAME      (gnutls_cli_opt_strs+1508)
-#define FINGERPRINT_name      (gnutls_cli_opt_strs+1520)
+#define FINGERPRINT_DESC      (gnutls_cli_opt_strs+1506)
+#define FINGERPRINT_NAME      (gnutls_cli_opt_strs+1555)
+#define FINGERPRINT_name      (gnutls_cli_opt_strs+1567)
 #define FINGERPRINT_FLAGS     (OPTST_DISABLED)
 
 /*
  *  disable-extensions option description:
  */
-#define DISABLE_EXTENSIONS_DESC      (gnutls_cli_opt_strs+1532)
-#define DISABLE_EXTENSIONS_NAME      (gnutls_cli_opt_strs+1563)
-#define DISABLE_EXTENSIONS_name      (gnutls_cli_opt_strs+1582)
+#define DISABLE_EXTENSIONS_DESC      (gnutls_cli_opt_strs+1579)
+#define DISABLE_EXTENSIONS_NAME      (gnutls_cli_opt_strs+1610)
+#define DISABLE_EXTENSIONS_name      (gnutls_cli_opt_strs+1629)
 #define DISABLE_EXTENSIONS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  print-cert option description:
  */
-#define PRINT_CERT_DESC      (gnutls_cli_opt_strs+1601)
-#define PRINT_CERT_NAME      (gnutls_cli_opt_strs+1640)
-#define PRINT_CERT_name      (gnutls_cli_opt_strs+1651)
+#define PRINT_CERT_DESC      (gnutls_cli_opt_strs+1648)
+#define PRINT_CERT_NAME      (gnutls_cli_opt_strs+1687)
+#define PRINT_CERT_name      (gnutls_cli_opt_strs+1698)
 #define PRINT_CERT_FLAGS     (OPTST_DISABLED)
 
 /*
  *  recordsize option description:
  */
-#define RECORDSIZE_DESC      (gnutls_cli_opt_strs+1662)
-#define RECORDSIZE_NAME      (gnutls_cli_opt_strs+1699)
-#define RECORDSIZE_name      (gnutls_cli_opt_strs+1710)
+#define RECORDSIZE_DESC      (gnutls_cli_opt_strs+1709)
+#define RECORDSIZE_NAME      (gnutls_cli_opt_strs+1746)
+#define RECORDSIZE_name      (gnutls_cli_opt_strs+1757)
 #define RECORDSIZE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  dh-bits option description:
  */
-#define DH_BITS_DESC      (gnutls_cli_opt_strs+1721)
-#define DH_BITS_NAME      (gnutls_cli_opt_strs+1763)
-#define DH_BITS_name      (gnutls_cli_opt_strs+1771)
+#define DH_BITS_DESC      (gnutls_cli_opt_strs+1768)
+#define DH_BITS_NAME      (gnutls_cli_opt_strs+1810)
+#define DH_BITS_name      (gnutls_cli_opt_strs+1818)
 #define DH_BITS_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  priority option description:
  */
-#define PRIORITY_DESC      (gnutls_cli_opt_strs+1779)
-#define PRIORITY_NAME      (gnutls_cli_opt_strs+1797)
-#define PRIORITY_name      (gnutls_cli_opt_strs+1806)
+#define PRIORITY_DESC      (gnutls_cli_opt_strs+1826)
+#define PRIORITY_NAME      (gnutls_cli_opt_strs+1844)
+#define PRIORITY_name      (gnutls_cli_opt_strs+1853)
 #define PRIORITY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509cafile option description:
  */
-#define X509CAFILE_DESC      (gnutls_cli_opt_strs+1815)
-#define X509CAFILE_NAME      (gnutls_cli_opt_strs+1855)
-#define X509CAFILE_name      (gnutls_cli_opt_strs+1866)
+#define X509CAFILE_DESC      (gnutls_cli_opt_strs+1862)
+#define X509CAFILE_NAME      (gnutls_cli_opt_strs+1902)
+#define X509CAFILE_name      (gnutls_cli_opt_strs+1913)
 #define X509CAFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509crlfile option description:
  */
-#define X509CRLFILE_DESC      (gnutls_cli_opt_strs+1877)
-#define X509CRLFILE_NAME      (gnutls_cli_opt_strs+1893)
-#define X509CRLFILE_name      (gnutls_cli_opt_strs+1905)
+#define X509CRLFILE_DESC      (gnutls_cli_opt_strs+1924)
+#define X509CRLFILE_NAME      (gnutls_cli_opt_strs+1940)
+#define X509CRLFILE_name      (gnutls_cli_opt_strs+1952)
 #define X509CRLFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyfile option description:
  */
-#define PGPKEYFILE_DESC      (gnutls_cli_opt_strs+1917)
-#define PGPKEYFILE_NAME      (gnutls_cli_opt_strs+1937)
-#define PGPKEYFILE_name      (gnutls_cli_opt_strs+1948)
+#define PGPKEYFILE_DESC      (gnutls_cli_opt_strs+1964)
+#define PGPKEYFILE_NAME      (gnutls_cli_opt_strs+1984)
+#define PGPKEYFILE_name      (gnutls_cli_opt_strs+1995)
 #define PGPKEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyring option description:
  */
-#define PGPKEYRING_DESC      (gnutls_cli_opt_strs+1959)
-#define PGPKEYRING_NAME      (gnutls_cli_opt_strs+1984)
-#define PGPKEYRING_name      (gnutls_cli_opt_strs+1995)
+#define PGPKEYRING_DESC      (gnutls_cli_opt_strs+2006)
+#define PGPKEYRING_NAME      (gnutls_cli_opt_strs+2031)
+#define PGPKEYRING_name      (gnutls_cli_opt_strs+2042)
 #define PGPKEYRING_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpcertfile option description:
  */
-#define PGPCERTFILE_DESC      (gnutls_cli_opt_strs+2006)
-#define PGPCERTFILE_NAME      (gnutls_cli_opt_strs+2047)
-#define PGPCERTFILE_name      (gnutls_cli_opt_strs+2059)
+#define PGPCERTFILE_DESC      (gnutls_cli_opt_strs+2053)
+#define PGPCERTFILE_NAME      (gnutls_cli_opt_strs+2094)
+#define PGPCERTFILE_name      (gnutls_cli_opt_strs+2106)
 #define PGPCERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  x509keyfile option description:
  */
-#define X509KEYFILE_DESC      (gnutls_cli_opt_strs+2071)
-#define X509KEYFILE_NAME      (gnutls_cli_opt_strs+2109)
-#define X509KEYFILE_name      (gnutls_cli_opt_strs+2121)
+#define X509KEYFILE_DESC      (gnutls_cli_opt_strs+2118)
+#define X509KEYFILE_NAME      (gnutls_cli_opt_strs+2156)
+#define X509KEYFILE_name      (gnutls_cli_opt_strs+2168)
 #define X509KEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509certfile option description:
  */
-#define X509CERTFILE_DESC      (gnutls_cli_opt_strs+2133)
-#define X509CERTFILE_NAME      (gnutls_cli_opt_strs+2179)
-#define X509CERTFILE_name      (gnutls_cli_opt_strs+2192)
+#define X509CERTFILE_DESC      (gnutls_cli_opt_strs+2180)
+#define X509CERTFILE_NAME      (gnutls_cli_opt_strs+2226)
+#define X509CERTFILE_name      (gnutls_cli_opt_strs+2239)
 #define X509CERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pgpsubkey option description:
  */
-#define PGPSUBKEY_DESC      (gnutls_cli_opt_strs+2205)
-#define PGPSUBKEY_NAME      (gnutls_cli_opt_strs+2237)
-#define PGPSUBKEY_name      (gnutls_cli_opt_strs+2247)
+#define PGPSUBKEY_DESC      (gnutls_cli_opt_strs+2252)
+#define PGPSUBKEY_NAME      (gnutls_cli_opt_strs+2284)
+#define PGPSUBKEY_name      (gnutls_cli_opt_strs+2294)
 #define PGPSUBKEY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  srpusername option description:
  */
-#define SRPUSERNAME_DESC      (gnutls_cli_opt_strs+2257)
-#define SRPUSERNAME_NAME      (gnutls_cli_opt_strs+2277)
-#define SRPUSERNAME_name      (gnutls_cli_opt_strs+2289)
+#define SRPUSERNAME_DESC      (gnutls_cli_opt_strs+2304)
+#define SRPUSERNAME_NAME      (gnutls_cli_opt_strs+2324)
+#define SRPUSERNAME_name      (gnutls_cli_opt_strs+2336)
 #define SRPUSERNAME_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  srppasswd option description:
  */
-#define SRPPASSWD_DESC      (gnutls_cli_opt_strs+2301)
-#define SRPPASSWD_NAME      (gnutls_cli_opt_strs+2321)
-#define SRPPASSWD_name      (gnutls_cli_opt_strs+2331)
+#define SRPPASSWD_DESC      (gnutls_cli_opt_strs+2348)
+#define SRPPASSWD_NAME      (gnutls_cli_opt_strs+2368)
+#define SRPPASSWD_name      (gnutls_cli_opt_strs+2378)
 #define SRPPASSWD_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pskusername option description:
  */
-#define PSKUSERNAME_DESC      (gnutls_cli_opt_strs+2341)
-#define PSKUSERNAME_NAME      (gnutls_cli_opt_strs+2361)
-#define PSKUSERNAME_name      (gnutls_cli_opt_strs+2373)
+#define PSKUSERNAME_DESC      (gnutls_cli_opt_strs+2388)
+#define PSKUSERNAME_NAME      (gnutls_cli_opt_strs+2408)
+#define PSKUSERNAME_name      (gnutls_cli_opt_strs+2420)
 #define PSKUSERNAME_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pskkey option description:
  */
-#define PSKKEY_DESC      (gnutls_cli_opt_strs+2385)
-#define PSKKEY_NAME      (gnutls_cli_opt_strs+2409)
-#define PSKKEY_name      (gnutls_cli_opt_strs+2416)
+#define PSKKEY_DESC      (gnutls_cli_opt_strs+2432)
+#define PSKKEY_NAME      (gnutls_cli_opt_strs+2456)
+#define PSKKEY_name      (gnutls_cli_opt_strs+2463)
 #define PSKKEY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  port option description:
  */
-#define PORT_DESC      (gnutls_cli_opt_strs+2423)
-#define PORT_NAME      (gnutls_cli_opt_strs+2457)
-#define PORT_name      (gnutls_cli_opt_strs+2462)
+#define PORT_DESC      (gnutls_cli_opt_strs+2470)
+#define PORT_NAME      (gnutls_cli_opt_strs+2504)
+#define PORT_name      (gnutls_cli_opt_strs+2509)
 #define PORT_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  insecure option description:
  */
-#define INSECURE_DESC      (gnutls_cli_opt_strs+2467)
-#define INSECURE_NAME      (gnutls_cli_opt_strs+2528)
-#define INSECURE_name      (gnutls_cli_opt_strs+2537)
+#define INSECURE_DESC      (gnutls_cli_opt_strs+2514)
+#define INSECURE_NAME      (gnutls_cli_opt_strs+2575)
+#define INSECURE_name      (gnutls_cli_opt_strs+2584)
 #define INSECURE_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-ciphers option description:
  */
-#define BENCHMARK_CIPHERS_DESC      (gnutls_cli_opt_strs+2546)
-#define BENCHMARK_CIPHERS_NAME      (gnutls_cli_opt_strs+2575)
-#define BENCHMARK_CIPHERS_name      (gnutls_cli_opt_strs+2593)
+#define BENCHMARK_CIPHERS_DESC      (gnutls_cli_opt_strs+2593)
+#define BENCHMARK_CIPHERS_NAME      (gnutls_cli_opt_strs+2622)
+#define BENCHMARK_CIPHERS_name      (gnutls_cli_opt_strs+2640)
 #define BENCHMARK_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-soft-ciphers option description:
  */
-#define BENCHMARK_SOFT_CIPHERS_DESC      (gnutls_cli_opt_strs+2611)
-#define BENCHMARK_SOFT_CIPHERS_NAME      (gnutls_cli_opt_strs+2670)
-#define BENCHMARK_SOFT_CIPHERS_name      (gnutls_cli_opt_strs+2693)
+#define BENCHMARK_SOFT_CIPHERS_DESC      (gnutls_cli_opt_strs+2658)
+#define BENCHMARK_SOFT_CIPHERS_NAME      (gnutls_cli_opt_strs+2717)
+#define BENCHMARK_SOFT_CIPHERS_name      (gnutls_cli_opt_strs+2740)
 #define BENCHMARK_SOFT_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-tls-kx option description:
  */
-#define BENCHMARK_TLS_KX_DESC      (gnutls_cli_opt_strs+2716)
-#define BENCHMARK_TLS_KX_NAME      (gnutls_cli_opt_strs+2751)
-#define BENCHMARK_TLS_KX_name      (gnutls_cli_opt_strs+2768)
+#define BENCHMARK_TLS_KX_DESC      (gnutls_cli_opt_strs+2763)
+#define BENCHMARK_TLS_KX_NAME      (gnutls_cli_opt_strs+2798)
+#define BENCHMARK_TLS_KX_name      (gnutls_cli_opt_strs+2815)
 #define BENCHMARK_TLS_KX_FLAGS     (OPTST_DISABLED)
 
 /*
  *  benchmark-tls-ciphers option description:
  */
-#define BENCHMARK_TLS_CIPHERS_DESC      (gnutls_cli_opt_strs+2785)
-#define BENCHMARK_TLS_CIPHERS_NAME      (gnutls_cli_opt_strs+2807)
-#define BENCHMARK_TLS_CIPHERS_name      (gnutls_cli_opt_strs+2829)
+#define BENCHMARK_TLS_CIPHERS_DESC      (gnutls_cli_opt_strs+2832)
+#define BENCHMARK_TLS_CIPHERS_NAME      (gnutls_cli_opt_strs+2854)
+#define BENCHMARK_TLS_CIPHERS_name      (gnutls_cli_opt_strs+2876)
 #define BENCHMARK_TLS_CIPHERS_FLAGS     (OPTST_DISABLED)
 
 /*
  *  list option description:
  */
-#define LIST_DESC      (gnutls_cli_opt_strs+2851)
-#define LIST_NAME      (gnutls_cli_opt_strs+2902)
-#define LIST_name      (gnutls_cli_opt_strs+2907)
+#define LIST_DESC      (gnutls_cli_opt_strs+2898)
+#define LIST_NAME      (gnutls_cli_opt_strs+2949)
+#define LIST_name      (gnutls_cli_opt_strs+2954)
 #define LIST_FLAGS     (OPTST_DISABLED)
 
 /*
  *  Help/More_Help/Version option descriptions:
  */
-#define HELP_DESC       (gnutls_cli_opt_strs+2912)
-#define HELP_name       (gnutls_cli_opt_strs+2956)
+#define HELP_DESC       (gnutls_cli_opt_strs+2959)
+#define HELP_name       (gnutls_cli_opt_strs+3003)
 #ifdef HAVE_WORKING_FORK
-#define MORE_HELP_DESC  (gnutls_cli_opt_strs+2961)
-#define MORE_HELP_name  (gnutls_cli_opt_strs+3006)
+#define MORE_HELP_DESC  (gnutls_cli_opt_strs+3008)
+#define MORE_HELP_name  (gnutls_cli_opt_strs+3053)
 #define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
 #else
 #define MORE_HELP_DESC  NULL
@@ -553,8 +564,8 @@ static char const gnutls_cli_opt_strs[3491] =
 #  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
                          OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
 #endif
-#define VER_DESC        (gnutls_cli_opt_strs+3016)
-#define VER_name        (gnutls_cli_opt_strs+3052)
+#define VER_DESC        (gnutls_cli_opt_strs+3063)
+#define VER_name        (gnutls_cli_opt_strs+3099)
 /*
  *  Declare option callback procedures
  */
@@ -635,8 +646,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ RESUME_DESC, RESUME_NAME, RESUME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 5, VALUE_OPT_REHANDSHAKE,
-     /* equiv idx, value */ 5, VALUE_OPT_REHANDSHAKE,
+  {  /* entry idx, value */ 5, VALUE_OPT_HEARTBEAT,
+     /* equiv idx, value */ 5, VALUE_OPT_HEARTBEAT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ HEARTBEAT_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --heartbeat */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ HEARTBEAT_DESC, HEARTBEAT_NAME, HEARTBEAT_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 6, VALUE_OPT_REHANDSHAKE,
+     /* equiv idx, value */ 6, VALUE_OPT_REHANDSHAKE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ REHANDSHAKE_FLAGS, 0,
@@ -647,8 +670,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ REHANDSHAKE_DESC, REHANDSHAKE_NAME, 
REHANDSHAKE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 6, VALUE_OPT_NOTICKET,
-     /* equiv idx, value */ 6, VALUE_OPT_NOTICKET,
+  {  /* entry idx, value */ 7, VALUE_OPT_NOTICKET,
+     /* equiv idx, value */ 7, VALUE_OPT_NOTICKET,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ NOTICKET_FLAGS, 0,
@@ -659,8 +682,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ NOTICKET_DESC, NOTICKET_NAME, NOTICKET_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 7, VALUE_OPT_STARTTLS,
-     /* equiv idx, value */ 7, VALUE_OPT_STARTTLS,
+  {  /* entry idx, value */ 8, VALUE_OPT_STARTTLS,
+     /* equiv idx, value */ 8, VALUE_OPT_STARTTLS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ STARTTLS_FLAGS, 0,
@@ -671,8 +694,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ STARTTLS_DESC, STARTTLS_NAME, STARTTLS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 8, VALUE_OPT_UDP,
-     /* equiv idx, value */ 8, VALUE_OPT_UDP,
+  {  /* entry idx, value */ 9, VALUE_OPT_UDP,
+     /* equiv idx, value */ 9, VALUE_OPT_UDP,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ UDP_FLAGS, 0,
@@ -683,8 +706,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ UDP_DESC, UDP_NAME, UDP_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 9, VALUE_OPT_MTU,
-     /* equiv idx, value */ 9, VALUE_OPT_MTU,
+  {  /* entry idx, value */ 10, VALUE_OPT_MTU,
+     /* equiv idx, value */ 10, VALUE_OPT_MTU,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ MTU_FLAGS, 0,
@@ -695,8 +718,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ MTU_DESC, MTU_NAME, MTU_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 10, VALUE_OPT_CRLF,
-     /* equiv idx, value */ 10, VALUE_OPT_CRLF,
+  {  /* entry idx, value */ 11, VALUE_OPT_CRLF,
+     /* equiv idx, value */ 11, VALUE_OPT_CRLF,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ CRLF_FLAGS, 0,
@@ -707,8 +730,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ CRLF_DESC, CRLF_NAME, CRLF_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 11, VALUE_OPT_X509FMTDER,
-     /* equiv idx, value */ 11, VALUE_OPT_X509FMTDER,
+  {  /* entry idx, value */ 12, VALUE_OPT_X509FMTDER,
+     /* equiv idx, value */ 12, VALUE_OPT_X509FMTDER,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509FMTDER_FLAGS, 0,
@@ -719,8 +742,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509FMTDER_DESC, X509FMTDER_NAME, X509FMTDER_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 12, VALUE_OPT_FINGERPRINT,
-     /* equiv idx, value */ 12, VALUE_OPT_FINGERPRINT,
+  {  /* entry idx, value */ 13, VALUE_OPT_FINGERPRINT,
+     /* equiv idx, value */ 13, VALUE_OPT_FINGERPRINT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ FINGERPRINT_FLAGS, 0,
@@ -731,8 +754,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ FINGERPRINT_DESC, FINGERPRINT_NAME, 
FINGERPRINT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 13, VALUE_OPT_DISABLE_EXTENSIONS,
-     /* equiv idx, value */ 13, VALUE_OPT_DISABLE_EXTENSIONS,
+  {  /* entry idx, value */ 14, VALUE_OPT_DISABLE_EXTENSIONS,
+     /* equiv idx, value */ 14, VALUE_OPT_DISABLE_EXTENSIONS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ DISABLE_EXTENSIONS_FLAGS, 0,
@@ -743,8 +766,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DISABLE_EXTENSIONS_DESC, DISABLE_EXTENSIONS_NAME, 
DISABLE_EXTENSIONS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 14, VALUE_OPT_PRINT_CERT,
-     /* equiv idx, value */ 14, VALUE_OPT_PRINT_CERT,
+  {  /* entry idx, value */ 15, VALUE_OPT_PRINT_CERT,
+     /* equiv idx, value */ 15, VALUE_OPT_PRINT_CERT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PRINT_CERT_FLAGS, 0,
@@ -755,8 +778,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PRINT_CERT_DESC, PRINT_CERT_NAME, PRINT_CERT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 15, VALUE_OPT_RECORDSIZE,
-     /* equiv idx, value */ 15, VALUE_OPT_RECORDSIZE,
+  {  /* entry idx, value */ 16, VALUE_OPT_RECORDSIZE,
+     /* equiv idx, value */ 16, VALUE_OPT_RECORDSIZE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ RECORDSIZE_FLAGS, 0,
@@ -767,8 +790,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ RECORDSIZE_DESC, RECORDSIZE_NAME, RECORDSIZE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 16, VALUE_OPT_DH_BITS,
-     /* equiv idx, value */ 16, VALUE_OPT_DH_BITS,
+  {  /* entry idx, value */ 17, VALUE_OPT_DH_BITS,
+     /* equiv idx, value */ 17, VALUE_OPT_DH_BITS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ DH_BITS_FLAGS, 0,
@@ -779,8 +802,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DH_BITS_DESC, DH_BITS_NAME, DH_BITS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 17, VALUE_OPT_PRIORITY,
-     /* equiv idx, value */ 17, VALUE_OPT_PRIORITY,
+  {  /* entry idx, value */ 18, VALUE_OPT_PRIORITY,
+     /* equiv idx, value */ 18, VALUE_OPT_PRIORITY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PRIORITY_FLAGS, 0,
@@ -791,8 +814,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PRIORITY_DESC, PRIORITY_NAME, PRIORITY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 18, VALUE_OPT_X509CAFILE,
-     /* equiv idx, value */ 18, VALUE_OPT_X509CAFILE,
+  {  /* entry idx, value */ 19, VALUE_OPT_X509CAFILE,
+     /* equiv idx, value */ 19, VALUE_OPT_X509CAFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CAFILE_FLAGS, 0,
@@ -803,8 +826,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CAFILE_DESC, X509CAFILE_NAME, X509CAFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 19, VALUE_OPT_X509CRLFILE,
-     /* equiv idx, value */ 19, VALUE_OPT_X509CRLFILE,
+  {  /* entry idx, value */ 20, VALUE_OPT_X509CRLFILE,
+     /* equiv idx, value */ 20, VALUE_OPT_X509CRLFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CRLFILE_FLAGS, 0,
@@ -815,8 +838,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CRLFILE_DESC, X509CRLFILE_NAME, 
X509CRLFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 20, VALUE_OPT_PGPKEYFILE,
-     /* equiv idx, value */ 20, VALUE_OPT_PGPKEYFILE,
+  {  /* entry idx, value */ 21, VALUE_OPT_PGPKEYFILE,
+     /* equiv idx, value */ 21, VALUE_OPT_PGPKEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYFILE_FLAGS, 0,
@@ -827,8 +850,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYFILE_DESC, PGPKEYFILE_NAME, PGPKEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 21, VALUE_OPT_PGPKEYRING,
-     /* equiv idx, value */ 21, VALUE_OPT_PGPKEYRING,
+  {  /* entry idx, value */ 22, VALUE_OPT_PGPKEYRING,
+     /* equiv idx, value */ 22, VALUE_OPT_PGPKEYRING,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYRING_FLAGS, 0,
@@ -839,8 +862,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYRING_DESC, PGPKEYRING_NAME, PGPKEYRING_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 22, VALUE_OPT_PGPCERTFILE,
-     /* equiv idx, value */ 22, VALUE_OPT_PGPCERTFILE,
+  {  /* entry idx, value */ 23, VALUE_OPT_PGPCERTFILE,
+     /* equiv idx, value */ 23, VALUE_OPT_PGPCERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPCERTFILE_FLAGS, 0,
@@ -851,8 +874,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPCERTFILE_DESC, PGPCERTFILE_NAME, 
PGPCERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 23, VALUE_OPT_X509KEYFILE,
-     /* equiv idx, value */ 23, VALUE_OPT_X509KEYFILE,
+  {  /* entry idx, value */ 24, VALUE_OPT_X509KEYFILE,
+     /* equiv idx, value */ 24, VALUE_OPT_X509KEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509KEYFILE_FLAGS, 0,
@@ -863,8 +886,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509KEYFILE_DESC, X509KEYFILE_NAME, 
X509KEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 24, VALUE_OPT_X509CERTFILE,
-     /* equiv idx, value */ 24, VALUE_OPT_X509CERTFILE,
+  {  /* entry idx, value */ 25, VALUE_OPT_X509CERTFILE,
+     /* equiv idx, value */ 25, VALUE_OPT_X509CERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CERTFILE_FLAGS, 0,
@@ -875,8 +898,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CERTFILE_DESC, X509CERTFILE_NAME, 
X509CERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 25, VALUE_OPT_PGPSUBKEY,
-     /* equiv idx, value */ 25, VALUE_OPT_PGPSUBKEY,
+  {  /* entry idx, value */ 26, VALUE_OPT_PGPSUBKEY,
+     /* equiv idx, value */ 26, VALUE_OPT_PGPSUBKEY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPSUBKEY_FLAGS, 0,
@@ -887,8 +910,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPSUBKEY_DESC, PGPSUBKEY_NAME, PGPSUBKEY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 26, VALUE_OPT_SRPUSERNAME,
-     /* equiv idx, value */ 26, VALUE_OPT_SRPUSERNAME,
+  {  /* entry idx, value */ 27, VALUE_OPT_SRPUSERNAME,
+     /* equiv idx, value */ 27, VALUE_OPT_SRPUSERNAME,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPUSERNAME_FLAGS, 0,
@@ -899,8 +922,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPUSERNAME_DESC, SRPUSERNAME_NAME, 
SRPUSERNAME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 27, VALUE_OPT_SRPPASSWD,
-     /* equiv idx, value */ 27, VALUE_OPT_SRPPASSWD,
+  {  /* entry idx, value */ 28, VALUE_OPT_SRPPASSWD,
+     /* equiv idx, value */ 28, VALUE_OPT_SRPPASSWD,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPPASSWD_FLAGS, 0,
@@ -911,8 +934,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPPASSWD_DESC, SRPPASSWD_NAME, SRPPASSWD_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 28, VALUE_OPT_PSKUSERNAME,
-     /* equiv idx, value */ 28, VALUE_OPT_PSKUSERNAME,
+  {  /* entry idx, value */ 29, VALUE_OPT_PSKUSERNAME,
+     /* equiv idx, value */ 29, VALUE_OPT_PSKUSERNAME,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKUSERNAME_FLAGS, 0,
@@ -923,8 +946,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKUSERNAME_DESC, PSKUSERNAME_NAME, 
PSKUSERNAME_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 29, VALUE_OPT_PSKKEY,
-     /* equiv idx, value */ 29, VALUE_OPT_PSKKEY,
+  {  /* entry idx, value */ 30, VALUE_OPT_PSKKEY,
+     /* equiv idx, value */ 30, VALUE_OPT_PSKKEY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKKEY_FLAGS, 0,
@@ -935,8 +958,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKKEY_DESC, PSKKEY_NAME, PSKKEY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 30, VALUE_OPT_PORT,
-     /* equiv idx, value */ 30, VALUE_OPT_PORT,
+  {  /* entry idx, value */ 31, VALUE_OPT_PORT,
+     /* equiv idx, value */ 31, VALUE_OPT_PORT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PORT_FLAGS, 0,
@@ -947,8 +970,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PORT_DESC, PORT_NAME, PORT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 31, VALUE_OPT_INSECURE,
-     /* equiv idx, value */ 31, VALUE_OPT_INSECURE,
+  {  /* entry idx, value */ 32, VALUE_OPT_INSECURE,
+     /* equiv idx, value */ 32, VALUE_OPT_INSECURE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ INSECURE_FLAGS, 0,
@@ -959,8 +982,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ INSECURE_DESC, INSECURE_NAME, INSECURE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 32, VALUE_OPT_BENCHMARK_CIPHERS,
-     /* equiv idx, value */ 32, VALUE_OPT_BENCHMARK_CIPHERS,
+  {  /* entry idx, value */ 33, VALUE_OPT_BENCHMARK_CIPHERS,
+     /* equiv idx, value */ 33, VALUE_OPT_BENCHMARK_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_CIPHERS_FLAGS, 0,
@@ -971,8 +994,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_CIPHERS_DESC, BENCHMARK_CIPHERS_NAME, 
BENCHMARK_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 33, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
-     /* equiv idx, value */ 33, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
+  {  /* entry idx, value */ 34, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
+     /* equiv idx, value */ 34, VALUE_OPT_BENCHMARK_SOFT_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_SOFT_CIPHERS_FLAGS, 0,
@@ -983,8 +1006,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_SOFT_CIPHERS_DESC, 
BENCHMARK_SOFT_CIPHERS_NAME, BENCHMARK_SOFT_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 34, VALUE_OPT_BENCHMARK_TLS_KX,
-     /* equiv idx, value */ 34, VALUE_OPT_BENCHMARK_TLS_KX,
+  {  /* entry idx, value */ 35, VALUE_OPT_BENCHMARK_TLS_KX,
+     /* equiv idx, value */ 35, VALUE_OPT_BENCHMARK_TLS_KX,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_TLS_KX_FLAGS, 0,
@@ -995,8 +1018,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_TLS_KX_DESC, BENCHMARK_TLS_KX_NAME, 
BENCHMARK_TLS_KX_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 35, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
-     /* equiv idx, value */ 35, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
+  {  /* entry idx, value */ 36, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
+     /* equiv idx, value */ 36, VALUE_OPT_BENCHMARK_TLS_CIPHERS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ BENCHMARK_TLS_CIPHERS_FLAGS, 0,
@@ -1007,8 +1030,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ BENCHMARK_TLS_CIPHERS_DESC, 
BENCHMARK_TLS_CIPHERS_NAME, BENCHMARK_TLS_CIPHERS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 36, VALUE_OPT_LIST,
-     /* equiv idx, value */ 36, VALUE_OPT_LIST,
+  {  /* entry idx, value */ 37, VALUE_OPT_LIST,
+     /* equiv idx, value */ 37, VALUE_OPT_LIST,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ LIST_FLAGS, 0,
@@ -1063,14 +1086,14 @@ static tOptDesc optDesc[OPTION_CT] = {
  *
  *  Define the gnutls-cli Option Environment
  */
-#define zPROGNAME       (gnutls_cli_opt_strs+3060)
-#define zUsageTitle     (gnutls_cli_opt_strs+3071)
+#define zPROGNAME       (gnutls_cli_opt_strs+3107)
+#define zUsageTitle     (gnutls_cli_opt_strs+3118)
 #define zRcName         NULL
 #define apzHomeList     NULL
-#define zBugsAddr       (gnutls_cli_opt_strs+3184)
-#define zExplain        (gnutls_cli_opt_strs+3203)
-#define zDetail         (gnutls_cli_opt_strs+3206)
-#define zFullVersion    (gnutls_cli_opt_strs+3390)
+#define zBugsAddr       (gnutls_cli_opt_strs+3231)
+#define zExplain        (gnutls_cli_opt_strs+3250)
+#define zDetail         (gnutls_cli_opt_strs+3253)
+#define zFullVersion    (gnutls_cli_opt_strs+3437)
 /* extracted from optcode.tlib near line 350 */
 
 #if defined(ENABLE_NLS)
@@ -1084,7 +1107,7 @@ static tOptDesc optDesc[OPTION_CT] = {
 
 #define gnutls_cli_full_usage (NULL)
 
-#define gnutls_cli_short_usage (gnutls_cli_opt_strs+3411)
+#define gnutls_cli_short_usage (gnutls_cli_opt_strs+3458)
 
 #endif /* not defined __doxygen__ */
 
@@ -1362,7 +1385,7 @@ tOptions gnutls_cliOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    40 /* full option count */, 37 /* user option count */,
+    41 /* full option count */, 38 /* user option count */,
     gnutls_cli_full_usage, gnutls_cli_short_usage,
     NULL, NULL,
     PKGDATADIR, gnutls_cli_packager_info
diff --git a/src/cli-args.def b/src/cli-args.def
index 5e2d6c6..1d9bc78 100644
--- a/src/cli-args.def
+++ b/src/cli-args.def
@@ -36,6 +36,13 @@ flag = {
 };
 
 flag = {
+    name      = heartbeat;
+    value     = b;
+    descrip   = "Activate heartbeat support";
+    doc      = "";
+};
+
+flag = {
     name      = rehandshake;
     value     = e;
     descrip   = "Establish a session and rehandshake";
diff --git a/src/cli-args.h b/src/cli-args.h
index e8c9dac..b738248 100644
--- a/src/cli-args.h
+++ b/src/cli-args.h
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (cli-args.h)
  *  
- *  It has been AutoGen-ed  June  6, 2012 at 09:09:25 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  August 30, 2012 at 09:58:04 PM by AutoGen 5.16
  *  From the definitions    cli-args.def
  *  and the template file   options
  *
@@ -72,44 +72,45 @@ typedef enum {
     INDEX_OPT_TOFU                    =  2,
     INDEX_OPT_OCSP                    =  3,
     INDEX_OPT_RESUME                  =  4,
-    INDEX_OPT_REHANDSHAKE             =  5,
-    INDEX_OPT_NOTICKET                =  6,
-    INDEX_OPT_STARTTLS                =  7,
-    INDEX_OPT_UDP                     =  8,
-    INDEX_OPT_MTU                     =  9,
-    INDEX_OPT_CRLF                    = 10,
-    INDEX_OPT_X509FMTDER              = 11,
-    INDEX_OPT_FINGERPRINT             = 12,
-    INDEX_OPT_DISABLE_EXTENSIONS      = 13,
-    INDEX_OPT_PRINT_CERT              = 14,
-    INDEX_OPT_RECORDSIZE              = 15,
-    INDEX_OPT_DH_BITS                 = 16,
-    INDEX_OPT_PRIORITY                = 17,
-    INDEX_OPT_X509CAFILE              = 18,
-    INDEX_OPT_X509CRLFILE             = 19,
-    INDEX_OPT_PGPKEYFILE              = 20,
-    INDEX_OPT_PGPKEYRING              = 21,
-    INDEX_OPT_PGPCERTFILE             = 22,
-    INDEX_OPT_X509KEYFILE             = 23,
-    INDEX_OPT_X509CERTFILE            = 24,
-    INDEX_OPT_PGPSUBKEY               = 25,
-    INDEX_OPT_SRPUSERNAME             = 26,
-    INDEX_OPT_SRPPASSWD               = 27,
-    INDEX_OPT_PSKUSERNAME             = 28,
-    INDEX_OPT_PSKKEY                  = 29,
-    INDEX_OPT_PORT                    = 30,
-    INDEX_OPT_INSECURE                = 31,
-    INDEX_OPT_BENCHMARK_CIPHERS       = 32,
-    INDEX_OPT_BENCHMARK_SOFT_CIPHERS  = 33,
-    INDEX_OPT_BENCHMARK_TLS_KX        = 34,
-    INDEX_OPT_BENCHMARK_TLS_CIPHERS   = 35,
-    INDEX_OPT_LIST                    = 36,
-    INDEX_OPT_VERSION                 = 37,
-    INDEX_OPT_HELP                    = 38,
-    INDEX_OPT_MORE_HELP               = 39
+    INDEX_OPT_HEARTBEAT               =  5,
+    INDEX_OPT_REHANDSHAKE             =  6,
+    INDEX_OPT_NOTICKET                =  7,
+    INDEX_OPT_STARTTLS                =  8,
+    INDEX_OPT_UDP                     =  9,
+    INDEX_OPT_MTU                     = 10,
+    INDEX_OPT_CRLF                    = 11,
+    INDEX_OPT_X509FMTDER              = 12,
+    INDEX_OPT_FINGERPRINT             = 13,
+    INDEX_OPT_DISABLE_EXTENSIONS      = 14,
+    INDEX_OPT_PRINT_CERT              = 15,
+    INDEX_OPT_RECORDSIZE              = 16,
+    INDEX_OPT_DH_BITS                 = 17,
+    INDEX_OPT_PRIORITY                = 18,
+    INDEX_OPT_X509CAFILE              = 19,
+    INDEX_OPT_X509CRLFILE             = 20,
+    INDEX_OPT_PGPKEYFILE              = 21,
+    INDEX_OPT_PGPKEYRING              = 22,
+    INDEX_OPT_PGPCERTFILE             = 23,
+    INDEX_OPT_X509KEYFILE             = 24,
+    INDEX_OPT_X509CERTFILE            = 25,
+    INDEX_OPT_PGPSUBKEY               = 26,
+    INDEX_OPT_SRPUSERNAME             = 27,
+    INDEX_OPT_SRPPASSWD               = 28,
+    INDEX_OPT_PSKUSERNAME             = 29,
+    INDEX_OPT_PSKKEY                  = 30,
+    INDEX_OPT_PORT                    = 31,
+    INDEX_OPT_INSECURE                = 32,
+    INDEX_OPT_BENCHMARK_CIPHERS       = 33,
+    INDEX_OPT_BENCHMARK_SOFT_CIPHERS  = 34,
+    INDEX_OPT_BENCHMARK_TLS_KX        = 35,
+    INDEX_OPT_BENCHMARK_TLS_CIPHERS   = 36,
+    INDEX_OPT_LIST                    = 37,
+    INDEX_OPT_VERSION                 = 38,
+    INDEX_OPT_HELP                    = 39,
+    INDEX_OPT_MORE_HELP               = 40
 } teOptIndex;
 
-#define OPTION_CT    40
+#define OPTION_CT    41
 #define GNUTLS_CLI_VERSION       "@VERSION@"
 #define GNUTLS_CLI_FULL_VERSION  "gnutls-cli @VERSION@"
 
@@ -154,43 +155,44 @@ typedef enum {
 #define VALUE_OPT_TOFU           2
 #define VALUE_OPT_OCSP           3
 #define VALUE_OPT_RESUME         'r'
+#define VALUE_OPT_HEARTBEAT      'b'
 #define VALUE_OPT_REHANDSHAKE    'e'
-#define VALUE_OPT_NOTICKET       6
+#define VALUE_OPT_NOTICKET       7
 #define VALUE_OPT_STARTTLS       's'
 #define VALUE_OPT_UDP            'u'
-#define VALUE_OPT_MTU            9
+#define VALUE_OPT_MTU            10
 
 #define OPT_VALUE_MTU            (DESC(MTU).optArg.argInt)
-#define VALUE_OPT_CRLF           10
-#define VALUE_OPT_X509FMTDER     11
+#define VALUE_OPT_CRLF           11
+#define VALUE_OPT_X509FMTDER     12
 #define VALUE_OPT_FINGERPRINT    'f'
-#define VALUE_OPT_DISABLE_EXTENSIONS 13
-#define VALUE_OPT_PRINT_CERT     14
-#define VALUE_OPT_RECORDSIZE     15
+#define VALUE_OPT_DISABLE_EXTENSIONS 14
+#define VALUE_OPT_PRINT_CERT     15
+#define VALUE_OPT_RECORDSIZE     16
 
 #define OPT_VALUE_RECORDSIZE     (DESC(RECORDSIZE).optArg.argInt)
-#define VALUE_OPT_DH_BITS        16
+#define VALUE_OPT_DH_BITS        17
 
 #define OPT_VALUE_DH_BITS        (DESC(DH_BITS).optArg.argInt)
-#define VALUE_OPT_PRIORITY       17
-#define VALUE_OPT_X509CAFILE     18
-#define VALUE_OPT_X509CRLFILE    19
-#define VALUE_OPT_PGPKEYFILE     20
-#define VALUE_OPT_PGPKEYRING     21
-#define VALUE_OPT_PGPCERTFILE    22
-#define VALUE_OPT_X509KEYFILE    23
-#define VALUE_OPT_X509CERTFILE   24
-#define VALUE_OPT_PGPSUBKEY      25
-#define VALUE_OPT_SRPUSERNAME    26
-#define VALUE_OPT_SRPPASSWD      27
-#define VALUE_OPT_PSKUSERNAME    28
-#define VALUE_OPT_PSKKEY         29
+#define VALUE_OPT_PRIORITY       18
+#define VALUE_OPT_X509CAFILE     19
+#define VALUE_OPT_X509CRLFILE    20
+#define VALUE_OPT_PGPKEYFILE     21
+#define VALUE_OPT_PGPKEYRING     22
+#define VALUE_OPT_PGPCERTFILE    23
+#define VALUE_OPT_X509KEYFILE    24
+#define VALUE_OPT_X509CERTFILE   25
+#define VALUE_OPT_PGPSUBKEY      26
+#define VALUE_OPT_SRPUSERNAME    27
+#define VALUE_OPT_SRPPASSWD      28
+#define VALUE_OPT_PSKUSERNAME    29
+#define VALUE_OPT_PSKKEY         30
 #define VALUE_OPT_PORT           'p'
-#define VALUE_OPT_INSECURE       31
-#define VALUE_OPT_BENCHMARK_CIPHERS 32
-#define VALUE_OPT_BENCHMARK_SOFT_CIPHERS 129
-#define VALUE_OPT_BENCHMARK_TLS_KX 130
-#define VALUE_OPT_BENCHMARK_TLS_CIPHERS 131
+#define VALUE_OPT_INSECURE       32
+#define VALUE_OPT_BENCHMARK_CIPHERS 129
+#define VALUE_OPT_BENCHMARK_SOFT_CIPHERS 130
+#define VALUE_OPT_BENCHMARK_TLS_KX 131
+#define VALUE_OPT_BENCHMARK_TLS_CIPHERS 132
 #define VALUE_OPT_LIST           'l'
 #define VALUE_OPT_HELP          'h'
 #define VALUE_OPT_MORE_HELP     '!'
diff --git a/src/cli.c b/src/cli.c
index 47f6d09..95180b7 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -625,6 +625,9 @@ init_tls_session (const char *hostname)
         }
     }
 
+  if (HAVE_OPT(HEARTBEAT))
+    gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
+
 #ifdef ENABLE_SESSION_TICKET
   if (disable_extensions == 0 && !HAVE_OPT(NOTICKET)t)
     gnutls_session_ticket_enable_client (session);
@@ -942,7 +945,7 @@ after_handshake:
         }
 
       if (inp == IN_KEYBOARD)
-        {
+      {
           if ((bytes = read (fileno (stdin), buffer, MAX_BUF - 1)) <= 0)
             {
               if (hd.secure == 0)
diff --git a/src/common.c b/src/common.c
index 1b881a8..4b21e22 100644
--- a/src/common.c
+++ b/src/common.c
@@ -34,6 +34,7 @@
 #include <gnutls/gnutls.h>
 #include <gnutls/x509.h>
 #include <gnutls/openpgp.h>
+#include <gnutls/crypto.h>
 #include <time.h>
 #include <common.h>
 
@@ -1040,18 +1041,20 @@ print_list (const char *priorities, int verbose)
 
 int check_command(gnutls_session_t session, const char* str)
 {
-int len = strlen(str);
-
+  size_t len = strnlen(str, 128);
+  fprintf (stderr, "*** Processing %zu bytes command: %s\n", len, str);
   if (len > 2 && str[0] == str[1] && str[0] == '*')
-    {
-      if (strncmp(str, "**REHANDSHAKE**",
-          sizeof ("**REHANDSHAKE**") - 1) == 0)
-        {
+  {
+      if (strncmp(str, "**REHANDSHAKE**", sizeof ("**REHANDSHAKE**") - 1) == 0)
+      {
           fprintf (stderr, "*** Sending rehandshake request\n");
-                   gnutls_rehandshake (session);
+         gnutls_rehandshake (session);
           return 1;
-        }
-    }
+      } else if (strncmp(str, "**HEARTBEAT**", sizeof ("**HEARTBEAT**") - 1) 
== 0) {
+         gnutls_heartbeat_ping_rnd (session);
+         return 2;
+      }
+  }
   return 0;
 }
 
diff --git a/src/serv-args.c b/src/serv-args.c
index 1d6bd62..f27ed08 100644
--- a/src/serv-args.c
+++ b/src/serv-args.c
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (serv-args.c)
  *  
- *  It has been AutoGen-ed  May  9, 2012 at 08:04:45 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  August 30, 2012 at 09:58:05 PM by AutoGen 5.16
  *  From the definitions    serv-args.def
  *  and the template file   options
  *
@@ -67,7 +67,7 @@ extern FILE * option_usage_fp;
 /*
  *  gnutls-serv option static const strings
  */
-static char const gnutls_serv_opt_strs[2947] =
+static char const gnutls_serv_opt_strs[2994] =
 /*     0 */ "gnutls-serv @address@hidden"
             "Copyright (C) 2000-2012 Free Software Foundation, all rights 
reserved.\n"
             "This is free software. It is licensed for use, modification and\n"
@@ -117,82 +117,85 @@ static char const gnutls_serv_opt_strs[2947] =
 /*  1330 */ "Require a client certificate\0"
 /*  1359 */ "REQUIRE_CLIENT_CERT\0"
 /*  1379 */ "require-client-cert\0"
-/*  1399 */ "Use DER format for certificates to read from\0"
-/*  1444 */ "X509FMTDER\0"
-/*  1455 */ "x509fmtder\0"
-/*  1466 */ "Priorities string\0"
-/*  1484 */ "PRIORITY\0"
-/*  1493 */ "priority\0"
-/*  1502 */ "DH params file to use\0"
-/*  1524 */ "DHPARAMS\0"
-/*  1533 */ "dhparams\0"
-/*  1542 */ "Certificate file or PKCS #11 URL to use\0"
-/*  1582 */ "X509CAFILE\0"
-/*  1593 */ "x509cafile\0"
-/*  1604 */ "CRL file to use\0"
-/*  1620 */ "X509CRLFILE\0"
-/*  1632 */ "x509crlfile\0"
-/*  1644 */ "PGP Key file to use\0"
-/*  1664 */ "PGPKEYFILE\0"
-/*  1675 */ "pgpkeyfile\0"
-/*  1686 */ "PGP Key ring file to use\0"
-/*  1711 */ "PGPKEYRING\0"
-/*  1722 */ "pgpkeyring\0"
-/*  1733 */ "PGP Public Key (certificate) file to use\0"
-/*  1774 */ "PGPCERTFILE\0"
-/*  1786 */ "pgpcertfile\0"
-/*  1798 */ "X.509 key file or PKCS #11 URL to use\0"
-/*  1836 */ "X509KEYFILE\0"
-/*  1848 */ "x509keyfile\0"
-/*  1860 */ "X.509 Certificate file or PKCS #11 URL to use\0"
-/*  1906 */ "X509CERTFILE\0"
-/*  1919 */ "x509certfile\0"
-/*  1932 */ "Alternative X.509 key file or PKCS #11 URL to use\0"
-/*  1982 */ "X509DSAKEYFILE\0"
-/*  1997 */ "x509dsakeyfile\0"
-/*  2012 */ "Alternative X.509 Certificate file or PKCS #11 URL to use\0"
-/*  2070 */ "X509DSACERTFILE\0"
-/*  2086 */ "x509dsacertfile\0"
-/*  2102 */ "X509ECCKEYFILE\0"
-/*  2117 */ "x509ecckeyfile\0"
-/*  2132 */ "X509ECCCERTFILE\0"
-/*  2148 */ "x509ecccertfile\0"
-/*  2164 */ "PGP subkey to use (hex or auto)\0"
-/*  2196 */ "PGPSUBKEY\0"
-/*  2206 */ "pgpsubkey\0"
-/*  2216 */ "SRP password file to use\0"
-/*  2241 */ "SRPPASSWD\0"
-/*  2251 */ "srppasswd\0"
-/*  2261 */ "SRP password configuration file to use\0"
-/*  2300 */ "SRPPASSWDCONF\0"
-/*  2314 */ "srppasswdconf\0"
-/*  2328 */ "PSK password file to use\0"
-/*  2353 */ "PSKPASSWD\0"
-/*  2363 */ "pskpasswd\0"
-/*  2373 */ "PSK identity hint to use\0"
-/*  2398 */ "PSKHINT\0"
-/*  2406 */ "pskhint\0"
-/*  2414 */ "The port to connect to\0"
-/*  2437 */ "PORT\0"
-/*  2442 */ "port\0"
-/*  2447 */ "Print a list of the supported algorithms and modes\0"
-/*  2498 */ "LIST\0"
-/*  2503 */ "list\0"
-/*  2508 */ "Display extended usage information and exit\0"
-/*  2552 */ "help\0"
-/*  2557 */ "Extended usage information passed thru pager\0"
-/*  2602 */ "more-help\0"
-/*  2612 */ "Output version information and exit\0"
-/*  2648 */ "version\0"
-/*  2656 */ "GNUTLS_SERV\0"
-/*  2668 */ "gnutls-serv - GnuTLS server - Ver. @address@hidden"
+/*  1399 */ "Activate heartbeat support\0"
+/*  1426 */ "HEARTBEAT\0"
+/*  1436 */ "heartbeat\0"
+/*  1446 */ "Use DER format for certificates to read from\0"
+/*  1491 */ "X509FMTDER\0"
+/*  1502 */ "x509fmtder\0"
+/*  1513 */ "Priorities string\0"
+/*  1531 */ "PRIORITY\0"
+/*  1540 */ "priority\0"
+/*  1549 */ "DH params file to use\0"
+/*  1571 */ "DHPARAMS\0"
+/*  1580 */ "dhparams\0"
+/*  1589 */ "Certificate file or PKCS #11 URL to use\0"
+/*  1629 */ "X509CAFILE\0"
+/*  1640 */ "x509cafile\0"
+/*  1651 */ "CRL file to use\0"
+/*  1667 */ "X509CRLFILE\0"
+/*  1679 */ "x509crlfile\0"
+/*  1691 */ "PGP Key file to use\0"
+/*  1711 */ "PGPKEYFILE\0"
+/*  1722 */ "pgpkeyfile\0"
+/*  1733 */ "PGP Key ring file to use\0"
+/*  1758 */ "PGPKEYRING\0"
+/*  1769 */ "pgpkeyring\0"
+/*  1780 */ "PGP Public Key (certificate) file to use\0"
+/*  1821 */ "PGPCERTFILE\0"
+/*  1833 */ "pgpcertfile\0"
+/*  1845 */ "X.509 key file or PKCS #11 URL to use\0"
+/*  1883 */ "X509KEYFILE\0"
+/*  1895 */ "x509keyfile\0"
+/*  1907 */ "X.509 Certificate file or PKCS #11 URL to use\0"
+/*  1953 */ "X509CERTFILE\0"
+/*  1966 */ "x509certfile\0"
+/*  1979 */ "Alternative X.509 key file or PKCS #11 URL to use\0"
+/*  2029 */ "X509DSAKEYFILE\0"
+/*  2044 */ "x509dsakeyfile\0"
+/*  2059 */ "Alternative X.509 Certificate file or PKCS #11 URL to use\0"
+/*  2117 */ "X509DSACERTFILE\0"
+/*  2133 */ "x509dsacertfile\0"
+/*  2149 */ "X509ECCKEYFILE\0"
+/*  2164 */ "x509ecckeyfile\0"
+/*  2179 */ "X509ECCCERTFILE\0"
+/*  2195 */ "x509ecccertfile\0"
+/*  2211 */ "PGP subkey to use (hex or auto)\0"
+/*  2243 */ "PGPSUBKEY\0"
+/*  2253 */ "pgpsubkey\0"
+/*  2263 */ "SRP password file to use\0"
+/*  2288 */ "SRPPASSWD\0"
+/*  2298 */ "srppasswd\0"
+/*  2308 */ "SRP password configuration file to use\0"
+/*  2347 */ "SRPPASSWDCONF\0"
+/*  2361 */ "srppasswdconf\0"
+/*  2375 */ "PSK password file to use\0"
+/*  2400 */ "PSKPASSWD\0"
+/*  2410 */ "pskpasswd\0"
+/*  2420 */ "PSK identity hint to use\0"
+/*  2445 */ "PSKHINT\0"
+/*  2453 */ "pskhint\0"
+/*  2461 */ "The port to connect to\0"
+/*  2484 */ "PORT\0"
+/*  2489 */ "port\0"
+/*  2494 */ "Print a list of the supported algorithms and modes\0"
+/*  2545 */ "LIST\0"
+/*  2550 */ "list\0"
+/*  2555 */ "Display extended usage information and exit\0"
+/*  2599 */ "help\0"
+/*  2604 */ "Extended usage information passed thru pager\0"
+/*  2649 */ "more-help\0"
+/*  2659 */ "Output version information and exit\0"
+/*  2695 */ "version\0"
+/*  2703 */ "GNUTLS_SERV\0"
+/*  2715 */ "gnutls-serv - GnuTLS server - Ver. @address@hidden"
             "USAGE:  %s [ -<flag> [<val>] | --<name>[{=| }<val>] ]...\n\0"
-/*  2771 */ "address@hidden"
-/*  2790 */ "\n\n\0"
-/*  2793 */ "\n"
+/*  2818 */ "address@hidden"
+/*  2837 */ "\n\n\0"
+/*  2840 */ "\n"
             "Server program that listens to incoming TLS connections.\n\0"
-/*  2852 */ "gnutls-serv @address@hidden"
-/*  2874 */ "Usage: gnutls-serv [options]\n"
+/*  2899 */ "gnutls-serv @address@hidden"
+/*  2921 */ "Usage: gnutls-serv [options]\n"
             "gnutls-serv --help for usage instructions.\n";
 
 /*
@@ -286,200 +289,208 @@ static char const gnutls_serv_opt_strs[2947] =
 #define REQUIRE_CLIENT_CERT_FLAGS     (OPTST_DISABLED)
 
 /*
+ *  heartbeat option description:
+ */
+#define HEARTBEAT_DESC      (gnutls_serv_opt_strs+1399)
+#define HEARTBEAT_NAME      (gnutls_serv_opt_strs+1426)
+#define HEARTBEAT_name      (gnutls_serv_opt_strs+1436)
+#define HEARTBEAT_FLAGS     (OPTST_DISABLED)
+
+/*
  *  x509fmtder option description:
  */
-#define X509FMTDER_DESC      (gnutls_serv_opt_strs+1399)
-#define X509FMTDER_NAME      (gnutls_serv_opt_strs+1444)
-#define X509FMTDER_name      (gnutls_serv_opt_strs+1455)
+#define X509FMTDER_DESC      (gnutls_serv_opt_strs+1446)
+#define X509FMTDER_NAME      (gnutls_serv_opt_strs+1491)
+#define X509FMTDER_name      (gnutls_serv_opt_strs+1502)
 #define X509FMTDER_FLAGS     (OPTST_DISABLED)
 
 /*
  *  priority option description:
  */
-#define PRIORITY_DESC      (gnutls_serv_opt_strs+1466)
-#define PRIORITY_NAME      (gnutls_serv_opt_strs+1484)
-#define PRIORITY_name      (gnutls_serv_opt_strs+1493)
+#define PRIORITY_DESC      (gnutls_serv_opt_strs+1513)
+#define PRIORITY_NAME      (gnutls_serv_opt_strs+1531)
+#define PRIORITY_name      (gnutls_serv_opt_strs+1540)
 #define PRIORITY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  dhparams option description:
  */
-#define DHPARAMS_DESC      (gnutls_serv_opt_strs+1502)
-#define DHPARAMS_NAME      (gnutls_serv_opt_strs+1524)
-#define DHPARAMS_name      (gnutls_serv_opt_strs+1533)
+#define DHPARAMS_DESC      (gnutls_serv_opt_strs+1549)
+#define DHPARAMS_NAME      (gnutls_serv_opt_strs+1571)
+#define DHPARAMS_name      (gnutls_serv_opt_strs+1580)
 #define DHPARAMS_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  x509cafile option description:
  */
-#define X509CAFILE_DESC      (gnutls_serv_opt_strs+1542)
-#define X509CAFILE_NAME      (gnutls_serv_opt_strs+1582)
-#define X509CAFILE_name      (gnutls_serv_opt_strs+1593)
+#define X509CAFILE_DESC      (gnutls_serv_opt_strs+1589)
+#define X509CAFILE_NAME      (gnutls_serv_opt_strs+1629)
+#define X509CAFILE_name      (gnutls_serv_opt_strs+1640)
 #define X509CAFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509crlfile option description:
  */
-#define X509CRLFILE_DESC      (gnutls_serv_opt_strs+1604)
-#define X509CRLFILE_NAME      (gnutls_serv_opt_strs+1620)
-#define X509CRLFILE_name      (gnutls_serv_opt_strs+1632)
+#define X509CRLFILE_DESC      (gnutls_serv_opt_strs+1651)
+#define X509CRLFILE_NAME      (gnutls_serv_opt_strs+1667)
+#define X509CRLFILE_name      (gnutls_serv_opt_strs+1679)
 #define X509CRLFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyfile option description:
  */
-#define PGPKEYFILE_DESC      (gnutls_serv_opt_strs+1644)
-#define PGPKEYFILE_NAME      (gnutls_serv_opt_strs+1664)
-#define PGPKEYFILE_name      (gnutls_serv_opt_strs+1675)
+#define PGPKEYFILE_DESC      (gnutls_serv_opt_strs+1691)
+#define PGPKEYFILE_NAME      (gnutls_serv_opt_strs+1711)
+#define PGPKEYFILE_name      (gnutls_serv_opt_strs+1722)
 #define PGPKEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpkeyring option description:
  */
-#define PGPKEYRING_DESC      (gnutls_serv_opt_strs+1686)
-#define PGPKEYRING_NAME      (gnutls_serv_opt_strs+1711)
-#define PGPKEYRING_name      (gnutls_serv_opt_strs+1722)
+#define PGPKEYRING_DESC      (gnutls_serv_opt_strs+1733)
+#define PGPKEYRING_NAME      (gnutls_serv_opt_strs+1758)
+#define PGPKEYRING_name      (gnutls_serv_opt_strs+1769)
 #define PGPKEYRING_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pgpcertfile option description:
  */
-#define PGPCERTFILE_DESC      (gnutls_serv_opt_strs+1733)
-#define PGPCERTFILE_NAME      (gnutls_serv_opt_strs+1774)
-#define PGPCERTFILE_name      (gnutls_serv_opt_strs+1786)
+#define PGPCERTFILE_DESC      (gnutls_serv_opt_strs+1780)
+#define PGPCERTFILE_NAME      (gnutls_serv_opt_strs+1821)
+#define PGPCERTFILE_name      (gnutls_serv_opt_strs+1833)
 #define PGPCERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  x509keyfile option description:
  */
-#define X509KEYFILE_DESC      (gnutls_serv_opt_strs+1798)
-#define X509KEYFILE_NAME      (gnutls_serv_opt_strs+1836)
-#define X509KEYFILE_name      (gnutls_serv_opt_strs+1848)
+#define X509KEYFILE_DESC      (gnutls_serv_opt_strs+1845)
+#define X509KEYFILE_NAME      (gnutls_serv_opt_strs+1883)
+#define X509KEYFILE_name      (gnutls_serv_opt_strs+1895)
 #define X509KEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509certfile option description:
  */
-#define X509CERTFILE_DESC      (gnutls_serv_opt_strs+1860)
-#define X509CERTFILE_NAME      (gnutls_serv_opt_strs+1906)
-#define X509CERTFILE_name      (gnutls_serv_opt_strs+1919)
+#define X509CERTFILE_DESC      (gnutls_serv_opt_strs+1907)
+#define X509CERTFILE_NAME      (gnutls_serv_opt_strs+1953)
+#define X509CERTFILE_name      (gnutls_serv_opt_strs+1966)
 #define X509CERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509dsakeyfile option description:
  */
-#define X509DSAKEYFILE_DESC      (gnutls_serv_opt_strs+1932)
-#define X509DSAKEYFILE_NAME      (gnutls_serv_opt_strs+1982)
-#define X509DSAKEYFILE_name      (gnutls_serv_opt_strs+1997)
+#define X509DSAKEYFILE_DESC      (gnutls_serv_opt_strs+1979)
+#define X509DSAKEYFILE_NAME      (gnutls_serv_opt_strs+2029)
+#define X509DSAKEYFILE_name      (gnutls_serv_opt_strs+2044)
 #define X509DSAKEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509dsacertfile option description:
  */
-#define X509DSACERTFILE_DESC      (gnutls_serv_opt_strs+2012)
-#define X509DSACERTFILE_NAME      (gnutls_serv_opt_strs+2070)
-#define X509DSACERTFILE_name      (gnutls_serv_opt_strs+2086)
+#define X509DSACERTFILE_DESC      (gnutls_serv_opt_strs+2059)
+#define X509DSACERTFILE_NAME      (gnutls_serv_opt_strs+2117)
+#define X509DSACERTFILE_name      (gnutls_serv_opt_strs+2133)
 #define X509DSACERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509ecckeyfile option description:
  */
-#define X509ECCKEYFILE_DESC      (gnutls_serv_opt_strs+1932)
-#define X509ECCKEYFILE_NAME      (gnutls_serv_opt_strs+2102)
-#define X509ECCKEYFILE_name      (gnutls_serv_opt_strs+2117)
+#define X509ECCKEYFILE_DESC      (gnutls_serv_opt_strs+1979)
+#define X509ECCKEYFILE_NAME      (gnutls_serv_opt_strs+2149)
+#define X509ECCKEYFILE_name      (gnutls_serv_opt_strs+2164)
 #define X509ECCKEYFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  x509ecccertfile option description:
  */
-#define X509ECCCERTFILE_DESC      (gnutls_serv_opt_strs+2012)
-#define X509ECCCERTFILE_NAME      (gnutls_serv_opt_strs+2132)
-#define X509ECCCERTFILE_name      (gnutls_serv_opt_strs+2148)
+#define X509ECCCERTFILE_DESC      (gnutls_serv_opt_strs+2059)
+#define X509ECCCERTFILE_NAME      (gnutls_serv_opt_strs+2179)
+#define X509ECCCERTFILE_name      (gnutls_serv_opt_strs+2195)
 #define X509ECCCERTFILE_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  pgpsubkey option description:
  */
-#define PGPSUBKEY_DESC      (gnutls_serv_opt_strs+2164)
-#define PGPSUBKEY_NAME      (gnutls_serv_opt_strs+2196)
-#define PGPSUBKEY_name      (gnutls_serv_opt_strs+2206)
+#define PGPSUBKEY_DESC      (gnutls_serv_opt_strs+2211)
+#define PGPSUBKEY_NAME      (gnutls_serv_opt_strs+2243)
+#define PGPSUBKEY_name      (gnutls_serv_opt_strs+2253)
 #define PGPSUBKEY_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  srppasswd option description:
  */
-#define SRPPASSWD_DESC      (gnutls_serv_opt_strs+2216)
-#define SRPPASSWD_NAME      (gnutls_serv_opt_strs+2241)
-#define SRPPASSWD_name      (gnutls_serv_opt_strs+2251)
+#define SRPPASSWD_DESC      (gnutls_serv_opt_strs+2263)
+#define SRPPASSWD_NAME      (gnutls_serv_opt_strs+2288)
+#define SRPPASSWD_name      (gnutls_serv_opt_strs+2298)
 #define SRPPASSWD_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  srppasswdconf option description:
  */
-#define SRPPASSWDCONF_DESC      (gnutls_serv_opt_strs+2261)
-#define SRPPASSWDCONF_NAME      (gnutls_serv_opt_strs+2300)
-#define SRPPASSWDCONF_name      (gnutls_serv_opt_strs+2314)
+#define SRPPASSWDCONF_DESC      (gnutls_serv_opt_strs+2308)
+#define SRPPASSWDCONF_NAME      (gnutls_serv_opt_strs+2347)
+#define SRPPASSWDCONF_name      (gnutls_serv_opt_strs+2361)
 #define SRPPASSWDCONF_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pskpasswd option description:
  */
-#define PSKPASSWD_DESC      (gnutls_serv_opt_strs+2328)
-#define PSKPASSWD_NAME      (gnutls_serv_opt_strs+2353)
-#define PSKPASSWD_name      (gnutls_serv_opt_strs+2363)
+#define PSKPASSWD_DESC      (gnutls_serv_opt_strs+2375)
+#define PSKPASSWD_NAME      (gnutls_serv_opt_strs+2400)
+#define PSKPASSWD_name      (gnutls_serv_opt_strs+2410)
 #define PSKPASSWD_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_FILE))
 
 /*
  *  pskhint option description:
  */
-#define PSKHINT_DESC      (gnutls_serv_opt_strs+2373)
-#define PSKHINT_NAME      (gnutls_serv_opt_strs+2398)
-#define PSKHINT_name      (gnutls_serv_opt_strs+2406)
+#define PSKHINT_DESC      (gnutls_serv_opt_strs+2420)
+#define PSKHINT_NAME      (gnutls_serv_opt_strs+2445)
+#define PSKHINT_name      (gnutls_serv_opt_strs+2453)
 #define PSKHINT_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_STRING))
 
 /*
  *  port option description:
  */
-#define PORT_DESC      (gnutls_serv_opt_strs+2414)
-#define PORT_NAME      (gnutls_serv_opt_strs+2437)
-#define PORT_name      (gnutls_serv_opt_strs+2442)
+#define PORT_DESC      (gnutls_serv_opt_strs+2461)
+#define PORT_NAME      (gnutls_serv_opt_strs+2484)
+#define PORT_name      (gnutls_serv_opt_strs+2489)
 #define PORT_FLAGS     (OPTST_DISABLED \
         | OPTST_SET_ARGTYPE(OPARG_TYPE_NUMERIC))
 
 /*
  *  list option description:
  */
-#define LIST_DESC      (gnutls_serv_opt_strs+2447)
-#define LIST_NAME      (gnutls_serv_opt_strs+2498)
-#define LIST_name      (gnutls_serv_opt_strs+2503)
+#define LIST_DESC      (gnutls_serv_opt_strs+2494)
+#define LIST_NAME      (gnutls_serv_opt_strs+2545)
+#define LIST_name      (gnutls_serv_opt_strs+2550)
 #define LIST_FLAGS     (OPTST_DISABLED)
 
 /*
  *  Help/More_Help/Version option descriptions:
  */
-#define HELP_DESC       (gnutls_serv_opt_strs+2508)
-#define HELP_name       (gnutls_serv_opt_strs+2552)
+#define HELP_DESC       (gnutls_serv_opt_strs+2555)
+#define HELP_name       (gnutls_serv_opt_strs+2599)
 #ifdef HAVE_WORKING_FORK
-#define MORE_HELP_DESC  (gnutls_serv_opt_strs+2557)
-#define MORE_HELP_name  (gnutls_serv_opt_strs+2602)
+#define MORE_HELP_DESC  (gnutls_serv_opt_strs+2604)
+#define MORE_HELP_name  (gnutls_serv_opt_strs+2649)
 #define MORE_HELP_FLAGS (OPTST_IMM | OPTST_NO_INIT)
 #else
 #define MORE_HELP_DESC  NULL
@@ -492,8 +503,8 @@ static char const gnutls_serv_opt_strs[2947] =
 #  define VER_FLAGS     (OPTST_SET_ARGTYPE(OPARG_TYPE_STRING) | \
                          OPTST_ARG_OPTIONAL | OPTST_IMM | OPTST_NO_INIT)
 #endif
-#define VER_DESC        (gnutls_serv_opt_strs+2612)
-#define VER_name        (gnutls_serv_opt_strs+2648)
+#define VER_DESC        (gnutls_serv_opt_strs+2659)
+#define VER_name        (gnutls_serv_opt_strs+2695)
 /*
  *  Declare option callback procedures
  */
@@ -648,8 +659,20 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ REQUIRE_CLIENT_CERT_DESC, 
REQUIRE_CLIENT_CERT_NAME, REQUIRE_CLIENT_CERT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 11, VALUE_OPT_X509FMTDER,
-     /* equiv idx, value */ 11, VALUE_OPT_X509FMTDER,
+  {  /* entry idx, value */ 11, VALUE_OPT_HEARTBEAT,
+     /* equiv idx, value */ 11, VALUE_OPT_HEARTBEAT,
+     /* equivalenced to  */ NO_EQUIVALENT,
+     /* min, max, act ct */ 0, 1, 0,
+     /* opt state flags  */ HEARTBEAT_FLAGS, 0,
+     /* last opt argumnt */ { NULL }, /* --heartbeat */
+     /* arg list/cookie  */ NULL,
+     /* must/cannot opts */ NULL, NULL,
+     /* option proc      */ NULL,
+     /* desc, NAME, name */ HEARTBEAT_DESC, HEARTBEAT_NAME, HEARTBEAT_name,
+     /* disablement strs */ NULL, NULL },
+
+  {  /* entry idx, value */ 12, VALUE_OPT_X509FMTDER,
+     /* equiv idx, value */ 12, VALUE_OPT_X509FMTDER,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509FMTDER_FLAGS, 0,
@@ -660,8 +683,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509FMTDER_DESC, X509FMTDER_NAME, X509FMTDER_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 12, VALUE_OPT_PRIORITY,
-     /* equiv idx, value */ 12, VALUE_OPT_PRIORITY,
+  {  /* entry idx, value */ 13, VALUE_OPT_PRIORITY,
+     /* equiv idx, value */ 13, VALUE_OPT_PRIORITY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PRIORITY_FLAGS, 0,
@@ -672,8 +695,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PRIORITY_DESC, PRIORITY_NAME, PRIORITY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 13, VALUE_OPT_DHPARAMS,
-     /* equiv idx, value */ 13, VALUE_OPT_DHPARAMS,
+  {  /* entry idx, value */ 14, VALUE_OPT_DHPARAMS,
+     /* equiv idx, value */ 14, VALUE_OPT_DHPARAMS,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ DHPARAMS_FLAGS, 0,
@@ -684,8 +707,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ DHPARAMS_DESC, DHPARAMS_NAME, DHPARAMS_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 14, VALUE_OPT_X509CAFILE,
-     /* equiv idx, value */ 14, VALUE_OPT_X509CAFILE,
+  {  /* entry idx, value */ 15, VALUE_OPT_X509CAFILE,
+     /* equiv idx, value */ 15, VALUE_OPT_X509CAFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CAFILE_FLAGS, 0,
@@ -696,8 +719,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CAFILE_DESC, X509CAFILE_NAME, X509CAFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 15, VALUE_OPT_X509CRLFILE,
-     /* equiv idx, value */ 15, VALUE_OPT_X509CRLFILE,
+  {  /* entry idx, value */ 16, VALUE_OPT_X509CRLFILE,
+     /* equiv idx, value */ 16, VALUE_OPT_X509CRLFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CRLFILE_FLAGS, 0,
@@ -708,8 +731,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CRLFILE_DESC, X509CRLFILE_NAME, 
X509CRLFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 16, VALUE_OPT_PGPKEYFILE,
-     /* equiv idx, value */ 16, VALUE_OPT_PGPKEYFILE,
+  {  /* entry idx, value */ 17, VALUE_OPT_PGPKEYFILE,
+     /* equiv idx, value */ 17, VALUE_OPT_PGPKEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYFILE_FLAGS, 0,
@@ -720,8 +743,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYFILE_DESC, PGPKEYFILE_NAME, PGPKEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 17, VALUE_OPT_PGPKEYRING,
-     /* equiv idx, value */ 17, VALUE_OPT_PGPKEYRING,
+  {  /* entry idx, value */ 18, VALUE_OPT_PGPKEYRING,
+     /* equiv idx, value */ 18, VALUE_OPT_PGPKEYRING,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPKEYRING_FLAGS, 0,
@@ -732,8 +755,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPKEYRING_DESC, PGPKEYRING_NAME, PGPKEYRING_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 18, VALUE_OPT_PGPCERTFILE,
-     /* equiv idx, value */ 18, VALUE_OPT_PGPCERTFILE,
+  {  /* entry idx, value */ 19, VALUE_OPT_PGPCERTFILE,
+     /* equiv idx, value */ 19, VALUE_OPT_PGPCERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPCERTFILE_FLAGS, 0,
@@ -744,8 +767,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPCERTFILE_DESC, PGPCERTFILE_NAME, 
PGPCERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 19, VALUE_OPT_X509KEYFILE,
-     /* equiv idx, value */ 19, VALUE_OPT_X509KEYFILE,
+  {  /* entry idx, value */ 20, VALUE_OPT_X509KEYFILE,
+     /* equiv idx, value */ 20, VALUE_OPT_X509KEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509KEYFILE_FLAGS, 0,
@@ -756,8 +779,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509KEYFILE_DESC, X509KEYFILE_NAME, 
X509KEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 20, VALUE_OPT_X509CERTFILE,
-     /* equiv idx, value */ 20, VALUE_OPT_X509CERTFILE,
+  {  /* entry idx, value */ 21, VALUE_OPT_X509CERTFILE,
+     /* equiv idx, value */ 21, VALUE_OPT_X509CERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509CERTFILE_FLAGS, 0,
@@ -768,8 +791,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509CERTFILE_DESC, X509CERTFILE_NAME, 
X509CERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 21, VALUE_OPT_X509DSAKEYFILE,
-     /* equiv idx, value */ 21, VALUE_OPT_X509DSAKEYFILE,
+  {  /* entry idx, value */ 22, VALUE_OPT_X509DSAKEYFILE,
+     /* equiv idx, value */ 22, VALUE_OPT_X509DSAKEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509DSAKEYFILE_FLAGS, 0,
@@ -780,8 +803,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509DSAKEYFILE_DESC, X509DSAKEYFILE_NAME, 
X509DSAKEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 22, VALUE_OPT_X509DSACERTFILE,
-     /* equiv idx, value */ 22, VALUE_OPT_X509DSACERTFILE,
+  {  /* entry idx, value */ 23, VALUE_OPT_X509DSACERTFILE,
+     /* equiv idx, value */ 23, VALUE_OPT_X509DSACERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509DSACERTFILE_FLAGS, 0,
@@ -792,8 +815,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509DSACERTFILE_DESC, X509DSACERTFILE_NAME, 
X509DSACERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 23, VALUE_OPT_X509ECCKEYFILE,
-     /* equiv idx, value */ 23, VALUE_OPT_X509ECCKEYFILE,
+  {  /* entry idx, value */ 24, VALUE_OPT_X509ECCKEYFILE,
+     /* equiv idx, value */ 24, VALUE_OPT_X509ECCKEYFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509ECCKEYFILE_FLAGS, 0,
@@ -804,8 +827,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509ECCKEYFILE_DESC, X509ECCKEYFILE_NAME, 
X509ECCKEYFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 24, VALUE_OPT_X509ECCCERTFILE,
-     /* equiv idx, value */ 24, VALUE_OPT_X509ECCCERTFILE,
+  {  /* entry idx, value */ 25, VALUE_OPT_X509ECCCERTFILE,
+     /* equiv idx, value */ 25, VALUE_OPT_X509ECCCERTFILE,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ X509ECCCERTFILE_FLAGS, 0,
@@ -816,8 +839,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ X509ECCCERTFILE_DESC, X509ECCCERTFILE_NAME, 
X509ECCCERTFILE_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 25, VALUE_OPT_PGPSUBKEY,
-     /* equiv idx, value */ 25, VALUE_OPT_PGPSUBKEY,
+  {  /* entry idx, value */ 26, VALUE_OPT_PGPSUBKEY,
+     /* equiv idx, value */ 26, VALUE_OPT_PGPSUBKEY,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PGPSUBKEY_FLAGS, 0,
@@ -828,8 +851,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PGPSUBKEY_DESC, PGPSUBKEY_NAME, PGPSUBKEY_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 26, VALUE_OPT_SRPPASSWD,
-     /* equiv idx, value */ 26, VALUE_OPT_SRPPASSWD,
+  {  /* entry idx, value */ 27, VALUE_OPT_SRPPASSWD,
+     /* equiv idx, value */ 27, VALUE_OPT_SRPPASSWD,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPPASSWD_FLAGS, 0,
@@ -840,8 +863,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPPASSWD_DESC, SRPPASSWD_NAME, SRPPASSWD_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 27, VALUE_OPT_SRPPASSWDCONF,
-     /* equiv idx, value */ 27, VALUE_OPT_SRPPASSWDCONF,
+  {  /* entry idx, value */ 28, VALUE_OPT_SRPPASSWDCONF,
+     /* equiv idx, value */ 28, VALUE_OPT_SRPPASSWDCONF,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ SRPPASSWDCONF_FLAGS, 0,
@@ -852,8 +875,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ SRPPASSWDCONF_DESC, SRPPASSWDCONF_NAME, 
SRPPASSWDCONF_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 28, VALUE_OPT_PSKPASSWD,
-     /* equiv idx, value */ 28, VALUE_OPT_PSKPASSWD,
+  {  /* entry idx, value */ 29, VALUE_OPT_PSKPASSWD,
+     /* equiv idx, value */ 29, VALUE_OPT_PSKPASSWD,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKPASSWD_FLAGS, 0,
@@ -864,8 +887,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKPASSWD_DESC, PSKPASSWD_NAME, PSKPASSWD_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 29, VALUE_OPT_PSKHINT,
-     /* equiv idx, value */ 29, VALUE_OPT_PSKHINT,
+  {  /* entry idx, value */ 30, VALUE_OPT_PSKHINT,
+     /* equiv idx, value */ 30, VALUE_OPT_PSKHINT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PSKHINT_FLAGS, 0,
@@ -876,8 +899,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PSKHINT_DESC, PSKHINT_NAME, PSKHINT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 30, VALUE_OPT_PORT,
-     /* equiv idx, value */ 30, VALUE_OPT_PORT,
+  {  /* entry idx, value */ 31, VALUE_OPT_PORT,
+     /* equiv idx, value */ 31, VALUE_OPT_PORT,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ PORT_FLAGS, 0,
@@ -888,8 +911,8 @@ static tOptDesc optDesc[OPTION_CT] = {
      /* desc, NAME, name */ PORT_DESC, PORT_NAME, PORT_name,
      /* disablement strs */ NULL, NULL },
 
-  {  /* entry idx, value */ 31, VALUE_OPT_LIST,
-     /* equiv idx, value */ 31, VALUE_OPT_LIST,
+  {  /* entry idx, value */ 32, VALUE_OPT_LIST,
+     /* equiv idx, value */ 32, VALUE_OPT_LIST,
      /* equivalenced to  */ NO_EQUIVALENT,
      /* min, max, act ct */ 0, 1, 0,
      /* opt state flags  */ LIST_FLAGS, 0,
@@ -944,14 +967,14 @@ static tOptDesc optDesc[OPTION_CT] = {
  *
  *  Define the gnutls-serv Option Environment
  */
-#define zPROGNAME       (gnutls_serv_opt_strs+2656)
-#define zUsageTitle     (gnutls_serv_opt_strs+2668)
+#define zPROGNAME       (gnutls_serv_opt_strs+2703)
+#define zUsageTitle     (gnutls_serv_opt_strs+2715)
 #define zRcName         NULL
 #define apzHomeList     NULL
-#define zBugsAddr       (gnutls_serv_opt_strs+2771)
-#define zExplain        (gnutls_serv_opt_strs+2790)
-#define zDetail         (gnutls_serv_opt_strs+2793)
-#define zFullVersion    (gnutls_serv_opt_strs+2852)
+#define zBugsAddr       (gnutls_serv_opt_strs+2818)
+#define zExplain        (gnutls_serv_opt_strs+2837)
+#define zDetail         (gnutls_serv_opt_strs+2840)
+#define zFullVersion    (gnutls_serv_opt_strs+2899)
 /* extracted from optcode.tlib near line 350 */
 
 #if defined(ENABLE_NLS)
@@ -965,7 +988,7 @@ static tOptDesc optDesc[OPTION_CT] = {
 
 #define gnutls_serv_full_usage (NULL)
 
-#define gnutls_serv_short_usage (gnutls_serv_opt_strs+2874)
+#define gnutls_serv_short_usage (gnutls_serv_opt_strs+2921)
 
 #endif /* not defined __doxygen__ */
 
@@ -1290,7 +1313,7 @@ tOptions gnutls_servOptions = {
       NO_EQUIVALENT, /* '-#' option index */
       NO_EQUIVALENT /* index of default opt */
     },
-    35 /* full option count */, 32 /* user option count */,
+    36 /* full option count */, 33 /* user option count */,
     gnutls_serv_full_usage, gnutls_serv_short_usage,
     NULL, NULL,
     PKGDATADIR, gnutls_serv_packager_info
diff --git a/src/serv-args.def b/src/serv-args.def
index 9264d13..e61034e 100644
--- a/src/serv-args.def
+++ b/src/serv-args.def
@@ -76,6 +76,13 @@ flag = {
 };
 
 flag = {
+    name      = heartbeat;
+    value     = b;
+    descrip   = "Activate heartbeat support";
+    doc      = "Regularly ping client via heartbeat extension messages";
+};
+
+flag = {
     name      = x509fmtder;
     descrip   = "Use DER format for certificates to read from";
     doc      = "";
diff --git a/src/serv-args.h b/src/serv-args.h
index a9c930e..9c4c86e 100644
--- a/src/serv-args.h
+++ b/src/serv-args.h
@@ -2,7 +2,7 @@
  *  
  *  DO NOT EDIT THIS FILE   (serv-args.h)
  *  
- *  It has been AutoGen-ed  May  9, 2012 at 08:04:44 PM by AutoGen 5.16
+ *  It has been AutoGen-ed  August 30, 2012 at 09:58:05 PM by AutoGen 5.16
  *  From the definitions    serv-args.def
  *  and the template file   options
  *
@@ -78,33 +78,34 @@ typedef enum {
     INDEX_OPT_MTU                  =  8,
     INDEX_OPT_DISABLE_CLIENT_CERT  =  9,
     INDEX_OPT_REQUIRE_CLIENT_CERT  = 10,
-    INDEX_OPT_X509FMTDER           = 11,
-    INDEX_OPT_PRIORITY             = 12,
-    INDEX_OPT_DHPARAMS             = 13,
-    INDEX_OPT_X509CAFILE           = 14,
-    INDEX_OPT_X509CRLFILE          = 15,
-    INDEX_OPT_PGPKEYFILE           = 16,
-    INDEX_OPT_PGPKEYRING           = 17,
-    INDEX_OPT_PGPCERTFILE          = 18,
-    INDEX_OPT_X509KEYFILE          = 19,
-    INDEX_OPT_X509CERTFILE         = 20,
-    INDEX_OPT_X509DSAKEYFILE       = 21,
-    INDEX_OPT_X509DSACERTFILE      = 22,
-    INDEX_OPT_X509ECCKEYFILE       = 23,
-    INDEX_OPT_X509ECCCERTFILE      = 24,
-    INDEX_OPT_PGPSUBKEY            = 25,
-    INDEX_OPT_SRPPASSWD            = 26,
-    INDEX_OPT_SRPPASSWDCONF        = 27,
-    INDEX_OPT_PSKPASSWD            = 28,
-    INDEX_OPT_PSKHINT              = 29,
-    INDEX_OPT_PORT                 = 30,
-    INDEX_OPT_LIST                 = 31,
-    INDEX_OPT_VERSION              = 32,
-    INDEX_OPT_HELP                 = 33,
-    INDEX_OPT_MORE_HELP            = 34
+    INDEX_OPT_HEARTBEAT            = 11,
+    INDEX_OPT_X509FMTDER           = 12,
+    INDEX_OPT_PRIORITY             = 13,
+    INDEX_OPT_DHPARAMS             = 14,
+    INDEX_OPT_X509CAFILE           = 15,
+    INDEX_OPT_X509CRLFILE          = 16,
+    INDEX_OPT_PGPKEYFILE           = 17,
+    INDEX_OPT_PGPKEYRING           = 18,
+    INDEX_OPT_PGPCERTFILE          = 19,
+    INDEX_OPT_X509KEYFILE          = 20,
+    INDEX_OPT_X509CERTFILE         = 21,
+    INDEX_OPT_X509DSAKEYFILE       = 22,
+    INDEX_OPT_X509DSACERTFILE      = 23,
+    INDEX_OPT_X509ECCKEYFILE       = 24,
+    INDEX_OPT_X509ECCCERTFILE      = 25,
+    INDEX_OPT_PGPSUBKEY            = 26,
+    INDEX_OPT_SRPPASSWD            = 27,
+    INDEX_OPT_SRPPASSWDCONF        = 28,
+    INDEX_OPT_PSKPASSWD            = 29,
+    INDEX_OPT_PSKHINT              = 30,
+    INDEX_OPT_PORT                 = 31,
+    INDEX_OPT_LIST                 = 32,
+    INDEX_OPT_VERSION              = 33,
+    INDEX_OPT_HELP                 = 34,
+    INDEX_OPT_MORE_HELP            = 35
 } teOptIndex;
 
-#define OPTION_CT    35
+#define OPTION_CT    36
 #define GNUTLS_SERV_VERSION       "@VERSION@"
 #define GNUTLS_SERV_FULL_VERSION  "gnutls-serv @VERSION@"
 
@@ -157,25 +158,26 @@ typedef enum {
 #define OPT_VALUE_MTU            (DESC(MTU).optArg.argInt)
 #define VALUE_OPT_DISABLE_CLIENT_CERT 'a'
 #define VALUE_OPT_REQUIRE_CLIENT_CERT 'r'
-#define VALUE_OPT_X509FMTDER     11
-#define VALUE_OPT_PRIORITY       12
-#define VALUE_OPT_DHPARAMS       13
-#define VALUE_OPT_X509CAFILE     14
-#define VALUE_OPT_X509CRLFILE    15
-#define VALUE_OPT_PGPKEYFILE     16
-#define VALUE_OPT_PGPKEYRING     17
-#define VALUE_OPT_PGPCERTFILE    18
-#define VALUE_OPT_X509KEYFILE    19
-#define VALUE_OPT_X509CERTFILE   20
-#define VALUE_OPT_X509DSAKEYFILE 21
-#define VALUE_OPT_X509DSACERTFILE 22
-#define VALUE_OPT_X509ECCKEYFILE 23
-#define VALUE_OPT_X509ECCCERTFILE 24
-#define VALUE_OPT_PGPSUBKEY      25
-#define VALUE_OPT_SRPPASSWD      26
-#define VALUE_OPT_SRPPASSWDCONF  27
-#define VALUE_OPT_PSKPASSWD      28
-#define VALUE_OPT_PSKHINT        29
+#define VALUE_OPT_HEARTBEAT      'b'
+#define VALUE_OPT_X509FMTDER     12
+#define VALUE_OPT_PRIORITY       13
+#define VALUE_OPT_DHPARAMS       14
+#define VALUE_OPT_X509CAFILE     15
+#define VALUE_OPT_X509CRLFILE    16
+#define VALUE_OPT_PGPKEYFILE     17
+#define VALUE_OPT_PGPKEYRING     18
+#define VALUE_OPT_PGPCERTFILE    19
+#define VALUE_OPT_X509KEYFILE    20
+#define VALUE_OPT_X509CERTFILE   21
+#define VALUE_OPT_X509DSAKEYFILE 22
+#define VALUE_OPT_X509DSACERTFILE 23
+#define VALUE_OPT_X509ECCKEYFILE 24
+#define VALUE_OPT_X509ECCCERTFILE 25
+#define VALUE_OPT_PGPSUBKEY      26
+#define VALUE_OPT_SRPPASSWD      27
+#define VALUE_OPT_SRPPASSWDCONF  28
+#define VALUE_OPT_PSKPASSWD      29
+#define VALUE_OPT_PSKHINT        30
 #define VALUE_OPT_PORT           'p'
 
 #define OPT_VALUE_PORT           (DESC(PORT).optArg.argInt)
diff --git a/src/serv.c b/src/serv.c
index eba281a..5b28f79 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -33,6 +33,7 @@
 #include <sys/types.h>
 #include <string.h>
 #include <gnutls/gnutls.h>
+#include <gnutls/dtls.h>
 #include <gnutls/openpgp.h>
 #include <sys/time.h>
 #include <sys/select.h>
@@ -80,10 +81,10 @@ const char *x509_ecccertfile = NULL;
 const char *x509_cafile = NULL;
 const char *dh_params_file = NULL;
 const char *x509_crlfile = NULL;
-const char * priorities = NULL;
+const char *priorities = NULL;
 
 gnutls_datum_t session_ticket_key;
-static void tcp_server(const char* name, int port);
+static void tcp_server (const char *name, int port);
 
 /* end of globals */
 
@@ -128,13 +129,11 @@ static void cmd_parser (int argc, char **argv);
 #define HTTP_STATE_RESPONSE    2
 #define HTTP_STATE_CLOSING     3
 
-LIST_TYPE_DECLARE (listener_item, char *http_request; char *http_response;
-                   int request_length; int response_length;
-                   int response_written; int http_state;
-                   int listen_socket; int fd;
-                   gnutls_session_t tls_session;
-                   int handshake_ok;
-  );
+LIST_TYPE_DECLARE (listener_item, char *http_request;
+                   char *http_response; int request_length;
+                   int response_length; int response_written;
+                   int http_state; int listen_socket;
+                   int fd; gnutls_session_t tls_session; int handshake_ok;);
 
 static const char *
 safe_strerror (int value)
@@ -171,7 +170,8 @@ gnutls_rsa_params_t rsa_params = NULL;
 static int
 generate_dh_primes (void)
 {
-  int prime_bits = gnutls_sec_param_to_pk_bits(GNUTLS_PK_DH, 
GNUTLS_SEC_PARAM_NORMAL);
+  int prime_bits =
+    gnutls_sec_param_to_pk_bits (GNUTLS_PK_DH, GNUTLS_SEC_PARAM_NORMAL);
 
   if (gnutls_dh_params_init (&dh_params) < 0)
     {
@@ -252,7 +252,7 @@ static char pkcs3[] =
 static int
 static_dh_params (void)
 {
-  gnutls_datum_t params = { (void*)pkcs3, sizeof (pkcs3) };
+  gnutls_datum_t params = { (void *) pkcs3, sizeof (pkcs3) };
   int ret;
 
   if (gnutls_dh_params_init (&dh_params) < 0)
@@ -329,7 +329,8 @@ generate_rsa_params (void)
 
 LIST_DECLARE_INIT (listener_list, listener_item, listener_free);
 
-gnutls_session_t initialize_session (int dtls)
+gnutls_session_t
+initialize_session (int dtls)
 {
   gnutls_session_t session;
   const char *err;
@@ -338,7 +339,7 @@ gnutls_session_t initialize_session (int dtls)
     priorities = "NORMAL";
 
   if (dtls)
-    gnutls_init (&session, GNUTLS_SERVER|GNUTLS_DATAGRAM);
+    gnutls_init (&session, GNUTLS_SERVER | GNUTLS_DATAGRAM);
   else
     gnutls_init (&session, GNUTLS_SERVER);
 
@@ -385,6 +386,9 @@ gnutls_session_t initialize_session (int dtls)
         gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
     }
 
+  if (HAVE_OPT (HEARTBEAT))
+    gnutls_heartbeat_enable(session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
+
   return session;
 }
 
@@ -489,7 +493,8 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 
     if (gnutls_server_name_get (session, dns, &dns_size, &type, 0) == 0)
       {
-        snprintf (tmp_buffer, tmp_buffer_size, "\n<p>Server Name: %s</p>\n", 
dns);
+        snprintf (tmp_buffer, tmp_buffer_size, "\n<p>Server Name: %s</p>\n",
+                  dns);
       }
 
   }
@@ -500,7 +505,8 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 #ifdef ENABLE_SRP
   if (kx_alg == GNUTLS_KX_SRP)
     {
-      snprintf (tmp_buffer, tmp_buffer_size, "<p>Connected as user 
'%s'.</p>\n",
+      snprintf (tmp_buffer, tmp_buffer_size,
+                "<p>Connected as user '%s'.</p>\n",
                 gnutls_srp_server_get_username (session));
     }
 #endif
@@ -508,7 +514,8 @@ peer_print_info (gnutls_session_t session, int *ret_length,
 #ifdef ENABLE_PSK
   if (kx_alg == GNUTLS_KX_PSK)
     {
-      snprintf (tmp_buffer, tmp_buffer_size, "<p>Connected as user 
'%s'.</p>\n",
+      snprintf (tmp_buffer, tmp_buffer_size,
+                "<p>Connected as user '%s'.</p>\n",
                 gnutls_psk_server_get_username (session));
     }
 #endif
@@ -546,45 +553,51 @@ peer_print_info (gnutls_session_t session, int 
*ret_length,
                                           (session));
       if (tmp == NULL)
         tmp = str_unknown;
-      snprintf (tmp_buffer, tmp_buffer_size, "<TR><TD>Certificate 
Type:</TD><TD>%s</TD></TR>\n",
-                tmp);
+      snprintf (tmp_buffer, tmp_buffer_size,
+                "<TR><TD>Certificate Type:</TD><TD>%s</TD></TR>\n", tmp);
     }
 
   tmp = gnutls_kx_get_name (kx_alg);
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp_buffer, tmp_buffer_size, "<TR><TD>Key 
Exchange:</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp_buffer, tmp_buffer_size,
+            "<TR><TD>Key Exchange:</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_compression_get_name (gnutls_compression_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp_buffer, tmp_buffer_size, 
"<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp_buffer, tmp_buffer_size,
+            "<TR><TD>Compression</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_cipher_get_name (gnutls_cipher_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp_buffer, tmp_buffer_size, 
"<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
+  snprintf (tmp_buffer, tmp_buffer_size,
+            "<TR><TD>Cipher</TD><TD>%s</TD></TR>\n", tmp);
 
   tmp = gnutls_mac_get_name (gnutls_mac_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp_buffer, tmp_buffer_size, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n", 
tmp);
+  snprintf (tmp_buffer, tmp_buffer_size, "<TR><TD>MAC</TD><TD>%s</TD></TR>\n",
+            tmp);
 
   tmp = gnutls_cipher_suite_get_name (kx_alg,
                                       gnutls_cipher_get (session),
                                       gnutls_mac_get (session));
   if (tmp == NULL)
     tmp = str_unknown;
-  snprintf (tmp_buffer, tmp_buffer_size, 
"<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n",
-            tmp);
+  snprintf (tmp_buffer, tmp_buffer_size,
+            "<TR><TD>Ciphersuite</TD><TD>%s</TD></TR></p></TABLE>\n", tmp);
 
   if (crtinfo)
     {
-      snprintf (tmp_buffer, tmp_buffer_size, "<hr><PRE>%s\n</PRE>\n", crtinfo);
+      snprintf (tmp_buffer, tmp_buffer_size, "<hr><PRE>%s\n</PRE>\n",
+                crtinfo);
       free (crtinfo);
     }
 
-  snprintf (tmp_buffer, tmp_buffer_size, "<hr><P>Your HTTP header 
was:<PRE>%s</PRE></P>\n" HTTP_END,
+  snprintf (tmp_buffer, tmp_buffer_size,
+            "<hr><P>Your HTTP header was:<PRE>%s</PRE></P>\n" HTTP_END,
             header);
 
   *ret_length = strlen (http_buffer);
@@ -640,7 +653,8 @@ human_addr (const struct sockaddr *sa, socklen_t salen,
   return save_buf;
 }
 
-int wait_for_connection(void)
+int
+wait_for_connection (void)
 {
   listener_item *j;
   fd_set rd, wr;
@@ -672,14 +686,14 @@ int wait_for_connection(void)
 
   /* find which one is ready */
   lloopstart (listener_list, j)
-    {
-      /* a new connection has arrived */
-      if (FD_ISSET (j->fd, &rd) && j->listen_socket)
-        {
-          sock = j->fd;
-          break;
-        }
-    }
+  {
+    /* a new connection has arrived */
+    if (FD_ISSET (j->fd, &rd) && j->listen_socket)
+      {
+        sock = j->fd;
+        break;
+      }
+  }
   lloopend (listener_list, j);
   return sock;
 }
@@ -698,9 +712,9 @@ listen_socket (const char *name, int listen_port, int 
socktype)
   hints.ai_socktype = socktype;
   hints.ai_flags = AI_PASSIVE
 #ifdef AI_ADDRCONFIG
-   | AI_ADDRCONFIG
+    | AI_ADDRCONFIG
 #endif
-   ;
+    ;
 
   if ((s = getaddrinfo (NULL, portname, &hints, &res)) != 0)
     {
@@ -711,7 +725,8 @@ listen_socket (const char *name, int listen_port, int 
socktype)
   for (ptr = res; ptr != NULL; ptr = ptr->ai_next)
     {
 #ifndef HAVE_IPV6
-      if (ptr->ai_family != AF_INET) continue;
+      if (ptr->ai_family != AF_INET)
+        continue;
 #endif
 
       /* Print what we are doing. */
@@ -730,6 +745,17 @@ listen_socket (const char *name, int listen_port, int 
socktype)
           continue;
         }
 
+#ifdef HAVE_IPV6
+      if (ptr->ai_family == AF_INET6)
+        {
+          yes = 1;
+          /* avoid listen on ipv6 addresses failing
+          * because already listening on ipv4 addresses: */
+          setsockopt (s, IPPROTO_IPV6, IPV6_V6ONLY,
+                          (const void *) &yes, sizeof (yes));
+        }
+#endif
+
       if (socktype == SOCK_STREAM)
         {
           yes = 1;
@@ -747,12 +773,12 @@ listen_socket (const char *name, int listen_port, int 
socktype)
           yes = 1;
           if (setsockopt (s, IPPROTO_IP, IP_DONTFRAG,
                           (const void *) &yes, sizeof (yes)) < 0)
-              perror ("setsockopt(IP_DF) failed");
+            perror ("setsockopt(IP_DF) failed");
 #elif defined(IP_MTU_DISCOVER)
           yes = IP_PMTUDISC_DO;
-          if (setsockopt(s, IPPROTO_IP, IP_MTU_DISCOVER, 
-                         (const void*) &yes, sizeof (yes)) < 0)
-              perror ("setsockopt(IP_DF) failed");
+          if (setsockopt (s, IPPROTO_IP, IP_MTU_DISCOVER,
+                          (const void *) &yes, sizeof (yes)) < 0)
+            perror ("setsockopt(IP_DF) failed");
 #endif
         }
 
@@ -768,7 +794,7 @@ listen_socket (const char *name, int listen_port, int 
socktype)
           if (listen (s, 10) < 0)
             {
               perror ("listen() failed");
-              exit(1);
+              exit (1);
             }
         }
 
@@ -839,7 +865,7 @@ get_response (gnutls_session_t session, char *request,
     {
       strip (request);
       fprintf (stderr, "received: %s\n", request);
-      if (check_command(session, request))
+      if (check_command (session, request))
         {
           *response = NULL;
           *response_length = 0;
@@ -902,7 +928,7 @@ main (int argc, char **argv)
   char name[256];
 
   set_program_name (argv[0]);
-  cmd_parser(argc, argv);
+  cmd_parser (argc, argv);
 
 #ifndef _WIN32
   signal (SIGHUP, SIG_IGN);
@@ -916,9 +942,10 @@ main (int argc, char **argv)
   if (nodb == 0)
     wrap_db_init ();
 
-  if (HAVE_OPT(UDP))
-    strcpy(name, "UDP ");
-  else name[0] = 0;
+  if (HAVE_OPT (UDP))
+    strcpy (name, "UDP ");
+  else
+    name[0] = 0;
 
   if (http == 1)
     {
@@ -1009,11 +1036,11 @@ main (int argc, char **argv)
         }
     }
 
-  if (HAVE_OPT(PGPCERTFILE))
+  if (HAVE_OPT (PGPCERTFILE))
     {
-      if (HAVE_OPT(PGPSUBKEY))
+      if (HAVE_OPT (PGPSUBKEY))
         ret = gnutls_certificate_set_openpgp_key_file2
-          (cert_cred, pgp_certfile, pgp_keyfile, OPT_ARG(PGPSUBKEY),
+          (cert_cred, pgp_certfile, pgp_keyfile, OPT_ARG (PGPSUBKEY),
            GNUTLS_OPENPGP_FMT_BASE64);
       else
         ret = gnutls_certificate_set_openpgp_key_file
@@ -1100,10 +1127,10 @@ main (int argc, char **argv)
           GERR (ret);
         }
 
-      if (HAVE_OPT(PSKHINT))
+      if (HAVE_OPT (PSKHINT))
         {
           ret = gnutls_psk_set_server_credentials_hint (psk_cred,
-                                                        OPT_ARG(PSKHINT));
+                                                        OPT_ARG (PSKHINT));
           if (ret)
             {
               fprintf (stderr, "Error setting PSK identity hint.\n");
@@ -1127,22 +1154,24 @@ main (int argc, char **argv)
     gnutls_session_ticket_key_generate (&session_ticket_key);
 #endif
 
-  if (HAVE_OPT(MTU))
+  if (HAVE_OPT (MTU))
     mtu = OPT_VALUE_MTU;
-  else mtu = 1300;
+  else
+    mtu = 1300;
 
-  if (HAVE_OPT(PORT))
+  if (HAVE_OPT (PORT))
     port = OPT_VALUE_PORT;
   else
     port = 5556;
 
-  if (HAVE_OPT(UDP))
-    udp_server(name, port, mtu);
+  if (HAVE_OPT (UDP))
+    udp_server (name, port, mtu);
   else
-    tcp_server(name, port);
+    tcp_server (name, port);
 }
 
-static void tcp_server(const char* name, int port)
+static void
+tcp_server (const char *name, int port)
 {
   int n, s;
   char topbuf[512];
@@ -1301,8 +1330,9 @@ static void tcp_server(const char* name, int port)
                                             &client_address, calen, topbuf,
                                             sizeof (topbuf)));
                         print_info (j->tls_session, verbose, verbose);
-                        if (gnutls_auth_get_type (j->tls_session) == 
GNUTLS_CRD_CERTIFICATE)
-                          cert_verify(j->tls_session, NULL);
+                        if (gnutls_auth_get_type (j->tls_session) ==
+                            GNUTLS_CRD_CERTIFICATE)
+                          cert_verify (j->tls_session, NULL);
                       }
                     j->handshake_ok = 1;
                   }
@@ -1344,12 +1374,19 @@ static void tcp_server(const char* name, int port)
                       }
                     else
                       {
-                        j->http_state = HTTP_STATE_CLOSING;
-                        if (r < 0 && r != GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
+                        if (r < 0)
                           {
-                            check_alert (j->tls_session, r);
-                            fprintf (stderr, "Error while receiving data\n");
-                            GERR (r);
+                            if (GNUTLS_E_HEARTBEAT_PONG_FAILED == r)
+                              fprintf (stderr,
+                                       "HeartBeat pong failed, ping 
dropped\n");
+                            else if (r != GNUTLS_E_UNEXPECTED_PACKET_LENGTH)
+                              {
+                                j->http_state = HTTP_STATE_CLOSING;
+                                check_alert (j->tls_session, r);
+                                fprintf (stderr,
+                                         "Error while receiving data\n");
+                                GERR (r);
+                              }
                           }
                       }
                   }
@@ -1426,8 +1463,9 @@ static void tcp_server(const char* name, int port)
                                             sizeof (topbuf)));
 
                         print_info (j->tls_session, verbose, verbose);
-                        if (gnutls_auth_get_type (j->tls_session) == 
GNUTLS_CRD_CERTIFICATE)
-                          cert_verify(j->tls_session, NULL);
+                        if (gnutls_auth_get_type (j->tls_session) ==
+                            GNUTLS_CRD_CERTIFICATE)
+                          cert_verify (j->tls_session, NULL);
                       }
                     j->handshake_ok = 1;
                   }
@@ -1534,80 +1572,82 @@ static void tcp_server(const char* name, int port)
 
 }
 
-static void cmd_parser (int argc, char **argv)
+static void
+cmd_parser (int argc, char **argv)
 {
-  optionProcess( &gnutls_servOptions, argc, argv);
+  optionProcess (&gnutls_servOptions, argc, argv);
 
-  disable_client_cert = HAVE_OPT(DISABLE_CLIENT_CERT);
-  require_cert = HAVE_OPT(REQUIRE_CLIENT_CERT);
-  if (HAVE_OPT(DEBUG))
+  disable_client_cert = HAVE_OPT (DISABLE_CLIENT_CERT);
+  require_cert = HAVE_OPT (REQUIRE_CLIENT_CERT);
+  if (HAVE_OPT (DEBUG))
     debug = OPT_VALUE_DEBUG;
 
-  if (HAVE_OPT(QUIET))
+  if (HAVE_OPT (QUIET))
     verbose = 0;
 
-  if (HAVE_OPT(PRIORITY)) 
-    priorities = OPT_ARG(PRIORITY);
-  
-  if (HAVE_OPT(LIST))
+  if (HAVE_OPT (PRIORITY))
+    priorities = OPT_ARG (PRIORITY);
+
+  if (HAVE_OPT (LIST))
     {
-      print_list(priorities, verbose);
-      exit(0);
+      print_list (priorities, verbose);
+      exit (0);
     }
 
-  nodb = HAVE_OPT(NODB);
-  noticket = HAVE_OPT(NOTICKET);
+  nodb = HAVE_OPT (NODB);
+  noticket = HAVE_OPT (NOTICKET);
 
-  if (HAVE_OPT(ECHO))
+  if (HAVE_OPT (ECHO))
     http = 0;
-  else http = 1;
+  else
+    http = 1;
 
-  if (HAVE_OPT(X509FMTDER))
+  if (HAVE_OPT (X509FMTDER))
     x509ctype = GNUTLS_X509_FMT_DER;
   else
     x509ctype = GNUTLS_X509_FMT_PEM;
 
-  generate = HAVE_OPT(GENERATE);
+  generate = HAVE_OPT (GENERATE);
+
+  if (HAVE_OPT (DHPARAMS))
+    dh_params_file = OPT_ARG (DHPARAMS);
 
-  if (HAVE_OPT(DHPARAMS))
-    dh_params_file = OPT_ARG(DHPARAMS);
+  if (HAVE_OPT (X509KEYFILE))
+    x509_keyfile = OPT_ARG (X509KEYFILE);
+  if (HAVE_OPT (X509CERTFILE))
+    x509_certfile = OPT_ARG (X509CERTFILE);
 
-  if (HAVE_OPT(X509KEYFILE))
-    x509_keyfile = OPT_ARG(X509KEYFILE);
-  if (HAVE_OPT(X509CERTFILE))
-    x509_certfile = OPT_ARG(X509CERTFILE);
+  if (HAVE_OPT (X509DSAKEYFILE))
+    x509_dsakeyfile = OPT_ARG (X509DSAKEYFILE);
+  if (HAVE_OPT (X509DSACERTFILE))
+    x509_dsacertfile = OPT_ARG (X509DSACERTFILE);
 
-  if (HAVE_OPT(X509DSAKEYFILE))
-    x509_dsakeyfile = OPT_ARG(X509DSAKEYFILE);
-  if (HAVE_OPT(X509DSACERTFILE))
-    x509_dsacertfile = OPT_ARG(X509DSACERTFILE);
 
+  if (HAVE_OPT (X509ECCKEYFILE))
+    x509_ecckeyfile = OPT_ARG (X509ECCKEYFILE);
+  if (HAVE_OPT (X509CERTFILE))
+    x509_ecccertfile = OPT_ARG (X509ECCCERTFILE);
 
-  if (HAVE_OPT(X509ECCKEYFILE))
-    x509_ecckeyfile = OPT_ARG(X509ECCKEYFILE);
-  if (HAVE_OPT(X509CERTFILE))
-    x509_ecccertfile = OPT_ARG(X509ECCCERTFILE);
-  
-  if (HAVE_OPT(X509CAFILE))
-    x509_cafile = OPT_ARG(X509CAFILE);
-  if (HAVE_OPT(X509CRLFILE))
-    x509_crlfile = OPT_ARG(X509CRLFILE);
+  if (HAVE_OPT (X509CAFILE))
+    x509_cafile = OPT_ARG (X509CAFILE);
+  if (HAVE_OPT (X509CRLFILE))
+    x509_crlfile = OPT_ARG (X509CRLFILE);
 
-  if (HAVE_OPT(PGPKEYFILE))
-    pgp_keyfile = OPT_ARG(PGPKEYFILE);
-  if (HAVE_OPT(PGPCERTFILE))
-    pgp_certfile = OPT_ARG(PGPCERTFILE);
+  if (HAVE_OPT (PGPKEYFILE))
+    pgp_keyfile = OPT_ARG (PGPKEYFILE);
+  if (HAVE_OPT (PGPCERTFILE))
+    pgp_certfile = OPT_ARG (PGPCERTFILE);
 
-  if (HAVE_OPT(PGPKEYRING))
-    pgp_keyring = OPT_ARG(PGPKEYRING);
+  if (HAVE_OPT (PGPKEYRING))
+    pgp_keyring = OPT_ARG (PGPKEYRING);
 
-  if (HAVE_OPT(SRPPASSWD))
-    srp_passwd = OPT_ARG(SRPPASSWD);
-  if (HAVE_OPT(SRPPASSWDCONF))
-    srp_passwd_conf = OPT_ARG(SRPPASSWDCONF);
+  if (HAVE_OPT (SRPPASSWD))
+    srp_passwd = OPT_ARG (SRPPASSWD);
+  if (HAVE_OPT (SRPPASSWDCONF))
+    srp_passwd_conf = OPT_ARG (SRPPASSWDCONF);
 
-  if (HAVE_OPT(PSKPASSWD))
-    psk_passwd = OPT_ARG(PSKPASSWD);
+  if (HAVE_OPT (PSKPASSWD))
+    psk_passwd = OPT_ARG (PSKPASSWD);
 
 }
 
diff --git a/src/socket.c b/src/socket.c
index c4d4001..b33f6bc 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -53,6 +53,10 @@ socket_recv (const socket_st * socket, void *buffer, int 
buffer_size)
     do
       {
         ret = gnutls_record_recv (socket->session, buffer, buffer_size);
+       if (GNUTLS_E_HEARTBEAT_PONG_FAILED == ret) {
+           fprintf (stderr, "HeartBeat pong failed, ping dropped\n");
+           ret = GNUTLS_E_AGAIN;
+       }
       }
     while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN);
   else
diff --git a/src/tests.c b/src/tests.c
index a3c5383..aad046c 100644
--- a/src/tests.c
+++ b/src/tests.c
@@ -946,10 +946,32 @@ test_hello_extension (gnutls_session_t session)
   gnutls_record_set_max_size (session, 4096);
 
   ret = do_handshake (session);
+
+
   return ret;
 }
 
 test_code_t
+test_heartbeat_extension (gnutls_session_t session)
+{
+  sprintf (prio_str,
+           INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS
+           ":" ALL_KX ":%s", protocol_str, rest);
+  _gnutls_priority_set_direct (session, prio_str);
+  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred);
+  gnutls_record_set_max_size (session, 4096);
+
+  gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND);
+  do_handshake (session);
+
+  switch (gnutls_heartbeat_allowed (session, 1)) {
+    case 1: return TEST_SUCCEED;
+    case 0: return TEST_FAILED;
+    default: return TEST_UNSURE;
+  }
+}
+
+test_code_t
 test_small_records (gnutls_session_t session)
 {
   int ret;
diff --git a/src/tests.h b/src/tests.h
index 53dda0c..03b7789 100644
--- a/src/tests.h
+++ b/src/tests.h
@@ -28,6 +28,7 @@ test_code_t test_record_padding (gnutls_session_t state);
 test_code_t test_export (gnutls_session_t state);
 test_code_t test_export_info (gnutls_session_t state);
 test_code_t test_hello_extension (gnutls_session_t state);
+test_code_t test_heartbeat_extension (gnutls_session_t state);
 test_code_t test_small_records (gnutls_session_t state);
 test_code_t test_dhe (gnutls_session_t state);
 test_code_t test_dhe_group (gnutls_session_t state);
diff --git a/src/tls_test.c b/src/tls_test.c
index 7552bf8..67ff904 100644
--- a/src/tls_test.c
+++ b/src/tls_test.c
@@ -114,6 +114,7 @@ static const TLS_TEST tls_tests[] = {
    test_rsa_pms_version_check, "yes", "no", "dunno"},
   {"whether the server can accept Hello Extensions",
    test_hello_extension, "yes", "no", "dunno"},
+  {"whether the server can accept HeartBeat Extension", 
test_heartbeat_extension, "yes", "no", "dunno"},
   {"whether the server can accept small records (512 bytes)",
    test_small_records, "yes", "no", "dunno"},
   {"whether the server can accept cipher suites not in SSL 3.0 spec",


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]