[openssl] master update

Dr. Paul Dale pauli at openssl.org
Mon Jul 15 22:31:43 UTC 2019


The branch master has been updated
       via  0d03acea7aa45e94903fb12186ed6cc324eb1b03 (commit)
       via  b8805834756434bfc6ee3840e7097e6e1a877905 (commit)
       via  15cb0f095878092a625219f58bd915bdf1acc973 (commit)
       via  8ae173bb57819a23717fd3c8e7c51cb62f4268d0 (commit)
       via  0d345f0e10b14392925479fc61b6c9072a9605a3 (commit)
       via  54846b7c6ef5718f507def9d192628133f97fe20 (commit)
      from  35e264c03232c7843733caa80f8e16bef7e2e829 (commit)


- Log -----------------------------------------------------------------
commit 0d03acea7aa45e94903fb12186ed6cc324eb1b03
Author: Pauli <paul.dale at oracle.com>
Date:   Fri Jul 12 06:27:19 2019 +1000

    remove end of line whitespace
    
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9111)

commit b8805834756434bfc6ee3840e7097e6e1a877905
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jun 10 17:52:15 2019 +0100

    Convert asn1_dsa.c to use the WPACKET API instead
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9111)

commit 15cb0f095878092a625219f58bd915bdf1acc973
Author: Matt Caswell <matt at openssl.org>
Date:   Mon Jun 10 17:48:26 2019 +0100

    Give WPACKET the ability to have a NULL buffer underneath it
    
    This means the WPACKET API can be used for calculating the number of
    bytes that would have been written if a non-NULL buffer had been used.
    This enables us to calculate the number of length bytes required when
    encoding ASN.1
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9111)

commit 8ae173bb57819a23717fd3c8e7c51cb62f4268d0
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 7 17:40:21 2019 +0100

    Convert asn1_dsa.c to use the PACKET API instead
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9111)

commit 0d345f0e10b14392925479fc61b6c9072a9605a3
Author: Matt Caswell <matt at openssl.org>
Date:   Fri Jun 7 16:32:49 2019 +0100

    Make the PACKET/WPACKET code available to both libcrypto and libssl
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    (Merged from https://github.com/openssl/openssl/pull/9111)

commit 54846b7c6ef5718f507def9d192628133f97fe20
Author: David Makepeace <david.p.makepeace at oracle.com>
Date:   Mon Jun 3 14:58:54 2019 +1000

    Add simple ASN.1 utils for DSA signature DER.
    
    Adds simple utility functions to allow both the default and fips providers to
    encode and decode DSA-Sig-Value and ECDSA-Sig-Value (DSA_SIG and ECDSA_SIG
    structures) to/from ASN.1 DER without requiring those providers to have a
    dependency on the asn1 module.
    
    Reviewed-by: Paul Dale <paul.dale at oracle.com>
    Reviewed-by: Matt Caswell <matt at openssl.org>
    (Merged from https://github.com/openssl/openssl/pull/9111)

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

Summary of changes:
 crypto/asn1_dsa.c                                  | 253 +++++++++++++++++++++
 crypto/build.info                                  |   3 +-
 crypto/dsa/dsa_asn1.c                              |  76 ++++++-
 crypto/ec/ec_asn1.c                                |  75 +++++-
 crypto/include/internal/asn1_dsa.h                 |  23 ++
 {ssl => crypto}/packet.c                           |  56 ++++-
 ssl/packet_locl.h => include/internal/packet.h     |  10 +
 ssl/build.info                                     |   6 +-
 ssl/record/rec_layer_d1.c                          |   2 +-
 ssl/record/rec_layer_s3.c                          |   2 +-
 ssl/ssl_locl.h                                     |   2 +-
 ssl/ssl_rsa.c                                      |   2 +-
 test/asn1_dsa_internal_test.c                      | 184 +++++++++++++++
 test/asynciotest.c                                 |   2 +-
 test/bad_dtls_test.c                               |   2 +-
 test/build.info                                    |   9 +-
 test/clienthellotest.c                             |   2 +-
 test/packettest.c                                  |   2 +-
 ...ernal_namemap.t => 03-test_internal_asn1_dsa.t} |   4 +-
 test/servername_test.c                             |   2 +-
 test/sslbuffertest.c                               |   2 +-
 test/tls13ccstest.c                                |   2 +-
 test/wpackettest.c                                 |   2 +-
 23 files changed, 679 insertions(+), 44 deletions(-)
 create mode 100644 crypto/asn1_dsa.c
 create mode 100644 crypto/include/internal/asn1_dsa.h
 rename {ssl => crypto}/packet.c (89%)
 rename ssl/packet_locl.h => include/internal/packet.h (98%)
 create mode 100644 test/asn1_dsa_internal_test.c
 copy test/recipes/{03-test_internal_namemap.t => 03-test_internal_asn1_dsa.t} (82%)

diff --git a/crypto/asn1_dsa.c b/crypto/asn1_dsa.c
new file mode 100644
index 0000000..8423ff8
--- /dev/null
+++ b/crypto/asn1_dsa.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+/*
+ * A simple ASN.1 DER encoder/decoder for DSA-Sig-Value and ECDSA-Sig-Value.
+ *
+ * DSA-Sig-Value ::= SEQUENCE {
+ *  r  INTEGER,
+ *  s  INTEGER
+ * }
+ *
+ * ECDSA-Sig-Value ::= SEQUENCE {
+ *  r  INTEGER,
+ *  s  INTEGER
+ * }
+ */
+
+#include <openssl/crypto.h>
+#include <openssl/bn.h>
+#include "internal/asn1_dsa.h"
+#include "internal/packet.h"
+
+#define ID_SEQUENCE 0x30
+#define ID_INTEGER 0x02
+
+/*
+ * Outputs the encoding of the length octets for a DER value with a content
+ * length of cont_len bytes to pkt. The maximum supported content length is
+ * 65535 (0xffff) bytes.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int encode_der_length(WPACKET *pkt, size_t cont_len)
+{
+    if (cont_len > 0xffff)
+        return 0; /* Too large for supported length encodings */
+
+    if (cont_len > 0xff) {
+        if (!WPACKET_put_bytes_u8(pkt, 0x82)
+                || !WPACKET_put_bytes_u16(pkt, cont_len))
+            return 0;
+    } else {
+        if (cont_len > 0x7f
+                && !WPACKET_put_bytes_u8(pkt, 0x81))
+            return 0;
+        if (!WPACKET_put_bytes_u8(pkt, cont_len))
+            return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * Outputs the DER encoding of a positive ASN.1 INTEGER to pkt.
+ *
+ * Results in an error if n is negative or too large.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int encode_der_integer(WPACKET *pkt, const BIGNUM *n)
+{
+    unsigned char *bnbytes;
+    size_t cont_len;
+
+    if (BN_is_negative(n))
+        return 0;
+
+    /*
+     * Calculate the ASN.1 INTEGER DER content length for n.
+     * This is the number of whole bytes required to represent n (i.e. rounded
+     * down), plus one.
+     * If n is zero then the content is a single zero byte (length = 1).
+     * If the number of bits of n is a multiple of 8 then an extra zero padding
+     * byte is included to ensure that the value is still treated as positive
+     * in the INTEGER two's complement representation.
+     */
+    cont_len = BN_num_bits(n) / 8 + 1;
+
+    if (!WPACKET_start_sub_packet(pkt)
+            || !WPACKET_put_bytes_u8(pkt, ID_INTEGER)
+            || !encode_der_length(pkt, cont_len)
+            || !WPACKET_allocate_bytes(pkt, cont_len, &bnbytes)
+            || !WPACKET_close(pkt))
+        return 0;
+
+    if (bnbytes != NULL
+            && BN_bn2binpad(n, bnbytes, (int)cont_len) != (int)cont_len)
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to pkt. pkt
+ * may be initialised with a NULL buffer which enables pkt to be used to
+ * calulate how many bytes would be needed.
+ *
+ * Returns 1 on success or 0 on error.
+ */
+int encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s)
+{
+    WPACKET tmppkt, *dummypkt;
+    size_t cont_len;
+    int isnull = WPACKET_is_null_buf(pkt);
+
+    if (!WPACKET_start_sub_packet(pkt))
+        return 0;
+
+    if (!isnull) {
+        if (!WPACKET_init_null(&tmppkt, 0))
+            return 0;
+        dummypkt = &tmppkt;
+    } else {
+        /* If the input packet has a NULL buffer, we don't need a dummy packet */
+        dummypkt = pkt;
+    }
+
+    /* Calculate the content length */
+    if (!encode_der_integer(dummypkt, r)
+            || !encode_der_integer(dummypkt, s)
+            || !WPACKET_get_length(dummypkt, &cont_len)
+            || (!isnull && !WPACKET_finish(dummypkt))) {
+        if (!isnull)
+            WPACKET_cleanup(dummypkt);
+        return 0;
+    }
+
+    /* Add the tag and length bytes */
+    if (!WPACKET_put_bytes_u8(pkt, ID_SEQUENCE)
+            || !encode_der_length(pkt, cont_len)
+               /*
+                * Really encode the integers. We already wrote to the main pkt
+                * if it had a NULL buffer, so don't do it again
+                */
+            || (!isnull && !encode_der_integer(pkt, r))
+            || (!isnull && !encode_der_integer(pkt, s))
+            || !WPACKET_close(pkt))
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Decodes the DER length octets in pkt and initialises subpkt with the
+ * following bytes of that length.
+ *
+ * Returns 1 on success or 0 on failure.
+ */
+int decode_der_length(PACKET *pkt, PACKET *subpkt)
+{
+    unsigned int byte;
+
+    if (!PACKET_get_1(pkt, &byte))
+        return 0;
+
+    if (byte < 0x80)
+        return PACKET_get_sub_packet(pkt, subpkt, (size_t)byte);
+    if (byte == 0x81)
+        return PACKET_get_length_prefixed_1(pkt, subpkt);
+    if (byte == 0x82)
+        return PACKET_get_length_prefixed_2(pkt, subpkt);
+
+    /* Too large, invalid, or not DER. */
+    return 0;
+}
+
+/*
+ * Decodes a single ASN.1 INTEGER value from pkt, which must be DER encoded,
+ * and updates n with the decoded value.
+ *
+ * The BIGNUM, n, must have already been allocated by calling BN_new().
+ * pkt must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns 1 on success or 0 on error.
+ *
+ * If the PACKET is supposed to only contain a single INTEGER value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+int decode_der_integer(PACKET *pkt, BIGNUM *n)
+{
+    PACKET contpkt, tmppkt;
+    unsigned int tag, tmp;
+
+    /* Check we have an integer and get the content bytes */
+    if (!PACKET_get_1(pkt, &tag)
+            || tag != ID_INTEGER
+            || !decode_der_length(pkt, &contpkt))
+        return 0;
+
+    /* Peek ahead at the first bytes to check for proper encoding */
+    tmppkt = contpkt;
+    /* The INTEGER must be positive */
+    if (!PACKET_get_1(&tmppkt, &tmp)
+            || (tmp & 0x80) != 0)
+        return 0;
+    /* If there a zero padding byte the next byte must have the msb set */
+    if (PACKET_remaining(&tmppkt) > 0 && tmp == 0) {
+        if (!PACKET_get_1(&tmppkt, &tmp)
+                || (tmp & 0x80) == 0)
+            return 0;
+    }
+
+    if (BN_bin2bn(PACKET_data(&contpkt),
+                  (int)PACKET_remaining(&contpkt), n) == NULL)
+        return 0;
+
+    return 1;
+}
+
+/*
+ * Decodes a single DSA-Sig-Value or ECDSA-Sig-Value from *ppin, which must be
+ * DER encoded, updates r and s with the decoded values, and increments *ppin
+ * past the data that was consumed.
+ *
+ * The BIGNUMs, r and s, must have already been allocated by calls to BN_new().
+ * ppin and *ppin must not be NULL.
+ *
+ * An attempt to consume more than len bytes results in an error.
+ * Returns the number of bytes of input consumed or 0 if an error occurs.
+ *
+ * If the buffer is supposed to only contain a single [EC]DSA-Sig-Value with no
+ * trailing garbage then it is up to the caller to verify that all bytes
+ * were consumed.
+ */
+size_t decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin,
+                          size_t len)
+{
+    size_t consumed;
+    PACKET pkt, contpkt;
+    unsigned int tag;
+
+    if (!PACKET_buf_init(&pkt, *ppin, len)
+            || !PACKET_get_1(&pkt, &tag)
+            || tag != ID_SEQUENCE
+            || !decode_der_length(&pkt, &contpkt)
+            || !decode_der_integer(&contpkt, r)
+            || !decode_der_integer(&contpkt, s)
+            || PACKET_remaining(&contpkt) != 0)
+        return 0;
+
+    consumed = PACKET_data(&pkt) - *ppin;
+    *ppin += consumed;
+    return consumed;
+}
+
diff --git a/crypto/build.info b/crypto/build.info
index fccca08..90ccbc8 100644
--- a/crypto/build.info
+++ b/crypto/build.info
@@ -75,11 +75,10 @@ SOURCE[../libcrypto]=$UTIL_COMMON \
         mem.c mem_sec.c mem_str.c mem_dbg.c \
         cversion.c info.c cpt_err.c ebcdic.c uid.c o_time.c o_dir.c \
         o_fopen.c getenv.c o_init.c o_fips.c init.c trace.c provider.c \
-        $UPLINKSRC
+        asn1_dsa.c packet.c $UPLINKSRC
 DEFINE[../libcrypto]=$UTIL_DEFINE $UPLINKDEF
 SOURCE[../providers/fips]=$UTIL_COMMON
 DEFINE[../providers/fips]=$UTIL_DEFINE
-        
 
 
 DEPEND[cversion.o]=buildinf.h
diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
index acf80c6..eddcc11 100644
--- a/crypto/dsa/dsa_asn1.c
+++ b/crypto/dsa/dsa_asn1.c
@@ -13,13 +13,7 @@
 #include <openssl/asn1.h>
 #include <openssl/asn1t.h>
 #include <openssl/rand.h>
-
-ASN1_SEQUENCE(DSA_SIG) = {
-        ASN1_SIMPLE(DSA_SIG, r, CBIGNUM),
-        ASN1_SIMPLE(DSA_SIG, s, CBIGNUM)
-} static_ASN1_SEQUENCE_END(DSA_SIG)
-
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(DSA_SIG, DSA_SIG, DSA_SIG)
+#include "internal/asn1_dsa.h"
 
 DSA_SIG *DSA_SIG_new(void)
 {
@@ -38,6 +32,74 @@ void DSA_SIG_free(DSA_SIG *sig)
     OPENSSL_free(sig);
 }
 
+DSA_SIG *d2i_DSA_SIG(DSA_SIG **psig, const unsigned char **ppin, long len)
+{
+    DSA_SIG *sig;
+
+    if (len < 0)
+        return NULL;
+    if (psig != NULL && *psig != NULL) {
+        sig = *psig;
+    } else {
+        sig = DSA_SIG_new();
+        if (sig == NULL)
+            return NULL;
+    }
+    if (sig->r == NULL)
+        sig->r = BN_new();
+    if (sig->s == NULL)
+        sig->s = BN_new();
+    if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
+        if (psig == NULL || *psig == NULL)
+            DSA_SIG_free(sig);
+        return NULL;
+    }
+    if (psig != NULL && *psig == NULL)
+        *psig = sig;
+    return sig;
+}
+
+int i2d_DSA_SIG(const DSA_SIG *sig, unsigned char **ppout)
+{
+    BUF_MEM *buf = NULL;
+    size_t encoded_len;
+    WPACKET pkt;
+
+    if (ppout == NULL) {
+        if (!WPACKET_init_null(&pkt, 0))
+            return -1;
+    } else if (*ppout == NULL) {
+        if ((buf = BUF_MEM_new()) == NULL
+                || !WPACKET_init_len(&pkt, buf, 0)) {
+            BUF_MEM_free(buf);
+            return -1;
+        }
+    } else {
+        if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
+            return -1;
+    }
+
+    if (!encode_der_dsa_sig(&pkt, sig->r, sig->s)
+            || !WPACKET_get_total_written(&pkt, &encoded_len)
+            || !WPACKET_finish(&pkt)) {
+        BUF_MEM_free(buf);
+        WPACKET_cleanup(&pkt);
+        return -1;
+    }
+
+    if (ppout != NULL) {
+        if (*ppout == NULL) {
+            *ppout = (unsigned char *)buf->data;
+            buf->data = NULL;
+            BUF_MEM_free(buf);
+        } else {
+            *ppout += encoded_len;
+        }
+    }
+
+    return (int)encoded_len;
+}
+
 void DSA_SIG_get0(const DSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
 {
     if (pr != NULL)
diff --git a/crypto/ec/ec_asn1.c b/crypto/ec/ec_asn1.c
index 35ff948..c2f9679 100644
--- a/crypto/ec/ec_asn1.c
+++ b/crypto/ec/ec_asn1.c
@@ -13,6 +13,7 @@
 #include <openssl/asn1t.h>
 #include <openssl/objects.h>
 #include "internal/nelem.h"
+#include "internal/asn1_dsa.h"
 
 int EC_GROUP_get_basis_type(const EC_GROUP *group)
 {
@@ -1137,14 +1138,8 @@ int i2o_ECPublicKey(const EC_KEY *a, unsigned char **out)
     return buf_len;
 }
 
-ASN1_SEQUENCE(ECDSA_SIG) = {
-        ASN1_SIMPLE(ECDSA_SIG, r, CBIGNUM),
-        ASN1_SIMPLE(ECDSA_SIG, s, CBIGNUM)
-} static_ASN1_SEQUENCE_END(ECDSA_SIG)
-
 DECLARE_ASN1_FUNCTIONS(ECDSA_SIG)
 DECLARE_ASN1_ENCODE_FUNCTIONS_name(ECDSA_SIG, ECDSA_SIG)
-IMPLEMENT_ASN1_ENCODE_FUNCTIONS_fname(ECDSA_SIG, ECDSA_SIG, ECDSA_SIG)
 
 ECDSA_SIG *ECDSA_SIG_new(void)
 {
@@ -1163,6 +1158,74 @@ void ECDSA_SIG_free(ECDSA_SIG *sig)
     OPENSSL_free(sig);
 }
 
+ECDSA_SIG *d2i_ECDSA_SIG(ECDSA_SIG **psig, const unsigned char **ppin, long len)
+{
+    ECDSA_SIG *sig;
+
+    if (len < 0)
+        return NULL;
+    if (psig != NULL && *psig != NULL) {
+        sig = *psig;
+    } else {
+        sig = ECDSA_SIG_new();
+        if (sig == NULL)
+            return NULL;
+    }
+    if (sig->r == NULL)
+        sig->r = BN_new();
+    if (sig->s == NULL)
+        sig->s = BN_new();
+    if (decode_der_dsa_sig(sig->r, sig->s, ppin, (size_t)len) == 0) {
+        if (psig == NULL || *psig == NULL)
+            ECDSA_SIG_free(sig);
+        return NULL;
+    }
+    if (psig != NULL && *psig == NULL)
+        *psig = sig;
+    return sig;
+}
+
+int i2d_ECDSA_SIG(const ECDSA_SIG *sig, unsigned char **ppout)
+{
+    BUF_MEM *buf = NULL;
+    size_t encoded_len;
+    WPACKET pkt;
+
+    if (ppout == NULL) {
+        if (!WPACKET_init_null(&pkt, 0))
+            return -1;
+    } else if (*ppout == NULL) {
+        if ((buf = BUF_MEM_new()) == NULL
+                || !WPACKET_init_len(&pkt, buf, 0)) {
+            BUF_MEM_free(buf);
+            return -1;
+        }
+    } else {
+        if (!WPACKET_init_static_len(&pkt, *ppout, SIZE_MAX, 0))
+            return -1;
+    }
+
+    if (!encode_der_dsa_sig(&pkt, sig->r, sig->s)
+            || !WPACKET_get_total_written(&pkt, &encoded_len)
+            || !WPACKET_finish(&pkt)) {
+        BUF_MEM_free(buf);
+        WPACKET_cleanup(&pkt);
+        return -1;
+    }
+
+    if (ppout != NULL) {
+        if (*ppout == NULL) {
+            *ppout = (unsigned char *)buf->data;
+            buf->data = NULL;
+            BUF_MEM_free(buf);
+        } else {
+            *ppout += encoded_len;
+        }
+    }
+
+    return (int)encoded_len;
+}
+
 void ECDSA_SIG_get0(const ECDSA_SIG *sig, const BIGNUM **pr, const BIGNUM **ps)
 {
     if (pr != NULL)
diff --git a/crypto/include/internal/asn1_dsa.h b/crypto/include/internal/asn1_dsa.h
new file mode 100644
index 0000000..d257051
--- /dev/null
+++ b/crypto/include/internal/asn1_dsa.h
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#ifndef HEADER_ASN1_DSA_H
+# define HEADER_ASN1_DSA_H
+
+#include "internal/packet.h"
+
+int encode_der_length(WPACKET *pkt, size_t cont_len);
+int encode_der_integer(WPACKET *pkt, const BIGNUM *n);
+int encode_der_dsa_sig(WPACKET *pkt, const BIGNUM *r, const BIGNUM *s);
+int decode_der_length(PACKET *pkt, PACKET *subpkt);
+int decode_der_integer(PACKET *pkt, BIGNUM *n);
+size_t decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin,
+                          size_t len);
+
+#endif
diff --git a/ssl/packet.c b/crypto/packet.c
similarity index 89%
rename from ssl/packet.c
rename to crypto/packet.c
index 26cf1eb..75a0317 100644
--- a/ssl/packet.c
+++ b/crypto/packet.c
@@ -8,7 +8,7 @@
  */
 
 #include "internal/cryptlib.h"
-#include "packet_locl.h"
+#include "internal/packet.h"
 #include <openssl/sslerr.h>
 
 #define DEFAULT_BUF_SIZE    256
@@ -35,7 +35,10 @@ int WPACKET_sub_allocate_bytes__(WPACKET *pkt, size_t len,
 }
 
 #define GETBUF(p)   (((p)->staticbuf != NULL) \
-                     ? (p)->staticbuf : (unsigned char *)(p)->buf->data)
+                     ? (p)->staticbuf \
+                     : ((p)->buf != NULL \
+                        ? (unsigned char *)(p)->buf->data \
+                        : NULL))
 
 int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
 {
@@ -46,7 +49,7 @@ int WPACKET_reserve_bytes(WPACKET *pkt, size_t len, unsigned char **allocbytes)
     if (pkt->maxsize - pkt->written < len)
         return 0;
 
-    if (pkt->staticbuf == NULL && (pkt->buf->length - pkt->written < len)) {
+    if (pkt->buf != NULL && (pkt->buf->length - pkt->written < len)) {
         size_t newlen;
         size_t reflen;
 
@@ -74,7 +77,8 @@ int WPACKET_sub_reserve_bytes__(WPACKET *pkt, size_t len,
     if (!WPACKET_reserve_bytes(pkt, lenbytes + len, allocbytes))
         return 0;
 
-    *allocbytes += lenbytes;
+    if (*allocbytes != NULL)
+        *allocbytes += lenbytes;
 
     return 1;
 }
@@ -110,7 +114,7 @@ static int wpacket_intern_init_len(WPACKET *pkt, size_t lenbytes)
         pkt->subs = NULL;
         return 0;
     }
-    pkt->subs->packet_len = lenchars - GETBUF(pkt);
+    pkt->subs->packet_len = 0;
 
     return 1;
 }
@@ -149,6 +153,15 @@ int WPACKET_init(WPACKET *pkt, BUF_MEM *buf)
     return WPACKET_init_len(pkt, buf, 0);
 }
 
