Extensions to d2i_test.
authorDr. Stephen Henson <steve@openssl.org>
Wed, 20 Apr 2016 20:37:57 +0000 (21:37 +0100)
committerDr. Stephen Henson <steve@openssl.org>
Fri, 22 Apr 2016 14:00:36 +0000 (15:00 +0100)
Using ASN1_ITEM tables in d2i_test: this then uses consistent names and
makes it easier to extend.

Add bio, reencode and compare tests.

Reviewed-by: Viktor Dukhovni <viktor@openssl.org>
test/d2i_test.c
test/recipes/25-test_d2i.t

index 6ffdf5507a4de136e129914730d516bfa6c9c14a..49882a3828599ed4e6506f860d656e9c5a03d937 100644 (file)
 #include "testutil.h"
 
 #include <openssl/asn1.h>
+#include <openssl/asn1t.h>
 #include <openssl/bio.h>
 #include <openssl/err.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
+#include "e_os.h"
 
 static const ASN1_ITEM *item_type;
 static const char *test_file;
 
+typedef enum {
+    ASN1_UNKNOWN,
+    ASN1_OK,
+    ASN1_BIO,
+    ASN1_DECODE,
+    ASN1_ENCODE,
+    ASN1_COMPARE
+} expected_error_t;
+
+typedef struct {
+    const char *str;
+    expected_error_t code;
+} error_enum;
+
+static expected_error_t expected_error = ASN1_UNKNOWN;
+
 typedef struct d2i_test_fixture {
     const char *test_case_name;
 } D2I_TEST_FIXTURE;
 
-
 static D2I_TEST_FIXTURE set_up(const char *const test_case_name)
 {
     D2I_TEST_FIXTURE fixture;
@@ -43,27 +60,56 @@ static int execute_test(D2I_TEST_FIXTURE fixture)
     int ret = 0;
     unsigned char buf[2048];
     const unsigned char *buf_ptr = buf;
+    unsigned char *der = NULL;
+    int derlen;
     int len;
 
     if ((bio = BIO_new_file(test_file, "r")) == NULL)
         return 0;
 
+    if (expected_error == ASN1_BIO) {
+        value = ASN1_item_d2i_bio(item_type, bio, NULL);
+        if (value == NULL)
+            ret = 1;
+        goto err;
+    }
+
     /*
-     * We don't use ASN1_item_d2i_bio because it, apparently,
-     * errors too early for some inputs.
+     * Unless we are testing it we don't use ASN1_item_d2i_bio because it
+     * performs sanity checks on the input and can reject it before the
+     * decoder is called.
      */
     len = BIO_read(bio, buf, sizeof buf);
     if (len < 0)
         goto err;
 
     value = ASN1_item_d2i(NULL, &buf_ptr, len, item_type);
-    if (value != NULL)
+    if (value == NULL) {
+        if (expected_error == ASN1_DECODE)
+            ret = 1;
         goto err;
+    }
+
+    derlen = ASN1_item_i2d(value, &der, item_type);
 
-    ret = 1;
+    if (der == NULL || derlen < 0) {
+        if (expected_error == ASN1_ENCODE)
+            ret = 1;
+        goto err;
+    }
+
+    if (derlen != len || memcmp(der, buf, derlen) != 0) {
+        if (expected_error == ASN1_COMPARE)
+            ret = 1;
+        goto err;
+    }
+
+    if (expected_error == ASN1_OK)
+        ret = 1;
 
  err:
     BIO_free(bio);
+    OPENSSL_free(der);
     ASN1_item_free(value, item_type);
     return ret;
 }
@@ -93,19 +139,59 @@ int main(int argc, char **argv)
 {
     int result = 0;
     const char *test_type_name;
-
-    if (argc != 3)
+    const char *expected_error_string;
+
+    size_t i;
+    static ASN1_ITEM_EXP *items[] = {
+        ASN1_ITEM_ref(ASN1_ANY),
+        ASN1_ITEM_ref(X509),
+        ASN1_ITEM_ref(GENERAL_NAME)
+    };
+
+    static error_enum expected_errors[] = {
+        {"OK", ASN1_OK},
+        {"BIO", ASN1_BIO},
+        {"decode", ASN1_DECODE},
+        {"encode", ASN1_ENCODE},
+        {"compare", ASN1_COMPARE}
+    };
+
+    if (argc != 4) {
+        fprintf(stderr,
+                "Usage: d2i_test item_name expected_error file.der\n");
         return 1;
+    }
 
     test_type_name = argv[1];
-    test_file = argv[2];
-
-    if (strcmp(test_type_name, "generalname") == 0) {
-        item_type = ASN1_ITEM_rptr(GENERAL_NAME);
-    } else if (strcmp(test_type_name, "x509") == 0) {
-        item_type = ASN1_ITEM_rptr(X509);
-    } else {
-        fprintf(stderr, "Bad type %s\n", test_type_name);
+    expected_error_string = argv[2];
+    test_file = argv[3];
+
+    for (i = 0; i < OSSL_NELEM(items); i++) {
+        const ASN1_ITEM *it = ASN1_ITEM_ptr(items[i]);
+        if (strcmp(test_type_name, it->sname) == 0) {
+            item_type = it;
+            break;
+        }
+    }
+    if (item_type == NULL) {
+        fprintf(stderr, "Unknown type %s\n", test_type_name);
+        fprintf(stderr, "Supported types:\n");
+        for (i = 0; i < OSSL_NELEM(items); i++) {
+            const ASN1_ITEM *it = ASN1_ITEM_ptr(items[i]);
+            fprintf(stderr, "\t%s\n", it->sname);
+        }
+        return 1;
+    }
+
+    for (i = 0; i < OSSL_NELEM(expected_errors); i++) {
+        if (strcmp(expected_errors[i].str, expected_error_string) == 0) {
+            expected_error = expected_errors[i].code;
+            break;
+        }
+    }
+
+    if (expected_error == ASN1_UNKNOWN) {
+        fprintf(stderr, "Unknown expected error %s\n", expected_error_string);
         return 1;
     }
 
index b7563a24245b6eeac1200b4eb5b3898c976d6fef..111fa5b100e4f45e3af0c909d8a9ed847a954573 100644 (file)
@@ -17,10 +17,10 @@ setup("test_d2i");
 
 plan tests => 2;
 
-ok(run(test(["d2i_test", "x509",
+ok(run(test(["d2i_test", "X509", "decode",
              srctop_file('test','d2i-tests','bad_cert.der')])),
    "Running d2i_test bad_cert.der");
 
-ok(run(test(["d2i_test", "generalname",
+ok(run(test(["d2i_test", "GENERAL_NAME", "decode",
              srctop_file('test','d2i-tests','bad_generalname.der')])),
    "Running d2i_test bad_generalname.der");