Trivial test improvements
[openssl.git] / test / evp_test.c
index b08114e827c2069335ed66fe7ab85e32b3747dd5..2ac69e11da77621f02a634eb6a7e11959c228831 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2017 The OpenSSL Project Authors. All Rights Reserved.
+ * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.
  *
  * Licensed under the OpenSSL license (the "License").  You may not use
  * this file except in compliance with the License.  You can obtain a copy
@@ -73,6 +73,29 @@ static KEY_LIST *public_keys;
 static int find_key(EVP_PKEY **ppk, const char *name, KEY_LIST *lst);
 
 static int parse_bin(const char *value, unsigned char **buf, size_t *buflen);
+static int pkey_test_ctrl(EVP_TEST *t, EVP_PKEY_CTX *pctx,
+                          const char *value);
+
+/*
+ * Compare two memory regions for equality, returning zero if they differ.
+ * However, if there is expected to be an error and the actual error
+ * matches then the memory is expected to be different so handle this
+ * case without producing unnecessary test framework output.
+ */
+static int memory_err_compare(EVP_TEST *t, const char *err,
+                              const void *expected, size_t expected_len,
+                              const void *got, size_t got_len)
+{
+    int r;
+
+    if (t->expected_err != NULL && strcmp(t->expected_err, err) == 0)
+        r = !TEST_mem_ne(expected, expected_len, got, got_len);
+    else
+        r = TEST_mem_eq(expected, expected_len, got, got_len);
+    if (!r)
+        t->err = err;
+    return r;
+}
 
 /*
  * Structure used to hold a list of blocks of memory to test
@@ -397,10 +420,11 @@ static int digest_test_run(EVP_TEST *t)
         t->err = "DIGEST_LENGTH_MISMATCH";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "DIGEST_MISMATCH";
+    if (!memory_err_compare(t, "DIGEST_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
+
     t->err = NULL;
 
  err:
@@ -435,7 +459,7 @@ typedef struct cipher_data_st {
     size_t plaintext_len;
     unsigned char *ciphertext;
     size_t ciphertext_len;
-    /* GCM, CCM only */
+    /* GCM, CCM and OCB only */
     unsigned char *aad;
     size_t aad_len;
     unsigned char *tag;
@@ -463,7 +487,7 @@ static int cipher_test_init(EVP_TEST *t, const char *alg)
     if (m == EVP_CIPH_GCM_MODE
             || m == EVP_CIPH_OCB_MODE
             || m == EVP_CIPH_CCM_MODE)
-        cdat->aead = EVP_CIPHER_mode(cipher);
+        cdat->aead = m;
     else if (EVP_CIPHER_flags(cipher) & EVP_CIPH_FLAG_AEAD_CIPHER)
         cdat->aead = -1;
     else
@@ -688,11 +712,9 @@ static int cipher_test_enc(EVP_TEST *t, int enc,
         t->err = "CIPHERFINAL_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected_out, out_len,
-                     tmp + out_misalign, tmplen + tmpflen)) {
-        t->err = "VALUE_MISMATCH";
+    if (!memory_err_compare(t, "VALUE_MISMATCH", expected_out, out_len,
+                            tmp + out_misalign, tmplen + tmpflen))
         goto err;
-    }
     if (enc && expected->aead) {
         unsigned char rtag[16];
 
@@ -705,11 +727,10 @@ static int cipher_test_enc(EVP_TEST *t, int enc,
             t->err = "TAG_RETRIEVE_ERROR";
             goto err;
         }
-        if (!TEST_mem_eq(expected->tag, expected->tag_len,
-                         rtag, expected->tag_len)) {
-            t->err = "TAG_VALUE_MISMATCH";
+        if (!memory_err_compare(t, "TAG_VALUE_MISMATCH",
+                                expected->tag, expected->tag_len,
+                                rtag, expected->tag_len))
             goto err;
-        }
     }
     t->err = NULL;
     ok = 1;
