Added macro that indicates presence of the time callback feature. Also added C++...
[BearSSL] / test / test_x509.c
index 344f8d9..c007068 100644 (file)
 #include <string.h>
 #include <stdint.h>
 
 #include <string.h>
 #include <stdint.h>
 
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <unistd.h>
+#endif
+
 #include "bearssl.h"
 
 #define STR(x)    STR_(x)
 #include "bearssl.h"
 
 #define STR(x)    STR_(x)
@@ -1432,6 +1438,21 @@ eqpkey(const br_x509_pkey *pk1, const br_x509_pkey *pk2)
 static size_t max_dp_usage;
 static size_t max_rp_usage;
 
 static size_t max_dp_usage;
 static size_t max_rp_usage;
 
+static int
+check_time(void *ctx, uint32_t nbd, uint32_t nbs, uint32_t nad, uint32_t nas)
+{
+       test_case *tc;
+
+       tc = ctx;
+       if (tc->days < nbd || (tc->days == nbd && tc->seconds < nbs)) {
+               return -1;
+       }
+       if (tc->days > nad || (tc->days == nad && tc->seconds > nas)) {
+               return 1;
+       }
+       return 0;
+}
+
 static void
 run_test_case(test_case *tc)
 {
 static void
 run_test_case(test_case *tc)
 {
@@ -1446,6 +1467,7 @@ run_test_case(test_case *tc)
        const br_x509_pkey *ee_pkey;
        unsigned usages;
        unsigned status;
        const br_x509_pkey *ee_pkey;
        unsigned usages;
        unsigned status;
+       int j;
 
        printf("%s: ", tc->name);
        fflush(stdout);
 
        printf("%s: ", tc->name);
        fflush(stdout);
@@ -1514,110 +1536,130 @@ run_test_case(test_case *tc)
        }
 
        /*
        }
 
        /*
-        * Initialise the engine.
+        * We do the test twice, to exercise distinct API functions.
         */
         */
-       br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
-       for (u = 0; hash_impls[u].id; u ++) {
-               int id;
+       for (j = 0; j < 2; j ++) {
+               /*
+                * Initialise the engine.
+                */
+               br_x509_minimal_init(&ctx, dnhash, anchors, num_anchors);
+               for (u = 0; hash_impls[u].id; u ++) {
+                       int id;
+
+                       id = hash_impls[u].id;
+                       if ((tc->hashes & ((unsigned)1 << id)) != 0) {
+                               br_x509_minimal_set_hash(&ctx,
+                                       id, hash_impls[u].impl);
+                       }
+               }
+               br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
+               br_x509_minimal_set_ecdsa(&ctx,
+                       br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
 
 
-               id = hash_impls[u].id;
-               if ((tc->hashes & ((unsigned)1 << id)) != 0) {
-                       br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
+               /*
+                * Set the validation date.
+                */
+               if (j == 0) {
+                       br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
+               } else {
+                       br_x509_minimal_set_time_callback(&ctx,
+                               tc, &check_time);
                }
                }
-       }
-       br_x509_minimal_set_rsa(&ctx, br_rsa_i31_pkcs1_vrfy);
-       br_x509_minimal_set_ecdsa(&ctx,
-               &br_ec_prime_i31, br_ecdsa_i31_vrfy_asn1);
 
 
-       /*
-        * Set the validation date.
-        */
-       br_x509_minimal_set_time(&ctx, tc->days, tc->seconds);
+               /*
+                * Put "canaries" to detect actual stack usage.
+                */
+               for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t);
+                       u ++)
+               {
+                       ctx.dp_stack[u] = 0xA7C083FE;
+               }
+               for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t);
+                       u ++)
+               {
+                       ctx.rp_stack[u] = 0xA7C083FE;
+               }
 
 
-       /*
-        * Put "canaries" to detect actual stack usage.
-        */
-       for (u = 0; u < (sizeof ctx.dp_stack) / sizeof(uint32_t); u ++) {
-               ctx.dp_stack[u] = 0xA7C083FE;
-       }
-       for (u = 0; u < (sizeof ctx.rp_stack) / sizeof(uint32_t); u ++) {
-               ctx.rp_stack[u] = 0xA7C083FE;
-       }
+               /*
+                * Run the engine. We inject certificates by chunks of 100
+                * bytes in order to exercise the coroutine API.
+                */
+               ctx.vtable->start_chain(&ctx.vtable, tc->servername);
+               for (u = 0; u < num_certs; u ++) {
+                       size_t v;
 
 
-       /*
-        * Run the engine. We inject certificates by chunks of 100 bytes
-        * in order to exercise the coroutine API.
-        */
-       ctx.vtable->start_chain(&ctx.vtable, tc->servername);
-       for (u = 0; u < num_certs; u ++) {
-               size_t v;
+                       ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
+                       v = 0;
+                       while (v < certs[u].len) {
+                               size_t w;
 
 
-               ctx.vtable->start_cert(&ctx.vtable, certs[u].len);
-               v = 0;
-               while (v < certs[u].len) {
-                       size_t w;
+                               w = certs[u].len - v;
+                               if (w > 100) {
+                                       w = 100;
+                               }
+                               ctx.vtable->append(&ctx.vtable,
+                                       certs[u].data + v, w);
+                               v += w;
+                       }
+                       ctx.vtable->end_cert(&ctx.vtable);
+               }
+               status = ctx.vtable->end_chain(&ctx.vtable);
+               ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
 
 
-                       w = certs[u].len - v;
-                       if (w > 100) {
-                               w = 100;
+               /*
+                * Check key type and usage.
+                */
+               if (ee_pkey != NULL) {
+                       unsigned ktu;
+
+                       ktu = ee_pkey->key_type | usages;
+                       if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
+                               fprintf(stderr, "wrong key type + usage"
+                                       " (expected 0x%02X, got 0x%02X)\n",
+                                       tc->key_type_usage, ktu);
+                               exit(EXIT_FAILURE);
                        }
                        }
-                       ctx.vtable->append(&ctx.vtable, certs[u].data + v, w);
-                       v += w;
                }
                }
