dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39194?usp=email )
Change subject: javacard, cosmetic: fix sourcecode fromatting and improve docstring
......................................................................
javacard, cosmetic: fix sourcecode fromatting and improve docstring
The line with TAGS is longer than 120 columns and there is some
comment that should be moved to the python docstring.
Related: OS#6679
Change-Id: I1d02098320cfbe17a0eb1bfdcf3bc85034cc8e20
---
M pySim/javacard.py
1 file changed, 7 insertions(+), 5 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/94/39194/1
diff --git a/pySim/javacard.py b/pySim/javacard.py
index 46f6ec0..07b0f39 100644
--- a/pySim/javacard.py
+++ b/pySim/javacard.py
@@ -6,14 +6,16 @@
import io
def ijc_to_cap(in_file: io.IOBase, out_zip: zipfile.ZipFile, p : str = "foo"):
- """Convert an ICJ (Interoperable Java Card) file [back] to a CAP file."""
- TAGS = ["Header", "Directory", "Applet", "Import", "ConstantPool", "Class", "Method", "StaticField", "RefLocation", "Export", "Descriptor", "Debug"]
+ """Convert an ICJ (Interoperable Java Card) file [back] to a CAP file.
+ example usage:
+ with io.open(sys.argv[1],"rb") as f, zipfile.ZipFile(sys.argv[2], "wb") as z:
+ ijc_to_cap(f, z)
+ """
+ TAGS = ["Header", "Directory", "Applet", "Import", "ConstantPool", "Class", "Method", "StaticField", "RefLocation",
+ "Export", "Descriptor", "Debug"]
b = in_file.read()
while len(b):
tag, size = struct.unpack('!BH', b[0:3])
out_zip.writestr(p+"/javacard/"+TAGS[tag-1]+".cap", b[0:3+size])
b = b[3+size:]
-# example usage:
-# with io.open(sys.argv[1],"rb") as f, zipfile.ZipFile(sys.argv[2], "wb") as z:
-# ijc_to_cap(f, z)
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/39194?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: I1d02098320cfbe17a0eb1bfdcf3bc85034cc8e20
Gerrit-Change-Number: 39194
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
dexter has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/39198?usp=email )
Change subject: javacard: add parser for JAVA-card CAP file format
......................................................................
javacard: add parser for JAVA-card CAP file format
To install JAVA-card applets we need to be able to extract the executeable
loadfile and the AIDs of the applet and the loadfile. This patch adds the
parser and related unittests.
Related: OS#6679
Change-Id: I581483ccb9d8a254fcecc995fec3c811c5cf38eb
---
M pySim/javacard.py
A tests/unittests/test_javacard.cap
A tests/unittests/test_javacard.py
3 files changed, 173 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/98/39198/1
diff --git a/pySim/javacard.py b/pySim/javacard.py
index 07b0f39..c304999 100644
--- a/pySim/javacard.py
+++ b/pySim/javacard.py
@@ -1,9 +1,30 @@
# JavaCard related utilities
-
+#
+# (C) 2024 by Sysmocom s.f.m.c. GmbH
+# All Rights Reserved
+#
+# 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/>.
+#
import zipfile
import struct
import sys
import io
+from osmocom.utils import b2h
+from construct import Struct, Array, this, Int32ub, Int16ub, Int8ub
+from osmocom.construct import *
+from osmocom.tlv import *
+from construct import Optional as COptional
def ijc_to_cap(in_file: io.IOBase, out_zip: zipfile.ZipFile, p : str = "foo"):
"""Convert an ICJ (Interoperable Java Card) file [back] to a CAP file.
@@ -19,3 +40,136 @@
out_zip.writestr(p+"/javacard/"+TAGS[tag-1]+".cap", b[0:3+size])
b = b[3+size:]
+class CapFile():
+
+ #TODO: At the moment we only support the compact .cap format, add support for the extended .cap format.
+
+ __component_header = None
+ __component_directory = None
+ __component_applet = None #optional
+ __component_import = None
+ __component_constantPool = None
+ __component_class = None
+ __component_method = None
+ __component_staticField = None
+ __component_referenceLocation = None
+ __component_export = None #optional
+ __component_descriptor = None
+ __component_debug = None #optional, since CAP format 2.2
+
+ # Java Card Platform Virtual Machine Specification, v3.2, section 6.4
+ __header_component_compact = Struct('tag'/Int8ub,
+ 'size'/Int16ub,
+ 'magic'/Int32ub,
+ 'minor_version'/Int8ub,
+ 'major_version'/Int8ub,
+ 'flags'/Int8ub,
+ 'package'/Struct('minor_version'/Int8ub,
+ 'major_version'/Int8ub,
+ 'AID'/LV),
+ 'package_name'/COptional(LV)) #since CAP format 2.2
+
+ # Java Card Platform Virtual Machine Specification, v3.2, section 6.6
+ __applet_component_compact = Struct('tag'/Int8ub,
+ 'size'/Int16ub,
+ 'count'/Int8ub,
+ 'applets'/Array(this.count, Struct('AID'/LV,
+ 'install_method_offset'/Int16ub)),
+ )
+
+ def __init__(self, filename:str):
+ # Extract the nested .cap components from the .cap file
+ # See also: Java Card Platform Virtual Machine Specification, v3.2, section 6.2.1
+ cap = zipfile.ZipFile(filename)
+ cap_namelist = cap.namelist()
+ for i, filename in enumerate(cap_namelist):
+ if filename.lower().endswith('header.cap'):
+ self.__component_header = cap.read(filename)
+ elif filename.lower().endswith('directory.cap'):
+ self.__component_directory = cap.read(filename)
+ elif filename.lower().endswith('applet.cap'):
+ self.__component_applet = cap.read(filename)
+ elif filename.lower().endswith('import.cap'):
+ self.__component_import = cap.read(filename)
+ elif filename.lower().endswith('constantpool.cap'):
+ self.__component_constantPool = cap.read(filename)
+ elif filename.lower().endswith('class.cap'):
+ self.__component_class = cap.read(filename)
+ elif filename.lower().endswith('method.cap'):
+ self.__component_method = cap.read(filename)
+ elif filename.lower().endswith('staticfield.cap'):
+ self.__component_staticField = cap.read(filename)
+ elif filename.lower().endswith('reflocation.cap'):
+ self.__component_referenceLocation = cap.read(filename)
+ elif filename.lower().endswith('export.cap'):
+ self.__component_export = cap.read(filename)
+ elif filename.lower().endswith('descriptor.cap'):
+ self.__component_descriptor = cap.read(filename)
+ elif filename.lower().endswith('debug.cap'):
+ self.__component_debug = cap.read(filename)
+
+ # Make sure that all mandatory components are present
+ # See also: Java Card Platform Virtual Machine Specification, v3.2, section 6.2
+ if self.__component_header is None:
+ raise ValueError("invalid cap file, COMPONENT_Header missing!")
+ if self.__component_directory is None:
+ raise ValueError("invalid cap file, COMPONENT_Directory missing!")
+ if self.__component_import is None:
+ raise ValueError("invalid cap file, COMPONENT_Import missing!")
+ if self.__component_constantPool is None:
+ raise ValueError("invalid cap file, COMPONENT_ConstantPool missing!")
+ if self.__component_class is None:
+ raise ValueError("invalid cap file, COMPONENT_Class missing!")
+ if self.__component_method is None:
+ raise ValueError("invalid cap file, COMPONENT_Method missing!")
+ if self.__component_staticField is None:
+ raise ValueError("invalid cap file, COMPONENT_StaticField missing!")
+ if self.__component_referenceLocation is None:
+ raise ValueError("invalid cap file, COMPONENT_ReferenceLocation missing!")
+ if self.__component_descriptor is None:
+ raise ValueError("invalid cap file, COMPONENT_Descriptor missing!")
+
+ def get_loadfile(self):
+ """Get the executeable loadfile as hexstring"""
+ # Concatenate all cap file components in the specified order
+ # see also: Java Card Platform Virtual Machine Specification, v3.2, section 6.3
+ loadfile = self.__component_header
+ loadfile += self.__component_directory
+ loadfile += self.__component_import
+ if self.__component_applet:
+ loadfile += self.__component_applet
+ loadfile += self.__component_class
+ loadfile += self.__component_method
+ loadfile += self.__component_staticField
+ if self.__component_export:
+ loadfile += self.__component_export
+ loadfile += self.__component_constantPool
+ loadfile += self.__component_referenceLocation
+ if self.__component_descriptor:
+ loadfile += self.__component_descriptor
+ return b2h(loadfile)
+
+ def get_loadfile_aid(self):
+ """Get the loadfile AID as hexstring"""
+ header = self.__header_component_compact.parse(self.__component_header)
+ magic = header['magic'] or 0
+ if magic != 0xDECAFFED:
+ raise ValueError("invalid cap file, COMPONENT_Header lacks magic number (0x%08X!=0xDECAFFED)!" % magic)
+ #TODO: check cap version and make sure we are compatible with it
+ return header['package']['AID']
+
+ def get_applet_aid(self, index:int = 0):
+ """Get the applet AID as hexstring"""
+ #To get the module AID, we must look into COMPONENT_Applet. Unfortunately, even though this component should
+ #be present in any .cap file, it is defined as an optional component.
+ if self.__component_applet is None:
+ raise ValueError("can't get the AID, this cap file lacks the optional COMPONENT_Applet component!")
+
+ applet = self.__applet_component_compact.parse(self.__component_applet)
+
+ if index > applet['count']:
+ raise ValueError("can't get the AID for applet with index=%u, this .cap file only has %u applets!" %
+ (index, applet['count']))
+
+ return applet['applets'][index]['AID']
+
diff --git a/tests/unittests/test_javacard.cap b/tests/unittests/test_javacard.cap
new file mode 100644
index 0000000..f96ea24
--- /dev/null
+++ b/tests/unittests/test_javacard.cap
Binary files differ
diff --git a/tests/unittests/test_javacard.py b/tests/unittests/test_javacard.py
new file mode 100755
index 0000000..30d8bdd
--- /dev/null
+++ b/tests/unittests/test_javacard.py
@@ -0,0 +1,18 @@
+#!/usr/bin/env python3
+
+import os
+import unittest
+from pySim.javacard import *
+
+class TestJavacard(unittest.TestCase):
+
+ def test_CapFile(self):
+ loadfile="01000fdecaffed010204000105d07002ca4402001f000f001f000c002800420018006d00320017000000a900040002002203010004002803020107a0000000620101060210a0000000090003ffffffff8910710002000107a000000062000103000c0108d07002ca44900101002006001843800301ff0007020000002f00398002008101010881000007006d000911188c00048d00012c18197b0002037b00029210240303038b000388007a02318f00053d8c00062e1b8b00077a0120188b000860037a7a02228d00092d1d10076b101a8b000a321fae006b06188c000b7a06118d000c2c1903077b000d037b000d928b000e198b000f3b7a08003200040002000203001857656c636f6d6520746f20546f6f7243616d70203230313203000a48656c6c6f2c2053544b0000000005004200100200000006810900050000020381090b0680030001000000060000010380030103800303068108000381080c0600005306810a000500000003810a1303810a1609001700021e2d0011050306040908040507090a0a06070404040b00a901000100000300030005800281018100ff080000000028ff08000002002800020000008003ff820001002f001d0000000000090020003f000d000000000701002f0042000800000000080100390046001800000000ff020053002f0018000000000010002200240028002a002fffff002f002f003100330022002f00370028003b002201300568109001b008b44323430110012005681080056810a00633b44104b431066800a10231"
+ cap = CapFile(os.path.dirname(os.path.abspath(__file__)) + "/test_javacard.cap")
+ self.assertTrue(cap.get_loadfile() == loadfile)
+ self.assertTrue(cap.get_loadfile_aid() == "d07002ca44")
+ self.assertTrue(cap.get_applet_aid() == "d07002ca44900101")
+
+
+if __name__ == "__main__":
+ unittest.main()
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/39198?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: I581483ccb9d8a254fcecc995fec3c811c5cf38eb
Gerrit-Change-Number: 39198
Gerrit-PatchSet: 1
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Hello Jenkins Builder,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/python/pyosmocom/+/39193?usp=email
to look at the new patch set (#2).
Change subject: construct: allow stripping of leading zeros with StripTrailerAdapter
......................................................................
construct: allow stripping of leading zeros with StripTrailerAdapter
The class StripTrailerAdapter is currently only able to strip zeros at the end
of an integer. What it can not do is stripping leading zeros. Let's add a
parameter for that and extend the unittests accordingly.
Related: OS#6679
Change-Id: I1a9fff17abbbef0c5f6d45f58198debfa12e78b6
---
M src/osmocom/construct.py
M tests/test_construct.py
2 files changed, 59 insertions(+), 6 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/python/pyosmocom refs/changes/93/39193/2
--
To view, visit https://gerrit.osmocom.org/c/python/pyosmocom/+/39193?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newpatchset
Gerrit-Project: python/pyosmocom
Gerrit-Branch: master
Gerrit-Change-Id: I1a9fff17abbbef0c5f6d45f58198debfa12e78b6
Gerrit-Change-Number: 39193
Gerrit-PatchSet: 2
Gerrit-Owner: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: Jenkins Builder
pespin has uploaded this change for review. ( https://gerrit.osmocom.org/c/osmo-pcap/+/39192?usp=email )
Change subject: pcap-server: remove unneeded check for null base_path
......................................................................
pcap-server: remove unneeded check for null base_path
It cannot be ever NULL. It is set to a non-null path during alloc(), and
it can only be replaced with another string through VTY.
Change-Id: I2f503f6f9af35d6ae6fbd03e85cade4f0eb93df2
---
M src/osmo_server_vty.c
1 file changed, 1 insertion(+), 2 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-pcap refs/changes/92/39192/1
diff --git a/src/osmo_server_vty.c b/src/osmo_server_vty.c
index 6a44da6..c3014c9 100644
--- a/src/osmo_server_vty.c
+++ b/src/osmo_server_vty.c
@@ -96,8 +96,7 @@
vty_out(vty, "server%s", VTY_NEWLINE);
- if (pcap_server->base_path)
- vty_out(vty, " base-path %s%s", pcap_server->base_path, VTY_NEWLINE);
+ vty_out(vty, " base-path %s%s", pcap_server->base_path, VTY_NEWLINE);
vty_out(vty, " file-permission-mask 0%o%s", pcap_server->permission_mask, VTY_NEWLINE);
if (pcap_server->addr)
vty_out(vty, " server ip %s%s", pcap_server->addr, VTY_NEWLINE);
--
To view, visit https://gerrit.osmocom.org/c/osmo-pcap/+/39192?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings?usp=email
Gerrit-MessageType: newchange
Gerrit-Project: osmo-pcap
Gerrit-Branch: master
Gerrit-Change-Id: I2f503f6f9af35d6ae6fbd03e85cade4f0eb93df2
Gerrit-Change-Number: 39192
Gerrit-PatchSet: 1
Gerrit-Owner: pespin <pespin(a)sysmocom.de>