I stumbled across this issue when performing a chain validation of X509 certificates for Remote SIM Provisioning (RSP) as defined in GSMA SGP.22 v2.5. The chain of these certificates is as follows:
- eUICC Certificate (Leaf)
- EUM Certificate (Intermediate CA)
- CI certificate (Root)
Section 4.5.2.1.0.3 of SGP.22 v2.5 mentions that the restriction for the Serial Number attribute of the EUM certificate is a 'startsWith' instead of an 'equals' comparison. Additionally, section 4.5.2.1.0.2 of SGP.22 v2.5 mentions that the subject field of the eUICC certificate must have at least the organization and serial number attributes but other attributes may be included as well. This will become relevant later.
The following is a snippet that reproduces the issue:
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralSubtree;
import org.bouncycastle.asn1.x509.NameConstraintValidatorException;
import org.bouncycastle.asn1.x509.PKIXNameConstraintValidator;
class Scratch {
public static void main(String[] args) {
PKIXNameConstraintValidator nameConstraintValidator = new PKIXNameConstraintValidator();
var permittedX500Name = new X500Name("O=VALID, serialNumber=89034011");
var permittedGeneralName = new GeneralName(permittedX500Name);
var permittedSubtree = new GeneralSubtree(permittedGeneralName);
//Add permitted subtree
nameConstraintValidator.intersectPermittedSubtree(permittedSubtree);
var subjectX500Name = new X500Name("C=ES, O=VALID, CN=VALID EUICC CD, OU=VALID, serialNumber=89034011026140000000000000001332");
try {
//This call throws NameConstraintValidatorException
nameConstraintValidator.checkPermittedDN(subjectX500Name);
} catch (NameConstraintValidatorException e) {
//Failed
e.printStackTrace();
}
}
}
In the previous snippet, the permitted subtree's distinguished name has the following attributes:
- Organization=
VALID (The subject Organization attribute must be 'equal')
- Serial Number=
89034011 (The subject serialNumber must 'startWith' the specified value).
However, since the subject's distinguished name more attributes (such as organizational unit name, common name, etc) than the organization and serial number, the validations fails because these additional attributes are messing with the order of the attributes required by the permitted subtree.
On top of that, the validation also fails when the Serial Number attribute happens to be the first attribute of the permitted subtree. The following snippet demonstrates the problem:
import org.bouncycastle.asn1.x500.X500Name;
import org.bouncycastle.asn1.x509.GeneralName;
import org.bouncycastle.asn1.x509.GeneralSubtree;
import org.bouncycastle.asn1.x509.NameConstraintValidatorException;
import org.bouncycastle.asn1.x509.PKIXNameConstraintValidator;
class Scratch {
public static void main(String[] args) {
PKIXNameConstraintValidator nameConstraintValidator = new PKIXNameConstraintValidator();
//var permittedX500Name = new X500Name("O=VALID, serialNumber=89034011");
var permittedX500Name = new X500Name("serialNumber=89034011, O=VALID");
var permittedGeneralName = new GeneralName(permittedX500Name);
var permittedSubtree = new GeneralSubtree(permittedGeneralName);
//Add permitted subtree
nameConstraintValidator.intersectPermittedSubtree(permittedSubtree);
var subjectX500Name = new X500Name("serialNumber=89034011026140000000000000001332, O=VALID");
try {
//Check if the x500 is a permitted directory name
nameConstraintValidator.checkPermittedDN(subjectX500Name);
} catch (NameConstraintValidatorException e) {
//Exception is thrown
e.printStackTrace();
}
}
}
Even though the subject distinguished name has the same attributes and in the exact order as specified by the permitted subtree, the name constraint validation is failing because the org.bouncycastle.asn1.x509.PKIXNameConstraintValidator class is comparing that the serialNumber of the subject distinguished name is 'equal' to the same attribute in the permitted subtree which is incorrect.
Proposed solution
Although section 7.1 of RFC 5280 dictates the rules for comparing distinguished names, the class org.bouncycastle.asn1.x509.PKIXNameConstraintValidator is already defining an exception for the Serial Number attribute for the GSMA SGP.22 RSP specification in the withinDNSubtree method as shown bellow:
// Two relative distinguished names
// RDN1 and RDN2 match if they have the same number of naming attributes
// and for each naming attribute in RDN1 there is a matching naming attribute in RDN2.
// NOTE: this is checking the attributes in the same order, which might be not necessary, if this is a problem also IETFUtils.rDNAreEqual must be changed.
// use new RFC 5280 comparison, NOTE: this is now different from with RFC 3280, where only binary comparison is used
// obey RFC 5280 7.1
// special treatment of serialNumber for GSMA SGP.22 RSP specification
if (!subtreeRdn.getFirst().getType().equals(dnsRdn.getFirst().getType()))
{
return false;
}
if (subtreeRdn.size() == 1 && subtreeRdn.getFirst().getType().equals(RFC4519Style.serialNumber))
{
if (!dnsRdn.getFirst().getValue().toString().startsWith(subtreeRdn.getFirst().getValue().toString()))
{
return false;
}
}
else if (!IETFUtils.rDNAreEqual(subtreeRdn, dnsRdn))
{
return false;
}
So the method could also include code to fix the issues described above.
I stumbled across this issue when performing a chain validation of X509 certificates for Remote SIM Provisioning (RSP) as defined in GSMA SGP.22 v2.5. The chain of these certificates is as follows:
Section 4.5.2.1.0.3 of SGP.22 v2.5 mentions that the restriction for the Serial Number attribute of the EUM certificate is a 'startsWith' instead of an 'equals' comparison. Additionally, section 4.5.2.1.0.2 of SGP.22 v2.5 mentions that the subject field of the eUICC certificate must have at least the organization and serial number attributes but other attributes may be included as well. This will become relevant later.
The following is a snippet that reproduces the issue:
In the previous snippet, the permitted subtree's distinguished name has the following attributes:
VALID(The subject Organization attribute must be 'equal')89034011(The subject serialNumber must 'startWith' the specified value).However, since the subject's distinguished name more attributes (such as organizational unit name, common name, etc) than the organization and serial number, the validations fails because these additional attributes are messing with the order of the attributes required by the permitted subtree.
On top of that, the validation also fails when the Serial Number attribute happens to be the first attribute of the permitted subtree. The following snippet demonstrates the problem:
Even though the subject distinguished name has the same attributes and in the exact order as specified by the permitted subtree, the name constraint validation is failing because the
org.bouncycastle.asn1.x509.PKIXNameConstraintValidatorclass is comparing that the serialNumber of the subject distinguished name is 'equal' to the same attribute in the permitted subtree which is incorrect.Proposed solution
Although section 7.1 of RFC 5280 dictates the rules for comparing distinguished names, the class
org.bouncycastle.asn1.x509.PKIXNameConstraintValidatoris already defining an exception for the Serial Number attribute for the GSMA SGP.22 RSP specification in thewithinDNSubtreemethod as shown bellow:So the method could also include code to fix the issues described above.