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.d...@oracle.com> Date: Fri Jul 12 06:27:19 2019 +1000 remove end of line whitespace Reviewed-by: Matt Caswell <m...@openssl.org> (Merged from https://github.com/openssl/openssl/pull/9111) commit b8805834756434bfc6ee3840e7097e6e1a877905 Author: Matt Caswell <m...@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.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9111) commit 15cb0f095878092a625219f58bd915bdf1acc973 Author: Matt Caswell <m...@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.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9111) commit 8ae173bb57819a23717fd3c8e7c51cb62f4268d0 Author: Matt Caswell <m...@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.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9111) commit 0d345f0e10b14392925479fc61b6c9072a9605a3 Author: Matt Caswell <m...@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.d...@oracle.com> (Merged from https://github.com/openssl/openssl/pull/9111) commit 54846b7c6ef5718f507def9d192628133f97fe20 Author: David Makepeace <david.p.makepe...@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.d...@oracle.com> Reviewed-by: Matt Caswell <m...@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 };