-               ctx.vtable->end_cert(&ctx.vtable);
-       }
-       status = ctx.vtable->end_chain(&ctx.vtable);
-       ee_pkey = ctx.vtable->get_pkey(&ctx.vtable, &usages);
 
 
-       /*
-        * Check key type and usage.
-        */
-       if (ee_pkey != NULL) {
-               unsigned ktu;
-
-               ktu = ee_pkey->key_type | usages;
-               if (tc->key_type_usage != (ktu & tc->key_type_usage)) {
-                       fprintf(stderr, "wrong key type + usage"
-                               " (expected 0x%02X, got 0x%02X)\n",
-                               tc->key_type_usage, ktu);
+               /*
+                * Check results. Note that we may still get a public key if
+                * the path is "not trusted" (but otherwise fine).
+                */
+               if (status != tc->status) {
+                       fprintf(stderr, "wrong status (got %d, expected %d)\n",
+                               status, tc->status);
+                       exit(EXIT_FAILURE);
+               }
+               if (status == BR_ERR_X509_NOT_TRUSTED) {
+                       ee_pkey = NULL;
+               }
+               if (!eqpkey(ee_pkey, ee_pkey_ref)) {
+                       fprintf(stderr, "wrong EE public key\n");
                        exit(EXIT_FAILURE);
                }
                        exit(EXIT_FAILURE);
                }
-       }
-
-       /*
-        * Check results. Note that we may still get a public key if
-        * the path is "not trusted" (but otherwise fine).
-        */
-       if (status != tc->status) {
-               fprintf(stderr, "wrong status (got %d, expected %d)\n",
-                       status, tc->status);
-               exit(EXIT_FAILURE);
-       }
-       if (status == BR_ERR_X509_NOT_TRUSTED) {
-               ee_pkey = NULL;
-       }
-       if (!eqpkey(ee_pkey, ee_pkey_ref)) {
-               fprintf(stderr, "wrong EE public key\n");
-               exit(EXIT_FAILURE);
-       }
 
 
-       /*
-        * Check stack usage.
-        */
-       for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t); u > 0; u --) {
-               if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
-                       if (max_dp_usage < u) {
-                               max_dp_usage = u;
+               /*
+                * Check stack usage.
+                */
+               for (u = (sizeof ctx.dp_stack) / sizeof(uint32_t);
+                       u > 0; u --)
+               {
+                       if (ctx.dp_stack[u - 1] != 0xA7C083FE) {
+                               if (max_dp_usage < u) {
+                                       max_dp_usage = u;
+                               }
+                               break;
                        }
                        }
-                       break;
                }
                }
