aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/sec_certs/dataset/cc.py12
-rw-r--r--src/sec_certs/rules.yaml5
-rw-r--r--src/sec_certs/sample/cc.py51
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.