laforge has uploaded this change for review.
contrib/es9p_client: Add support for reporting notifications to SM-DP+
The ES9+ interface is not only used for downloading eSIM profiles, but
it is also used to report back the installation result as well as
profile management operations like enable/disable/delete.
Change-Id: Iefba7fa0471b34eae30700ed43531a515af0eb93
---
M contrib/es9p_client.py
1 file changed, 89 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/99/37499/1
diff --git a/contrib/es9p_client.py b/contrib/es9p_client.py
index 5e72e7b..7e763a3 100755
--- a/contrib/es9p_client.py
+++ b/contrib/es9p_client.py
@@ -30,7 +30,8 @@
import pySim.esim.rsp as rsp
from pySim.esim import es9p
-from pySim.utils import h2b, b2h, swap_nibbles, bertlv_parse_one_rawtag, bertlv_return_one_rawtlv
+from pySim.utils import h2b, b2h, swap_nibbles, is_hexstr
+from pySim.utils import bertlv_parse_one_rawtag, bertlv_return_one_rawtlv
from pySim.esim.x509_cert import CertAndPrivkey
from pySim.esim.es8p import BoundProfilePackage
@@ -63,6 +64,27 @@
parser_dl.add_argument('--confirmation-code',
help="Confirmation Code for the eSIM download")
+# notification
+parser_ntf = subparsers.add_parser('notification', help='ES9+ (other) notification')
+parser_ntf.add_argument('operation', choices=['enable','disable','delete'],
+ help='Profile Management Opreation whoise occurrence shall be notififed')
+parser_ntf.add_argument('--sequence-nr', type=int, required=True,
+ help='eUICC global notification sequence number')
+parser_ntf.add_argument('--notification-address', help='notificationAddress, if different from URL')
+
+# notification-install
+parser_ntfi = subparsers.add_parser('notification-install', help='ES9+ installation notification')
+parser_ntfi.add_argument('--sequence-nr', type=int, required=True,
+ help='eUICC global notification sequence number')
+parser_ntfi.add_argument('--transaction-id', required=True,
+ help='transactionId of previous ES9+ download')
+parser_ntfi.add_argument('--notification-address', help='notificationAddress, if different from URL')
+parser_ntfi.add_argument('--smdpp-oid', required=True, help='SM-DP+ OID (as in CERT.DPpb.ECDSA)')
+parser_ntfi.add_argument('--isdp-aid', type=is_hexstr, required=True,
+ help='AID of the ISD-P of the installed profile')
+parser_ntfi.add_argument('--sima-response', type=is_hexstr, required=True,
+ help='hex digits of BER-encoded SAIP EUICCResponse')
+
class Es9pClient:
def __init__(self, opts):
self.opts = opts
@@ -91,6 +113,54 @@
self.peer = es9p.Es9pApiClient(opts.url, server_cert_verify=opts.server_ca_cert)
+ def do_notification(self):
+
+ pmo4operation = {
+ 'install': 0x80,
+ 'enable': 0x40,
+ 'disable': 0x20,
+ 'delete': 0x10,
+ }
+
+ ntf_metadata = {
+ 'seqNumber': self.opts.sequence_nr,
+ 'profileManagementOperation': (bytes([pmo4operation[self.opts.operation]]), 1),
+ 'notificationAddress': self.opts.notification_address or urlparse(self.opts.url).netloc,
+ }
+
+ if self.opts.operation == 'download':
+ pird = {
+ 'transactionId': self.opts.transaction_id,
+ 'notificationMetadata': ntf_metadata,
+ 'smdpOid': self.opts.smdpp_oid,
+ 'finalResult': ('successResult', {
+ 'aid': self.opts.isdp_aid,
+ 'simaResponse': self.opts.sima_response,
+ }),
+ }
+ pird_bin = rsp.asn1.encode('ProfileInstallationResultData', pird)
+ signature = self.cert_and_key.ecdsa_sign(pird_bin)
+ pn_dict = ('profileInstallationResult', {
+ 'profileInstallationResultData': pird,
+ 'euiccSignPIR': signature,
+ })
+ else:
+ ntf_bin = rsp.asn1.encode('NotificationMetadata', ntf_metadata)
+ signature = self.cert_and_key.ecdsa_sign(ntf_bin)
+ pn_dict = ('otherSignedNotification', {
+ 'tbsOtherNotification': ntf_metadata,
+ 'euiccNotificationSignature': signature,
+ 'euiccCertificate': rsp.asn1.decode('Certificate', self.cert_and_key.get_cert_as_der()),
+ 'eumCertificate': rsp.asn1.decode('Certificate', self.eum_cert.public_bytes(Encoding.DER)),
+ })
+
+ data = {
+ 'pendingNotification': pn_dict,
+ }
+ #print(data)
+ res = self.peer.call_handleNotification(data)
+
+
def do_download(self):
print("Step 1: InitiateAuthentication...")
@@ -243,3 +313,8 @@
if opts.command == 'download':
c.do_download()
+ elif opts.command == 'notification':
+ c.do_notification()
+ elif opts.command == 'notification-install':
+ opts.operation = 'install'
+ c.do_notification()
To view, visit change 37499. To unsubscribe, or for help writing mail filters, visit settings.