laforge has uploaded this change for review. ( 
https://gerrit.osmocom.org/c/pysim/+/35635?usp=email )


Change subject: osmo-smdpp: Implement eUICC + EUM certificate signatre chain 
validation
......................................................................

osmo-smdpp: Implement eUICC + EUM certificate signatre chain validation

Change-Id: I961827c50ed5e34c6507bfdf853952ece5b0d121
---
M osmo-smdpp.py
M pySim/esim/rsp.py
2 files changed, 42 insertions(+), 20 deletions(-)



  git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/35/35635/1

diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index 7e0db27..2d1cd66 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -36,7 +36,8 @@

 import pySim.esim.rsp as rsp
 from pySim.esim.es8p import *
-from pySim.esim.x509_cert import oid, cert_policy_has_oid, CertAndPrivkey
+from pySim.esim.x509_cert import oid, cert_policy_has_oid, cert_get_auth_key_id
+from pySim.esim.x509_cert import CertAndPrivkey, CertificateSet, 
cert_get_subject_key_id

 # HACK: make this configurable
 DATA_DIR = './smdpp-data'
@@ -214,7 +215,11 @@
         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):
+        for x in pkid_list:
+            ci_cert = self.ci_get_cert_for_pkid(x)
+            if ci_cert:
+                break
+        if not ci_cert:
            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:
@@ -257,7 +262,8 @@
         #output['otherCertsInChain'] = b64encode2str()

         # create SessionState and store it in rss
-        self.rss[transactionId] = rsp.RspSessionState(transactionId, 
serverChallenge)
+        self.rss[transactionId] = rsp.RspSessionState(transactionId, 
serverChallenge,
+                                                      
cert_get_subject_key_id(ci_cert))

         return output

@@ -292,29 +298,35 @@
         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?
+        ss.eum_cert = eum_cert # TODO: 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
+        # Verify that the Root Certificate of the eUICC certificate chain 
corresponds to the
+        # euiccCiPKIdToBeUsed or TODO: euiccCiPKIdToBeUsedV3
+        if cert_get_auth_key_id(eum_cert) != ss.ci_cert_id:
+            raise ApiError('8.11.1', '3.9', 'Unknown')
+
+        # Verify the validity of the eUICC certificate chain
+        cs = CertificateSet(self.ci_get_cert_for_pkid(ss.ci_cert_id))
+        cs.add_intermediate_cert(eum_cert)
+        # TODO v3: otherCertsInChain
+        try:
+            cs.verify_cert_chain(euicc_cert)
+        except VerifyError:
+            raise ApiError('8.1.3', '6.1', 'Verification failed')
+        #   raise ApiError('8.1.3', '6.3', 'Expired')
+
+
+        # 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')
+
         # 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
diff --git a/pySim/esim/rsp.py b/pySim/esim/rsp.py
index b5289be..1f8e989 100644
--- a/pySim/esim/rsp.py
+++ b/pySim/esim/rsp.py
@@ -35,10 +35,11 @@
     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):
+    def __init__(self, transactionId: str, serverChallenge: bytes, ci_cert_id: 
bytes):
         self.transactionId = transactionId
         self.serverChallenge = serverChallenge
         #  used at a later point between API calsl
+        self.ci_cert_id = ci_cert_id
         self.euicc_cert: Optional[x509.Certificate] = None
         self.eum_cert: Optional[x509.Certificate] = None
         self.eid: Optional[bytes] = None

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/35635?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings

Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I961827c50ed5e34c6507bfdf853952ece5b0d121
Gerrit-Change-Number: 35635
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <[email protected]>
Gerrit-MessageType: newchange

Reply via email to