aboutsummaryrefslogtreecommitdiffstats
path: root/certService/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'certService/src/main/java')
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java2
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java9
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java11
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/certification/model/CertificateUpdateModel.java24
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java17
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java82
-rw-r--r--certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java15
7 files changed, 144 insertions, 16 deletions
diff --git a/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java b/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java
index d21b1eb5..9f877788 100644
--- a/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java
+++ b/certService/src/main/java/org/onap/oom/certservice/api/CertificationController.java
@@ -112,7 +112,7 @@ public class CertificationController {
@RequestHeader("PK") String encodedPrivateKey,
@RequestHeader("OLD_CERT") String encodedOldCert,
@RequestHeader("OLD_PK") String encodedOldPrivateKey
- ) throws DecryptionException, CertificateDecryptionException {
+ ) throws DecryptionException, CmpClientException, CertificateDecryptionException {
caName = replaceWhiteSpaceChars(caName);
LOGGER.info("Received certificate update request for CA named: {}", caName);
CertificateUpdateModel certificateUpdateModel = new CertificateUpdateModel.CertificateUpdateModelBuilder()
diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java
index d5d9d9b8..a5076a38 100644
--- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java
+++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationModelFactory.java
@@ -76,7 +76,7 @@ public class CertificationModelFactory {
}
public CertificationModel createCertificationModel(CertificateUpdateModel certificateUpdateModel)
- throws DecryptionException, CertificateDecryptionException {
+ throws DecryptionException, CmpClientException, CertificateDecryptionException {
LOGGER.info("CSR: " + certificateUpdateModel.getEncodedCsr() +
", old cert: " + certificateUpdateModel.getEncodedOldCert() +
", CA: " + certificateUpdateModel.getCaName());
@@ -87,10 +87,15 @@ public class CertificationModelFactory {
final X509CertificateModel certificateModel = x509CertificateModelFactory.createCertificateModel(
new StringBase64(certificateUpdateModel.getEncodedOldCert()));
+ Cmpv2Server cmpv2Server = cmpv2ServerProvider.getCmpv2Server(certificateUpdateModel.getCaName());
+ LOGGER.debug("Found server for given CA name: \n{}", cmpv2Server);
+ LOGGER.info("Sending update request for certification model for CA named: {}, and certificate update request:\n{}",
+ certificateUpdateModel.getCaName(), csrModel);
+
if (updateRequestTypeDetector.isKur(csrModel.getCertificateData(), certificateModel.getCertificateData())) {
LOGGER.info(
"Certificate Signing Request and Old Certificate have the same parameters. Preparing Key Update Request");
- throw new UnsupportedOperationException("TODO: implement KUR in separate MR");
+ return certificationProvider.updateCertificate(csrModel, cmpv2Server, certificateUpdateModel);
} else {
LOGGER.info(
"Certificate Signing Request and Old Certificate have different parameters. Preparing Certification Request");
diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java
index 91148a22..bfa83103 100644
--- a/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java
+++ b/certService/src/main/java/org/onap/oom/certservice/certification/CertificationProvider.java
@@ -2,7 +2,7 @@
* ============LICENSE_START=======================================================
* Cert Service
* ================================================================================
- * Copyright (C) 2020 Nokia. All rights reserved.
+ * Copyright (C) 2020-2021 Nokia. All rights reserved.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -24,6 +24,7 @@ import org.bouncycastle.openssl.jcajce.JcaMiscPEMGenerator;
import org.bouncycastle.util.io.pem.PemObjectGenerator;
import org.bouncycastle.util.io.pem.PemWriter;
import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server;
+import org.onap.oom.certservice.certification.model.CertificateUpdateModel;
import org.onap.oom.certservice.certification.model.CertificationModel;
import org.onap.oom.certservice.certification.model.CsrModel;
import org.onap.oom.certservice.cmpv2client.api.CmpClient;
@@ -59,6 +60,13 @@ public class CertificationProvider {
convertFromX509CertificateListToPemList(certificates.getTrustedCertificates()));
}
+ public CertificationModel updateCertificate(CsrModel csrModel, Cmpv2Server cmpv2Server,
+ CertificateUpdateModel certificateUpdateModel) throws CmpClientException {
+ Cmpv2CertificationModel certificates = cmpClient.updateCertificate(csrModel, cmpv2Server, certificateUpdateModel);
+ return new CertificationModel(convertFromX509CertificateListToPemList(certificates.getCertificateChain()),
+ convertFromX509CertificateListToPemList(certificates.getTrustedCertificates()));
+ }
+
private static List<String> convertFromX509CertificateListToPemList(List<X509Certificate> certificates) {
return certificates.stream().map(CertificationProvider::convertFromX509CertificateToPem).filter(cert -> !cert.isEmpty())
.collect(Collectors.toList());
@@ -74,5 +82,4 @@ public class CertificationProvider {
}
return sw.toString();
}
-
}
diff --git a/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificateUpdateModel.java b/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificateUpdateModel.java
index 699ffe71..9423af52 100644
--- a/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificateUpdateModel.java
+++ b/certService/src/main/java/org/onap/oom/certservice/certification/model/CertificateUpdateModel.java
@@ -20,7 +20,16 @@
package org.onap.oom.certservice.certification.model;
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Objects;
+import org.bouncycastle.util.io.pem.PemObject;
+import org.onap.oom.certservice.certification.PemObjectFactory;
+import org.onap.oom.certservice.certification.StringBase64;
+import org.onap.oom.certservice.certification.exception.KeyDecryptionException;
public final class CertificateUpdateModel {
@@ -29,6 +38,7 @@ public final class CertificateUpdateModel {
private final String encodedOldCert;
private final String encodedOldPrivateKey;
private final String caName;
+ private static final PemObjectFactory PEM_OBJECT_FACTORY = new PemObjectFactory();
private CertificateUpdateModel(String encodedCsr, String encodedPrivateKey, String encodedOldCert,
String encodedOldPrivateKey, String caName) {
@@ -59,6 +69,20 @@ public final class CertificateUpdateModel {
return caName;
}
+ public PrivateKey getOldPrivateKeyObject()
+ throws KeyDecryptionException, InvalidKeySpecException, NoSuchAlgorithmException {
+
+ StringBase64 stringBase64 = new StringBase64(encodedOldPrivateKey);
+ PemObject pemObject = stringBase64.asString()
+ .flatMap(PEM_OBJECT_FACTORY::createPemObject)
+ .orElseThrow(
+ () -> new KeyDecryptionException("Incorrect Key, decryption failed")
+ );
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pemObject.getContent());
+ KeyFactory keyFactory = KeyFactory.getInstance("RSA");
+ return keyFactory.generatePrivate(keySpec);
+ }
+
@Override
public boolean equals(Object o) {
if (this == o) return true;
diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java
index d525c6e3..5ded3056 100644
--- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java
+++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/api/CmpClient.java
@@ -1,6 +1,7 @@
/*-
* ============LICENSE_START=======================================================
* Copyright (C) 2020 Nordix Foundation.
+ * Copyright (C) 2021 Nokia.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -23,6 +24,7 @@ package org.onap.oom.certservice.cmpv2client.api;
import java.util.Date;
import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server;
+import org.onap.oom.certservice.certification.model.CertificateUpdateModel;
import org.onap.oom.certservice.certification.model.CsrModel;
import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException;
import org.onap.oom.certservice.cmpv2client.model.Cmpv2CertificationModel;
@@ -71,4 +73,19 @@ public interface CmpClient {
CsrModel csrModel,
Cmpv2Server server)
throws CmpClientException;
+
+ /**
+ * Requests for a External Root CA Certificate to be updated for the passed keyPair wrapped
+ * in a CSRMeta with common details. Authentication using End Entity Certificate. Old certificate and old privateKey
+ * are wrapped in CertificateUpdateModel.class
+ * Exception thrown if verification fails or issue encountered in fetching certificate from CA.
+ *
+ * @param csrModel Certificate Signing Request Model. Must not be {@code null}.
+ * @param cmpv2Server CMPv2 server. Must not be {@code null}.
+ * @param certificateUpdateModel Model with key update parameters {@code null}.
+ * @return model for certification containing certificate chain and trusted certificates
+ * @throws CmpClientException if client error occurs.
+ */
+ Cmpv2CertificationModel updateCertificate(CsrModel csrModel, Cmpv2Server cmpv2Server,
+ CertificateUpdateModel certificateUpdateModel) throws CmpClientException;
}
diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
index 06e785ac..270b5995 100644
--- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
+++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CmpClientImpl.java
@@ -29,15 +29,21 @@ import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHel
import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifyPasswordBasedProtection;
import static org.onap.oom.certservice.cmpv2client.impl.CmpResponseValidationHelper.verifySignature;
+import java.io.ByteArrayInputStream;
import java.io.IOException;
+import java.io.InputStreamReader;
import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
+import java.security.spec.InvalidKeySpecException;
import java.util.Collections;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;
+import org.apache.commons.codec.binary.Base64;
import org.apache.http.impl.client.CloseableHttpClient;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.cmp.CMPCertificate;
@@ -47,8 +53,12 @@ import org.bouncycastle.asn1.cmp.PKIBody;
import org.bouncycastle.asn1.cmp.PKIHeader;
import org.bouncycastle.asn1.cmp.PKIMessage;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
+import org.bouncycastle.asn1.x509.Certificate;
+import org.bouncycastle.util.io.pem.PemReader;
import org.onap.oom.certservice.certification.configuration.model.CaMode;
import org.onap.oom.certservice.certification.configuration.model.Cmpv2Server;
+import org.onap.oom.certservice.certification.exception.KeyDecryptionException;
+import org.onap.oom.certservice.certification.model.CertificateUpdateModel;
import org.onap.oom.certservice.certification.model.CsrModel;
import org.onap.oom.certservice.cmpv2client.api.CmpClient;
import org.onap.oom.certservice.cmpv2client.exceptions.CmpClientException;
@@ -83,25 +93,19 @@ public class CmpClientImpl implements CmpClient {
throws CmpClientException {
validate(csrModel, server, httpClient, notBefore, notAfter);
- KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey());
final String iak = server.getAuthentication().getIak();
final PkiMessageProtection pkiMessageProtection = new PasswordBasedProtection(iak);
final CreateCertRequest certRequest =
- CmpMessageBuilder.of(CreateCertRequest::new)
- .with(CreateCertRequest::setIssuerDn, server.getIssuerDN())
- .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData())
- .with(CreateCertRequest::setSansArray, csrModel.getSans())
- .with(CreateCertRequest::setSubjectKeyPair, keyPair)
+ getCmpMessageBuilderWithCommonRequestValues(csrModel, server)
.with(CreateCertRequest::setNotBefore, notBefore)
.with(CreateCertRequest::setNotAfter, notAfter)
.with(CreateCertRequest::setSenderKid, server.getAuthentication().getRv())
+ .with(CreateCertRequest::setCmpRequestType, PKIBody.TYPE_INIT_REQ)
.with(CreateCertRequest::setProtection, pkiMessageProtection)
.build();
- final PKIMessage pkiMessage = certRequest.generateCertReq();
- Cmpv2HttpClient cmpv2HttpClient = new Cmpv2HttpClient(httpClient);
- return retrieveCertificates(csrModel, server, pkiMessage, cmpv2HttpClient);
+ return executeCmpRequest(csrModel, server, certRequest);
}
@Override
@@ -110,6 +114,66 @@ public class CmpClientImpl implements CmpClient {
return createCertificate(csrModel, server, null, null);
}
+ @Override
+ public Cmpv2CertificationModel updateCertificate(CsrModel csrModel, Cmpv2Server cmpv2Server,
+ CertificateUpdateModel certificateUpdateModel) throws CmpClientException {
+ validate(csrModel, cmpv2Server, httpClient, null, null);
+
+ final PkiMessageProtection pkiMessageProtection = getSignatureProtection(certificateUpdateModel);
+ final CreateCertRequest certRequest =
+ getCmpMessageBuilderWithCommonRequestValues(csrModel, cmpv2Server)
+ .with(CreateCertRequest::setCmpRequestType, PKIBody.TYPE_KEY_UPDATE_REQ)
+ .with(CreateCertRequest::setExtraCerts, getCMPCertificateFromPem(certificateUpdateModel.getEncodedOldCert()))
+ .with(CreateCertRequest::setProtection, pkiMessageProtection)
+ .build();
+
+ return executeCmpRequest(csrModel, cmpv2Server, certRequest);
+
+ }
+
+ private Cmpv2CertificationModel executeCmpRequest(CsrModel csrModel, Cmpv2Server cmpv2Server,
+ CreateCertRequest certRequest) throws CmpClientException {
+ final PKIMessage pkiMessage = certRequest.generateCertReq();
+ Cmpv2HttpClient cmpv2HttpClient = new Cmpv2HttpClient(httpClient);
+ return retrieveCertificates(csrModel, cmpv2Server, pkiMessage, cmpv2HttpClient);
+ }
+
+ private CmpMessageBuilder<CreateCertRequest> getCmpMessageBuilderWithCommonRequestValues(CsrModel csrModel,
+ Cmpv2Server cmpv2Server) {
+ KeyPair keyPair = new KeyPair(csrModel.getPublicKey(), csrModel.getPrivateKey());
+ return CmpMessageBuilder.of(CreateCertRequest::new)
+ .with(CreateCertRequest::setIssuerDn, cmpv2Server.getIssuerDN())
+ .with(CreateCertRequest::setSubjectDn, csrModel.getSubjectData())
+ .with(CreateCertRequest::setSansArray, csrModel.getSans())
+ .with(CreateCertRequest::setSubjectKeyPair, keyPair);
+ }
+
+ private SignatureProtection getSignatureProtection(CertificateUpdateModel certificateUpdateModel)
+ throws CmpClientException {
+ try {
+ PrivateKey oldPrivateKey = certificateUpdateModel.getOldPrivateKeyObject();
+ return new SignatureProtection(oldPrivateKey);
+ } catch (NoSuchAlgorithmException | KeyDecryptionException | InvalidKeySpecException e) {
+ throw new CmpClientException("Cannot parse old private key ", e);
+ }
+
+ }
+
+ private CMPCertificate[] getCMPCertificateFromPem(String encodedCertPem) throws CmpClientException {
+ try {
+ Certificate certificate = Certificate.getInstance(
+ new PemReader(
+ new InputStreamReader(
+ new ByteArrayInputStream(
+ Base64.decodeBase64(encodedCertPem))))
+ .readPemObject().getContent());
+ CMPCertificate cert = new CMPCertificate(certificate);
+ return new CMPCertificate[]{cert};
+ } catch (IOException | NullPointerException e ) {
+ throw new CmpClientException("Cannot parse old certificate", e);
+ }
+ }
+
private void checkCmpResponse(
final PKIMessage respPkiMessage, final PublicKey publicKey, final String initAuthPassword)
throws CmpClientException {
diff --git a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java
index 0ed493b7..c3283044 100644
--- a/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java
+++ b/certService/src/main/java/org/onap/oom/certservice/cmpv2client/impl/CreateCertRequest.java
@@ -29,6 +29,7 @@ import java.util.Date;
import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.cmp.CMPCertificate;
import org.bouncycastle.asn1.cmp.PKIBody;
import org.bouncycastle.asn1.cmp.PKIHeader;
import org.bouncycastle.asn1.cmp.PKIMessage;
@@ -58,6 +59,8 @@ class CreateCertRequest {
private Date notBefore;
private Date notAfter;
private String senderKid;
+ private int cmpRequestType;
+ private CMPCertificate[] extraCerts;
private final int certReqId = createRandomInt(Integer.MAX_VALUE);
private final AlgorithmIdentifier signingAlgorithm = new DefaultSignatureAlgorithmIdentifierFinder()
@@ -95,6 +98,14 @@ class CreateCertRequest {
this.senderKid = senderKid;
}
+ public void setCmpRequestType(int requestType) {
+ this.cmpRequestType = requestType;
+ }
+
+ public void setExtraCerts(CMPCertificate[] extraCert) {
+ this.extraCerts = extraCert;
+ }
+
/**
* Method to create {@link PKIMessage} from {@link CertRequest},{@link ProofOfPossession}, {@link
* CertReqMsg}, {@link CertReqMessages}, {@link PKIHeader} and {@link PKIBody}.
@@ -127,9 +138,9 @@ class CreateCertRequest {
issuerDn,
pkiMessageProtection.getAlgorithmIdentifier(),
senderKid);
- final PKIBody pkiBody = new PKIBody(PKIBody.TYPE_INIT_REQ, certReqMessages);
+ final PKIBody pkiBody = new PKIBody(cmpRequestType, certReqMessages);
final DERBitString messageProtection = this.pkiMessageProtection.generatePkiMessageProtection(pkiHeader, pkiBody);
- return new PKIMessage(pkiHeader, pkiBody, messageProtection);
+ return new PKIMessage(pkiHeader, pkiBody, messageProtection, extraCerts);
}
}