falconia has posted comments on this change. ( https://gerrit.osmocom.org/c/libosmocore/+/36967?usp=email )
Change subject: gsm48_ie: add helper function for speech bearer cap on GSM MS side
......................................................................
Patch Set 1:
(1 comment)
Patchset:
PS1:
@laforge@osmocom.org wrote:
> I'm not entirely sure if this should go into the library or into osmocom-bb, though.
If osmocom-bb devs (of which I am obviously not one) feel that this code should go there, please feel free to lift the code from this patch and adapt as you see fit. I can't be the patch owner on anything going into osmocom-bb repo (outside of rare exceptions of which this isn't one), but please feel free to reuse the code itself as you like.
The only reason I produced this patch is because it would have been improper to argue against the other patch (by @degrunert.web@googlemail.com) without offering an alternative - but it is absolutely **not** my place to argue or even suggest what osmocom-bb should or should not do.
As food for thought though, whoever takes this issue up in osmocom-bb will have to decide how to handle the "policy" aspect of it, i.e., selecting between spec-correct behavior vs sending intentionally invalid stuff like in that Russian MNO experiment that brought this whole issue into focus.
--
To view, visit https://gerrit.osmocom.org/c/libosmocore/+/36967?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: libosmocore
Gerrit-Branch: master
Gerrit-Change-Id: Iaf41687da1d377e98f26e6a16d991ab7d95be0fc
Gerrit-Change-Number: 36967
Gerrit-PatchSet: 1
Gerrit-Owner: falconia <falcon(a)freecalypso.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Comment-Date: Fri, 31 May 2024 23:59:16 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Gerrit-MessageType: comment
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36955?usp=email )
Change subject: osmo-smdpp: Make error message more descriptive
......................................................................
osmo-smdpp: Make error message more descriptive
Before this patch we had three different error causes that would cause a
"Verification failed" error message. Let's state explicitly which part
of verification did actually fail.
Change-Id: I5030758fe365bb802ae367b494aace5a66bc7a91
---
M osmo-smdpp.py
1 file changed, 16 insertions(+), 3 deletions(-)
Approvals:
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index 9ed1e39..d7fc872 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -325,14 +325,14 @@
try:
cs.verify_cert_chain(euicc_cert)
except VerifyError:
- raise ApiError('8.1.3', '6.1', 'Verification failed')
+ raise ApiError('8.1.3', '6.1', 'Verification failed (certificate chain)')
# 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')
+ raise ApiError('8.1', '6.1', 'Verification failed (euiccSignature1 over euiccSigned1)')
# TODO: verify EID of eUICC cert is within permitted range of EUM cert
@@ -343,7 +343,7 @@
# 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')
+ raise ApiError('8.1', '6.1', 'Verification failed (serverChallenge)')
# If ctxParams1 contains a ctxParamsForCommonAuthentication data object, the SM-DP+ Shall [...]
# TODO: We really do a very simplistic job here, this needs to be properly implemented later,
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36955?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: I5030758fe365bb802ae367b494aace5a66bc7a91
Gerrit-Change-Number: 36955
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36954?usp=email )
Change subject: osmo-smdpp: Don't re-encode euiccSigned1/euiccSigned2
......................................................................
osmo-smdpp: Don't re-encode euiccSigned1/euiccSigned2
We used to re-encode those parts of a decoded ASN.1 struct that is
cryptographically signed in the GSMA SGP.22 specification. However, if
the received data follows a later spec and contains new/unknown records,
then our poor-man's attempt at re-encoding will render a different
binary, which in turn means the signature check will fail.
Let's instead do a manual step-by-step raw decode of the DER TLV
structure to extract the actual binary information of parts of ASN.1
objects.
Change-Id: I4e31fd4b23ec3be15b9d07c2c30a3e31e22bdda1
Closes: OS#6473
---
M osmo-smdpp.py
M pySim/esim/rsp.py
2 files changed, 61 insertions(+), 4 deletions(-)
Approvals:
Jenkins Builder: Verified
laforge: Looks good to me, approved
diff --git a/osmo-smdpp.py b/osmo-smdpp.py
index 3dc6131..9ed1e39 100755
--- a/osmo-smdpp.py
+++ b/osmo-smdpp.py
@@ -292,8 +292,7 @@
r_ok = authenticateServerResp[1]
euiccSigned1 = r_ok['euiccSigned1']
- # TODO: use original data, don't re-encode?
- euiccSigned1_bin = rsp.asn1.encode('EuiccSigned1', euiccSigned1)
+ euiccSigned1_bin = rsp.extract_euiccSigned1(authenticateServerResp_bin)
euiccSignature1_bin = r_ok['euiccSignature1']
euiccCertificate_dec = r_ok['euiccCertificate']
# TODO: use original data, don't re-encode?
@@ -422,8 +421,7 @@
# 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)
+ euiccSigned2_bin = rsp.extract_euiccSigned2(prepDownloadResp_bin)
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')
diff --git a/pySim/esim/rsp.py b/pySim/esim/rsp.py
index ec317fc..a032031 100644
--- a/pySim/esim/rsp.py
+++ b/pySim/esim/rsp.py
@@ -24,6 +24,7 @@
from cryptography.hazmat.primitives.serialization import Encoding
from cryptography import x509
+from pySim.utils import bertlv_parse_one, bertlv_encode_tag, bertlv_encode_len, b2h
from pySim.esim import compile_asn1_subdir
asn1 = compile_asn1_subdir('rsp')
@@ -96,3 +97,41 @@
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."""
+
+def extract_euiccSigned1(authenticateServerResponse: bytes) -> bytes:
+ """Extract the raw, DER-encoded binary euiccSigned1 field from the given AuthenticateServerResponse. This
+ is needed due to the very peculiar SGP.22 notion of signing sections of DER-encoded ASN.1 objects."""
+ tdict, l, v, remainder = bertlv_parse_one(authenticateServerResponse)
+ rawtag = bertlv_encode_tag(tdict)
+ if len(remainder):
+ raise ValueError('Excess data at end of TLV')
+ if b2h(rawtag) != 'bf38':
+ raise ValueError('Unexpected outer tag: %s' % b2h(rawtag))
+ tdict, l, v1, remainder = bertlv_parse_one(v)
+ rawtag = bertlv_encode_tag(tdict)
+ if b2h(rawtag) != 'a0':
+ raise ValueError('Unexpected tag where CHOICE was expected')
+ tdict, l, v2, remainder = bertlv_parse_one(v1)
+ rawtag = bertlv_encode_tag(tdict)
+ if b2h(rawtag) != '30':
+ raise ValueError('Unexpected tag where SEQUENCE was expected')
+ return rawtag + bertlv_encode_len(l) + v2
+
+def extract_euiccSigned2(prepareDownloadResponse: bytes) -> bytes:
+ """Extract the raw, DER-encoded binary euiccSigned2 field from the given prepareDownloadrResponse. This is
+ needed due to the very peculiar SGP.22 notion of signing sections of DER-encoded ASN.1 objects."""
+ tdict, l, v, remainder = bertlv_parse_one(prepareDownloadResponse)
+ rawtag = bertlv_encode_tag(tdict)
+ if len(remainder):
+ raise ValueError('Excess data at end of TLV')
+ if b2h(rawtag) != 'bf21':
+ raise ValueError('Unexpected outer tag: %s' % b2h(rawtag))
+ tdict, l, v1, remainder = bertlv_parse_one(v)
+ rawtag = bertlv_encode_tag(tdict)
+ if b2h(rawtag) != 'a0':
+ raise ValueError('Unexpected tag where CHOICE was expected')
+ tdict, l, v2, remainder = bertlv_parse_one(v1)
+ rawtag = bertlv_encode_tag(tdict)
+ if b2h(rawtag) != '30':
+ raise ValueError('Unexpected tag where SEQUENCE was expected')
+ return rawtag + bertlv_encode_len(l) + v2
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36954?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: I4e31fd4b23ec3be15b9d07c2c30a3e31e22bdda1
Gerrit-Change-Number: 36954
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36956?usp=email )
Change subject: add globalplatform.uicc
......................................................................
add globalplatform.uicc
GlobalPlatform has a [non-public] "UICC Configuration" spec, which
defines some specific aspects of implementing GlobalPlatform in the
context of an UICC. Let's add some python definitions about it.
Change-Id: If4cb110a9bc5f873b0e097c006bef59264ee48fa
---
A pySim/global_platform/uicc.py
1 file changed, 120 insertions(+), 0 deletions(-)
Approvals:
Jenkins Builder: Verified
laforge: Looks good to me, approved
diff --git a/pySim/global_platform/uicc.py b/pySim/global_platform/uicc.py
new file mode 100644
index 0000000..2cf5e96
--- /dev/null
+++ b/pySim/global_platform/uicc.py
@@ -0,0 +1,107 @@
+# coding=utf-8
+"""GlobalPLatform UICC Configuration 1.0 parameters
+
+(C) 2024 by Harald Welte <laforge(a)osmocom.org>
+
+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 <http://www.gnu.org/licenses/>.
+"""
+
+from construct import Optional as COptional
+from construct import Struct, GreedyRange, FlagsEnum, Int16ub, Int24ub, Padding, Bit, Const
+from pySim.construct import *
+from pySim.utils import *
+from pySim.tlv import *
+
+# Section 11.6.2.3 / Table 11-58
+class SecurityDomainAid(BER_TLV_IE, tag=0x4f):
+ _construct = GreedyBytes
+class LoadFileDataBlockSignature(BER_TLV_IE, tag=0xc3):
+ _construct = GreedyBytes
+class DapBlock(BER_TLV_IE, tag=0xe2, nested=[SecurityDomainAid, LoadFileDataBlockSignature]):
+ pass
+class LoadFileDataBlock(BER_TLV_IE, tag=0xc4):
+ _construct = GreedyBytes
+class Icv(BER_TLV_IE, tag=0xd3):
+ _construct = GreedyBytes
+class CipheredLoadFileDataBlock(BER_TLV_IE, tag=0xd4):
+ _construct = GreedyBytes
+class LoadFile(TLV_IE_Collection, nested=[DapBlock, LoadFileDataBlock, Icv, CipheredLoadFileDataBlock]):
+ pass
+
+# UICC Configuration v1.0.1 / Section 4.3.2
+class UiccScp(BER_TLV_IE, tag=0x81):
+ _construct = Struct('scp'/Int8ub, 'i'/Int8ub)
+
+class AcceptExtradAppsAndElfToSd(BER_TLV_IE, tag=0x82):
+ _construct = GreedyBytes
+
+class AcceptDelOfAssocSd(BER_TLV_IE, tag=0x83):
+ _construct = GreedyBytes
+
+class LifeCycleTransitionToPersonalized(BER_TLV_IE, tag=0x84):
+ _construct = GreedyBytes
+
+class CasdCapabilityInformation(BER_TLV_IE, tag=0x86):
+ _construct = GreedyBytes
+
+class AcceptExtradAssocAppsAndElf(BER_TLV_IE, tag=0x87):
+ _construct = GreedyBytes
+
+# Security Domain Install Parameters (inside C9 during INSTALL [for install])
+class UiccSdInstallParams(TLV_IE_Collection, nested=[UiccScp, AcceptExtradAppsAndElfToSd, AcceptDelOfAssocSd,
+ LifeCycleTransitionToPersonalized,
+ CasdCapabilityInformation, AcceptExtradAssocAppsAndElf]):
+ def has_scp(self, scp: int) -> bool:
+ """Determine if SD Installation parameters already specify given SCP."""
+ for c in self.children:
+ if not isinstance(c, UiccScp):
+ continue
+ if c.decoded['scp'] == scp:
+ return True
+ return False
+
+ def add_scp(self, scp: int, i: int):
+ """Add given SCP (and i parameter) to list of SCP of the Security Domain Install Params.
+ Example: add_scp(0x03, 0x70) for SCP03, or add_scp(0x02, 0x55) for SCP02."""
+ if self.has_scp(scp):
+ raise ValueError('SCP%02x already present' % scp)
+ self.children.append(UiccScp(decoded={'scp': scp, 'i': i}))
+
+ def remove_scp(self, scp: int):
+ """Remove given SCP from list of SCP of the Security Domain Install Params."""
+ for c in self.children:
+ if not isinstance(c, UiccScp):
+ continue
+ if c.decoded['scp'] == scp:
+ self.children.remove(c)
+ return
+ raise ValueError("SCP%02x not present" % scp)
+
+
+# Key Usage:
+# KVN 0x01 .. 0x0F reserved for SCP80
+# KVN 0x11 reserved for DAP specified in ETSI TS 102 226
+# KVN 0x20 .. 0x2F reserved for SCP02
+# KID 0x01 = ENC; 0x02 = MAC; 0x03 = DEK
+# KVN 0x30 .. 0x3F reserved for SCP03
+# KID 0x01 = ENC; 0x02 = MAC; 0x03 = DEK
+# KVN 0x70 KID 0x01: Token key (RSA public or DES)
+# KVN 0x71 KID 0x01: Receipt key (DES)
+# KVN 0x73 KID 0x01: DAP verifiation key (RS public or DES)
+# KVN 0x74 reserved for CASD
+# KID 0x01: PK.CA.AUT
+# KID 0x02: SK.CASD.AUT (PK) and KS.CASD.AUT (Non-PK)
+# KID 0x03: SK.CASD.CT (P) and KS.CASD.CT (Non-PK)
+# KVN 0x75 KID 0x01: 16-byte DES key for Ciphered Load File Data Block
+# KVN 0xFF reserved for ISD with SCP02 without SCP80 s upport
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36956?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: If4cb110a9bc5f873b0e097c006bef59264ee48fa
Gerrit-Change-Number: 36956
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: merged