Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/40468?usp=email )
Change subject: smdpp: less verbose by default ......................................................................
smdpp: less verbose by default
Those data blobs are huge.
Change-Id: I04a72b8f52417862d4dcba1f0743700dd942ef49 --- M osmo-smdpp.py M pySim/esim/bsp.py M pySim/esim/es8p.py 3 files changed, 51 insertions(+), 11 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/68/40468/1
diff --git a/osmo-smdpp.py b/osmo-smdpp.py index 92bbb42..b8b6303 100755 --- a/osmo-smdpp.py +++ b/osmo-smdpp.py @@ -47,6 +47,9 @@ 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, VerifyError
+import logging +logger = logging.getLogger(__name__) + # HACK: make this configurable DATA_DIR = './smdpp-data' HOSTNAME = 'testsmdpplus1.example.com' # must match certificates! @@ -356,7 +359,7 @@ validate_request_headers(request)
content = json.loads(request.content.read()) - print("Rx JSON: %s" % json.dumps(content)) + logger.debug("Rx JSON: %s" % json.dumps(content)) set_headers(request)
output = func(self, request, content) @@ -364,7 +367,7 @@ return ''
build_resp_header(output) - print("Tx JSON: %s" % json.dumps(output)) + logger.debug("Tx JSON: %s" % json.dumps(output)) return json.dumps(output) return _api_wrapper
@@ -383,7 +386,7 @@
euiccInfo1_bin = b64decode(content['euiccInfo1']) euiccInfo1 = rsp.asn1.decode('EUICCInfo1', euiccInfo1_bin) - print("Rx euiccInfo1: %s" % euiccInfo1) + logger.debug("Rx euiccInfo1: %s" % euiccInfo1) #euiccInfo1['svn']
# TODO: If euiccCiPKIdListForSigningV3 is present ... @@ -458,7 +461,7 @@
authenticateServerResp_bin = b64decode(content['authenticateServerResponse']) authenticateServerResp = rsp.asn1.decode('AuthenticateServerResponse', authenticateServerResp_bin) - print("Rx %s: %s" % authenticateServerResp) + logger.debug("Rx %s: %s" % authenticateServerResp) if authenticateServerResp[0] == 'authenticateResponseError': r_err = authenticateServerResp[1] #r_err['transactionId'] @@ -589,7 +592,7 @@
prepDownloadResp_bin = b64decode(content['prepareDownloadResponse']) prepDownloadResp = rsp.asn1.decode('PrepareDownloadResponse', prepDownloadResp_bin) - print("Rx %s: %s" % prepDownloadResp) + logger.debug("Rx %s: %s" % prepDownloadResp)
if prepDownloadResp[0] == 'downloadResponseError': r_err = prepDownloadResp[1] @@ -611,7 +614,7 @@
# store otPK.EUICC.ECKA in session state ss.euicc_otpk = euiccSigned2['euiccOtpk'] - print("euiccOtpk: %s" % (b2h(ss.euicc_otpk))) + logger.debug("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 @@ -619,8 +622,8 @@ 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()))) + logger.debug("smdpOtpk: %s" % b2h(ss.smdp_otpk)) + logger.debug("smdpOtsk: %s" % b2h(ss.smdp_ot.private_bytes(Encoding.DER, PrivateFormat.PKCS8, NoEncryption())))
ss.host_id = b'mahlzeit'
@@ -661,7 +664,7 @@ request.setResponseCode(204) pendingNotification_bin = b64decode(content['pendingNotification']) pendingNotification = rsp.asn1.decode('PendingNotification', pendingNotification_bin) - print("Rx %s: %s" % pendingNotification) + logger.debug("Rx %s: %s" % pendingNotification) if pendingNotification[0] == 'profileInstallationResult': profileInstallRes = pendingNotification[1] pird = profileInstallRes['profileInstallationResultData'] @@ -714,7 +717,7 @@ @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) + logger.debug("Rx JSON: %s" % content) transactionId = content['transactionId']
# Verify that the received transactionId is known and relates to an ongoing RSP session @@ -724,7 +727,7 @@
cancelSessionResponse_bin = b64decode(content['cancelSessionResponse']) cancelSessionResponse = rsp.asn1.decode('CancelSessionResponse', cancelSessionResponse_bin) - print("Rx %s: %s" % cancelSessionResponse) + logger.debug("Rx %s: %s" % cancelSessionResponse)
if cancelSessionResponse[0] == 'cancelSessionResponseError': # FIXME: print some error @@ -760,8 +763,11 @@ parser.add_argument("-p", "--port", help="TCP port to bind HTTP to", default=8000) parser.add_argument("-c", "--certpath", help=f"cert subdir relative to {DATA_DIR}", default="certs") parser.add_argument("-s", "--nossl", help="do NOT use ssl", action='store_true', default=False) + parser.add_argument("-v", "--verbose", help="dump more raw info", action='store_true', default=False) args = parser.parse_args()
+ logging.basicConfig(level=logging.DEBUG if args.verbose else logging.WARNING) + common_cert_path = os.path.join(DATA_DIR, args.certpath) hs = SmDppHttpServer(server_hostname=HOSTNAME, ci_certs_path=os.path.join(common_cert_path, 'CertificateIssuer'), common_cert_path=common_cert_path, use_brainpool=False) if(args.nossl): diff --git a/pySim/esim/bsp.py b/pySim/esim/bsp.py index fb4c0b3..6935802 100644 --- a/pySim/esim/bsp.py +++ b/pySim/esim/bsp.py @@ -149,8 +149,18 @@ temp_data = self.mac_chain + tag_and_length + data old_mcv = self.mac_chain c_mac = self._auth(temp_data) + + # DEBUG: Show MAC computation details + logger.debug(f"MAC_DEBUG: tag=0x{tag:02x}, lcc={lcc}") + logger.debug(f"MAC_DEBUG: tag_and_length: {tag_and_length.hex()}") + logger.debug(f"MAC_DEBUG: mac_chain[:20]: {old_mcv[:20].hex()}") + logger.debug(f"MAC_DEBUG: temp_data[:20]: {temp_data[:20].hex()}") + logger.debug(f"MAC_DEBUG: c_mac: {c_mac.hex()}") + # The output data is computed by concatenating the following data: the tag, the final length, the result of step 2 and the C-MAC value. ret = tag_and_length + data + c_mac + logger.debug(f"MAC_DEBUG: final_output[:20]: {ret[:20].hex()}") + logger.debug("auth(tag=0x%x, mcv=%s, s_mac=%s, plaintext=%s, temp=%s) -> %s", tag, b2h(old_mcv), b2h(self.s_mac), b2h(data), b2h(temp_data), b2h(ret)) return ret @@ -204,6 +214,11 @@ s_enc = out[l:2*l] s_mac = out[l*2:3*l]
+ logger.debug(f"BSP_KDF_DEBUG: kdf_out = {b2h(out)}") + logger.debug(f"BSP_KDF_DEBUG: initial_mcv = {b2h(initial_mac_chaining_value)}") + logger.debug(f"BSP_KDF_DEBUG: s_enc = {b2h(s_enc)}") + logger.debug(f"BSP_KDF_DEBUG: s_mac = {b2h(s_mac)}") + return s_enc, s_mac, initial_mac_chaining_value
@@ -231,9 +246,21 @@ """Encrypt + MAC a single plaintext TLV. Returns the protected ciphertext.""" assert tag <= 255 assert len(plaintext) <= self.max_payload_size + + # DEBUG: Show what we're processing + logger.debug(f"BSP_DEBUG: encrypt_and_mac_one(tag=0x{tag:02x}, plaintext_len={len(plaintext)})") + logger.debug(f"BSP_DEBUG: plaintext[:20]: {plaintext[:20].hex()}") + logger.debug(f"BSP_DEBUG: s_enc[:20]: {self.c_algo.s_enc[:20].hex()}") + logger.debug(f"BSP_DEBUG: s_mac[:20]: {self.m_algo.s_mac[:20].hex()}") + logger.debug("encrypt_and_mac_one(tag=0x%x, plaintext=%s)", tag, b2h(plaintext)) ciphered = self.c_algo.encrypt(plaintext) + logger.debug(f"BSP_DEBUG: ciphered[:20]: {ciphered[:20].hex()}") + maced = self.m_algo.auth(tag, ciphered) + logger.debug(f"BSP_DEBUG: final_result[:20]: {maced[:20].hex()}") + logger.debug(f"BSP_DEBUG: final_result_len: {len(maced)}") + return maced
def encrypt_and_mac(self, tag: int, plaintext:bytes) -> List[bytes]: diff --git a/pySim/esim/es8p.py b/pySim/esim/es8p.py index 8bd7e14..4c854f1 100644 --- a/pySim/esim/es8p.py +++ b/pySim/esim/es8p.py @@ -25,6 +25,9 @@ from pySim.esim.bsp import BspInstance from pySim.esim import PMO
+import logging +logger = logging.getLogger(__name__) + # 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. @@ -196,8 +199,12 @@ # 'initialiseSecureChannelRequest' bpp_seq = rsp.asn1.encode('InitialiseSecureChannelRequest', iscr) # firstSequenceOf87 + logger.debug(f"BPP_ENCODE_DEBUG: Encrypting ConfigureISDP with BSP keys") + logger.debug(f"BPP_ENCODE_DEBUG: BSP S-ENC: {bsp.c_algo.s_enc.hex()}") + logger.debug(f"BPP_ENCODE_DEBUG: BSP S-MAC: {bsp.m_algo.s_mac.hex()}") bpp_seq += encode_seq(0xa0, bsp.encrypt_and_mac(0x87, conf_idsp_bin)) # sequenceOF88 + logger.debug(f"BPP_ENCODE_DEBUG: MAC-only StoreMetadata with BSP keys") bpp_seq += encode_seq(0xa1, bsp.mac_only(0x88, smr_bin))
if self.ppp: # we have to use session keys