summaryrefslogtreecommitdiffstats
path: root/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main
diff options
context:
space:
mode:
authorTomasz Pietruszkiewicz <tomasz.pietruszkiewicz@nokia.com>2021-01-14 17:03:31 +0100
committerChristophe Closset <christophe.closset@intl.att.com>2021-01-19 13:48:17 +0000
commit5b9a4251a7bce56895ca80b867ee7537e7382320 (patch)
tree6d09cf14e50b0007e97bbcf9a44e7e5ce3ab63e1 /openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main
parentf3b0ef4dc7cc21b273ea160781b5170b2d105e1a (diff)
Fix signature validation in SDC (PNF package onboarding)
Change-Id: Ief8bf62e48a23a091e9084333c2523d8490fdcd2 Issue-ID: SDC-3386 Signed-off-by: Tomasz Pietruszkiewicz <tomasz.pietruszkiewicz@nokia.com>
Diffstat (limited to 'openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main')
-rw-r--r--openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java119
1 files changed, 71 insertions, 48 deletions
diff --git a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java
index 6fae6f0e72..56d0142e3b 100644
--- a/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java
+++ b/openecomp-be/backend/openecomp-sdc-vendor-software-product-manager/src/main/java/org/openecomp/sdc/vendorsoftwareproduct/security/SecurityManager.java
@@ -20,23 +20,15 @@
package org.openecomp.sdc.vendorsoftwareproduct.security;
import com.google.common.collect.ImmutableSet;
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
+
+import java.io.*;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
-import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.security.PublicKey;
import java.security.Security;
-import java.security.SignatureException;
import java.security.cert.CertPathBuilder;
import java.security.cert.CertStore;
-import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateFactory;
@@ -49,7 +41,12 @@ import java.security.cert.X509CertSelector;
import java.security.cert.X509Certificate;
import java.util.Collection;
import java.util.HashSet;
+import java.util.function.Predicate;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import java.util.Set;
+
import org.bouncycastle.asn1.cms.ContentInfo;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.cms.CMSException;
@@ -77,6 +74,7 @@ public class SecurityManager {
private Logger logger = LoggerFactory.getLogger(SecurityManager.class);
private Set<X509Certificate> trustedCertificates = new HashSet<>();
+ private Set<X509Certificate> trustedCertificatesFromPackage = new HashSet<>();
private File certificateDirectory;
static {
@@ -113,7 +111,7 @@ public class SecurityManager {
* @return set of trustedCertificates
* @throws SecurityManagerException
*/
- public Set<X509Certificate> getTrustedCertificates() throws SecurityManagerException {
+ public Set<X509Certificate> getTrustedCertificates() throws SecurityManagerException, FileNotFoundException {
//if file number in certificate directory changed reload certs
String[] certFiles = certificateDirectory.list();
if (certFiles == null) {
@@ -124,6 +122,10 @@ public class SecurityManager {
trustedCertificates = new HashSet<>();
processCertificateDir();
}
+ if (!trustedCertificatesFromPackage.isEmpty()) {
+ return Stream.concat(trustedCertificatesFromPackage.stream(), trustedCertificates.stream())
+ .collect(Collectors.toUnmodifiableSet());
+ }
return ImmutableSet.copyOf(trustedCertificates);
}
@@ -146,7 +148,7 @@ public class SecurityManager {
public boolean verifySignedData(final byte[] messageSyntaxSignature, final byte[] packageCert,
final byte[] innerPackageFile) throws SecurityManagerException {
try (ByteArrayInputStream signatureStream = new ByteArrayInputStream(messageSyntaxSignature);
- final PEMParser pemParser = new PEMParser(new InputStreamReader(signatureStream))) {
+ final PEMParser pemParser = new PEMParser(new InputStreamReader(signatureStream))) {
final Object parsedObject = pemParser.readObject();
if (!(parsedObject instanceof ContentInfo)) {
throw new SecurityManagerException("Signature is not recognized");
@@ -158,17 +160,17 @@ public class SecurityManager {
final Collection<SignerInformation> signers = signedData.getSignerInfos().getSigners();
final SignerInformation firstSigner = signers.iterator().next();
final X509Certificate cert;
+ Collection<X509CertificateHolder> certs;
if (packageCert == null) {
- final Collection<X509CertificateHolder> firstSignerCertificates = signedData.getCertificates()
- .getMatches(firstSigner.getSID());
- if (!firstSignerCertificates.iterator().hasNext()) {
- throw new SecurityManagerException(
- "No certificate found in cms signature that should contain one!");
- }
- cert = loadCertificate(firstSignerCertificates.iterator().next().getEncoded());
+ certs = signedData.getCertificates().getMatches(null);
+ cert = readSignCert(certs, firstSigner).orElseThrow(() -> new SecurityManagerException(
+ "No certificate found in cms signature that should contain one!"));
} else {
- cert = loadCertificate(packageCert);
+ certs = parseCertsFromPem(packageCert);
+ cert = readSignCert(certs, firstSigner).orElseThrow(() -> new SecurityManagerException(
+ "No matching certificate found in certificate file that should contain one!"));
}
+ trustedCertificatesFromPackage = readTrustedCerts(certs, firstSigner);
if (verifyCertificate(cert, getTrustedCertificates()) == null) {
return false;
@@ -183,7 +185,36 @@ public class SecurityManager {
}
}
- private void processCertificateDir() throws SecurityManagerException {
+ private Optional<X509Certificate> readSignCert(final Collection<X509CertificateHolder> certs, final SignerInformation firstSigner) {
+ return certs.stream()
+ .filter(crt -> firstSigner.getSID().match(crt))
+ .findAny()
+ .map(this::loadCertificate);
+ }
+
+ private Set<X509Certificate> readTrustedCerts(final Collection<X509CertificateHolder> certs, final SignerInformation firstSigner) {
+ return certs.stream()
+ .filter(crt -> !firstSigner.getSID().match(crt))
+ .map(this::loadCertificate)
+ .filter(Predicate.not(this::isSelfSigned))
+ .collect(Collectors.toSet());
+ }
+
+ private Set<X509CertificateHolder> parseCertsFromPem(final byte[] packageCert) throws IOException {
+ final ByteArrayInputStream packageCertStream = new ByteArrayInputStream(packageCert);
+ final PEMParser pemParser = new PEMParser(new InputStreamReader(packageCertStream));
+ Object readObject = pemParser.readObject();
+ Set<X509CertificateHolder> allCerts = new HashSet<>();
+ while (readObject != null) {
+ if (readObject instanceof X509CertificateHolder) {
+ allCerts.add((X509CertificateHolder) readObject);
+ }
+ readObject = pemParser.readObject();
+ }
+ return allCerts;
+ }
+
+ private void processCertificateDir() throws SecurityManagerException, FileNotFoundException {
if (!certificateDirectory.exists() || !certificateDirectory.isDirectory()) {
logger.error("Issue with certificate directory, check if exists!");
return;
@@ -207,27 +238,30 @@ public class SecurityManager {
return new File(certDirLocation);
}
- private X509Certificate loadCertificate(File certFile) throws SecurityManagerException {
- try (InputStream fileInputStream = new FileInputStream(certFile)) {
- CertificateFactory factory = CertificateFactory.getInstance("X.509");
- return (X509Certificate) factory.generateCertificate(fileInputStream);
- } catch (CertificateException | IOException e) {
- throw new SecurityManagerException("Error during loading Certificate file!", e);
+ private X509Certificate loadCertificate(File certFile) throws SecurityManagerException, FileNotFoundException {
+ return loadCertificateFactory(new FileInputStream(certFile));
+ }
+
+ private X509Certificate loadCertificate(X509CertificateHolder cert) {
+ try {
+ return loadCertificateFactory(new ByteArrayInputStream(cert.getEncoded()));
+ } catch (IOException | SecurityManagerException e) {
+ throw new RuntimeException("Error during loading Certificate from bytes!", e);
}
}
- private X509Certificate loadCertificate(byte[] certFile) throws SecurityManagerException {
- try (InputStream in = new ByteArrayInputStream(certFile)) {
+ private X509Certificate loadCertificateFactory(InputStream in) throws SecurityManagerException {
+ try {
CertificateFactory factory = CertificateFactory.getInstance("X.509");
return (X509Certificate) factory.generateCertificate(in);
- } catch (CertificateException | IOException e) {
+ } catch (CertificateException e) {
throw new SecurityManagerException("Error during loading Certificate from bytes!", e);
}
}
private PKIXCertPathBuilderResult verifyCertificate(X509Certificate cert,
Set<X509Certificate> additionalCerts)
- throws GeneralSecurityException, SecurityManagerException {
+ throws GeneralSecurityException, SecurityManagerException {
if (null == cert) {
throw new SecurityManagerException("The certificate is empty!");
}
@@ -256,7 +290,7 @@ public class SecurityManager {
private PKIXCertPathBuilderResult verifyCertificate(X509Certificate cert,
Set<X509Certificate> allTrustedRootCerts,
Set<X509Certificate> allIntermediateCerts)
- throws GeneralSecurityException {
+ throws GeneralSecurityException {
// Create the selector that specifies the starting certificate
X509CertSelector selector = new X509CertSelector();
@@ -286,14 +320,14 @@ public class SecurityManager {
pkixParams.addCertStore(createCertStore(allTrustedRootCerts));
CertPathBuilder builder = CertPathBuilder
- .getInstance(CertPathBuilder.getDefaultType(), BouncyCastleProvider.PROVIDER_NAME);
+ .getInstance(CertPathBuilder.getDefaultType(), BouncyCastleProvider.PROVIDER_NAME);
return (PKIXCertPathBuilderResult) builder.build(pkixParams);
}
private CertStore createCertStore(Set<X509Certificate> certificateSet) throws InvalidAlgorithmParameterException,
- NoSuchAlgorithmException, NoSuchProviderException {
+ NoSuchAlgorithmException, NoSuchProviderException {
return CertStore.getInstance("Collection", new CollectionCertStoreParameters(certificateSet),
- BouncyCastleProvider.PROVIDER_NAME);
+ BouncyCastleProvider.PROVIDER_NAME);
}
private boolean isExpired(X509Certificate cert) {
@@ -309,18 +343,7 @@ public class SecurityManager {
return false;
}
- private boolean isSelfSigned(Certificate cert)
- throws CertificateException, NoSuchAlgorithmException,
- NoSuchProviderException {
- try {
- // Try to verify certificate signature with its own public key
- PublicKey key = cert.getPublicKey();
- cert.verify(key);
- return true;
- } catch (SignatureException | InvalidKeyException e) {
- logger.error(e.getMessage(), e);
- //not self-signed
- return false;
- }
+ private boolean isSelfSigned(X509Certificate cert) {
+ return cert.getIssuerDN().equals(cert.getSubjectDN());
}
}