Hoernchen has uploaded a new patch set (#2). ( https://gerrit.osmocom.org/c/pysim/+/43200?usp=email )
Change subject: GP: fix kcb for non block aligned keys
......................................................................
GP: fix kcb for non block aligned keys
how encrypt_key() pads a kcv:
len(key) % blocksize bytes
what it should do to actually do it right:
blocksize - len(key) % blocksize
so the plaintext handed to the cipher was only block aligned by luck as
long as the key length happened to be a multiple of half the block size.
And of course decrypt_key() did not invert encrypt_key() at all,
the clear text length of GP CardSpec v2.3 Table 11-70 precedes the
ENCRYPTED kcv, but it was parsed out of the DECRYPTED data, and the
length byte itself was fed to the cipher along with the cryptogram.
Fix this up with a helper and tests so it is actually usable.
Change-Id: I02b4f2ed948c31e1741e40f0226fb49757fa2570
---
M pySim/global_platform/scp.py
M tests/unittests/test_globalplatform.py
2 files changed, 48 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/00/43200/2
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43200?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I02b4f2ed948c31e1741e40f0226fb49757fa2570
Gerrit-Change-Number: 43200
Gerrit-PatchSet: 2
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-CC: Jenkins Builder
Attention is currently required from: dexter, laforge.
Hoernchen has posted comments on this change by Hoernchen. ( https://gerrit.osmocom.org/c/pysim/+/43172?usp=email )
Change subject: GP: LOAD/STORE DATA chunk size from SCP overhead
......................................................................
Set Ready For Review
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43172?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: comment
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Ic208f3959a38896f64fb6ccefb24cc360a3ac3a2
Gerrit-Change-Number: 43172
Gerrit-PatchSet: 3
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Attention: laforge <laforge(a)osmocom.org>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
Gerrit-Comment-Date: Mon, 10 Aug 2026 18:44:58 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: No
Hoernchen has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/43200?usp=email )
Change subject: GP: fix kcb for non block aligned keys
......................................................................
GP: fix kcb for non block aligned keys
how encrypt_key() pads a kcv:
len(key) % blocksize bytes
what it should do to actually do it right:
blocksize - len(key) % blocksize
so the plaintext handed to the cipher was only block aligned by luck as
long as the key length happened to be a multiple of half the block size.
And of course decrypt_key() did not invert encrypt_key() at all,
the clear text length of Table 11-70 precedes the ENCRYPTED kcv,
but it was parsed out of the DECRYPTED data, and the length byte itself
was fed to the cipher along with the cryptogram.
Fix this up with a helper and tests so it is actually usable.
Change-Id: I02b4f2ed948c31e1741e40f0226fb49757fa2570
---
M pySim/global_platform/scp.py
M tests/unittests/test_globalplatform.py
2 files changed, 48 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/00/43200/1
diff --git a/pySim/global_platform/scp.py b/pySim/global_platform/scp.py
index a5fcf51..a50b17e 100644
--- a/pySim/global_platform/scp.py
+++ b/pySim/global_platform/scp.py
@@ -215,11 +215,19 @@
def gen_ext_auth_apdu(self, security_level: int = 0x01) -> bytes:
pass
+ def pad_to_blocksize(self, data: bytes) -> bytes:
+ """Right pad the data with zero bytes to a multiple of the DEK cipher block size."""
+ if len(data) % self.sk.blocksize:
+ data += b'\x00' * (self.sk.blocksize - len(data) % self.sk.blocksize)
+ return data
+
def encrypt_key(self, key: bytes) -> bytes:
"""Encrypt a key with the DEK."""
- num_pad = len(key) % self.sk.blocksize
- if num_pad:
- return bertlv_encode_len(len(key)) + self.dek_encrypt(key + b'\x00'*num_pad)
+ if len(key) % self.sk.blocksize:
+ # The kcv is right padded before encryption and the kcb
+ # is formatted as described in Table 11-70: preceded by the actual length of the
+ # clear text kcv.
+ return bertlv_encode_len(len(key)) + self.dek_encrypt(self.pad_to_blocksize(key))
return self.dek_encrypt(key)
def decrypt_key(self, encrypted_key:bytes) -> bytes:
@@ -232,9 +240,8 @@
# Block provides the actual length of the key component value, which allows recovering the
# clear-text key component value after decryption of the encrypted key component value and removal
# of padding bytes.
- decrypted = self.dek_decrypt(encrypted_key)
- key_len, remainder = bertlv_parse_len(decrypted)
- return remainder[:key_len]
+ key_len, remainder = bertlv_parse_len(encrypted_key)
+ return self.dek_decrypt(remainder)[:key_len]
else:
# If the length of the Key Component Block is a multiple of the block size of the encryption
# algorithm (i.e. 8 bytes for DES, 16 bytes for AES), then it shall be assumed that no padding
diff --git a/tests/unittests/test_globalplatform.py b/tests/unittests/test_globalplatform.py
index 8698470..576407d 100644
--- a/tests/unittests/test_globalplatform.py
+++ b/tests/unittests/test_globalplatform.py
@@ -283,6 +283,41 @@
# FIXME: test auth with random (0x60) vs pseudo-random (0x70) challenge
+class KeyComponentBlock_Test(unittest.TestCase):
+ """Tests for the kcb of GP CardSpec v2.3
+ - Table 11-70 kcv that required padding, preceded by its clear-text length
+ - Table 11-71 no padding required"""
+
+ def setUp(self):
+ # SCP02 (3DES DEK, 8 byte blocks), same vectors as SCP02_Test
+ self.scp02 = SCP02(card_keys=ck_3des_70)
+ self.scp02.gen_init_update_apdu(host_challenge=h2b('40A62C37FA6304F8'))
+ self.scp02.parse_init_update_resp(h2b('00000000000000000000700200016B4524ABEE7CF32EA3838BC148F3'))
+ self.scp02.gen_ext_auth_apdu()
+ # SCP03 (AES DEK, 16 byte blocks), same vectors as SCP03_Test_AES128_11
+ self.scp03 = SCP03(card_keys=KEYSET_AES128)
+ self.scp03.gen_init_update_apdu(h2b('b13e5f938fc108c4'))
+ self.scp03.parse_init_update_resp(h2b('000000000000000000003003703eb51047495b249f66c484c1d2ef1948000002'))
+ self.scp03.gen_ext_auth_apdu(0x11)
+
+ def test_encrypt_decrypt_key(self):
+ for scp in (self.scp02, self.scp03):
+ bs = scp.sk.blocksize
+ for keylen in range(1, 3 * bs + 1):
+ with self.subTest(scp=type(scp).__name__, keylen=keylen):
+ key = bytes(range(keylen))
+ kcb = scp.encrypt_key(key)
+ if keylen % bs:
+ # Table 11-70: <length of clear key component> || <encrypted padded value>
+ self.assertEqual(kcb[0], keylen)
+ self.assertEqual((len(kcb) - 1) % bs, 0)
+ self.assertEqual(len(kcb) - 1, keylen + (bs - keylen % bs))
+ else:
+ # Table 11-71: only the encrypted key component value
+ self.assertEqual(len(kcb), keylen)
+ self.assertEqual(scp.decrypt_key(kcb), key)
+
+
class SCP03_KCV_Test(unittest.TestCase):
def test_kcv(self):
self.assertEqual(compute_kcv('aes', KEYSET_AES128.enc), h2b('C35280'))
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/43200?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I02b4f2ed948c31e1741e40f0226fb49757fa2570
Gerrit-Change-Number: 43200
Gerrit-PatchSet: 1
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/simtrace2/+/43129?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: firmware: sniffer: fix ~INS procedure byte comparison
......................................................................
firmware: sniffer: fix ~INS procedure byte comparison
(~g_tpdu.packet[1]) == byte can never be true.
Unary ~ applies the integer promotions first,
so for tpdu INS = 0xA4 lhs should be 0x5B but as int
it gets zero extended to at least 16 bits and then flipped,
so it is 0xFFFFFF5B = -165, byte promotes to 0..255.
The ack was therefore dead code -> fallthrough to SW1
branch, fails 0x6x/0x9x test, TPDU gets flagged
SNIFF_DATA_FLAG_ERROR_MALFORMED from what I can tell.
But I am losing track of all these arcane issues to be honest.
Narrow the complement back to 8 bits.
Fyi this is unrelated to signedness and not specific to ARM.
Change-Id: I800f50ef35356429d07aa685ea919e70ec34946e
---
M firmware/libcommon/source/sniffer.c
1 file changed, 1 insertion(+), 1 deletion(-)
Approvals:
Jenkins Builder: Verified
laforge: Looks good to me, but someone else must approve
lynxis lazus: Looks good to me, approved
diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c
index 948eee8..419e8fb 100644
--- a/firmware/libcommon/source/sniffer.c
+++ b/firmware/libcommon/source/sniffer.c
@@ -775,7 +775,7 @@
} else if (g_tpdu.packet[1] == byte) { /* get all remaining data bytes */
change_tpdu_state(TPDU_S_DATA_REMAINING);
break;
- } else if ((~g_tpdu.packet[1]) == byte) { /* get single data byte */
+ } else if ((uint8_t)(~g_tpdu.packet[1]) == byte) { /* get single data byte */
change_tpdu_state(TPDU_S_DATA_SINGLE);
break;
}
--
To view, visit https://gerrit.osmocom.org/c/simtrace2/+/43129?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-Change-Id: I800f50ef35356429d07aa685ea919e70ec34946e
Gerrit-Change-Number: 43129
Gerrit-PatchSet: 3
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>
lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/simtrace2/+/43130?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: firmware: sniffer: do not drop maximum-length ATRs
......................................................................
firmware: sniffer: do not drop maximum-length ATRs
7816-3 8.1/8.2.1 allow TS plus 32 bytes.
atr_i is a byte count, not an index, process_byte_atr() guards its own
store with the same condition before incrementing, so atr_i reaches 33.
Change-Id: Ic8398cbefc0b522946b6470fd0268fa70662dab1
---
M firmware/libcommon/source/sniffer.c
1 file changed, 1 insertion(+), 1 deletion(-)
Approvals:
laforge: Looks good to me, but someone else must approve
Jenkins Builder: Verified
lynxis lazus: Looks good to me, approved
diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c
index 419e8fb..98cc6cd 100644
--- a/firmware/libcommon/source/sniffer.c
+++ b/firmware/libcommon/source/sniffer.c
@@ -406,7 +406,7 @@
TRACE_WARNING("Can't print ATR in ISO 7816-3 state %u\n\r", iso_state);
return;
}
- if (g_atr.atr_i >= ARRAY_SIZE(g_atr.atr)) {
+ if (g_atr.atr_i > ARRAY_SIZE(g_atr.atr)) {
TRACE_ERROR("ATR buffer overflow\n\r");
return;
}
--
To view, visit https://gerrit.osmocom.org/c/simtrace2/+/43130?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-Change-Id: Ic8398cbefc0b522946b6470fd0268fa70662dab1
Gerrit-Change-Number: 43130
Gerrit-PatchSet: 3
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>
lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/simtrace2/+/43131?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: firmware: sniffer: honor the ep argument of usb_msg_alloc_hdr()
......................................................................
firmware: sniffer: honor the ep argument of usb_msg_alloc_hdr()
Even though all callers pass the same endpoint anyway the arg should
be used and not discarded.
Change-Id: I1fa0097b9eef531900b359c7293a6c60040254e4
---
M firmware/libcommon/source/sniffer.c
1 file changed, 2 insertions(+), 2 deletions(-)
Approvals:
laforge: Looks good to me, but someone else must approve
lynxis lazus: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/firmware/libcommon/source/sniffer.c b/firmware/libcommon/source/sniffer.c
index 98cc6cd..93a66b2 100644
--- a/firmware/libcommon/source/sniffer.c
+++ b/firmware/libcommon/source/sniffer.c
@@ -239,14 +239,14 @@
static struct msgb *usb_msg_alloc_hdr(uint8_t ep, uint8_t msg_class, uint8_t msg_type)
{
/* Only allocate message if not too many are already in the queue */
- struct llist_head *head = usb_get_queue(SIMTRACE_USB_EP_CARD_DATAIN);
+ struct llist_head *head = usb_get_queue(ep);
if (!head) {
return NULL;
}
if (llist_count(head) > 5) {
return NULL;
}
- struct msgb *usb_msg = usb_buf_alloc(SIMTRACE_USB_EP_CARD_DATAIN);
+ struct msgb *usb_msg = usb_buf_alloc(ep);
if (!usb_msg) {
return NULL;
}
--
To view, visit https://gerrit.osmocom.org/c/simtrace2/+/43131?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-Change-Id: I1fa0097b9eef531900b359c7293a6c60040254e4
Gerrit-Change-Number: 43131
Gerrit-PatchSet: 3
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>
lynxis lazus has submitted this change. ( https://gerrit.osmocom.org/c/simtrace2/+/43133?usp=email )
(
1 is the latest approved patch-set.
No files were changed between the latest approved patch-set and the submitted one.
)Change subject: host: simtrace2_api: do not log random memory
......................................................................
host: simtrace2_api: do not log random memory
tx_cfg->features is logged before the memcpy() that fills it.
Looks like no one is using config.ac --enable-sanitize?
Change-Id: Id8369d312c8600ba9eea80c8f7782f196d7e20d1
---
M host/lib/simtrace2_api.c
1 file changed, 1 insertion(+), 1 deletion(-)
Approvals:
lynxis lazus: Looks good to me, approved
Jenkins Builder: Verified
laforge: Looks good to me, but someone else must approve
diff --git a/host/lib/simtrace2_api.c b/host/lib/simtrace2_api.c
index 37be08a..e2bad31 100644
--- a/host/lib/simtrace2_api.c
+++ b/host/lib/simtrace2_api.c
@@ -280,7 +280,7 @@
tx_cfg = (struct cardemu_usb_msg_config *) msgb_put(msg, sizeof(*tx_cfg));
- LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(features=%08x)\n", __func__, tx_cfg->features);
+ LOGSLOT(ci->slot, LOGL_NOTICE, "<= %s(features=%08x)\n", __func__, user_cfg->features);
memcpy(tx_cfg, user_cfg, sizeof(*tx_cfg));
osmo_store32le(user_cfg->features, &tx_cfg->features);
--
To view, visit https://gerrit.osmocom.org/c/simtrace2/+/43133?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: merged
Gerrit-Project: simtrace2
Gerrit-Branch: master
Gerrit-Change-Id: Id8369d312c8600ba9eea80c8f7782f196d7e20d1
Gerrit-Change-Number: 43133
Gerrit-PatchSet: 3
Gerrit-Owner: Hoernchen <ewild(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>