summaryrefslogtreecommitdiff
path: root/lib/libcrypto/hmac
diff options
context:
space:
mode:
authorTheo Buehler <tb@cvs.openbsd.org>2022-11-18 15:01:05 +0000
committerTheo Buehler <tb@cvs.openbsd.org>2022-11-18 15:01:05 +0000
commitbbf3b181d70106f16d567654ad65dc6bb0b26cd5 (patch)
tree8f9f400f857c72a7c7a9540015284721b769c615 /lib/libcrypto/hmac
parent9f4e08be828995f9db5889a542cba4c9ccc39d7a (diff)
Wire up HMAC to raw private key methods
Obviously, the brilliant API design kitchen decided that an interface carrying public and private key in its name (so that every sane person thinks of asymmetric cryptography), is also perfectly suitable for MACs. Wire up HMAC since Ruby's OpenSSL gem uses these bindings if the build system detects that EVP_PKEY_new_raw_public_key() is available in evp.h. While there, also add the missing pub_cmp() ameth, which obviously treats two things as equal by returning 1. Reported by jeremy and anton, fixes regress/lib/libssl/openssl-ruby tests ok jsing
Diffstat (limited to 'lib/libcrypto/hmac')
-rw-r--r--lib/libcrypto/hmac/hm_ameth.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/lib/libcrypto/hmac/hm_ameth.c b/lib/libcrypto/hmac/hm_ameth.c
index 86e42bdfabc..858110a5613 100644
--- a/lib/libcrypto/hmac/hm_ameth.c
+++ b/lib/libcrypto/hmac/hm_ameth.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hm_ameth.c,v 1.13 2022/11/18 14:45:10 tb Exp $ */
+/* $OpenBSD: hm_ameth.c,v 1.14 2022/11/18 15:01:04 tb Exp $ */
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
* project 2007.
*/
@@ -56,6 +56,7 @@
*
*/
+#include <limits.h>
#include <stdio.h>
#include <string.h>
@@ -74,6 +75,13 @@
*/
static int
+hmac_pkey_public_cmp(const EVP_PKEY *a, const EVP_PKEY *b)
+{
+ /* The ameth pub_cmp must return 1 on match, 0 on mismatch. */
+ return ASN1_OCTET_STRING_cmp(a->pkey.ptr, b->pkey.ptr) == 0;
+}
+
+static int
hmac_size(const EVP_PKEY *pkey)
{
return EVP_MAX_MD_SIZE;
@@ -103,6 +111,51 @@ hmac_pkey_ctrl(EVP_PKEY *pkey, int op, long arg1, void *arg2)
}
}
+static int
+hmac_set_priv_key(EVP_PKEY *pkey, const unsigned char *priv, size_t len)
+{
+ ASN1_OCTET_STRING *os = NULL;
+
+ if (pkey->pkey.ptr != NULL)
+ goto err;
+
+ if (len > INT_MAX)
+ goto err;
+
+ if ((os = ASN1_OCTET_STRING_new()) == NULL)
+ goto err;
+
+ if (!ASN1_OCTET_STRING_set(os, priv, len))
+ goto err;
+
+ pkey->pkey.ptr = os;
+
+ return 1;
+
+ err:
+ ASN1_OCTET_STRING_free(os);
+
+ return 0;
+}
+
+static int
+hmac_get_priv_key(const EVP_PKEY *pkey, unsigned char *priv, size_t *len)
+{
+ ASN1_OCTET_STRING *os = pkey->pkey.ptr;
+ CBS cbs;
+
+ if (priv == NULL) {
+ *len = os->length;
+ return 1;
+ }
+
+ if (os == NULL)
+ return 0;
+
+ CBS_init(&cbs, os->data, os->length);
+ return CBS_write_bytes(&cbs, priv, *len, len);
+}
+
#ifdef HMAC_TEST_PRIVATE_KEY_FORMAT
/* A bogus private key format for test purposes. This is simply the
* HMAC key with "HMAC PRIVATE KEY" in the headers. When enabled the
@@ -161,12 +214,18 @@ const EVP_PKEY_ASN1_METHOD hmac_asn1_meth = {
.pem_str = "HMAC",
.info = "OpenSSL HMAC method",
+ .pub_cmp = hmac_pkey_public_cmp,
+
.pkey_size = hmac_size,
.pkey_free = hmac_key_free,
.pkey_ctrl = hmac_pkey_ctrl,
+
#ifdef HMAC_TEST_PRIVATE_KEY_FORMAT
.old_priv_decode = old_hmac_decode,
- .old_priv_encode = old_hmac_encode
+ .old_priv_encode = old_hmac_encode,
#endif
+
+ .set_priv_key = hmac_set_priv_key,
+ .get_priv_key = hmac_get_priv_key,
};