Add a way for the application to get OpenSSL configuration data
[openssl.git] / test / evp_test.c
index eaedab2cb87071d793cb35d60ff8e2a827ca3194..cad580e10cdb7ff59741595e863e613ee5b3539a 100644 (file)
@@ -864,6 +864,9 @@ typedef struct mac_data_st {
     size_t output_len;
     unsigned char *custom;
     size_t custom_len;
+    /* MAC salt (blake2) */
+    unsigned char *salt;
+    size_t salt_len;
     /* Collection of controls */
     STACK_OF(OPENSSL_STRING) *controls;
 } MAC_DATA;
@@ -947,6 +950,7 @@ static void mac_test_cleanup(EVP_TEST *t)
     OPENSSL_free(mdat->key);
     OPENSSL_free(mdat->iv);
     OPENSSL_free(mdat->custom);
+    OPENSSL_free(mdat->salt);
     OPENSSL_free(mdat->input);
     OPENSSL_free(mdat->output);
 }
@@ -962,6 +966,8 @@ static int mac_test_parse(EVP_TEST *t,
         return parse_bin(value, &mdata->iv, &mdata->iv_len);
     if (strcmp(keyword, "Custom") == 0)
         return parse_bin(value, &mdata->custom, &mdata->custom_len);
+    if (strcmp(keyword, "Salt") == 0)
+        return parse_bin(value, &mdata->salt, &mdata->salt_len);
     if (strcmp(keyword, "Algorithm") == 0) {
         mdata->alg = OPENSSL_strdup(value);
         if (!mdata->alg)
@@ -1156,6 +1162,18 @@ static int mac_test_run_mac(EVP_TEST *t)
         }
     }
 
+    if (expected->salt != NULL) {
+        rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_SALT,
+                          expected->salt, expected->salt_len);
+        if (rv == -2) {
+            t->err = "MAC_CTRL_INVALID";
+            goto err;
+        } else if (rv <= 0) {
+            t->err = "MAC_CTRL_ERROR";
+            goto err;
+        }
+    }
+
     if (expected->iv != NULL) {
         rv = EVP_MAC_ctrl(ctx, EVP_MAC_CTRL_SET_IV,
                           expected->iv, expected->iv_len);
@@ -1168,10 +1186,6 @@ static int mac_test_run_mac(EVP_TEST *t)
         }
     }
 
-    if (!EVP_MAC_init(ctx)) {
-        t->err = "MAC_INIT_ERROR";
-        goto err;
-    }
     for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++) {
         char *p, *tmpval;
         char *value = sk_OPENSSL_STRING_value(expected->controls, i);
@@ -1193,6 +1207,10 @@ static int mac_test_run_mac(EVP_TEST *t)
             goto err;
         }
     }