+int WPACKET_init_null(WPACKET *pkt, size_t lenbytes)
+{
+    pkt->staticbuf = NULL;
+    pkt->buf = NULL;
+    pkt->maxsize = maxmaxsize(lenbytes);
+
+    return wpacket_intern_init_len(pkt, 0);
+}
+
 int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
 {
     /* Internal API, so should not fail */
@@ -163,6 +176,9 @@ int WPACKET_set_flags(WPACKET *pkt, unsigned int flags)
 /* Store the |value| of length |len| at location |data| */
 static int put_value(unsigned char *data, size_t value, size_t len)
 {
+    if (data == NULL)
+        return 1;
+
     for (data += len - 1; len > 0; len--) {
         *data = (unsigned char)(value & 0xff);
         data--;
@@ -209,10 +225,14 @@ static int wpacket_intern_close(WPACKET *pkt, WPACKET_SUB *sub, int doclose)
     }
 
     /* Write out the WPACKET length if needed */
-    if (sub->lenbytes > 0
-                && !put_value(&GETBUF(pkt)[sub->packet_len], packlen,
+    if (sub->lenbytes > 0) {
+        unsigned char *buf = GETBUF(pkt);
+
+        if (buf != NULL
+                && !put_value(&buf[sub->packet_len], packlen,
                               sub->lenbytes))
             return 0;
+    }
 
     if (doclose) {
         pkt->subs = sub->parent;
@@ -293,10 +313,10 @@ int WPACKET_start_sub_packet_len__(WPACKET *pkt, size_t lenbytes)
         return 1;
     }
 
+    sub->packet_len = pkt->written;
+
     if (!WPACKET_allocate_bytes(pkt, lenbytes, &lenchars))
         return 0;
-    /* Convert to an offset in case the underlying BUF_MEM gets realloc'd */
-    sub->packet_len = lenchars - GETBUF(pkt);
 
     return 1;
 }
@@ -354,7 +374,8 @@ int WPACKET_memset(WPACKET *pkt, int ch, size_t len)
     if (!WPACKET_allocate_bytes(pkt, len, &dest))
         return 0;
 
-    memset(dest, ch, len);
+    if (dest != NULL)
+        memset(dest, ch, len);
 
     return 1;
 }
@@ -369,7 +390,8 @@ int WPACKET_memcpy(WPACKET *pkt, const void *src, size_t len)
     if (!WPACKET_allocate_bytes(pkt, len, &dest))
         return 0;
 
-    memcpy(dest, src, len);
+    if (dest != NULL)
+        memcpy(dest, src, len);
 
     return 1;
 }
@@ -409,7 +431,17 @@ int WPACKET_get_length(WPACKET *pkt, size_t *len)
 
 unsigned char *WPACKET_get_curr(WPACKET *pkt)
 {
-    return GETBUF(pkt) + pkt->curr;
+    unsigned char *buf = GETBUF(pkt);
+
+    if (buf == NULL)
+        return NULL;
+
+    return buf + pkt->curr;
+}
+
+int WPACKET_is_null_buf(WPACKET *pkt)
+{
+    return pkt->buf == NULL && pkt->staticbuf == NULL;
 }
 
 void WPACKET_cleanup(WPACKET *pkt)
diff --git a/ssl/packet_locl.h b/include/internal/packet.h
similarity index 98%
rename from ssl/packet_locl.h
rename to include/internal/packet.h
index 9f8a098..69a6bd1 100644
--- a/ssl/packet_locl.h
+++ b/include/internal/packet.h
@@ -670,6 +670,13 @@ int WPACKET_init_len(WPACKET *pkt, BUF_MEM *buf, size_t lenbytes);
 int WPACKET_init(WPACKET *pkt, BUF_MEM *buf);
 
 /*
+ * Same as WPACKET_init_len except there is no underlying buffer. No data is
+ * ever actually written. We just keep track of how much data would have been
+ * written if a buffer was there.
+ */
+int WPACKET_init_null(WPACKET *pkt, size_t lenbytes);
+
+/*
  * Same as WPACKET_init_len except we do not use a growable BUF_MEM structure.
  * A fixed buffer of memory |buf| of size |len| is used instead. A failure will
  * occur if you attempt to write beyond the end of the buffer
@@ -868,6 +875,9 @@ int WPACKET_get_length(WPACKET *pkt, size_t *len);
  */
 unsigned char *WPACKET_get_curr(WPACKET *pkt);
 
+/* Returns true if the underlying buffer is actually NULL */
+int WPACKET_is_null_buf(WPACKET *pkt);
+
 /* Release resources in a WPACKET if a failure has occurred. */
 void WPACKET_cleanup(WPACKET *pkt);
 
diff --git a/ssl/build.info b/ssl/build.info
index bb2f1de..152810b 100644
--- a/ssl/build.info
+++ b/ssl/build.info
@@ -1,6 +1,10 @@
 LIBS=../libssl
+#TODO: For now we just include the libcrypto packet.c in libssl as well. We
+#      could either continue to do it like this, or export all the WPACKET
+#      symbols so that libssl can use them like any other. Probably would do
+#      this privately so it does not become part of the public API.
 SOURCE[../libssl]=\
-        pqueue.c packet.c \
+        pqueue.c ../crypto/packet.c \
         statem/statem_srvr.c statem/statem_clnt.c  s3_lib.c  s3_enc.c record/rec_layer_s3.c \
         statem/statem_lib.c statem/extensions.c statem/extensions_srvr.c \
         statem/extensions_clnt.c statem/extensions_cust.c s3_cbc.c s3_msg.c \
diff --git a/ssl/record/rec_layer_d1.c b/ssl/record/rec_layer_d1.c
index 821c9cc..1256f9e 100644
--- a/ssl/record/rec_layer_d1.c
+++ b/ssl/record/rec_layer_d1.c
@@ -13,7 +13,7 @@
 #include <openssl/evp.h>
 #include <openssl/buffer.h>
 #include "record_locl.h"
-#include "../packet_locl.h"
+#include "internal/packet.h"
 #include "internal/cryptlib.h"
 
 int DTLS_RECORD_LAYER_new(RECORD_LAYER *rl)
diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c
index a991132..9efaf54 100644
--- a/ssl/record/rec_layer_s3.c
+++ b/ssl/record/rec_layer_s3.c
@@ -15,7 +15,7 @@
 #include <openssl/buffer.h>
 #include <openssl/rand.h>
 #include "record_locl.h"
-#include "../packet_locl.h"
+#include "internal/packet.h"
 
 #if     defined(OPENSSL_SMALL_FOOTPRINT) || \
         !(      defined(AES_ASM) &&     ( \
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 269f542..a4278b2 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -30,7 +30,7 @@
 # include <openssl/ct.h>
 # include "record/record.h"
 # include "statem/statem.h"
-# include "packet_locl.h"
+# include "internal/packet.h"
 # include "internal/dane.h"
 # include "internal/refcount.h"
 # include "internal/tsan_assist.h"
diff --git a/ssl/ssl_rsa.c b/ssl/ssl_rsa.c
index 897c8f2..2c447ee 100644
--- a/ssl/ssl_rsa.c
+++ b/ssl/ssl_rsa.c
@@ -9,7 +9,7 @@
 
 #include <stdio.h>
 #include "ssl_locl.h"
-#include "packet_locl.h"
+#include "internal/packet.h"
 #include <openssl/bio.h>
 #include <openssl/objects.h>
 #include <openssl/evp.h>
diff --git a/test/asn1_dsa_internal_test.c b/test/asn1_dsa_internal_test.c
new file mode 100644
index 0000000..a62f5e4
--- /dev/null
+++ b/test/asn1_dsa_internal_test.c
@@ -0,0 +1,184 @@
+/*
+ * Copyright 2019 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the Apache License 2.0 (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+#include "internal/asn1_dsa.h"
+#include "testutil.h"
+
+static unsigned char t_dsa_sig[] = {
+    0x30, 0x06,                  /* SEQUENCE tag + length */
+    0x02, 0x01, 0x01,            /* INTEGER tag + length + content */
+    0x02, 0x01, 0x02             /* INTEGER tag + length + content */
+};
+
+static unsigned char t_dsa_sig_extra[] = {
+    0x30, 0x06,                  /* SEQUENCE tag + length */
+    0x02, 0x01, 0x01,            /* INTEGER tag + length + content */
+    0x02, 0x01, 0x02,            /* INTEGER tag + length + content */
+    0x05, 0x00                   /* NULL tag + length */
+};
+
+static unsigned char t_dsa_sig_msb[] = {
+    0x30, 0x08,                  /* SEQUENCE tag + length */
+    0x02, 0x02, 0x00, 0x81,      /* INTEGER tag + length + content */
+    0x02, 0x02, 0x00, 0x82       /* INTEGER tag + length + content */
+};
+
+static unsigned char t_dsa_sig_two[] = {
+    0x30, 0x08,                  /* SEQUENCE tag + length */
+    0x02, 0x02, 0x01, 0x00,      /* INTEGER tag + length + content */
+    0x02, 0x02, 0x02, 0x00       /* INTEGER tag + length + content */
+};
+
+/*
+ * Badly coded ASN.1 INTEGER zero wrapped in a sequence along with another
+ * (valid) INTEGER.
+ */
+static unsigned char t_invalid_int_zero[] = {
+    0x30, 0x05,                  /* SEQUENCE tag + length */
+    0x02, 0x00,                  /* INTEGER tag + length */
+    0x02, 0x01, 0x2a             /* INTEGER tag + length */
+};
+
+/*
+ * Badly coded ASN.1 INTEGER (with leading zeros) wrapped in a sequence along
+ * with another (valid) INTEGER.
+ */
+static unsigned char t_invalid_int[] = {
+    0x30, 0x07,                  /* SEQUENCE tag + length */
+    0x02, 0x02, 0x00, 0x7f,      /* INTEGER tag + length */
+    0x02, 0x01, 0x2a             /* INTEGER tag + length */
+};
+
+/*
+ * Negative ASN.1 INTEGER wrapped in a sequence along with another
+ * (valid) INTEGER.
+ */
+static unsigned char t_neg_int[] = {
+    0x30, 0x06,                  /* SEQUENCE tag + length */
+    0x02, 0x01, 0xaa,            /* INTEGER tag + length */
+    0x02, 0x01, 0x2a             /* INTEGER tag + length */
+};
+
+static unsigned char t_trunc_der[] = {
+    0x30, 0x08,                  /* SEQUENCE tag + length */
+    0x02, 0x02, 0x00, 0x81,      /* INTEGER tag + length */
+    0x02, 0x02, 0x00             /* INTEGER tag + length */
+};
+
+static unsigned char t_trunc_seq[] = {
+    0x30, 0x07,                  /* SEQUENCE tag + length */
+    0x02, 0x02, 0x00, 0x81,      /* INTEGER tag + length */
+    0x02, 0x02, 0x00, 0x82       /* INTEGER tag + length */
+};
+
+static int test_decode(void)
+{
+    int rv = 0;
+    BIGNUM *r;
+    BIGNUM *s;
+    const unsigned char *pder;
+
+    r = BN_new();
+    s = BN_new();
+
+    /* Positive tests */
+    pder = t_dsa_sig;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_dsa_sig)) == 0
+            || !TEST_ptr_eq(pder, (t_dsa_sig + sizeof(t_dsa_sig)))
+            || !TEST_BN_eq_word(r, 1) || !TEST_BN_eq_word(s, 2)) {
+        TEST_info("asn1_dsa test_decode: t_dsa_sig failed");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_dsa_sig_extra;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_dsa_sig_extra)) == 0
+            || !TEST_ptr_eq(pder,
+                            (t_dsa_sig_extra + sizeof(t_dsa_sig_extra) - 2))
+            || !TEST_BN_eq_word(r, 1) || !TEST_BN_eq_word(s, 2)) {
+        TEST_info("asn1_dsa test_decode: t_dsa_sig_extra failed");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_dsa_sig_msb;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_dsa_sig_msb)) == 0
+            || !TEST_ptr_eq(pder, (t_dsa_sig_msb + sizeof(t_dsa_sig_msb)))
+            || !TEST_BN_eq_word(r, 0x81) || !TEST_BN_eq_word(s, 0x82)) {
+        TEST_info("asn1_dsa test_decode: t_dsa_sig_msb failed");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_dsa_sig_two;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_dsa_sig_two)) == 0
+            || !TEST_ptr_eq(pder, (t_dsa_sig_two + sizeof(t_dsa_sig_two)))
+            || !TEST_BN_eq_word(r, 0x100) || !TEST_BN_eq_word(s, 0x200)) {
+        TEST_info("asn1_dsa test_decode: t_dsa_sig_two failed");
+        goto fail;
+    }
+
+    /* Negative tests */
+    pder = t_invalid_int_zero;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_invalid_int_zero)) != 0) {
+        TEST_info("asn1_dsa test_decode: Expected t_invalid_int_zero to fail");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_invalid_int;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_invalid_int)) != 0) {
+        TEST_info("asn1_dsa test_decode: Expected t_invalid_int to fail");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_neg_int;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_neg_int)) != 0) {
+        TEST_info("asn1_dsa test_decode: Expected t_neg_int to fail");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_trunc_der;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_trunc_der)) != 0) {
+        TEST_info("asn1_dsa test_decode: Expected fail t_trunc_der");
+        goto fail;
+    }
+
+    BN_clear(r);
+    BN_clear(s);
+    pder = t_trunc_seq;
+    if (decode_der_dsa_sig(r, s, &pder, sizeof(t_trunc_seq)) != 0) {
+        TEST_info("asn1_dsa test_decode: Expected fail t_trunc_seq");
+        goto fail;
+    }
+
+    rv = 1;
+fail:
+    BN_free(r);
+    BN_free(s);
+    return rv;
+}
+
+int setup_tests(void)
+{
+    ADD_TEST(test_decode);
+    return 1;
+}
diff --git a/test/asynciotest.c b/test/asynciotest.c
index 3bba098..bf0a205 100644
--- a/test/asynciotest.c
+++ b/test/asynciotest.c
@@ -13,7 +13,7 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 
 #include "ssltestlib.h"
 #include "testutil.h"
diff --git a/test/bad_dtls_test.c b/test/bad_dtls_test.c
index 5f6b6a9..66b5e1d 100644
--- a/test/bad_dtls_test.c
+++ b/test/bad_dtls_test.c
@@ -37,7 +37,7 @@
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <openssl/kdf.h>
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 #include "internal/nelem.h"
 #include "testutil.h"
 
diff --git a/test/build.info b/test/build.info
index f5b802d..e38f142 100644
--- a/test/build.info
+++ b/test/build.info
@@ -469,7 +469,8 @@ IF[{- !$disabled{tests} -}]
     PROGRAMS{noinst}=asn1_internal_test modes_internal_test x509_internal_test \
                      tls13encryptiontest wpackettest ctype_internal_test \
                      rdrand_sanitytest property_test \
-                     rsa_sp800_56b_test bn_internal_test
+                     rsa_sp800_56b_test bn_internal_test \
+                     asn1_dsa_internal_test
 
     IF[{- !$disabled{poly1305} -}]
       PROGRAMS{noinst}=poly1305_internal_test
@@ -561,6 +562,10 @@ IF[{- !$disabled{tests} -}]
     SOURCE[bn_internal_test]=bn_internal_test.c
     INCLUDE[bn_internal_test]=.. ../include ../crypto/include ../crypto/bn ../apps/include
     DEPEND[bn_internal_test]=../libcrypto.a libtestutil.a
