Search in sources :

Example 1 with GrantedCertTemplate

use of org.xipki.ca.server.X509Ca.GrantedCertTemplate 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 GrantedCertTemplate

use of org.xipki.ca.server.X509Ca.GrantedCertTemplate 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)

Aggregations

BigInteger (java.math.BigInteger)2 InvalidKeySpecException (java.security.spec.InvalidKeySpecException)2 Date (java.util.Date)2 ASN1Integer (org.bouncycastle.asn1.ASN1Integer)2 ASN1ObjectIdentifier (org.bouncycastle.asn1.ASN1ObjectIdentifier)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 OperationException (org.xipki.ca.api.OperationException)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 NotAfterMode (org.xipki.ca.api.profile.NotAfterMode)2