mirror of
https://gitea.osmocom.org/sim-card/pysim.git
synced 2026-03-17 02:48:34 +03:00
It's generally a bad idea to keep [card specific] key material lying around unencrypted in CSV files. The industry standard solution in the GSMA is a so-called "transport key", which encrypts the key material. Let's introduce support for this in the CardKeyProvider (and specifically, the CardKeyProviderCSV) and allow the user to specify transport key material as command line options to pySim-shell. Different transport keys can be used for different key materials, so allow specification of keys on a CSV-column base. The higher-level goal is to allow the CSV file not only to store the ADM keys (like now), but also global platform key material for establishing SCP towards various security domains in a given card. Change-Id: I13146a799448d03c681dc868aaa31eb78b7821ff
127 lines
5.1 KiB
ReStructuredText
127 lines
5.1 KiB
ReStructuredText
|
|
Retrieving card-individual keys via CardKeyProvider
|
|
==================================================
|
|
|
|
When working with a batch of cards, or more than one card in general, it
|
|
is a lot of effort to manually retrieve the card-specific PIN (like
|
|
ADM1) or key material (like SCP02/SCP03 keys).
|
|
|
|
To increase productivity in that regard, pySim has a concept called the
|
|
`CardKeyProvider`. This is a generic mechanism by which different parts
|
|
of the pySim[-shell] code can programmatically request card-specific key material
|
|
from some data source (*provider*).
|
|
|
|
For example, when you want to verify the ADM1 PIN using the `verify_adm`
|
|
command without providing an ADM1 value yourself, pySim-shell will
|
|
request the ADM1 value for the ICCID of the card via the
|
|
CardKeyProvider.
|
|
|
|
There can in theory be multiple different CardKeyProviders. You can for
|
|
example develop your own CardKeyProvider that queries some kind of
|
|
database for the key material, or that uses a key derivation function to
|
|
derive card-specific key material from a global master key.
|
|
|
|
The only actual CardKeyProvider implementation included in pySim is the
|
|
`CardKeyProviderCsv` which retrieves the key material from a
|
|
[potentially encrypted] CSV file.
|
|
|
|
|
|
The CardKeyProviderCsv
|
|
----------------------
|
|
|
|
The `CardKeyProviderCsv` allows you to retrieve card-individual key
|
|
material from a CSV (comma separated value) file that is accessible to pySim.
|
|
|
|
The CSV file must have the expected column names, for example `ICCID`
|
|
and `ADM1` in case you would like to use that CSV to obtain the
|
|
card-specific ADM1 PIN when using the `verify_adm` command.
|
|
|
|
You can specify the CSV file to use via the `--csv` command-line option
|
|
of pySim-shell. If you do not specify a CSV file, pySim will attempt to
|
|
open a CSV file from the default location at
|
|
`~/.osmocom/pysim/card_data.csv`, and use that, if it exists.
|
|
|
|
Column-Level CSV encryption
|
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
|
|
pySim supports column-level CSV encryption. This feature will make sure
|
|
that your key material is not stored in plaintext in the CSV file.
|
|
|
|
The encryption mechanism uses AES in CBC mode. You can use any key
|
|
length permitted by AES (128/192/256 bit).
|
|
|
|
Following GSMA FS.28, the encryption works on column level. This means
|
|
different columns can be decrypted using different key material. This
|
|
means that leakage of a column encryption key for one column or set of
|
|
columns (like a specific security domain) does not compromise various
|
|
other keys that might be stored in other columns.
|
|
|
|
You can specify column-level decryption keys using the
|
|
`--csv-column-key` command line argument. The syntax is
|
|
`FIELD:AES_KEY_HEX`, for example:
|
|
|
|
`pySim-shell.py --csv-column-key SCP03_ENC_ISDR:000102030405060708090a0b0c0d0e0f`
|
|
|
|
In order to avoid having to repeat the column key for each and every
|
|
column of a group of keys within a keyset, there are pre-defined column
|
|
group aliases, which will make sure that the specified key will be used
|
|
by all columns of the set:
|
|
|
|
* `UICC_SCP02` is a group alias for `UICC_SCP02_KIC1`, `UICC_SCP02_KID1`, `UICC_SCP02_KIK1`
|
|
* `UICC_SCP03` is a group alias for `UICC_SCP03_KIC1`, `UICC_SCP03_KID1`, `UICC_SCP03_KIK1`
|
|
* `SCP03_ECASD` is a group alias for `SCP03_ENC_ECASD`, `SCP03_MAC_ECASD`, `SCP03_DEK_ECASD`
|
|
* `SCP03_ISDA` is a group alias for `SCP03_ENC_ISDA`, `SCP03_MAC_ISDA`, `SCP03_DEK_ISDA`
|
|
* `SCP03_ISDR` is a group alias for `SCP03_ENC_ISDR`, `SCP03_MAC_ISDR`, `SCP03_DEK_ISDR`
|
|
|
|
|
|
Field naming
|
|
------------
|
|
|
|
* For look-up of UICC/SIM/USIM/ISIM or eSIM profile specific key
|
|
material, pySim uses the `ICCID` field as lookup key.
|
|
|
|
* For look-up of eUICC specific key material (like SCP03 keys for the
|
|
ISD-R, ECASD), pySim uses the `EID` field as lookup key.
|
|
|
|
As soon as the CardKeyProviderCsv finds a line (row) in your CSV where
|
|
the ICCID or EID match, it looks for the column containing the requested
|
|
data.
|
|
|
|
|
|
ADM PIN
|
|
~~~~~~~
|
|
|
|
The `verify_adm` command will attempt to look up the `ADM1` column
|
|
indexed by the ICCID of the SIM/UICC.
|
|
|
|
|
|
SCP02 / SCP03
|
|
~~~~~~~~~~~~~
|
|
|
|
SCP02 and SCP03 each use key triplets consisting if ENC, MAC and DEK
|
|
keys. For more details, see the applicable GlobalPlatform
|
|
specifications.
|
|
|
|
If you do not want to manually enter the key material for each specific
|
|
card as arguments to the `establish_scp02` or `establish_scp03`
|
|
commands, you can make use of the `--key-provider-suffix` option. pySim
|
|
uses this suffix to compose the column names for the CardKeyProvider as
|
|
follows.
|
|
|
|
* `SCP02_ENC_` + suffix for the SCP02 ciphering key
|
|
* `SCP02_MAC_` + suffix for the SCP02 MAC key
|
|
* `SCP02_DEK_` + suffix for the SCP02 DEK key
|
|
* `SCP03_ENC_` + suffix for the SCP03 ciphering key
|
|
* `SCP03_MAC_` + suffix for the SCP03 MAC key
|
|
* `SCP03_DEK_` + suffix for the SCP03 DEK key
|
|
|
|
So for example, if you are using a command like `establish_scp03
|
|
--key-provider-suffix ISDR`, then the column names for the key material
|
|
look-up are `SCP03_ENC_ISDR`, `SCP03_MAC_ISDR` and `SCP03_DEK_ISDR`,
|
|
respectively.
|
|
|
|
The identifier used for look-up is determined by the definition of the
|
|
Security Domain. For example, the eUICC ISD-R and ECASD will use the EID
|
|
of the eUICC. On the other hand, the ISD-P of an eSIM or the ISD of an
|
|
UICC will use the ICCID.
|