+ unsigned char *tmpdata = alloca(len);
+
+ if(digest->hmac_ctx) {
+ bool ok;
+
+#if OPENSSL_VERSION_MAJOR < 3
+ ok = HMAC_Init_ex(digest->hmac_ctx, NULL, 0, NULL, NULL)
+ && HMAC_Update(digest->hmac_ctx, indata, inlen)
+ && HMAC_Final(digest->hmac_ctx, tmpdata, NULL);
+#else
+ EVP_MAC_CTX *mac_ctx = EVP_MAC_CTX_dup(digest->hmac_ctx);
+
+ ok = mac_ctx
+ && EVP_MAC_update(mac_ctx, indata, inlen)
+ && EVP_MAC_final(mac_ctx, tmpdata, NULL, len);
+
+ EVP_MAC_CTX_free(mac_ctx);
+#endif
+
+ if(!ok) {
+ openssl_err("create HMAC");
+ return false;
+ }
+ } else {
+ if(!digest->md_ctx) {
+ digest->md_ctx = EVP_MD_CTX_create();
+ }
+
+ if(!digest->md_ctx) {
+ abort();
+ }
+
+ if(!EVP_DigestInit(digest->md_ctx, digest->digest)
+ || !EVP_DigestUpdate(digest->md_ctx, indata, inlen)
+ || !EVP_DigestFinal(digest->md_ctx, tmpdata, NULL)) {
+ openssl_err("create digest");
+ return false;
+ }
+ }
+
+ memcpy(outdata, tmpdata, digest->maclength);
+ return true;
+}
+
+bool digest_verify(digest_t *digest, const void *indata, size_t inlen, const void *cmpdata) {
+ size_t len = digest->maclength;
+ unsigned char *outdata = alloca(len);