Search in sources :

Example 1 with Validity

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;
}
Also used : Certprofile(org.xipki.ca.api.profile.Certprofile) NameId(org.xipki.ca.api.NameId) X500Name(org.bouncycastle.asn1.x500.X500Name) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) KeypairGenControl(org.xipki.ca.api.profile.KeypairGenControl) ValidityMode(org.xipki.ca.api.mgmt.ValidityMode) RSAPublicKey(org.bouncycastle.asn1.pkcs.RSAPublicKey) CertprofileException(org.xipki.ca.api.profile.CertprofileException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) GrantedCertTemplate(org.xipki.ca.server.X509Ca.GrantedCertTemplate) OperationException(org.xipki.ca.api.OperationException) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) BigInteger(java.math.BigInteger) RSAPrivateKey(org.bouncycastle.asn1.pkcs.RSAPrivateKey) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier) java.security(java.security) RDN(org.bouncycastle.asn1.x500.RDN) java.security.interfaces(java.security.interfaces) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) NotAfterMode(org.xipki.ca.api.profile.NotAfterMode) Date(java.util.Date) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) BigInteger(java.math.BigInteger) Validity(org.xipki.util.Validity) RuntimeCryptoException(org.bouncycastle.crypto.RuntimeCryptoException) ConcurrentContentSigner(org.xipki.security.ConcurrentContentSigner) CertStore(org.xipki.ca.server.db.CertStore) PrivateKeyInfo(org.bouncycastle.asn1.pkcs.PrivateKeyInfo)

Example 2 with Validity

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)
}
Also used : Validity(org.xipki.util.Validity) SerialWithId(org.xipki.ca.server.db.CertStore.SerialWithId) CrlReason(org.xipki.security.CrlReason) OperationException(org.xipki.ca.api.OperationException)

Example 3 with Validity

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;
}
Also used : Certprofile(org.xipki.ca.api.profile.Certprofile) NameId(org.xipki.ca.api.NameId) X500Name(org.bouncycastle.asn1.x500.X500Name) ASN1BitString(org.bouncycastle.asn1.ASN1BitString) SubjectPublicKeyInfo(org.bouncycastle.asn1.x509.SubjectPublicKeyInfo) ASN1BitString(org.bouncycastle.asn1.ASN1BitString) AlgorithmIdentifier(org.bouncycastle.asn1.x509.AlgorithmIdentifier) KeypairGenControl(org.xipki.ca.api.profile.KeypairGenControl) XiSecurityException(org.xipki.security.XiSecurityException) ValidityMode(org.xipki.ca.api.mgmt.ValidityMode) RSAPublicKey(org.bouncycastle.asn1.pkcs.RSAPublicKey) CertprofileException(org.xipki.ca.api.profile.CertprofileException) InvalidKeySpecException(java.security.spec.InvalidKeySpecException) GrantedCertTemplate(org.xipki.ca.server.X509Ca.GrantedCertTemplate) RDN(org.bouncycastle.asn1.x500.RDN) OperationException(org.xipki.ca.api.OperationException) ECPrivateKey(org.bouncycastle.asn1.sec.ECPrivateKey) KeypairGenerator(org.xipki.security.KeypairGenerator) IOException(java.io.IOException) NotAfterMode(org.xipki.ca.api.profile.NotAfterMode) Date(java.util.Date) ASN1Integer(org.bouncycastle.asn1.ASN1Integer) BigInteger(java.math.BigInteger) Validity(org.xipki.util.Validity) ConcurrentContentSigner(org.xipki.security.ConcurrentContentSigner) ASN1Sequence(org.bouncycastle.asn1.ASN1Sequence) BadCertTemplateException(org.xipki.ca.api.BadCertTemplateException) BigInteger(java.math.BigInteger) RSAPrivateKey(org.bouncycastle.asn1.pkcs.RSAPrivateKey) CertStore(org.xipki.ca.server.db.CertStore) PrivateKeyInfo(org.bouncycastle.asn1.pkcs.PrivateKeyInfo) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 4 with Validity

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, ");
                }
            }
        }
    }
}
Also used : RSAParametersOption(org.xipki.ca.api.profile.KeyParametersOption.RSAParametersOption) ECParamatersOption(org.xipki.ca.api.profile.KeyParametersOption.ECParamatersOption) DSAParametersOption(org.xipki.ca.api.profile.KeyParametersOption.DSAParametersOption) Validity(org.xipki.util.Validity) KeyParametersOption(org.xipki.ca.api.profile.KeyParametersOption) CertificatePolicies(org.bouncycastle.asn1.x509.CertificatePolicies) ASN1ObjectIdentifier(org.bouncycastle.asn1.ASN1ObjectIdentifier)

Example 5 with Validity

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());
    }
}
Also used : Validity(org.xipki.util.Validity) org.bouncycastle.asn1.x509(org.bouncycastle.asn1.x509)

Aggregations

Validity (org.xipki.util.Validity)5 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)3 OperationException (org.xipki.ca.api.OperationException)3 BigInteger (java.math.BigInteger)2 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)2 Date (java.util.Date)2 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)2 ASN1Sequence (org.bouncycastle.asn1.ASN1Sequence)2 PrivateKeyInfo (org.bouncycastle.asn1.pkcs.PrivateKeyInfo)2 RSAPrivateKey (org.bouncycastle.asn1.pkcs.RSAPrivateKey)2 RSAPublicKey (org.bouncycastle.asn1.pkcs.RSAPublicKey)2 RDN (org.bouncycastle.asn1.x500.RDN)2 X500Name (org.bouncycastle.asn1.x500.X500Name)2 SubjectPublicKeyInfo (org.bouncycastle.asn1.x509.SubjectPublicKeyInfo)2 BadCertTemplateException (org.xipki.ca.api.BadCertTemplateException)2 NameId (org.xipki.ca.api.NameId)2 ValidityMode (org.xipki.ca.api.mgmt.ValidityMode)2 Certprofile (org.xipki.ca.api.profile.Certprofile)2 CertprofileException (org.xipki.ca.api.profile.CertprofileException)2 KeypairGenControl (org.xipki.ca.api.profile.KeypairGenControl)2