ARIN RPKI DATA ISSUE (August 12th, 2020) ======================================== status: RESOLVED last update: Thu Aug 13 15:41:29 UTC 2020 report contact: job@ntt.net contributors: Sebastian Benoit, Theo Buehler, Joel Sing, Job Snijders, and Claudio Jeker ARIN update #1: https://www.arin.net/announcements/20200812/ ARIN update #2: https://www.arin.net/announcements/20200813/ Executive overview ------------------ On August 12th, 2020 a change was made to ARIN's RPKI signing infrastructure, after the change the rpki-client and FORT validators no longer considered ARIN's RPKI data to be valid. An important manifest close to the top of the tree is now considered invalid with the following openssl/libressl error code: X509_V_ERR_CERT_SIGNATURE_FAILURE: certificate signature failure Upon further inspection, it appears the RPKI data now violates this X.509 standards requirement: RFC 5280 ("Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile") section 4.1.1.2: """ This field MUST contain the same algorithm identifier as the signature field in the sequence tbsCertificate (Section 4.1.2.3). """ Both signature identifiers are in the manifest file, the first one is in cert metadata if you will, the second one is the actual signature. One of them has an explicit ASN NULL object and the other one doesn't have one, so they are considered distinct and the signature validation procedure thus returns 'invalid'. Both occurances of algorithm identifier MUST have an explicit NULL object, as per RFC 4055: """ -- When the following OIDs are used in an AlgorithmIdentifier, the -- parameters MUST be present and MUST be NULL. sha224WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 14 } sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 } sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 } sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 } """ This NULL parameter is also found in the data in all other RPKI repositories from other RIRs. SOLUTION ======== ARIN's signing machinery should correctly specify the algorithm identifier to resolve this issue. DETAILS & MANUALLY ANNOTATED HEXDUMP ==================================== (emails from openbsd/libressl developers) claudio@ wrote: > I did some more digging. The verification fails in X509_ALGOR_cmp() > because a->parameter is NULL but b->parameter is not and so > ASN1_TYPE_cmp() fails. > > This is called from X509_verify() as: > X509_ALGOR_cmp(a->sig_alg, a->cert_info->signature) > Why is a->sig_alg->parameter NULL but a->cert_info->signature->parameter not? > > Btw. up until this point all calls to X509_ALGOR_cmp() took the other path > where both a->parameter and b->parameter is NULL. > What is this parameter and why is there a difference? tb@ wrote: It's stored like this in mft.crt (so no parsing bug in libcrypto). To recap. At the point where the comparison fails, we have this: (gdb) p *a $12 = {algorithm = 0x62537a5bb40, parameter = 0x0} (gdb) p *b $13 = {algorithm = 0x62537a5bec0, parameter = 0x6250eece630} (gdb) x/9bx a->algorithm->data 0x6256f5d2e70: 0x2a 0x86 0x48 0x86 0xf7 0x0d 0x01 0x01 0x6256f5d2e78: 0x0b (gdb) x/9bx b->algorithm->data 0x625af836970: 0x2a 0x86 0x48 0x86 0xf7 0x0d 0x01 0x01 0x625af836978: 0x0b So both are sha256WithRSAEncryption (see libcrypto/obj/obj_dat.h) The EE certificate extracted from 5e4a23ea-e80a-403e-b08c-2171da2157d3.mft sent by benno@ contains this: $ openssl x509 -in mft.crt -noout -text Certificate: Data: Version: 3 (0x2) Serial Number: 01:0d:0c:9f:43:28:57:6d:51:cc:73:c0:42:cf:c1:73:e3:5f:2b:1c Signature Algorithm: sha256WithRSAEncryption [...] Signature Algorithm: sha256WithRSAEncryption 81:4a:4b:9d:e7:1a:19:9b:88:05:8d:94:82:01:12:ed:5f:bf: [...] It turns out that the first sigalg has the ASN NULL part, while the second hasn't. Since the -text output often silently skips/swallows stuff, I usually only take this as an aid in orientation and decode the DER form by hand (hackathons/p2k9.gif): $ openssl x509 -in mft.crt -out mft.der -outform der # convert it $ hexdump -Cv mft.der | less # look at it The hexdump starts as follows: 00000000 30 82 05 73 30 82 04 5d a0 03 02 01 02 02 14 01 |0..s0..]........| 00000010 0d 0c 9f 43 28 57 6d 51 cc 73 c0 42 cf c1 73 e3 |...C(WmQ.s.B..s.| 00000020 5f 2b 1c 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b |_+.0...*.H......| 00000030 05 00 |..0/1-0+..U...$5| Annotated by hand: Certificate (length 0x573): 30 82 05 73 Data (length 0x45d): 30 82 04 5d Version (length 3): a0 03 Integer (length 1) 02 01 02 Serial Number (length 0x14): 02 14 01 0d 0c 9f 43 28 57 6d 51 cc 73 c0 42 cf c1 73 e3 5f 2b 1c And the bit we're interested in: Signature Algorithm (length 0x0d) 30 0d 06 09 2a 86 48 86 f7 0d 01 01 0b sha256WithRSAEncryption 05 00 And the 05 00 is the ASN1 NULL object in b, (the cert_info bit). continuing in the hexdump, we find the sig_alg bit towards the end: ... 00000460 30 0b 06 09 2a 86 48 86 f7 0d 01 |.html0...*.H....| 00000470 01 0b 03 82 01 01 00 81 4a 4b 9d e7 1a 19 9b 88 |........JK......| ... Here we have a Signature Algorithm of length 0x0b only: 30 0b 06 09 2a 86 48 86 f7 0d 01 01 0b sha256WithRSAEncryption No ASN1 NULL object here, and it is directly followed by 03 82 01 01, a 0x101 = 257 bytes long bit string starting with 00 81 4a 4b 9d e7 1a 19 9b 88 which is the same as the colon separated hex output at the end of the openssl x509 -text display