-       }
-       for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t); u > 0; u --) {
-               if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
-                       if (max_rp_usage < u) {
-                               max_rp_usage = u;
+               for (u = (sizeof ctx.rp_stack) / sizeof(uint32_t);
+                       u > 0; u --)
+               {
+                       if (ctx.rp_stack[u - 1] != 0xA7C083FE) {
+                               if (max_rp_usage < u) {
+                                       max_rp_usage = u;
+                               }
+                               break;
                        }
                        }
-                       break;
                }
        }
 
                }
        }
 
@@ -1813,9 +1855,9 @@ test_name_extraction(void)
                id = hash_impls[u].id;
                br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
        }
                id = hash_impls[u].id;
                br_x509_minimal_set_hash(&ctx, id, hash_impls[u].impl);
        }
-       br_x509_minimal_set_rsa(&ctx, br_rsa_i31_pkcs1_vrfy);
+       br_x509_minimal_set_rsa(&ctx, br_rsa_pkcs1_vrfy_get_default());
        br_x509_minimal_set_ecdsa(&ctx,
        br_x509_minimal_set_ecdsa(&ctx,
-               &br_ec_prime_i31, br_ecdsa_i31_vrfy_asn1);
+               br_ec_get_default(), br_ecdsa_vrfy_asn1_get_default());
        string_to_time(DEFAULT_TIME, &days, &seconds);
        br_x509_minimal_set_time(&ctx, days, seconds);
 
        string_to_time(DEFAULT_TIME, &days, &seconds);
        br_x509_minimal_set_time(&ctx, days, seconds);
 
@@ -1976,10 +2018,59 @@ test_name_extraction(void)
 }
 
 int
 }
 
 int
-main(void)
+main(int argc, const char *argv[])
 {
        size_t u;
 
 {
        size_t u;
 
+#ifdef SRCDIRNAME
+       /*
+        * We want to change the current directory to that of the
+        * executable, so that test files are reliably located. We
+        * do that only if SRCDIRNAME is defined (old Makefile would
+        * not do that).
+        */
+       if (argc >= 1) {
+               const char *arg, *c;
+
+               arg = argv[0];
+               for (c = arg + strlen(arg);; c --) {
+                       int sep, r;
+
+#ifdef _WIN32
+                       sep = (*c == '/') || (*c == '\\');
+#else
+                       sep = (*c == '/');
+#endif
+                       if (sep) {
+                               size_t len;
+                               char *dn;
+
+                               len = 1 + (c - arg);
+                               dn = xmalloc(len + 1);
+                               memcpy(dn, arg, len);
+                               dn[len] = 0;
+#ifdef _WIN32
+                               r = _chdir(dn);
+#else
+                               r = chdir(dn);
+#endif
+                               if (r != 0) {
+                                       fprintf(stderr, "warning: could not"
+                                               " set directory to '%s'\n", dn);
+                               }
+                               xfree(dn);
+                               break;
+                       }
+                       if (c == arg) {
+                               break;
+                       }
+               }
+       }
+#else
+       (void)argc;
+       (void)argv;
+#endif
+
        process_conf_file(CONFFILE);
 
        max_dp_usage = 0;
        process_conf_file(CONFFILE);
 
        max_dp_usage = 0;