From 5bbb144a319393e0b2bdd06f403905f28528e459 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 11 Dec 2023 12:46:47 +0100 Subject: [PATCH] Initial proof-of-concept SM-DP+ for GSMA consumer eSIM RSP This commit introduces * the osmo-smdpp.py program implementing the main procedures and the HTTP/REST based ES9+ * python modules for ES8+ and non-volatile RSP Session State storage * the ASN.1 source files required to parse/encode RSP * 3GPP test certificates from SGP.26 * an unsigned profile package (UPP) of a SAIP v2.3 TS48 test profile As I couldn't get the 'Klein' tls support to work, the SM-DP+ code currently does not support HTTPS/TLS but plan HTTP, so you either have to modify your LPA to use HTTP instead of HTTPS, or put a TLS proxy in front. I have successfully installed an eSIM profile on a test eUICC that contains certificate/key data within the test CI defined in GSMA SGP.26 Change-Id: I6232847432dc6920cd2bd08c84d7099c29ca1c11 --- .checkpatch.conf | 2 + docs/index.rst | 1 + docs/osmo-smdpp.rst | 93 +++ osmo-smdpp.py | 594 +++++++++++++ pySim/esim/__init__.py | 16 + pySim/esim/asn1/rsp/PKIX1Explicit88.asn | 657 +++++++++++++++ pySim/esim/asn1/rsp/PKIX1Implicit88.asn | 343 ++++++++ pySim/esim/asn1/rsp/rsp.asn | 785 ++++++++++++++++++ pySim/esim/es8p.py | 185 +++++ pySim/esim/rsp.py | 100 +++ requirements.txt | 1 + .../CertificateIssuer/CERT_CI_ECDSA_BRP.der | Bin 0 -> 597 bytes .../CertificateIssuer/CERT_CI_ECDSA_BRP.pem | 15 + .../CertificateIssuer/CERT_CI_ECDSA_NIST.der | Bin 0 -> 596 bytes .../CertificateIssuer/CERT_CI_ECDSA_NIST.pem | 15 + smdpp-data/certs/CertificateIssuer/CI-csr.cnf | 25 + .../DPauth/CERT_S_SM_DP2auth_ECDSA_BRP.der | Bin 0 -> 575 bytes .../DPauth/CERT_S_SM_DP2auth_ECDSA_NIST.der | Bin 0 -> 573 bytes .../DPauth/CERT_S_SM_DPauth_ECDSA_BRP.der | Bin 0 -> 573 bytes .../DPauth/CERT_S_SM_DPauth_ECDSA_NIST.der | Bin 0 -> 572 bytes .../DPauth/PK_S_SM_DP2auth_ECDSA_BRP.pem | 4 + .../DPauth/PK_S_SM_DP2auth_ECDSA_NIST.pem | 4 + .../certs/DPauth/PK_S_SM_DPauth_ECDSA_BRP.pem | 4 + .../DPauth/PK_S_SM_DPauth_ECDSA_NIST.pem | 4 + .../DPauth/SK_S_SM_DP2auth_ECDSA_BRP.pem | 8 + .../DPauth/SK_S_SM_DP2auth_ECDSA_NIST.pem | 8 + .../certs/DPauth/SK_S_SM_DPauth_ECDSA_BRP.pem | 8 + .../DPauth/SK_S_SM_DPauth_ECDSA_NIST.pem | 8 + smdpp-data/certs/DPauth/data_sig.der | 1 + .../certs/DPpb/CERT_S_SM_DP2pb_ECDSA_BRP.der | Bin 0 -> 574 bytes .../certs/DPpb/CERT_S_SM_DP2pb_ECDSA_NIST.der | Bin 0 -> 575 bytes .../certs/DPpb/CERT_S_SM_DPpb_ECDSA_BRP.der | Bin 0 -> 573 bytes .../certs/DPpb/CERT_S_SM_DPpb_ECDSA_NIST.der | Bin 0 -> 573 bytes .../certs/DPpb/PK_S_SM_DP2pb_ECDSA_BRP.pem | 4 + .../certs/DPpb/PK_S_SM_DP2pb_ECDSA_NIST.pem | 4 + .../certs/DPpb/PK_S_SM_DPpb_ECDSA_BRP.pem | 4 + .../certs/DPpb/PK_S_SM_DPpb_ECDSA_NIST.pem | 4 + .../certs/DPpb/SK_S_SM_DP2pb_ECDSA_BRP.pem | 8 + .../certs/DPpb/SK_S_SM_DP2pb_ECDSA_NIST.pem | 8 + .../certs/DPpb/SK_S_SM_DPpb_ECDSA_BRP.pem | 8 + .../certs/DPpb/SK_S_SM_DPpb_ECDSA_NIST.pem | 8 + .../certs/DPtls/CERT_S_SM_DP2_TLS.csr.cnf | 10 + smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.der | Bin 0 -> 647 bytes .../certs/DPtls/CERT_S_SM_DP2_TLS.ext.cnf | 14 + .../certs/DPtls/CERT_S_SM_DP4_TLS.csr.cnf | 10 + smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.der | Bin 0 -> 647 bytes .../certs/DPtls/CERT_S_SM_DP4_TLS.ext.cnf | 14 + .../certs/DPtls/CERT_S_SM_DP8_TLS.csr.cnf | 10 + smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.der | Bin 0 -> 647 bytes .../certs/DPtls/CERT_S_SM_DP8_TLS.ext.cnf | 14 + .../certs/DPtls/CERT_S_SM_DP_TLS.csr.cnf | 10 + .../certs/DPtls/CERT_S_SM_DP_TLS.ext.cnf | 14 + .../certs/DPtls/CERT_S_SM_DP_TLS_BRP.der | Bin 0 -> 646 bytes .../certs/DPtls/CERT_S_SM_DP_TLS_NIST.der | Bin 0 -> 647 bytes .../Expired 2021/CERT_S_SM_DP2_TLS.der | Bin 0 -> 646 bytes .../Expired 2021/CERT_S_SM_DP4_TLS.der | Bin 0 -> 647 bytes .../Expired 2021/CERT_S_SM_DP8_TLS.der | Bin 0 -> 647 bytes .../Expired 2021/CERT_S_SM_DP_TLS_BRP.der | Bin 0 -> 646 bytes .../Expired 2021/CERT_S_SM_DP_TLS_NIST.der | Bin 0 -> 647 bytes .../Expired 2022/CERT_S_SM_DP2_TLS.der | Bin 0 -> 647 bytes .../Expired 2022/CERT_S_SM_DP4_TLS.der | Bin 0 -> 646 bytes .../Expired 2022/CERT_S_SM_DP8_TLS.der | Bin 0 -> 646 bytes .../Expired 2022/CERT_S_SM_DP_TLS_BRP.der | Bin 0 -> 646 bytes .../Expired 2022/CERT_S_SM_DP_TLS_NIST.der | Bin 0 -> 645 bytes .../Expired 2023/CERT_S_SM_DP2_TLS.der | Bin 0 -> 646 bytes .../Expired 2023/CERT_S_SM_DP4_TLS.der | Bin 0 -> 647 bytes .../Expired 2023/CERT_S_SM_DP8_TLS.der | Bin 0 -> 648 bytes .../Expired 2023/CERT_S_SM_DP_TLS_BRP.der | Bin 0 -> 648 bytes .../Expired 2023/CERT_S_SM_DP_TLS_NIST.der | Bin 0 -> 646 bytes .../certs/DPtls/PK_S_SM_DP2_TLS_NIST.pem | 4 + smdpp-data/certs/DPtls/PK_S_SM_DP4_TLS.pem | 4 + smdpp-data/certs/DPtls/PK_S_SM_DP8_TLS.pem | 4 + smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_BRP.pem | 4 + .../certs/DPtls/PK_S_SM_DP_TLS_NIST.pem | 4 + .../certs/DPtls/SK_S_SM_DP2_TLS_NIST.pem | 8 + smdpp-data/certs/DPtls/SK_S_SM_DP4_TLS.pem | 8 + smdpp-data/certs/DPtls/SK_S_SM_DP8_TLS.pem | 8 + smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_BRP.pem | 8 + .../certs/DPtls/SK_S_SM_DP_TLS_NIST.pem | 8 + smdpp-data/certs/README | 1 + ...48 V2 eSIM_GTP_SAIP2.1_NoBERTLV.rename2der | Bin 0 -> 12207 bytes ...48 V2 eSIM_GTP_SAIP2.3_NoBERTLV.rename2der | Bin 0 -> 12251 bytes tests/test_esim.py | 51 ++ tests/test_esim_bsp.py | 26 + 84 files changed, 3163 insertions(+) create mode 100644 .checkpatch.conf create mode 100644 docs/osmo-smdpp.rst create mode 100755 osmo-smdpp.py create mode 100644 pySim/esim/asn1/rsp/PKIX1Explicit88.asn create mode 100644 pySim/esim/asn1/rsp/PKIX1Implicit88.asn create mode 100644 pySim/esim/asn1/rsp/rsp.asn create mode 100644 pySim/esim/es8p.py create mode 100644 pySim/esim/rsp.py create mode 100644 smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_BRP.der create mode 100644 smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_NIST.der create mode 100644 smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/CertificateIssuer/CI-csr.cnf create mode 100644 smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_BRP.der create mode 100644 smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_NIST.der create mode 100644 smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_BRP.der create mode 100644 smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_NIST.der create mode 100644 smdpp-data/certs/DPauth/PK_S_SM_DP2auth_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPauth/PK_S_SM_DP2auth_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPauth/PK_S_SM_DPauth_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPauth/PK_S_SM_DPauth_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPauth/SK_S_SM_DP2auth_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPauth/SK_S_SM_DP2auth_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPauth/SK_S_SM_DPauth_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPauth/SK_S_SM_DPauth_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPauth/data_sig.der create mode 100644 smdpp-data/certs/DPpb/CERT_S_SM_DP2pb_ECDSA_BRP.der create mode 100644 smdpp-data/certs/DPpb/CERT_S_SM_DP2pb_ECDSA_NIST.der create mode 100644 smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_BRP.der create mode 100644 smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_NIST.der create mode 100644 smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_BRP.pem create mode 100644 smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_NIST.pem create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.csr.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.der create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.ext.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.csr.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.der create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.ext.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.csr.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.der create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.ext.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.csr.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.ext.cnf create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS_BRP.der create mode 100644 smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS_NIST.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP2_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP4_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP8_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP_TLS_BRP.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP_TLS_NIST.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP2_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP4_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP8_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP_TLS_BRP.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP_TLS_NIST.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP2_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP4_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP8_TLS.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP_TLS_BRP.der create mode 100644 smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP_TLS_NIST.der create mode 100644 smdpp-data/certs/DPtls/PK_S_SM_DP2_TLS_NIST.pem create mode 100644 smdpp-data/certs/DPtls/PK_S_SM_DP4_TLS.pem create mode 100644 smdpp-data/certs/DPtls/PK_S_SM_DP8_TLS.pem create mode 100644 smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_BRP.pem create mode 100644 smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_NIST.pem create mode 100644 smdpp-data/certs/DPtls/SK_S_SM_DP2_TLS_NIST.pem create mode 100644 smdpp-data/certs/DPtls/SK_S_SM_DP4_TLS.pem create mode 100644 smdpp-data/certs/DPtls/SK_S_SM_DP8_TLS.pem create mode 100644 smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_BRP.pem create mode 100644 smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_NIST.pem create mode 100644 smdpp-data/certs/README create mode 100644 smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.1_NoBERTLV.rename2der create mode 100644 smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.3_NoBERTLV.rename2der create mode 100755 tests/test_esim.py diff --git a/.checkpatch.conf b/.checkpatch.conf new file mode 100644 index 00000000..8fdd97e6 --- /dev/null +++ b/.checkpatch.conf @@ -0,0 +1,2 @@ +--exclude ^pySim/esim/asn1/.*\.asn$ +--exclude ^smdpp-data/.*$ diff --git a/docs/index.rst b/docs/index.rst index a46aee0a..bcbc7f06 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -42,6 +42,7 @@ pySim consists of several parts: trace legacy library + osmo-smdpp Indices and tables diff --git a/docs/osmo-smdpp.rst b/docs/osmo-smdpp.rst new file mode 100644 index 00000000..5687fc60 --- /dev/null +++ b/docs/osmo-smdpp.rst @@ -0,0 +1,93 @@ +osmo-smdpp +========== + +`osmo-smdpp` is a proof-of-concept implementation of a minimal **SM-DP+** as specified for the *GSMA +Consumer eSIM Remote SIM provisioning*. + +At least at this point, it is intended to be used for research and development, and not as a +production SM-DP+. + +Unless you are a GSMA SAS-SM accredited SM-DP+ operator and have related DPtls, DPauth and DPpb +certificates signed by the GSMA CI, you **can not use osmo-smdpp with regular production eUICC**. +This is due to how the GSMA eSIM security architecture works. You can, however, use osmo-smdpp with +so-called *test-eUICC*, which contain certificates/keys signed by GSMA test certificates as laid out +in GSMA SGP.26. + +At this point, osmo-smdpp does not support anything beyond the bare minimum required to download +eSIM profiles to an eUICC. Specifically, there is no ES2+ interface, and there is no built-in +support for profile personalization yet. + +osmo-smdpp currently + +* always provides the exact same profile to every request. The profile always has the same IMSI and + ICCID. +* **is absolutely insecure**, as it + + * does not perform any certificate verification + * does not evaluate/consider any *Matching ID* or *Confirmation Code* + * stores the sessions in an unencrypted _python shelve_ and is hence leaking one-time key materials + used for profile encryption and signing. + + +Running osmo-smdpp +------------------ + +osmo-smdpp does not have built-in TLS support as the used *twisted* framework appears to have +problems when using the example elliptic curve certificates (both NIST and Brainpool) from GSMA. + +So in order to use it, you have to put it behind a TLS reverse proxy, which terminates the ES9+ +HTTPS from the LPA, and then forwards it as plain HTTP to osmo-smdpp. + +nginx as TLS proxy +~~~~~~~~~~~~~~~~~~ + +If you use `nginx` as web server, you can use the following configuration snippet:: + + upstream smdpp { + server localhost:8000; + } + + server { + listen 443 ssl; + server_name testsmdpplus1.example.com; + + ssl_certificate /my/path/to/pysim/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS_NIST.pem; + ssl_certificate_key /my/path/to/pysim/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_NIST.pem; + + location / { + proxy_read_timeout 600s; + + proxy_hide_header X-Powered-By; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto https; + proxy_set_header X-Forwarded-Port $proxy_port; + proxy_set_header Host $host; + + proxy_pass http://smdpp/; + } + } + +You can of course achieve a similar functionality with apache, lighttpd or many other web server +software. + + +osmo-smdpp +~~~~~~~~~~ + +osmo-smdpp currently doesn't have any configuration file or command line options. You just run it, +and it will bind its plain-HTTP ES9+ interface to local TCP port 8000. + +The `smdpp-data/certs`` directory contains the DPtls, DPauth and DPpb as well as CI certificates +used; they are copied from GSMA SGP.26 v2. + +The `smdpp-data/upp` directory contains the UPP (Unprotected Profile Package) used. + + +DNS setup for your LPA +~~~~~~~~~~~~~~~~~~~~~~ + +The LPA must resolve `testsmdpplus1.example.com` to the IP address of your TLS proxy. + +It must also accept the TLS certificates used by your TLS proxy. + diff --git a/osmo-smdpp.py b/osmo-smdpp.py new file mode 100755 index 00000000..6ae5be88 --- /dev/null +++ b/osmo-smdpp.py @@ -0,0 +1,594 @@ +#!/usr/bin/env python3 + +# Early proof-of-concept towards a SM-DP+ HTTP service for GSMA consumer eSIM RSP +# +# (C) 2023-2024 by Harald Welte +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import json +import sys +import argparse +import uuid +import os +import functools +from typing import Optional, Dict, List +from pprint import pprint as pp + +import base64 +from base64 import b64decode +from klein import Klein +from twisted.web.iweb import IRequest +import asn1tools + +from pySim.utils import h2b, b2h, swap_nibbles + +import pySim.esim.rsp as rsp +from pySim.esim.es8p import * + +# HACK: make this configurable +DATA_DIR = './smdpp-data' +HOSTNAME = 'testsmdpplus1.example.com' # must match certificates! + + +def b64encode2str(req: bytes) -> str: + """Encode given input bytes as base64 and return result as string.""" + return base64.b64encode(req).decode('ascii') + +def set_headers(request: IRequest): + """Set the request headers as mandatory by GSMA eSIM RSP.""" + request.setHeader('Content-Type', 'application/json;charset=UTF-8') + request.setHeader('X-Admin-Protocol', 'gsma/rsp/v2.1.0') + +def build_status_code(subject_code: str, reason_code: str, subject_id: Optional[str], message: Optional[str]) -> Dict: + r = {'subjectCode': subject_code, 'reasonCode': reason_code } + if subject_id: + r['subjectIdentifier'] = subject_id + if message: + r['message'] = message + return r + +def build_resp_header(js: dict, status: str = 'Executed-Success', status_code_data = None) -> None: + # SGP.22 v3.0 6.5.1.4 + js['header'] = { + 'functionExecutionStatus': { + 'status': status, + } + } + if status_code_data: + js['header']['functionExecutionStatus']['statusCodeData'] = status_code_data + +from cryptography.hazmat.primitives.asymmetric.utils import decode_dss_signature, encode_dss_signature +from cryptography.hazmat.primitives.serialization import load_pem_private_key, Encoding, PublicFormat, PrivateFormat, NoEncryption +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives import hashes +from cryptography.exceptions import InvalidSignature +from cryptography import x509 + + +def ecdsa_dss_to_tr03111(sig: bytes) -> bytes: + """convert from DER format to BSI TR-03111; first get long integers; then convert those to bytes.""" + r, s = decode_dss_signature(sig) + return r.to_bytes(32, 'big') + s.to_bytes(32, 'big') + +def ecdsa_tr03111_to_dss(sig: bytes) -> bytes: + """convert an ECDSA signature from BSI TR-03111 format to DER: first get long integers; then encode those.""" + assert len(sig) == 64 + r = int.from_bytes(sig[0:32], 'big') + s = int.from_bytes(sig[32:32*2], 'big') + return encode_dss_signature(r, s) + + +class CertAndPrivkey: + """A pair of certificate and private key, as used for ECDSA signing.""" + def __init__(self, required_policy_oid: Optional[x509.ObjectIdentifier] = None, + cert: Optional[x509.Certificate] = None, priv_key = None): + self.required_policy_oid = required_policy_oid + self.cert = cert + self.priv_key = priv_key + + def cert_from_der_file(self, path: str): + with open(path, 'rb') as f: + cert = x509.load_der_x509_certificate(f.read()) + if self.required_policy_oid: + # verify it is the right type of certificate (id-rspRole-dp-auth, id-rspRole-dp-auth-v2, etc.) + assert cert_policy_has_oid(cert, self.required_policy_oid) + self.cert = cert + + def privkey_from_pem_file(self, path: str, password: Optional[str] = None): + with open(path, 'rb') as f: + self.priv_key = load_pem_private_key(f.read(), password) + + def ecdsa_sign(self, plaintext: bytes) -> bytes: + """Sign some input-data using an ECDSA signature compliant with SGP.22, + which internally refers to Global Platform 2.2 Annex E, which in turn points + to BSI TS-03111 which states "concatengated raw R + S values". """ + sig = self.priv_key.sign(plaintext, ec.ECDSA(hashes.SHA256())) + # convert from DER format to BSI TR-03111; first get long integers; then convert those to bytes + return ecdsa_dss_to_tr03111(sig) + + def get_authority_key_identifier(self) -> x509.AuthorityKeyIdentifier: + """Return the AuthorityKeyIdentifier X.509 extension of the certificate.""" + return list(filter(lambda x: isinstance(x.value, x509.AuthorityKeyIdentifier), self.cert.extensions))[0].value + + def get_subject_alt_name(self) -> x509.SubjectAlternativeName: + """Return the SubjectAlternativeName X.509 extension of the certificate.""" + return list(filter(lambda x: isinstance(x.value, x509.SubjectAlternativeName), self.cert.extensions))[0].value + + def get_cert_as_der(self) -> bytes: + """Return certificate encoded as DER.""" + return self.cert.public_bytes(Encoding.DER) + + def get_curve(self) -> ec.EllipticCurve: + return self.cert.public_key().public_numbers().curve + + + + +class ApiError(Exception): + def __init__(self, subject_code: str, reason_code: str, message: Optional[str] = None, + subject_id: Optional[str] = None): + self.status_code = build_status_code(subject_code, reason_code, subject_id, message) + + def encode(self) -> str: + """Encode the API Error into a responseHeader string.""" + js = {} + build_resp_header(js, 'Failed', self.status_code) + return json.dumps(js) + +def cert_policy_has_oid(cert: x509.Certificate, match_oid: x509.ObjectIdentifier) -> bool: + """Determine if given certificate has a certificatePolicy extension of matching OID.""" + for policy_ext in filter(lambda x: isinstance(x.value, x509.CertificatePolicies), cert.extensions): + if any(policy.policy_identifier == match_oid for policy in policy_ext.value._policies): + return True + return False + +ID_RSP = "2.23.146.1" +ID_RSP_CERT_OBJECTS = '.'.join([ID_RSP, '2']) +ID_RSP_ROLE = '.'.join([ID_RSP_CERT_OBJECTS, '1']) + +class oid: + id_rspRole_ci = x509.ObjectIdentifier(ID_RSP_ROLE + '.0') + id_rspRole_euicc_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.1') + id_rspRole_eum_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.2') + id_rspRole_dp_tls_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.3') + id_rspRole_dp_auth_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.4') + id_rspRole_dp_pb_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.5') + id_rspRole_ds_tls_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.6') + id_rspRole_ds_auth_v2 = x509.ObjectIdentifier(ID_RSP_ROLE + '.7') + +class SmDppHttpServer: + app = Klein() + + @staticmethod + def load_certs_from_path(path: str) -> List[x509.Certificate]: + """Load all DER + PEM files from given directory path and return them as list of x509.Certificate + instances.""" + certs = [] + for dirpath, dirnames, filenames in os.walk(path): + for filename in filenames: + cert = None + if filename.endswith('.der'): + with open(os.path.join(dirpath, filename), 'rb') as f: + cert = x509.load_der_x509_certificate(f.read()) + elif filename.endswith('.pem'): + with open(os.path.join(dirpath, filename), 'rb') as f: + cert = x509.load_pem_x509_certificate(f.read()) + if cert: + # verify it is a CI certificate (keyCertSign + i-rspRole-ci) + if not cert_policy_has_oid(cert, oid.id_rspRole_ci): + raise ValueError("alleged CI certificate %s doesn't have CI policy" % filename) + certs.append(cert) + return certs + + def ci_get_cert_for_pkid(self, ci_pkid: bytes) -> Optional[x509.Certificate]: + """Find CI certificate for given key identifier.""" + for cert in self.ci_certs: + print("cert: %s" % cert) + subject_exts = list(filter(lambda x: isinstance(x.value, x509.SubjectKeyIdentifier), cert.extensions)) + print(subject_exts) + subject_pkid = subject_exts[0].value + print(subject_pkid) + if subject_pkid and subject_pkid.key_identifier == ci_pkid: + return cert + return None + + def __init__(self, server_hostname: str, ci_certs_path: str, use_brainpool: bool = False): + self.server_hostname = server_hostname + self.ci_certs = self.load_certs_from_path(ci_certs_path) + # load DPauth cert + key + self.dp_auth = CertAndPrivkey(oid.id_rspRole_dp_auth_v2) + cert_dir = os.path.join(DATA_DIR, 'certs') + if use_brainpool: + self.dp_auth.cert_from_der_file(os.path.join(cert_dir, 'DPauth', 'CERT_S_SM_DPauth_ECDSA_BRP.der')) + self.dp_auth.privkey_from_pem_file(os.path.join(cert_dir, 'DPauth', 'SK_S_SM_DPauth_ECDSA_BRP.pem')) + else: + self.dp_auth.cert_from_der_file(os.path.join(cert_dir, 'DPauth', 'CERT_S_SM_DPauth_ECDSA_NIST.der')) + self.dp_auth.privkey_from_pem_file(os.path.join(cert_dir, 'DPauth', 'SK_S_SM_DPauth_ECDSA_NIST.pem')) + # load DPpb cert + key + self.dp_pb = CertAndPrivkey(oid.id_rspRole_dp_pb_v2) + if use_brainpool: + self.dp_pb.cert_from_der_file(os.path.join(cert_dir, 'DPpb', 'CERT_S_SM_DPpb_ECDSA_BRP.der')) + self.dp_pb.privkey_from_pem_file(os.path.join(cert_dir, 'DPpb', 'SK_S_SM_DPpb_ECDSA_BRP.pem')) + else: + self.dp_pb.cert_from_der_file(os.path.join(cert_dir, 'DPpb', 'CERT_S_SM_DPpb_ECDSA_NIST.der')) + self.dp_pb.privkey_from_pem_file(os.path.join(cert_dir, 'DPpb', 'SK_S_SM_DPpb_ECDSA_NIST.pem')) + self.rss = rsp.RspSessionStore(os.path.join(DATA_DIR, "sm-dp-sessions")) + + @app.handle_errors(ApiError) + def handle_apierror(self, request: IRequest, failure): + request.setResponseCode(200) + pp(failure) + return failure.value.encode() + + @staticmethod + def _ecdsa_verify(cert: x509.Certificate, signature: bytes, data: bytes) -> bool: + pubkey = cert.public_key() + dss_sig = ecdsa_tr03111_to_dss(signature) + try: + pubkey.verify(dss_sig, data, ec.ECDSA(hashes.SHA256())) + return True + except InvalidSignature: + return False + + @staticmethod + def rsp_api_wrapper(func): + """Wrapper that can be used as decorator in order to perform common REST API endpoint entry/exit + functionality, such as JSON decoding/encoding and debug-printing.""" + @functools.wraps(func) + def _api_wrapper(self, request: IRequest): + # TODO: evaluate User-Agent + X-Admin-Protocol header + # TODO: reject any non-JSON Content-type + + content = json.loads(request.content.read()) + print("Rx JSON: %s" % content) + set_headers(request) + + output = func(self, request, content) or {} + + build_resp_header(output) + print("Tx JSON: %s" % output) + return json.dumps(output) + return _api_wrapper + + @app.route('/gsma/rsp2/es9plus/initiateAuthentication', methods=['POST']) + @rsp_api_wrapper + def initiateAutentication(self, request: IRequest, content: dict) -> dict: + """See ES9+ InitiateAuthentication SGP.22 Section 5.6.1""" + # Verify that the received address matches its own SM-DP+ address, where the comparison SHALL be + # case-insensitive. Otherwise, the SM-DP+ SHALL return a status code "SM-DP+ Address - Refused". + if content['smdpAddress'] != self.server_hostname: + raise ApiError('8.8.1', '3.8', 'Invalid SM-DP+ Address') + + euiccChallenge = b64decode(content['euiccChallenge']) + if len(euiccChallenge) != 16: + raise ValueError + + euiccInfo1_bin = b64decode(content['euiccInfo1']) + euiccInfo1 = rsp.asn1.decode('EUICCInfo1', euiccInfo1_bin) + print("Rx euiccInfo1: %s" % euiccInfo1) + #euiccInfo1['svn'] + + # TODO: If euiccCiPKIdListForSigningV3 is present ... + + pkid_list = euiccInfo1['euiccCiPKIdListForSigning'] + if 'euiccCiPKIdListForSigningV3' in euiccInfo1: + pkid_list = pkid_list + euiccInfo1['euiccCiPKIdListForSigningV3'] + # verify it supports one of the keys indicated by euiccCiPKIdListForSigning + if not any(self.ci_get_cert_for_pkid(x) for x in pkid_list): + raise ApiError('8.8.2', '3.1', 'None of the proposed Public Key Identifiers is supported by the SM-DP+') + + # TODO: Determine the set of CERT.DPauth.SIG that satisfy the following criteria: + # * Part of a certificate chain ending at one of the eSIM CA RootCA Certificate, whose Public Keys is + # supported by the eUICC (indicated by euiccCiPKIdListForVerification). + # * Using a certificate chain that the eUICC and the LPA both support: + #euiccInfo1['euiccCiPKIdListForVerification'] + # raise ApiError('8.8.4', '3.7', 'The SM-DP+ has no CERT.DPauth.SIG which chains to one of the eSIM CA Root CA CErtificate with a Public Key supported by the eUICC') + + # Generate a TransactionID which is used to identify the ongoing RSP session. The TransactionID + # SHALL be unique within the scope and lifetime of each SM-DP+. + transactionId = uuid.uuid4().hex + assert not transactionId in self.rss + + # Generate a serverChallenge for eUICC authentication attached to the ongoing RSP session. + serverChallenge = os.urandom(16) + + # Generate a serverSigned1 data object as expected by the eUICC and described in section 5.7.13 "ES10b.AuthenticateServer". If and only if both eUICC and LPA indicate crlStaplingV3Support, the SM-DP+ SHALL indicate crlStaplingV3Used in sessionContext. + serverSigned1 = { + 'transactionId': h2b(transactionId), + 'euiccChallenge': euiccChallenge, + 'serverAddress': self.server_hostname, + 'serverChallenge': serverChallenge, + } + print("Tx serverSigned1: %s" % serverSigned1) + serverSigned1_bin = rsp.asn1.encode('ServerSigned1', serverSigned1) + print("Tx serverSigned1: %s" % rsp.asn1.decode('ServerSigned1', serverSigned1_bin)) + output = {} + output['serverSigned1'] = b64encode2str(serverSigned1_bin) + + # Generate a signature (serverSignature1) as described in section 5.7.13 "ES10b.AuthenticateServer" using the SK related to the selected CERT.DPauth.SIG. + # serverSignature1 SHALL be created using the private key associated to the RSP Server Certificate for authentication, and verified by the eUICC using the contained public key as described in section 2.6.9. serverSignature1 SHALL apply on serverSigned1 data object. + output['serverSignature1'] = b64encode2str(b'\x5f\x37\x40' + self.dp_auth.ecdsa_sign(serverSigned1_bin)) + + output['transactionId'] = transactionId + server_cert_aki = self.dp_auth.get_authority_key_identifier() + output['euiccCiPKIdToBeUsed'] = b64encode2str(b'\x04\x14' + server_cert_aki.key_identifier) + output['serverCertificate'] = b64encode2str(self.dp_auth.get_cert_as_der()) # CERT.DPauth.SIG + # FIXME: add those certificate + #output['otherCertsInChain'] = b64encode2str() + + # create SessionState and store it in rss + self.rss[transactionId] = rsp.RspSessionState(transactionId, serverChallenge) + + return output + + @app.route('/gsma/rsp2/es9plus/authenticateClient', methods=['POST']) + @rsp_api_wrapper + def authenticateClient(self, request: IRequest, content: dict) -> dict: + """See ES9+ AuthenticateClient in SGP.22 Section 5.6.3""" + transactionId = content['transactionId'] + + authenticateServerResp_bin = b64decode(content['authenticateServerResponse']) + authenticateServerResp = rsp.asn1.decode('AuthenticateServerResponse', authenticateServerResp_bin) + print("Rx %s: %s" % authenticateServerResp) + if authenticateServerResp[0] == 'authenticateResponseError': + r_err = authenticateServerResp[1] + #r_err['transactionId'] + #r_err['authenticateErrorCode'] + raise ValueError("authenticateResponseError %s" % r_err) + + r_ok = authenticateServerResp[1] + euiccSigned1 = r_ok['euiccSigned1'] + # TODO: use original data, don't re-encode? + euiccSigned1_bin = rsp.asn1.encode('EuiccSigned1', euiccSigned1) + euiccSignature1_bin = r_ok['euiccSignature1'] + euiccCertificate_dec = r_ok['euiccCertificate'] + # TODO: use original data, don't re-encode? + euiccCertificate_bin = rsp.asn1.encode('Certificate', euiccCertificate_dec) + eumCertificate_dec = r_ok['eumCertificate'] + eumCertificate_bin = rsp.asn1.encode('Certificate', eumCertificate_dec) + # TODO v3: otherCertsInChain + + # load certificate + euicc_cert = x509.load_der_x509_certificate(euiccCertificate_bin) + eum_cert = x509.load_der_x509_certificate(eumCertificate_bin) + + # TODO: Verify the validity of the eUICC certificate chain + # raise ApiError('8.1.3', '6.1', 'Verification failed') + # raise ApiError('8.1.3', '6.3', 'Expired') + + # TODO: Verify that the Root Certificate of the eUICC certificate chain corresponds to the + # euiccCiPKIdToBeUsed or euiccCiPKIdToBeUsedV3 + # raise ApiError('8.11.1', '3.9', 'Unknown') + + # Verify euiccSignature1 over euiccSigned1 using pubkey from euiccCertificate. + # Otherwise, the SM-DP+ SHALL return a status code "eUICC - Verification failed" + if not self._ecdsa_verify(euicc_cert, euiccSignature1_bin, euiccSigned1_bin): + raise ApiError('8.1', '6.1', 'Verification failed') + + # Verify that the transactionId is known and relates to an ongoing RSP session. Otherwise, the SM-DP+ + # SHALL return a status code "TransactionId - Unknown" + ss = self.rss.get(transactionId, None) + if ss is None: + raise ApiError('8.10.1', '3.9', 'Unknown') + ss.euicc_cert = euicc_cert + ss.eum_cert = eum_cert # do we need this in the state? + + # TODO: verify eUICC cert is signed by EUM cert + # TODO: verify EUM cert is signed by CI cert + # TODO: verify EID of eUICC cert is within permitted range of EUM cert + + ss.eid = ss.euicc_cert.subject.get_attributes_for_oid(x509.oid.NameOID.SERIAL_NUMBER)[0].value + print("EID (from eUICC cert): %s" % ss.eid) + + # Verify that the serverChallenge attached to the ongoing RSP session matches the + # serverChallenge returned by the eUICC. Otherwise, the SM-DP+ SHALL return a status code "eUICC - + # Verification failed". + if euiccSigned1['serverChallenge'] != ss.serverChallenge: + raise ApiError('8.1', '6.1', 'Verification failed') + + # Put together profileMetadata + _bin + ss.profileMetadata = ProfileMetadata(iccid_bin= h2b(swap_nibbles('89000123456789012358')), spn="OsmocomSPN", profile_name="OsmocomProfile") + profileMetadata_bin = ss.profileMetadata.gen_store_metadata_request() + + # Put together smdpSigned2 + _bin + smdpSigned2 = { + 'transactionId': h2b(ss.transactionId), + 'ccRequiredFlag': False, # whether the Confirmation Code is required + #'bppEuiccOtpk': None, # whether otPK.EUICC.ECKA already used for binding the BPP, tag '5F49' + } + smdpSigned2_bin = rsp.asn1.encode('SmdpSigned2', smdpSigned2) + + ss.smdpSignature2_do = b'\x5f\x37\x40' + self.dp_pb.ecdsa_sign(smdpSigned2_bin + b'\x5f\x37\x40' + euiccSignature1_bin) + + # update non-volatile state with updated ss object + self.rss[transactionId] = ss + return { + 'transactionId': transactionId, + 'profileMetadata': b64encode2str(profileMetadata_bin), + 'smdpSigned2': b64encode2str(smdpSigned2_bin), + 'smdpSignature2': b64encode2str(ss.smdpSignature2_do), + 'smdpCertificate': b64encode2str(self.dp_pb.get_cert_as_der()), # CERT.DPpb.SIG + } + + @app.route('/gsma/rsp2/es9plus/getBoundProfilePackage', methods=['POST']) + @rsp_api_wrapper + def getBoundProfilePackage(self, request: IRequest, content: dict) -> dict: + """See ES9+ GetBoundProfilePackage SGP.22 Section 5.6.2""" + transactionId = content['transactionId'] + + # Verify that the received transactionId is known and relates to an ongoing RSP session + ss = self.rss.get(transactionId, None) + if not ss: + raise ApiError('8.10.1', '3.9', 'The RSP session identified by the TransactionID is unknown') + + prepDownloadResp_bin = b64decode(content['prepareDownloadResponse']) + prepDownloadResp = rsp.asn1.decode('PrepareDownloadResponse', prepDownloadResp_bin) + print("Rx %s: %s" % prepDownloadResp) + + if prepDownloadResp[0] == 'downloadResponseError': + r_err = prepDownloadResp[1] + #r_err['transactionId'] + #r_err['downloadErrorCode'] + raise ValueError("downloadResponseError %s" % r_err) + + r_ok = prepDownloadResp[1] + + # Verify the euiccSignature2 computed over euiccSigned2 and smdpSignature2 using the PK.EUICC.SIG attached to the ongoing RSP session + euiccSigned2 = r_ok['euiccSigned2'] + # TODO: use original data, don't re-encode? + euiccSigned2_bin = rsp.asn1.encode('EUICCSigned2', euiccSigned2) + if not self._ecdsa_verify(ss.euicc_cert, r_ok['euiccSignature2'], euiccSigned2_bin + ss.smdpSignature2_do): + raise ApiError('8.1', '6.1', 'eUICC signature is invalid') + + # not in spec: Verify that signed TransactionID is outer transaction ID + if h2b(transactionId) != euiccSigned2['transactionId']: + raise ApiError('8.10.1', '3.9', 'The signed transactionId != outer transactionId') + + # store otPK.EUICC.ECKA in session state + ss.euicc_otpk = euiccSigned2['euiccOtpk'] + print("euiccOtpk: %s" % (b2h(ss.euicc_otpk))) + + # Generate a one-time ECKA key pair (ot{PK,SK}.DP.ECKA) using the curve indicated by the Key Parameter + # Reference value of CERT.DPpb.ECDDSA + print("curve = %s" % self.dp_pb.get_curve()) + ss.smdp_ot = ec.generate_private_key(self.dp_pb.get_curve()) + # extract the public key in (hopefully) the right format for the ES8+ interface + ss.smdp_otpk = ss.smdp_ot.public_key().public_bytes(Encoding.X962, PublicFormat.UncompressedPoint) + print("smdpOtpk: %s" % b2h(ss.smdp_otpk)) + print("smdpOtsk: %s" % b2h(ss.smdp_ot.private_bytes(Encoding.DER, PrivateFormat.PKCS8, NoEncryption()))) + + ss.host_id = b'mahlzeit' + + # Generate Session Keys using the CRT, opPK.eUICC.ECKA and otSK.DP.ECKA according to annex G + euicc_public_key = ec.EllipticCurvePublicKey.from_encoded_point(ss.smdp_ot.curve, ss.euicc_otpk) + ss.shared_secret = ss.smdp_ot.exchange(ec.ECDH(), euicc_public_key) + print("shared_secret: %s" % b2h(ss.shared_secret)) + + # TODO: Check if this order requires a Confirmation Code verification + + # Perform actual protection + binding of profile package (or return pre-bound one) + with open(os.path.join(DATA_DIR, 'upp', 'TS48 V2 eSIM_GTP_SAIP2.1_NoBERTLV.rename2der'), 'rb') as f: + upp = UnprotectedProfilePackage.from_der(f.read(), metadata=ss.profileMetadata) + # HACK: Use empty PPP as we're still debuggin the configureISDP step, and we want to avoid + # cluttering the log with stuff happening after the failure + #upp = UnprotectedProfilePackage.from_der(b'', metadata=ss.profileMetadata) + if False: + # Use random keys + bpp = BoundProfilePackage.from_upp(upp) + else: + # Use sesssion keys + ppp = ProtectedProfilePackage.from_upp(upp, BspInstance(b'\x00'*16, b'\x11'*16, b'\x22'*16)) + bpp = BoundProfilePackage.from_ppp(ppp) + + # update non-volatile state with updated ss object + self.rss[transactionId] = ss + return { + 'transactionId': transactionId, + 'boundProfilePackage': b64encode2str(bpp.encode(ss, self.dp_pb)), + } + + @app.route('/gsma/rsp2/es9plus/handleNotification', methods=['POST']) + @rsp_api_wrapper + def handleNotification(self, request: IRequest, content: dict) -> dict: + """See ES9+ HandleNotification in SGP.22 Section 5.6.4""" + pendingNotification_bin = b64decode(content['pendingNotification']) + pendingNotification = rsp.asn1.decode('PendingNotification', pendingNotification_bin) + print("Rx %s: %s" % pendingNotification) + if pendingNotification[0] == 'profileInstallationResult': + profileInstallRes = pendingNotification[1] + pird = profileInstallRes['profileInstallationResultData'] + transactionId = b2h(pird['transactionId']) + ss = self.rss.get(transactionId, None) + if ss is None: + print("Unable to find session for transactionId") + return + profileInstallRes['euiccSignPIR'] + # TODO: use original data, don't re-encode? + pird_bin = rsp.asn1.encode('ProfileInstallationResultData', pird) + # verify eUICC signature + if not self._ecdsa_verify(ss.euicc_cert, profileInstallRes['euiccSignPIR'], pird_bin): + print("Unable to verify eUICC signature") + print("Profile Installation Final Result: ", pird['finalResult']) + # remove session state + del self.rss[transactionId] + elif pendingNotification[0] == 'otherSignedNotification': + # TODO + pass + else: + raise ValueError(pendingNotification) + + #@app.route('/gsma/rsp3/es9plus/handleDeviceChangeRequest, methods=['POST']') + #@rsp_api_wrapper + #"""See ES9+ ConfirmDeviceChange in SGP.22 Section 5.6.6""" + # TODO: implement this + + @app.route('/gsma/rsp2/es9plus/cancelSession', methods=['POST']) + @rsp_api_wrapper + def cancelSession(self, request: IRequest, content: dict) -> dict: + """See ES9+ CancelSession in SGP.22 Section 5.6.5""" + print("Rx JSON: %s" % content) + transactionId = content['transactionId'] + + # Verify that the received transactionId is known and relates to an ongoing RSP session + ss = self.rss.get(transactionId, None) + if ss is None: + raise ApiError('8.10.1', '3.9', 'The RSP session identified by the transactionId is unknown') + + cancelSessionResponse_bin = b64decode(content['cancelSessionResponse']) + cancelSessionResponse = rsp.asn1.decode('CancelSessionResponse', cancelSessionResponse_bin) + print("Rx %s: %s" % cancelSessionResponse) + + if cancelSessionResponse[0] == 'cancelSessionResponseError': + # FIXME: print some error + return + cancelSessionResponseOk = cancelSessionResponse[1] + # TODO: use original data, don't re-encode? + ecsr = cancelSessionResponseOk['euiccCancelSessionSigned'] + ecsr_bin = rsp.asn1.encode('EuiccCancelSessionSigned', ecsr) + # Verify the eUICC signature (euiccCancelSessionSignature) using the PK.EUICC.SIG attached to the ongoing RSP session + if not self._ecdsa_verify(ss.euicc_cert, cancelSessionResponseOk['euiccCancelSessionSignature'], ecsr_bin): + raise ApiError('8.1', '6.1', 'eUICC signature is invalid') + + # Verify that the received smdpOid corresponds to the one in SM-DP+ CERT.DPauth.SIG + subj_alt_name = self.dp_auth.get_subject_alt_name() + if x509.ObjectIdentifier(ecsr['smdpOid']) != subj_alt_name.oid: + raise ApiError('8.8', '3.10', 'The provided SM-DP+ OID is invalid.') + + if ecsr['transactionId'] != h2b(transactionId): + raise ApiError('8.10.1', '3.9', 'The signed transactionId != outer transactionId') + + # TODO: 1. Notify the Operator using the function "ES2+.HandleNotification" function + # TODO: 2. Terminate the corresponding pending download process. + # TODO: 3. If required, execute the SM-DS Event Deletion procedure described in section 3.6.3. + + # delete actual session data + del self.rss[transactionId] + return { 'transactionId': transactionId } + + +def main(argv): + parser = argparse.ArgumentParser() + #parser.add_argument("-H", "--host", help="Host/IP to bind HTTP to", default="localhost") + #parser.add_argument("-p", "--port", help="TCP port to bind HTTP to", default=8000) + #parser.add_argument("-v", "--verbose", help="increase output verbosity", action='count', default=0) + + args = parser.parse_args() + + hs = SmDppHttpServer(HOSTNAME, os.path.join(DATA_DIR, 'certs', 'CertificateIssuer'), use_brainpool=True) + #hs.app.run(endpoint_description="ssl:port=8000:dhParameters=dh_param_2048.pem") + hs.app.run("localhost", 8000) + +if __name__ == "__main__": + main(sys.argv) diff --git a/pySim/esim/__init__.py b/pySim/esim/__init__.py index e69de29b..4d6c6093 100644 --- a/pySim/esim/__init__.py +++ b/pySim/esim/__init__.py @@ -0,0 +1,16 @@ +import sys +from importlib import resources + +import asn1tools + +def compile_asn1_subdir(subdir_name:str): + """Helper function that compiles ASN.1 syntax from all files within given subdir""" + asn_txt = '' + __ver = sys.version_info + if (__ver.major, __ver.minor) >= (3, 9): + for i in resources.files('pySim.esim').joinpath('asn1').joinpath(subdir_name).iterdir(): + asn_txt += i.read_text() + asn_txt += "\n" + #else: + #print(resources.read_text(__name__, 'asn1/rsp.asn')) + return asn1tools.compile_string(asn_txt, codec='der') diff --git a/pySim/esim/asn1/rsp/PKIX1Explicit88.asn b/pySim/esim/asn1/rsp/PKIX1Explicit88.asn new file mode 100644 index 00000000..9284c65e --- /dev/null +++ b/pySim/esim/asn1/rsp/PKIX1Explicit88.asn @@ -0,0 +1,657 @@ +PKIX1Explicit88 { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18) } + +DEFINITIONS EXPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL -- + +-- IMPORTS NONE -- + +-- UNIVERSAL Types defined in 1993 and 1998 ASN.1 +-- and required by this specification + +-- pycrate: UniversalString, BMPString and UTF8String already in the builtin types + +--UniversalString ::= [UNIVERSAL 28] IMPLICIT OCTET STRING + -- UniversalString is defined in ASN.1:1993 + +--BMPString ::= [UNIVERSAL 30] IMPLICIT OCTET STRING + -- BMPString is the subtype of UniversalString and models + -- the Basic Multilingual Plane of ISO/IEC 10646 + +--UTF8String ::= [UNIVERSAL 12] IMPLICIT OCTET STRING + -- The content of this type conforms to RFC 3629. + +-- PKIX specific OIDs + +id-pkix OBJECT IDENTIFIER ::= + { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) } + +-- PKIX arcs + +id-pe OBJECT IDENTIFIER ::= { id-pkix 1 } + -- arc for private certificate extensions +id-qt OBJECT IDENTIFIER ::= { id-pkix 2 } + -- arc for policy qualifier types +id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } + -- arc for extended key purpose OIDS +id-ad OBJECT IDENTIFIER ::= { id-pkix 48 } + -- arc for access descriptors + +-- policyQualifierIds for Internet policy qualifiers + +id-qt-cps OBJECT IDENTIFIER ::= { id-qt 1 } + -- OID for CPS qualifier +id-qt-unotice OBJECT IDENTIFIER ::= { id-qt 2 } + -- OID for user notice qualifier + +-- access descriptor definitions + +id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 } +id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 } +id-ad-timeStamping OBJECT IDENTIFIER ::= { id-ad 3 } +id-ad-caRepository OBJECT IDENTIFIER ::= { id-ad 5 } + +-- attribute data types + +Attribute ::= SEQUENCE { + type AttributeType, + values SET OF AttributeValue } + -- at least one value is required + +AttributeType ::= OBJECT IDENTIFIER + +AttributeValue ::= ANY -- DEFINED BY AttributeType + +AttributeTypeAndValue ::= SEQUENCE { + type AttributeType, + value AttributeValue } + +-- suggested naming attributes: Definition of the following +-- information object set may be augmented to meet local +-- requirements. Note that deleting members of the set may +-- prevent interoperability with conforming implementations. +-- presented in pairs: the AttributeType followed by the +-- type definition for the corresponding AttributeValue + +-- Arc for standard naming attributes + +id-at OBJECT IDENTIFIER ::= { joint-iso-ccitt(2) ds(5) 4 } + +-- Naming attributes of type X520name + +id-at-name AttributeType ::= { id-at 41 } +id-at-surname AttributeType ::= { id-at 4 } +id-at-givenName AttributeType ::= { id-at 42 } +id-at-initials AttributeType ::= { id-at 43 } +id-at-generationQualifier AttributeType ::= { id-at 44 } + +-- Naming attributes of type X520Name: +-- X520name ::= DirectoryString (SIZE (1..ub-name)) +-- +-- Expanded to avoid parameterized type: +X520name ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-name)), + printableString PrintableString (SIZE (1..ub-name)), + universalString UniversalString (SIZE (1..ub-name)), + utf8String UTF8String (SIZE (1..ub-name)), + bmpString BMPString (SIZE (1..ub-name)) } + +-- Naming attributes of type X520CommonName + +id-at-commonName AttributeType ::= { id-at 3 } + +-- Naming attributes of type X520CommonName: +-- X520CommonName ::= DirectoryName (SIZE (1..ub-common-name)) +-- +-- Expanded to avoid parameterized type: +X520CommonName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-common-name)), + printableString PrintableString (SIZE (1..ub-common-name)), + universalString UniversalString (SIZE (1..ub-common-name)), + utf8String UTF8String (SIZE (1..ub-common-name)), + bmpString BMPString (SIZE (1..ub-common-name)) } + +-- Naming attributes of type X520LocalityName + +id-at-localityName AttributeType ::= { id-at 7 } + +-- Naming attributes of type X520LocalityName: +-- X520LocalityName ::= DirectoryName (SIZE (1..ub-locality-name)) +-- +-- Expanded to avoid parameterized type: +X520LocalityName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-locality-name)), + printableString PrintableString (SIZE (1..ub-locality-name)), + universalString UniversalString (SIZE (1..ub-locality-name)), + utf8String UTF8String (SIZE (1..ub-locality-name)), + bmpString BMPString (SIZE (1..ub-locality-name)) } + +-- Naming attributes of type X520StateOrProvinceName + +id-at-stateOrProvinceName AttributeType ::= { id-at 8 } + +-- Naming attributes of type X520StateOrProvinceName: +-- X520StateOrProvinceName ::= DirectoryName (SIZE (1..ub-state-name)) +-- +-- Expanded to avoid parameterized type: +X520StateOrProvinceName ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-state-name)), + printableString PrintableString (SIZE (1..ub-state-name)), + universalString UniversalString (SIZE (1..ub-state-name)), + utf8String UTF8String (SIZE (1..ub-state-name)), + bmpString BMPString (SIZE (1..ub-state-name)) } + +-- Naming attributes of type X520OrganizationName + +id-at-organizationName AttributeType ::= { id-at 10 } + +-- Naming attributes of type X520OrganizationName: +-- X520OrganizationName ::= +-- DirectoryName (SIZE (1..ub-organization-name)) +-- +-- Expanded to avoid parameterized type: +X520OrganizationName ::= CHOICE { + teletexString TeletexString + (SIZE (1..ub-organization-name)), + printableString PrintableString + (SIZE (1..ub-organization-name)), + universalString UniversalString + (SIZE (1..ub-organization-name)), + utf8String UTF8String + (SIZE (1..ub-organization-name)), + bmpString BMPString + (SIZE (1..ub-organization-name)) } + +-- Naming attributes of type X520OrganizationalUnitName + +id-at-organizationalUnitName AttributeType ::= { id-at 11 } + +-- Naming attributes of type X520OrganizationalUnitName: +-- X520OrganizationalUnitName ::= +-- DirectoryName (SIZE (1..ub-organizational-unit-name)) +-- +-- Expanded to avoid parameterized type: +X520OrganizationalUnitName ::= CHOICE { + teletexString TeletexString + (SIZE (1..ub-organizational-unit-name)), + printableString PrintableString + (SIZE (1..ub-organizational-unit-name)), + universalString UniversalString + (SIZE (1..ub-organizational-unit-name)), + utf8String UTF8String + (SIZE (1..ub-organizational-unit-name)), + bmpString BMPString + (SIZE (1..ub-organizational-unit-name)) } + +-- Naming attributes of type X520Title + +id-at-title AttributeType ::= { id-at 12 } + +-- Naming attributes of type X520Title: +-- X520Title ::= DirectoryName (SIZE (1..ub-title)) +-- +-- Expanded to avoid parameterized type: +X520Title ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-title)), + printableString PrintableString (SIZE (1..ub-title)), + universalString UniversalString (SIZE (1..ub-title)), + utf8String UTF8String (SIZE (1..ub-title)), + bmpString BMPString (SIZE (1..ub-title)) } + +-- Naming attributes of type X520dnQualifier + +id-at-dnQualifier AttributeType ::= { id-at 46 } + +X520dnQualifier ::= PrintableString + +-- Naming attributes of type X520countryName (digraph from IS 3166) + +id-at-countryName AttributeType ::= { id-at 6 } + +X520countryName ::= PrintableString (SIZE (2)) + +-- Naming attributes of type X520SerialNumber + +id-at-serialNumber AttributeType ::= { id-at 5 } + +X520SerialNumber ::= PrintableString (SIZE (1..ub-serial-number)) + +-- Naming attributes of type X520Pseudonym + +id-at-pseudonym AttributeType ::= { id-at 65 } + +-- Naming attributes of type X520Pseudonym: +-- X520Pseudonym ::= DirectoryName (SIZE (1..ub-pseudonym)) +-- +-- Expanded to avoid parameterized type: +X520Pseudonym ::= CHOICE { + teletexString TeletexString (SIZE (1..ub-pseudonym)), + printableString PrintableString (SIZE (1..ub-pseudonym)), + universalString UniversalString (SIZE (1..ub-pseudonym)), + utf8String UTF8String (SIZE (1..ub-pseudonym)), + bmpString BMPString (SIZE (1..ub-pseudonym)) } + +-- Naming attributes of type DomainComponent (from RFC 4519) + +id-domainComponent AttributeType ::= { 0 9 2342 19200300 100 1 25 } + +DomainComponent ::= IA5String + +-- Legacy attributes + +pkcs-9 OBJECT IDENTIFIER ::= + { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } + +id-emailAddress AttributeType ::= { pkcs-9 1 } + +EmailAddress ::= IA5String (SIZE (1..ub-emailaddress-length)) + +-- naming data types -- + +Name ::= CHOICE { -- only one possibility for now -- + rdnSequence RDNSequence } + +RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + +DistinguishedName ::= RDNSequence + +RelativeDistinguishedName ::= SET SIZE (1..MAX) OF AttributeTypeAndValue + +-- Directory string type -- + +DirectoryString ::= CHOICE { + teletexString TeletexString (SIZE (1..MAX)), + printableString PrintableString (SIZE (1..MAX)), + universalString UniversalString (SIZE (1..MAX)), + utf8String UTF8String (SIZE (1..MAX)), + bmpString BMPString (SIZE (1..MAX)) } + +-- certificate and CRL specific structures begin here + +Certificate ::= SEQUENCE { + tbsCertificate TBSCertificate, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertificate ::= SEQUENCE { + version [0] Version DEFAULT v1, + serialNumber CertificateSerialNumber, + signature AlgorithmIdentifier, + issuer Name, + validity Validity, + subject Name, + subjectPublicKeyInfo SubjectPublicKeyInfo, + issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version MUST be v2 or v3 + subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + -- If present, version MUST be v2 or v3 + extensions [3] Extensions OPTIONAL + -- If present, version MUST be v3 -- } + +Version ::= INTEGER { v1(0), v2(1), v3(2) } + +CertificateSerialNumber ::= INTEGER + +Validity ::= SEQUENCE { + notBefore Time, + notAfter Time } + +Time ::= CHOICE { + utcTime UTCTime, + generalTime GeneralizedTime } + +UniqueIdentifier ::= BIT STRING + +SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING } + +Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + +Extension ::= SEQUENCE { + extnID OBJECT IDENTIFIER, + critical BOOLEAN DEFAULT FALSE, + extnValue OCTET STRING + -- contains the DER encoding of an ASN.1 value + -- corresponding to the extension type identified + -- by extnID + } + +-- CRL structures + +CertificateList ::= SEQUENCE { + tbsCertList TBSCertList, + signatureAlgorithm AlgorithmIdentifier, + signature BIT STRING } + +TBSCertList ::= SEQUENCE { + version Version OPTIONAL, + -- if present, MUST be v2 + signature AlgorithmIdentifier, + issuer Name, + thisUpdate Time, + nextUpdate Time OPTIONAL, + revokedCertificates SEQUENCE OF SEQUENCE { + userCertificate CertificateSerialNumber, + revocationDate Time, + crlEntryExtensions Extensions OPTIONAL + -- if present, version MUST be v2 + } OPTIONAL, + crlExtensions [0] Extensions OPTIONAL } + -- if present, version MUST be v2 + +-- Version, Time, CertificateSerialNumber, and Extensions were +-- defined earlier for use in the certificate structure + +AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL } + -- contains a value of the type + -- registered for use with the + -- algorithm object identifier value + +-- X.400 address syntax starts here + +ORAddress ::= SEQUENCE { + built-in-standard-attributes BuiltInStandardAttributes, + built-in-domain-defined-attributes + BuiltInDomainDefinedAttributes OPTIONAL, + -- see also teletex-domain-defined-attributes + extension-attributes ExtensionAttributes OPTIONAL } + +-- Built-in Standard Attributes + +BuiltInStandardAttributes ::= SEQUENCE { + country-name CountryName OPTIONAL, + administration-domain-name AdministrationDomainName OPTIONAL, + network-address [0] IMPLICIT NetworkAddress OPTIONAL, + -- see also extended-network-address + terminal-identifier [1] IMPLICIT TerminalIdentifier OPTIONAL, + private-domain-name [2] PrivateDomainName OPTIONAL, + organization-name [3] IMPLICIT OrganizationName OPTIONAL, + -- see also teletex-organization-name + numeric-user-identifier [4] IMPLICIT NumericUserIdentifier + OPTIONAL, + personal-name [5] IMPLICIT PersonalName OPTIONAL, + -- see also teletex-personal-name + organizational-unit-names [6] IMPLICIT OrganizationalUnitNames + OPTIONAL } + -- see also teletex-organizational-unit-names + +CountryName ::= [APPLICATION 1] CHOICE { + x121-dcc-code NumericString + (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +AdministrationDomainName ::= [APPLICATION 2] CHOICE { + numeric NumericString (SIZE (0..ub-domain-name-length)), + printable PrintableString (SIZE (0..ub-domain-name-length)) } + +NetworkAddress ::= X121Address -- see also extended-network-address + +X121Address ::= NumericString (SIZE (1..ub-x121-address-length)) + +TerminalIdentifier ::= PrintableString (SIZE (1..ub-terminal-id-length)) + +PrivateDomainName ::= CHOICE { + numeric NumericString (SIZE (1..ub-domain-name-length)), + printable PrintableString (SIZE (1..ub-domain-name-length)) } + +OrganizationName ::= PrintableString + (SIZE (1..ub-organization-name-length)) + -- see also teletex-organization-name + +NumericUserIdentifier ::= NumericString + (SIZE (1..ub-numeric-user-id-length)) + +PersonalName ::= SET { + surname [0] IMPLICIT PrintableString + (SIZE (1..ub-surname-length)), + given-name [1] IMPLICIT PrintableString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] IMPLICIT PrintableString + (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] IMPLICIT PrintableString + (SIZE (1..ub-generation-qualifier-length)) + OPTIONAL } + -- see also teletex-personal-name + +OrganizationalUnitNames ::= SEQUENCE SIZE (1..ub-organizational-units) + OF OrganizationalUnitName + -- see also teletex-organizational-unit-names + +OrganizationalUnitName ::= PrintableString (SIZE + (1..ub-organizational-unit-name-length)) + +-- Built-in Domain-defined Attributes + +BuiltInDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF + BuiltInDomainDefinedAttribute + +BuiltInDomainDefinedAttribute ::= SEQUENCE { + type PrintableString (SIZE + (1..ub-domain-defined-attribute-type-length)), + value PrintableString (SIZE + (1..ub-domain-defined-attribute-value-length)) } + +-- Extension Attributes + +ExtensionAttributes ::= SET SIZE (1..ub-extension-attributes) OF + ExtensionAttribute + +ExtensionAttribute ::= SEQUENCE { + extension-attribute-type [0] IMPLICIT INTEGER + (0..ub-extension-attributes), + extension-attribute-value [1] + ANY DEFINED BY extension-attribute-type } + +-- Extension types and attribute values + +common-name INTEGER ::= 1 + +CommonName ::= PrintableString (SIZE (1..ub-common-name-length)) + +teletex-common-name INTEGER ::= 2 + +TeletexCommonName ::= TeletexString (SIZE (1..ub-common-name-length)) + +teletex-organization-name INTEGER ::= 3 + +TeletexOrganizationName ::= + TeletexString (SIZE (1..ub-organization-name-length)) + +teletex-personal-name INTEGER ::= 4 + +TeletexPersonalName ::= SET { + surname [0] IMPLICIT TeletexString + (SIZE (1..ub-surname-length)), + given-name [1] IMPLICIT TeletexString + (SIZE (1..ub-given-name-length)) OPTIONAL, + initials [2] IMPLICIT TeletexString + (SIZE (1..ub-initials-length)) OPTIONAL, + generation-qualifier [3] IMPLICIT TeletexString + (SIZE (1..ub-generation-qualifier-length)) + OPTIONAL } + +teletex-organizational-unit-names INTEGER ::= 5 + +TeletexOrganizationalUnitNames ::= SEQUENCE SIZE + (1..ub-organizational-units) OF TeletexOrganizationalUnitName + +TeletexOrganizationalUnitName ::= TeletexString + (SIZE (1..ub-organizational-unit-name-length)) + +pds-name INTEGER ::= 7 + +PDSName ::= PrintableString (SIZE (1..ub-pds-name-length)) + +physical-delivery-country-name INTEGER ::= 8 + +PhysicalDeliveryCountryName ::= CHOICE { + x121-dcc-code NumericString (SIZE (ub-country-name-numeric-length)), + iso-3166-alpha2-code PrintableString + (SIZE (ub-country-name-alpha-length)) } + +postal-code INTEGER ::= 9 + +PostalCode ::= CHOICE { + numeric-code NumericString (SIZE (1..ub-postal-code-length)), + printable-code PrintableString (SIZE (1..ub-postal-code-length)) } + +physical-delivery-office-name INTEGER ::= 10 + +PhysicalDeliveryOfficeName ::= PDSParameter + +physical-delivery-office-number INTEGER ::= 11 + +PhysicalDeliveryOfficeNumber ::= PDSParameter + +extension-OR-address-components INTEGER ::= 12 + +ExtensionORAddressComponents ::= PDSParameter + +physical-delivery-personal-name INTEGER ::= 13 + +PhysicalDeliveryPersonalName ::= PDSParameter + +physical-delivery-organization-name INTEGER ::= 14 + +PhysicalDeliveryOrganizationName ::= PDSParameter + +extension-physical-delivery-address-components INTEGER ::= 15 + +ExtensionPhysicalDeliveryAddressComponents ::= PDSParameter + +unformatted-postal-address INTEGER ::= 16 + +UnformattedPostalAddress ::= SET { + printable-address SEQUENCE SIZE (1..ub-pds-physical-address-lines) + OF PrintableString (SIZE (1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE (1..ub-unformatted-address-length)) OPTIONAL } + +street-address INTEGER ::= 17 + +StreetAddress ::= PDSParameter + +post-office-box-address INTEGER ::= 18 + +PostOfficeBoxAddress ::= PDSParameter + +poste-restante-address INTEGER ::= 19 + +PosteRestanteAddress ::= PDSParameter + +unique-postal-name INTEGER ::= 20 + +UniquePostalName ::= PDSParameter + +local-postal-attributes INTEGER ::= 21 + +LocalPostalAttributes ::= PDSParameter + +PDSParameter ::= SET { + printable-string PrintableString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL, + teletex-string TeletexString + (SIZE(1..ub-pds-parameter-length)) OPTIONAL } + +extended-network-address INTEGER ::= 22 + +ExtendedNetworkAddress ::= CHOICE { + e163-4-address SEQUENCE { + number [0] IMPLICIT NumericString + (SIZE (1..ub-e163-4-number-length)), + sub-address [1] IMPLICIT NumericString + (SIZE (1..ub-e163-4-sub-address-length)) + OPTIONAL }, + psap-address [0] IMPLICIT PresentationAddress } + +PresentationAddress ::= SEQUENCE { + pSelector [0] EXPLICIT OCTET STRING OPTIONAL, + sSelector [1] EXPLICIT OCTET STRING OPTIONAL, + tSelector [2] EXPLICIT OCTET STRING OPTIONAL, + nAddresses [3] EXPLICIT SET SIZE (1..MAX) OF OCTET STRING } + +terminal-type INTEGER ::= 23 + +TerminalType ::= INTEGER { + telex (3), + teletex (4), + g3-facsimile (5), + g4-facsimile (6), + ia5-terminal (7), + videotex (8) } (0..ub-integer-options) + +-- Extension Domain-defined Attributes + +teletex-domain-defined-attributes INTEGER ::= 6 + +TeletexDomainDefinedAttributes ::= SEQUENCE SIZE + (1..ub-domain-defined-attributes) OF TeletexDomainDefinedAttribute + +TeletexDomainDefinedAttribute ::= SEQUENCE { + type TeletexString + (SIZE (1..ub-domain-defined-attribute-type-length)), + value TeletexString + (SIZE (1..ub-domain-defined-attribute-value-length)) } + +-- specifications of Upper Bounds MUST be regarded as mandatory +-- from Annex B of ITU-T X.411 Reference Definition of MTS Parameter +-- Upper Bounds + +-- Upper Bounds +ub-name INTEGER ::= 32768 +ub-common-name INTEGER ::= 64 +ub-locality-name INTEGER ::= 128 +ub-state-name INTEGER ::= 128 +ub-organization-name INTEGER ::= 64 +ub-organizational-unit-name INTEGER ::= 64 +ub-title INTEGER ::= 64 +ub-serial-number INTEGER ::= 64 +ub-match INTEGER ::= 128 +ub-emailaddress-length INTEGER ::= 255 +ub-common-name-length INTEGER ::= 64 +ub-country-name-alpha-length INTEGER ::= 2 +ub-country-name-numeric-length INTEGER ::= 3 +ub-domain-defined-attributes INTEGER ::= 4 +ub-domain-defined-attribute-type-length INTEGER ::= 8 +ub-domain-defined-attribute-value-length INTEGER ::= 128 +ub-domain-name-length INTEGER ::= 16 +ub-extension-attributes INTEGER ::= 256 +ub-e163-4-number-length INTEGER ::= 15 +ub-e163-4-sub-address-length INTEGER ::= 40 +ub-generation-qualifier-length INTEGER ::= 3 +ub-given-name-length INTEGER ::= 16 +ub-initials-length INTEGER ::= 5 +ub-integer-options INTEGER ::= 256 +ub-numeric-user-id-length INTEGER ::= 32 +ub-organization-name-length INTEGER ::= 64 +ub-organizational-unit-name-length INTEGER ::= 32 +ub-organizational-units INTEGER ::= 4 +ub-pds-name-length INTEGER ::= 16 +ub-pds-parameter-length INTEGER ::= 30 +ub-pds-physical-address-lines INTEGER ::= 6 +ub-postal-code-length INTEGER ::= 16 +ub-pseudonym INTEGER ::= 128 +ub-surname-length INTEGER ::= 40 +ub-terminal-id-length INTEGER ::= 24 +ub-unformatted-address-length INTEGER ::= 180 +ub-x121-address-length INTEGER ::= 16 + +-- Note - upper bounds on string types, such as TeletexString, are +-- measured in characters. Excepting PrintableString or IA5String, a +-- significantly greater number of octets will be required to hold +-- such a value. As a minimum, 16 octets, or twice the specified +-- upper bound, whichever is the larger, should be allowed for +-- TeletexString. For UTF8String or UniversalString at least four +-- times the upper bound should be allowed. + +END + diff --git a/pySim/esim/asn1/rsp/PKIX1Implicit88.asn b/pySim/esim/asn1/rsp/PKIX1Implicit88.asn new file mode 100644 index 00000000..aafd7854 --- /dev/null +++ b/pySim/esim/asn1/rsp/PKIX1Implicit88.asn @@ -0,0 +1,343 @@ +PKIX1Implicit88 { iso(1) identified-organization(3) dod(6) internet(1) + security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19) } + +DEFINITIONS IMPLICIT TAGS ::= + +BEGIN + +-- EXPORTS ALL -- + +IMPORTS + id-pe, id-kp, id-qt-unotice, id-qt-cps, + ORAddress, Name, RelativeDistinguishedName, + CertificateSerialNumber, Attribute, DirectoryString + FROM PKIX1Explicit88 { iso(1) identified-organization(3) + dod(6) internet(1) security(5) mechanisms(5) pkix(7) + id-mod(0) id-pkix1-explicit(18) }; + +-- ISO arc for standard certificate and CRL extensions + +id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} + +-- authority key identifier OID and syntax + +id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } + +AuthorityKeyIdentifier ::= SEQUENCE { + keyIdentifier [0] KeyIdentifier OPTIONAL, + authorityCertIssuer [1] GeneralNames OPTIONAL, + authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL } + -- authorityCertIssuer and authorityCertSerialNumber MUST both + -- be present or both be absent + +KeyIdentifier ::= OCTET STRING + +-- subject key identifier OID and syntax + +id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } + +SubjectKeyIdentifier ::= KeyIdentifier + +-- key usage extension OID and syntax + +id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } + +KeyUsage ::= BIT STRING { + digitalSignature (0), + nonRepudiation (1), -- recent editions of X.509 have + -- renamed this bit to contentCommitment + keyEncipherment (2), + dataEncipherment (3), + keyAgreement (4), + keyCertSign (5), + cRLSign (6), + encipherOnly (7), + decipherOnly (8) } + +-- private key usage period extension OID and syntax + +id-ce-privateKeyUsagePeriod OBJECT IDENTIFIER ::= { id-ce 16 } + +PrivateKeyUsagePeriod ::= SEQUENCE { + notBefore [0] GeneralizedTime OPTIONAL, + notAfter [1] GeneralizedTime OPTIONAL } + -- either notBefore or notAfter MUST be present + +-- certificate policies extension OID and syntax + +id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } + +anyPolicy OBJECT IDENTIFIER ::= { id-ce-certificatePolicies 0 } + +CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation + +PolicyInformation ::= SEQUENCE { + policyIdentifier CertPolicyId, + policyQualifiers SEQUENCE SIZE (1..MAX) OF + PolicyQualifierInfo OPTIONAL } + +CertPolicyId ::= OBJECT IDENTIFIER + +PolicyQualifierInfo ::= SEQUENCE { + policyQualifierId PolicyQualifierId, + qualifier ANY DEFINED BY policyQualifierId } + +-- Implementations that recognize additional policy qualifiers MUST +-- augment the following definition for PolicyQualifierId + +PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice ) + +-- CPS pointer qualifier + +CPSuri ::= IA5String + +-- user notice qualifier + +UserNotice ::= SEQUENCE { + noticeRef NoticeReference OPTIONAL, + explicitText DisplayText OPTIONAL } + +NoticeReference ::= SEQUENCE { + organization DisplayText, + noticeNumbers SEQUENCE OF INTEGER } + +DisplayText ::= CHOICE { + ia5String IA5String (SIZE (1..200)), + visibleString VisibleString (SIZE (1..200)), + bmpString BMPString (SIZE (1..200)), + utf8String UTF8String (SIZE (1..200)) } + +-- policy mapping extension OID and syntax + +id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } + +PolicyMappings ::= SEQUENCE SIZE (1..MAX) OF SEQUENCE { + issuerDomainPolicy CertPolicyId, + subjectDomainPolicy CertPolicyId } + +-- subject alternative name extension OID and syntax + +id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } + +SubjectAltName ::= GeneralNames + +GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + +GeneralName ::= CHOICE { + otherName [0] AnotherName, + rfc822Name [1] IA5String, + dNSName [2] IA5String, + x400Address [3] ORAddress, + directoryName [4] Name, + ediPartyName [5] EDIPartyName, + uniformResourceIdentifier [6] IA5String, + iPAddress [7] OCTET STRING, + registeredID [8] OBJECT IDENTIFIER } + +-- AnotherName replaces OTHER-NAME ::= TYPE-IDENTIFIER, as +-- TYPE-IDENTIFIER is not supported in the '88 ASN.1 syntax + +AnotherName ::= SEQUENCE { + type-id OBJECT IDENTIFIER, + value [0] EXPLICIT ANY DEFINED BY type-id } + +EDIPartyName ::= SEQUENCE { + nameAssigner [0] DirectoryString OPTIONAL, + partyName [1] DirectoryString } + +-- issuer alternative name extension OID and syntax + +id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } + +IssuerAltName ::= GeneralNames + +id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } + +SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF Attribute + +-- basic constraints extension OID and syntax + +id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } + +BasicConstraints ::= SEQUENCE { + cA BOOLEAN DEFAULT FALSE, + pathLenConstraint INTEGER (0..MAX) OPTIONAL } + +-- name constraints extension OID and syntax + +id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } + +NameConstraints ::= SEQUENCE { + permittedSubtrees [0] GeneralSubtrees OPTIONAL, + excludedSubtrees [1] GeneralSubtrees OPTIONAL } + +GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree + +GeneralSubtree ::= SEQUENCE { + base GeneralName, + minimum [0] BaseDistance DEFAULT 0, + maximum [1] BaseDistance OPTIONAL } + +BaseDistance ::= INTEGER (0..MAX) + +-- policy constraints extension OID and syntax + +id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } + +PolicyConstraints ::= SEQUENCE { + requireExplicitPolicy [0] SkipCerts OPTIONAL, + inhibitPolicyMapping [1] SkipCerts OPTIONAL } + +SkipCerts ::= INTEGER (0..MAX) + +-- CRL distribution points extension OID and syntax + +id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= {id-ce 31} + +CRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint + +DistributionPoint ::= SEQUENCE { + distributionPoint [0] DistributionPointName OPTIONAL, + reasons [1] ReasonFlags OPTIONAL, + cRLIssuer [2] GeneralNames OPTIONAL } + +DistributionPointName ::= CHOICE { + fullName [0] GeneralNames, + nameRelativeToCRLIssuer [1] RelativeDistinguishedName } + +ReasonFlags ::= BIT STRING { + unused (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), + privilegeWithdrawn (7), + aACompromise (8) } + +-- extended key usage extension OID and syntax + +id-ce-extKeyUsage OBJECT IDENTIFIER ::= {id-ce 37} + +ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + +KeyPurposeId ::= OBJECT IDENTIFIER + +-- permit unspecified key uses + +anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } + +-- extended key purpose OIDs + +id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } +id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } +id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } +id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } +id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } +id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } + +-- inhibit any policy OID and syntax + +id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } + +InhibitAnyPolicy ::= SkipCerts + +-- freshest (delta)CRL extension OID and syntax + +id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } + +FreshestCRL ::= CRLDistributionPoints + +-- authority info access + +id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 } + +AuthorityInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + +AccessDescription ::= SEQUENCE { + accessMethod OBJECT IDENTIFIER, + accessLocation GeneralName } + +-- subject info access + +id-pe-subjectInfoAccess OBJECT IDENTIFIER ::= { id-pe 11 } + +SubjectInfoAccessSyntax ::= + SEQUENCE SIZE (1..MAX) OF AccessDescription + +-- CRL number extension OID and syntax + +id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } + +CRLNumber ::= INTEGER (0..MAX) + +-- issuing distribution point extension OID and syntax + +id-ce-issuingDistributionPoint OBJECT IDENTIFIER ::= { id-ce 28 } + +IssuingDistributionPoint ::= SEQUENCE { + distributionPoint [0] DistributionPointName OPTIONAL, + onlyContainsUserCerts [1] BOOLEAN DEFAULT FALSE, + onlyContainsCACerts [2] BOOLEAN DEFAULT FALSE, + onlySomeReasons [3] ReasonFlags OPTIONAL, + indirectCRL [4] BOOLEAN DEFAULT FALSE, + onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE } + -- at most one of onlyContainsUserCerts, onlyContainsCACerts, + -- and onlyContainsAttributeCerts may be set to TRUE. + +id-ce-deltaCRLIndicator OBJECT IDENTIFIER ::= { id-ce 27 } + +BaseCRLNumber ::= CRLNumber + +-- reason code extension OID and syntax + +id-ce-cRLReasons OBJECT IDENTIFIER ::= { id-ce 21 } + +CRLReason ::= ENUMERATED { + unspecified (0), + keyCompromise (1), + cACompromise (2), + affiliationChanged (3), + superseded (4), + cessationOfOperation (5), + certificateHold (6), + removeFromCRL (8), + privilegeWithdrawn (9), + aACompromise (10) } + +-- certificate issuer CRL entry extension OID and syntax + +id-ce-certificateIssuer OBJECT IDENTIFIER ::= { id-ce 29 } + +CertificateIssuer ::= GeneralNames + +-- hold instruction extension OID and syntax + +id-ce-holdInstructionCode OBJECT IDENTIFIER ::= { id-ce 23 } + +HoldInstructionCode ::= OBJECT IDENTIFIER + +-- ANSI x9 arc holdinstruction arc + +holdInstruction OBJECT IDENTIFIER ::= + {joint-iso-itu-t(2) member-body(2) us(840) x9cm(10040) 2} + +-- ANSI X9 holdinstructions + +id-holdinstruction-none OBJECT IDENTIFIER ::= + {holdInstruction 1} -- deprecated + +id-holdinstruction-callissuer OBJECT IDENTIFIER ::= {holdInstruction 2} + +id-holdinstruction-reject OBJECT IDENTIFIER ::= {holdInstruction 3} + +-- invalidity date CRL entry extension OID and syntax + +id-ce-invalidityDate OBJECT IDENTIFIER ::= { id-ce 24 } + +InvalidityDate ::= GeneralizedTime + +END + diff --git a/pySim/esim/asn1/rsp/rsp.asn b/pySim/esim/asn1/rsp/rsp.asn new file mode 100644 index 00000000..e87b74ea --- /dev/null +++ b/pySim/esim/asn1/rsp/rsp.asn @@ -0,0 +1,785 @@ +RSPDefinitions {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1) spec-version(1) version-two(2)} +DEFINITIONS +AUTOMATIC TAGS +EXTENSIBILITY IMPLIED ::= +BEGIN + +IMPORTS Certificate, CertificateList, Time FROM PKIX1Explicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-explicit(18)} +SubjectKeyIdentifier FROM PKIX1Implicit88 {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) pkix(7) id-mod(0) id-pkix1-implicit(19)}; + +id-rsp OBJECT IDENTIFIER ::= {joint-iso-itu-t(2) international-organizations(23) gsma(146) rsp(1)} + +-- Basic types, for size constraints +Octet8 ::= OCTET STRING (SIZE(8)) +Octet16 ::= OCTET STRING (SIZE(16)) +OctetTo16 ::= OCTET STRING (SIZE(1..16)) +Octet32 ::= OCTET STRING (SIZE(32)) +Octet1 ::= OCTET STRING(SIZE(1)) +Octet2 ::= OCTET STRING (SIZE(2)) +VersionType ::= OCTET STRING(SIZE(3)) -- major/minor/revision version are coded as binary value on byte 1/2/3, e.g. '02 00 0C' for v2.0.12. +Iccid ::= [APPLICATION 26] OCTET STRING (SIZE(10)) -- ICCID as coded in EFiccid, corresponding tag is '5A' +RemoteOpId ::= [2] INTEGER {installBoundProfilePackage(1)} +TransactionId ::= OCTET STRING (SIZE(1..16)) + +-- Definition of EUICCInfo1 -------------------------- +GetEuiccInfo1Request ::= [32] SEQUENCE { -- Tag 'BF20' +} + +EUICCInfo1 ::= [32] SEQUENCE { -- Tag 'BF20' + svn [2] VersionType, -- GSMA SGP.22 version supported (SVN) + euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification + euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier -- List of CI Public Key Identifier supported on the eUICC for signature creation +} + +-- Definition of EUICCInfo2 -------------------------- +GetEuiccInfo2Request ::= [34] SEQUENCE { -- Tag 'BF22' +} + +EUICCInfo2 ::= [34] SEQUENCE { -- Tag 'BF22' + profileVersion [1] VersionType, -- SIMAlliance Profile package version supported + svn [2] VersionType, -- GSMA SGP.22 version supported (SVN) + euiccFirmwareVer [3] VersionType, -- eUICC Firmware version + extCardResource [4] OCTET STRING, -- Extended Card Resource Information according to ETSI TS 102 226 + uiccCapability [5] UICCCapability, + javacardVersion [6] VersionType OPTIONAL, + globalplatformVersion [7] VersionType OPTIONAL, + rspCapability [8] RspCapability, + euiccCiPKIdListForVerification [9] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifiers supported on the eUICC for signature verification + euiccCiPKIdListForSigning [10] SEQUENCE OF SubjectKeyIdentifier, -- List of CI Public Key Identifier supported on the eUICC for signature creation + euiccCategory [11] INTEGER { + other(0), + basicEuicc(1), + mediumEuicc(2), + contactlessEuicc(3) + } OPTIONAL, + forbiddenProfilePolicyRules [25] PprIds OPTIONAL, -- Tag '99' + ppVersion VersionType, -- Protection Profile version + sasAcreditationNumber UTF8String (SIZE(0..64)), + certificationDataObject [12] CertificationDataObject OPTIONAL +} + +-- Definition of RspCapability +RspCapability ::= BIT STRING { + additionalProfile(0), -- at least one more Profile can be installed + crlSupport(1), -- CRL + rpmSupport(2), -- Remote Profile Management + testProfileSupport (3) -- support for test profile +} + +-- Definition of CertificationDataObject +CertificationDataObject ::= SEQUENCE { + platformLabel UTF8String, -- Platform_Label as defined in GlobalPlatform DLOA specification [57] + discoveryBaseURL UTF8String -- Discovery Base URL of the SE default DLOA Registrar as defined in GlobalPlatform DLOA specification [57] +} + +CertificateInfo ::= BIT STRING { + + reserved(0), -- eUICC has a CERT.EUICC.ECDSA in GlobalPlatform format. The use of this bit is deprecated. + certSigningX509(1), -- eUICC has a CERT.EUICC.ECDSA in X.509 format + rfu2(2), + rfu3(3), + reserved2(4), -- Handling of Certificate in GlobalPlatform format. The use of this bit is deprecated. + certVerificationX509(5)-- Handling of Certificate in X.509 format +} + +-- Definition of UICCCapability +UICCCapability ::= BIT STRING { +/* Sequence is derived from ServicesList[] defined in SIMalliance PEDefinitions*/ + contactlessSupport(0), -- Contactless (SWP, HCI and associated APIs) + usimSupport(1), -- USIM as defined by 3GPP + isimSupport(2), -- ISIM as defined by 3GPP + csimSupport(3), -- CSIM as defined by 3GPP2 + + akaMilenage(4), -- Milenage as AKA algorithm + akaCave(5), -- CAVE as authentication algorithm + akaTuak128(6), -- TUAK as AKA algorithm with 128 bit key length + akaTuak256(7), -- TUAK as AKA algorithm with 256 bit key length + rfu1(8), -- reserved for further algorithms + rfu2(9), -- reserved for further algorithms + + gbaAuthenUsim(10), -- GBA authentication in the context of USIM + gbaAuthenISim(11), -- GBA authentication in the context of ISIM + mbmsAuthenUsim(12), -- MBMS authentication in the context of USIM + eapClient(13), -- EAP client + + javacard(14), -- Javacard support + multos(15), -- Multos support + + multipleUsimSupport(16), -- Multiple USIM applications are supported within the same Profile + multipleIsimSupport(17), -- Multiple ISIM applications are supported within the same Profile + multipleCsimSupport(18) -- Multiple CSIM applications are supported within the same Profile +} + +-- Definition of DeviceInfo +DeviceInfo ::= SEQUENCE { + tac Octet8, + deviceCapabilities DeviceCapabilities, + imei Octet8 OPTIONAL +} + +DeviceCapabilities ::= SEQUENCE { -- Highest fully supported release for each definition + -- The device SHALL set all the capabilities it supports + gsmSupportedRelease VersionType OPTIONAL, + utranSupportedRelease VersionType OPTIONAL, + cdma2000onexSupportedRelease VersionType OPTIONAL, + cdma2000hrpdSupportedRelease VersionType OPTIONAL, + cdma2000ehrpdSupportedRelease VersionType OPTIONAL, + eutranSupportedRelease VersionType OPTIONAL, + contactlessSupportedRelease VersionType OPTIONAL, + rspCrlSupportedVersion VersionType OPTIONAL, + rspRpmSupportedVersion VersionType OPTIONAL +} + +ProfileInfoListRequest ::= [45] SEQUENCE { -- Tag 'BF2D' + searchCriteria [0] CHOICE { + isdpAid [APPLICATION 15] OctetTo16, -- AID of the ISD-P, tag '4F' + iccid Iccid, -- ICCID, tag '5A' + profileClass [21] ProfileClass -- Tag '95' + } OPTIONAL, + tagList [APPLICATION 28] OCTET STRING OPTIONAL -- tag '5C' +} + +-- Definition of ProfileInfoList +ProfileInfoListResponse ::= [45] CHOICE { -- Tag 'BF2D' + profileInfoListOk SEQUENCE OF ProfileInfo, + profileInfoListError ProfileInfoListError +} + +ProfileInfo ::= [PRIVATE 3] SEQUENCE { -- Tag 'E3' + iccid Iccid OPTIONAL, + isdpAid [APPLICATION 15] OctetTo16 OPTIONAL, -- AID of the ISD-P containing the Profile, tag '4F' + profileState [112] ProfileState OPTIONAL, -- Tag '9F70' + profileNickname [16] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '90' + serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91' + profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92' + iconType [19] IconType OPTIONAL, -- Tag '93' + icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94', see condition in ES10c:GetProfilesInfo + profileClass [21] ProfileClass DEFAULT operational, -- Tag '95' + notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL, -- Tag 'B6' + profileOwner [23] OperatorID OPTIONAL, -- Tag 'B7' + dpProprietaryData [24] DpProprietaryData OPTIONAL, -- Tag 'B8' + profilePolicyRules [25] PprIds OPTIONAL -- Tag '99' +} + +PprIds ::= BIT STRING {-- Definition of Profile Policy Rules identifiers + pprUpdateControl(0), -- defines how to update PPRs via ES6 + ppr1(1), -- Indicator for PPR1 'Disabling of this Profile is not allowed' + ppr2(2), -- Indicator for PPR2 'Deletion of this Profile is not allowed' + ppr3(3) -- Indicator for PPR3 'Deletion of this Profile is required upon its successful disabling' +} + +OperatorID ::= SEQUENCE { + mccMnc OCTET STRING (SIZE(3)), -- MCC and MNC coded as defined in 3GPP TS 24.008 [32] + gid1 OCTET STRING OPTIONAL, -- referring to content of EF GID1 (file identifier '6F3E') as defined in 3GPP TS 31.102 [54] + gid2 OCTET STRING OPTIONAL -- referring to content of EF GID2 (file identifier '6F3F') as defined in 3GPP TS 31.102 [54] +} + +ProfileInfoListError ::= INTEGER {incorrectInputValues(1), undefinedError(127)} + +-- Definition of StoreMetadata request + +StoreMetadataRequest ::= [37] SEQUENCE { -- Tag 'BF25' + iccid Iccid, + serviceProviderName [17] UTF8String (SIZE(0..32)), -- Tag '91' + profileName [18] UTF8String (SIZE(0..64)), -- Tag '92' (corresponds to 'Short Description' defined in SGP.21 [2]) + iconType [19] IconType OPTIONAL, -- Tag '93' (JPG or PNG) + icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94'(Data of the icon. Size 64 x 64 pixel. This field SHALL only be present if iconType is present) + profileClass [21] ProfileClass OPTIONAL, -- Tag '95' (default if absent: 'operational') + notificationConfigurationInfo [22] SEQUENCE OF NotificationConfigurationInformation OPTIONAL, + profileOwner [23] OperatorID OPTIONAL, -- Tag 'B7' + profilePolicyRules [25] PprIds OPTIONAL -- Tag '99' +} + +NotificationEvent ::= BIT STRING { + notificationInstall (0), + notificationEnable(1), + notificationDisable(2), + notificationDelete(3) +} + +NotificationConfigurationInformation ::= SEQUENCE { + profileManagementOperation NotificationEvent, + notificationAddress UTF8String -- FQDN to forward the notification +} + +IconType ::= INTEGER {jpg(0), png(1)} +ProfileState ::= INTEGER {disabled(0), enabled(1)} +ProfileClass ::= INTEGER {test(0), provisioning(1), operational(2)} + +-- Definition of UpdateMetadata request +UpdateMetadataRequest ::= [42] SEQUENCE { -- Tag 'BF2A' + serviceProviderName [17] UTF8String (SIZE(0..32)) OPTIONAL, -- Tag '91' + profileName [18] UTF8String (SIZE(0..64)) OPTIONAL, -- Tag '92' + iconType [19] IconType OPTIONAL, -- Tag '93' + icon [20] OCTET STRING (SIZE(0..1024)) OPTIONAL, -- Tag '94' + profilePolicyRules [25] PprIds OPTIONAL -- Tag '99' +} + +-- Definition of data objects for command PrepareDownload ------------------------- +PrepareDownloadRequest ::= [33] SEQUENCE { -- Tag 'BF21' + smdpSigned2 SmdpSigned2, -- Signed information + smdpSignature2 [APPLICATION 55] OCTET STRING, -- DP_Sign1, tag '5F37' + hashCc Octet32 OPTIONAL, -- Hash of confirmation code + smdpCertificate Certificate -- CERT.DPpb.ECDSA +} + +SmdpSigned2 ::= SEQUENCE { + transactionId [0] TransactionId, -- The TransactionID generated by the SM DP+ + ccRequiredFlag BOOLEAN, --Indicates if the Confirmation Code is required + bppEuiccOtpk [APPLICATION 73] OCTET STRING OPTIONAL -- otPK.EUICC.ECKA already used for binding the BPP, tag '5F49' +} + +PrepareDownloadResponse ::= [33] CHOICE { -- Tag 'BF21' + downloadResponseOk PrepareDownloadResponseOk, + downloadResponseError PrepareDownloadResponseError +} + +PrepareDownloadResponseOk ::= SEQUENCE { + euiccSigned2 EUICCSigned2, -- Signed information + euiccSignature2 [APPLICATION 55] OCTET STRING -- tag '5F37' +} + +EUICCSigned2 ::= SEQUENCE { + transactionId [0] TransactionId, + euiccOtpk [APPLICATION 73] OCTET STRING, -- otPK.EUICC.ECKA, tag '5F49' + hashCc Octet32 OPTIONAL -- Hash of confirmation code +} + +PrepareDownloadResponseError ::= SEQUENCE { + transactionId [0] TransactionId, + downloadErrorCode DownloadErrorCode +} + +DownloadErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2), unsupportedCurve(3), noSessionContext(4), invalidTransactionId(5), undefinedError(127)} + +-- Definition of data objects for command AuthenticateServer-------------------- +AuthenticateServerRequest ::= [56] SEQUENCE { -- Tag 'BF38' + serverSigned1 ServerSigned1, -- Signed information + serverSignature1 [APPLICATION 55] OCTET STRING, -- tag ?5F37? + euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- CI Public Key Identifier to be used + serverCertificate Certificate, -- RSP Server Certificate CERT.XXauth.ECDSA + ctxParams1 CtxParams1 +} + +ServerSigned1 ::= SEQUENCE { + transactionId [0] TransactionId, -- The Transaction ID generated by the RSP Server + euiccChallenge [1] Octet16, -- The eUICC Challenge + serverAddress [3] UTF8String, -- The RSP Server address + serverChallenge [4] Octet16 -- The RSP Server Challenge +} + +CtxParams1 ::= CHOICE { + ctxParamsForCommonAuthentication CtxParamsForCommonAuthentication -- New contextual data objects may be defined for extensibility +} + +CtxParamsForCommonAuthentication ::= SEQUENCE { + matchingId UTF8String OPTIONAL,-- The MatchingId could be the Activation code token or EventID or empty + deviceInfo DeviceInfo -- The Device information +} + +AuthenticateServerResponse ::= [56] CHOICE { -- Tag 'BF38' + authenticateResponseOk AuthenticateResponseOk, + authenticateResponseError AuthenticateResponseError +} + +AuthenticateResponseOk ::= SEQUENCE { + euiccSigned1 EuiccSigned1, -- Signed information + euiccSignature1 [APPLICATION 55] OCTET STRING, --EUICC_Sign1, tag 5F37 + euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM + eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI +} + +EuiccSigned1 ::= SEQUENCE { + transactionId [0] TransactionId, + serverAddress [3] UTF8String, + serverChallenge [4] Octet16, -- The RSP Server Challenge + euiccInfo2 [34] EUICCInfo2, + ctxParams1 CtxParams1 +} + +AuthenticateResponseError ::= SEQUENCE { + transactionId [0] TransactionId, + authenticateErrorCode AuthenticateErrorCode +} + +AuthenticateErrorCode ::= INTEGER {invalidCertificate(1), invalidSignature(2), unsupportedCurve(3), noSessionContext(4), invalidOid(5), euiccChallengeMismatch(6), ciPKUnknown(7), undefinedError(127)} + +-- Definition of Cancel Session------------------------------ +CancelSessionRequest ::= [65] SEQUENCE { -- Tag 'BF41' + transactionId TransactionId, -- The TransactionID generated by the RSP Server + reason CancelSessionReason +} + +CancelSessionReason ::= INTEGER {endUserRejection(0), postponed(1), timeout(2), pprNotAllowed(3)} + +CancelSessionResponse ::= [65] CHOICE { -- Tag 'BF41' + cancelSessionResponseOk CancelSessionResponseOk, + cancelSessionResponseError INTEGER {invalidTransactionId(5), undefinedError(127)} +} + +CancelSessionResponseOk ::= SEQUENCE { + euiccCancelSessionSigned EuiccCancelSessionSigned, -- Signed information + euiccCancelSessionSignature [APPLICATION 55] OCTET STRING -- tag '5F37 +} + +EuiccCancelSessionSigned ::= SEQUENCE { + transactionId TransactionId, + smdpOid OBJECT IDENTIFIER, -- SM-DP+ OID as contained in CERT.DPauth.ECDSA + reason CancelSessionReason +} + +-- Definition of Bound Profile Package -------------------------- +BoundProfilePackage ::= [54] SEQUENCE { -- Tag 'BF36' + initialiseSecureChannelRequest [35] InitialiseSecureChannelRequest, -- Tag 'BF23' + firstSequenceOf87 [0] SEQUENCE OF [7] OCTET STRING, -- sequence of '87' TLVs + sequenceOf88 [1] SEQUENCE OF [8] OCTET STRING, -- sequence of '88' TLVs + secondSequenceOf87 [2] SEQUENCE OF [7] OCTET STRING OPTIONAL, -- sequence of '87' TLVs + sequenceOf86 [3] SEQUENCE OF [6] OCTET STRING -- sequence of '86' TLVs +} + +-- Definition of Get eUICC Challenge -------------------------- +GetEuiccChallengeRequest ::= [46] SEQUENCE { -- Tag 'BF2E' +} + +GetEuiccChallengeResponse ::= [46] SEQUENCE { -- Tag 'BF2E' + euiccChallenge Octet16 -- random eUICC challenge +} + +-- Definition of Profile Installation Resulceipt +ProfileInstallationResult ::= [55] SEQUENCE { -- Tag 'BF37' + profileInstallationResultData [39] ProfileInstallationResultData, + euiccSignPIR EuiccSignPIR +} + +ProfileInstallationResultData ::= [39] SEQUENCE { -- Tag 'BF27' + transactionId[0] TransactionId, -- The TransactionID generated by the SM-DP+ + notificationMetadata[47] NotificationMetadata, + smdpOid OBJECT IDENTIFIER OPTIONAL, -- SM-DP+ OID (same value as in CERT.DPpb.ECDSA) + finalResult [2] CHOICE { + successResult SuccessResult, + errorResult ErrorResult + } +} + +EuiccSignPIR ::= [APPLICATION 55] OCTET STRING -- Tag '5F37', eUICC?s signature + +SuccessResult ::= SEQUENCE { + aid [APPLICATION 15] OCTET STRING (SIZE (5..16)), -- AID of ISD-P + simaResponse OCTET STRING -- contains (multiple) 'EUICCResponse' as defined in [5] +} + +ErrorResult ::= SEQUENCE { + bppCommandId BppCommandId, + errorReason ErrorReason, + simaResponse OCTET STRING OPTIONAL -- contains (multiple) 'EUICCResponse' as defined in [5] +} + +BppCommandId ::= INTEGER {initialiseSecureChannel(0), configureISDP(1), storeMetadata(2), storeMetadata2(3), replaceSessionKeys(4), loadProfileElements(5)} + +ErrorReason ::= INTEGER { + incorrectInputValues(1), + invalidSignature(2), + invalidTransactionId(3), + unsupportedCrtValues(4), + unsupportedRemoteOperationType(5), + unsupportedProfileClass(6), + scp03tStructureError(7), + scp03tSecurityError(8), + installFailedDueToIccidAlreadyExistsOnEuicc(9), installFailedDueToInsufficientMemoryForProfile(10), + installFailedDueToInterruption(11), + installFailedDueToPEProcessingError (12), + installFailedDueToIccidMismatch(13), + testProfileInstallFailedDueToInvalidNaaKey(14), + pprNotAllowed(15), + installFailedDueToUnknownError(127) +} + +ListNotificationRequest ::= [40] SEQUENCE { -- Tag 'BF28' + profileManagementOperation [1] NotificationEvent OPTIONAL +} + +ListNotificationResponse ::= [40] CHOICE { -- Tag 'BF28' + notificationMetadataList SEQUENCE OF NotificationMetadata, + listNotificationsResultError INTEGER {undefinedError(127)} +} + +NotificationMetadata ::= [47] SEQUENCE { -- Tag 'BF2F' + seqNumber [0] INTEGER, + profileManagementOperation [1] NotificationEvent, --Only one bit set to 1 + notificationAddress UTF8String, -- FQDN to forward the notification + iccid Iccid OPTIONAL +} + +-- Definition of Profile Nickname Information +SetNicknameRequest ::= [41] SEQUENCE { -- Tag 'BF29' + iccid Iccid, + profileNickname [16] UTF8String (SIZE(0..64)) +} + +SetNicknameResponse ::= [41] SEQUENCE { -- Tag 'BF29' + setNicknameResult INTEGER {ok(0), iccidNotFound (1), undefinedError(127)} +} + +id-rsp-cert-objects OBJECT IDENTIFIER ::= { id-rsp cert-objects(2)} + +id-rspExt OBJECT IDENTIFIER ::= {id-rsp-cert-objects 0} + +id-rspRole OBJECT IDENTIFIER ::= {id-rsp-cert-objects 1} + +-- Definition of OIDs for role identification +id-rspRole-ci OBJECT IDENTIFIER ::= {id-rspRole 0} +id-rspRole-euicc OBJECT IDENTIFIER ::= {id-rspRole 1} +id-rspRole-eum OBJECT IDENTIFIER ::= {id-rspRole 2} +id-rspRole-dp-tls OBJECT IDENTIFIER ::= {id-rspRole 3} +id-rspRole-dp-auth OBJECT IDENTIFIER ::= {id-rspRole 4} +id-rspRole-dp-pb OBJECT IDENTIFIER ::= {id-rspRole 5} +id-rspRole-ds-tls OBJECT IDENTIFIER ::= {id-rspRole 6} +id-rspRole-ds-auth OBJECT IDENTIFIER ::= {id-rspRole 7} + +--Definition of data objects for InitialiseSecureChannel Request +InitialiseSecureChannelRequest ::= [35] SEQUENCE { -- Tag 'BF23' + remoteOpId RemoteOpId, -- Remote Operation Type Identifier (value SHALL be set to installBoundProfilePackage) + transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+ + controlRefTemplate[6] IMPLICIT ControlRefTemplate, -- Control Reference Template (Key Agreement). Current specification considers a subset of CRT specified in GlobalPlatform Card Specification [8], section 6.4.2.3 for the Mutual Authentication Data Field + smdpOtpk [APPLICATION 73] OCTET STRING, ---otPK.DP.ECKA as specified in GlobalPlatform Card Specification [8] section 6.4.2.3 for ePK.OCE.ECKA, tag '5F49' + smdpSign [APPLICATION 55] OCTET STRING -- SM-DP's signature, tag '5F37' +} + +ControlRefTemplate ::= SEQUENCE { +keyType[0] Octet1, -- Key type according to GlobalPlatform Card Specification [8] Table 11-16, AES= '88', Tag '80' +keyLen[1] Octet1, --Key length in number of bytes. For current specification key length SHALL by 0x10 bytes, Tag '81' +hostId[4] OctetTo16 -- Host ID value , Tag '84' +} + +--Definition of data objects for ConfigureISDPRequest +ConfigureISDPRequest ::= [36] SEQUENCE { -- Tag 'BF24' + dpProprietaryData [24] DpProprietaryData OPTIONAL -- Tag 'B8' +} + +DpProprietaryData ::= SEQUENCE { -- maximum size including tag and length field: 128 bytes + dpOid OBJECT IDENTIFIER -- OID in the tree of the SM-DP+ that created the Profile + -- additional data objects defined by the SM-DP+ MAY follow +} + +-- Definition of request message for command ReplaceSessionKeys +ReplaceSessionKeysRequest ::= [38] SEQUENCE { -- tag 'BF26' +/*The new initial MAC chaining value*/ + initialMacChainingValue OCTET STRING, +/*New session key value for encryption/decryption (PPK-ENC)*/ + ppkEnc OCTET STRING, +/*New session key value of the session key C-MAC computation/verification (PPK-MAC)*/ + ppkCmac OCTET STRING +} + +-- Definition of data objects for RetrieveNotificationsList +RetrieveNotificationsListRequest ::= [43] SEQUENCE { -- Tag 'BF2B' + searchCriteria CHOICE { + seqNumber [0] INTEGER, + profileManagementOperation [1] NotificationEvent + } OPTIONAL +} + +RetrieveNotificationsListResponse ::= [43] CHOICE { -- Tag 'BF2B' + notificationList SEQUENCE OF PendingNotification, + notificationsListResultError INTEGER {noResultAvailable(1), undefinedError(127)} +} + +PendingNotification ::= CHOICE { + profileInstallationResult [55] ProfileInstallationResult, -- tag 'BF37' + otherSignedNotification OtherSignedNotification +} + +OtherSignedNotification ::= SEQUENCE { + tbsOtherNotification NotificationMetadata, + euiccNotificationSignature [APPLICATION 55] OCTET STRING, -- eUICC signature of tbsOtherNotification, Tag '5F37' + euiccCertificate Certificate, -- eUICC Certificate (CERT.EUICC.ECDSA) signed by the EUM + eumCertificate Certificate -- EUM Certificate (CERT.EUM.ECDSA) signed by the requested CI +} + +-- Definition of notificationSent +NotificationSentRequest ::= [48] SEQUENCE { -- Tag 'BF30' + seqNumber [0] INTEGER +} + +NotificationSentResponse ::= [48] SEQUENCE { -- Tag 'BF30' + deleteNotificationStatus INTEGER {ok(0), nothingToDelete(1), undefinedError(127)} +} + +-- Definition of Enable Profile -------------------------- +EnableProfileRequest ::= [49] SEQUENCE { -- Tag 'BF31' + profileIdentifier CHOICE { + isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F' + iccid Iccid -- ICCID, tag '5A' + }, + refreshFlag BOOLEAN -- indicating whether REFRESH is required +} + +EnableProfileResponse ::= [49] SEQUENCE { -- Tag 'BF31' + enableResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInDisabledState(2), disallowedByPolicy(3), wrongProfileReenabling(4), undefinedError(127)} +} + +-- Definition of Disable Profile -------------------------- +DisableProfileRequest ::= [50] SEQUENCE { -- Tag 'BF32' + profileIdentifier CHOICE { + isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F' + iccid Iccid -- ICCID, tag '5A' + }, + refreshFlag BOOLEAN -- indicating whether REFRESH is required +} + +DisableProfileResponse ::= [50] SEQUENCE { -- Tag 'BF32' + disableResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInEnabledState(2), disallowedByPolicy(3), undefinedError(127)} +} + +-- Definition of Delete Profile -------------------------- +DeleteProfileRequest ::= [51] CHOICE { -- Tag 'BF33' + isdpAid [APPLICATION 15] OctetTo16, -- AID, tag '4F' + iccid Iccid -- ICCID, tag '5A' +} + +DeleteProfileResponse ::= [51] SEQUENCE { -- Tag 'BF33' + deleteResult INTEGER {ok(0), iccidOrAidNotFound (1), profileNotInDisabledState(2), disallowedByPolicy(3), undefinedError(127)} +} + +-- Definition of Memory Reset -------------------------- +EuiccMemoryResetRequest ::= [52] SEQUENCE { -- Tag 'BF34' + resetOptions [2] BIT STRING { + deleteOperationalProfiles(0), + deleteFieldLoadedTestProfiles(1), + resetDefaultSmdpAddress(2)} +} + +EuiccMemoryResetResponse ::= [52] SEQUENCE { -- Tag 'BF34' + resetResult INTEGER {ok(0), nothingToDelete(1), undefinedError(127)} +} + +-- Definition of Get EID -------------------------- +GetEuiccDataRequest ::= [62] SEQUENCE { -- Tag 'BF3E' + tagList [APPLICATION 28] Octet1 -- tag '5C', the value SHALL be set to '5A' +} + +GetEuiccDataResponse ::= [62] SEQUENCE { -- Tag 'BF3E' + eidValue [APPLICATION 26] Octet16 -- tag '5A' +} + +-- Definition of Get Rat + +GetRatRequest ::= [67] SEQUENCE { -- Tag ' BF43' + -- No input data +} + + +GetRatResponse ::= [67] SEQUENCE { -- Tag 'BF43' + rat RulesAuthorisationTable +} + +RulesAuthorisationTable ::= SEQUENCE OF ProfilePolicyAuthorisationRule +ProfilePolicyAuthorisationRule ::= SEQUENCE { + pprIds PprIds, + allowedOperators SEQUENCE OF OperatorID, + pprFlags BIT STRING {consentRequired(0)} +} + +-- Definition of data structure command for loading a CRL +LoadCRLRequest ::= [53] SEQUENCE { -- Tag 'BF35' + -- A CRL-A + crl CertificateList +} + +-- Definition of data structure response for loading a CRL +LoadCRLResponse ::= [53] CHOICE { -- Tag 'BF35' +loadCRLResponseOk LoadCRLResponseOk, +loadCRLResponseError LoadCRLResponseError +} + +LoadCRLResponseOk ::= SEQUENCE { + missingParts SEQUENCE OF SEQUENCE { + number INTEGER (0..MAX) + } OPTIONAL +} +LoadCRLResponseError ::= INTEGER {invalidSignature(1), invalidCRLFormat(2), notEnoughMemorySpace(3), verificationKeyNotFound(4), undefinedError(127)} + +-- Definition of the extension for Certificate Expiration Date +id-rsp-expDate OBJECT IDENTIFIER ::= {id-rspExt 1} +ExpirationDate ::= Time + +-- Definition of the extension id for total partial-CRL number +id-rsp-totalPartialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 2} +TotalPartialCrlNumber ::= INTEGER + + +-- Definition of the extension id for the partial-CRL number +id-rsp-partialCrlNumber OBJECT IDENTIFIER ::= {id-rspExt 3} +PartialCrlNumber ::= INTEGER + +-- Definition for ES9+ ASN.1 Binding -------------------------- +RemoteProfileProvisioningRequest ::= [2] CHOICE { -- Tag 'A2' + initiateAuthenticationRequest [57] InitiateAuthenticationRequest, -- Tag 'BF39' + authenticateClientRequest [59] AuthenticateClientRequest, -- Tag 'BF3B' + getBoundProfilePackageRequest [58] GetBoundProfilePackageRequest, -- Tag 'BF3A' + cancelSessionRequestEs9 [65] CancelSessionRequestEs9, -- Tag 'BF41' + handleNotification [61] HandleNotification -- tag 'BF3D' +} + +RemoteProfileProvisioningResponse ::= [2] CHOICE { -- Tag 'A2' + initiateAuthenticationResponse [57] InitiateAuthenticationResponse, -- Tag 'BF39' + authenticateClientResponseEs9 [59] AuthenticateClientResponseEs9, -- Tag 'BF3B' + getBoundProfilePackageResponse [58] GetBoundProfilePackageResponse, -- Tag 'BF3A' + cancelSessionResponseEs9 [65] CancelSessionResponseEs9, -- Tag 'BF41' + authenticateClientResponseEs11 [64] AuthenticateClientResponseEs11 -- Tag 'BF40' +} + +InitiateAuthenticationRequest ::= [57] SEQUENCE { -- Tag 'BF39' + euiccChallenge [1] Octet16, -- random eUICC challenge + smdpAddress [3] UTF8String, + euiccInfo1 EUICCInfo1 +} + +InitiateAuthenticationResponse ::= [57] CHOICE { -- Tag 'BF39' + initiateAuthenticationOk InitiateAuthenticationOkEs9, + initiateAuthenticationError INTEGER { + invalidDpAddress(1), + euiccVersionNotSupportedByDp(2), + ciPKNotSupported(3) + } +} + +InitiateAuthenticationOkEs9 ::= SEQUENCE { + transactionId [0] TransactionId, -- The TransactionID generated by the SM-DP+ + serverSigned1 ServerSigned1, -- Signed information + serverSignature1 [APPLICATION 55] OCTET STRING, -- Server_Sign1, tag '5F37' + euiccCiPKIdToBeUsed SubjectKeyIdentifier, -- The curve CI Public Key to be used as required by ES10b.AuthenticateServer + serverCertificate Certificate +} + +AuthenticateClientRequest ::= [59] SEQUENCE { -- Tag 'BF3B' + transactionId [0] TransactionId, + authenticateServerResponse [56] AuthenticateServerResponse -- This is the response from ES10b.AuthenticateServer +} + +AuthenticateClientResponseEs9 ::= [59] CHOICE { -- Tag 'BF3B' + authenticateClientOk AuthenticateClientOk, + authenticateClientError INTEGER { + eumCertificateInvalid(1), + eumCertificateExpired(2), + euiccCertificateInvalid(3), + euiccCertificateExpired(4), + euiccSignatureInvalid(5), + matchingIdRefused(6), + eidMismatch(7), + noEligibleProfile(8), + ciPKUnknown(9), + invalidTransactionId(10), + undefinedError(127) + } +} + +AuthenticateClientOk ::= SEQUENCE { + transactionId [0] TransactionId, + profileMetaData [37] StoreMetadataRequest, + prepareDownloadRequest [33] PrepareDownloadRequest +} + +GetBoundProfilePackageRequest ::= [58] SEQUENCE { -- Tag 'BF3A' + transactionId [0] TransactionId, + prepareDownloadResponse [33] PrepareDownloadResponse +} + +GetBoundProfilePackageResponse ::= [58] CHOICE { -- Tag 'BF3A' + getBoundProfilePackageOk GetBoundProfilePackageOk, + getBoundProfilePackageError INTEGER { + euiccSignatureInvalid(1), + confirmationCodeMissing(2), + confirmationCodeRefused(3), + confirmationCodeRetriesExceeded(4), + invalidTransactionId(95), + undefinedError(127) + } +} + +GetBoundProfilePackageOk ::= SEQUENCE { + transactionId [0] TransactionId, + boundProfilePackage [54] BoundProfilePackage +} + +HandleNotification ::= [61] SEQUENCE { -- Tag 'BF3D' + pendingNotification PendingNotification +} + +CancelSessionRequestEs9 ::= [65] SEQUENCE { -- Tag 'BF41' + transactionId TransactionId, + cancelSessionResponse CancelSessionResponse -- data structure defined for ES10b.CancelSession function +} + +CancelSessionResponseEs9 ::= [65] CHOICE { -- Tag 'BF41' + cancelSessionOk CancelSessionOk, + cancelSessionError INTEGER { + invalidTransactionId(1), + euiccSignatureInvalid(2), + undefinedError(127) + } +} + +CancelSessionOk ::= SEQUENCE { -- This function has no output data +} + +EuiccConfiguredAddressesRequest ::= [60] SEQUENCE { -- Tag 'BF3C' +} + +EuiccConfiguredAddressesResponse ::= [60] SEQUENCE { -- Tag 'BF3C' + defaultDpAddress UTF8String OPTIONAL, -- Default SM-DP+ address as an FQDN + rootDsAddress UTF8String -- Root SM-DS address as an FQDN +} + +ISDRProprietaryApplicationTemplate ::= [PRIVATE 0] SEQUENCE { -- Tag 'E0' + svn [2] VersionType, -- GSMA SGP.22 version supported (SVN) + lpaeSupport BIT STRING { + lpaeUsingCat(0), -- LPA in the eUICC using Card Application Toolkit + lpaeUsingScws(1) -- LPA in the eUICC using Smartcard Web Server + } OPTIONAL +} + +LpaeActivationRequest ::= [66] SEQUENCE { -- Tag 'BF42' + lpaeOption BIT STRING { + activateCatBasedLpae(0), -- LPAe with LUIe based on CAT + activateScwsBasedLpae(1) -- LPAe with LUIe based on SCWS + } +} + +LpaeActivationResponse ::= [66] SEQUENCE { -- Tag 'BF42' + lpaeActivationResult INTEGER {ok(0), notSupported(1)} +} + +SetDefaultDpAddressRequest ::= [63] SEQUENCE { -- Tag 'BF3F' + defaultDpAddress UTF8String -- Default SM-DP+ address as an FQDN +} + +SetDefaultDpAddressResponse ::= [63] SEQUENCE { -- Tag 'BF3F' + setDefaultDpAddressResult INTEGER { ok (0), undefinedError (127)} +} + +AuthenticateClientResponseEs11 ::= [64] CHOICE { -- Tag 'BF40' + authenticateClientOk AuthenticateClientOkEs11, + authenticateClientError INTEGER { + eumCertificateInvalid(1), + eumCertificateExpired(2), + euiccCertificateInvalid(3), + euiccCertificateExpired(4), + euiccSignatureInvalid(5), + eventIdUnknown(6), + invalidTransactionId(7), + undefinedError(127) + } +} + +AuthenticateClientOkEs11 ::= SEQUENCE { + transactionId TransactionId, + eventEntries SEQUENCE OF EventEntries +} + +EventEntries ::= SEQUENCE { + eventId UTF8String, + rspServerAddress UTF8String +} + +END \ No newline at end of file diff --git a/pySim/esim/es8p.py b/pySim/esim/es8p.py new file mode 100644 index 00000000..81b0fc9c --- /dev/null +++ b/pySim/esim/es8p.py @@ -0,0 +1,185 @@ +# Implementation of GSMA eSIM RSP (Remote SIM Provisioning) ES8+ +# as per SGP22 v3.0 Section 5.5 +# +# (C) 2023-2024 by Harald Welte +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from typing import Dict, List, Optional +from pySim.utils import b2h, h2b, bertlv_encode_tag, bertlv_encode_len + +import pySim.esim.rsp as rsp +from pySim.esim.bsp import BspInstance + +# Given that GSMA RSP uses ASN.1 in a very weird way, we actually cannot encode the full data type before +# signing, but we have to build parts of it separately first, then sign that, so we can put the signature +# into the same sequence as the signed data. We use the existing pySim TLV code for this. + +def wrap_as_der_tlv(tag: int, val: bytes) -> bytes: + """Wrap the 'value' into a DER-encoded TLV.""" + return bertlv_encode_tag(tag) + bertlv_encode_len(len(val)) + val + +def gen_init_sec_chan_signed_part(iscsp: Dict) -> bytes: + """Generate the concatenated remoteOpId, transactionId, controlRefTemplate and smdpOtpk data objects + without the outer SEQUENCE tag / length or the remainder of initialiseSecureChannel, as is required + for signing purpose.""" + out = b'' + out += wrap_as_der_tlv(0x82, bytes([iscsp['remoteOpId']])) + out += wrap_as_der_tlv(0x80, iscsp['transactionId']) + + crt = iscsp['controlRefTemplate'] + out_crt = wrap_as_der_tlv(0x80, crt['keyType']) + out_crt += wrap_as_der_tlv(0x81, crt['keyLen']) + out_crt += wrap_as_der_tlv(0x84, crt['hostId']) + out += wrap_as_der_tlv(0xA6, out_crt) + + out += wrap_as_der_tlv(0x5F49, iscsp['smdpOtpk']) + return out + + +# SGP.22 Section 5.5.1 +def gen_initialiseSecureChannel(transactionId: str, host_id: bytes, smdp_otpk: bytes, euicc_otpk: bytes, dp_pb): + """Generate decoded representation of (signed) initialiseSecureChannel (SGP.22 5.5.2)""" + init_scr = { 'remoteOpId': 1, # installBoundProfilePackage + 'transactionId': h2b(transactionId), + # GlobalPlatform Card Specification Amendment F [13] section 6.5.2.3 for the Mutual Authentication Data Field + 'controlRefTemplate': { 'keyType': bytes([0x88]), 'keyLen': bytes([16]), 'hostId': host_id }, + 'smdpOtpk': smdp_otpk, # otPK.DP.KA + } + to_sign = gen_init_sec_chan_signed_part(init_scr) + wrap_as_der_tlv(0x5f49, euicc_otpk) + init_scr['smdpSign'] = dp_pb.ecdsa_sign(to_sign) + return init_scr + +def gen_replace_session_keys(ppk_enc: bytes, ppk_cmac: bytes, initial_mcv: bytes) -> bytes: + """Generate encoded (but unsigned) ReplaceSessionKeysReqest DO (SGP.22 5.5.4)""" + rsk = { 'ppkEnc': ppk_enc, 'ppkCmac': ppk_cmac, 'initialMacChainingValue': initial_mcv } + return rsp.asn1.encode('ReplaceSessionKeysRequest', rsk) + + +class ProfileMetadata: + """Representation of Profile metadata. Right now only the mandatory bits are + supported, but in general this should follow the StoreMetadataRequest of SGP.22 5.5.3""" + def __init__(self, iccid_bin: bytes, spn: str, profile_name: str): + self.iccid_bin = iccid_bin + self.spn = spn + self.profile_name = profile_name + + def gen_store_metadata_request(self) -> bytes: + """Generate encoded (but unsigned) StoreMetadataReqest DO (SGP.22 5.5.3)""" + smr = { + 'iccid': self.iccid_bin, + 'serviceProviderName': self.spn, + 'profileName': self.profile_name, + } + return rsp.asn1.encode('StoreMetadataRequest', smr) + + +class ProfilePackage: + def __init__(self, metadata: Optional[ProfileMetadata] = None): + self.metadata = metadata + +class UnprotectedProfilePackage(ProfilePackage): + """Representing an unprotected profile package (UPP) as defined in SGP.22 Section 2.5.2""" + + @classmethod + def from_der(cls, der: bytes, metadata: Optional[ProfileMetadata] = None) -> 'UnprotectedProfilePackage': + """Load an UPP from its DER representation.""" + inst = cls(metadata=metadata) + cls.der = der + # TODO: we later certainly want to parse it so we can perform modification (IMSI, key material, ...) + # just like in the traditional SIM/USIM dynamic data phase at the end of personalization + return inst + + def to_der(self): + """Return the DER representation of the UPP.""" + # TODO: once we work on decoded structures, we may want to re-encode here + return self.der + +class ProtectedProfilePackage(ProfilePackage): + """Representing a protected profile package (PPP) as defined in SGP.22 Section 2.5.3""" + + @classmethod + def from_upp(cls, upp: UnprotectedProfilePackage, bsp: BspInstance) -> 'ProtectedProfilePackage': + """Generate the PPP as a sequence of encrypted and MACed Command TLVs representing the UPP""" + inst = cls(metadata=upp.metadata) + inst.upp = upp + # store ppk-enc, ppc-mac + inst.ppk_enc = bsp.c_algo.s_enc + inst.ppk_mac = bsp.m_algo.s_mac + inst.initial_mcv = bsp.m_algo.mac_chain + inst.encoded = bsp.encrypt_and_mac(0x86, upp.to_der()) + return inst + + #def __val__(self): + #return self.encoded + +class BoundProfilePackage(ProfilePackage): + """Representing a bound profile package (BPP) as defined in SGP.22 Section 2.5.4""" + + @classmethod + def from_ppp(cls, ppp: ProtectedProfilePackage): + inst = cls() + inst.upp = None + inst.ppp = ppp + return inst + + @classmethod + def from_upp(cls, upp: UnprotectedProfilePackage): + inst = cls() + inst.upp = upp + inst.ppp = None + return inst + + def encode(self, ss: 'RspSessionState', dp_pb: 'CertAndPrivkey') -> bytes: + """Generate a bound profile package (SGP.22 2.5.4).""" + + def encode_seq(tag: int, sequence: List[bytes]) -> bytes: + """Encode a "sequenceOfXX" as specified in SGP.22 specifying the raw SEQUENCE OF tag, + and assuming the caller provides the fully-encoded (with TAG + LEN) member TLVs.""" + payload = b''.join(sequence) + return bertlv_encode_tag(tag) + bertlv_encode_len(len(payload)) + payload + + bsp = BspInstance.from_kdf(ss.shared_secret, 0x88, 16, ss.host_id, h2b(ss.eid)) + + iscr = gen_initialiseSecureChannel(ss.transactionId, ss.host_id, ss.smdp_otpk, ss.euicc_otpk, dp_pb) + # generate unprotected input data + conf_idsp_bin = rsp.asn1.encode('ConfigureISDPRequest', {}) + if self.upp: + smr_bin = self.upp.metadata.gen_store_metadata_request() + else: + smr_bin = self.ppp.metadata.gen_store_metadata_request() + + # we don't use rsp.asn1.encode('boundProfilePackage') here, as the BSP already provides + # fully encoded + MACed TLVs including their tag + length values. We cannot put those as + # 'value' input into an ASN.1 encoder, as that would double the TAG + LENGTH :( + + # 'initialiseSecureChannelRequest' + bpp_seq = rsp.asn1.encode('InitialiseSecureChannelRequest', iscr) + # firstSequenceOf87 + bpp_seq += encode_seq(0xa0, bsp.encrypt_and_mac(0x87, conf_idsp_bin)) + # sequenceOF88 + bpp_seq += encode_seq(0xa1, bsp.mac_only(0x88, smr_bin)) + + if self.ppp: # we have to use session keys + rsk_bin = gen_replace_session_keys(self.ppp.ppk_enc, self.ppp.ppk_mac, self.ppp.initial_mcv) + # secondSequenceOf87 + bpp_seq += encode_seq(0xa2, bsp.encrypt_and_mac(0x87, rsk_bin)) + else: + self.ppp = ProtectedProfilePackage.from_upp(self.upp, bsp) + + # 'sequenceOf86' + bpp_seq += encode_seq(0xa3, self.ppp.encoded) + + # manual DER encode: wrap in outer SEQUENCE + return bertlv_encode_tag(0xbf36) + bertlv_encode_len(len(bpp_seq)) + bpp_seq diff --git a/pySim/esim/rsp.py b/pySim/esim/rsp.py new file mode 100644 index 00000000..b5289be2 --- /dev/null +++ b/pySim/esim/rsp.py @@ -0,0 +1,100 @@ +# Implementation of GSMA eSIM RSP (Remote SIM Provisioning) +# as per SGP22 v3.0 +# +# (C) 2023-2024 by Harald Welte +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + + +from typing import Optional +import shelve +import copyreg + +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.serialization import Encoding +from cryptography import x509 +from collections.abc import MutableMapping + +from pySim.esim import compile_asn1_subdir + +asn1 = compile_asn1_subdir('rsp') + +class RspSessionState: + """Encapsulates the state of a RSP session. It is created during the initiateAuthentication + and subsequently used by further API calls using the same transactionId. The session state + is removed either after cancelSession or after notification. + TODO: add some kind of time based expiration / garbage collection.""" + def __init__(self, transactionId: str, serverChallenge: bytes): + self.transactionId = transactionId + self.serverChallenge = serverChallenge + # used at a later point between API calsl + self.euicc_cert: Optional[x509.Certificate] = None + self.eum_cert: Optional[x509.Certificate] = None + self.eid: Optional[bytes] = None + self.profileMetadata: Optional['ProfileMetadata'] = None + self.smdpSignature2_do = None + # really only needed while processing getBoundProfilePackage request? + self.euicc_otpk: Optional[bytes] = None + self.smdp_ot: Optional[ec.EllipticCurvePrivateKey] = None + self.smdp_otpk: Optional[bytes] = None + self.host_id: Optional[bytes] = None + self.shared_secret: Optional[bytes] = None + + + def __getstate__(self): + """helper function called when pickling the object to persistent storage. We must pickel all + members that are not pickle-able.""" + state = self.__dict__.copy() + # serialize eUICC certificate as DER + if state.get('euicc_cert', None): + state['_euicc_cert'] = self.euicc_cert.public_bytes(Encoding.DER) + del state['euicc_cert'] + # serialize EUM certificate as DER + if state.get('eum_cert', None): + state['_eum_cert'] = self.eum_cert.public_bytes(Encoding.DER) + del state['eum_cert'] + # serialize one-time SMDP private key to integer + curve + if state.get('smdp_ot', None): + state['_smdp_otsk'] = self.smdp_ot.private_numbers().private_value + state['_smdp_ot_curve'] = self.smdp_ot.curve + del state['smdp_ot'] + return state + + def __setstate__(self, state): + """helper function called when unpickling the object from persistent storage. We must recreate all + members from the state generated in __getstate__ above.""" + # restore eUICC certificate from DER + if '_euicc_cert' in state: + self.euicc_cert = x509.load_der_x509_certificate(state['_euicc_cert']) + del state['_euicc_cert'] + else: + self.euicc_cert = None + # restore EUM certificate from DER + if '_eum_cert' in state: + self.eum_cert = x509.load_der_x509_certificate(state['_eum_cert']) + del state['_eum_cert'] + # restore one-time SMDP private key from integer + curve + if state.get('_smdp_otsk', None): + self.smdp_ot = ec.derive_private_key(state['_smdp_otsk'], state['_smdp_ot_curve']) + # FIXME: how to add the public key from smdp_otpk to an instance of EllipticCurvePrivateKey? + del state['_smdp_otsk'] + del state['_smdp_ot_curve'] + # automatically recover all the remainig state + self.__dict__.update(state) + + +class RspSessionStore(shelve.DbfilenameShelf): + """A derived class as wrapper around the database-backed non-volatile storage 'shelve', in case we might + need to extend it in the future. We use it to store RspSessionState objects indexed by transactionId.""" + pass diff --git a/requirements.txt b/requirements.txt index f17e293a..5b735f00 100644 --- a/requirements.txt +++ b/requirements.txt @@ -11,5 +11,6 @@ termcolor colorlog pycryptodomex cryptography +asn1tools packaging git+https://github.com/hologram-io/smpp.pdu diff --git a/smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_BRP.der b/smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_BRP.der new file mode 100644 index 0000000000000000000000000000000000000000..98942c17bd8c4d578ba94edd29df60904b268eff GIT binary patch literal 597 zcmXqLVhS{9V*IgynTe5!iIZVR$>-I-a$GJOaItY{wRxPgWnpGAa4{4x;A3MBWnt!F z4@oU9QE>J&6g1!miE#69gt!KWIJ*Xgz!Y)uum=SPfJ6>0cM?KqzNRm1!{qwq^Jzq|W{XCF9zuTHFAF6P3)R+B#gDbM^fa*rCT zpQ@KVw<1b&%HqcJ290M7WPzTNjYMd6wl1=3-I-a$GJOaItY{wRxPgWnpGAa4{4x;A3MBWnt!F z4@oU9QE>J&6g1!miE#69gt!KWIJ*Xgz!Y)uum=SPfJ6cNFq9eDAbddd4gG7)7fbpQ0T9KGrkdvyHoS&=j9OR?xsFz%nL!??Kuv(;O zW_D*VaA8siD$QDdh>0ub&3?Uj8--3)f&ZGNvYOqOH;CR$i1L3{%cKxKL&NOJCDyx_ do*h28C3JFqcAlqog8s#AIi@9@D^0&=0|0kksx$xq literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_NIST.pem b/smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_NIST.pem new file mode 100644 index 00000000..9f6f4cdc --- /dev/null +++ b/smdpp-data/certs/CertificateIssuer/CERT_CI_ECDSA_NIST.pem @@ -0,0 +1,15 @@ +-----BEGIN CERTIFICATE----- +MIICUDCCAfegAwIBAgIJALh086v6bETTMAoGCCqGSM49BAMCMEQxEDAOBgNVBAMM +B1Rlc3QgQ0kxETAPBgNVBAsMCFRFU1RDRVJUMRAwDgYDVQQKDAdSU1BURVNUMQsw +CQYDVQQGEwJJVDAgFw0yMDA0MDEwODI3NTFaGA8yMDU1MDQwMTA4Mjc1MVowRDEQ +MA4GA1UEAwwHVGVzdCBDSTERMA8GA1UECwwIVEVTVENFUlQxEDAOBgNVBAoMB1JT +UFRFU1QxCzAJBgNVBAYTAklUMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAElAZX +pnPcKI+J1S6opHcEmSeR+cNLADbmM+LQy6lFTWXbMusXmBeZ0vJDiO4rlcEJRUbJ +eQHOrrqWUJGaLiDSKaOBzzCBzDAdBgNVHQ4EFgQU9UFyvfmKldZcvriKOKHBHYAK +hcMwDwYDVR0TAQH/BAUwAwEB/zAXBgNVHSABAf8EDTALMAkGB2eBEgECAQAwDgYD +VR0PAQH/BAQDAgEGMA4GA1UdEQQHMAWIA4g3ATBhBgNVHR8EWjBYMCqgKKAmhiRo +dHRwOi8vY2kudGVzdC5leGFtcGxlLmNvbS9DUkwtQS5jcmwwKqAooCaGJGh0dHA6 +Ly9jaS50ZXN0LmV4YW1wbGUuY29tL0NSTC1CLmNybDAKBggqhkjOPQQDAgNHADBE +AiBSdWqvwgIKbOy/Ll88IIklEP8pdR0pi9OwFdlgWk/mfQIgV5goNuTSBd3S5sPB +tFWTf2tuSTtgL9G2bDV0iak192s= +-----END CERTIFICATE----- diff --git a/smdpp-data/certs/CertificateIssuer/CI-csr.cnf b/smdpp-data/certs/CertificateIssuer/CI-csr.cnf new file mode 100644 index 00000000..89fdf6db --- /dev/null +++ b/smdpp-data/certs/CertificateIssuer/CI-csr.cnf @@ -0,0 +1,25 @@ +#openssl x509 extfile params +extensions = extend +# This prevent the user to be prompted for values +prompt = no + +distinguished_name = dn-param +[dn-param] # DN fields +CN = Test CI +OU = TESTCERT +O = RSPTEST +C = IT + +# Extensions for the Test CI +[extend] # openssl extensions +subjectKeyIdentifier = hash + +basicConstraints = critical, CA:true + +certificatePolicies=critical,2.23.146.1.2.1.0 + +keyUsage =critical, keyCertSign, cRLSign + +subjectAltName = RID:2.999.1 + +crlDistributionPoints=URI:http://ci.test.example.com/CRL-A.crl, URI:http://ci.test.example.com/CRL-B.crl \ No newline at end of file diff --git a/smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_BRP.der b/smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_BRP.der new file mode 100644 index 0000000000000000000000000000000000000000..a3caae502ad922a580f68e2673206c316da3f313 GIT binary patch literal 575 zcmXqLVzM@9VtlxOnTe4J2p9~w*f_M>JkHs&Ff$pr7z!Bhu`!3TF!Qj7q!yPbIC~lj z8t{WexOq52T!TZLU4uekinw^#gMtGtYu>Y%GtT9^-YZ9bj^klMIunvl zrf&b!s(Ij)-)#TXX>&AeQj=4{+Y2SWT@=^NQchjmc;BG$j)6STT3KZl2?MbPkpp`Q zc9~6@>%1lXe|R{n!PBZ8e{LAaf)wzvh_Q%V=ljcAy+*z!^i^z++CDL+NiEUq!C@sU z$ii;G+QHmm&I94|Gcx{X0fr`fgMm0my8?(0^f54q*wY(@7?~JZ3=%;S@+?sX5e8Zd zG#03}sbrLt6jADXbM@7l8?1=EA&9nZEN*zLXIpCeP!uWQbqD`zMAI5H_RG#|8GkRBKJ+WF{e by%oWnhZ^5#f6e?Dcvva#A=~+%XD$N(F0ZCn literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_NIST.der b/smdpp-data/certs/DPauth/CERT_S_SM_DP2auth_ECDSA_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..81715bb1f03fc0360261d099cbae6ae357b22b73 GIT binary patch literal 573 zcmXqLVzM-7VtlZGnTe4J2p9~w*f_M>JkHs&Ff$pr7z!Bhu`!3TF!Qj7q!yPbIC~lj z8t{WexOq52T!TZLU4uekinw^#gMtGPTirc4j9A7Hz%Ru9pK3%=*GN(Ybly1Pk|13ANAozOPn2!pHpM_O^gNk??>X?FWp- z?r(lc|NLJ1{6bwrT+qWA-PI9Mg@Wsh7dPHFXuM+}542TQnMJ}ttU=_fW6|E9T~n{c z?Ay_0vGAa516S)|16hy)J{B<+k*V{(KMOdxPch36$=+Zf4$`gw;sZSl3?cUPMj=KfMizrakc2!-ltF}n)&h+MYHcbR zB_#z``ufS4dL_Vc*GsKP%q_@C)l1IL)pri^(RI{IF3KTNtrJ)+QnWI=GZ?rqDez5m zZ(Mo8HF#B(pp@cV8-86i?(55ZVl%EfxICC3m*&T$pcWbO!)X6zw;j(^FE!XJXKGgM TGhF;r`Tu;*8qJ$G{@(=vDnq9O literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_BRP.der b/smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_BRP.der new file mode 100644 index 0000000000000000000000000000000000000000..45c043c3c1622c31d024ec1da750f365112114ea GIT binary patch literal 573 zcmXqLVzM-7VtlZGnTe5!iHVWHfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC{~U}9isU}0=% zY!D^RYiwX(48#zwfvO>|0XIlF7Y~c0v#+b6h=CBqQf`o83c|m!c zF|u)Lt1vS&aWFEnGdnS`sK(Z=XL#QtTlT9e`I_D4e>w9DJasK3m4E!$Tdnf>=vuM9 zeb$_J8$Qje|Esd(;=YplX5}YElbWa9efdCC=G88V#f|q38t)j$18tR6W|1%uYY;iG zr(l=aq`A&p(*K8tvl=|D+VSUxfh6$=+Zf4$`gw;sZSl3?cUPMj=KfMizrakc2!-ltF}n z)&h+MYHcbRB_#z``ufS4dL_Vc*GsKP%q_@C)l1IL)pri^(RI{IF3KTNtrJ)+QnWI= zGZ?rqDKN8lUx{Q1Y}pfV(6Z3+$4=%M&vuBLzbPnm0}c$PbaZ&-7`C?OdD0>Y{1 literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_NIST.der b/smdpp-data/certs/DPauth/CERT_S_SM_DPauth_ECDSA_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..914b8a1dd4842d37092e05847fe564c3a57475d2 GIT binary patch literal 572 zcmXqLVzMx3V!XeAnTe5!iHVWHfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC{~U}9isU}0=% zY!D^RYiwX(48#zwfvO>|0XIlF7Y~c0v#+b6h=CBqQf`o83c|m!c zF+$zQ%*f8{#K7YF@5+}<_lf((rk-11P-VJBf^phZi|XyswJPr0wkphLab4#Z7bJ7h zqT_n}gPPU`C9OxiyVl5-pDi=+oa`ih-Ewi`eS^k32J%2lWtCYZ48$5lzB(4|{n<73 zTFky3T^0)u$~JJd9yX8#Dd1xfV-eXK)pSN`T7sg)uF`~s|C^V0D{?;thm@=!3%dbp z2Xlux7lhBx$oQWH7?$h}2I3&?3LrkvzrX-uPj3`rWMX77NCZj9vqTw07-%ifSfJLX zl2KApV5P60oT*m=40gTLip1Q4oK(H!{9JwKARk>vz2u@CBGo#9)gr|zvpa)<3zGte z^1Iq!akdvKEM6M?kUs47az5MX#gXd&<^|}u`5yfDm`QJkHs&Ff$pr7z!Bhu`!3TF!Qj7q!yPbIC~lj z8t{WexOq52T!TZLU4uekinw^#gMtG%1lXe|R{n!PBZ8e{LAaf)wzvh_Q$mGIxb;+jlUV5g2@We+ zK^Arc)(++la~=qvpONuD3ota<8w|uj+7&>2ppSt;#Gc+L#K^?RYLEz$kY|Z9h%nGv zps_%$O(mnGq`*pFKRHvc1Q_sosTGO21v#mD$@#hZ&Otu9j(W*OIYg>;0;@%eS7vtx z0~aO*o9YklH?OI*p5Jop_RP>DF~6?dJ9plCg2oEp_f?9|>^3kdB)Gllu4hcQSax7~ a^(VEYzAdj$AC|DX_~zsZ9cxohZa)BlysAS0 literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPpb/CERT_S_SM_DP2pb_ECDSA_NIST.der b/smdpp-data/certs/DPpb/CERT_S_SM_DP2pb_ECDSA_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..11a13398aa0d27f090ac80909f87706a458912ce GIT binary patch literal 575 zcmXqLVzM@9VtlZGnTe4J2pA2x*f_M>JkHs&Ff$pr7z!Bhu`!3TF!Qj7q!yPbIC~lj z8t{WexOq52T!TZLU4uekinw^#gMtGPTirc4j9A7CYV2g=|VfVu#kf_;t1Adu6iCPnQhoxZ_dNQtjg%WZbhJ&kf08)-}4o z&Q;y^^v>&5cR$N4Jyez>nSFisAt}a&#f|q38t)j$18tR6W|1%uYY_SBShV+N*VJn< z`*w6$EIcUNz}0%#Ko+Eck420{L}Bp?gO_^Gmt-7$t-h=GV@u@Pzt_P*B`e6nZot~X z++ofG;qx;x{$~LOCVPW{I7qt!h!6BIFof9C8-*B|7+DPxK@##TQ3eqPS_?E5sI{qN zl#~=$>FXzF>XiV)T`#pFF}ENmRWCU|SKm3vN7qp=xhRK7wN7BQNYTpd$zb5dq{y(g zUaj8nr^&g;kLGcHi%?^}H0{z?C2uaNogF9JnI}J%1S;vT3w-yi_&(c3uHb;3J`CHL U{!hCzjn}X;{h37h|3Ky20Pwr29{>OV literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_BRP.der b/smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_BRP.der new file mode 100644 index 0000000000000000000000000000000000000000..089230bbc8c94dbea872f439fa756ab83db3dbe7 GIT binary patch literal 573 zcmXqLVzM-7VtlZGnTe5!iHVWXfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC{~U}9isU}0=x zViqONYiwX(48#zwfvO>|0XIlF7Y~c0v#+b6h=CBqQf`o83c|m!c zF|u)Lt1vS&aWFEnGdnS`bQ%S}Iq4I4-~U}6?}n)|e^Qf58n-(3g%)IfY5%n_ByH*G zK7ljZ7MycFtHiv1l+kZ-Vz6=vu+<4!h@s5E!&{kPx76}8f29X1M z3U--In(MqJ{eO5ktHIN%9e-{Z$buB`v52vVtT@*D#q)LHnx*wtaPT`3DXv zSwR+d1J(}a4s$LDpP!NOKMOE0*&7VRLE05Se4vMcA;g~ED8$Ib$ZC)Xl8|SKGKetH zTA;B&txYAPq@=(~Uq3lhuLKzGdZ`tOxdl0?ddc~@`p!W2P1RrL&q~f%nc}gc;GFxvICnlKg&gnWN;Z>XLwfIC bzH#@4pu{Z&&0<6O1fktr3eWE9R#yW6(4D8K literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_NIST.der b/smdpp-data/certs/DPpb/CERT_S_SM_DPpb_ECDSA_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..3b585e8eea9b854400a1b4cbb7c428e20a4f1730 GIT binary patch literal 573 zcmXqLVzM-7V!XeAnTe5!iHVWXfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC{~U}9isU}0=x zVj3mRYiwX(48#zwfvO>|0XIlF7Y~c0v#+b6h=CBqQf`o83c|m!c zF+$zQ%*f8{#K0opqxJZL?)y2@CnYXFR>)Acv!Fvz2u@CBGo#9)gr|zvj>BLE0coV zQfWrbKY}lu5BKzJWKr=sKk3HZJy)*&y!DsseF4{O874)Bf1jKF7ykPbA=YKael;U@ W`)QAFTTIj>CVD2f?zy(LwF&^+HmZ#P literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_BRP.pem b/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_BRP.pem new file mode 100644 index 00000000..c6007b64 --- /dev/null +++ b/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_BRP.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABHNhhV5ZAmSyUscaYGKgIeJ7Rvdg +uBOCBqf3RCDvi8Vai5iNFlj51w06LYSAqt9k5ixNcSfeWgorkXqUP0R0qt0= +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_NIST.pem b/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_NIST.pem new file mode 100644 index 00000000..b8c30e2a --- /dev/null +++ b/smdpp-data/certs/DPpb/PK_S_SM_DP2pb_ECDSA_NIST.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEPi11oQYiEhbCruj61YT3eWM8+URo +G17HWpZlP19AHEdq451UbAMtMtAHCnuG5dzrqt3zHKXCdmwZa9ebwhoBgA== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_BRP.pem b/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_BRP.pem new file mode 100644 index 00000000..95c77bf2 --- /dev/null +++ b/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_BRP.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABIkyU+zJTFHfT+5uDbCVHPxlYnSB +tUGOVXBp9If6oVRmpcuOEMwrOAmc8qkp9/gtrAZRJrcdBkCWHbf5GknpVhI= +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_NIST.pem b/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_NIST.pem new file mode 100644 index 00000000..fabd554f --- /dev/null +++ b/smdpp-data/certs/DPpb/PK_S_SM_DPpb_ECDSA_NIST.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEEEwq49At75yXkmGnxnEAdrlwch0J +VaJkSuBfrkvCMU5dwJ9r8BGAJhZTQuISMYd142XztXMlNzBmuZBuC9E4jQ== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_BRP.pem b/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_BRP.pem new file mode 100644 index 00000000..1e1b4371 --- /dev/null +++ b/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_BRP.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgkrJAMDAggBAQc= +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHgCAQEEIJyuLhpWB6nVeDgu7pMuJR9SME+G7rHxcIzb08B74s09oAsGCSskAwMC +CAEBB6FEA0IABHNhhV5ZAmSyUscaYGKgIeJ7RvdguBOCBqf3RCDvi8Vai5iNFlj5 +1w06LYSAqt9k5ixNcSfeWgorkXqUP0R0qt0= +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_NIST.pem b/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_NIST.pem new file mode 100644 index 00000000..63045bd9 --- /dev/null +++ b/smdpp-data/certs/DPpb/SK_S_SM_DP2pb_ECDSA_NIST.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIGaTEUljnbqsHcPTBsWL0t/SL3O/Y6yGMZgykLV/kJNFoAoGCCqGSM49 +AwEHoUQDQgAEPi11oQYiEhbCruj61YT3eWM8+URoG17HWpZlP19AHEdq451UbAMt +MtAHCnuG5dzrqt3zHKXCdmwZa9ebwhoBgA== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_BRP.pem b/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_BRP.pem new file mode 100644 index 00000000..9da501dc --- /dev/null +++ b/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_BRP.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgkrJAMDAggBAQc= +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHgCAQEEIHX/Mi9BZhba4aSE73HUh0+w3zKV/TXCy6SJ+7K7nHv2oAsGCSskAwMC +CAEBB6FEA0IABIkyU+zJTFHfT+5uDbCVHPxlYnSBtUGOVXBp9If6oVRmpcuOEMwr +OAmc8qkp9/gtrAZRJrcdBkCWHbf5GknpVhI= +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_NIST.pem b/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_NIST.pem new file mode 100644 index 00000000..9595c072 --- /dev/null +++ b/smdpp-data/certs/DPpb/SK_S_SM_DPpb_ECDSA_NIST.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEINzWlLd4lX6Omt292UQz6e+Pc9EeSRxI1CWjipSRvTvtoAoGCCqGSM49 +AwEHoUQDQgAEEEwq49At75yXkmGnxnEAdrlwch0JVaJkSuBfrkvCMU5dwJ9r8BGA +JhZTQuISMYd142XztXMlNzBmuZBuC9E4jQ== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.csr.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.csr.cnf new file mode 100644 index 00000000..8ed5b2bb --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.csr.cnf @@ -0,0 +1,10 @@ +[ req ] +prompt = no +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +O = ACME + +# shall be aligned with SGP.23 value #TEST_DP_ADDRESS2 +CN = testsmdpplus2.example.com + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.der b/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..be20b3405c217b25b9d505ca4a1b049eecc8eca7 GIT binary patch literal 647 zcmXqLVrn*MV$xi|%*4pV#KbVufQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|BU}j)xXlY<- zXcz_Lni!ZH8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^8|kH1B<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5i_}d9o>D*aM7vV{?fZ+J{$1rhP!#mGB{kdi z+INnMsT?c+KbR)2yk7AAiMz{YWq#T!(Y;wnxQT1iUAeCfdi__nEpB3zGH7BH1N&T- zpONuD3otC$8^Df|RR!_I3`E#CwAmP0S=pI^wnJG=KvCvUSp^oLcYyw9Pj3`rWMX7C zkOhhIv52vV%#Y9JdCp*@s(Vi0vgfi;3F%h5a|ZGtX=N4(1F;5?uZ~4~e|Am17PD_h zm&L+^vJG6VhYd7A3Ithzq0)pqKsuN^%y|qFK}zLWq6{Jov=(SAP-|1kC@Cqh($`PU z)B}YjauDh}2l?na>LnND5UJJ)tQIMKFncfth_twt0EAyO%O4ls^eg;ZCW_oV0gQ=@sjuxnDQw`oDka_(RzJ+hMO4*O>wI CHN6J_ literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.ext.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.ext.cnf new file mode 100644 index 00000000..d224daf7 --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP2_TLS.ext.cnf @@ -0,0 +1,14 @@ +###################################################################################################################################################################### +# Extensions for a DPTLS +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, serverAuth, clientAuth +certificatePolicies = 2.23.146.1.2.1.3 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer + +# RID shall be aligend with SGP.23 value SM-DP+OID2 +# DNS name shall be aligned with SGP.23 value #TEST_DP_ADDRESS2 +subjectAltName = DNS:testsmdpplus2.example.com, RID:2.999.12 + +crlDistributionPoints=URI:http://ci.test.example.com/CRL-A.crl, URI:http://ci.test.example.com/CRL-B.crl + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.csr.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.csr.cnf new file mode 100644 index 00000000..abaa1dae --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.csr.cnf @@ -0,0 +1,10 @@ +[ req ] +prompt = no +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +O = ACME + +# shall be aligned with SGP.23 value #TEST_DP_ADDRESS4 +CN = testsmdpplus4.example.com + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.der b/smdpp-data/certs/DPtls/CERT_S_SM_DP4_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..07b4c855a5231b002b68d6990c59c1c173e46e6c GIT binary patch literal 647 zcmXqLVrn*MV$xi|%*4pV#KbwpfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|BU}j)xXlY<- zWEchHni!ZH8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^o9LxhB<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5i`DHHzRD}4zF9B2F|#>mcgFIhu+6*$Y6iB4 zvk%686Er*W`#BTimZQt^Y}aIKTTiW;x!bQqfceG#5`7L~rd74e7B?|U88k79fqgE^ z&&c?n1sE3W4PZyfs)G1p1|n=6+H8!htnAD{+o3EbpeS>wtO5(rJ3#-lr#A{QGBGk6 z$bv-qSj1RFg!yf&H*ZK?YZFmXwr6*C%U{o`)dun)X=N4(1F;5?uZ~4~e|Am17PD_h zm&L+^vJG6VhYd7A3Ithzq0)pqKsuN^%=ruwK}zLWq6{Jov=(SAP-|1kC@Cqh($`PU z)B}YjauDh}2l?na>LnND5UJJ)tQIMKFncfS2ZNLdq#3sz-8DbzO&TC|BU}j)xXlY<- zWElnIni!ZH8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^Tj-@$B<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5%Q;6wiC-x*^KNXK{bx<9ar3iSd!>alpHIvF z!Zs^2!czOG{QEMhDoJL7$YO>{XsY!8H@DU;}xOv@(l?fmnmcSI45gKf9)0i`loM z%VOa{*#@rG!v>ll1%fQVP-(&)ARWvd=0XOEAf@swQ3eqPS_?E5sI{qNl#~=$>FXzF z>Vd)%ISBQggM4%y^^%Knh*awYR*RHAm^~N_T$vQ=w#rZ7@GEGj*T}f>UVELK-ORPK zrgvt|Q9EgPq4CG<%S?(4{hfJB>dMw+JyGU$Ob$JG@WKWo))R04?6~Xy#%d3jt{niA C(Y&w# literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.ext.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.ext.cnf new file mode 100644 index 00000000..cc88f83f --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP8_TLS.ext.cnf @@ -0,0 +1,14 @@ +###################################################################################################################################################################### +# Extensions for a DPTLS +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, serverAuth, clientAuth +certificatePolicies = 2.23.146.1.2.1.3 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer + +# RID shall be aligend with SGP.23 value SM-DP+OID8 +# DNS name shall be aligned with SGP.23 value #TEST_DP_ADDRESS8 +subjectAltName = DNS:testsmdpplus8.example.com, RID:2.999.18 + +crlDistributionPoints=URI:http://ci.test.example.com/CRL-A.crl, URI:http://ci.test.example.com/CRL-B.crl + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.csr.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.csr.cnf new file mode 100644 index 00000000..d9b785ca --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.csr.cnf @@ -0,0 +1,10 @@ +[ req ] +prompt = no +distinguished_name = req_distinguished_name + +[ req_distinguished_name ] +O = ACME + +# shall be aligned with SGP.23 value #TEST_DP_ADDRESS1 +CN = testsmdpplus1.example.com + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.ext.cnf b/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.ext.cnf new file mode 100644 index 00000000..f80caf63 --- /dev/null +++ b/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS.ext.cnf @@ -0,0 +1,14 @@ +###################################################################################################################################################################### +# Extensions for a DPTLS +keyUsage = critical, digitalSignature +extendedKeyUsage = critical, serverAuth, clientAuth +certificatePolicies = 2.23.146.1.2.1.3 +subjectKeyIdentifier = hash +authorityKeyIdentifier = keyid:always,issuer + +# RID shall be aligend with SGP.23 value SM-DP+OID +# DNS name shall be aligned with SGP.23 value #TEST_DP_ADDRESS1 +subjectAltName = DNS:testsmdpplus1.example.com, RID:2.999.10 + +crlDistributionPoints=URI:http://ci.test.example.com/CRL-A.crl, URI:http://ci.test.example.com/CRL-B.crl + diff --git a/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS_BRP.der b/smdpp-data/certs/DPtls/CERT_S_SM_DP_TLS_BRP.der new file mode 100644 index 0000000000000000000000000000000000000000..dc730f0317e2cd411fecb81facb2a9967f4d941f GIT binary patch literal 646 zcmXqLVrnvIV$xi|%*4pV#K>vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8M6ZGq5zYG%ztW zj{<>N%7~65bL6c?0ZiBoe**@ zr}V(kIlF=zAV`DdapJz1NvOmexq$GYyh2J#?jWflnou?CR?dkS`$O`7Yx zCH;SRIIF?asvUoB7-)hN2(kc!r3rV4bTD_Aa~ULpl*+S28AKRpEznq?)~1qCQc_^0 zub-T$2MSE&Fw}Pr^3iqFOD@VGQmqqMEm8tuc4shfVN&3VQSh0ZJ*$Vo=hz~NsKwlK zPXyUD-3(Px51gc-nK4zGNkOo!pt!cavD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8M6ZGq5zYG%ztS ziUM*?49pD;p$TOi7ZNZJB8N zag+B}#vT9sHu>7|TI#FX=SxpXD%gBVQ_tjfepUPCrQg;}iRW0{#3*IZ#3%;#xhy{; z<9`-lSg<#M9VM#@;)@xGuyJU!F|x9D8$Ib$ZQ}B z66IqNV-ZpR_wkdaMBVY`x8ELUrYs5U4ZpI|KprHm%pzeR)*$lLv1sqluBq2z_U-7h zSa?vjfvfeffhI_SAPX>5ns5h52Xluxmq8*(sXR-RL4<+U0*wV~Z7LZhB?VUc`pKDk zps+*^LVf2TA6-YiS2ZNLdq#3sz-8DbzO&TC{~U}9isU}0ir zXb~mOYiwX(48#zwfw3X40XIlF7Y~c0v#+b6l7RxmQppmarNy}^1qC^!#YTFm6^Xe8 zIjMTd`MCy>2EuIYV23g>LS4+v$jVk*bV{|}~#E3X%Pf8y@4S(%@2r3{)F#lSw7 ztO>;kODy#V5l_V4v-G!4s#xZM37Q>mMDV=1FZ!b3)I?FGD=Dctn~Gh zGxb1Wi5!Ib&Otu9j(W*OIYg>;0;@$zAI$Cy1};nr>b&b^#O9}56MZe{#o)-$+;Wev zHEef7cy)NAdFEMGpb85v8@b@?`O>^S#lN?oOK+4-zpGbsIQuxCo#6ZWW2YSf;E%Mj literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP4_TLS.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP4_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..70820fa019a0db99eba434a017dcd372bf547a44 GIT binary patch literal 647 zcmXqLVrn*MV$xi|%*4pV#KbwpfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC{~U}9isU}0ir zXb~mOYiwX(48#zwfw3X40XIlF7Y~c0v#+b6l7RxmQppmarNy}^1qC^!#U^^G6^Xe8 zIjMTd`MCy>2EuIYV23g>LS4+v$j`X*`2XGDQq)uftrEs z;p~I4-vrH${C>{FxaH`wJli$d+SXI6X72VY5nz6?zeJxym}yn*vc*k|QU*dhNc*V;r>ltO>;kODy#V5l_V4v-G!4s$+(M37Q>mMDV=1FZ!b3)I?FGD=Dctn~Gh zGxb1Wi5!Ib&Otu9j(W*OIYg>;0;@$zAIu&M2ChsBg8i&4sXd3U>ua`nZ=0MEyn4E@ zmC`rWo#J;stS2ZNLdq#3sz-8DbzO&TC{~U}9itXk=n$ zY#AlaYYgI=L%9aVhP(#cAmv;Lusr8blfhv$2C6%ESnDF*74Ovl9c$IY&c@Unw*5Zfu(UXHBbd^RrlcrG+z}Ps{$o zHY+p2Qv0dp1%_9FOFg;;+ONHKKfu_ME0bQzOxm=y;qmlURRh~h?H509119_0NGK++PScAw{$D+MIyQW@?*|($1 zV&OsA2Cmk_2AUuRf-JyLX~G>K9n2l(LI#N-rSdFM1`!5Y3p5s}wW(y3loVL$>nCUG zfx;3w2=$$Vd~_Z4l8bVPROx*9 z+)qqCaMPJ_&0RnBi%bgaZ(6@sKfW>TgGW_w#^hIqeU=$6iVn5vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8LDHZU*-VhGp3*pSzN8>F0zhsDv^*VRzTKmlT@WC_sH;@p&if}GM~L%r0B#N2|M zRK4W-X!f;H2OxroXAj=Q&DdZ(ZEPC}q&Z zCb1us48RC94YJivext&}L&~Wo2h(gtM4{qRgSP3M@eX00V$My-|pf ziILer79`5YBE}+OYs}gFdH$K`OHbBjER$UB?y;_Wu7NyATA4+{K&(OJz@CC#W|QVR zZ%O|j9?oj;v}(tn8wQ#n1%fQVU}?e~A|1>f=3EAeAf@swQ3eqPS_?E5sI{qNl#~=$ z>FXzF>VX0iISlokgM4%y^^%Knh*awYR*RHCnB5r+T$mJsuYO66WKQ&ucKLfkvv%+N z^TL~0cV{eKXX0%ec2GX%DwBfzoJ~f`i*|U5_N_hs?f>4F-~K$FX=t_L)jqy2>A&k= G$O8cW{J!S^ literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP_TLS_NIST.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2021/CERT_S_SM_DP_TLS_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..38927b17046cc9fb3dc9a420bb9c0b00461f8bc6 GIT binary patch literal 647 zcmXqLVrn*MV$xW^%*4pV#K>vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8LF0zhsDv^*VRzTKmlT@WC_sH;@p&if}GM~L%r0B#N2|M zRK4W(NHlcJ=gbFeqDNor9SeJ;z- z$oQWH7#8deU`NTSg7{(vB5WMmY>cd|?94#hp)4k#D08T+0t?VPK>xF+HwrN_F)|y- zf<*aP#8^bs|9$+VDN%R4`R%s{nkh>Hd&94+G>`{LE3-%#h&70Obu8NZvuoY@i8JAjkp?l_uN)(!tze&Sj7YQYz09We{PYwLoKmTANBnNlAf~zJ7A1 z9w;o4gHYc&$Vb;vFS#g(NVQI2wMglM*^|M*jY*N=x$=#U7*S!9xmOIK z+T+cCx4v8TwVX}gC<~}$lf5UK;2xW<4U5aCUs(J=Y5Q!Gtk*>+e_u5)U7fT090vd~ CKfE3Q literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP2_TLS.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP2_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..32909ce2299daef2809ed5da1190b879c8d8fe89 GIT binary patch literal 647 zcmXqLVrn*MV$xi|%*4pV#KbVufQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|7U}|V+U}0on zY7hnF8X1@w8bi4T#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^8|kH1B<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5i_}d9o>D*aM7vV{?fZ+J{$1rhP!#mGB{kdi z+INnMsT?c+KbR)2yk7AAiMz{YWq#T!(Y;wnxQT1iUAeCfdi__nEpB3zGH7BH1N&T- zpONuD3otC$8^Df|RR!_I3`E#CwAmP0S=pI^wnJG=KvCvUSp^oLcYyw9Pj3`rWMX7C zkOhhIv52vV%#Y9JdCp*@s(Vi0vgfi;3F%h5a|ZGtX=N4(1F;5?uZ~4~e|Am17PD_h zm&L+^vJG6VhYd7A3Ithzq0)pqKsuN^%y|qFK}zLWq6{Jov=(SAP-|1kC@Cqh($`PU z)B}YjauDh}2l?na>LnND5UJJ)tQIMKFncf{ZEJC$~~>c@(GIzCE4qCLIek zh+Mt@)BAr)yRS-KJjJBQaB+7;=F&4WGPQJ!|KIcar8-5%dcpI8507(O&NoIj$884y DoF2T! literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP4_TLS.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP4_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..ea11075a255f386447f0019423eb102178850714 GIT binary patch literal 646 zcmXqLVrnvIV$xi|%*4pV#KbwpfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|7U}|V+U}0ov zY!C(H8X1@YSrD#)u_3PkH%K`b4~wI-udAVwfda%*$r7NY#kna31v#a~CVHtAiMa(i zsd~xzxdxF2!ffndhcYojUChkL&g{g%Vs-n4uks41Z`O-$%xuotov}PAY%_0xnt|=% z?1Qo21kH~8e$K?W<><0J+cnwR)>Ery?)EDYV1BW`M4v;LX;tmA#Z8P-22G4&V4utK zGcx{X0fq&81K3frsvy3Yfe0IiHX9==D?2mLb|{MpD9RivtH1*E4$%MX>5W2+OpMG1 zvLI1D7BLnPVSd}{%^OnJ+C)^8?b)5(^4GI!wShcHTA4+{K&(OJt7FmLpIuY0#q8VB zWwG#}Yy(&8VFOK&0znpFs5IdYkPhY!b3TJakWzV;D1!(Ctpyqj)Y?=sN=gc>^!1Z7 z^*~{X9EAGLK|Z>UddWpOM5=WHt3^s5%ZE=&sYdN0j4)cs533H9>)cSic?l?Z)< zN1Hc4yR`d>%JqPW_Dl*Hzg`vE_}AC0(utqGb;g_Aue{Z-E$!Pc9kYv17ve3S0RU`? ByD0zw literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP8_TLS.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP8_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..93a0cc0e183cb5125b49f9b732a47f9b486484c4 GIT binary patch literal 646 zcmXqLVrnvIV$xi|%*4pV#KbwnfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|7U}|V+U||Gg zL;<-*24;rFP_BWoA+G^9NI4e|i=(rztD%yC0>o0u5}>8UxhVw&Ii@; z8UM2Y!-Bm5>?m1P5MRtdgpEU+jggg=of&95l*I%TWe$~9U;%mu=zsR~Mj=KfMrH$9 zkSHIE7>me`I~yzXe2&+m1j_J%|t8MKprHm%pzeR)*$lLv1sqluBq2z_U-7h zSa?vjfvfeffhI_SAPX>5ns5h52XlwHkU=6ysXR-RL4<+U0*wV~Z7LZhB?VUc`pKDk zps+*^LVf2TA6-Yi#Dv{@2vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8M0XH8eD^Ftju= zjskLx49pCTp<>N%7~65bL6c?0ZiBoe**@ zr}V(kIlF=zAV`DdapJz1NvOmexq$GYyh2J#?jWflnou?CR?dkS`$O`7Yx zCH;SRIIF?asvUoB7-)hN2(kc!r3rV4bTD_Aa~ULpl*+S28AKRpEznq?)~1qCQc_^0 zub-T$2MSE&Fw}Pr^3iqFOD@VGQmqqMEm8tuc4shfVNwtaonOCh+d_-?Ii*plB5u2m z?A&$n>;7HZw_m<~(z(D}gGoW>l-(9ttNzy&J5weluWIDjxW=>Yr2YAYVN>put=Ru_ FDFAlUz;gfq literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP_TLS_NIST.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2022/CERT_S_SM_DP_TLS_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..179c37bbf09ef7942a4583a46b0abeffd843a06e GIT binary patch literal 645 zcmXqLVrn#KV$xW^%*4pV#K>vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8M0XH8eD^Ftji< zivn_u49pCTp$TOi7ZNZJB8N zag+B}#vT9sHu>7|TI#FX=SxpXD%gBVQ_tjfepUPCrQg;}iRW0{#3*IZ#3%;#xhy{; z<9`-lSg<#M9VM#@;)@xGuyJU!F|x9D8$Ib$ZQ}B z66IqNV-ZpR_wkdaMBVY`x8ELUrYs5U4ZpI|KprHm%pzeR)*$lLv1sqluBq2z_U-7h zSa?vjfvfeffhI_SAPX>5ns5h52Xluxmq8*(sXR-RL4<+U0*wV~Z7LZhB?VUc`pKDk zps+*^LVf2TA6-YiS2ZNLdq#3sz-8DbzO&TC|3U}j)pXk=n) zY!(IN8XK4!8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^8|kH1B<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5i_}d9o>D*aM7vV{?fZ+J{$1rhP!#mGB{kdi z+INnMsT?c+KbR)2yk7AAiMz{YWq#T!(Y;wnxQT1iUAeCfdi__nEpB3zGH7BH1N&T- zpONuD3otC$8^Df|RR!_I3`E#CwAmP0S=pI^wnJG=KvCvUSp^oLcYyw9Pj3`rWMX7C zkOhhIv52vV%#Y9JdCp*@s(Vi0vgfi;3F%h5a|ZGtX=N4(1F;5?uZ~4~e|Am17PD_h zm&L+^vJG6VhYd7A3Ithzq0)pqKsuN^%y|qFK}zLWq6{Jov=(SAP-|1kC@Cqh($`PU z)B}YjauDh}2l?na>LnND5UJJ)tQIMKFuOAtxG*V5-Tts3nB|n2ws3fz^kh4Ao!cyr zCQW51?CTG+C@cOumq{V-iYvd-lpEYtN^LtN%Y1A+`xXdAPjXJ0d}RYuRhHN_06y%s AO8@`> literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP4_TLS.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP4_TLS.der new file mode 100644 index 0000000000000000000000000000000000000000..b1c222c82f34943a6c07d08a9962af054f937c6c GIT binary patch literal 647 zcmXqLVrn*MV$xi|%*4pV#KbwpfQyYotIgw_EekV~fs3Jl0UsN4C<`+Wdq`?=iGs7I zp`ZajNQ9e*Bg8d0#Mw0{1g40Khdn4b03>S2ZNLdq#3sz-8DbzO&TC|3U}j)pXk=n) zVjKnJ8XK4!8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^o9LxhB<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5i`DHHzRD}4zF9B2F|#>mcgFIhu+6*$Y6iB4 zvk%686Er*W`#BTimZQt^Y}aIKTTiW;x!bQqfceG#5`7L~rd74e7B?|U88k79fqgE^ z&&c?n1sE3W4PZyfs)G1p1|n=6+H8!htnAD{+o3EbpeS>wtO5(rJ3#-lr#A{QGBGk6 z$bv-qSj1RFg!yf&H*ZK?YZFmXwr6*C%U{o`)dun)X=N4(1F;5?uZ~4~e|Am17PD_h zm&L+^vJG6VhYd7A3Ithzq0)pqKsuN^%=ruwK}zLWq6{Jov=(SAP-|1kC@Cqh($`PU z)B}YjauDh}2l?na>LnND5UJJ)tQIMKFncfS2ZNLdq#3sz-8DbzO&TC|3U}j)pXk=n) zY7zzH8XK4!8bY}S#)iBG+#uy#JS>jRzOIH!1_}^MB};&o7U!lE6y%f^Tj-@$B<2?6 zr0ON-=Nd#B2(z(+9m>QAbulv|JF^o5%Q;6wiC-x*^KNXK{bx<9ar3iSd!>alpHIvF z!Zs^2!czOG{QEMhDoJL7$YO>{XsY!8H@DU;}xOv@(l?fmnmcSI45gKf9)0i`loM z%VOa{*#@rG!v>ll1%fQVP-(&)ARWvd=0XOEAf@swQ3eqPS_?E5sI{qNl#~=$>FXzF z>Vd)%ISBQggM4%y^^%Knh*awYR*RHAm^~Q`+?W&@rmGYetbZxa6xCxAzU$G9T*bwU zm)dLZogX>jZ`)!f*Hu6zJ3Zv~6)&s&E!vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8L_VGq5l;GBGtW zivn_u4a^M<>N%7~65bL6c?0ZiBoe**@ zr}V(kIlF=zAV`DdapJz1NvOmexq$GYyh2J#?jWflnou?CR?dkS`$O`7Yx zCH;SRIIF?asvUoB7-)hN2(kc!r3rV4bTD_Aa~ULpl*+S28AKRpEznq?)~1qCQc_^0 zub-T$2MSE&Fw}Pr^3iqFOD@VGQmqqMEm8tu_GB<{V^U;jN#l8bV>4G~yibbiF12%P zQT>xIPM>zweD#)w^Sb|~OMpsd@=wy=y>nya4B<7_?{2UB!_U5TqOWn>{HRO6mmlWZ GEDQimpuE5U literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP_TLS_NIST.der b/smdpp-data/certs/DPtls/Old_TLS_Validity/Expired 2023/CERT_S_SM_DP_TLS_NIST.der new file mode 100644 index 0000000000000000000000000000000000000000..6977bd324cf3fd3846bfac54074d5c942329b835 GIT binary patch literal 646 zcmXqLVrnvIV$xW^%*4pV#K>vD#m1r4=5fxJg_+5~#ZbV2kBvE$g_(yvB(=Ci!P(PL z(10H#!p*}G;u;*{>>3mTQ^du?9uyn^5;f#D-~=gR6K3)ZF_07IH8L_VGq5l;GBGhV zi~@3v4a^M$TOi7ZNZJB8N zag+B}#vT9sHu>7|TI#FX=SxpXD%gBVQ_tjfepUPCrQg;}iRW0{#3*IZ#3%;#xhy{; z<9`-lSg<#M9VM#@;)@xGuyJU!F|x9D8$Ib$ZQ}B z66IqNV-ZpR_wkdaMBVY`x8ELUrYs5U4ZpI|KprHm%pzeR)*$lLv1sqluBq2z_U-7h zSa?vjfvfeffhI_SAPX>5ns5h52Xluxmq8*(sXR-RL4<+U0*wV~Z7LZhB?VUc`pKDk zps+*^LVf2TA6-YiK^=Fqo3eqv(mGV91&)VYY^ETY9 zTr6_qT1Dml8)q69Gbu9sjc>5EW>~)L_O{B<_LFBsb01zSHhZ`uqg?G+#Rvb&^8o&3 BzSjT% literal 0 HcmV?d00001 diff --git a/smdpp-data/certs/DPtls/PK_S_SM_DP2_TLS_NIST.pem b/smdpp-data/certs/DPtls/PK_S_SM_DP2_TLS_NIST.pem new file mode 100644 index 00000000..702bcf76 --- /dev/null +++ b/smdpp-data/certs/DPtls/PK_S_SM_DP2_TLS_NIST.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEGtkADHVON2E+dQ+3v3NC/tULwHJS +7YRla0XW9wh4lQip/+CWFyOvEe/I3aaaafK1GIuzEhOCCrLdHvWALo/Utg== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPtls/PK_S_SM_DP4_TLS.pem b/smdpp-data/certs/DPtls/PK_S_SM_DP4_TLS.pem new file mode 100644 index 00000000..9c165c7b --- /dev/null +++ b/smdpp-data/certs/DPtls/PK_S_SM_DP4_TLS.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEOtvoTSOoGvY7otiZg2y7aKdiVrMN +cCYwPcNrwV32ETbE++cCAbTFpm49rGsrO5V6mbtOdBAD6L90LwgTAqp9pg== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPtls/PK_S_SM_DP8_TLS.pem b/smdpp-data/certs/DPtls/PK_S_SM_DP8_TLS.pem new file mode 100644 index 00000000..0ff45865 --- /dev/null +++ b/smdpp-data/certs/DPtls/PK_S_SM_DP8_TLS.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEzkExGPpkmW7Yspv8rIUzg+ZdPyKh +meeWa/QGmmlYOSvlOdAA6lGlSIsQh9brR8ABhG0eaH7EkOgagJZJQgxSaw== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_BRP.pem b/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_BRP.pem new file mode 100644 index 00000000..8fd826fc --- /dev/null +++ b/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_BRP.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFowFAYHKoZIzj0CAQYJKyQDAwIIAQEHA0IABEwizNgsjQIh+dhUO3LhB7zJ/ZBU +1mx1wOt0p73nMOdhjvZbJwteguQ6eW+N7guvivvrilNiU3oC/WXHnkEZa7U= +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_NIST.pem b/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_NIST.pem new file mode 100644 index 00000000..15ea8ea1 --- /dev/null +++ b/smdpp-data/certs/DPtls/PK_S_SM_DP_TLS_NIST.pem @@ -0,0 +1,4 @@ +-----BEGIN PUBLIC KEY----- +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEKCQwdc6O/R+uZ2g5QH2ybkzLQ3CU +YhybOWEz8bJLtQG4/k6yTT4NOS8lP28blGJws8opLjTbb3qHs6X2rJRfCA== +-----END PUBLIC KEY----- diff --git a/smdpp-data/certs/DPtls/SK_S_SM_DP2_TLS_NIST.pem b/smdpp-data/certs/DPtls/SK_S_SM_DP2_TLS_NIST.pem new file mode 100644 index 00000000..b25606d4 --- /dev/null +++ b/smdpp-data/certs/DPtls/SK_S_SM_DP2_TLS_NIST.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIE5lYcZAiPZpkHrb45SxGoQkLgM6gqiEAjFjbckbTuP1oAoGCCqGSM49 +AwEHoUQDQgAEGtkADHVON2E+dQ+3v3NC/tULwHJS7YRla0XW9wh4lQip/+CWFyOv +Ee/I3aaaafK1GIuzEhOCCrLdHvWALo/Utg== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPtls/SK_S_SM_DP4_TLS.pem b/smdpp-data/certs/DPtls/SK_S_SM_DP4_TLS.pem new file mode 100644 index 00000000..32bdfde3 --- /dev/null +++ b/smdpp-data/certs/DPtls/SK_S_SM_DP4_TLS.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIPJlnS9Sj0sRN0DVig0q8+srSOEiwrYKavb8lq2Gvm+koAoGCCqGSM49 +AwEHoUQDQgAEOtvoTSOoGvY7otiZg2y7aKdiVrMNcCYwPcNrwV32ETbE++cCAbTF +pm49rGsrO5V6mbtOdBAD6L90LwgTAqp9pg== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPtls/SK_S_SM_DP8_TLS.pem b/smdpp-data/certs/DPtls/SK_S_SM_DP8_TLS.pem new file mode 100644 index 00000000..51ca1685 --- /dev/null +++ b/smdpp-data/certs/DPtls/SK_S_SM_DP8_TLS.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIP9uSlCbrds4EIgxwjzMLUQwevKB6SWWf4zfHZVUoCiNoAoGCCqGSM49 +AwEHoUQDQgAEzkExGPpkmW7Yspv8rIUzg+ZdPyKhmeeWa/QGmmlYOSvlOdAA6lGl +SIsQh9brR8ABhG0eaH7EkOgagJZJQgxSaw== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_BRP.pem b/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_BRP.pem new file mode 100644 index 00000000..6ad37b0e --- /dev/null +++ b/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_BRP.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BgkrJAMDAggBAQc= +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHgCAQEEID9nFSgCs/TH+uZ5WFX2glQeReNe//TooFVloPGRKnguoAsGCSskAwMC +CAEBB6FEA0IABEwizNgsjQIh+dhUO3LhB7zJ/ZBU1mx1wOt0p73nMOdhjvZbJwte +guQ6eW+N7guvivvrilNiU3oC/WXHnkEZa7U= +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_NIST.pem b/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_NIST.pem new file mode 100644 index 00000000..c1329f94 --- /dev/null +++ b/smdpp-data/certs/DPtls/SK_S_SM_DP_TLS_NIST.pem @@ -0,0 +1,8 @@ +-----BEGIN EC PARAMETERS----- +BggqhkjOPQMBBw== +-----END EC PARAMETERS----- +-----BEGIN EC PRIVATE KEY----- +MHcCAQEEIKA+fORVBHS+pLeoc5nOWoyfZhtoD5QBOf/4Tp3sak2MoAoGCCqGSM49 +AwEHoUQDQgAEKCQwdc6O/R+uZ2g5QH2ybkzLQ3CUYhybOWEz8bJLtQG4/k6yTT4N +OS8lP28blGJws8opLjTbb3qHs6X2rJRfCA== +-----END EC PRIVATE KEY----- diff --git a/smdpp-data/certs/README b/smdpp-data/certs/README new file mode 100644 index 00000000..a3cd547a --- /dev/null +++ b/smdpp-data/certs/README @@ -0,0 +1 @@ +files taken from SGP.26 v3 diff --git a/smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.1_NoBERTLV.rename2der b/smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.1_NoBERTLV.rename2der new file mode 100644 index 0000000000000000000000000000000000000000..78006773929a4086852f0a7afff288e5e9e45c6f GIT binary patch literal 12207 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 MvZOv1mDJPz2h_KZ(f|Me literal 0 HcmV?d00001 diff --git a/smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.3_NoBERTLV.rename2der b/smdpp-data/upp/TS48 V2 eSIM_GTP_SAIP2.3_NoBERTLV.rename2der new file mode 100644 index 0000000000000000000000000000000000000000..0a0bdff5a230caa07dfe9592fec1ddff83fc979a GIT binary patch literal 12251 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 +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +import unittest +import logging +import base64 + +from pySim.utils import b2h, h2b +from pySim.esim.bsp import * +import pySim.esim.rsp as rsp + +from cryptography.hazmat.primitives.asymmetric import ec + +class TestECKA(unittest.TestCase): + def test_mode51(self): + curve = ec.SECP256R1() + euicc_otpk_der = h2b('0400f7b8d71403f21d84b00cd9e561178d737d3f4d065e62fee279271298dd4f074794ab791b9939d4461296efe388aa26731064263af988b7d2c4d77da44801b5') + smdp_otpk_der = h2b('04a27e2bdbd94dcf67d4c9ae5cb149d9d0f093be7a16dc41ec9db0318e4db72d09234a7d7631979a5d150eec40afe17ce41673df9d2f2e4246d60051c74eba7964') + smdp_otsk_bytes = h2b('fb68a38ccedb69e15cbe03c256228998ac398587e5dc7117f948145c839d61a4') + expected_shared_secret = h2b('c9a993dd4879a8f7161f2085410edd4f9652f1df37be097ba96ba2ca6be528fe') + + euicc_otpk = ec.EllipticCurvePublicKey.from_encoded_point(curve, bytes(euicc_otpk_der)) + smdp_otpk = ec.EllipticCurvePublicKey.from_encoded_point(curve, bytes(smdp_otpk_der)) + smdp_otsk = ec.derive_private_key(int.from_bytes(smdp_otsk_bytes, 'big'), curve) + + shared_secret = smdp_otsk.exchange(ec.ECDH(), euicc_otpk) + + self.assertEqual(shared_secret, expected_shared_secret) + + +class TestBSPdecode(unittest.TestCase): + bpp_b64 = "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" + + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/test_esim_bsp.py b/tests/test_esim_bsp.py index 650b1fda..d7b37b08 100755 --- a/tests/test_esim_bsp.py +++ b/tests/test_esim_bsp.py @@ -21,6 +21,7 @@ import base64 from pySim.utils import b2h, h2b from pySim.esim.bsp import * +import pySim.esim.rsp as rsp class BSP_Test(unittest.TestCase): shared_secret = h2b('8902dca391bbb22570fe60c176076246f568b1941265dff1d729e63039658089') @@ -68,5 +69,30 @@ class BSP_Test_mode51(unittest.TestCase): self.assertEqual(output, h2b('868203f8648e034ae0dc4ce022ee1e60b130dda95e13b21b0da3de7677677f47900c1beb3637b8aa35f3a9e096c0285ffe3e931983df900b36b7e6bc4b9af14b0ee3d49637eb2d4cff314b5d00789a751dfd9554651fb2b7c66ad4e22a794d5b88cb71ccf4c05d53abeba8bd3b0c8209346f014cbdee62be4878e3fea09a96007135a6c584aa843c48972842bdbece1c439723021b3f0d535d557995beedbd2b56f416148df90cb1a4d2fa26288801d56a2cbb0a404f2fd9a73042d7a3486bfb7256c1d274aae5b7ec24e8eba28b7dce69edc44189b24186b98397b4a74831f8ab46e8e46a2ed3077d4924f5d3f6e4c1de5ddffd194e7f0f97d94ea2801d1364835c9871bae6539e3e1355c5970711d845864f04d9c1dccac0d4068dcf4664e9976509fe43fec6beb3ddc96839aba6d89bb1593c5b6ebbc32fff39c4a5bb3e5c9df6a1abc05818dbd5149733381e69521066e1bbd648eb19b00602767e90beaeb3b3b92679940a603c0500e37892d7b4fa44355c3deec8af207f89d04f83cd88603e9cb9c96f74643816e87af85a8a9d0283cdf535d1fbaefb930fd4a0dba2ae30ee9d2d9e2a31827a012a6380af42ac87f3bfd7079ddd8fa27d2299fb4d5879e9a17a5062e13cab4f7bed22ed54932fa53d630bca8592f957a7ed148e9d4f28075c2565a550694b876091a1181ba512e70fde4f28ae6968a18d721396c0fee9cd7744dee90bf85f5adddb3417b3ede9ea3cfd5eae2d820b17600ce3b95f6df38a5bc39302c5155c3f241ddfc7cee527af7f6a67868a577c39e76e26c4ed5d6aca031a97c280da27ae8de20e57a1dbab40a31e96e054f9a6f50578fd00156e37b70eead71af3258075c1ba84282aea462553504a868443b301ed99dcd5f414b720ef67cf5c4d16f1f7b9df741c2343246dcb717f3fa62b633539bdcc0082d161499caad8d097be78133dafd19777559f77c6d7a8f61323ff660613aa47cee26a4f7515204eee3c7eaa00eb55529b0ddae3436ec679fc591fe2063de94db00b5d0f041beeb80a91f108f7cf4b3b1344b0fbb437630ee437b4c7744c54009a59a9099681f3a3fa386f294c0eb4562581202a369772833efdc6e840695352de3864671e7fb0fd081ec162a2a62ea5b8a9da837f3920b4196fbe2ec912ade440537ae4a07dfc115c9c030539f278e0801bda4f15298ba50e329b18992af8b899686ec97175509d4a217d2eba8feef5f5732fc7be86370f7723896b784bd45517af86a7521e952b6be924d91a5190e3c2c65ce8924df43ddb25c529dde324a722a156df459f4b38bb062975fad9fadd27f6425e422b1abd9a7259f0bd712a486e1aa25ca848cf65c5fb888bf61ae136b68cf55cb643c198537cd83df0dbb842c5f4982ca3088cc2d8e867c3049a84b515ec39b0b774a8482099327006acff')) +class TestBSPdecode(unittest.TestCase): + """This test verifies whether some fully encoded/encrypted/MACed bound profile package can be properly + decrypted and verified using our BSP code base.""" + bpp_b64 = "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" + + def test_decrypt_and_mac_verify(self): + bpp_bin = base64.b64decode(self.bpp_b64) + iscr = rsp.asn1.decode('BoundProfilePackage', bpp_bin) + + # BSP segment for ConfigureISDP using S-ENC/S-MAC + bsp = BspInstance(h2b('f11b921c302efb1df6bf218bf2de0dd8'), h2b('8cd4d3a761eeac108641d5f4531a137e'), h2b('ee3140eafd692b68eff40119b363bc6c')) + plain_cfg_isdp = bsp.demac_and_decrypt(iscr['firstSequenceOf87']) + self.assertEqual(plain_cfg_isdp, h2b('bf2400')) + + # BSP segment for StoreMetadata using /S-MAC + plain_smd = bsp.demac_only(iscr['sequenceOf88']) + self.assertEqual(plain_smd, h2b('bf25285a0a89000123456789012341910a4f736d6f636f6d53504e920e4f736d6f636f6d50726f66696c65')) + + # BSP payload using PPK-ENC/PPK-MAC + bsp_ppk = BspInstance(h2b('00000000000000000000000000000000'), h2b('11111111111111111111111111111111'), h2b('22222222222222222222222222222222')) + plain_upp = bsp_ppk.demac_and_decrypt(iscr['sequenceOf86']) + original_upp = b'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wLSCCiugBYAAgQEJgQZngQ8BAgWiEaEPggJBIYMCbwWLA28GBaUAoxmhF4ICQSGDAm83iwNvBgmIAKUGwAFAwgEApB+hHYIERiEAA4MCbzmLA28GC4ABD4gB4KUGwAGAwgEApRqhFIICQSGDAm8+iwNvBgSAAQKIAKUAgwL//6YaoRSCAkEhgwJvP4sDbwYEgAECiAClAIMC//+nGKEWggRCIQAcgwJvQIsDbwYEgAE4iAClAKgaoRGCAkEhgwJvQYsDbwYBiAClAIMF////AACpFqEUggJBIYMCb0WLA28GAoABCIgApQCqFKESggJBIYMCb0iLA28GBIABCKUAqxihFoIEQiEAHIMCb0mLA28GCoABjIgApQCsHKEaggRCIQANgwJvS4sDbwYBgAFBiAClBMECAP+tHKEaggRCIQANgwJvTIsDbwYDgAFBiAClBMECAP+uFqEUggJBIYMCb1CLA28GBoABEIgApQCvgcGhEoICQSGDAm9giwNvBgaAAaqlAIOBqv///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAAsIIBEaESggJBIYMCb2GLA28GA4AB+qUAg4H6////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AALGCARGhEoICQSGDAm9iiwNvBgOAAfqlAIOB+v///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AAD///8AAP///wAA////AACyFqEUggJBIYMCbyyLA28GAogApQPAAUCzGaEXggJBIYMCbzKLA28GA4ABPIgApQPAAUC0HaEbggRCIQAegwJvR4sDbwYCgAIBLIgApQTBAgD/tRuhGYIEQiEAFYMCb02LA28GAYABP4gApQPAAUC2HKEaggRCIQANgwJvTosDbwYCgAFBiAClBMECAP+3E6ERggRCIQAPgwJvT4sDbwYCpQC5GqEYggJBIYMCb1eLA28GAYAByIgApQTBAgD/uhuhGYIEQiEAVYMCb1iLA28GA4ABqogApQPAAUC7RKFCggRGIQAqgwJvgIsDbwYCgAHSpS7AAYDBKf//////////////////////////////////////////////AAAAAAD/vEOhQYIERiEAKYMCb4GLA28GAoABzaUtwAGAwSj//////////////////////////////////////////////wAAAAD/vR6hHIIERiEAA4MCb4KLA28GC4ABHogApQbAAYDCAQC+HqEcggRGIQADgwJvg4sDbwYLgAEeiAClBsABgMIBAL8fgeShF4ICQSGDAm+xiwNvBgSAAciIAKUDwAFAg4HIIf///yHz//8hQ///IUP4/yFDGf8hUyD5IVPx/yFT8v8hU/P/IVP0/yFT9f8hU/b/IVP3/yFT+P8hU/n/AgDw/wIA8f8CAPL/AgDz/wIA9P8CAPX/AgD2/wIA9/8CAPj/AgD5/wIQ8P9mZvD/Zmbx/2Zm8v9mZoP/Zmb0/2Zm9f9mZvb/Zmb3/2Zm+P9mZvn/Znbw/wgh8P8IIfH/CCHy/wgh8/8IIfT/CCH1/wgh9v8IIff/CCH4/wgh+f8IMfD/mZn5/xEREfm/IB+hFIICQSGDAm+yiwNvBgOIAKUDwAFAgwcVAAAA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' + self.assertEqual(plain_upp, base64.b64decode(original_upp)) + + if __name__ == "__main__": unittest.main()