Home | History | Annotate | Line # | Download | only in test
      1 /*
      2  * Copyright 2016-2020 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the Apache License 2.0 (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 /* Regression tests for ASN.1 parsing bugs. */
     11 
     12 #include <stdio.h>
     13 #include <string.h>
     14 
     15 #include "testutil.h"
     16 
     17 #include <openssl/asn1.h>
     18 #include <openssl/asn1t.h>
     19 #include <openssl/bio.h>
     20 #include <openssl/err.h>
     21 #include <openssl/x509.h>
     22 #include <openssl/x509v3.h>
     23 #include "internal/nelem.h"
     24 
     25 static const ASN1_ITEM *item_type;
     26 static const char *test_file;
     27 
     28 typedef enum {
     29     ASN1_UNKNOWN,
     30     ASN1_OK,
     31     ASN1_BIO,
     32     ASN1_DECODE,
     33     ASN1_ENCODE,
     34     ASN1_COMPARE
     35 } expected_error_t;
     36 
     37 typedef struct {
     38     const char *str;
     39     expected_error_t code;
     40 } error_enum;
     41 
     42 static expected_error_t expected_error = ASN1_UNKNOWN;
     43 
     44 static int test_bad_asn1(void)
     45 {
     46     BIO *bio = NULL;
     47     ASN1_VALUE *value = NULL;
     48     int ret = 0;
     49     unsigned char buf[2048];
     50     const unsigned char *buf_ptr = buf;
     51     unsigned char *der = NULL;
     52     int derlen;
     53     int len;
     54 
     55     bio = BIO_new_file(test_file, "r");
     56     if (!TEST_ptr(bio))
     57         return 0;
     58 
     59     if (expected_error == ASN1_BIO) {
     60         if (TEST_ptr_null(ASN1_item_d2i_bio(item_type, bio, NULL)))
     61             ret = 1;
     62         goto err;
     63     }
     64 
     65     /*
     66      * Unless we are testing it we don't use ASN1_item_d2i_bio because it
     67      * performs sanity checks on the input and can reject it before the
     68      * decoder is called.
     69      */
     70     len = BIO_read(bio, buf, sizeof(buf));
     71     if (!TEST_int_ge(len, 0))
     72         goto err;
     73 
     74     value = ASN1_item_d2i(NULL, &buf_ptr, len, item_type);
     75     if (value == NULL) {
     76         if (TEST_int_eq(expected_error, ASN1_DECODE))
     77             ret = 1;
     78         goto err;
     79     }
     80 
     81     derlen = ASN1_item_i2d(value, &der, item_type);
     82 
     83     if (der == NULL || derlen < 0) {
     84         if (TEST_int_eq(expected_error, ASN1_ENCODE))
     85             ret = 1;
     86         goto err;
     87     }
     88 
     89     if (derlen != len || memcmp(der, buf, derlen) != 0) {
     90         if (TEST_int_eq(expected_error, ASN1_COMPARE))
     91             ret = 1;
     92         goto err;
     93     }
     94 
     95     if (TEST_int_eq(expected_error, ASN1_OK))
     96         ret = 1;
     97 
     98 err:
     99     /* Don't indicate success for memory allocation errors */
    100     if (ret == 1
    101         && !TEST_false(ERR_GET_REASON(ERR_peek_error()) == ERR_R_MALLOC_FAILURE))
    102         ret = 0;
    103     BIO_free(bio);
    104     OPENSSL_free(der);
    105     ASN1_item_free(value, item_type);
    106     return ret;
    107 }
    108 
    109 OPT_TEST_DECLARE_USAGE("item_name expected_error test_file.der\n")
    110 
    111 /*
    112  * Usage: d2i_test <name> <type> <file>, e.g.
    113  * d2i_test generalname bad_generalname.der
    114  */
    115 int setup_tests(void)
    116 {
    117     const char *test_type_name;
    118     const char *expected_error_string;
    119 
    120     size_t i;
    121 
    122     static error_enum expected_errors[] = {
    123         { "OK", ASN1_OK },
    124         { "BIO", ASN1_BIO },
    125         { "decode", ASN1_DECODE },
    126         { "encode", ASN1_ENCODE },
    127         { "compare", ASN1_COMPARE }
    128     };
    129 
    130     if (!test_skip_common_options()) {
    131         TEST_error("Error parsing test options\n");
    132         return 0;
    133     }
    134 
    135     if (!TEST_ptr(test_type_name = test_get_argument(0))
    136         || !TEST_ptr(expected_error_string = test_get_argument(1))
    137         || !TEST_ptr(test_file = test_get_argument(2)))
    138         return 0;
    139 
    140     item_type = ASN1_ITEM_lookup(test_type_name);
    141 
    142     if (item_type == NULL) {
    143         TEST_error("Unknown type %s", test_type_name);
    144         TEST_note("Supported types:");
    145         for (i = 0;; i++) {
    146             const ASN1_ITEM *it = ASN1_ITEM_get(i);
    147 
    148             if (it == NULL)
    149                 break;
    150             TEST_note("\t%s", it->sname);
    151         }
    152         return 0;
    153     }
    154 
    155     for (i = 0; i < OSSL_NELEM(expected_errors); i++) {
    156         if (strcmp(expected_errors[i].str, expected_error_string) == 0) {
    157             expected_error = expected_errors[i].code;
    158             break;
    159         }
    160     }
    161 
    162     if (expected_error == ASN1_UNKNOWN) {
    163         TEST_error("Unknown expected error %s\n", expected_error_string);
    164         return 0;
    165     }
    166 
    167     ADD_TEST(test_bad_asn1);
    168     return 1;
    169 }
    170