CREATE TABLE iana_tls_cipher_suites (
    value TEXT PRIMARY KEY,
    description TEXT,
    dtls TEXT,
    recommended TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_tls_signature_schemes (
    value TEXT PRIMARY KEY,
    description TEXT,
    dtls TEXT,
    recommended TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_tls_supported_groups (
    value TEXT PRIMARY KEY,
    description TEXT,
    dtls TEXT,
    recommended TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_tls_alerts (
    value TEXT PRIMARY KEY,
    description TEXT,
    dtls TEXT,
    recommended TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_tls_content_types (
    value TEXT PRIMARY KEY,
    description TEXT,
    dtls TEXT,
    recommended TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_ikev2_encryption_algorithms (
    value TEXT PRIMARY KEY,
    description TEXT,
    esp TEXT,
    ikev2 TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_ikev2_prf_algorithms (
    value TEXT PRIMARY KEY,
    description TEXT,
    status TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_ikev2_integrity_algorithms (
    value TEXT PRIMARY KEY,
    description TEXT,
    status TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_ikev2_dh_groups (
    value TEXT PRIMARY KEY,
    description TEXT,
    status TEXT,
    rfc_draft TEXT
);
CREATE TABLE iana_ikev2_authentication_methods (
    value TEXT PRIMARY KEY,
    description TEXT,
    status TEXT,
    rfc_draft TEXT
);
CREATE TABLE bsi_tr_02102_2_tls (
    name TEXT,
    iana_number TEXT,
    category TEXT,
    tls_version TEXT,
    valid_until INTEGER,
    reference TEXT,
    notes TEXT,
    PRIMARY KEY (name, tls_version, iana_number)
);
CREATE TABLE bsi_tr_02102_3_ikev2_encryption (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    laenge TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_3_ikev2_prf (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_3_ikev2_integrity (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_3_ikev2_dh_groups (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_3_ikev2_auth (
    verfahren TEXT,
    bit_laenge TEXT,
    hash_funktion TEXT,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung TEXT,
    PRIMARY KEY (verfahren, hash_funktion)
);
CREATE TABLE bsi_tr_02102_3_esp_encryption (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    aes_schluessellaenge TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_3_esp_integrity (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung_bis TEXT
);
CREATE TABLE bsi_tr_02102_3_ah_integrity (
    verfahren TEXT PRIMARY KEY,
    iana_nr TEXT,
    spezifikation TEXT,
    verwendung_bis TEXT
);
CREATE TABLE bsi_tr_02102_4_ssh_kex (
    key_exchange_method TEXT PRIMARY KEY,
    spezifikation TEXT,
    verwendung TEXT,
    bemerkung TEXT
);
CREATE TABLE bsi_tr_02102_4_ssh_encryption (
    verschluesselungsverfahren TEXT PRIMARY KEY,
    spezifikation TEXT,
    verwendung TEXT,
    bemerkung TEXT
);
CREATE TABLE bsi_tr_02102_4_ssh_mac (
    mac_verfahren TEXT PRIMARY KEY,
    spezifikation TEXT,
    verwendung TEXT
);
CREATE TABLE bsi_tr_02102_4_ssh_auth (
    signaturverfahren TEXT PRIMARY KEY,
    spezifikation TEXT,
    verwendung TEXT,
    bemerkung TEXT
);
CREATE INDEX idx_bsi_tls_category ON bsi_tr_02102_2_tls(category);
CREATE INDEX idx_bsi_tls_valid_until ON bsi_tr_02102_2_tls(valid_until);
CREATE INDEX idx_iana_cipher_recommended ON iana_tls_cipher_suites(recommended);
CREATE INDEX idx_iana_groups_recommended ON iana_tls_supported_groups(recommended);
CREATE TABLE bsi_tr_02102_1_key_requirements (
    algorithm_type TEXT NOT NULL,
    usage_context TEXT NOT NULL,
    min_key_length INTEGER,
    recommended_key_length INTEGER,
    valid_from INTEGER NOT NULL,
    valid_until INTEGER,
    notes TEXT,
    reference_section TEXT,
    PRIMARY KEY (algorithm_type, usage_context, valid_from)
);
CREATE INDEX idx_bsi_key_req_algo ON bsi_tr_02102_1_key_requirements(algorithm_type);
CREATE INDEX idx_bsi_key_req_context ON bsi_tr_02102_1_key_requirements(usage_context);
CREATE TABLE bsi_tr_02102_1_hash_requirements (
    algorithm TEXT PRIMARY KEY,
    min_output_bits INTEGER,
    recommended_for TEXT,
    valid_from INTEGER NOT NULL,
    deprecated INTEGER DEFAULT 0,
    notes TEXT,
    reference_section TEXT
);
CREATE TABLE bsi_tr_02102_1_symmetric_requirements (
    algorithm TEXT NOT NULL,
    mode TEXT,
    min_key_bits INTEGER,
    recommended_key_bits INTEGER,
    block_size_bits INTEGER,
    valid_from INTEGER NOT NULL,
    deprecated INTEGER DEFAULT 0,
    notes TEXT,
    reference_section TEXT,
    PRIMARY KEY (algorithm, mode, valid_from)
);
CREATE INDEX idx_bsi_sym_algo ON bsi_tr_02102_1_symmetric_requirements(algorithm);
CREATE INDEX idx_bsi_sym_mode ON bsi_tr_02102_1_symmetric_requirements(mode);
CREATE TABLE bsi_tr_02102_1_mac_requirements (
    algorithm TEXT PRIMARY KEY,
    min_key_bits INTEGER,
    min_tag_bits INTEGER,
    valid_from INTEGER NOT NULL,
    notes TEXT,
    reference_section TEXT
);
CREATE TABLE bsi_tr_02102_1_pqc_requirements (
    algorithm TEXT NOT NULL,
    parameter_set TEXT,
    usage_context TEXT NOT NULL,
    valid_from INTEGER NOT NULL,
    notes TEXT,
    reference_section TEXT,
    PRIMARY KEY (algorithm, parameter_set, usage_context)
);
CREATE INDEX idx_bsi_pqc_algo ON bsi_tr_02102_1_pqc_requirements(algorithm);
CREATE INDEX idx_bsi_pqc_context ON bsi_tr_02102_1_pqc_requirements(usage_context);
CREATE TABLE bsi_tr_02102_1_auth_requirements (
    method TEXT PRIMARY KEY,
    min_length INTEGER,
    min_entropy_bits INTEGER,
    max_attempts INTEGER,
    valid_from INTEGER NOT NULL,
    notes TEXT,
    reference_section TEXT
);
CREATE TABLE bsi_tr_02102_1_rng_requirements (
    class TEXT PRIMARY KEY,
    min_seed_entropy_bits INTEGER,
    valid_from INTEGER NOT NULL,
    deprecated INTEGER DEFAULT 0,
    notes TEXT,
    reference_section TEXT
);
CREATE TABLE bsi_tr_02102_1_metadata (
    key TEXT PRIMARY KEY,
    value TEXT
);
CREATE TABLE schema_version (
    version INTEGER PRIMARY KEY,
    applied_at TEXT NOT NULL,
    description TEXT
);
CREATE TABLE scans (
    scan_id INTEGER PRIMARY KEY AUTOINCREMENT,
    timestamp TEXT NOT NULL,
    hostname TEXT NOT NULL,
    ports TEXT NOT NULL,
    scan_duration_seconds REAL
);
CREATE TABLE sqlite_sequence(name,seq);
CREATE TABLE scanned_hosts (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    fqdn TEXT NOT NULL,
    ipv4 TEXT,
    ipv6 TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_cipher_suites (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    tls_version TEXT NOT NULL,
    cipher_suite_name TEXT NOT NULL,
    accepted BOOLEAN NOT NULL,
    iana_value TEXT,
    key_size INTEGER,
    is_anonymous BOOLEAN,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_supported_groups (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    group_name TEXT NOT NULL,
    iana_value INTEGER,
    openssl_nid INTEGER,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_certificates (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    position INTEGER NOT NULL,
    subject TEXT,
    issuer TEXT,
    serial_number TEXT,
    not_before TEXT,
    not_after TEXT,
    key_type TEXT,
    key_bits INTEGER,
    signature_algorithm TEXT,
    fingerprint_sha256 TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_vulnerabilities (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    vuln_type TEXT NOT NULL,
    vulnerable BOOLEAN NOT NULL,
    details TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_compliance_status (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    timestamp TEXT NOT NULL,
    check_type TEXT NOT NULL,
    item_name TEXT NOT NULL,
    iana_value TEXT,
    iana_recommended TEXT,
    bsi_approved BOOLEAN,
    bsi_valid_until INTEGER,
    passed BOOLEAN NOT NULL,
    severity TEXT,
    details TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_protocol_features (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    feature_type TEXT NOT NULL,
    supported BOOLEAN NOT NULL,
    details TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_session_features (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    feature_type TEXT NOT NULL,
    client_initiated BOOLEAN,
    secure BOOLEAN,
    session_id_supported BOOLEAN,
    ticket_supported BOOLEAN,
    attempted_resumptions INTEGER,
    successful_resumptions INTEGER,
    details TEXT,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE TABLE scan_http_headers (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER NOT NULL,
    port INTEGER NOT NULL,
    header_name TEXT NOT NULL,
    header_value TEXT,
    is_present BOOLEAN NOT NULL,
    FOREIGN KEY (scan_id) REFERENCES scans(scan_id) ON DELETE CASCADE
);
CREATE INDEX idx_scans_hostname ON scans(hostname);
CREATE INDEX idx_scans_timestamp ON scans(timestamp);
CREATE INDEX idx_scanned_hosts_scan ON scanned_hosts(scan_id);
CREATE INDEX idx_scanned_hosts_fqdn ON scanned_hosts(fqdn);
CREATE INDEX idx_cipher_suites_scan ON scan_cipher_suites(scan_id, port);
CREATE INDEX idx_cipher_suites_name ON scan_cipher_suites(cipher_suite_name);
CREATE INDEX idx_supported_groups_scan ON scan_supported_groups(scan_id);
CREATE INDEX idx_certificates_scan ON scan_certificates(scan_id);
CREATE INDEX idx_vulnerabilities_scan ON scan_vulnerabilities(scan_id);
CREATE INDEX idx_compliance_scan ON scan_compliance_status(scan_id);
CREATE INDEX idx_compliance_passed ON scan_compliance_status(passed);
CREATE INDEX idx_protocol_features_scan ON scan_protocol_features(scan_id);
CREATE INDEX idx_session_features_scan ON scan_session_features(scan_id);
CREATE INDEX idx_http_headers_scan ON scan_http_headers(scan_id);
CREATE VIEW v_cipher_suites_with_compliance AS
SELECT
    scs.scan_id,
    scs.port,
    scs.tls_version,
    scs.cipher_suite_name,
    scs.accepted,
    scs.iana_value,
    scs.key_size,
    scs.is_anonymous,
    sc.iana_recommended,
    sc.bsi_approved,
    sc.bsi_valid_until,
    sc.passed as compliant,
    CASE
        WHEN scs.accepted = 1 THEN sc.iana_recommended
        ELSE iana.recommended
    END as iana_recommended_final,
    CASE
        WHEN scs.accepted = 1 THEN sc.bsi_approved
        ELSE (bsi.name IS NOT NULL)
    END as bsi_approved_final,
    CASE
        WHEN scs.accepted = 1 THEN sc.bsi_valid_until
        ELSE bsi.valid_until
    END as bsi_valid_until_final
FROM scan_cipher_suites scs
LEFT JOIN scan_compliance_status sc
    ON scs.scan_id = sc.scan_id
    AND scs.port = sc.port
    AND sc.check_type = 'cipher_suite'
    AND scs.cipher_suite_name = sc.item_name
LEFT JOIN iana_tls_cipher_suites iana
    ON scs.cipher_suite_name = iana.description
LEFT JOIN bsi_tr_02102_2_tls bsi
    ON scs.cipher_suite_name = bsi.name
    AND scs.tls_version = bsi.tls_version
    AND bsi.category = 'cipher_suite'
/* v_cipher_suites_with_compliance(scan_id,port,tls_version,cipher_suite_name,accepted,iana_value,key_size,is_anonymous,iana_recommended,bsi_approved,bsi_valid_until,compliant,iana_recommended_final,bsi_approved_final,bsi_valid_until_final) */;
CREATE VIEW v_supported_groups_with_compliance AS
SELECT
    ssg.scan_id,
    ssg.port,
    ssg.group_name,
    ssg.iana_value,
    ssg.openssl_nid,
    sc.iana_recommended,
    sc.bsi_approved,
    sc.bsi_valid_until,
    sc.passed as compliant
FROM scan_supported_groups ssg
LEFT JOIN scan_compliance_status sc
    ON ssg.scan_id = sc.scan_id
    AND ssg.port = sc.port
    AND sc.check_type = 'supported_group'
    AND ssg.group_name = sc.item_name
/* v_supported_groups_with_compliance(scan_id,port,group_name,iana_value,openssl_nid,iana_recommended,bsi_approved,bsi_valid_until,compliant) */;
CREATE VIEW v_certificates_with_compliance AS
SELECT
    c.scan_id,
    c.port,
    c.position,
    c.subject,
    c.issuer,
    c.serial_number,
    c.not_before,
    c.not_after,
    c.key_type,
    c.key_bits,
    c.signature_algorithm,
    c.fingerprint_sha256,
    MAX(cs.passed) as compliant,
    MAX(cs.details) as compliance_details
FROM scan_certificates c
LEFT JOIN scan_compliance_status cs
    ON c.scan_id = cs.scan_id
    AND c.port = cs.port
    AND cs.check_type = 'certificate'
    AND cs.item_name = (c.key_type || ' ' || c.key_bits || ' Bit')
GROUP BY c.scan_id, c.port, c.position, c.subject, c.issuer, c.serial_number,
         c.not_before, c.not_after, c.key_type, c.key_bits,
         c.signature_algorithm, c.fingerprint_sha256
/* v_certificates_with_compliance(scan_id,port,position,subject,issuer,serial_number,not_before,not_after,key_type,key_bits,signature_algorithm,fingerprint_sha256,compliant,compliance_details) */;
CREATE VIEW v_port_compliance_summary AS
SELECT
    scan_id,
    port,
    check_type,
    COUNT(*) as total,
    SUM(CASE WHEN passed = 1 THEN 1 ELSE 0 END) as passed,
    ROUND(CAST(SUM(CASE WHEN passed = 1 THEN 1 ELSE 0 END) AS REAL) / COUNT(*) * 100, 1) as percentage
FROM scan_compliance_status
GROUP BY scan_id, port, check_type
/* v_port_compliance_summary(scan_id,port,check_type,total,passed,percentage) */;
CREATE VIEW v_missing_bsi_groups AS
SELECT
    s.scan_id,
    s.ports,
    bsi.name as group_name,
    bsi.tls_version,
    bsi.valid_until
FROM scans s
CROSS JOIN (
    SELECT DISTINCT name, tls_version, valid_until
    FROM bsi_tr_02102_2_tls
    WHERE category = 'dh_group'
) bsi
WHERE NOT EXISTS (
    SELECT 1
    FROM scan_supported_groups ssg
    WHERE ssg.scan_id = s.scan_id
    AND LOWER(ssg.group_name) = LOWER(bsi.name)
)
/* v_missing_bsi_groups(scan_id,ports,group_name,tls_version,valid_until) */;
CREATE VIEW v_missing_iana_groups AS
SELECT
    s.scan_id,
    s.ports,
    iana.description as group_name,
    iana.value as iana_value
FROM scans s
CROSS JOIN (
    SELECT description, value
    FROM iana_tls_supported_groups
    WHERE recommended = 'Y'
) iana
WHERE NOT EXISTS (
    SELECT 1
    FROM scan_supported_groups ssg
    WHERE ssg.scan_id = s.scan_id
    AND LOWER(ssg.group_name) = LOWER(iana.description)
)
AND NOT EXISTS (
    SELECT 1
    FROM bsi_tr_02102_2_tls bsi
    WHERE LOWER(bsi.name) = LOWER(iana.description)
    AND bsi.category = 'dh_group'
)
/* v_missing_iana_groups(scan_id,ports,group_name,iana_value) */;
CREATE TABLE csv_export_metadata (
    id INTEGER PRIMARY KEY,
    export_type TEXT UNIQUE NOT NULL,
    headers TEXT NOT NULL,
    description TEXT
);
