use of org.xipki.util.Validity in project xipki by xipki.
the class GrandCertTemplateBuilder method create.
GrantedCertTemplate create(IdentifiedCertprofile certprofile, CertTemplateData certTemplate, RequestorInfo requestor, boolean update) throws OperationException {
if (caInfo.getRevocationInfo() != null) {
throw new OperationException(NOT_PERMITTED, "CA is revoked");
}
if (certprofile == null) {
throw new OperationException(UNKNOWN_CERT_PROFILE, "unknown cert profile " + certTemplate.getCertprofileName());
}
ConcurrentContentSigner signer = caInfo.getSigner(certprofile.getSignatureAlgorithms());
if (signer == null) {
throw new OperationException(SYSTEM_FAILURE, "CA does not support any signature algorithm restricted by the cert profile");
}
final NameId certprofileIdent = certprofile.getIdent();
if (certprofile.getVersion() != Certprofile.X509CertVersion.v3) {
throw new OperationException(SYSTEM_FAILURE, "unknown cert version " + certprofile.getVersion());
}
if (certprofile.isOnlyForRa()) {
if (requestor == null || !requestor.isRa()) {
throw new OperationException(NOT_PERMITTED, "profile " + certprofileIdent + " not applied to non-RA");
}
}
switch(certprofile.getCertLevel()) {
case RootCA:
throw new OperationException(NOT_PERMITTED, "CA is not allowed to generate Root CA certificate");
case SubCA:
Integer reqPathlen = certprofile.getPathLenBasicConstraint();
int caPathLen = caInfo.getPathLenConstraint();
boolean allowed = (reqPathlen == null && caPathLen == Integer.MAX_VALUE) || (reqPathlen != null && reqPathlen < caPathLen);
if (!allowed) {
throw new OperationException(NOT_PERMITTED, "invalid BasicConstraint.pathLenConstraint");
}
break;
default:
}
X500Name requestedSubject = CaUtil.removeEmptyRdns(certTemplate.getSubject());
if (!certprofile.isSerialNumberInReqPermitted()) {
RDN[] rdns = requestedSubject.getRDNs(ObjectIdentifiers.DN.SN);
if (rdns != null && rdns.length > 0) {
throw new OperationException(BAD_CERT_TEMPLATE, "subjectDN SerialNumber in request is not permitted");
}
}
Date reqNotBefore = certTemplate.getNotBefore();
Date grantedNotBefore = certprofile.getNotBefore(reqNotBefore);
// notBefore in the past is not permitted (due to the fact that some clients may not have
// accurate time, we allow max. 5 minutes in the past)
long currentMillis = System.currentTimeMillis();
if (currentMillis - grantedNotBefore.getTime() > MS_PER_10MINUTES) {
grantedNotBefore = new Date(currentMillis - MS_PER_10MINUTES);
}
long time = caInfo.getNoNewCertificateAfter();
if (grantedNotBefore.getTime() > time) {
throw new OperationException(NOT_PERMITTED, "CA is not permitted to issue certifate after " + new Date(time));
}
if (grantedNotBefore.before(caInfo.getNotBefore())) {
// notBefore may not be before CA's notBefore
grantedNotBefore = caInfo.getNotBefore();
}
PrivateKeyInfo privateKey;
SubjectPublicKeyInfo grantedPublicKeyInfo = certTemplate.getPublicKeyInfo();
if (grantedPublicKeyInfo != null) {
privateKey = null;
try {
grantedPublicKeyInfo = X509Util.toRfc3279Style(certTemplate.getPublicKeyInfo());
} catch (InvalidKeySpecException ex) {
LogUtil.warn(LOG, ex, "invalid SubjectPublicKeyInfo");
throw new OperationException(BAD_CERT_TEMPLATE, "invalid SubjectPublicKeyInfo");
}
// CHECK weak public key, like RSA key (ROCA)
if (grantedPublicKeyInfo.getAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) {
try {
ASN1Sequence seq = ASN1Sequence.getInstance(grantedPublicKeyInfo.getPublicKeyData().getOctets());
if (seq.size() != 2) {
throw new OperationException(BAD_CERT_TEMPLATE, "invalid format of RSA public key");
}
BigInteger modulus = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue();
if (RSABrokenKey.isAffected(modulus)) {
throw new OperationException(BAD_CERT_TEMPLATE, "RSA public key is too weak");
}
} catch (IllegalArgumentException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, "invalid format of RSA public key");
}
}
} else if (certTemplate.isCaGenerateKeypair()) {
KeypairGenControl kg = certprofile.getKeypairGenControl();
try {
if (kg instanceof KeypairGenControl.InheritCAKeypairGenControl) {
kg = keypairGenControlByImplictCA;
}
if (kg == null || kg instanceof KeypairGenControl.ForbiddenKeypairGenControl) {
throw new OperationException(BAD_CERT_TEMPLATE, "no public key is specified");
}
if (kg instanceof KeypairGenControl.RSAKeypairGenControl) {
KeypairGenControl.RSAKeypairGenControl tkg = (KeypairGenControl.RSAKeypairGenControl) kg;
int keysize = tkg.getKeysize();
if (keysize > 4096) {
throw new OperationException(BAD_CERT_TEMPLATE, "keysize too large");
}
BigInteger publicExponent = tkg.getPublicExponent();
KeyPair kp = KeyUtil.generateRSAKeypair(keysize, publicExponent, random);
java.security.interfaces.RSAPublicKey rsaPubKey = (java.security.interfaces.RSAPublicKey) kp.getPublic();
grantedPublicKeyInfo = new SubjectPublicKeyInfo(tkg.getKeyAlgorithm(), new RSAPublicKey(rsaPubKey.getModulus(), rsaPubKey.getPublicExponent()));
/*
* RSA private keys are BER-encoded according to PKCS #1’s RSAPrivateKey ASN.1 type.
*
* RSAPrivateKey ::= SEQUENCE {
* version Version,
* modulus INTEGER, -- n
* publicExponent INTEGER, -- e
* privateExponent INTEGER, -- d
* prime1 INTEGER, -- p
* prime2 INTEGER, -- q
* exponent1 INTEGER, -- d mod (p-1)
* exponent2 INTEGER, -- d mod (q-1)
* coefficient INTEGER, -- (inverse of q) mod p
* otherPrimeInfos OtherPrimeInfos OPTIONAL.
* }
*/
RSAPrivateCrtKey priv = (RSAPrivateCrtKey) kp.getPrivate();
privateKey = new PrivateKeyInfo(tkg.getKeyAlgorithm(), new RSAPrivateKey(priv.getModulus(), priv.getPublicExponent(), priv.getPrivateExponent(), priv.getPrimeP(), priv.getPrimeQ(), priv.getPrimeExponentP(), priv.getPrimeExponentQ(), priv.getCrtCoefficient()));
} else if (kg instanceof KeypairGenControl.ECKeypairGenControl) {
KeypairGenControl.ECKeypairGenControl tkg = (KeypairGenControl.ECKeypairGenControl) kg;
ASN1ObjectIdentifier curveOid = tkg.getCurveOid();
KeyPair kp = KeyUtil.generateECKeypair(curveOid, random);
ECPublicKey pub = (ECPublicKey) kp.getPublic();
int orderBitLength = pub.getParams().getOrder().bitLength();
byte[] keyData = KeyUtil.getUncompressedEncodedECPoint(pub.getW(), orderBitLength);
grantedPublicKeyInfo = new SubjectPublicKeyInfo(tkg.getKeyAlgorithm(), keyData);
/*
* ECPrivateKey ::= SEQUENCE {
* Version INTEGER { ecPrivkeyVer1(1) }
* (ecPrivkeyVer1),
* privateKey OCTET STRING,
* parameters [0] Parameters OPTIONAL,
* publicKey [1] BIT STRING OPTIONAL
* }
*
* Since the EC domain parameters are placed in the PKCS #8’s privateKeyAlgorithm field,
* the optional parameters field in an ECPrivateKey must be omitted. A Cryptoki
* application must be able to unwrap an ECPrivateKey that contains the optional publicKey
* field; however, what is done with this publicKey field is outside the scope of
* Cryptoki.
*/
ECPrivateKey priv = (ECPrivateKey) kp.getPrivate();
privateKey = new PrivateKeyInfo(tkg.getKeyAlgorithm(), new org.bouncycastle.asn1.sec.ECPrivateKey(orderBitLength, priv.getS()));
} else if (kg instanceof KeypairGenControl.DSAKeypairGenControl) {
KeypairGenControl.DSAKeypairGenControl tkg = (KeypairGenControl.DSAKeypairGenControl) kg;
KeyPair kp = KeyUtil.generateDSAKeypair(tkg.getParameterSpec(), random);
grantedPublicKeyInfo = new SubjectPublicKeyInfo(tkg.getKeyAlgorithm(), new ASN1Integer(((DSAPublicKey) kp.getPublic()).getY()));
// DSA private keys are represented as BER-encoded ASN.1 type INTEGER.
DSAPrivateKey priv = (DSAPrivateKey) kp.getPrivate();
privateKey = new PrivateKeyInfo(grantedPublicKeyInfo.getAlgorithm(), new ASN1Integer(priv.getX()));
} else if (kg instanceof KeypairGenControl.EDDSAKeypairGenControl) {
KeypairGenControl.EDDSAKeypairGenControl tkg = (KeypairGenControl.EDDSAKeypairGenControl) kg;
KeyPair kp = KeyUtil.generateEdECKeypair(tkg.getKeyAlgorithm().getAlgorithm(), random);
grantedPublicKeyInfo = KeyUtil.createSubjectPublicKeyInfo(kp.getPublic());
// make sure that the algorithm match
if (!grantedPublicKeyInfo.getAlgorithm().equals(tkg.getKeyAlgorithm())) {
throw new OperationException(SYSTEM_FAILURE, "invalid SubjectPublicKeyInfo.algorithm");
}
privateKey = PrivateKeyInfo.getInstance(kp.getPrivate().getEncoded());
} else {
throw new RuntimeCryptoException("unknown KeyPairGenControl " + kg);
}
} catch (InvalidAlgorithmParameterException | NoSuchAlgorithmException | NoSuchProviderException | InvalidKeyException | IOException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
} else {
// show not reach here
throw new OperationException(BAD_CERT_TEMPLATE, "no public key is specified genkey");
}
// public key
try {
grantedPublicKeyInfo = certprofile.checkPublicKey(grantedPublicKeyInfo);
} catch (CertprofileException ex) {
throw new OperationException(SYSTEM_FAILURE, "exception in cert profile " + certprofileIdent);
} catch (BadCertTemplateException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, ex);
}
// subject
Certprofile.SubjectInfo subjectInfo;
try {
subjectInfo = certprofile.getSubject(requestedSubject, grantedPublicKeyInfo);
} catch (CertprofileException ex) {
throw new OperationException(SYSTEM_FAILURE, "exception in cert profile " + certprofileIdent);
} catch (BadCertTemplateException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, ex);
}
X500Name grantedSubject = subjectInfo.getGrantedSubject();
// make sure that empty subject is not permitted
ASN1ObjectIdentifier[] attrTypes = grantedSubject.getAttributeTypes();
if (attrTypes == null || attrTypes.length == 0) {
throw new OperationException(BAD_CERT_TEMPLATE, "empty subject is not permitted");
}
// make sure that the grantedSubject does not equal the CA's subject
if (X509Util.canonicalizName(grantedSubject).equals(caInfo.getPublicCaInfo().getC14nSubject())) {
throw new OperationException(ALREADY_ISSUED, "certificate with the same subject as CA is not allowed");
}
if (update) {
CertStore.CertStatus certStatus = certstore.getCertStatusForSubject(caInfo.getIdent(), grantedSubject);
if (certStatus == CertStore.CertStatus.REVOKED) {
throw new OperationException(CERT_REVOKED);
} else if (certStatus == CertStore.CertStatus.UNKNOWN) {
throw new OperationException(UNKNOWN_CERT);
}
}
// end if(update)
StringBuilder msgBuilder = new StringBuilder();
if (subjectInfo.getWarning() != null) {
msgBuilder.append(", ").append(subjectInfo.getWarning());
}
Validity validity = certprofile.getValidity();
if (validity == null) {
validity = caInfo.getMaxValidity();
} else if (validity.compareTo(caInfo.getMaxValidity()) > 0) {
validity = caInfo.getMaxValidity();
}
Date maxNotAfter = validity.add(grantedNotBefore);
// maxNotAfter not after 99991231-235959
if (maxNotAfter.getTime() > MAX_CERT_TIME_MS) {
maxNotAfter = MAX_CERT_TIME;
}
Date grantedNotAfter = certTemplate.getNotAfter();
if (grantedNotAfter != null) {
if (grantedNotAfter.after(maxNotAfter)) {
grantedNotAfter = maxNotAfter;
msgBuilder.append(", notAfter modified");
}
} else {
grantedNotAfter = maxNotAfter;
}
if (grantedNotAfter.after(caInfo.getNotAfter())) {
ValidityMode caMode = caInfo.getValidityMode();
NotAfterMode profileMode = certprofile.getNotAfterMode();
if (profileMode == null) {
profileMode = NotAfterMode.BY_CA;
}
if (profileMode == NotAfterMode.STRICT) {
throw new OperationException(NOT_PERMITTED, "notAfter outside of CA's validity is not permitted by the CertProfile");
}
if (caMode == ValidityMode.STRICT) {
throw new OperationException(NOT_PERMITTED, "notAfter outside of CA's validity is not permitted by the CA");
}
if (caMode == ValidityMode.CUTOFF) {
grantedNotAfter = caInfo.getNotAfter();
} else if (caMode == ValidityMode.LAX) {
if (profileMode == NotAfterMode.CUTOFF) {
grantedNotAfter = caInfo.getNotAfter();
}
} else {
throw new IllegalStateException("should not reach here, CA ValidityMode " + caMode + " CertProfile NotAfterMode " + profileMode);
}
// end if (mode)
}
// end if (notAfter)
String warning = null;
if (msgBuilder.length() > 2) {
warning = msgBuilder.substring(2);
}
GrantedCertTemplate gct = new GrantedCertTemplate(certTemplate.getExtensions(), certprofile, grantedNotBefore, grantedNotAfter, requestedSubject, grantedPublicKeyInfo, privateKey, signer, warning);
gct.setGrantedSubject(grantedSubject);
return gct;
}
use of org.xipki.util.Validity in project xipki by xipki.
the class X509RevokerModule method revokeSuspendedCerts0.
private int revokeSuspendedCerts0() throws OperationException {
if (!masterMode) {
throw new OperationException(NOT_PERMITTED, "CA could not remove expired certificates in slave mode");
}
final int numEntries = 100;
Validity val = caInfo.revokeSuspendedCertsControl().getUnchangedSince();
long ms;
switch(val.getUnit()) {
case MINUTE:
ms = val.getValidity() * MS_PER_MINUTE;
break;
case HOUR:
ms = val.getValidity() * MS_PER_HOUR;
break;
case DAY:
ms = val.getValidity() * MS_PER_DAY;
break;
case WEEK:
ms = val.getValidity() * MS_PER_WEEK;
break;
case YEAR:
ms = val.getValidity() * 365 * MS_PER_DAY;
break;
default:
throw new IllegalStateException("should not reach here, unknown Validity Unit " + val.getUnit());
}
// seconds
final long latestLastUpdatedAt = (System.currentTimeMillis() - ms) / 1000;
final CrlReason reason = caInfo.revokeSuspendedCertsControl().getTargetReason();
int sum = 0;
while (true) {
List<SerialWithId> serials = certstore.getSuspendedCertSerials(caIdent, latestLastUpdatedAt, numEntries);
if (CollectionUtil.isEmpty(serials)) {
return sum;
}
for (SerialWithId serial : serials) {
boolean revoked;
try {
revoked = revokeSuspendedCert(serial, reason) != null;
if (revoked) {
sum++;
}
} catch (OperationException ex) {
LOG.info("revoked {} suspended certificates of CA {}", sum, caIdent.getName());
LogUtil.error(LOG, ex, "could not revoke suspended certificate with serial" + serial);
throw ex;
}
// end try
}
// end for
}
// end while (true)
}
use of org.xipki.util.Validity in project xipki by xipki.
the class GrandCertTemplateBuilder method create.
GrantedCertTemplate create(IdentifiedCertprofile certprofile, CertTemplateData certTemplate, RequestorInfo requestor, List<KeypairGenerator> keypairGenerators, boolean update) throws OperationException {
if (caInfo.getRevocationInfo() != null) {
throw new OperationException(NOT_PERMITTED, "CA is revoked");
}
if (certprofile == null) {
throw new OperationException(UNKNOWN_CERT_PROFILE, "unknown cert profile " + certTemplate.getCertprofileName());
}
ConcurrentContentSigner signer = caInfo.getSigner(certprofile.getSignatureAlgorithms());
if (signer == null) {
throw new OperationException(SYSTEM_FAILURE, "CA does not support any signature algorithm restricted by the cert profile");
}
final NameId certprofileIdent = certprofile.getIdent();
if (certprofile.getVersion() != Certprofile.X509CertVersion.v3) {
throw new OperationException(SYSTEM_FAILURE, "unknown cert version " + certprofile.getVersion());
}
if (certprofile.isOnlyForRa()) {
if (requestor == null || !requestor.isRa()) {
throw new OperationException(NOT_PERMITTED, "profile " + certprofileIdent + " not applied to non-RA");
}
}
switch(certprofile.getCertLevel()) {
case RootCA:
throw new OperationException(NOT_PERMITTED, "CA is not allowed to generate Root CA certificate");
case SubCA:
Integer reqPathlen = certprofile.getPathLenBasicConstraint();
int caPathLen = caInfo.getPathLenConstraint();
boolean allowed = (reqPathlen == null && caPathLen == Integer.MAX_VALUE) || (reqPathlen != null && reqPathlen < caPathLen);
if (!allowed) {
throw new OperationException(NOT_PERMITTED, "invalid BasicConstraint.pathLenConstraint");
}
break;
default:
}
X500Name requestedSubject = CaUtil.removeEmptyRdns(certTemplate.getSubject());
if (!certprofile.isSerialNumberInReqPermitted()) {
RDN[] rdns = requestedSubject.getRDNs(ObjectIdentifiers.DN.SN);
if (rdns != null && rdns.length > 0) {
throw new OperationException(BAD_CERT_TEMPLATE, "subjectDN SerialNumber in request is not permitted");
}
}
Date reqNotBefore = certTemplate.getNotBefore();
Date grantedNotBefore = certprofile.getNotBefore(reqNotBefore);
// notBefore in the past is not permitted (due to the fact that some clients may not have
// accurate time, we allow max. 5 minutes in the past)
long currentMillis = System.currentTimeMillis();
if (currentMillis - grantedNotBefore.getTime() > MS_PER_10MINUTES) {
grantedNotBefore = new Date(currentMillis - MS_PER_10MINUTES);
}
long time = caInfo.getNoNewCertificateAfter();
if (grantedNotBefore.getTime() > time) {
throw new OperationException(NOT_PERMITTED, "CA is not permitted to issue certificate after " + new Date(time));
}
if (grantedNotBefore.before(caInfo.getNotBefore())) {
// notBefore may not be before CA's notBefore
grantedNotBefore = caInfo.getNotBefore();
}
PrivateKeyInfo privateKey = null;
SubjectPublicKeyInfo grantedPublicKeyInfo = certTemplate.getPublicKeyInfo();
if (grantedPublicKeyInfo != null) {
try {
grantedPublicKeyInfo = X509Util.toRfc3279Style(certTemplate.getPublicKeyInfo());
} catch (InvalidKeySpecException ex) {
LogUtil.warn(LOG, ex, "invalid SubjectPublicKeyInfo");
throw new OperationException(BAD_CERT_TEMPLATE, "invalid SubjectPublicKeyInfo");
}
// CHECK weak public key, like RSA key (ROCA)
if (grantedPublicKeyInfo.getAlgorithm().getAlgorithm().equals(PKCSObjectIdentifiers.rsaEncryption)) {
try {
ASN1Sequence seq = ASN1Sequence.getInstance(grantedPublicKeyInfo.getPublicKeyData().getOctets());
if (seq.size() != 2) {
throw new OperationException(BAD_CERT_TEMPLATE, "invalid format of RSA public key");
}
BigInteger modulus = ASN1Integer.getInstance(seq.getObjectAt(0)).getPositiveValue();
if (RSABrokenKey.isAffected(modulus)) {
throw new OperationException(BAD_CERT_TEMPLATE, "RSA public key is too weak");
}
} catch (IllegalArgumentException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, "invalid format of RSA public key");
}
}
} else if (certTemplate.isCaGenerateKeypair()) {
KeypairGenControl kg = certprofile.getKeypairGenControl();
ASN1ObjectIdentifier keyAlgOid;
String keyspec;
if (kg == null || kg instanceof KeypairGenControl.ForbiddenKeypairGenControl) {
throw new OperationException(BAD_CERT_TEMPLATE, "no public key is specified");
}
if (kg instanceof KeypairGenControl.InheritCAKeypairGenControl) {
keyspec = keyspecByImplicitCA;
keyAlgOid = keyAlgOidByImplicitCA;
} else {
keyspec = kg.getKeyspec();
keyAlgOid = kg.getKeyAlgorithmOid();
}
KeypairGenerator keypairGenerator = null;
if (keypairGenerators != null) {
for (KeypairGenerator m : keypairGenerators) {
if (m.supports(keyspec)) {
keypairGenerator = m;
break;
}
}
}
if (keypairGenerator == null) {
throw new OperationException(SYSTEM_FAILURE, "found no keypair generator for keyspec " + keyspec);
}
String name = keypairGenerator.getName();
try {
privateKey = keypairGenerator.generateKeypair(keyspec);
LOG.info("generated keypair {} with generator {}", keyspec, name);
} catch (XiSecurityException ex) {
String msg = "error generating keypair " + keyspec + " using generator " + name;
LogUtil.error(LOG, ex, msg);
throw new OperationException(SYSTEM_FAILURE, msg);
}
// adapt the algorithm identifier in private key and public key
if (!privateKey.getPrivateKeyAlgorithm().getAlgorithm().equals(keyAlgOid)) {
ASN1BitString asn1PublicKeyData = privateKey.getPublicKeyData();
try {
privateKey = new PrivateKeyInfo(new AlgorithmIdentifier(keyAlgOid, privateKey.getPrivateKeyAlgorithm().getParameters()), privateKey.getPrivateKey().toASN1Primitive(), privateKey.getAttributes(), asn1PublicKeyData == null ? null : asn1PublicKeyData.getOctets());
} catch (IOException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
}
// construct SubjectPublicKeyInfo
String keyType = keyspec.split("/")[0].toUpperCase(Locale.ROOT);
byte[] publicKeyData;
switch(keyType) {
case "RSA":
{
RSAPrivateKey sk = RSAPrivateKey.getInstance(privateKey.getPrivateKey().getOctets());
try {
publicKeyData = new RSAPublicKey(sk.getModulus(), sk.getPublicExponent()).getEncoded();
} catch (IOException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
break;
}
case "EC":
{
ECPrivateKey sk = ECPrivateKey.getInstance(privateKey.getPrivateKey().getOctets());
publicKeyData = sk.getPublicKey().getBytes();
break;
}
case "DSA":
case "ED25519":
case "ED448":
case "X25519":
case "X448":
{
publicKeyData = privateKey.getPublicKeyData().getBytes();
break;
}
default:
throw new IllegalStateException("unknown key type " + keyType);
}
grantedPublicKeyInfo = new SubjectPublicKeyInfo(privateKey.getPrivateKeyAlgorithm(), publicKeyData);
try {
grantedPublicKeyInfo = X509Util.toRfc3279Style(grantedPublicKeyInfo);
} catch (InvalidKeySpecException ex) {
throw new OperationException(SYSTEM_FAILURE, ex);
}
} else {
// show not reach here
throw new OperationException(BAD_CERT_TEMPLATE, "no public key is specified");
}
// public key
try {
grantedPublicKeyInfo = certprofile.checkPublicKey(grantedPublicKeyInfo);
} catch (CertprofileException ex) {
throw new OperationException(SYSTEM_FAILURE, "exception in cert profile " + certprofileIdent);
} catch (BadCertTemplateException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, ex);
}
// subject
Certprofile.SubjectInfo subjectInfo;
try {
subjectInfo = certprofile.getSubject(requestedSubject, grantedPublicKeyInfo);
} catch (CertprofileException ex) {
throw new OperationException(SYSTEM_FAILURE, "exception in cert profile " + certprofileIdent);
} catch (BadCertTemplateException ex) {
throw new OperationException(BAD_CERT_TEMPLATE, ex);
}
X500Name grantedSubject = subjectInfo.getGrantedSubject();
// make sure that empty subject is not permitted
ASN1ObjectIdentifier[] attrTypes = grantedSubject.getAttributeTypes();
if (attrTypes == null || attrTypes.length == 0) {
throw new OperationException(BAD_CERT_TEMPLATE, "empty subject is not permitted");
}
// make sure that the grantedSubject does not equal the CA's subject
if (X509Util.canonicalizName(grantedSubject).equals(caInfo.getPublicCaInfo().getC14nSubject())) {
throw new OperationException(ALREADY_ISSUED, "certificate with the same subject as CA is not allowed");
}
if (update) {
CertStore.CertStatus certStatus = certstore.getCertStatusForSubject(caInfo.getIdent(), grantedSubject);
if (certStatus == CertStore.CertStatus.REVOKED) {
throw new OperationException(CERT_REVOKED);
} else if (certStatus == CertStore.CertStatus.UNKNOWN) {
throw new OperationException(UNKNOWN_CERT);
}
}
// end if(update)
StringBuilder msgBuilder = new StringBuilder();
if (subjectInfo.getWarning() != null) {
msgBuilder.append(", ").append(subjectInfo.getWarning());
}
Validity validity = certprofile.getValidity();
if (validity == null) {
validity = caInfo.getMaxValidity();
} else if (validity.compareTo(caInfo.getMaxValidity()) > 0) {
validity = caInfo.getMaxValidity();
}
Date maxNotAfter = validity.add(grantedNotBefore);
// maxNotAfter not after 99991231-235959
if (maxNotAfter.getTime() > MAX_CERT_TIME_MS) {
maxNotAfter = MAX_CERT_TIME;
}
Date grantedNotAfter = certTemplate.getNotAfter();
if (grantedNotAfter != null) {
if (grantedNotAfter.after(maxNotAfter)) {
grantedNotAfter = maxNotAfter;
msgBuilder.append(", notAfter modified");
}
} else {
grantedNotAfter = maxNotAfter;
}
if (grantedNotAfter.after(caInfo.getNotAfter())) {
ValidityMode caMode = caInfo.getValidityMode();
NotAfterMode profileMode = certprofile.getNotAfterMode();
if (profileMode == null) {
profileMode = NotAfterMode.BY_CA;
}
if (profileMode == NotAfterMode.STRICT) {
throw new OperationException(NOT_PERMITTED, "notAfter outside of CA's validity is not permitted by the CertProfile");
}
if (caMode == ValidityMode.STRICT) {
throw new OperationException(NOT_PERMITTED, "notAfter outside of CA's validity is not permitted by the CA");
}
if (caMode == ValidityMode.CUTOFF) {
grantedNotAfter = caInfo.getNotAfter();
} else if (caMode == ValidityMode.LAX) {
if (profileMode == NotAfterMode.CUTOFF) {
grantedNotAfter = caInfo.getNotAfter();
}
} else {
throw new IllegalStateException("should not reach here, CA ValidityMode " + caMode + " CertProfile NotAfterMode " + profileMode);
}
// end if (mode)
}
// end if (notAfter)
String warning = null;
if (msgBuilder.length() > 2) {
warning = msgBuilder.substring(2);
}
GrantedCertTemplate gct = new GrantedCertTemplate(certTemplate.getExtensions(), certprofile, grantedNotBefore, grantedNotAfter, requestedSubject, grantedPublicKeyInfo, privateKey, signer, warning);
gct.setGrantedSubject(grantedSubject);
return gct;
}
use of org.xipki.util.Validity in project xipki by xipki.
the class CertprofileValidator method validateCABForumBR.
// method validate
private static void validateCABForumBR(Certprofile certprofile, StringBuilder msg) {
// Subject only one entries in a RDN is allowed
SubjectControl subjectCtl = certprofile.getSubjectControl();
if (CollectionUtil.isNotEmpty(subjectCtl.getGroups())) {
msg.append("multiple AttributeAndTypes in one RDN is not permitted, ");
}
for (ASN1ObjectIdentifier m : subjectCtl.getTypes()) {
RdnControl ctl = subjectCtl.getControl(m);
if (ctl.getMaxOccurs() > 1) {
msg.append("multiple RDNs of the same type are not permitted, ");
}
}
CertLevel certLevel = certprofile.getCertLevel();
// validity
if (certLevel == CertLevel.EndEntity) {
Validity validity = certprofile.getValidity();
if (validity.compareTo(maxCabEeValidity) > 0) {
msg.append("validity exceeds the maximal validity of subscriber certificate, ");
}
}
// Signature/hash algorithm
List<SignAlgo> sigAlgos = certprofile.getSignatureAlgorithms();
if (sigAlgos == null) {
msg.append("signature algorithms not defined, ");
} else {
List<HashAlgo> allowedHashAlgos = Arrays.asList(HashAlgo.SHA256, HashAlgo.SHA384, HashAlgo.SHA512);
for (SignAlgo signAlgo : sigAlgos) {
HashAlgo hashAlgo = signAlgo.getHashAlgo();
if (!allowedHashAlgos.contains(hashAlgo)) {
msg.append("unpermitted hash algorithm ").append(hashAlgo).append(", ");
}
}
}
// Public Key
Map<ASN1ObjectIdentifier, KeyParametersOption> keyAlgorithms = certprofile.getKeyAlgorithms();
if (CollectionUtil.isEmpty(keyAlgorithms)) {
msg.append("keyAlgorithms is not configured, ");
} else {
for (Entry<ASN1ObjectIdentifier, KeyParametersOption> entry : keyAlgorithms.entrySet()) {
ASN1ObjectIdentifier m = entry.getKey();
KeyParametersOption opt = entry.getValue();
if (m.equals(PKCSObjectIdentifiers.rsaEncryption)) {
if (opt instanceof RSAParametersOption) {
if (((RSAParametersOption) opt).allowsModulusLength(2048 - 1)) {
msg.append("minimum RSA modulus size 2048 bit not satisfied, ");
}
} else {
msg.append("unpermitted RSA modulus are configured, ");
}
} else if (m.equals(X9ObjectIdentifiers.id_ecPublicKey)) {
if (opt instanceof ECParamatersOption) {
Set<ASN1ObjectIdentifier> curveOids = new HashSet<>(((ECParamatersOption) opt).getCurveOids());
curveOids.remove(SECObjectIdentifiers.secp256r1);
curveOids.remove(SECObjectIdentifiers.secp384r1);
curveOids.remove(SECObjectIdentifiers.secp521r1);
if (!curveOids.isEmpty()) {
msg.append("EC curves ").append(curveOids).append(" are not permitted, ");
}
} else {
msg.append("unpermitted EC curves are configured, ");
}
} else if (m.equals(X9ObjectIdentifiers.id_dsa)) {
if (opt instanceof DSAParametersOption) {
DSAParametersOption dsaOpt = (DSAParametersOption) opt;
if (dsaOpt.allowsPlength(2048 - 1)) {
msg.append("minimum L (2048) not satisfied, ");
}
if (dsaOpt.allowsQlength(224 - 1)) {
msg.append("minimum N (224) not satisfied, ");
}
} else {
msg.append("unpermitted DSA (p,q) are configured, ");
}
} else {
msg.append("keyAlgorithm ").append(m.getId()).append(" is not permitted, ");
}
}
}
// CRLDistributionPoints
if (certLevel != CertLevel.RootCA) {
CrlDistributionPointsControl crlDpControl = certprofile.getCrlDpControl();
if (crlDpControl != null) {
Set<String> protocols = crlDpControl.getProtocols();
if (protocols == null || protocols.size() != 1 || !protocols.contains("http")) {
msg.append("CRLDistributionPoints allows protocol other than http, ");
}
}
// FreshestCRLDistributionPoints
CrlDistributionPointsControl freshestCrlControl = certprofile.getFreshestCrlControl();
if (freshestCrlControl != null) {
Set<String> protocols = freshestCrlControl.getProtocols();
if (protocols == null || protocols.size() != 1 || !protocols.contains("http")) {
msg.append("FreshestCRL allows protocol other than http, ");
}
}
// AuthorityInfoAccess*
AuthorityInfoAccessControl aiaControl = certprofile.getAiaControl();
if (aiaControl != null) {
if (!aiaControl.isIncludesOcsp()) {
msg.append("access method id-ad-ocsp is not configured, ");
} else {
Set<String> protocols = aiaControl.getOcspProtocols();
if (protocols == null || protocols.size() != 1 || !protocols.contains("http")) {
msg.append("AIA OCSP allows protocol other than http, ");
}
}
if (!aiaControl.isIncludesCaIssuers()) {
msg.append("access method id-ad-caIssuers is not configured, ");
} else {
Set<String> protocols = aiaControl.getCaIssuersProtocols();
if (protocols == null || protocols.size() != 1 || !protocols.contains("http")) {
msg.append("AIA CAIssuers allows protocol other than http, ");
}
}
}
}
// Certificate Policies
if (certLevel == CertLevel.SubCA || certLevel == CertLevel.EndEntity) {
CertificatePolicies certPolicyValue = certprofile.getCertificatePolicies();
if (certPolicyValue == null) {
msg.append("CertificatePolicies is not configured, ");
}
}
// KeyUsage
Set<KeyUsageControl> usages = certprofile.getKeyUsage();
if (certLevel == CertLevel.RootCA || certLevel == CertLevel.SubCA) {
if (!containsKeyusage(usages, KeyUsage.cRLSign)) {
msg.append("RootCA profile does contain keyUsage ").append(KeyUsage.cRLSign).append(", ");
}
} else if (certLevel == CertLevel.EndEntity) {
if (containsKeyusage(usages, KeyUsage.cRLSign)) {
msg.append("EndEntity profile must not contain keyUsage ").append(KeyUsage.cRLSign).append(", ");
}
}
// ExtendedKeyUsage
Set<ExtKeyUsageControl> ekuControls = certprofile.getExtendedKeyUsages();
if (certLevel == CertLevel.EndEntity) {
// ekuControls could not be null here.
boolean xkuTlsServerRequired = false;
boolean xkuTlsClientRequired = false;
for (ExtKeyUsageControl m : ekuControls) {
ASN1ObjectIdentifier oid = m.getExtKeyUsage();
if (m.isRequired()) {
if (XKU.id_kp_serverAuth.equals(oid)) {
xkuTlsServerRequired = true;
} else if (XKU.id_kp_clientAuth.equals(oid)) {
xkuTlsClientRequired = true;
}
}
if (!(XKU.id_kp_serverAuth.equals(oid) || XKU.id_kp_clientAuth.equals(oid) || XKU.id_kp_emailProtection.equals(oid))) {
msg.append("extendedKeyUsage ").append(oid.getId()).append(" is not permitted, ");
}
}
if (!(xkuTlsClientRequired | xkuTlsServerRequired)) {
msg.append("none of ").append(XKU.id_kp_clientAuth).append(" and ").append(XKU.id_kp_serverAuth).append(" is not configured, ");
}
} else {
if (ekuControls != null) {
for (ExtKeyUsageControl m : ekuControls) {
if (m.getExtKeyUsage().equals(XKU.id_kp_anyExtendedKeyUsage)) {
msg.append(XKU.id_kp_clientAuth).append(" is not allowed, ");
}
}
}
}
}
use of org.xipki.util.Validity in project xipki by xipki.
the class O2tChecker method checkExtnPrivateKeyUsagePeriod.
// method checkExtnMappings
void checkExtnPrivateKeyUsagePeriod(StringBuilder failureMsg, byte[] extnValue, Date certNotBefore, Date certNotAfter) {
ASN1GeneralizedTime notBefore = new ASN1GeneralizedTime(certNotBefore);
Date dateNotAfter;
Validity privateKeyUsagePeriod = getCertprofile().extensions().getPrivateKeyUsagePeriod();
if (privateKeyUsagePeriod == null) {
dateNotAfter = certNotAfter;
} else {
dateNotAfter = privateKeyUsagePeriod.add(certNotBefore);
if (dateNotAfter.after(certNotAfter)) {
dateNotAfter = certNotAfter;
}
}
ASN1GeneralizedTime notAfter = new ASN1GeneralizedTime(dateNotAfter);
org.bouncycastle.asn1.x509.PrivateKeyUsagePeriod extValue = org.bouncycastle.asn1.x509.PrivateKeyUsagePeriod.getInstance(extnValue);
ASN1GeneralizedTime time = extValue.getNotBefore();
if (time == null) {
failureMsg.append("notBefore is absent but expected present; ");
} else if (!time.equals(notBefore)) {
addViolation(failureMsg, "notBefore", time.getTimeString(), notBefore.getTimeString());
}
time = extValue.getNotAfter();
if (time == null) {
failureMsg.append("notAfter is absent but expected present; ");
} else if (!time.equals(notAfter)) {
addViolation(failureMsg, "notAfter", time.getTimeString(), notAfter.getTimeString());
}
}
Aggregations