This is a "cheap and cheerful" utility for exploring captured COER packets which can be useful when debugging or developing new concrete implementations of the CODECs abstract API. Indeed, it is an outgrowth of several quick and dirty programs used during the development of the ASN1C implementation which comes with the standard OpenSCMS stack.
It is tightly bound to the ASN1C codecs, with deep internal knowledge of that implementation. As such, it can not easily be ported to a different version of the bridge. To achieve this, it links to the static version of the oscms-codecs-bridge library, which makes all the otherwise hidden symbols from all levels of the stack available to the program.
A typical usage is to capture an exchange in Wireshark, extract the encoded SPDUs, and then iteratively decode them. Another valuable usage is for checking interoperability. For example, encoding an SPDU with a new API implementation, saving it to a file, and then using the explorer to see if it can decode it successfully. Alternatively, you can capture something sent by an EE and decode it with the explorer, then use that understanding to help you debug the decoding side of your own API implementation.
We assume a debian-based development environment, ideally Ubuntu 24.04 or newer.
The following libraries need to be installed on your development machine.
sudo apt install -y \
libzip-dev \
libssl-dev \
libcurl4-openssl-devYou will also need a set of tools
sudo apt-get -qy install \
build-essential \
clang-format-18 \
cmake \
cppcheck \
curl \
gengetopt \
git \
gzip \
valgrind \
wgetAlternatively, you can use the docker file provided in the oscms-ci-docker repository. This is the image used for all CI jobs for the C-language repositories during the initial development.
Clone the repository and build the image as follows
git clone git@github.com:OpenSCMS/oscms-ci-docker.git
cd oscms-ci-docker
docker build -t oscms-ci-docker . -f openscms-ci.dockerfileNow change to the directory where you cloned this repository and run the container thus
docker run -ti --rm --volume $PWD:/WORK --user $(id -u):$(id -g) \
oscms-ci-dockerThis will place you in a bash shell within the container, with your cloned source available at /WORK. Your user inside the container will have the same group and user id as on your host, so any changes you make will have the correct permissions.
It should also be possible to use this image as a VS Code development container. The development team has not used it in this way, so if it doesn't work ... contributions are welcome.
The Open SCMS stack makes heavy use of submodules. Therefore, the clone command should ensure it pulls down all sub modules as follows.
git clone --recurse-submodules git@github.com:OpenSCMS/oscms-coer-explorer.gitObviously, replace the URL with your own if you are cloning a fork.
Due to the use of relative submodule paths, if you are going to fork one repository you will need to fork them all. The alternative is for you to modify the paths in .gitmodules, but DO NOT commit these changes. Such a pull request will not be accepted.
The list of repositories, and their relative submodule dependencies is as follows
The project also makes use of the Cmake Helpers project
All C code is built using CMake and the CMake scripts will enforce out-of-source builds.
After cloning, create a build directory. We usually use BUILD directly in the repository root (it's included in the .gitignore), but feel free to put it anywhere convenient.
Change to your build directory and configure and build as follows
cmake .. # Or the path to your repository root
makeThis will compile and link a Debug build and include all unit tests.
The CMake script supports a common set of options and command line definitions.
| Option | Default | Description |
|---|---|---|
| CMAKE_BUILD_TYPE | Debug | Defines the build type. Acceptable values are Debug or Release. This primarily affects debug symbols and optimization levels. |
| EXTRA_MEMCHECK_OPTIONS | empty | Allows the specification of additional arguments to valgrind |
| RUN_CPPCHECK | On | Enables or disables running cppcheck on all code during the build. |
| SKIP_INSTALL | Off | If set to On, suppresses generation of any install targets |
Note that this project does NOT respect the SKIP_INSTALL option itself, as it is a standalone CLI tool and you will probably want to install it at some time. It does, however, override anything specified on the command line when building the lower level projects. This avoids all the libraries and include files etc being included in the generated make install target.
The generated executable is self contained, relying only on run time libraries installed in your path. Therefore you have two options for installing.
For a system wide install, enter the following command from the build directory, which will install the executable to /usr/local/bin (which should be in your PATH).
sudo make installAlternatively, for a local install, simply copy the executable to a directory which is in your PATH, such as ${HOME}/.local/bin.
Help can be obtained by using the -h or --help command line option.
$ ./OscmsCoerExplorer --help
Usage: OscmsCoerExplorer [-h|--help] [-V|--version] [-llevel|--loglevel=level]
[-p|--print-asn1c] [-d|--dump] [-i|--identify] [FILE]...
Development tool to explore COER-encoded files
-h, --help Print help and exit
-V, --version Print version and exit
-l, --loglevel=level Minimum level of message to log (possible
values="emergency", "alert", "critical",
"error", "warning", "notice", "info",
"debug" default=`critical')
Group: Non-interactive Actions
Mutually exclusive options which will quickly display information and then
exit
-p, --print-asn1c Output a raw ASN1C printf of the decoded file
-d, --dump Dump the file as hex
-i, --identify Simply identify the apparent type of objectThe tool can operate in an interactive mode, or be used to perform a number of quick actions.
More than one file can be provided on the command line, and the tool will work through each one in order in whatever mode it is operating.
Finally, the --loglevel option allows the user to see more detailed logging from the underlying stack. OscmsCoerExplorer itself doesn't use logging, but many of the functions it calls do. The output can be very noisy as, for example, the process of identifying the file content type will generate many error logs. However, it is provided as a last resort aid to someone trying to modify the tool.
There are three quick actions, described in the help above, which can quickly let you get a feel for a file containing a captured object.
-d- Dump the file as hex and ASCII, in a format similar to runninghexdump -C-i- Try and identify the contents of the provided file(s) and print out the results.-p- Use the ASN1Casn_fprintfunction to print a human-readable decoding of the file, assuming it can identify the type.
For example, running the tool on all the data files under the test-data directory, with the --identify option provides something like the following
$ OscmsCoerExplorer -i *.dat
File CertificateManagementInfoStatusSpdu.dat appears to be a Ieee1609Dot2Data-Signed
File CertManagementPdu.dat appears to be a CertificateManagementInfoStatus
File composite-crl-file.dat appears to be a Ieee1609Dot2Data-Unsecured
File composite-crl-scms-pdu.dat appears to be a CompositeCrl
File DecryptedEeRaCertRequestSpdu.dat appears to be a Ieee1609Dot2Data-SignedCertRequest
File DecryptedSuccessorEnrollmentRequest.dat appears to be a Ieee1609Dot2Data-SignedCertRequest
File EeEcaCertRequestSpdu.dat appears to be a Ieee1609Dot2Data-SignedCertRequest
File EeRaCertRequest.dat appears to be a Ieee1609Dot2Data-Encrypted
File EeRaCertRequestSpdu.dat appears to be a Ieee1609Dot2Data-Encrypted
File EeRaDownloadRequestSpdu.dat appears to be a Ieee1609Dot2Data-Encrypted
File EeRaSuccessorEnrollmentRequest.dat appears to be a Ieee1609Dot2Data-Encrypted
File EncryptedEeEcaCertRequestSpdu.dat appears to be a Ieee1609Dot2Data-SignedCertRequest
File MultiSignedCtlSpdu.dat appears to be a Ieee1609Dot2Data-Unsecured
File OscmsCertificateChainFile.dat appears to be a CertificateChain
File OscmsCertificateChainFileSpdu.dat appears to be a Ieee1609Dot2Data-Unsecured
File RaCertificate.dat appears to be a Certificate
File SecuredCrl.dat appears to be a Ieee1609Dot2Data-SignedAnd here is a sample output for the -p option on a small file
$ OscmsCoerExplorer -p CertManagementPdu.dat
File CertManagementPdu.dat
CertificateManagementInfoStatus ::= {
crl: SequenceOfCrlInfoStatus ::= {
CrlInfoStatus ::= {
cracaId: 15 E2 98 FE 7B 1D 91 99
series: 1
issueDate: 1757440535
}
}
ctl: SequenceOfCtlInfoStatus ::= {
CtlInfoStatus ::= {
ctlSeriesId: FF FF FF FF FF FF FF 00
sequenceNumber: 0
lastUpdate: 1757442522
}
}
caCcf: 1757442522
ma: SequenceOfMaInfoStatus ::= {
}
ra: 1757440534
}This mode is most useful when you are trying to understand the contents of a captured SPDU or other object.
When provided with a file, the explorer will first attempt to make a guess at the contents. The result may at first surprise you, but bear in mind many of the specific SPDU's defined in the standard are simply parameterized versions of more generic structures. For example, a CertificateChainSpdu is simply an Ieee1609Dot2Data-Unsecured with a specific payload (an encoded ScmsPdu).
At this point, you will be presented with a prompt for a command. The prompt will grow longer as you descend into the object.
Entering ? at this prompt will provide a list of all possible commands.
Available commands:
?: Display this help
q: Stop inspecting this object or file
Q: Stop inspecting this object or file
p: Print current object to stdout
P: Print current object to file
l: List available sub-objects
d: Try and decode sub-object
w: Save sub-object to file as binaryqorQwill stop inspection at the current level and return you to the parent object. If you are at the top, it will either exit the program or proceed with the next file.pwill provide a formatted ASN1C display of the current object, similar to the-pcommand line option.Pdoes the same aspbut prints the object to the file you specify.lwill list any objects embedded in the current object which the explorer knowns how to decode. If there are none, you will be advised of it.dwill descend into the sub-object you select, decoding it and presenting you with a new prompt. If only one sub-object is available, it will be automatically selected. If the explorer can't decode it, you will remain at the current level.wallows to to extract the sub-object in binary, COER-encoded, form and save it to a file.
If you are 10 levels deep and want to quit, either keep entering q until you exit ... or just hit Ctrl+C.
If you find your self looking at an Ieee1609Dot2Data-Encrypted, all is not lost. The d command will offer you two sub-objects:
$ ./OscmsCoerExplorer ../test-data/EeRaDownloadRequestSpdu.dat
File ../test-data/EeRaDownloadRequestSpdu.dat appears to be a Ieee1609Dot2Data-Encrypted
Ieee1609Dot2Data-Encrypted (? for help): d
Available sub-objects:
1: Raw Embedded Cypher text
2: Decrypted Payload (need to provide key and certificate)
Select a sub-object (1-2, 0 to cancel):Selecting the second object will then prompt you for two files:
- The appropriate private key
- The COER encoded 1609.2 Certificate for the receiver (usually the server)
it will then proceed to try and decrypt the payload. If it succeeds, it will then decode the payload and descend into it.
For testing purposes, the test-data/certs directory contains the keys and certificates used during the session from which the test data was captured. Thus, the above file can be analyzed as follows:
$ ./OscmsCoerExplorer ../test-data/EeRaDownloadRequestSpdu.dat
File ../test-data/EeRaDownloadRequestSpdu.dat appears to be a Ieee1609Dot2Data-Encrypted
Ieee1609Dot2Data-Encrypted (? for help): d
Available sub-objects:
1: Raw Embedded Cypher text
2: Decrypted Payload (need to provide key and certificate)
Select a sub-object (1-2, 0 to cancel): 2
Enter the private key file name: raEncPrivateKey.dat
Enter the certificate file name: raCertificate.dat
Ieee1609Dot2Data-Encrypted.Ieee1609Dot2Data-Signed (? for help): l
Available sub-objects:
1: Signed Data Payload
Ieee1609Dot2Data-Encrypted.Ieee1609Dot2Data-Signed (? for help): d
Only one sub-object available, auto-selecting Signed Data Payload
Ieee1609Dot2Data-Encrypted.Ieee1609Dot2Data-Signed.Ieee1609Dot2Data-Unsecured (? for help): d
Only one sub-object available, auto-selecting Unsecured Data
Ieee1609Dot2Data-Encrypted.Ieee1609Dot2Data-Signed.Ieee1609Dot2Data-Unsecured.EeRaDownloadRequest (? for help): d
No sub-objects available
Ieee1609Dot2Data-Encrypted.Ieee1609Dot2Data-Signed.Ieee1609Dot2Data-Unsecured.EeRaDownloadRequest (? for help): p
EeRaDownloadRequest ::= {
generationTime: 689891085
filename: 4068FB4412F8B0F2.zip
}Which shows a complete descent through the file to the most atomic structure, and nicely demonstrates just how deeply nested these SPDU's are. In this case, an EeRaDownloadRequestSpdu is actually an
Encrypted(Signed(Unsecured(EeRaDownloadRequest)))
with 4 rounds of encoding needed to produce the final SPDU.
Contributions are welcome. Please see the CONTRIBUTING file for details, including the Code of Conduct and C Style Guide.
This project is licensed under the Apache-2.0 License. See the LICENSE file for details.