-
Notifications
You must be signed in to change notification settings - Fork 30.2k
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
crypto: add OID constants for EVP_PKEY_ types #27181
Conversation
@sam-github would the OID be then also available on a KeyObject instance? I can easily replace |
@panva In this PR, no, but this is an incremental step towards it. This PR exposes the values that would be necessary for comparisons: |
Sounds good. |
src/node_constants.cc
Outdated
// Convert nid's to the string representation of their OID. Non-reentrant, and | ||
// will abort if called with invalid nids (so only pass values from OpenSSL's | ||
// headers). | ||
static const char* OBJ_nid2oid(int nid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This more or less duplicates OBJ_nid2ln()
, doesn't it?
(Or maybe OBJ_nid2ln()
followed by OBJ_nid2sn()
if the former doesn't find anything.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, check out nid_objs
in deps/openssl/openssl/crypto/objects/obj_dat.h
. I'd hoped the ln would be what I want, but it's the name used in the ASN.1 (as opposed to the sn which is the openssl abbreviated name). Its the "txt" I want, and that can only be gotten this way (AFAICT).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I get it now. Okay, objection withdrawn but can you use CHECK_NOT_NULL(obj)
?
NID2OID(EVP_PKEY_DH); | ||
NID2OID(EVP_PKEY_EC); | ||
// Note for backporters: following are new in openssl 1.1.1. | ||
NID2OID(EVP_PKEY_ED25519); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap these in #ifdef EVP_PKEY_ED25519
etc.?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
master doesn't support anything earlier than openssl 1.1.1, and I didn't want to introduce the possibility that someone might try and get a superficially working build. This is constructed this way (without the #define EVPS(V) V( EVP_PKEY_DH)
idiom so that when this backports to 11.x or 10.x, it will be trivial to put in the macros.
I don't know. IIRC #26709 was closed because we did not see much use for OIDs as long as there was a 1:1 mapping of key type strings (
True, but on the other hand, these constants won't make it much easier to implement ASN.1. So the only reason I can currently see is to determine which key types are supported, and I wonder whether this is the best way to do that.
I agree not to expose NIDs. For our own testing, we don't need to expose them to users, though, we could use internal constants. |
If this makes backporting easier why not (so long as it is accompanied by |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM with suggestions.
src/node_constants.cc
Outdated
// Convert nid's to the string representation of their OID. Non-reentrant, and | ||
// will abort if called with invalid nids (so only pass values from OpenSSL's | ||
// headers). | ||
static const char* OBJ_nid2oid(int nid) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I get it now. Okay, objection withdrawn but can you use CHECK_NOT_NULL(obj)
?
src/node_constants.cc
Outdated
CHECK(obj); | ||
|
||
static char buf[128]; | ||
CHECK_LE(OBJ_obj2txt(buf, sizeof(buf), obj, 1), 128); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sizeof(buf)
Consider having the caller pass in the buffer: declare the param as char (*buf)[128]
, the caller then passes in &buf
and can't get the size wrong. (See GetHumanReadableProcessName()
for another example.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I rewrote as you suggested, but I don't use sizeof(buf)
because it is size_t
, and obj2txt()
returns int
, and comparison causes warnings on sign mismatch. I can static_cast<size_t>(OBJ_obj2txt())
, but that doesn't seem clearly better.
The existence of the constant can be used to check for support for the key types, and the value is useful when encoding/decoding keys using ASN.1.
e4901fb
to
e159ce8
Compare
@panva we can't make breaking ( @tniessen Good reminder. Perhaps I'll make them properties of the internal Maybe it's time to add |
Definitely no objections to having this for internal unit tests as long as it isn't exposed to users.
That's true, except that the names are very OpenSSL-specific (
I remember there was an issue about feature detection in Node.js. We are currently doing that half-heartedly at best. For each recently added feature, there might be a way to tell if it is there, but there certainly is no uniform way across builtin modules. If adding these constants is the best way to do it, then we probably should do it. Feature detection aside, I guess it boils down to this question: Do users need to deal with OIDs, and are there any benefits of using OIDs over strings? For example, as far as I know, all EC curves have well-known names, so returning the name instead of the OID might be easier for users. I feel like adding numeric constants (or string representations of these) and using them as parameters or to check for equality is usually just a more difficult way of expressing a more abstract principle:
I think if we decide to add |
EC curves may not be the best example with curves being given different names by different standards bodies. OIDs are definitive in this case. I think we shouldn’t be adding stuff that is ultimately part of .fields and could end up being duplicated. |
I'll do some more thinking about this, its clearly not ready to land as-is. I will consier just transforming this into the minimal change I need to the binding layer or constants so that feature detection is easy. |
The existence of the constant can be used to check for support for the
key types, and the value is useful when encoding/decoding keys using
ASN.1.
Follow-on to #26786 (comment), these values might be useful if we move to key type constants, rather than strings like "rsa", etc.
Also, when PRs are backported from master to 11.x that use EVP key types that aren't supported by OpenSSL 1.1.0, it is trivial to ifdef out the C++ code that uses them. It's less trivial to deal with in the tests. Checking openssl version numbers explicitly is fragile (and hard if range checks are required). It will be easier to just test for existence of the define (effectively) from js. I didn't want to expose the NIDs, but the OIDs are useful values (I think).
@tniessen @panva Thoughts?
Checklist
make -j4 test
(UNIX), orvcbuild test
(Windows) passes