From ed77ac88ab64620f8b3c5a3ed9e730e129f2f507 Mon Sep 17 00:00:00 2001 From: Bartosz Gardziejewski Date: Thu, 10 Dec 2020 09:55:20 +0100 Subject: Add signature and certificate for individual artifacts. Signed-off-by: Bartosz Gardziejewski Change-Id: Ifb9e06fffefea6b4d068a915b69b66c750ab02e8 Issue-ID: VNFSDK-714 --- .../cvc/csar/cc/sol004/VTPValidateCSARR130206.java | 139 ++++++++++++++++++--- .../org/onap/cvc/csar/parser/MetadataParser.java | 6 +- 2 files changed, 123 insertions(+), 22 deletions(-) (limited to 'csarvalidation/src/main') diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java index 05feb54..6f1ff1f 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java @@ -57,7 +57,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { private static final String EMPTY_STRING = ""; private final ShaHashCodeGenerator shaHashCodeGenerator = new ShaHashCodeGenerator(); - private final ManifestFileSignatureValidator manifestFileSignatureValidator = new ManifestFileSignatureValidator(); + private final FileSignatureValidator fileSignatureValidator = new FileSignatureValidator(); public static class CSARErrorUnableToFindCertificate extends CSARArchive.CSARError { @@ -178,6 +178,54 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } + public static class CSARErrorUnableToFindArtifactCertificate extends CSARArchive.CSARError { + + CSARErrorUnableToFindArtifactCertificate(String path) { + super("0x4015"); + this.message = String.format("Source '%s' has signature tag, but unable to find certificate tag!", path); + } + } + + public static class CSARErrorUnableToFindArtifactCertificateFile extends CSARArchive.CSARError { + + CSARErrorUnableToFindArtifactCertificateFile(String path) { + super("0x4016"); + this.message = String.format("Source '%s' has certificate tag, pointing to non existing file!", path); + } + } + + public static class CSARErrorUnableToFindArtifactSignature extends CSARArchive.CSARError { + + CSARErrorUnableToFindArtifactSignature(String path) { + super("0x4017"); + this.message = String.format("Source '%s' has certificate tag, but unable to find signature tag!", path); + } + } + + public static class CSARErrorUnableToFindArtifactSignatureFile extends CSARArchive.CSARError { + + CSARErrorUnableToFindArtifactSignatureFile(String path) { + super("0x4018"); + this.message = String.format("Source '%s' has signature tag, pointing to non existing file!", path); + } + } + + public static class CSARErrorFailToLoadArtifactSignature extends CSARArchive.CSARError { + + CSARErrorFailToLoadArtifactSignature(String path, String cms) { + super("0x4019"); + this.message = String.format("Fail to load signature '%s', for source '%s'!", path, cms); + } + } + + public static class CSARErrorIncorrectArtifactSignature extends CSARArchive.CSARError { + + CSARErrorIncorrectArtifactSignature(String path) { + super("0x4020"); + this.message = String.format("Source '%s' has incorrect signature!", path); + } + } + public static class CSARWarningNoSecurity extends CSARArchive.CSARErrorWarning { CSARWarningNoSecurity() { super(EMPTY_STRING, EMPTY_STRING, -1, EMPTY_STRING); @@ -207,9 +255,9 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { if (containsCms(csar.getManifest())) { validateCmsSignature(csar, csarRootDirectory); } else if ( - ( containsToscaMeta(csar) && containsCertificateInTosca(csar.getToscaMeta()) ) || + (containsToscaMeta(csar) && containsCertificateInTosca(csar.getToscaMeta())) || containsCertificateInRootCatalog(csar) || - containsHashOrAlgorithm(csar.getManifest())) { + containsPerArtifactSecurity(csar.getManifest())) { this.errors.add(new CSARErrorUnableToFindCms()); } else { this.errors.add(new CSARWarningNoSecurity()); @@ -218,7 +266,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { private void validateCmsSignature(CSARArchive csar, Path csarRootDirectory) throws NoSuchAlgorithmException, IOException { try { - CmsSignatureData signatureData = this.manifestFileSignatureValidator.createSignatureData(csar.getManifestMfFile()); + CmsSignatureData signatureData = this.fileSignatureValidator.createSignatureDataForManifestFile(csar.getManifestMfFile()); if (signatureData.getCertificate().isPresent()) { validateCertificationUsingCmsCertificate(signatureData, csar, csarRootDirectory); } else if (containsToscaMeta(csar)) { @@ -253,11 +301,13 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { return potentialCertificateFileInRootDirectory.exists(); } - private boolean containsHashOrAlgorithm(CSARArchive.Manifest manifest) { + private boolean containsPerArtifactSecurity(CSARArchive.Manifest manifest) { return manifest.getSources().stream().anyMatch( source -> !source.getAlgorithm().equals(EMPTY_STRING) || - !source.getHash().equals(EMPTY_STRING) + !source.getHash().equals(EMPTY_STRING) || + !source.getCertificate().equals(EMPTY_STRING) || + !source.getSignature().equals(EMPTY_STRING) ); } @@ -288,7 +338,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } private boolean loadCertificateFromTosca(CmsSignatureData signatureData, CSARArchive csar) { - if(csar.getToscaMeta().getEntryCertificate() != null) { + if (csar.getToscaMeta().getEntryCertificate() != null) { try { final Path absolutePathToEntryCertificate = csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).toPath(); signatureData.loadCertificate(absolutePathToEntryCertificate); @@ -368,7 +418,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } private void validateFileSignature(CmsSignatureData signatureData) { - final boolean isValid = this.manifestFileSignatureValidator.isValid(signatureData); + final boolean isValid = this.fileSignatureValidator.isValid(signatureData); if (!isValid) { this.errors.add(new CSARErrorInvalidSignature()); } @@ -378,23 +428,27 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { throws NoSuchAlgorithmException, IOException { final List sources = manifest.getSources(); for (SourcesParser.Source source : sources) { - if (!source.getAlgorithm().isEmpty() || !source.getHash().isEmpty()) { - validateSource(csarRootDirectory, source); - } + validateSource(csarRootDirectory, source); } } private void validateSource(Path csarRootDirectory, SourcesParser.Source source) throws NoSuchAlgorithmException, IOException { final Path sourcePath = csarRootDirectory.resolve(source.getValue()); - if (!sourcePath.toFile().exists()) { - this.errors.add(new CSARErrorUnableToFindSource(source.getValue())); + if (sourcePath.toFile().exists()) { + validateHashIfPresent(csarRootDirectory, source); + validateArtifactSignatureIfPresent(csarRootDirectory, source); } else { - if (!source.getAlgorithm().isEmpty()) { - validateSourceHashCode(csarRootDirectory, source); - } else if (source.getAlgorithm().isEmpty() && !source.getHash().isEmpty()) { - this.errors.add(new CSARErrorUnableToFindAlgorithm(source.getValue())); - } + this.errors.add(new CSARErrorUnableToFindSource(source.getValue())); + } + } + + private void validateHashIfPresent(Path csarRootDirectory, SourcesParser.Source source) + throws NoSuchAlgorithmException, IOException { + if (!source.getAlgorithm().isEmpty()) { + validateSourceHashCode(csarRootDirectory, source); + } else if (source.getAlgorithm().isEmpty() && !source.getHash().isEmpty()) { + this.errors.add(new CSARErrorUnableToFindAlgorithm(source.getValue())); } } @@ -420,19 +474,55 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { throw new UnsupportedOperationException(String.format("Algorithm '%s' is not supported!", algorithm)); } + private void validateArtifactSignatureIfPresent(Path csarRootDirectory, SourcesParser.Source source) + throws IOException { + if (!source.getSignature().isEmpty() && !source.getCertificate().isEmpty()) { + validateArtifactSignature(csarRootDirectory, source); + } else if (!source.getSignature().isEmpty()) { + this.errors.add(new CSARErrorUnableToFindArtifactCertificate(source.getValue())); + } else if (!source.getCertificate().isEmpty()) { + this.errors.add(new CSARErrorUnableToFindArtifactSignature(source.getValue())); + } + } + + private void validateArtifactSignature(Path csarRootDirectory, SourcesParser.Source source) + throws IOException { + final Path filePath = csarRootDirectory.resolve(source.getValue()); + final Path signaturePath = csarRootDirectory.resolve(source.getSignature()); + final Path certificatePath = csarRootDirectory.resolve(source.getCertificate()); + if (signaturePath.toFile().exists() && certificatePath.toFile().exists()) { + try { + CmsSignatureData signatureData = + fileSignatureValidator.createSignatureData(filePath, signaturePath, certificatePath); + if( !fileSignatureValidator.isValid(signatureData) ) { + this.errors.add(new CSARErrorIncorrectArtifactSignature(source.getValue())); + } + } catch (CmsSignatureLoadingException e) { + this.errors.add(new CSARErrorFailToLoadArtifactSignature(source.getValue(),source.getSignature())); + } + } else { + if (!signaturePath.toFile().exists()) { + this.errors.add(new CSARErrorUnableToFindArtifactSignatureFile(source.getValue())); + } + if (!certificatePath.toFile().exists()) { + this.errors.add(new CSARErrorUnableToFindArtifactCertificateFile(source.getValue())); + } + } + } + @Override protected String getVnfReqsNo() { return "R130206"; } - static class ManifestFileSignatureValidator { + static class FileSignatureValidator { private final ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter(); private final CmsSignatureValidator cmsSignatureValidator = new CmsSignatureValidator(); private final CmsSignatureDataFactory cmsSignatureDataFactory = new CmsSignatureDataFactory(); - CmsSignatureData createSignatureData(File manifestFile) throws CmsSignatureLoadingException { + CmsSignatureData createSignatureDataForManifestFile(File manifestFile) throws CmsSignatureLoadingException { ManifestFileModel mf = manifestFileSplitter.split(manifestFile); return cmsSignatureDataFactory.createForFirstSigner( toBytes(mf.getCMS(), mf.getNewLine()), @@ -440,6 +530,15 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { ); } + CmsSignatureData createSignatureData(Path filePath, Path cmsFilePath, Path certFilePath) throws CmsSignatureLoadingException, IOException { + CmsSignatureData signatureData = cmsSignatureDataFactory.createForFirstSigner( + Files.readAllBytes(cmsFilePath), + Files.readAllBytes(filePath) + ); + signatureData.loadCertificate(certFilePath); + return signatureData; + } + boolean isValid(CmsSignatureData signatureData) { try { return cmsSignatureValidator.verifySignedData(signatureData); diff --git a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java index f529c45..8e3a9b8 100644 --- a/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java +++ b/csarvalidation/src/main/java/org/onap/cvc/csar/parser/MetadataParser.java @@ -91,13 +91,15 @@ public class MetadataParser { private boolean isSourceSection(Pair data) { return data.getKey().equalsIgnoreCase(SOURCE_TAG_SECTION) || data.getKey().equalsIgnoreCase(ALGORITHM) - || data.getKey().equalsIgnoreCase(HASH); + || data.getKey().equalsIgnoreCase(HASH) + || data.getKey().equalsIgnoreCase(SIGNATURE) + || data.getKey().equalsIgnoreCase(CERTIFICATE); } private boolean isSectionSupported(String key) { return Lists.newArrayList( METADATA_SECTION_TAG_SECTION, - SOURCE_TAG_SECTION, ALGORITHM, HASH, + SOURCE_TAG_SECTION, ALGORITHM, HASH, SIGNATURE, CERTIFICATE, NON_MANO_ARTIFACT_SETS_TAG_SECTION).contains(key.toLowerCase()); } -- cgit 1.2.3-korg