Skip to content

Repository files navigation

euicc-rsp

The SM-DP+ role of SGP.22, as a C library. It runs an RSP session's server side -- InitiateAuthentication, AuthenticateClient, GetBoundProfilePackage -- and builds the Bound Profile Package the last of those hands back. It is not a server: no HTTPS, no ES2+, no SM-DS, no activation code, and no Profile order database, so the caller supplies the Profile metadata this library has nowhere to look it up from. euicc-tools is the command that uses it.

The BPP now carries everything SGP.22 v2.6 section 2.5.4's Table 4 requires for a card to accept it: '87' encrypted and MAC'd, '88' MAC'd, and real transactionId, hostId and smdpSign where placeholders used to be. That is a conformance claim, checked against Table 4 and against this library's own recovery of what it built -- not a card's answer. No eUICC in this repository accepts anything, because the card side is not in this repository.

What is still open is narrower, and each piece is spec-conformant on its own: the Profile Protection Keys ("random key") mode, a '88' too large for one segment, and a handful of OPTIONAL metadata fields -- include/rsp.h's comment on rsp_bpp_input_t has the full list and why each one is still open.

serverAddress used to sit on that list and no longer does. The SM-DP+'s own address is now a parameter of rsp_dp_initiate_authentication, and so is the smdpAddress the LPA sent: SGP.22 section 5.6.1 has the server compare the two case-insensitively, and a mismatch is the one thing that function refuses. An .invalid placeholder used to be signed in its place. The same call's response can now be read apart into the five fields the ES9+ JSON binding names (section 6.5.2.6), as can AuthenticateClient's (section 6.5.2.8) -- cut out of the encoded bytes rather than decoded and rebuilt, so what a server puts on the wire is what was signed.

The session still stops where the download does. Of ES9+'s five functions, the three above are implemented; HandleNotification and CancelSession are not. A ProfileInstallationResult that reaches this library is checked against the eUICC's own signature over it (rsp_dp_verify_installation_result), but nothing here receives one over a network, and no notification the eUICC queues is collected. This library can bind a Profile to an eUICC and judge the report it is handed; it cannot yet go and ask for one.

Repository Role
asn1c-vn the language
euicc-schema the vocabulary
euicc-tools the command
euicc-rsp (this one) the protocol

Threads

This library can be called from more than one thread at once. Two things were needed, and neither alone was enough.

rsp_sign used to keep its RNG in a file-scope singleton behind an unsynchronised lazy initialisation: one thread's mbedtls_ctr_drbg_init would memset a context another was already seeding. It builds one per call now, on the stack, the way src/rsp_pki.c always has — the sharing is removed rather than guarded.

That fixed this library's own state but not mbedTLS's. With only the first change, a concurrent caller still crashed inside mbedTLS's entropy accumulator, so the Makefile now compiles the vendored mbedTLS and everything here with MBEDTLS_THREADING_C and MBEDTLS_THREADING_PTHREAD. Both flags have to reach both: they add mutex members to mbedTLS contexts, so a translation unit built without them would size those contexts differently than the library it links against. Anything linking this — euicc-lpa, euicc-tools — passes the same two flags, and links with -pthread.

tests/test_threads.c holds it: eight threads, 12 800 signatures, crossing MBEDTLS_CTR_DRBG_RESEED_INTERVAL on purpose so the second race is reached as well as the first. Before the fixes it segfaulted in five runs out of six; after, 0 in 20, at 755% CPU.

Build

git clone --recurse-submodules https://github.com/waigel/euicc-rsp.git
cd euicc-rsp
make
make check

make check needs no card reader. Every test in this repository is provable on a machine with no hardware attached -- the transport, the ES10 command layer and the read-only card commands, the parts that would need one, live in euicc-lpa now, not here.

make check also generates the RSP codec with asn1c (see below) the first time it runs. Install it with brew install asn1c, or point ASN1C= at a binary you already built; SKELDIR= overrides the skeleton directory the same way, if it is not next to asn1c on PATH.

This needs asn1c 0.9.29 or later. The codec rule passes -D (the destination directory for generated files), which was added in that release. Debian and Ubuntu package 0.9.28, which does not have it -- asn1c: invalid option -- 'D' means this is why. brew install asn1c on macOS already gets 0.9.29 or newer; on Debian/Ubuntu, build from source (see .github/workflows/ci.yml for a working sequence) and point ASN1C=/SKELDIR= at the result instead of installing the packaged one.

The RSP ASN.1 module

rsp-2.5.asn is the RSPDefinitions module of GSMA SGP.22 (RSP Technical Specification), the wire format this library encodes and decodes -- BoundProfilePackage, StoreMetadataRequest, ProfileInstallationResult, and the rest of the ES8+/ES9+ messages. make runs it through asn1c and writes the generated codec to dist/, which is not committed.

It imports Certificate, CertificateList, Time and SubjectKeyIdentifier from the PKIX ASN.1 modules (RFC 3280). Those are vendored in third_party/pkix/: generated once from the RFC text by the same crfc2asn1.pl extraction euicc-schema already performs, and copied in rather than re-run here, so this repository does not depend on that sibling or on Perl at build time.

License and attribution

The code of this project, its Makefile and its documentation are under the MIT License. Two parts have their own origin:

  • rsp-2.5.asn, the RSPDefinitions module, is © GSMA. It comes from the public RSP Technical Specification (SGP.22) and is not under an open source license; the specification carries no warranty and its own IPR disclaimer applies. This copy was fetched from estkme-group/lpac, one of several public projects that redistribute it, and cross-checked against the independent copy in osmocom/pysim (pySim/esim/asn1/rsp/rsp.asn) -- the two agree on the module identifier and on every type both define.
  • third_party/pkix/ is extracted from IETF RFC 3280, under the IETF Trust's rules, which permit unmodified redistribution.
  • The code generator and the runtime skeletons are asn1c by Lev Walkin, under a BSD license.

Test material only

The certificates and keys in testdata/sgp26/ are the published GSMA SGP.26 test material -- the ASN.1 module above is a format definition, not test material, and is unaffected by this note. They work on test eUICCs and nowhere else. A production eUICC rejects them, and a production profile must never be loaded with them. The DP certificates' private keys are part of the published material, redistributed here byte-identical from osmocom/pysim; the Certificate Issuer's private key is not published and is not in this repository -- see testdata/sgp26/README.md for what each file is and where it came from.

About

The SM-DP+ role for loading eSIM profiles onto a test eUICC: SGP.22 credentials, SCP03t, Bound Profile Packages and the handshake signatures. A C library, no server.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages