use of com.github.zhenwei.core.asn1.x509.ExtendedKeyUsage in project xipki by xipki.
the class ExtensionsChecker method checkExtensions.
// constructor
public List<ValidationIssue> checkExtensions(Certificate cert, X509IssuerInfo issuerInfo, Extensions requestedExtensions, X500Name requestedSubject) {
ParamUtil.requireNonNull("cert", cert);
ParamUtil.requireNonNull("issuerInfo", issuerInfo);
X509Certificate jceCert;
try {
jceCert = X509Util.toX509Cert(cert);
} catch (CertificateException ex) {
throw new IllegalArgumentException("invalid cert: " + ex.getMessage());
}
List<ValidationIssue> result = new LinkedList<>();
// detect the list of extension types in certificate
Set<ASN1ObjectIdentifier> presentExtenionTypes = getExensionTypes(cert, issuerInfo, requestedExtensions);
Extensions extensions = cert.getTBSCertificate().getExtensions();
ASN1ObjectIdentifier[] oids = extensions.getExtensionOIDs();
if (oids == null) {
ValidationIssue issue = new ValidationIssue("X509.EXT.GEN", "extension general");
result.add(issue);
issue.setFailureMessage("no extension is present");
return result;
}
List<ASN1ObjectIdentifier> certExtTypes = Arrays.asList(oids);
for (ASN1ObjectIdentifier extType : presentExtenionTypes) {
if (!certExtTypes.contains(extType)) {
ValidationIssue issue = createExtensionIssue(extType);
result.add(issue);
issue.setFailureMessage("extension is absent but is required");
}
}
Map<ASN1ObjectIdentifier, ExtensionControl> extensionControls = certProfile.getExtensionControls();
for (ASN1ObjectIdentifier oid : certExtTypes) {
ValidationIssue issue = createExtensionIssue(oid);
result.add(issue);
if (!presentExtenionTypes.contains(oid)) {
issue.setFailureMessage("extension is present but is not permitted");
continue;
}
Extension ext = extensions.getExtension(oid);
StringBuilder failureMsg = new StringBuilder();
ExtensionControl extControl = extensionControls.get(oid);
if (extControl.isCritical() != ext.isCritical()) {
addViolation(failureMsg, "critical", ext.isCritical(), extControl.isCritical());
}
byte[] extensionValue = ext.getExtnValue().getOctets();
try {
if (Extension.authorityKeyIdentifier.equals(oid)) {
// AuthorityKeyIdentifier
checkExtensionIssuerKeyIdentifier(failureMsg, extensionValue, issuerInfo);
} else if (Extension.subjectKeyIdentifier.equals(oid)) {
// SubjectKeyIdentifier
checkExtensionSubjectKeyIdentifier(failureMsg, extensionValue, cert.getSubjectPublicKeyInfo());
} else if (Extension.keyUsage.equals(oid)) {
// KeyUsage
checkExtensionKeyUsage(failureMsg, extensionValue, jceCert.getKeyUsage(), requestedExtensions, extControl);
} else if (Extension.certificatePolicies.equals(oid)) {
// CertificatePolicies
checkExtensionCertificatePolicies(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.policyMappings.equals(oid)) {
// Policy Mappings
checkExtensionPolicyMappings(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.subjectAlternativeName.equals(oid)) {
// SubjectAltName
checkExtensionSubjectAltName(failureMsg, extensionValue, requestedExtensions, extControl, requestedSubject);
} else if (Extension.subjectDirectoryAttributes.equals(oid)) {
// SubjectDirectoryAttributes
checkExtensionSubjectDirAttrs(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.issuerAlternativeName.equals(oid)) {
// IssuerAltName
checkExtensionIssuerAltNames(failureMsg, extensionValue, issuerInfo);
} else if (Extension.basicConstraints.equals(oid)) {
// Basic Constraints
checkExtensionBasicConstraints(failureMsg, extensionValue);
} else if (Extension.nameConstraints.equals(oid)) {
// Name Constraints
checkExtensionNameConstraints(failureMsg, extensionValue, extensions, extControl);
} else if (Extension.policyConstraints.equals(oid)) {
// PolicyConstrains
checkExtensionPolicyConstraints(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.extendedKeyUsage.equals(oid)) {
// ExtendedKeyUsage
checkExtensionExtendedKeyUsage(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.cRLDistributionPoints.equals(oid)) {
// CRL Distribution Points
checkExtensionCrlDistributionPoints(failureMsg, extensionValue, issuerInfo);
} else if (Extension.inhibitAnyPolicy.equals(oid)) {
// Inhibit anyPolicy
checkExtensionInhibitAnyPolicy(failureMsg, extensionValue, extensions, extControl);
} else if (Extension.freshestCRL.equals(oid)) {
// Freshest CRL
checkExtensionDeltaCrlDistributionPoints(failureMsg, extensionValue, issuerInfo);
} else if (Extension.authorityInfoAccess.equals(oid)) {
// Authority Information Access
checkExtensionAuthorityInfoAccess(failureMsg, extensionValue, issuerInfo);
} else if (Extension.subjectInfoAccess.equals(oid)) {
// SubjectInfoAccess
checkExtensionSubjectInfoAccess(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_extension_admission.equals(oid)) {
// Admission
checkExtensionAdmission(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_extension_pkix_ocsp_nocheck.equals(oid)) {
// ocsp-nocheck
checkExtensionOcspNocheck(failureMsg, extensionValue);
} else if (ObjectIdentifiers.id_extension_restriction.equals(oid)) {
// restriction
checkExtensionRestriction(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_extension_additionalInformation.equals(oid)) {
// additionalInformation
checkExtensionAdditionalInformation(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_extension_validityModel.equals(oid)) {
// validityModel
checkExtensionValidityModel(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.privateKeyUsagePeriod.equals(oid)) {
// privateKeyUsagePeriod
checkExtensionPrivateKeyUsagePeriod(failureMsg, extensionValue, jceCert.getNotBefore(), jceCert.getNotAfter());
} else if (Extension.qCStatements.equals(oid)) {
// qCStatements
checkExtensionQcStatements(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (Extension.biometricInfo.equals(oid)) {
// biometricInfo
checkExtensionBiometricInfo(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_pe_tlsfeature.equals(oid)) {
// tlsFeature
checkExtensionTlsFeature(failureMsg, extensionValue, requestedExtensions, extControl);
} else if (ObjectIdentifiers.id_xipki_ext_authorizationTemplate.equals(oid)) {
// authorizationTemplate
checkExtensionAuthorizationTemplate(failureMsg, extensionValue, requestedExtensions, extControl);
} else {
byte[] expected;
if (ObjectIdentifiers.id_smimeCapabilities.equals(oid)) {
// SMIMECapabilities
expected = smimeCapabilities.getValue();
} else {
expected = getExpectedExtValue(oid, requestedExtensions, extControl);
}
if (!Arrays.equals(expected, extensionValue)) {
addViolation(failureMsg, "extension valus", hex(extensionValue), (expected == null) ? "not present" : hex(expected));
}
}
if (failureMsg.length() > 0) {
issue.setFailureMessage(failureMsg.toString());
}
} catch (IllegalArgumentException | ClassCastException | ArrayIndexOutOfBoundsException ex) {
LOG.debug("extension value does not have correct syntax", ex);
issue.setFailureMessage("extension value does not have correct syntax");
}
}
return result;
}
use of com.github.zhenwei.core.asn1.x509.ExtendedKeyUsage in project xipki by xipki.
the class IdentifiedX509Certprofile method getExtensions.
/**
* TODO.
* @param requestedSubject
* Subject requested subject. Must not be {@code null}.
* @param grantedSubject
* Granted subject. Must not be {@code null}.
* @param requestedExtensions
* Extensions requested by the requestor. Could be {@code null}.
* @param publicKeyInfo
* Subject public key. Must not be {@code null}.
* @param publicCaInfo
* CA information. Must not be {@code null}.
* @param crlSignerCert
* CRL signer certificate. Could be {@code null}.
* @param notBefore
* NotBefore. Must not be {@code null}.
* @param notAfter
* NotAfter. Must not be {@code null}.
* @param caInfo
* CA information.
* @return the extensions of the certificate to be issued.
*/
public ExtensionValues getExtensions(X500Name requestedSubject, X500Name grantedSubject, Extensions requestedExtensions, SubjectPublicKeyInfo publicKeyInfo, PublicCaInfo publicCaInfo, X509Certificate crlSignerCert, Date notBefore, Date notAfter) throws CertprofileException, BadCertTemplateException {
ParamUtil.requireNonNull("publicKeyInfo", publicKeyInfo);
ExtensionValues values = new ExtensionValues();
Map<ASN1ObjectIdentifier, ExtensionControl> controls = new HashMap<>(certprofile.getExtensionControls());
Set<ASN1ObjectIdentifier> neededExtTypes = new HashSet<>();
Set<ASN1ObjectIdentifier> wantedExtTypes = new HashSet<>();
if (requestedExtensions != null) {
Extension reqExtension = requestedExtensions.getExtension(ObjectIdentifiers.id_xipki_ext_cmpRequestExtensions);
if (reqExtension != null) {
ExtensionExistence ee = ExtensionExistence.getInstance(reqExtension.getParsedValue());
neededExtTypes.addAll(ee.getNeedExtensions());
wantedExtTypes.addAll(ee.getWantExtensions());
}
for (ASN1ObjectIdentifier oid : neededExtTypes) {
if (wantedExtTypes.contains(oid)) {
wantedExtTypes.remove(oid);
}
if (!controls.containsKey(oid)) {
throw new BadCertTemplateException("could not add needed extension " + oid.getId());
}
}
}
// SubjectKeyIdentifier
ASN1ObjectIdentifier extType = Extension.subjectKeyIdentifier;
ExtensionControl extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
byte[] encodedSpki = publicKeyInfo.getPublicKeyData().getBytes();
byte[] skiValue = HashAlgo.SHA1.hash(encodedSpki);
SubjectKeyIdentifier value = new SubjectKeyIdentifier(skiValue);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// Authority key identifier
extType = Extension.authorityKeyIdentifier;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
byte[] ikiValue = publicCaInfo.getSubjectKeyIdentifer();
AuthorityKeyIdentifier value = null;
if (ikiValue != null) {
if (certprofile.includesIssuerAndSerialInAki()) {
GeneralNames x509CaSubject = new GeneralNames(new GeneralName(publicCaInfo.getX500Subject()));
value = new AuthorityKeyIdentifier(ikiValue, x509CaSubject, publicCaInfo.getSerialNumber());
} else {
value = new AuthorityKeyIdentifier(ikiValue);
}
}
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// IssuerAltName
extType = Extension.issuerAlternativeName;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
GeneralNames value = publicCaInfo.getSubjectAltName();
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// AuthorityInfoAccess
extType = Extension.authorityInfoAccess;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
AuthorityInfoAccessControl aiaControl = certprofile.getAiaControl();
List<String> caIssuers = null;
if (aiaControl == null || aiaControl.isIncludesCaIssuers()) {
caIssuers = publicCaInfo.getCaCertUris();
}
List<String> ocspUris = null;
if (aiaControl == null || aiaControl.isIncludesOcsp()) {
ocspUris = publicCaInfo.getOcspUris();
}
if (CollectionUtil.isNonEmpty(caIssuers) || CollectionUtil.isNonEmpty(ocspUris)) {
AuthorityInformationAccess value = CaUtil.createAuthorityInformationAccess(caIssuers, ocspUris);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
}
if (controls.containsKey(Extension.cRLDistributionPoints) || controls.containsKey(Extension.freshestCRL)) {
X500Name crlSignerSubject = (crlSignerCert == null) ? null : X500Name.getInstance(crlSignerCert.getSubjectX500Principal().getEncoded());
X500Name x500CaPrincipal = publicCaInfo.getX500Subject();
// CRLDistributionPoints
extType = Extension.cRLDistributionPoints;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
if (CollectionUtil.isNonEmpty(publicCaInfo.getCrlUris())) {
CRLDistPoint value = CaUtil.createCrlDistributionPoints(publicCaInfo.getCrlUris(), x500CaPrincipal, crlSignerSubject);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
}
// FreshestCRL
extType = Extension.freshestCRL;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
if (CollectionUtil.isNonEmpty(publicCaInfo.getDeltaCrlUris())) {
CRLDistPoint value = CaUtil.createCrlDistributionPoints(publicCaInfo.getDeltaCrlUris(), x500CaPrincipal, crlSignerSubject);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
}
}
// BasicConstraints
extType = Extension.basicConstraints;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
BasicConstraints value = CaUtil.createBasicConstraints(certprofile.getCertLevel(), certprofile.getPathLenBasicConstraint());
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// KeyUsage
extType = Extension.keyUsage;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
Set<KeyUsage> usages = new HashSet<>();
Set<KeyUsageControl> usageOccs = certprofile.getKeyUsage();
for (KeyUsageControl k : usageOccs) {
if (k.isRequired()) {
usages.add(k.getKeyUsage());
}
}
// the optional KeyUsage will only be set if requested explicitly
if (requestedExtensions != null && extControl.isRequest()) {
addRequestedKeyusage(usages, requestedExtensions, usageOccs);
}
org.bouncycastle.asn1.x509.KeyUsage value = X509Util.createKeyUsage(usages);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// ExtendedKeyUsage
extType = Extension.extendedKeyUsage;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
List<ASN1ObjectIdentifier> usages = new LinkedList<>();
Set<ExtKeyUsageControl> usageOccs = certprofile.getExtendedKeyUsages();
for (ExtKeyUsageControl k : usageOccs) {
if (k.isRequired()) {
usages.add(k.getExtKeyUsage());
}
}
// the optional ExtKeyUsage will only be set if requested explicitly
if (requestedExtensions != null && extControl.isRequest()) {
addRequestedExtKeyusage(usages, requestedExtensions, usageOccs);
}
if (extControl.isCritical() && usages.contains(ObjectIdentifiers.id_anyExtendedKeyUsage)) {
extControl = new ExtensionControl(false, extControl.isRequired(), extControl.isRequest());
}
ExtendedKeyUsage value = X509Util.createExtendedUsage(usages);
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// ocsp-nocheck
extType = ObjectIdentifiers.id_extension_pkix_ocsp_nocheck;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
// the extension ocsp-nocheck will only be set if requested explicitly
DERNull value = DERNull.INSTANCE;
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// SubjectInfoAccess
extType = Extension.subjectInfoAccess;
extControl = controls.remove(extType);
if (extControl != null && addMe(extType, extControl, neededExtTypes, wantedExtTypes)) {
ASN1Sequence value = null;
if (requestedExtensions != null && extControl.isRequest()) {
value = createSubjectInfoAccess(requestedExtensions, certprofile.getSubjectInfoAccessModes());
}
addExtension(values, extType, value, extControl, neededExtTypes, wantedExtTypes);
}
// remove extensions that are not required frrom the list
List<ASN1ObjectIdentifier> listToRm = null;
for (ASN1ObjectIdentifier extnType : controls.keySet()) {
ExtensionControl ctrl = controls.get(extnType);
if (ctrl.isRequired()) {
continue;
}
if (neededExtTypes.contains(extnType) || wantedExtTypes.contains(extnType)) {
continue;
}
if (listToRm == null) {
listToRm = new LinkedList<>();
}
listToRm.add(extnType);
}
if (listToRm != null) {
for (ASN1ObjectIdentifier extnType : listToRm) {
controls.remove(extnType);
}
}
ExtensionValues subvalues = certprofile.getExtensions(Collections.unmodifiableMap(controls), requestedSubject, grantedSubject, requestedExtensions, notBefore, notAfter, publicCaInfo);
Set<ASN1ObjectIdentifier> extTypes = new HashSet<>(controls.keySet());
for (ASN1ObjectIdentifier type : extTypes) {
extControl = controls.remove(type);
boolean addMe = addMe(type, extControl, neededExtTypes, wantedExtTypes);
if (addMe) {
ExtensionValue value = null;
if (requestedExtensions != null && extControl.isRequest()) {
Extension reqExt = requestedExtensions.getExtension(type);
if (reqExt != null) {
value = new ExtensionValue(reqExt.isCritical(), reqExt.getParsedValue());
}
}
if (value == null) {
value = subvalues.getExtensionValue(type);
}
addExtension(values, type, value, extControl, neededExtTypes, wantedExtTypes);
}
}
Set<ASN1ObjectIdentifier> unprocessedExtTypes = new HashSet<>();
for (ASN1ObjectIdentifier type : controls.keySet()) {
if (controls.get(type).isRequired()) {
unprocessedExtTypes.add(type);
}
}
if (CollectionUtil.isNonEmpty(unprocessedExtTypes)) {
throw new CertprofileException("could not add required extensions " + toString(unprocessedExtTypes));
}
if (CollectionUtil.isNonEmpty(neededExtTypes)) {
throw new BadCertTemplateException("could not add requested extensions " + toString(neededExtTypes));
}
return values;
}
use of com.github.zhenwei.core.asn1.x509.ExtendedKeyUsage in project xipki by xipki.
the class IdentifiedX509Certprofile method addRequestedExtKeyusage.
// method addRequestedKeyusage
private static void addRequestedExtKeyusage(List<ASN1ObjectIdentifier> usages, Extensions requestedExtensions, Set<ExtKeyUsageControl> usageOccs) {
Extension extension = requestedExtensions.getExtension(Extension.extendedKeyUsage);
if (extension == null) {
return;
}
ExtendedKeyUsage reqKeyUsage = ExtendedKeyUsage.getInstance(extension.getParsedValue());
for (ExtKeyUsageControl k : usageOccs) {
if (k.isRequired()) {
continue;
}
if (reqKeyUsage.hasKeyPurposeId(KeyPurposeId.getInstance(k.getExtKeyUsage()))) {
usages.add(k.getExtKeyUsage());
}
}
}
use of com.github.zhenwei.core.asn1.x509.ExtendedKeyUsage in project candlepin by candlepin.
the class BouncyCastlePKIUtility method createX509Certificate.
@Override
public X509Certificate createX509Certificate(String dn, Set<X509ExtensionWrapper> extensions, Set<X509ByteExtensionWrapper> byteExtensions, Date startDate, Date endDate, KeyPair clientKeyPair, BigInteger serialNumber, String alternateName) throws GeneralSecurityException, IOException {
X509Certificate caCert = reader.getCACert();
byte[] publicKeyEncoded = clientKeyPair.getPublic().getEncoded();
X509v3CertificateBuilder certGen = new X509v3CertificateBuilder(X500Name.getInstance(caCert.getSubjectX500Principal().getEncoded()), serialNumber, startDate, endDate, new X500Name(dn), SubjectPublicKeyInfo.getInstance(publicKeyEncoded));
// set key usage - required for proper x509 function
KeyUsage keyUsage = new KeyUsage(KeyUsage.digitalSignature | KeyUsage.keyEncipherment | KeyUsage.dataEncipherment);
// add SSL extensions - required for proper x509 function
NetscapeCertType certType = new NetscapeCertType(NetscapeCertType.sslClient | NetscapeCertType.smime);
certGen.addExtension(MiscObjectIdentifiers.netscapeCertType, false, certType);
certGen.addExtension(Extension.keyUsage, false, keyUsage);
JcaX509ExtensionUtils extensionUtil = new JcaX509ExtensionUtils();
AuthorityKeyIdentifier aki = extensionUtil.createAuthorityKeyIdentifier(caCert);
certGen.addExtension(Extension.authorityKeyIdentifier, false, aki.getEncoded());
certGen.addExtension(Extension.subjectKeyIdentifier, false, subjectKeyWriter.getSubjectKeyIdentifier(clientKeyPair, extensions));
certGen.addExtension(Extension.extendedKeyUsage, false, new ExtendedKeyUsage(KeyPurposeId.id_kp_clientAuth));
// Add an additional alternative name if provided.
if (alternateName != null) {
/*
Why add the certificate subject again as an alternative name? RFC 6125 Section 6.4.4
stipulates that if SANs are provided, a validator MUST use them instead of the certificate
subject. If no SANs are present, the RFC allows the validator to use the subject field. So,
if we do have an SAN to add, we need to add the subject field again as an SAN.
See http://stackoverflow.com/questions/5935369 and
https://tools.ietf.org/html/rfc6125#section-6.4.4 and
NB: These extensions should *not* be marked critical since the subject field is not empty.
*/
GeneralName subject = new GeneralName(GeneralName.directoryName, dn);
GeneralName name = new GeneralName(GeneralName.directoryName, "CN=" + alternateName);
ASN1Encodable[] altNameArray = { subject, name };
GeneralNames altNames = GeneralNames.getInstance(new DERSequence(altNameArray));
certGen.addExtension(Extension.subjectAlternativeName, false, altNames);
}
if (extensions != null) {
for (X509ExtensionWrapper wrapper : extensions) {
// Bouncycastle hates null values. So, set them to blank
// if they are null
String value = wrapper.getValue() == null ? "" : wrapper.getValue();
certGen.addExtension(wrapper.toASN1Primitive(), wrapper.isCritical(), new DERUTF8String(value));
}
}
if (byteExtensions != null) {
for (X509ByteExtensionWrapper wrapper : byteExtensions) {
// Bouncycastle hates null values. So, set them to blank
// if they are null
byte[] value = wrapper.getValue() == null ? new byte[0] : wrapper.getValue();
certGen.addExtension(wrapper.toASN1Primitive(), wrapper.isCritical(), new DEROctetString(value));
}
}
JcaContentSignerBuilder builder = new JcaContentSignerBuilder(SIGNATURE_ALGO).setProvider(BC_PROVIDER);
ContentSigner signer;
try {
signer = builder.build(reader.getCaKey());
} catch (OperatorCreationException e) {
throw new IOException(e);
}
// Generate the certificate
return new JcaX509CertificateConverter().getCertificate(certGen.build(signer));
}
use of com.github.zhenwei.core.asn1.x509.ExtendedKeyUsage in project xipki by xipki.
the class XmlX509Certprofile method getExtensions.
@Override
public ExtensionValues getExtensions(Map<ASN1ObjectIdentifier, ExtensionControl> extensionOccurences, X500Name requestedSubject, X500Name grantedSubject, Extensions requestedExtensions, Date notBefore, Date notAfter, PublicCaInfo caInfo) throws CertprofileException, BadCertTemplateException {
ExtensionValues values = new ExtensionValues();
if (CollectionUtil.isEmpty(extensionOccurences)) {
return values;
}
ParamUtil.requireNonNull("requestedSubject", requestedSubject);
ParamUtil.requireNonNull("notBefore", notBefore);
ParamUtil.requireNonNull("notAfter", notAfter);
Set<ASN1ObjectIdentifier> occurences = new HashSet<>(extensionOccurences.keySet());
// AuthorityKeyIdentifier
// processed by the CA
// SubjectKeyIdentifier
// processed by the CA
// KeyUsage
// processed by the CA
// CertificatePolicies
ASN1ObjectIdentifier type = Extension.certificatePolicies;
if (certificatePolicies != null) {
if (occurences.remove(type)) {
values.addExtension(type, certificatePolicies);
}
}
// Policy Mappings
type = Extension.policyMappings;
if (policyMappings != null) {
if (occurences.remove(type)) {
values.addExtension(type, policyMappings);
}
}
// SubjectAltName
type = Extension.subjectAlternativeName;
if (occurences.contains(type)) {
GeneralNames genNames = createRequestedSubjectAltNames(requestedSubject, grantedSubject, requestedExtensions);
if (genNames != null) {
ExtensionValue value = new ExtensionValue(extensionControls.get(type).isCritical(), genNames);
values.addExtension(type, value);
occurences.remove(type);
}
}
// IssuerAltName
// processed by the CA
// Subject Directory Attributes
type = Extension.subjectDirectoryAttributes;
if (occurences.contains(type) && subjectDirAttrsControl != null) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("no SubjectDirecotryAttributes extension is contained in the request");
}
ASN1GeneralizedTime dateOfBirth = null;
String placeOfBirth = null;
String gender = null;
List<String> countryOfCitizenshipList = new LinkedList<>();
List<String> countryOfResidenceList = new LinkedList<>();
Map<ASN1ObjectIdentifier, List<ASN1Encodable>> otherAttrs = new HashMap<>();
Vector<?> reqSubDirAttrs = SubjectDirectoryAttributes.getInstance(extension.getParsedValue()).getAttributes();
final int n = reqSubDirAttrs.size();
for (int i = 0; i < n; i++) {
Attribute attr = (Attribute) reqSubDirAttrs.get(i);
ASN1ObjectIdentifier attrType = attr.getAttrType();
ASN1Encodable attrVal = attr.getAttributeValues()[0];
if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
dateOfBirth = ASN1GeneralizedTime.getInstance(attrVal);
} else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
placeOfBirth = DirectoryString.getInstance(attrVal).getString();
} else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
gender = DERPrintableString.getInstance(attrVal).getString();
} else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
String country = DERPrintableString.getInstance(attrVal).getString();
countryOfCitizenshipList.add(country);
} else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
String country = DERPrintableString.getInstance(attrVal).getString();
countryOfResidenceList.add(country);
} else {
List<ASN1Encodable> otherAttrVals = otherAttrs.get(attrType);
if (otherAttrVals == null) {
otherAttrVals = new LinkedList<>();
otherAttrs.put(attrType, otherAttrVals);
}
otherAttrVals.add(attrVal);
}
}
Vector<Attribute> attrs = new Vector<>();
for (ASN1ObjectIdentifier attrType : subjectDirAttrsControl.getTypes()) {
if (ObjectIdentifiers.DN_DATE_OF_BIRTH.equals(attrType)) {
if (dateOfBirth != null) {
String timeStirng = dateOfBirth.getTimeString();
if (!SubjectDnSpec.PATTERN_DATE_OF_BIRTH.matcher(timeStirng).matches()) {
throw new BadCertTemplateException("invalid dateOfBirth " + timeStirng);
}
attrs.add(new Attribute(attrType, new DERSet(dateOfBirth)));
continue;
}
} else if (ObjectIdentifiers.DN_PLACE_OF_BIRTH.equals(attrType)) {
if (placeOfBirth != null) {
ASN1Encodable attrVal = new DERUTF8String(placeOfBirth);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
continue;
}
} else if (ObjectIdentifiers.DN_GENDER.equals(attrType)) {
if (gender != null && !gender.isEmpty()) {
char ch = gender.charAt(0);
if (!(gender.length() == 1 && (ch == 'f' || ch == 'F' || ch == 'm' || ch == 'M'))) {
throw new BadCertTemplateException("invalid gender " + gender);
}
ASN1Encodable attrVal = new DERPrintableString(gender);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
continue;
}
} else if (ObjectIdentifiers.DN_COUNTRY_OF_CITIZENSHIP.equals(attrType)) {
if (!countryOfCitizenshipList.isEmpty()) {
for (String country : countryOfCitizenshipList) {
if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
throw new BadCertTemplateException("invalid countryOfCitizenship code " + country);
}
ASN1Encodable attrVal = new DERPrintableString(country);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
} else if (ObjectIdentifiers.DN_COUNTRY_OF_RESIDENCE.equals(attrType)) {
if (!countryOfResidenceList.isEmpty()) {
for (String country : countryOfResidenceList) {
if (!SubjectDnSpec.isValidCountryAreaCode(country)) {
throw new BadCertTemplateException("invalid countryOfResidence code " + country);
}
ASN1Encodable attrVal = new DERPrintableString(country);
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
} else if (otherAttrs.containsKey(attrType)) {
for (ASN1Encodable attrVal : otherAttrs.get(attrType)) {
attrs.add(new Attribute(attrType, new DERSet(attrVal)));
}
continue;
}
throw new BadCertTemplateException("could not process type " + attrType.getId() + " in extension SubjectDirectoryAttributes");
}
SubjectDirectoryAttributes subjDirAttrs = new SubjectDirectoryAttributes(attrs);
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), subjDirAttrs);
values.addExtension(type, extValue);
occurences.remove(type);
}
// Basic Constraints
// processed by the CA
// Name Constraints
type = Extension.nameConstraints;
if (nameConstraints != null) {
if (occurences.remove(type)) {
values.addExtension(type, nameConstraints);
}
}
// PolicyConstrains
type = Extension.policyConstraints;
if (policyConstraints != null) {
if (occurences.remove(type)) {
values.addExtension(type, policyConstraints);
}
}
// ExtendedKeyUsage
// processed by CA
// CRL Distribution Points
// processed by the CA
// Inhibit anyPolicy
type = Extension.inhibitAnyPolicy;
if (inhibitAnyPolicy != null) {
if (occurences.remove(type)) {
values.addExtension(type, inhibitAnyPolicy);
}
}
// Freshest CRL
// processed by the CA
// Authority Information Access
// processed by the CA
// Subject Information Access
// processed by the CA
// Admission
type = ObjectIdentifiers.id_extension_admission;
if (occurences.contains(type) && admission != null) {
if (admission.isInputFromRequestRequired()) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("No Admission extension is contained in the request");
}
Admissions[] reqAdmissions = org.bouncycastle.asn1.isismtt.x509.AdmissionSyntax.getInstance(extension.getParsedValue()).getContentsOfAdmissions();
final int n = reqAdmissions.length;
List<List<String>> reqRegNumsList = new ArrayList<>(n);
for (int i = 0; i < n; i++) {
Admissions reqAdmission = reqAdmissions[i];
ProfessionInfo[] reqPis = reqAdmission.getProfessionInfos();
List<String> reqNums = new ArrayList<>(reqPis.length);
reqRegNumsList.add(reqNums);
for (ProfessionInfo reqPi : reqPis) {
String reqNum = reqPi.getRegistrationNumber();
reqNums.add(reqNum);
}
}
values.addExtension(type, admission.getExtensionValue(reqRegNumsList));
occurences.remove(type);
} else {
values.addExtension(type, admission.getExtensionValue(null));
occurences.remove(type);
}
}
// OCSP Nocheck
// processed by the CA
// restriction
type = ObjectIdentifiers.id_extension_restriction;
if (restriction != null) {
if (occurences.remove(type)) {
values.addExtension(type, restriction);
}
}
// AdditionalInformation
type = ObjectIdentifiers.id_extension_additionalInformation;
if (additionalInformation != null) {
if (occurences.remove(type)) {
values.addExtension(type, additionalInformation);
}
}
// ValidityModel
type = ObjectIdentifiers.id_extension_validityModel;
if (validityModel != null) {
if (occurences.remove(type)) {
values.addExtension(type, validityModel);
}
}
// PrivateKeyUsagePeriod
type = Extension.privateKeyUsagePeriod;
if (occurences.contains(type)) {
Date tmpNotAfter;
if (privateKeyUsagePeriod == null) {
tmpNotAfter = notAfter;
} else {
tmpNotAfter = privateKeyUsagePeriod.add(notBefore);
if (tmpNotAfter.after(notAfter)) {
tmpNotAfter = notAfter;
}
}
ASN1EncodableVector vec = new ASN1EncodableVector();
vec.add(new DERTaggedObject(false, 0, new DERGeneralizedTime(notBefore)));
vec.add(new DERTaggedObject(false, 1, new DERGeneralizedTime(tmpNotAfter)));
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
}
// QCStatements
type = Extension.qCStatements;
if (occurences.contains(type) && (qcStatments != null || qcStatementsOption != null)) {
if (qcStatments != null) {
values.addExtension(type, qcStatments);
occurences.remove(type);
} else if (requestedExtensions != null && qcStatementsOption != null) {
// extract the euLimit data from request
Extension extension = requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("No QCStatement extension is contained in the request");
}
ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
Map<String, int[]> qcEuLimits = new HashMap<>();
final int n = seq.size();
for (int i = 0; i < n; i++) {
QCStatement stmt = QCStatement.getInstance(seq.getObjectAt(i));
if (!ObjectIdentifiers.id_etsi_qcs_QcLimitValue.equals(stmt.getStatementId())) {
continue;
}
MonetaryValue monetaryValue = MonetaryValue.getInstance(stmt.getStatementInfo());
int amount = monetaryValue.getAmount().intValue();
int exponent = monetaryValue.getExponent().intValue();
Iso4217CurrencyCode currency = monetaryValue.getCurrency();
String currencyS = currency.isAlphabetic() ? currency.getAlphabetic().toUpperCase() : Integer.toString(currency.getNumeric());
qcEuLimits.put(currencyS, new int[] { amount, exponent });
}
ASN1EncodableVector vec = new ASN1EncodableVector();
for (QcStatementOption m : qcStatementsOption) {
if (m.getStatement() != null) {
vec.add(m.getStatement());
continue;
}
MonetaryValueOption monetaryOption = m.getMonetaryValueOption();
String currencyS = monetaryOption.getCurrencyString();
int[] limit = qcEuLimits.get(currencyS);
if (limit == null) {
throw new BadCertTemplateException("no EuLimitValue is specified for currency '" + currencyS + "'");
}
int amount = limit[0];
Range2Type range = monetaryOption.getAmountRange();
if (amount < range.getMin() || amount > range.getMax()) {
throw new BadCertTemplateException("amount for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
}
int exponent = limit[1];
range = monetaryOption.getExponentRange();
if (exponent < range.getMin() || exponent > range.getMax()) {
throw new BadCertTemplateException("exponent for currency '" + currencyS + "' is not within [" + range.getMin() + ", " + range.getMax() + "]");
}
MonetaryValue monetaryVale = new MonetaryValue(monetaryOption.getCurrency(), amount, exponent);
QCStatement qcStatment = new QCStatement(m.getStatementId(), monetaryVale);
vec.add(qcStatment);
}
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
} else {
throw new RuntimeException("should not reach here");
}
}
// BiometricData
type = Extension.biometricInfo;
if (occurences.contains(type) && biometricInfo != null) {
Extension extension = (requestedExtensions == null) ? null : requestedExtensions.getExtension(type);
if (extension == null) {
throw new BadCertTemplateException("no biometricInfo extension is contained in the request");
}
ASN1Sequence seq = ASN1Sequence.getInstance(extension.getParsedValue());
final int n = seq.size();
if (n < 1) {
throw new BadCertTemplateException("biometricInfo extension in request contains empty sequence");
}
ASN1EncodableVector vec = new ASN1EncodableVector();
for (int i = 0; i < n; i++) {
BiometricData bd = BiometricData.getInstance(seq.getObjectAt(i));
TypeOfBiometricData bdType = bd.getTypeOfBiometricData();
if (!biometricInfo.isTypePermitted(bdType)) {
throw new BadCertTemplateException("biometricInfo[" + i + "].typeOfBiometricData is not permitted");
}
ASN1ObjectIdentifier hashAlgo = bd.getHashAlgorithm().getAlgorithm();
if (!biometricInfo.isHashAlgorithmPermitted(hashAlgo)) {
throw new BadCertTemplateException("biometricInfo[" + i + "].hashAlgorithm is not permitted");
}
int expHashValueSize;
try {
expHashValueSize = AlgorithmUtil.getHashOutputSizeInOctets(hashAlgo);
} catch (NoSuchAlgorithmException ex) {
throw new CertprofileException("should not happen, unknown hash algorithm " + hashAlgo);
}
byte[] hashValue = bd.getBiometricDataHash().getOctets();
if (hashValue.length != expHashValueSize) {
throw new BadCertTemplateException("biometricInfo[" + i + "].biometricDataHash has incorrect length");
}
DERIA5String sourceDataUri = bd.getSourceDataUri();
switch(biometricInfo.getSourceDataUriOccurrence()) {
case FORBIDDEN:
sourceDataUri = null;
break;
case REQUIRED:
if (sourceDataUri == null) {
throw new BadCertTemplateException("biometricInfo[" + i + "].sourceDataUri is not specified in request but is required");
}
break;
case OPTIONAL:
break;
default:
throw new BadCertTemplateException("could not reach here, unknown tripleState");
}
AlgorithmIdentifier newHashAlg = new AlgorithmIdentifier(hashAlgo, DERNull.INSTANCE);
BiometricData newBiometricData = new BiometricData(bdType, newHashAlg, new DEROctetString(hashValue), sourceDataUri);
vec.add(newBiometricData);
}
ExtensionValue extValue = new ExtensionValue(extensionControls.get(type).isCritical(), new DERSequence(vec));
values.addExtension(type, extValue);
occurences.remove(type);
}
// TlsFeature
type = ObjectIdentifiers.id_pe_tlsfeature;
if (tlsFeature != null) {
if (occurences.remove(type)) {
values.addExtension(type, tlsFeature);
}
}
// AuthorizationTemplate
type = ObjectIdentifiers.id_xipki_ext_authorizationTemplate;
if (authorizationTemplate != null) {
if (occurences.remove(type)) {
values.addExtension(type, authorizationTemplate);
}
}
// SMIME
type = ObjectIdentifiers.id_smimeCapabilities;
if (smimeCapabilities != null) {
if (occurences.remove(type)) {
values.addExtension(type, smimeCapabilities);
}
}
// constant extensions
if (constantExtensions != null) {
for (ASN1ObjectIdentifier m : constantExtensions.keySet()) {
if (!occurences.remove(m)) {
continue;
}
ExtensionValue extensionValue = constantExtensions.get(m);
if (extensionValue != null) {
values.addExtension(m, extensionValue);
}
}
}
ExtensionValues extraExtensions = getExtraExtensions(extensionOccurences, requestedSubject, grantedSubject, requestedExtensions, notBefore, notAfter, caInfo);
if (extraExtensions != null) {
for (ASN1ObjectIdentifier m : extraExtensions.getExtensionTypes()) {
values.addExtension(m, extraExtensions.getExtensionValue(m));
}
}
return values;
}
Aggregations