Skip to content

Add support for CMAC #891

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open

Add support for CMAC #891

wants to merge 8 commits into from

Conversation

kmfukuda
Copy link

Follow-up to #806.

Implements #802 by adding the OpenSSL::MAC and OpenSSL::MAC::CMAC classes.

The classes are defined if compiled against OpenSSL 3.

@kmfukuda kmfukuda mentioned this pull request May 21, 2025
@rhenium
Copy link
Member

rhenium commented May 21, 2025

Thanks for working on this series.

The base class OpenSSL::MAC doesn't seem to be useful on its own currently. The EVP_MAC API seems quite generic, so I wonder if we can expose the OSSL_PARAM construction part and the EVP_MAC_init() call as a method under OpenSSL::MAC that accepts arbitrary (parameter, value) pairs. That way, OpenSSL::MAC::CMAC (or other MACs supported by EVP_MAC) could be implemented entirely in lib/openssl/mac.rb without requiring a specialized extension method.

Regarding the method naming, is there particular reason for choosing #{,hex,base64}mac instead of #*digest? Since OpenSSL::HMAC already uses #*digest, I think copying it would have less friction, though I agree it might not have been the best choice originally.

The #*mac naming seems redundant, especially when used with the shorthand methods like OpenSSL::MAC::CMAC.mac(ciph, key, data). Another idea would be to use #final taken from the C API, which is what OpenSSL::Cipher does. That said I'm not sure what name I'd give to the variant that returns the hexadecimal string.

Also, we need docs.

@kmfukuda
Copy link
Author

kmfukuda commented Jul 1, 2025

Thanks for the second review.

That way, OpenSSL::MAC::CMAC (or other MACs supported by EVP_MAC ) could be implemented entirely in lib/openssl/mac.rb without requiring a specialized extension method.

I think we can do it the way you suggest.
However, another approach has occurred to me: OpenSSL::MAC#initialize would also accept key and parameters and call EVP_MAC_init() .
Here, parameters would be an array of objects of the future OpenSSL::Parameter class, which would represent OSSL_PARAM to a certain extent.
I don't currently see which approach is better.
What do you think about these approaches?

Regarding the method naming, is there particular reason for choosing #{,hex,base64}mac instead of #*digest ?

I chose the method names like "mac" because OpenSSL refers to MACs as "MACs," distinguishing them from "digests."
That said, I admit these method names are redundant when used with class names like "MAC."
I propose "value" as yet another option. This is because the term "MAC value" is frequently seen, and since "value" is a noun, it can be preceded by modifiers.

@rhenium
Copy link
Member

rhenium commented Jul 4, 2025

I leaning towards sticking with the *digest naming here. We'll likely want a variant that returns a hexadecimal string and one-shot methods for OpenSSL::MAC, similar to what the digest or OpenSSL::HMAC already provides. Using "final" (from the C API) or "value" would require inventing a new naming scheme just for OpenSSL::MAC which I prefer not to do.

Digging through the history, it appears OpenSSL::HMAC initially had method names #hmac and #hexhmac in 2002. They were later renamed to #digest and #hexdigest around when the one-shot class methods were added. This seems like a it was a deliberate change.

rhenium@9eb38c6

@rhenium
Copy link
Member

rhenium commented Jul 4, 2025

That way, OpenSSL::MAC::CMAC (or other MACs supported by EVP_MAC ) could be implemented entirely in lib/openssl/mac.rb without requiring a specialized extension method.

I think we can do it the way you suggest. However, another approach has occurred to me: OpenSSL::MAC#initialize would also accept key and parameters and call EVP_MAC_init() . Here, parameters would be an array of objects of the future OpenSSL::Parameter class, which would represent OSSL_PARAM to a certain extent. I don't currently see which approach is better. What do you think about these approaches?

FWIW, in #906, I've been working on exposing EVP_KDF that was also added in OpenSSL 3.0 and similarly takes an array of OSSL_PARAM for input. It's not set in stone and the PR is not finished yet, but I'm thinking of an interface to take them at one time as an enumerable of (key, value) tuples.

EVP_KEM mentioned in #894 (comment) (not being worked on yet) also takes it.

I'm hoping they can have a consistent behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants