diff options
author | Theo Buehler <tb@cvs.openbsd.org> | 2022-11-18 15:01:05 +0000 |
---|---|---|
committer | Theo Buehler <tb@cvs.openbsd.org> | 2022-11-18 15:01:05 +0000 |
commit | bbf3b181d70106f16d567654ad65dc6bb0b26cd5 (patch) | |
tree | 8f9f400f857c72a7c7a9540015284721b769c615 /lib/libcrypto/hmac | |
parent | 9f4e08be828995f9db5889a542cba4c9ccc39d7a (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.c | 63 |
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, }; |