#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/err.h>
+#include <openssl/provider.h>
#include <openssl/x509v3.h>
#include <openssl/pkcs12.h>
#include <openssl/kdf.h>
static int parse_bin(const char *value, unsigned char **buf, size_t *buflen);
+static OSSL_PROVIDER *defltprov = NULL;
+static OSSL_PROVIDER *legacyprov = NULL;
+
/*
* Compare two memory regions for equality, returning zero if they differ.
* However, if there is expected to be an error and the actual error
return evp_test_buffer_set_count(value, mdata->input);
if (strcmp(keyword, "Ncopy") == 0)
return evp_test_buffer_ncopy(value, mdata->input);
+ if (strcmp(keyword, "Legacy") == 0) {
+ if (legacyprov == NULL)
+ t->skip = 1;
+ return 1;
+ }
return 0;
}
size_t aad_len[AAD_NUM];
unsigned char *tag;
size_t tag_len;
+ int tag_late;
} CIPHER_DATA;
static int cipher_test_init(EVP_TEST *t, const char *alg)
}
if (strcmp(keyword, "Tag") == 0)
return parse_bin(value, &cdat->tag, &cdat->tag_len);
+ if (strcmp(keyword, "SetTagLate") == 0) {
+ if (strcmp(value, "TRUE") == 0)
+ cdat->tag_late = 1;
+ else if (strcmp(value, "FALSE") == 0)
+ cdat->tag_late = 0;
+ else
+ return 0;
+ return 1;
+ }
}
if (strcmp(keyword, "Operation") == 0) {
* If encrypting or OCB just set tag length initially, otherwise
* set tag length and value.
*/
- if (enc || expected->aead == EVP_CIPH_OCB_MODE) {
+ if (enc || expected->aead == EVP_CIPH_OCB_MODE || expected->tag_late) {
t->err = "TAG_LENGTH_SET_ERROR";
tag = NULL;
} else {
goto err;
}
- if (!enc && expected->aead == EVP_CIPH_OCB_MODE) {
- if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
- expected->tag_len, expected->tag)) {
- t->err = "TAG_SET_ERROR";
- goto err;
- }
- }
-
if (expected->aead == EVP_CIPH_CCM_MODE) {
if (!EVP_CipherUpdate(ctx, NULL, &tmplen, NULL, out_len)) {
t->err = "CCM_PLAINTEXT_LENGTH_SET_ERROR";
}
}
}
+
+ if (!enc && (expected->aead == EVP_CIPH_OCB_MODE || expected->tag_late)) {
+ if (!EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG,
+ expected->tag_len, expected->tag)) {
+ t->err = "TAG_SET_ERROR";
+ goto err;
+ }
+ }
+
EVP_CIPHER_CTX_set_padding(ctx, 0);
t->err = "CIPHERUPDATE_ERROR";
tmplen = 0;
PKEY_DATA *expected = t->data;
unsigned char *got = NULL;
size_t got_len;
+ EVP_PKEY_CTX *copy = NULL;
if (expected->keyop(expected->ctx, NULL, &got_len,
expected->input, expected->input_len) <= 0
goto err;
t->err = NULL;
+ OPENSSL_free(got);
+ got = NULL;
+
+ /* Repeat the test on a copy. */
+ if (!TEST_ptr(copy = EVP_PKEY_CTX_dup(expected->ctx))) {
+ t->err = "INTERNAL_ERROR";
+ goto err;
+ }
+ if (expected->keyop(copy, NULL, &got_len, expected->input,
+ expected->input_len) <= 0
+ || !TEST_ptr(got = OPENSSL_malloc(got_len))) {
+ t->err = "KEYOP_LENGTH_ERROR";
+ goto err;
+ }
+ if (expected->keyop(copy, got, &got_len, expected->input,
+ expected->input_len) <= 0) {
+ t->err = "KEYOP_ERROR";
+ goto err;
+ }
+ if (!memory_err_compare(t, "KEYOP_MISMATCH",
+ expected->output, expected->output_len,
+ got, got_len))
+ goto err;
+
err:
OPENSSL_free(got);
+ EVP_PKEY_CTX_free(copy);
return 1;
}
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;
static int kdf_test_init(EVP_TEST *t, const char *name)
{
KDF_DATA *kdata;
- int kdf_nid = OBJ_sn2nid(name);
+ const EVP_KDF *kdf;
#ifdef OPENSSL_NO_SCRYPT
if (strcmp(name, "scrypt") == 0) {
}
#endif
- if (kdf_nid == NID_undef)
- kdf_nid = OBJ_ln2nid(name);
+ kdf = EVP_get_kdfbyname(name);
+ if (kdf == NULL)
+ return 0;
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(kdf);
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;
}
{
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,
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;
}
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;
}
};
+/**
+*** 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
**/
&digestverify_test_method,
&encode_test_method,
&kdf_test_method,
+ &pkey_kdf_test_method,
&keypair_test_method,
&keygen_test_method,
&mac_test_method,
while (!BIO_eof(t->s.fp)) {
c = parse(t);
- if (t->skip)
+ if (t->skip) {
+ t->s.numskip++;
continue;
+ }
if (c == 0 || !run_test(t)) {
t->s.errors++;
break;
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;
- }
+
+ defltprov = OSSL_PROVIDER_load(NULL, "default");
+ if (!TEST_ptr(defltprov))
+ return 0;
+#ifndef NO_LEGACY_MODULE
+ legacyprov = OSSL_PROVIDER_load(NULL, "legacy");
+ if (!TEST_ptr(legacyprov))
+ return 0;
+#endif /* NO_LEGACY_MODULE */
ADD_ALL_TESTS(run_file_tests, n);
return 1;
}
+
+void cleanup_tests(void)
+{
+ OSSL_PROVIDER_unload(legacyprov);
+ OSSL_PROVIDER_unload(defltprov);
+}