When implementing a project related to the use of Russian cryptographic algorithms in the
KMail email client
in the Kleopatra and GnuPG application , to convert Russian
oid- s from dot-decimal form to DER-encoding, I decided to use the
oidcalc utility from the
NSS (Network Security Services) package , which is preinstalled in all Linux distributions, including domestic clones. The resulting code was used in the work.
And everything went well until an
oid was
found that had a decimal digit of 0 (zero), namely “1.2.643.2.2.36.0” (szOID_GostR3410_2001_CryptoPro_XchA_ParamSet). And here an unpleasant surprise was waiting for me - my code stopped working. At some point I decided to look, and what this
oid means :
# oidcalc 1.2.643.2.2.36.0 0x2a, 0x85, 0x3, 0x2, 0x2, 0x24, #
But it should have been
0x2a, 0x85, 0x3, 0x2, 0x2, 0x24, 0x0, - the trailing hex zero was missing.
I tried to translate another oid "1.2.643.3.6.0.1" (CryptoPro Pro, Certificate validity period 1 month):
')
# oidcalc 1.2.643.3.6.0.1 0x2a, 0x85, 0x3, 0x3 0x3, 0x6, 0x1, #
The same sad result - there is no penultimate byte with zero. It became clear that the oidcalc utility throws out zeros from the oid. The following example only confirmed this assumption:
# oidcalc 1.2.643.3.6.1 0x2a, 0x85, 0x3, 0x3 0x3, 0x6, 0x1, #
For another check, I had to use the
oid utility and got the result I expected:
# ./oid 1.2.643.2.2.36.0 06 07 2A 85 03 02 02 24 00 # ./oid 1.2.643.3.6.0.1 06 07 2A 85 03 03 06 00 01 #
The
oid utility displays the result already in ASN1-encoding, where the first byte determines the type of sequence, the second byte - the length of the sequence in bytes, and then the oid itself is in hexadecimal.
After that, it remained to analyze the source code of the
oidcalc.c utility and together the minimal changes:
. . . memset(buf, 0, sizeof(buf)); val = atoi(curstr); count = 0; if(curstr[0] != '0') while (val) { buf[count] = (val & 0x7f); val = val >> 7; count++; } else buf[count++] = 0x00; . . .
Now, if you rebuild the utility, then everything works fine:
#oidcalc 1.2.643.2.2.36.0 0x2a, 0x85, 0x3, 0x2, 0x2, 0x24, 0x0, #oidcalc 1.2.643.3.6.0.1 0x2a, 0x85, 0x3, 0x3, 0x6, 0x0, 0x1, #
What was wrong with the utility developer? In the little things. To translate a number from a string to an integer, the author uses the
atoi functions, which returns 0 (zero) and in case of translating the character '0' and in case of impossibility of translation (no number is given). It turned out to be enough to add additional checks and it all worked.
Did I write to the NSS developers? Yes, he wrote. Moreover, the NSS package with plug-in cryptographic tokens / smartcards that support
the PKCS # 11 interface is actually a cryptographic
core of applications from Mozilla, and is also used in Google's Chrome browsers. No reply, code not corrected. Therefore, this note appeared so that someone else did not step on this rake as your humble servant. And, of course, we hope that the suppliers of domestic Linux forks / clones will fix this error in their packages.