+    if (!EVP_MAC_init(ctx)) {
+        t->err = "MAC_INIT_ERROR";
+        goto err;
+    }
     if (!EVP_MAC_update(ctx, expected->input, expected->input_len)) {
         t->err = "MAC_UPDATE_ERROR";
         goto err;
@@ -1874,13 +1892,14 @@ static const EVP_TEST_METHOD encode_test_method = {
     encode_test_run,
 };
 
+
 /**
 ***  KDF TESTS
 **/
 
 typedef struct kdf_data_st {
     /* Context for this operation */
-    EVP_PKEY_CTX *ctx;
+    EVP_KDF_CTX *ctx;
     /* Expected output */
     unsigned char *output;
     size_t output_len;
@@ -1907,16 +1926,11 @@ static int kdf_test_init(EVP_TEST *t, const char *name)
 
     if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
         return 0;
-    kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+    kdata->ctx = EVP_KDF_CTX_new_id(kdf_nid);
     if (kdata->ctx == NULL) {
         OPENSSL_free(kdata);
         return 0;
     }
-    if (EVP_PKEY_derive_init(kdata->ctx) <= 0) {
-        EVP_PKEY_CTX_free(kdata->ctx);
-        OPENSSL_free(kdata);
-        return 0;
-    }
     t->data = kdata;
     return 1;
 }
@@ -1925,7 +1939,42 @@ static void kdf_test_cleanup(EVP_TEST *t)
 {
     KDF_DATA *kdata = t->data;
     OPENSSL_free(kdata->output);
-    EVP_PKEY_CTX_free(kdata->ctx);
+    EVP_KDF_CTX_free(kdata->ctx);
+}
+
+static int kdf_test_ctrl(EVP_TEST *t, EVP_KDF_CTX *kctx,
+                         const char *value)
+{
+    int rv;
+    char *p, *tmpval;
+
+    if (!TEST_ptr(tmpval = OPENSSL_strdup(value)))
+        return 0;
+    p = strchr(tmpval, ':');
+    if (p != NULL)
+        *p++ = '\0';
+    rv = EVP_KDF_ctrl_str(kctx, tmpval, p);
+    if (rv == -2) {
+        t->err = "KDF_CTRL_INVALID";
+        rv = 1;
+    } else if (p != NULL && rv <= 0) {
+        /* If p has an OID and lookup fails assume disabled algorithm */
+        int nid = OBJ_sn2nid(p);
+
+        if (nid == NID_undef)
+             nid = OBJ_ln2nid(p);
+        if (nid != NID_undef
+                && EVP_get_digestbynid(nid) == NULL
+                && EVP_get_cipherbynid(nid) == NULL) {
+            t->skip = 1;
+            rv = 1;
+        } else {
+            t->err = "KDF_CTRL_ERROR";
+            rv = 1;
+        }
+    }
+    OPENSSL_free(tmpval);
+    return rv > 0;
 }
 
 static int kdf_test_parse(EVP_TEST *t,
@@ -1936,7 +1985,7 @@ static int kdf_test_parse(EVP_TEST *t,
     if (strcmp(keyword, "Output") == 0)
         return parse_bin(value, &kdata->output, &kdata->output_len);
     if (strncmp(keyword, "Ctrl", 4) == 0)
-        return pkey_test_ctrl(t, kdata->ctx, value);
+        return kdf_test_ctrl(t, kdata->ctx, value);
     return 0;
 }
 
@@ -1950,7 +1999,7 @@ static int kdf_test_run(EVP_TEST *t)
         t->err = "INTERNAL_ERROR";
         goto err;
     }
-    if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
+    if (EVP_KDF_derive(expected->ctx, got, got_len) <= 0) {
         t->err = "KDF_DERIVE_ERROR";
         goto err;
     }
@@ -1975,6 +2024,106 @@ static const EVP_TEST_METHOD kdf_test_method = {
 };
 
 
+/**
+***  PKEY KDF TESTS
+**/
+
+typedef struct pkey_kdf_data_st {
+    /* Context for this operation */
+    EVP_PKEY_CTX *ctx;
+    /* Expected output */
+    unsigned char *output;
+    size_t output_len;
+} PKEY_KDF_DATA;
+
+/*
+ * Perform public key operation setup: lookup key, allocated ctx and call
+ * the appropriate initialisation function
+ */
+static int pkey_kdf_test_init(EVP_TEST *t, const char *name)
+{
+    PKEY_KDF_DATA *kdata;
+    int kdf_nid = OBJ_sn2nid(name);
+
+#ifdef OPENSSL_NO_SCRYPT
+    if (strcmp(name, "scrypt") == 0) {
+        t->skip = 1;
+        return 1;
+    }
+#endif
+
+    if (kdf_nid == NID_undef)
+        kdf_nid = OBJ_ln2nid(name);
+
+    if (!TEST_ptr(kdata = OPENSSL_zalloc(sizeof(*kdata))))
+        return 0;
+    kdata->ctx = EVP_PKEY_CTX_new_id(kdf_nid, NULL);
+    if (kdata->ctx == NULL) {
+        OPENSSL_free(kdata);
+        return 0;
+    }
+    if (EVP_PKEY_derive_init(kdata->ctx) <= 0) {
+        EVP_PKEY_CTX_free(kdata->ctx);
+        OPENSSL_free(kdata);
+        return 0;
+    }
+    t->data = kdata;
+    return 1;
+}
+
+static void pkey_kdf_test_cleanup(EVP_TEST *t)
+{
+    PKEY_KDF_DATA *kdata = t->data;
+    OPENSSL_free(kdata->output);
+    EVP_PKEY_CTX_free(kdata->ctx);
+}
+
+static int pkey_kdf_test_parse(EVP_TEST *t,
+                               const char *keyword, const char *value)
+{
+    PKEY_KDF_DATA *kdata = t->data;
+
+    if (strcmp(keyword, "Output") == 0)
+        return parse_bin(value, &kdata->output, &kdata->output_len);
+    if (strncmp(keyword, "Ctrl", 4) == 0)
+        return pkey_test_ctrl(t, kdata->ctx, value);
+    return 0;
+}
+
+static int pkey_kdf_test_run(EVP_TEST *t)
+{
+    PKEY_KDF_DATA *expected = t->data;
+    unsigned char *got = NULL;
+    size_t got_len = expected->output_len;
+
+    if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
+        t->err = "INTERNAL_ERROR";
+        goto err;
+    }
+    if (EVP_PKEY_derive(expected->ctx, got, &got_len) <= 0) {
+        t->err = "KDF_DERIVE_ERROR";
+        goto err;
+    }
+    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
+        t->err = "KDF_MISMATCH";
+        goto err;
+    }
+    t->err = NULL;
+
+ err:
+    OPENSSL_free(got);
+    return 1;
+}
+
+static const EVP_TEST_METHOD pkey_kdf_test_method = {
+    "PKEYKDF",
+    pkey_kdf_test_init,
+    pkey_kdf_test_cleanup,
+    pkey_kdf_test_parse,
+    pkey_kdf_test_run
+};
+
+
 /**
 ***  KEYPAIR TESTS
 **/
@@ -2479,6 +2628,7 @@ static const EVP_TEST_METHOD *evp_test_list[] = {
     &digestverify_test_method,
     &encode_test_method,
     &kdf_test_method,
+    &pkey_kdf_test_method,
     &keypair_test_method,
     &keygen_test_method,
     &mac_test_method,
@@ -2883,14 +3033,14 @@ static int run_file_tests(int i)
     return c == 0;
 }
 
+OPT_TEST_DECLARE_USAGE("file...\n")
+
 int setup_tests(void)
 {
     size_t n = test_get_argument_count();
 
-    if (n == 0) {
-        TEST_error("Usage: %s file...", test_get_program_name());
+    if (n == 0)
         return 0;
-    }
 
     ADD_ALL_TESTS(run_file_tests, n);
     return 1;