diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/sec_certs/dataset/cc.py | 12 | ||||
| -rw-r--r-- | src/sec_certs/rules.yaml | 5 | ||||
| -rw-r--r-- | src/sec_certs/sample/cc.py | 51 |
3 files changed, 65 insertions, 3 deletions
diff --git a/src/sec_certs/dataset/cc.py b/src/sec_certs/dataset/cc.py index d5417a23..568e68ce 100644 --- a/src/sec_certs/dataset/cc.py +++ b/src/sec_certs/dataset/cc.py @@ -885,10 +885,22 @@ class CCDataset(Dataset[CCCertificate, CCAuxiliaryDatasets], ComplexSerializable for cert in self: cert.heuristics.extracted_sars = transformer.transform_single_cert(cert) + @staged(logger, "Computing heuristics: certificate versions") + def _compute_cert_versions(self) -> None: + cert_ids = { + cert.dgst: CertificateId(cert.scheme, cert.heuristics.cert_id) + if cert.heuristics.cert_id is not None + else None + for cert in self + } + for cert in self: + cert.compute_heuristics_cert_versions(cert_ids) + def _compute_heuristics(self) -> None: self._compute_normalized_cert_ids() super()._compute_heuristics() self._compute_scheme_data() + self._compute_cert_versions() self._compute_cert_labs() self._compute_sars() diff --git a/src/sec_certs/rules.yaml b/src/sec_certs/rules.yaml index e1e7f1f8..f3d137cf 100644 --- a/src/sec_certs/rules.yaml +++ b/src/sec_certs/rules.yaml @@ -23,7 +23,7 @@ cc_cert_id: # Rapport de certification 2001/02v2 # Certification Report 2003/20 NL: - - "(?:NSCIB-|CC-|NSCIB-CC-)(?P<core>((?P<year>[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P<doc>(?:CR|MA|MR)[0-9]*))?" + - "(?:NSCIB-|CC-|NSCIB-CC-)(?P<core>((?P<year>[0-9]{2})-)?(?:-?[0-9]+)+)(?:-?(?P<doc>(?:CR|MA|MR)(?P<version>[0-9]*)))?" # Examples: # NSCIB-CC-22-0428888-CR2 (with year=22 and CR2) # NSCIB-CC-228723-CR (no year) @@ -57,11 +57,12 @@ cc_cert_id: # CRP208 # CERTIFICATION REPORT No. P123A ES: - - "(?P<year>[0-9]{4})[-‐](?P<project>[0-9]+)[-‐]INF[-‐](?P<counter>[0-9]+)[ -‐]{1,2}[vV](?P<version>[0-9])" + - "(?P<year>[0-9]{4})[-‐](?P<project>[0-9]+)[-‐]INF[-‐](?P<counter>[0-9]+)(?:[ -‐]{1,2}[vV](?P<version>[0-9]))?" # Examples: # 2006-4-INF-98 v2 # 2020-34-INF-3784- v1 # 2019-20-INF-3379-v1 + # 2011-14-INF-1095 (also without the version) KR: - "KECS[-‐](?P<word>ISIS|NISS|CISS)[-‐](?P<counter>[0-9]{2,4})[-‐](?P<year>[0-9]{4})" # XXX: Do not use KECS-CR as those refer to the certificate report and do not represent the certificate id. diff --git a/src/sec_certs/sample/cc.py b/src/sec_certs/sample/cc.py index 63c2cca5..a9aa2262 100644 --- a/src/sec_certs/sample/cc.py +++ b/src/sec_certs/sample/cc.py @@ -2,6 +2,7 @@ from __future__ import annotations import copy import re +from bisect import insort from collections import Counter, defaultdict from dataclasses import dataclass, field from datetime import date, datetime @@ -18,7 +19,7 @@ import sec_certs.utils.pdf from sec_certs import constants from sec_certs.cert_rules import SARS_IMPLIED_FROM_EAL, cc_rules, rules, security_level_csv_scan from sec_certs.configuration import config -from sec_certs.sample.cc_certificate_id import canonicalize, schemes +from sec_certs.sample.cc_certificate_id import CertificateId, canonicalize, schemes from sec_certs.sample.certificate import Certificate, References, logger from sec_certs.sample.certificate import Heuristics as BaseHeuristics from sec_certs.sample.certificate import PdfData as BasePdfData @@ -345,6 +346,8 @@ class CCCertificate( related_cves: set[str] | None = field(default=None) cert_lab: list[str] | None = field(default=None) cert_id: str | None = field(default=None) + prev_certificates: list[str] | None = field(default=None) + next_certificates: list[str] | None = field(default=None) st_references: References = field(default_factory=References) report_references: References = field(default_factory=References) @@ -1000,6 +1003,52 @@ class CCCertificate( cert.pdf_data.cert_keywords = cert_keywords return cert + def compute_heuristics_cert_versions(self, cert_ids: dict[str, CertificateId | None]) -> None: # noqa: C901 + """ + Fills in the previous and next certificate versions based on the cert ID. + """ + self.heuristics.prev_certificates = [] + self.heuristics.next_certificates = [] + own = cert_ids[self.dgst] + if own is None: + return + if self.scheme not in ("DE", "FR", "ES", "NL", "MY"): + # There is no version in the cert_id, so skip it + return + version = own.meta.get("version") + for other_dgst, other in cert_ids.items(): + if other_dgst == self.dgst: + # Skip ourselves + continue + if other is None or other.scheme != own.scheme: + # The other does not have cert ID or is different scheme or does not have a version. + continue + other_version = other.meta.get("version") + # Go over the own meta and compare, if some field other than version is different, bail out. + # If all except the version are the same, we have a match. + for key, value in own.meta.items(): + if key == "version": + continue + if self.scheme == "DE" and key == "year": + # For German certs we want to also ignore the year in comparison. + continue + if value != other.meta.get(key): + break + else: + if other_version is None and version is None: + # This means a duplicate ID is present, and it has no version. + # Just pass silently. + pass + elif version is None: + insort(self.heuristics.next_certificates, str(other)) + elif other_version is None: + insort(self.heuristics.prev_certificates, str(other)) + else: + if other_version < version: + insort(self.heuristics.prev_certificates, str(other)) + else: + insort(self.heuristics.next_certificates, str(other)) + def compute_heuristics_version(self) -> None: """ Fills in the heuristically obtained version of certified product into attribute in heuristics class. |
