Closed Bug 1186070 Opened 5 years ago Closed 4 years ago

Replace DottedOIDToCode.py with use of C++ user-defined literals

Categories

(Core :: Security: PSM, enhancement, P5)

enhancement

Tracking

()

RESOLVED WONTFIX
Tracking Status
firefox42 --- affected

People

(Reporter: briansmith, Assigned: tareqakhandaker, Mentored)

References

Details

(Keywords: helpwanted, Whiteboard: [psm-assigned])

User-defined literals should allow us to write something like this:

     "1.2.3.4"_OID

and have the compiler convert it, *at compile time*, into the uint8_t[] DER encoding of the OID. Then we don't need the DottedOIDToCode.py script and we can make the code dealing with OIDs much clearer.

If somebody wants to experiment with implementing this this, I am available to help (either here or at https://github.com/briansmith/mozillapkix, if you prefer GitHub over Bugzilla). It wouldn't be able to land in Firefox until bug 1186060 (at least) is fixed, but I would consider landing it in my GitHub tree sooner.
Er, I meant bug 1186064.
Depends on: 1186064
No longer depends on: vs2015
I took a crack at this issue by mostly taking the DottedOIDToCode.py script and rewriting it in C++11.  I am at the point where I am about to write the user-defined literal code, but I have a few questions.

1) I realized that there needs to be a way to supply the mode (e.g. "alg") somehow. Should I just add that to the literal and parse it accordingly? e.g. "alg 1.2.3.4"_OID

2) How will the "prefixdefine" feature work with user-define literals? Should I not worry about it?

3) Where should the final code be located? Any header files? What should the files be called? I am just calling it oid.cpp on my local machine.
Flags: needinfo?(brian)
(In reply to Tareq Khandaker from comment #2)
> 1) I realized that there needs to be a way to supply the mode (e.g. "alg")
> somehow. Should I just add that to the literal and parse it accordingly?
> e.g. "alg 1.2.3.4"_OID

I would suggest instead that you have a different suffix, like "1.2.3.4"_ALGORITHM_ID.

However, I also suggest that you just worry about the simplest case for now, because the simplest case is the one that is used in lib/*, which is the part where it is most interesting to get rid of the Python-generated code. In fact, we may want to keep the Python-generated code for use in test/* so that we can use it to verify that the user-defined literal implementation is correct.

> 2) How will the "prefixdefine" feature work with user-define literals?
> Should I not worry about it?

Again, that's not so interesting because that is used in test/*, not in lib/*.

> 3) Where should the final code be located? Any header files? What should the
> files be called? I am just calling it oid.cpp on my local machine.

AFAIK, user-defined literal code has to be in a header file in order for the compiler to execute it during compilation. I suggest oid.h next to der.h, and then have der.h include oid.h.

WARNING: It may be a very long time before Mozilla can use user-defined literals in C++ code, so it may be a long time before it gets checked in here. However, if you finish the work then I can integrate it into https://github.com/briansmith/mozillapkix sooner.

Also, I recommend that you take a look at the oid macros I wrote for libwebpki: https://github.com/briansmith/webpki/blob/b808268039fa9598bb338845895b59d6d259755c/src/der.rs#L263. Doing something simpler, like that, may be the best approach. Otherwise, the user-defined-literal code may be so complicated that it is not worth using to replace the Python code.
Flags: needinfo?(brian)
I put my code in the mozilla-central tree in the security/pkix folder and built it with ./mach build . I tried returning a vector's data (uint8_t*) or an outright std::string, but in both cases I get this error (): 

/src/mozilla-central/security/pkix/lib/pkixder.cpp:132:24: error: array initializer must be an initializer list or string literal
 0:14.03   static const uint8_t ecdsa_with_SHA256[] = "1.2.840.10045.4.3.2"_OID;

I did some online searches ("array initialization with user-defined literals"), but I didn't find anyone trying to do the same thing.
Flags: needinfo?(brian)
IIRC, you need to define a |struct OID { const uint8_t bytes[] };| and have your UDL implementation return instances of OID.

Note that creating an implementation of user-defined literals is quite hard, especially for OIDs.
Flags: needinfo?(brian)
Does this mean I can change  |static const uint8_t ecdsa_with_SHA256[] = ...| to something like |static const struct OID ecdsa_with_SHA256 = ...| ?
Flags: needinfo?(brian)
After a lot of research, I found out that user-defined literals arguments are not constexpr (https://stackoverflow.com/questions/8108473/user-defined-literal-arguments-are-not-constexpr). This needs to be the case in order to evaluate the DER encoding at compile time. 

However, all is not lost. I read that raw string literals can be evaluated at compile time (https://akrzemi1.wordpress.com/2012/10/23/user-defined-literals-part-ii/). However, they only work for integer and floating-point literals, so I cannot do something like "1.2.3.4"_OID. I might be able to do something like 1_OID_first @ 2_OID_second @ 3_OID @ 4_OID where @ is some operator?

1_OID_first + 2_OID_second + 3 + 4 might work too since the + operator operates left to right.

Let me know if that is acceptable. I might try to do it anyway just to see if it is possible.
Assignee: nobody → tareqakhandaker
Priority: -- → P5
Whiteboard: [psm-assigned]
I think at this point we can say this isn't a fruitful direction to go in.
Tareq, I appreciate your willingness to work on this, and I apologize for not resolving this sooner. If you're still interested in working on bugs in this area, feel free to search around in the Core :: Security: PSM component.
Status: NEW → RESOLVED
Closed: 4 years ago
Flags: needinfo?(brian)
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.