diff options
author | David Makepeace <david.p.makepeace@oracle.com> | 2019-06-03 06:58:54 +0200 |
---|---|---|
committer | Pauli <paul.dale@oracle.com> | 2019-07-11 22:26:46 +0200 |
commit | 54846b7c6ef5718f507def9d192628133f97fe20 (patch) | |
tree | 4d6810f0dda7442ec72619737c0724322e024ace | |
parent | Coverity #1451596: check dirlen for being negative (diff) | |
download | openssl-54846b7c6ef5718f507def9d192628133f97fe20.tar.xz openssl-54846b7c6ef5718f507def9d192628133f97fe20.zip |
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@oracle.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/9111)
-rw-r--r-- | crypto/asn1_dsa.c | 321 | ||||
-rw-r--r-- | crypto/build.info | 3 | ||||
-rw-r--r-- | crypto/dsa/dsa_asn1.c | 64 | ||||
-rw-r--r-- | crypto/ec/ec_asn1.c | 63 | ||||
-rw-r--r-- | crypto/include/internal/asn1_dsa.h | 23 | ||||
-rw-r--r-- | test/asn1_dsa_internal_test.c | 184 | ||||
-rw-r--r-- | test/build.info | 7 | ||||
-rw-r--r-- | test/recipes/03-test_internal_asn1_dsa.t | 16 |
8 files changed, 665 insertions, 16 deletions
diff --git a/crypto/asn1_dsa.c b/crypto/asn1_dsa.c new file mode 100644 index 0000000000..bb7f87a80c --- /dev/null +++ b/crypto/asn1_dsa.c @@ -0,0 +1,321 @@ +/* + * 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" + +#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 *ppout and, if successful, increments *ppout + * past the data just written. + * + * The maximum supported content length is 65535 (0xffff) bytes. + * The maximum returned length in bytes of the encoded output is 3. + * + * If ppout is NULL then the output size is calculated and returned but no + * output is produced. + * If ppout is not NULL then *ppout must not be NULL. + * + * An attempt to produce more than len bytes results in an error. + * Returns the number of bytes of output produced (or that would be produced) + * or 0 if an error occurs. + */ +size_t encode_der_length(size_t cont_len, unsigned char **ppout, size_t len) +{ + size_t encoded_len; + + if (cont_len <= 0x7f) { + encoded_len = 1; + } else if (cont_len <= 0xff) { + encoded_len = 2; + } else if (cont_len <= 0xffff) { + encoded_len = 3; + } else { + /* Too large for supported length encodings */ + return 0; + } + if (encoded_len > len) + return 0; + if (ppout != NULL) { + unsigned char *out = *ppout; + switch (encoded_len) { + case 2: + *out++ = 0x81; + break; + case 3: + *out++ = 0x82; + *out++ = (unsigned char)(cont_len >> 8); + break; + } + *out++ = (unsigned char)cont_len; + *ppout = out; + } + return encoded_len; +} + +/* + * Outputs the DER encoding of a positive ASN.1 INTEGER to *ppout and, if + * successful, increments *ppout past the data just written. + * + * If n is negative then an error results. + * If ppout is NULL then the output size is calculated and returned but no + * output is produced. + * If ppout is not NULL then *ppout must not be NULL. + * + * An attempt to produce more than len bytes results in an error. + * Returns the number of bytes of output produced (or that would be produced) + * or 0 if an error occurs. + */ +size_t encode_der_integer(const BIGNUM *n, unsigned char **ppout, size_t len) +{ + unsigned char *out = NULL; + unsigned char **pp = NULL; + size_t produced; + size_t c; + size_t cont_len; + + if (len < 1 || 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 (ppout != NULL) { + out = *ppout; + pp = &out; + *out++ = ID_INTEGER; + } + produced = 1; + if ((c = encode_der_length(cont_len, pp, len - produced)) == 0) + return 0; + produced += c; + if (cont_len > len - produced) + return 0; + if (pp != NULL) { + if (BN_bn2binpad(n, out, (int)cont_len) != (int)cont_len) + return 0; + out += cont_len; + *ppout = out; + } + produced += cont_len; + return produced; +} + +/* + * Outputs the DER encoding of a DSA-Sig-Value or ECDSA-Sig-Value to *ppout + * and increments *ppout past the data just written. + * + * If ppout is NULL then the output size is calculated and returned but no + * output is produced. + * If ppout is not NULL then *ppout must not be NULL. + * + * An attempt to produce more than len bytes results in an error. + * Returns the number of bytes of output produced (or that would be produced) + * or 0 if an error occurs. + */ +size_t encode_der_dsa_sig(const BIGNUM *r, const BIGNUM *s, + unsigned char **ppout, size_t len) +{ + unsigned char *out = NULL; + unsigned char **pp = NULL; + size_t produced; + size_t c; + size_t r_der_len; + size_t s_der_len; + size_t cont_len; + + if (len < 1 + || (r_der_len = encode_der_integer(r, NULL, SIZE_MAX)) == 0 + || (s_der_len = encode_der_integer(s, NULL, SIZE_MAX)) == 0) + return 0; + + cont_len = r_der_len + s_der_len; + + if (ppout != NULL) { + out = *ppout; + pp = &out; + *out++ = ID_SEQUENCE; + } + produced = 1; + if ((c = encode_der_length(cont_len, pp, len - produced)) == 0) + return 0; + produced += c; + if ((c = encode_der_integer(r, pp, len - produced)) == 0) + return 0; + produced += c; + if ((c = encode_der_integer(s, pp, len - produced)) == 0) + return 0; + produced += c; + if (pp != NULL) + *ppout = out; + return produced; +} + +/* + * Decodes the DER length octets at *ppin, stores the decoded length to + * *pcont_len and, if successful, increments *ppin past the data that was + * consumed. + * + * pcont_len, 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. + */ +size_t decode_der_length(size_t *pcont_len, const unsigned char **ppin, + size_t len) +{ + const unsigned char *in = *ppin; + size_t consumed; + size_t n; + + if (len < 1) + return 0; + n = *in++; + consumed = 1; + if (n > 0x7f) { + if (n == 0x81 && len - consumed >= 1) { + n = *in++; + if (n <= 0x7f) + return 0; /* Not DER. */ + ++consumed; + } else if (n == 0x82 && len - consumed >= 2) { + n = *in++ << 8; + n |= *in++; + if (n <= 0xff) + return 0; /* Not DER. */ + consumed += 2; + } else { + return 0; /* Too large, invalid, or not DER. */ + } + } + *pcont_len = n; + *ppin = in; + return consumed; +} + +/* + * Decodes a single ASN.1 INTEGER value from *ppin, which must be DER encoded, + * updates n with the decoded value, and, if successful, increments *ppin past + * the data that was consumed. + * + * The BIGNUM, n, must have already been allocated by calling 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 INTEGER value with no + * trailing garbage then it is up to the caller to verify that all bytes + * were consumed. + */ +size_t decode_der_integer(BIGNUM *n, const unsigned char **ppin, size_t len) +{ + const unsigned char *in = *ppin; + size_t consumed; + size_t c; + size_t cont_len; + + if (len < 1 || n == NULL || *in++ != ID_INTEGER) + return 0; + consumed = 1; + if ((c = decode_der_length(&cont_len, &in, len - consumed)) == 0) + return 0; + consumed += c; + /* Check for a positive INTEGER with valid content encoding and decode. */ + if (cont_len > len - consumed || cont_len < 1 || (in[0] & 0x80) != 0 + || (cont_len >= 2 && in[0] == 0 && (in[1] & 0x80) == 0) + || BN_bin2bn(in, (int)cont_len, n) == NULL) + return 0; + in += cont_len; + consumed += cont_len; + *ppin = in; + return consumed; +} + +static size_t decode_dsa_sig_content(BIGNUM *r, BIGNUM *s, + const unsigned char **ppin, size_t len) +{ + const unsigned char *in = *ppin; + size_t consumed = 0; + size_t c; + + if ((c = decode_der_integer(r, &in, len - consumed)) == 0) + return 0; + consumed += c; + if ((c = decode_der_integer(s, &in, len - consumed)) == 0) + return 0; + consumed += c; + *ppin = in; + return consumed; +} + +/* + * 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) +{ + const unsigned char *in = *ppin; + size_t consumed; + size_t c; + size_t cont_len; + + if (len < 1 || *in++ != ID_SEQUENCE) + return 0; + consumed = 1; + if ((c = decode_der_length(&cont_len, &in, len - consumed)) == 0) + return 0; + consumed += c; + if (cont_len > len - consumed + || (c = decode_dsa_sig_content(r, s, &in, cont_len)) == 0 + || c != cont_len) + return 0; + consumed += c; + *ppin = in; + return consumed; +} + diff --git a/crypto/build.info b/crypto/build.info index fccca08153..b82978e1c7 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 $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 acf80c651a..1c7e8c86bd 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,62 @@ 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) +{ + unsigned char *buf = NULL; + unsigned char *tmp; + unsigned char **pp = NULL; + size_t len; + size_t encoded_len; + + if (ppout != NULL && *ppout == NULL) { + if ((len = encode_der_dsa_sig(sig->r, sig->s, NULL, SIZE_MAX)) == 0) + return -1; + buf = OPENSSL_malloc(len); + if (buf == NULL) + return -1; + tmp = buf; + pp = &tmp; + } else { + len = SIZE_MAX; + pp = ppout; + } + if ((encoded_len = encode_der_dsa_sig(sig->r, sig->s, pp, len)) == 0) { + OPENSSL_free(buf); + return -1; + } + if (buf != NULL) + *ppout = buf; + 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 35ff9488f3..57de90d367 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,62 @@ 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) +{ + unsigned char *buf = NULL; + unsigned char *tmp; + unsigned char **pp = NULL; + size_t len; + size_t encoded_len; + + if (ppout != NULL && *ppout == NULL) { + if ((len = encode_der_dsa_sig(sig->r, sig->s, NULL, SIZE_MAX)) == 0) + return -1; + buf = OPENSSL_malloc(len); + if (buf == NULL) + return -1; + tmp = buf; + pp = &tmp; + } else { + len = SIZE_MAX; + pp = ppout; + } + if ((encoded_len = encode_der_dsa_sig(sig->r, sig->s, pp, len)) == 0) { + OPENSSL_free(buf); + return -1; + } + if (buf != NULL) + *ppout = buf; + 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 0000000000..7c720a1733 --- /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 + +size_t encode_der_length(size_t cont_len, unsigned char **ppout, size_t len); +size_t encode_der_integer(const BIGNUM *n, unsigned char **ppout, size_t len); +size_t encode_der_dsa_sig(const BIGNUM *r, const BIGNUM *s, + unsigned char **ppout, size_t len); +size_t decode_der_length(size_t *pcont_len, const unsigned char **ppin, + size_t len); +size_t decode_der_integer(BIGNUM *n, const unsigned char **ppin, size_t len); +size_t decode_der_dsa_sig(BIGNUM *r, BIGNUM *s, const unsigned char **ppin, + size_t len); + +#endif diff --git a/test/asn1_dsa_internal_test.c b/test/asn1_dsa_internal_test.c new file mode 100644 index 0000000000..a62f5e4cd4 --- /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/build.info b/test/build.info index f5b802da4d..a61c0ce2be 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} -}] diff --git a/test/recipes/03-test_internal_asn1_dsa.t b/test/recipes/03-test_internal_asn1_dsa.t new file mode 100644 index 0000000000..ecacac73cb --- /dev/null +++ b/test/recipes/03-test_internal_asn1_dsa.t @@ -0,0 +1,16 @@ +#! /usr/bin/env perl +# 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 + +use strict; +use OpenSSL::Test; # get 'plan' +use OpenSSL::Test::Simple; +use OpenSSL::Test::Utils; + +setup("test_internal_asn1_dsa"); + +simple_test("test_internal_asn1_dsa", "asn1_dsa_internal_test"); |