+
+    SOURCE[asn1_dsa_internal_test]=asn1_dsa_internal_test.c
+    INCLUDE[asn1_dsa_internal_test]=.. ../include ../apps/include ../crypto/include
+    DEPEND[asn1_dsa_internal_test]=../libcrypto.a libtestutil.a
   ENDIF
 
   IF[{- !$disabled{mdc2} -}]
@@ -582,7 +587,7 @@ IF[{- !$disabled{tests} -}]
   IF[{- !$disabled{shared} -}]
     PROGRAMS{noinst}=tls13secretstest
     SOURCE[tls13secretstest]=tls13secretstest.c
-    SOURCE[tls13secretstest]= ../ssl/tls13_enc.c ../ssl/packet.c
+    SOURCE[tls13secretstest]= ../ssl/tls13_enc.c ../crypto/packet.c
     INCLUDE[tls13secretstest]=.. ../include ../apps/include
     DEPEND[tls13secretstest]=../libcrypto ../libssl libtestutil.a
   ENDIF
diff --git a/test/clienthellotest.c b/test/clienthellotest.c
index 0afad6d..03b8745 100644
--- a/test/clienthellotest.c
+++ b/test/clienthellotest.c
@@ -17,7 +17,7 @@
 #include <openssl/err.h>
 #include <time.h>
 
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 
 #include "testutil.h"
 
