laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/38959?usp=email )
Change subject: contrib/suci-keytool.py: Convenience tool for SUCI key generation ......................................................................
contrib/suci-keytool.py: Convenience tool for SUCI key generation
This adds a small utility program that can be used for generating keys used for SUCI in 5G SA networks, as well as for dumping them in a format that's compatible with what is needed on the USIM.
Change-Id: I9e92bbba7f700e160ea9c58da5f23fa4c31d40c6 --- A contrib/suci-keytool.py M docs/index.rst A docs/suci-keytool.rst 3 files changed, 111 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/59/38959/1
diff --git a/contrib/suci-keytool.py b/contrib/suci-keytool.py new file mode 100755 index 0000000..6abd489 --- /dev/null +++ b/contrib/suci-keytool.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 + +# small utility program to deal with 5G SUCI key material, at least for the ECIES Protection Scheme +# Profile A (curve25519) and B (secp256r1) + +# (C) 2024 by Harald Welte laforge@osmocom.org +# SPDX-License-Identifier: GPL-2.0+ + +import argparse + +from osmocom.utils import b2h +from Cryptodome.PublicKey import ECC +# if used with pycryptodome < v3.21.0 you will get the following error when using curve25519: +# "Cryptodome.PublicKey.ECC.UnsupportedEccFeature: Unsupported ECC purpose (OID: 1.3.101.110)" + +def gen_key(opts): + # FIXME: avoid overwriting key files + mykey = ECC.generate(curve=opts.curve) + data = mykey.export_key(format='PEM') + with open(opts.key_file, "wt") as f: + f.write(data) + +def dump_pkey(opts): + + #with open("curve25519-1.key", "r") as f: + + with open(opts.key_file, "r") as f: + data = f.read() + mykey = ECC.import_key(data) + + der = mykey.public_key().export_key(format='raw', compress=opts.compressed) + print(b2h(der)) + +arg_parser = argparse.ArgumentParser(description="""Generate or export SUCI keys for 5G SA networks""") +arg_parser.add_argument('--key-file', help='The key file to use', required=True) + +subparsers = arg_parser.add_subparsers(dest='command', help="The command to perform", required=True) + +parser_genkey = subparsers.add_parser('generate-key', help='Generate a new key pair') +parser_genkey.add_argument('--curve', help='The ECC curve to use', choices=['secp256r1','curve25519'], required=True) + +parser_dump_pkey = subparsers.add_parser('dump-pub-key', help='Dump the public key') +parser_dump_pkey.add_argument('--compressed', help='Use point compression', action='store_true') + +if __name__ == '__main__': + + opts = arg_parser.parse_args() + + if opts.command == 'generate-key': + gen_key(opts) + elif opts.command == 'dump-pub-key': + dump_pkey(opts) diff --git a/docs/index.rst b/docs/index.rst index 228fb79..1dfa624 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -44,6 +44,7 @@ library osmo-smdpp sim-rest + suci-keytool
Indices and tables diff --git a/docs/suci-keytool.rst b/docs/suci-keytool.rst new file mode 100644 index 0000000..88e3a24 --- /dev/null +++ b/docs/suci-keytool.rst @@ -0,0 +1,58 @@ +suci-keytool +============ + +Subscriber concealment is an important feature of the 5G SA architecture: It avoids the many privacy +issues associated with having a permanent identifier (SUPI, traditionally the IMSI) transmitted in plain text +over the air interface. Using SUCI solves this issue not just for the air interface; it even ensures the SUPI/IMSI +is not known to the visited network (VPLMN) at all. + +In principle, the SUCI mechanism works by encrypting the SUPI by asymmetric (public key) cryptography: +Only the HPLMN is in possession of the private key and hence can decrypt the SUCI to the SUPI, while +each subscriber has the public key in order to encrypt their SUPI into the SUCI. In reality, the +details are more complex, as there are ephemeral keys and cryptographic MAC involved. + +In any case, in order to operate a SUCI-enabled 5G SA network, you will have to + +#. generate a ECC key pair of public + private key +#. deploy the public key on your USIMs +#. deploy the private key on your 5GC, specifically the UDM function + +pysim contains (int its `contrib` directory) a small utility program that can make it easy to generate +such keys: `suci-keytool.py` + +Generating keys +~~~~~~~~~~~~~~~ + +Example: Generating a *secp256r1* ECC public key pair and storing it to `/tmp/suci.key`: +:: + + $ ./contrib/suci-keytool.py --key-file /tmp/suci.key generate-key --curve secp256r1 + +Dumping public keys +~~~~~~~~~~~~~~~~~~~ + +In order to store the key to SIM cards as part of `ADF.USIM/DF.5GS/EF.SUCI_Calc_Info`, you will need +a hexadecimal representation of the public key. You can achieve that using the `dump-pub-key` operation +of suci-keytool: + +Example: Dumping the public key part from a previously generated key file: +:: + + $ ./contrib/suci-keytool.py --key-file /tmp/suci.key dump-pub-key + 0473152f32523725f5175d255da2bd909de97b1d06449a9277bc629fe42112f8643e6b69aa6dce6c86714ccbe6f2e0f4f4898d102e2b3f0c18ce26626f052539bb + +If you want the point-compressed representation, you can use the `--compressed` option: +:: + + $ ./contrib/suci-keytool.py --key-file /tmp/suci.key dump-pub-key --compressed + 0373152f32523725f5175d255da2bd909de97b1d06449a9277bc629fe42112f864 + + + +suci-keytool syntax +~~~~~~~~~~~~~~~~~~~ + +.. argparse:: + :module: contrib.suci-keytool + :func: arg_parser + :prog: contrib/suci-keytool.py