@@ -824,6 +845,8 @@ typedef struct mac_data_st {
     /* Expected output */
     unsigned char *output;
     size_t output_len;
+    /* Collection of controls */
+    STACK_OF(OPENSSL_STRING) *controls;
 } MAC_DATA;
 
 static int mac_test_init(EVP_TEST *t, const char *alg)
@@ -859,14 +882,22 @@ static int mac_test_init(EVP_TEST *t, const char *alg)
 
     mdat = OPENSSL_zalloc(sizeof(*mdat));
     mdat->type = type;
+    mdat->controls = sk_OPENSSL_STRING_new_null();
     t->data = mdat;
     return 1;
 }
 
+/* Because OPENSSL_free is a macro, it can't be passed as a function pointer */
+static void openssl_free(char *m)
+{
+    OPENSSL_free(m);
+}
+
 static void mac_test_cleanup(EVP_TEST *t)
 {
     MAC_DATA *mdat = t->data;
 
+    sk_OPENSSL_STRING_pop_free(mdat->controls, openssl_free);
     OPENSSL_free(mdat->alg);
     OPENSSL_free(mdat->key);
     OPENSSL_free(mdat->input);
@@ -890,6 +921,9 @@ static int mac_test_parse(EVP_TEST *t,
         return parse_bin(value, &mdata->input, &mdata->input_len);
     if (strcmp(keyword, "Output") == 0)
         return parse_bin(value, &mdata->output, &mdata->output_len);
+    if (strcmp(keyword, "Ctrl") == 0)
+        return sk_OPENSSL_STRING_push(mdata->controls,
+                                      OPENSSL_strdup(value)) != 0;
     return 0;
 }
 
@@ -902,6 +936,7 @@ static int mac_test_run(EVP_TEST *t)
     const EVP_MD *md = NULL;
     unsigned char *got = NULL;
     size_t got_len;
+    int i;
 
 #ifdef OPENSSL_NO_DES
     if (expected->alg != NULL && strstr(expected->alg, "DES") != NULL) {
@@ -911,31 +946,17 @@ static int mac_test_run(EVP_TEST *t)
     }
 #endif
 
-    if (!TEST_ptr(genctx = EVP_PKEY_CTX_new_id(expected->type, NULL))) {
-        t->err = "MAC_PKEY_CTX_ERROR";
-        goto err;
-    }
-
-    if (EVP_PKEY_keygen_init(genctx) <= 0) {
-        t->err = "MAC_KEYGEN_INIT_ERROR";
-        goto err;
-    }
-    if (expected->type == EVP_PKEY_CMAC
-             && EVP_PKEY_CTX_ctrl_str(genctx, "cipher", expected->alg) <= 0) {
-        t->err = "MAC_ALGORITHM_SET_ERROR";
-        goto err;
-    }
-
-    if (EVP_PKEY_CTX_set_mac_key(genctx, expected->key,
-                                 expected->key_len) <= 0) {
-        t->err = "MAC_KEY_SET_ERROR";
+    if (expected->type == EVP_PKEY_CMAC)
+        key = EVP_PKEY_new_CMAC_key(NULL, expected->key, expected->key_len,
+                                    EVP_get_cipherbyname(expected->alg));
+    else
+        key = EVP_PKEY_new_raw_private_key(expected->type, NULL, expected->key,
+                                           expected->key_len);
+    if (key == NULL) {
+        t->err = "MAC_KEY_CREATE_ERROR";
         goto err;
     }
 
-    if (EVP_PKEY_keygen(genctx, &key) <= 0) {
-        t->err = "MAC_KEY_GENERATE_ERROR";
-        goto err;
-    }
     if (expected->type == EVP_PKEY_HMAC) {
         if (!TEST_ptr(md = EVP_get_digestbyname(expected->alg))) {
             t->err = "MAC_ALGORITHM_SET_ERROR";
@@ -950,7 +971,12 @@ static int mac_test_run(EVP_TEST *t)
         t->err = "DIGESTSIGNINIT_ERROR";
         goto err;
     }
-
+    for (i = 0; i < sk_OPENSSL_STRING_num(expected->controls); i++)
+        if (!pkey_test_ctrl(t, pctx,
+                            sk_OPENSSL_STRING_value(expected->controls, i))) {
+            t->err = "EVPPKEYCTXCTRL_ERROR";
+            goto err;
+        }
     if (!EVP_DigestSignUpdate(mctx, expected->input, expected->input_len)) {
         t->err = "DIGESTSIGNUPDATE_ERROR";
         goto err;
@@ -964,8 +990,9 @@ static int mac_test_run(EVP_TEST *t)
         goto err;
     }
     if (!EVP_DigestSignFinal(mctx, got, &got_len)
-            || !TEST_mem_eq(expected->output, expected->output_len,
-                            got, got_len)) {
+            || !memory_err_compare(t, "TEST_MAC_ERR",
+                                   expected->output, expected->output_len,
+                                   got, got_len)) {
         t->err = "TEST_MAC_ERR";
         goto err;
     }
@@ -1122,10 +1149,11 @@ static int pkey_test_run(EVP_TEST *t)
         t->err = "KEYOP_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "KEYOP_MISMATCH";
+    if (!memory_err_compare(t, "KEYOP_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
+
     t->err = NULL;
  err:
     OPENSSL_free(got);
@@ -1228,7 +1256,10 @@ static int pderive_test_run(EVP_TEST *t)
     unsigned char *got = NULL;
     size_t got_len;
 
-    got_len = expected->output_len;
+    if (EVP_PKEY_derive(expected->ctx, NULL, &got_len) <= 0) {
+        t->err = "DERIVE_ERROR";
+        goto err;
+    }
     if (!TEST_ptr(got = OPENSSL_malloc(got_len))) {
         t->err = "DERIVE_ERROR";
         goto err;
@@ -1237,10 +1268,10 @@ static int pderive_test_run(EVP_TEST *t)
         t->err = "DERIVE_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "SHARED_SECRET_MISMATCH";
+    if (!memory_err_compare(t, "SHARED_SECRET_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
 
     t->err = NULL;
  err:
@@ -1455,11 +1486,10 @@ static int pbe_test_run(EVP_TEST *t)
             goto err;
         }
     }
-    if (!TEST_mem_eq(expected->key, expected->key_len,
-                     key, expected->key_len)) {
-        t->err = "KEY_MISMATCH";
+    if (!memory_err_compare(t, "KEY_MISMATCH", expected->key, expected->key_len,
+                            key, expected->key_len))
         goto err;
-    }
+
     t->err = NULL;
 err:
     OPENSSL_free(key);
@@ -1570,11 +1600,10 @@ static int encode_test_run(EVP_TEST *t)
 
         EVP_ENCODE_CTX_free(encode_ctx);
 
-        if (!TEST_mem_eq(expected->output, expected->output_len,
-                         encode_out, output_len)) {
-            t->err = "BAD_ENCODING";
+        if (!memory_err_compare(t, "BAD_ENCODING",
+                                expected->output, expected->output_len,
+                                encode_out, output_len))
             goto err;
-        }
     }
 
     if (!TEST_ptr(decode_out =
@@ -1596,8 +1625,9 @@ static int encode_test_run(EVP_TEST *t)
     output_len += chunk_len;
 
     if (expected->encoding != BASE64_INVALID_ENCODING
-            && !TEST_mem_eq(expected->input, expected->input_len,
-                            decode_out, output_len)) {
+            && !memory_err_compare(t, "BAD_DECODING",
+                                   expected->input, expected->input_len,
+                                   decode_out, output_len)) {
         t->err = "BAD_DECODING";
         goto err;
     }
@@ -1698,10 +1728,11 @@ static int kdf_test_run(EVP_TEST *t)
         t->err = "KDF_DERIVE_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "KDF_MISMATCH";
+    if (!memory_err_compare(t, "KDF_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
+
     t->err = NULL;
 
  err:
@@ -2090,11 +2121,12 @@ static int digestsign_test_run(EVP_TEST *t)
         t->err = "DIGESTSIGNFINAL_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "SIGNATURE_MISMATCH";
+    if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
 
+    t->err = NULL;
  err:
     OPENSSL_free(got);
     return 1;
@@ -2167,11 +2199,12 @@ static int oneshot_digestsign_test_run(EVP_TEST *t)
         t->err = "DIGESTSIGN_ERROR";
         goto err;
     }
-    if (!TEST_mem_eq(expected->output, expected->output_len, got, got_len)) {
-        t->err = "SIGNATURE_MISMATCH";
+    if (!memory_err_compare(t, "SIGNATURE_MISMATCH",
+                            expected->output, expected->output_len,
+                            got, got_len))
         goto err;
-    }
 
+    t->err = NULL;
  err:
     OPENSSL_free(got);
     return 1;
@@ -2389,7 +2422,7 @@ static void free_key_list(KEY_LIST *lst)
 /*
  * Is the key type an unsupported algorithm?
  */
-static int key_unsupported()
+static int key_unsupported(void)
 {
     long err = ERR_peek_error();
 
@@ -2450,20 +2483,65 @@ top:
     if (strcmp(pp->key, "PrivateKey") == 0) {
         pkey = PEM_read_bio_PrivateKey(t->s.key, NULL, 0, NULL);
         if (pkey == NULL && !key_unsupported()) {
+            EVP_PKEY_free(pkey);
             TEST_info("Can't read private key %s", pp->value);
             TEST_openssl_errors();
             return 0;
         }
         klist = &private_keys;
-    }
-    else if (strcmp(pp->key, "PublicKey") == 0) {
+    } else if (strcmp(pp->key, "PublicKey") == 0) {
         pkey = PEM_read_bio_PUBKEY(t->s.key, NULL, 0, NULL);
         if (pkey == NULL && !key_unsupported()) {
+            EVP_PKEY_free(pkey);
             TEST_info("Can't read public key %s", pp->value);
             TEST_openssl_errors();
             return 0;
         }
         klist = &public_keys;
+    } else if (strcmp(pp->key, "PrivateKeyRaw") == 0
+               || strcmp(pp->key, "PublicKeyRaw") == 0 ) {
+        char *strnid = NULL, *keydata = NULL;
+        unsigned char *keybin;
+        size_t keylen;
+        int nid;
+
+        if (strcmp(pp->key, "PrivateKeyRaw") == 0)
+            klist = &private_keys;
+        else
+            klist = &public_keys;
+
+        strnid = strchr(pp->value, ':');
+        if (strnid != NULL) {
+            *strnid++ = '\0';
+            keydata = strchr(strnid, ':');
+            if (keydata != NULL)
+                *keydata++ = '\0';
+        }
+        if (keydata == NULL) {
+            TEST_info("Failed to parse %s value", pp->key);
+            return 0;
+        }
+
+        nid = OBJ_txt2nid(strnid);
+        if (nid == NID_undef) {
+            TEST_info("Uncrecognised algorithm NID");
+            return 0;
+        }
+        if (!parse_bin(keydata, &keybin, &keylen)) {
+            TEST_info("Failed to create binary key");
+            return 0;
+        }
+        if (klist == &private_keys)
+            pkey = EVP_PKEY_new_raw_private_key(nid, NULL, keybin, keylen);
+        else
+            pkey = EVP_PKEY_new_raw_public_key(nid, NULL, keybin, keylen);
+        if (pkey == NULL && !key_unsupported()) {
+            TEST_info("Can't read %s data", pp->key);
+            OPENSSL_free(keybin);
+            TEST_openssl_errors();
+            return 0;
+        }
+        OPENSSL_free(keybin);
     }
 
     /* If we have a key add to list */
@@ -2475,6 +2553,17 @@ top:
         if (!TEST_ptr(key = OPENSSL_malloc(sizeof(*key))))
             return 0;
         key->name = take_value(pp);
+
+        /* Hack to detect SM2 keys */
+        if(pkey != NULL && strstr(key->name, "SM2") != NULL) {
+#ifdef OPENSSL_NO_SM2
+            EVP_PKEY_free(pkey);
+            pkey = NULL;
+#else
+            EVP_PKEY_set_alias_type(pkey, EVP_PKEY_SM2);
+#endif
+        }
+
         key->key = pkey;
         key->next = *klist;
         *klist = key;