diff options
Diffstat (limited to 'csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java')
-rw-r--r-- | csarvalidation/src/main/java/org/onap/cvc/csar/cc/sol004/VTPValidateCSARR130206.java | 266 |
1 files changed, 221 insertions, 45 deletions
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 fefe65b..05feb54 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 @@ -26,6 +26,10 @@ import org.onap.cvc.csar.cc.VTPValidateCSARBase; import org.onap.cvc.csar.parser.ManifestFileModel; import org.onap.cvc.csar.parser.ManifestFileSplitter; import org.onap.cvc.csar.parser.SourcesParser; +import org.onap.cvc.csar.security.CertificateLoadingException; +import org.onap.cvc.csar.security.CmsSignatureData; +import org.onap.cvc.csar.security.CmsSignatureDataFactory; +import org.onap.cvc.csar.security.CmsSignatureLoadingException; import org.onap.cvc.csar.security.CmsSignatureValidator; import org.onap.cvc.csar.security.CmsSignatureValidatorException; import org.onap.cvc.csar.security.ShaHashCodeGenerator; @@ -50,23 +54,31 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { private static final Logger LOG = LoggerFactory.getLogger(VTPValidateCSARR130206.class); private static final String SHA_256 = "SHA-256"; private static final String SHA_512 = "SHA-512"; + private static final String EMPTY_STRING = ""; private final ShaHashCodeGenerator shaHashCodeGenerator = new ShaHashCodeGenerator(); private final ManifestFileSignatureValidator manifestFileSignatureValidator = new ManifestFileSignatureValidator(); public static class CSARErrorUnableToFindCertificate extends CSARArchive.CSARError { - CSARErrorUnableToFindCertificate(String paramName) { + CSARErrorUnableToFindCertificate() { super("0x4001"); - this.message = String.format("Unable to find cert file defined by %s!", paramName); + this.message = "Unable to find cert file!"; } } - public static class CSARErrorUnableToFindCmsSection extends CSARArchive.CSARError { + public static class CSARErrorUnableToFindCms extends CSARArchive.CSARError { - CSARErrorUnableToFindCmsSection() { + CSARErrorUnableToFindCms() { super("0x4002"); - this.message = "Unable to find CMS section in manifest!"; + this.message = "Unable to find cms signature!"; + } + } + + public static class CSARErrorUnableToLoadCms extends CSARArchive.CSARError { + CSARErrorUnableToLoadCms() { + super("0x4002"); + this.message = "Unable to load cms signature!"; } } @@ -106,7 +118,7 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { CSARErrorInvalidSignature() { super("0x4007"); - this.message = "File has invalid CMS signature!"; + this.message = "File has invalid signature!"; } } @@ -118,6 +130,61 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } } + public static class CSARErrorUnableToFindEntryCertificate extends CSARArchive.CSARError { + + CSARErrorUnableToFindEntryCertificate() { + super("0x4009"); + this.message = "Unable to find cert file defined by ETSI-Entry-Certificate!"; + } + } + + public static class CSARErrorEntryCertificateIsDefinedDespiteTheCms extends CSARArchive.CSARError { + + CSARErrorEntryCertificateIsDefinedDespiteTheCms() { + super("0x4011"); + this.message = "ETSI-Entry-Certificate entry in Tosca.meta is defined despite the certificate is included in the signature container"; + } + } + + public static class CSARErrorEntryCertificateIsPresentDespiteTheCms extends CSARArchive.CSARError { + + CSARErrorEntryCertificateIsPresentDespiteTheCms() { + super("0x4012"); + this.message = "ETSI-Entry-Certificate certificate present despite the certificate is included in the signature container"; + } + } + + public static class CSARErrorRootCertificateIsPresentDespiteTheCms extends CSARArchive.CSARError { + + CSARErrorRootCertificateIsPresentDespiteTheCms() { + super("0x4013"); + this.message = "Certificate present in root catalog despite the certificate is included in the signature container"; + } + } + + public static class CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate extends CSARArchive.CSARError { + + CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate() { + super("0x4013"); + this.message = "Certificate present in root catalog despite the TOSCA.meta file"; + } + } + + public static class CSARErrorUnableToFindCertificateEntryInTosca extends CSARArchive.CSARError { + + CSARErrorUnableToFindCertificateEntryInTosca() { + super("0x4014"); + this.message = "Unable to find ETSI-Entry-Certificate in Tosca file"; + } + } + + public static class CSARWarningNoSecurity extends CSARArchive.CSARErrorWarning { + CSARWarningNoSecurity() { + super(EMPTY_STRING, EMPTY_STRING, -1, EMPTY_STRING); + this.message = "Warning. Consider adding package integrity and authenticity assurance according to ETSI NFV-SOL 004 Security Option 1"; + } + } + @Override protected void validateCSAR(CSARArchive csar) throws OnapCommandException { @@ -137,20 +204,146 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } private void validate(CSARArchive csar, Path csarRootDirectory) throws IOException, NoSuchAlgorithmException { - final CSARArchive.Manifest manifest = csar.getManifest(); + if (containsCms(csar.getManifest())) { + validateCmsSignature(csar, csarRootDirectory); + } else if ( + ( containsToscaMeta(csar) && containsCertificateInTosca(csar.getToscaMeta()) ) || + containsCertificateInRootCatalog(csar) || + containsHashOrAlgorithm(csar.getManifest())) { + this.errors.add(new CSARErrorUnableToFindCms()); + } else { + this.errors.add(new CSARWarningNoSecurity()); + } + } + + private void validateCmsSignature(CSARArchive csar, Path csarRootDirectory) throws NoSuchAlgorithmException, IOException { + try { + CmsSignatureData signatureData = this.manifestFileSignatureValidator.createSignatureData(csar.getManifestMfFile()); + if (signatureData.getCertificate().isPresent()) { + validateCertificationUsingCmsCertificate(signatureData, csar, csarRootDirectory); + } else if (containsToscaMeta(csar)) { + validateCertificationUsingTosca(signatureData, csar, csarRootDirectory); + } else if (containsCertificateInRootCatalog(csar)) { + validateCertificationUsingCertificateFromRootDirectory(signatureData, csar, csarRootDirectory); + } else { + this.errors.add(new CSARErrorUnableToFindCertificate()); + } + } catch (CmsSignatureLoadingException e) { + LOG.error("Unable to load CMS!", e); + this.errors.add(new CSARErrorUnableToLoadCms()); + } + } + + private boolean containsCms(CSARArchive.Manifest manifest) { + String cms = manifest.getCms(); + return cms != null && !cms.equals(EMPTY_STRING); + } + + private boolean containsToscaMeta(CSARArchive archive) { + return archive.getToscaMetaFile() != null; + } + + private boolean containsCertificateInTosca(CSARArchive.TOSCAMeta toscaMeta) { + String certificate = toscaMeta.getEntryCertificate(); + return certificate != null && !certificate.equals(EMPTY_STRING); + } + + private boolean containsCertificateInRootCatalog(CSARArchive csar) { + File potentialCertificateFileInRootDirectory = getCertificateFromRootDirectory(csar); + return potentialCertificateFileInRootDirectory.exists(); + } - validateSecurityStructure(csar, csarRootDirectory); + private boolean containsHashOrAlgorithm(CSARArchive.Manifest manifest) { + return manifest.getSources().stream().anyMatch( + source -> + !source.getAlgorithm().equals(EMPTY_STRING) || + !source.getHash().equals(EMPTY_STRING) + ); + } + + private void validateCertificationUsingCmsCertificate(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory) + throws NoSuchAlgorithmException, IOException { + validateAllSources(csar, csarRootDirectory); + validateFileSignature(signatureData); + if (containsCertificateInTosca(csar.getToscaMeta())) { + errors.add(new CSARErrorEntryCertificateIsDefinedDespiteTheCms()); + if (csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).exists()) { + errors.add(new CSARErrorEntryCertificateIsPresentDespiteTheCms()); + } + } + if (containsCertificateInRootCatalog(csar)) { + errors.add(new CSARErrorRootCertificateIsPresentDespiteTheCms()); + } + } + + private void validateCertificationUsingTosca(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory) + throws NoSuchAlgorithmException, IOException { + validateAllSources(csar, csarRootDirectory); + if (loadCertificateFromTosca(signatureData, csar)) { + validateFileSignature(signatureData); + } + if (containsCertificateInRootCatalog(csar) && rootCertificateIsNotReferredAsToscaEtsiEntryCertificate(csar)) { + errors.add(new CSARErrorRootCertificateIsPresentDespiteTheEtsiEntryCertificate()); + } + } + + private boolean loadCertificateFromTosca(CmsSignatureData signatureData, CSARArchive csar) { + if(csar.getToscaMeta().getEntryCertificate() != null) { + try { + final Path absolutePathToEntryCertificate = csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).toPath(); + signatureData.loadCertificate(absolutePathToEntryCertificate); + return true; + } catch (CertificateLoadingException e) { + this.errors.add(new CSARErrorUnableToFindEntryCertificate()); + return false; + } + } else { + this.errors.add(new CSARErrorUnableToFindCertificateEntryInTosca()); + return false; + } + } + + private boolean rootCertificateIsNotReferredAsToscaEtsiEntryCertificate(CSARArchive csar) { + String pathToRootCertificate = getCertificateFromRootDirectory(csar).getPath(); + String pathToEntryEtsiCertificate = csar.getFileFromCsar(csar.getToscaMeta().getEntryCertificate()).getPath(); + return !pathToRootCertificate.equals(pathToEntryEtsiCertificate); + } + + private void validateCertificationUsingCertificateFromRootDirectory(CmsSignatureData signatureData, CSARArchive csar, Path csarRootDirectory) + throws NoSuchAlgorithmException, IOException { + validateAllSources(csar, csarRootDirectory); + if (loadCertificateFromRootDirectory(signatureData, csar)) { + validateFileSignature(signatureData); + } + } + + private boolean loadCertificateFromRootDirectory(CmsSignatureData signatureData, CSARArchive csar) { + try { + File certificateFileFromRootDirectory = getCertificateFromRootDirectory(csar); + signatureData.loadCertificate(certificateFileFromRootDirectory.toPath()); + return true; + } catch (CertificateLoadingException e) { + LOG.error("Uable to read ETSI entry certificate file!", e); + return false; + } + } + + private File getCertificateFromRootDirectory(CSARArchive csar) { + String nameOfCertificate = + csar.getManifestMfFile().getName().split("\\.")[0] + + ".cert"; + return csar.getFileFromCsar(nameOfCertificate); + } + + private void validateAllSources(CSARArchive csar, Path csarRootDirectory) + throws NoSuchAlgorithmException, IOException { + final CSARArchive.Manifest manifest = csar.getManifest(); validateSources(csarRootDirectory, manifest); final Map<String, Map<String, List<String>>> nonMano = manifest.getNonMano(); final List<SourcesParser.Source> sources = manifest.getSources(); validateNonManoCohesionWithSources(nonMano, sources); - - final File manifestMfFile = csar.getManifestMfFile(); - if (manifestMfFile != null) { - validateFileSignature(manifestMfFile); - } } private void validateNonManoCohesionWithSources(final Map<String, Map<String, List<String>>> nonMano, @@ -174,36 +367,13 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } - private void validateFileSignature(File manifestMfFile) { - final boolean isValid = this.manifestFileSignatureValidator.isValid(manifestMfFile); + private void validateFileSignature(CmsSignatureData signatureData) { + final boolean isValid = this.manifestFileSignatureValidator.isValid(signatureData); if (!isValid) { this.errors.add(new CSARErrorInvalidSignature()); } } - private void validateSecurityStructure(CSARArchive csar, Path csarRootDirectory) { - final CSARArchive.Manifest manifest = csar.getManifest(); - final CSARArchive.TOSCAMeta toscaMeta = csar.getToscaMeta(); - final String entryCertificateParamName = csar.getEntryCertificateParamName(); - final Optional<File> entryCertificate = resolveCertificateFilePath(toscaMeta, csarRootDirectory); - if (!entryCertificate.isPresent() || !entryCertificate.get().exists()) { - this.errors.add(new CSARErrorUnableToFindCertificate(entryCertificateParamName)); - } - - if (manifest.getCms() == null || manifest.getCms().isEmpty()) { - this.errors.add(new CSARErrorUnableToFindCmsSection()); - } - } - - private Optional<File> resolveCertificateFilePath(CSARArchive.TOSCAMeta toscaMeta, Path csarRootDirectory) { - final String certificatePath = toscaMeta.getEntryCertificate(); - if (certificatePath == null) { - return Optional.empty(); - } else { - return Optional.of(csarRootDirectory.resolve(certificatePath).toFile()); - } - } - private void validateSources(Path csarRootDirectory, CSARArchive.Manifest manifest) throws NoSuchAlgorithmException, IOException { final List<SourcesParser.Source> sources = manifest.getSources(); @@ -256,18 +426,23 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { } - class ManifestFileSignatureValidator { + static class ManifestFileSignatureValidator { - private final Logger LOG = LoggerFactory.getLogger(ManifestFileSignatureValidator.class); private final ManifestFileSplitter manifestFileSplitter = new ManifestFileSplitter(); private final CmsSignatureValidator cmsSignatureValidator = new CmsSignatureValidator(); + private final CmsSignatureDataFactory cmsSignatureDataFactory = new CmsSignatureDataFactory(); + + CmsSignatureData createSignatureData(File manifestFile) throws CmsSignatureLoadingException { + ManifestFileModel mf = manifestFileSplitter.split(manifestFile); + return cmsSignatureDataFactory.createForFirstSigner( + toBytes(mf.getCMS(), mf.getNewLine()), + toBytes(mf.getData(), mf.getNewLine()) + ); + } - boolean isValid(File manifestFile) { + boolean isValid(CmsSignatureData signatureData) { try { - ManifestFileModel mf = manifestFileSplitter.split(manifestFile); - return cmsSignatureValidator.verifySignedData(toBytes(mf.getCMS(), mf.getNewLine()), - Optional.empty(), - toBytes(mf.getData(), mf.getNewLine())); + return cmsSignatureValidator.verifySignedData(signatureData); } catch (CmsSignatureValidatorException e) { LOG.error("Unable to verify signed data!", e); return false; @@ -279,4 +454,5 @@ public class VTPValidateCSARR130206 extends VTPValidateCSARBase { return updatedData.getBytes(Charset.defaultCharset()); } } + } |