diff --git a/test/packettest.c b/test/packettest.c
index 41d938a..2d6c2a6 100644
--- a/test/packettest.c
+++ b/test/packettest.c
@@ -7,7 +7,7 @@
  * https://www.openssl.org/source/license.html
  */
 
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 #include "testutil.h"
 
 #define BUF_LEN 255
diff --git a/test/recipes/03-test_internal_namemap.t b/test/recipes/03-test_internal_asn1_dsa.t
similarity index 82%
copy from test/recipes/03-test_internal_namemap.t
copy to test/recipes/03-test_internal_asn1_dsa.t
index 9214242..ecacac7 100644
--- a/test/recipes/03-test_internal_namemap.t
+++ b/test/recipes/03-test_internal_asn1_dsa.t
@@ -11,6 +11,6 @@ use OpenSSL::Test;              # get 'plan'
 use OpenSSL::Test::Simple;
 use OpenSSL::Test::Utils;
 
-setup("test_internal_namemap");
+setup("test_internal_asn1_dsa");
 
-simple_test("test_internal_namemap", "namemap_internal_test");
+simple_test("test_internal_asn1_dsa", "asn1_dsa_internal_test");
diff --git a/test/servername_test.c b/test/servername_test.c
index 86d261f..3d19265 100644
--- a/test/servername_test.c
+++ b/test/servername_test.c
@@ -18,7 +18,7 @@
 #include <openssl/err.h>
 #include <time.h>
 
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 
 #include "testutil.h"
 #include "internal/nelem.h"
diff --git a/test/sslbuffertest.c b/test/sslbuffertest.c
index 9a5ec2b..e8293f7 100644
--- a/test/sslbuffertest.c
+++ b/test/sslbuffertest.c
@@ -13,7 +13,7 @@
 #include <openssl/bio.h>
 #include <openssl/err.h>
 
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 
 #include "ssltestlib.h"
 #include "testutil.h"
diff --git a/test/tls13ccstest.c b/test/tls13ccstest.c
index 1d0a268..999ca57 100644
--- a/test/tls13ccstest.c
+++ b/test/tls13ccstest.c
@@ -11,7 +11,7 @@
 #include <string.h>
 #include "ssltestlib.h"
 #include "testutil.h"
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 
 static char *cert = NULL;
 static char *privkey = NULL;
diff --git a/test/wpackettest.c b/test/wpackettest.c
index 0a27c63..abb001e 100644
--- a/test/wpackettest.c
+++ b/test/wpackettest.c
@@ -9,7 +9,7 @@
 
 #include <string.h>
 #include <openssl/buffer.h>
-#include "../ssl/packet_locl.h"
+#include "internal/packet.h"
 #include "testutil.h"
 
 static const unsigned char simple1[] = { 0xff };


More information about the openssl-commits mailing list