Oh boy. I wonder how many other companies that have previously been lax about validating that cert revocation is handled correctly by their devices are going to validate the eMudrha cert revocation and discover that they are not, in fact, handling revocation correctly. Yikes.
This caught my eye, remember how the eMudhra certificates had weirdly low parameters, like 4 and others in the single digits?
"Mbed TLS - Medium, CVSS 5.9 - A buffer-length typo reduces a 2048-bit DH modulus to one byte. TLS 1.2 DHE_RSA sessions are decryptable when the client accepts the broken parameters. GOAHEAD-SA-2026-0005."
Not familiar with those implementation details but was this the root cause?
The first sizeof(dhm_g) should have been sizeof(dhm_p). So, do you attribute this to a simple typo (hard to catch at a glance due to similar letter shapes), "single letter variable names are bad" but the wikipedia page on DH also calls them p and g - it takes a little digging to get that "root" and "modulus" would have been better names, but maybe having them directly match the most common form of the equation would have made them easier to review...
Or do you just add it to the list of C crimes, that "passing storage length and pointer" is maybe the worst possible way to return written-to storage from a function :-)
At first glance I almost misread this as a different C crime, since the declarations aren't in scope... uint8_t dhm_p[2048]; and uint8_t *dhm_p = (...)malloc(2048); both make dhm_p a reasonable pointer to 2k bytes of storage and are totally suitable for that argument, but sizeof the first one is 2048 and sizeof the second one is 4 (or more likely 8 these days, but this is specifically code from an embedded web server so I can say 4 :-)
But no, the actual problem was so much less subtle.
Yeah, this is just C doesn't have fat pointers. Fat pointers were proposed for C89. In some alternate universe C89 has fat pointers and in that universe probably by now many of the weird 0-terminated APIs we're frustrated by work on fat pointers instead and we're all better off for it.
A fat pointer is one ordinary thin pointer, plus a pointer-sized blob of extra information, commonly a length. Examples would be Rust's &[T] slice reference, its &str string reference and a pointer for dynamic dispatch &dyn Shape in which that extra blob is pointing to a v-table of functions for how this particular type implements the Shape trait.
This specific bug won't have been why eMudhra had crap parameters, that's most likely because somebody didn't understand how to use the hardware the new keys lived in properly.
But one possibility for their misunderstanding is related in that it'd be a confusion between an item (key #4) and the index to that item (4) and yeah, these APIs do encourage you to make that sort of mistake.
Skipping CRL checks is not a Critical. A Critical is "whoops we were not checking the signature on the certificates" or "I guess all zeroes is a fine session ticket key" (both happened, the former in wolfSSL, the latter in GnuTLS).
Bypassing chain length limits is... barely a Low? It's definitely not a High.
The DHE one is fun. It'd have been valuable if they spent some tokens figuring out if any open source library would accept those broken parameters. If not, it doesn't really matter. (Another good reason not to negotiate DH parameters ever!)
18 comments
[ 965 ms ] story [ 938 ms ] thread"Mbed TLS - Medium, CVSS 5.9 - A buffer-length typo reduces a 2048-bit DH modulus to one byte. TLS 1.2 DHE_RSA sessions are decryptable when the client accepts the broken parameters. GOAHEAD-SA-2026-0005."
Not familiar with those implementation details but was this the root cause?
Or do you just add it to the list of C crimes, that "passing storage length and pointer" is maybe the worst possible way to return written-to storage from a function :-)
But no, the actual problem was so much less subtle.
A fat pointer is one ordinary thin pointer, plus a pointer-sized blob of extra information, commonly a length. Examples would be Rust's &[T] slice reference, its &str string reference and a pointer for dynamic dispatch &dyn Shape in which that extra blob is pointing to a v-table of functions for how this particular type implements the Shape trait.
But one possibility for their misunderstanding is related in that it'd be a confusion between an item (key #4) and the index to that item (4) and yeah, these APIs do encourage you to make that sort of mistake.
Skipping CRL checks is not a Critical. A Critical is "whoops we were not checking the signature on the certificates" or "I guess all zeroes is a fine session ticket key" (both happened, the former in wolfSSL, the latter in GnuTLS).
Bypassing chain length limits is... barely a Low? It's definitely not a High.
The DHE one is fun. It'd have been valuable if they spent some tokens figuring out if any open source library would accept those broken parameters. If not, it doesn't really matter. (Another good reason not to negotiate DH parameters ever!)