+/*
+ * If we have OMAC1/CMAC test vector,
+ * use CMAC provider to test it.
+ */
+static int do_cmac_prov(int iter, const char *plaintext,
+ const struct hash_testvec *t)
+{
+#if OPENSSL_VERSION_MAJOR >= 3
+ char *ciphername = NULL;
+ /*
+ * CMAC needs CBC.
+ * Convert 'mac' digest to the underlying CBC cipher.
+ */
+ switch (OBJ_sn2nid(t->algname)) {
+ case NID_grasshopper_mac:
+ ciphername = "kuznyechik-cbc";
+ break;
+ case NID_magma_mac:
+ ciphername = "magma-cbc";
+ break;
+ default:
+ return 0;
+ }
+
+ if (!iter)
+ printf("[CMAC(%s)] ", ciphername);
+
+ size_t len;
+ unsigned char out[EVP_MAX_MD_SIZE];
+ size_t outsize = t->outsize;
+ if (t->truncate)
+ outsize = t->truncate;
+
+ EVP_MAC *cmac;
+ T(cmac = EVP_MAC_fetch(NULL, "CMAC", NULL));
+ EVP_MAC_CTX *ctx;
+ T(ctx = EVP_MAC_CTX_new(cmac));
+ OSSL_PARAM params[] = {
+ OSSL_PARAM_utf8_string(OSSL_MAC_PARAM_CIPHER, ciphername, 0),
+ OSSL_PARAM_END
+ };
+ T(EVP_MAC_CTX_set_params(ctx, params));
+ T(EVP_MAC_init(ctx, (const unsigned char *)t->key, t->key_size, params));
+ T(EVP_MAC_update(ctx, (unsigned char *)plaintext, t->psize));
+ T(EVP_MAC_final(ctx, out, &len, sizeof(out)));
+ EVP_MAC_CTX_free(ctx);
+ EVP_MAC_free(cmac);
+
+ /* CMAC provider will not respect outsize, and will output full block.
+ * So, just compare until what we need. */
+ T(outsize <= len);
+ if (memcmp(out, t->digest, outsize) != 0) {
+ printf(cRED "cmac mismatch (iter %d)" cNORM "\n", iter);
+ hexdump(t->digest, outsize);
+ hexdump(out, len);
+ return 1;
+ }
+#endif
+ return 0;
+}
+
+static int do_mac(int iter, EVP_MAC *mac, const char *plaintext,
+ const struct hash_testvec *t)
+{
+ if (!iter)
+ printf("[MAC %d] ", t->outsize);
+
+ size_t acpkm = (size_t)t->acpkm;
+ size_t acpkm_t = (size_t)t->acpkm_t;
+ OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END, OSSL_PARAM_END };
+ OSSL_PARAM *p = params;
+ if (acpkm) {
+ *p++ = OSSL_PARAM_construct_size_t("key-mesh", &acpkm);
+ if (acpkm_t)
+ *p++ = OSSL_PARAM_construct_size_t("cipher-key-mesh", &acpkm_t);
+ }
+
+ EVP_MAC_CTX *ctx;
+ T(ctx = EVP_MAC_CTX_new(mac));
+ if (t->outsize)
+ T(EVP_MAC_CTX_get_mac_size(ctx) == t->outsize);
+ size_t outsize;
+ if (t->truncate)
+ outsize = t->truncate;
+ else
+ outsize = EVP_MAC_CTX_get_mac_size(ctx);
+
+ T(EVP_MAC_init(ctx, (const unsigned char *)t->key, t->key_size, NULL));
+ T(EVP_MAC_CTX_set_params(ctx, params));
+ T(EVP_MAC_update(ctx, (unsigned char *)plaintext, t->psize));
+
+ size_t len = 0;
+ unsigned char out[256];
+ if (t->truncate) {
+ T(outsize <= sizeof(out));
+ T(EVP_MAC_finalXOF(ctx, out, outsize));
+ len = outsize;
+ } else {
+ T(EVP_MAC_CTX_get_mac_size(ctx) == outsize);
+ T(EVP_MAC_final(ctx, out, &len, sizeof(out)));
+ }
+
+ EVP_MAC_CTX_free(ctx);
+ T(len == outsize);
+ if (memcmp(out, t->digest, outsize) != 0) {
+ printf(cRED "mac mismatch (iter %d, outsize %d)" cNORM "\n",
+ iter, (int)outsize);
+ hexdump(t->digest, outsize);
+ hexdump(out, outsize);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int do_digest(int iter, const EVP_MD *type, const char *plaintext,
+ const struct hash_testvec *t)