@particle/esim-tooling 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +187 -0
- package/dist/activation-code.d.ts +11 -0
- package/dist/activation-code.d.ts.map +1 -0
- package/dist/activation-code.js +56 -0
- package/dist/activation-code.js.map +1 -0
- package/dist/apdu.d.ts +73 -0
- package/dist/apdu.d.ts.map +1 -0
- package/dist/apdu.js +357 -0
- package/dist/apdu.js.map +1 -0
- package/dist/errors.d.ts +32 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +52 -0
- package/dist/errors.js.map +1 -0
- package/dist/es10/es10b-notifications.d.ts +30 -0
- package/dist/es10/es10b-notifications.d.ts.map +1 -0
- package/dist/es10/es10b-notifications.js +294 -0
- package/dist/es10/es10b-notifications.js.map +1 -0
- package/dist/es10/es10b.d.ts +34 -0
- package/dist/es10/es10b.d.ts.map +1 -0
- package/dist/es10/es10b.js +108 -0
- package/dist/es10/es10b.js.map +1 -0
- package/dist/es10/es10c.d.ts +12 -0
- package/dist/es10/es10c.d.ts.map +1 -0
- package/dist/es10/es10c.js +133 -0
- package/dist/es10/es10c.js.map +1 -0
- package/dist/es10/iccid.d.ts +9 -0
- package/dist/es10/iccid.d.ts.map +1 -0
- package/dist/es10/iccid.js +31 -0
- package/dist/es10/iccid.js.map +1 -0
- package/dist/es10/index.d.ts +5 -0
- package/dist/es10/index.d.ts.map +1 -0
- package/dist/es10/index.js +4 -0
- package/dist/es10/index.js.map +1 -0
- package/dist/es10/tags.d.ts +55 -0
- package/dist/es10/tags.d.ts.map +1 -0
- package/dist/es10/tags.js +63 -0
- package/dist/es10/tags.js.map +1 -0
- package/dist/es9plus.d.ts +52 -0
- package/dist/es9plus.d.ts.map +1 -0
- package/dist/es9plus.js +227 -0
- package/dist/es9plus.js.map +1 -0
- package/dist/gsma-rsp2-root-ci1.d.ts +38 -0
- package/dist/gsma-rsp2-root-ci1.d.ts.map +1 -0
- package/dist/gsma-rsp2-root-ci1.js +52 -0
- package/dist/gsma-rsp2-root-ci1.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/lpa.d.ts +15 -0
- package/dist/lpa.d.ts.map +1 -0
- package/dist/lpa.js +283 -0
- package/dist/lpa.js.map +1 -0
- package/dist/tlv.d.ts +14 -0
- package/dist/tlv.d.ts.map +1 -0
- package/dist/tlv.js +132 -0
- package/dist/tlv.js.map +1 -0
- package/dist/types.d.ts +230 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +108 -0
- package/dist/types.js.map +1 -0
- package/package.json +50 -0
- package/src/activation-code.ts +64 -0
- package/src/apdu.ts +419 -0
- package/src/errors.ts +69 -0
- package/src/es10/es10b-notifications.ts +331 -0
- package/src/es10/es10b.ts +163 -0
- package/src/es10/es10c.ts +168 -0
- package/src/es10/iccid.ts +32 -0
- package/src/es10/index.ts +42 -0
- package/src/es10/tags.ts +69 -0
- package/src/es9plus.ts +331 -0
- package/src/gsma-rsp2-root-ci1.ts +53 -0
- package/src/index.ts +43 -0
- package/src/lpa.ts +346 -0
- package/src/tlv.ts +137 -0
- package/src/types.ts +264 -0
package/README.md
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
# @particle/esim-tooling
|
|
2
|
+
|
|
3
|
+
TypeScript library for eSIM profile provisioning (SGP.22). Manages eSIM profiles on
|
|
4
|
+
devices with an eUICC — list, enable, disable, delete, and install profiles.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```
|
|
9
|
+
npm install @particle/esim-tooling
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
## Quick Start
|
|
13
|
+
|
|
14
|
+
```typescript
|
|
15
|
+
import { EsimLpa } from '@particle/esim-tooling';
|
|
16
|
+
import type { DeviceAdapter, ServerAdapter } from '@particle/esim-tooling';
|
|
17
|
+
|
|
18
|
+
// Create adapters for your environment
|
|
19
|
+
const device: DeviceAdapter = createMyDeviceAdapter();
|
|
20
|
+
const server: ServerAdapter = createMyServerAdapter();
|
|
21
|
+
|
|
22
|
+
const lpa = new EsimLpa({ device, server });
|
|
23
|
+
|
|
24
|
+
// List profiles
|
|
25
|
+
const profiles = await lpa.listProfiles();
|
|
26
|
+
for (const p of profiles) {
|
|
27
|
+
console.log(`${p.iccid} ${p.profileName} [${p.state === 1 ? 'enabled' : 'disabled'}]`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Enable a profile
|
|
31
|
+
await lpa.enableProfile('89012345678901234567');
|
|
32
|
+
|
|
33
|
+
// Disable a profile
|
|
34
|
+
await lpa.disableProfile('89012345678901234567');
|
|
35
|
+
|
|
36
|
+
// Delete a profile (must be disabled first)
|
|
37
|
+
await lpa.deleteProfile('89012345678901234567');
|
|
38
|
+
|
|
39
|
+
// Install a new profile
|
|
40
|
+
const result = await lpa.installProfile({
|
|
41
|
+
activationCode: '1$smdp.example.com$ACTIVATION-TOKEN',
|
|
42
|
+
onProgress: (p) => console.log(p.step),
|
|
43
|
+
});
|
|
44
|
+
console.log(`Installed: ${result.iccid}`);
|
|
45
|
+
|
|
46
|
+
// Process pending notifications
|
|
47
|
+
const notifResult = await lpa.processNotifications();
|
|
48
|
+
console.log(`Sent ${notifResult.sent}/${notifResult.total} notifications`);
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Adapters
|
|
52
|
+
|
|
53
|
+
This library does not directly communicate with devices or servers. You provide
|
|
54
|
+
two adapters that handle I/O.
|
|
55
|
+
|
|
56
|
+
### DeviceAdapter
|
|
57
|
+
|
|
58
|
+
Sends a single APDU to the eUICC and returns the response. The library handles
|
|
59
|
+
all higher-level protocol concerns (logical channels, STORE DATA chunking,
|
|
60
|
+
GET RESPONSE chaining, BPP segmentation).
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface DeviceAdapter {
|
|
64
|
+
sendApdu(apdu: Uint8Array): Promise<Uint8Array>;
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Example: Particle USB adapter**
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
import { openDeviceById } from 'particle-usb';
|
|
72
|
+
import DeviceOSProtobuf from '@particle/device-os-protobuf';
|
|
73
|
+
|
|
74
|
+
const proto = {
|
|
75
|
+
ManagerRequest: DeviceOSProtobuf.schema.system.esim.ManagerRequest,
|
|
76
|
+
ManagerResponse: DeviceOSProtobuf.schema.system.esim.ManagerResponse,
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
function createParticleUsbAdapter(device): DeviceAdapter {
|
|
80
|
+
return {
|
|
81
|
+
async sendApdu(apdu: Uint8Array): Promise<Uint8Array> {
|
|
82
|
+
// Encode APDU as protobuf ManagerRequest
|
|
83
|
+
const request = proto.ManagerRequest.create({ apdu: { data: apdu } });
|
|
84
|
+
const requestBytes = proto.ManagerRequest.encode(request).finish();
|
|
85
|
+
const response = await device.sendControlRequest(10, Buffer.from(requestBytes));
|
|
86
|
+
// Decode protobuf ManagerResponse, return APDU response
|
|
87
|
+
const managerResponse = proto.ManagerResponse.decode(response.data);
|
|
88
|
+
return new Uint8Array(managerResponse.apdu.data);
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### ServerAdapter
|
|
95
|
+
|
|
96
|
+
Forwards ES9+ ASN.1 DER requests to SM-DP+ servers. SM-DP+ servers use TLS certificates
|
|
97
|
+
signed by the GSMA RSP2 Root CI, which is not in standard system CA stores.
|
|
98
|
+
The adapter owns the entire HTTP lifecycle — URL construction, headers, TLS.
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
interface ServerAdapter {
|
|
102
|
+
sendRsp(smdpAddress: string, endpoint: string, requestData: Uint8Array): Promise<ServerResponse>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
interface ServerResponse {
|
|
106
|
+
statusCode: number;
|
|
107
|
+
responseData?: Uint8Array;
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Example: direct adapter**
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
const server: ServerAdapter = {
|
|
115
|
+
async sendRsp(smdpAddress, endpoint, requestData) {
|
|
116
|
+
const response = await fetch(`https://${smdpAddress}/gsma/rsp2/asn1`, {
|
|
117
|
+
method: 'POST',
|
|
118
|
+
headers: {
|
|
119
|
+
'Content-Type': 'application/x-gsma-rsp-asn1',
|
|
120
|
+
'User-Agent': 'gsma-rsp-lpad',
|
|
121
|
+
'X-Admin-Protocol': 'gsma/rsp/v2.1.0',
|
|
122
|
+
},
|
|
123
|
+
body: requestData,
|
|
124
|
+
});
|
|
125
|
+
const statusCode = response.status;
|
|
126
|
+
if (statusCode === 204) return { statusCode };
|
|
127
|
+
const responseData = new Uint8Array(await response.arrayBuffer());
|
|
128
|
+
return { statusCode, responseData };
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## API Reference
|
|
134
|
+
|
|
135
|
+
### `EsimLpa`
|
|
136
|
+
|
|
137
|
+
| Method | Description |
|
|
138
|
+
|--------|-------------|
|
|
139
|
+
| `getEid()` | Get the 32-character hex EID |
|
|
140
|
+
| `listProfiles()` | List all profiles on the eUICC |
|
|
141
|
+
| `enableProfile(iccid)` | Enable a disabled profile |
|
|
142
|
+
| `disableProfile(iccid)` | Disable the active profile |
|
|
143
|
+
| `deleteProfile(iccid)` | Delete a disabled profile |
|
|
144
|
+
| `installProfile(options)` | Download and install a profile from SM-DP+ |
|
|
145
|
+
| `listNotifications()` | List pending notification metadata |
|
|
146
|
+
| `processNotifications()` | Send all pending notifications to SM-DP+ servers |
|
|
147
|
+
|
|
148
|
+
### Profile States
|
|
149
|
+
|
|
150
|
+
| Value | State |
|
|
151
|
+
|-------|-------|
|
|
152
|
+
| 0 | Disabled |
|
|
153
|
+
| 1 | Enabled |
|
|
154
|
+
|
|
155
|
+
### Notification Events
|
|
156
|
+
|
|
157
|
+
| Value | Event |
|
|
158
|
+
|-------|-------|
|
|
159
|
+
| 0x80 | Install |
|
|
160
|
+
| 0x40 | Enable |
|
|
161
|
+
| 0x20 | Disable |
|
|
162
|
+
| 0x10 | Delete |
|
|
163
|
+
|
|
164
|
+
## Error Handling
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
import { Es10Error, Es9PlusError, DeviceError } from '@particle/esim-tooling';
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
await lpa.enableProfile(iccid);
|
|
171
|
+
} catch (error) {
|
|
172
|
+
if (error instanceof Es10Error) {
|
|
173
|
+
// eUICC returned an error (e.g., profile not found, policy violation)
|
|
174
|
+
console.log('eUICC error:', error.resultCode, error.message);
|
|
175
|
+
} else if (error instanceof Es9PlusError) {
|
|
176
|
+
// SM-DP+ server error
|
|
177
|
+
console.log('Server error:', error.statusCode, error.serverStatus);
|
|
178
|
+
} else if (error instanceof DeviceError) {
|
|
179
|
+
// Device communication error
|
|
180
|
+
console.log('Device error:', error.result);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## License
|
|
186
|
+
|
|
187
|
+
Apache-2.0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ActivationCode } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an RSP activation code string per SGP.22 Section 4.1.
|
|
4
|
+
* Format: LPA:1$<smdpAddress>$<matchingId>[$<smdpOid>][$<ccRequired>]
|
|
5
|
+
* Per spec, the parser SHALL ignore a delimiter and any further parameters
|
|
6
|
+
* beyond those it recognizes.
|
|
7
|
+
*/
|
|
8
|
+
export declare function parseActivationCode(code: string): ActivationCode;
|
|
9
|
+
export declare function isValidActivationCode(code: string): boolean;
|
|
10
|
+
export declare function formatActivationCode(params: Omit<ActivationCode, 'format'>): string;
|
|
11
|
+
//# sourceMappingURL=activation-code.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation-code.d.ts","sourceRoot":"","sources":["../src/activation-code.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,cAAc,CAkChE;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAO3D;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,GAAG,MAAM,CASnF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { ActivationCodeError } from './errors.js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse an RSP activation code string per SGP.22 Section 4.1.
|
|
4
|
+
* Format: LPA:1$<smdpAddress>$<matchingId>[$<smdpOid>][$<ccRequired>]
|
|
5
|
+
* Per spec, the parser SHALL ignore a delimiter and any further parameters
|
|
6
|
+
* beyond those it recognizes.
|
|
7
|
+
*/
|
|
8
|
+
export function parseActivationCode(code) {
|
|
9
|
+
// Strip optional "LPA:" prefix
|
|
10
|
+
let input = code;
|
|
11
|
+
if (input.startsWith('LPA:')) {
|
|
12
|
+
input = input.substring(4);
|
|
13
|
+
}
|
|
14
|
+
const parts = input.split('$');
|
|
15
|
+
if (parts.length < 3) {
|
|
16
|
+
throw new ActivationCodeError('Activation code must have at least format, address, and matching ID');
|
|
17
|
+
}
|
|
18
|
+
const format = parseInt(parts[0], 10);
|
|
19
|
+
if (format !== 1) {
|
|
20
|
+
throw new ActivationCodeError(`Unsupported activation code format: ${format}`);
|
|
21
|
+
}
|
|
22
|
+
const smdpAddress = parts[1];
|
|
23
|
+
if (!smdpAddress) {
|
|
24
|
+
throw new ActivationCodeError('SM-DP+ address is required');
|
|
25
|
+
}
|
|
26
|
+
const matchingId = parts[2];
|
|
27
|
+
const smdpOid = parts.length > 3 && parts[3] ? parts[3] : undefined;
|
|
28
|
+
const confirmationCodeRequired = parts.length > 4 && parts[4] === '1';
|
|
29
|
+
return {
|
|
30
|
+
format,
|
|
31
|
+
smdpAddress,
|
|
32
|
+
matchingId,
|
|
33
|
+
smdpOid,
|
|
34
|
+
confirmationCodeRequired,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
export function isValidActivationCode(code) {
|
|
38
|
+
try {
|
|
39
|
+
parseActivationCode(code);
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
export function formatActivationCode(params) {
|
|
47
|
+
let code = `1$${params.smdpAddress}$${params.matchingId}`;
|
|
48
|
+
if (params.smdpOid || params.confirmationCodeRequired) {
|
|
49
|
+
code += `$${params.smdpOid ?? ''}`;
|
|
50
|
+
}
|
|
51
|
+
if (params.confirmationCodeRequired) {
|
|
52
|
+
code += '$1';
|
|
53
|
+
}
|
|
54
|
+
return code;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=activation-code.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"activation-code.js","sourceRoot":"","sources":["../src/activation-code.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAGlD;;;;;GAKG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,+BAA+B;IAC/B,IAAI,KAAK,GAAG,IAAI,CAAC;IACjB,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;IAC7B,CAAC;IAED,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,MAAM,IAAI,mBAAmB,CAAC,qEAAqE,CAAC,CAAC;IACvG,CAAC;IAED,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,CAAC,EAAE,CAAC;QACjB,MAAM,IAAI,mBAAmB,CAAC,uCAAuC,MAAM,EAAE,CAAC,CAAC;IACjF,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAC7B,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,mBAAmB,CAAC,4BAA4B,CAAC,CAAC;IAC9D,CAAC;IAED,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;IAE5B,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IACpE,MAAM,wBAAwB,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC;IAEtE,OAAO;QACL,MAAM;QACN,WAAW;QACX,UAAU;QACV,OAAO;QACP,wBAAwB;KACzB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,IAAI,CAAC;QACH,mBAAmB,CAAC,IAAI,CAAC,CAAC;QAC1B,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,MAAsC;IACzE,IAAI,IAAI,GAAG,KAAK,MAAM,CAAC,WAAW,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;IAC1D,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,wBAAwB,EAAE,CAAC;QACtD,IAAI,IAAI,IAAI,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;IACrC,CAAC;IACD,IAAI,MAAM,CAAC,wBAAwB,EAAE,CAAC;QACpC,IAAI,IAAI,IAAI,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/apdu.d.ts
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { DeviceAdapter } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* APDU transport layer — handles logical channel management, STORE DATA
|
|
4
|
+
* chunking, GET RESPONSE chaining, and BPP segmentation over a DeviceAdapter
|
|
5
|
+
* that sends individual APDUs.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ApduTransport {
|
|
8
|
+
private device;
|
|
9
|
+
private channel;
|
|
10
|
+
constructor(device: DeviceAdapter);
|
|
11
|
+
/**
|
|
12
|
+
* Send a complete SGP.22 TLV payload to the eUICC and return the complete
|
|
13
|
+
* TLV response. Handles STORE DATA chunking and GET RESPONSE chaining.
|
|
14
|
+
*/
|
|
15
|
+
sendCommand(data: Uint8Array): Promise<Uint8Array>;
|
|
16
|
+
/**
|
|
17
|
+
* Load BPP per SGP.22 Section 2.5.5 Segmented BPP loading.
|
|
18
|
+
*
|
|
19
|
+
* Segmentation order:
|
|
20
|
+
* 1. BF36 header + BF23 (InitialiseSecureChannel)
|
|
21
|
+
* 2. A0 complete (firstSequenceOf87)
|
|
22
|
+
* 3. A1 header only (sequenceOf88)
|
|
23
|
+
* 4. Each 88 TLV individually
|
|
24
|
+
* 5. A2 complete if present (secondSequenceOf87)
|
|
25
|
+
* 6. A3 header only (sequenceOf86)
|
|
26
|
+
* 7. Each 86 TLV individually
|
|
27
|
+
*
|
|
28
|
+
* Critical: P1=0x91 only on the VERY LAST APDU of entire BPP.
|
|
29
|
+
* Block number (P2) resets at each segment boundary.
|
|
30
|
+
*/
|
|
31
|
+
loadBoundProfilePackage(bpp: Uint8Array): Promise<Uint8Array | undefined>;
|
|
32
|
+
/**
|
|
33
|
+
* Build Segment 1: BF36 header (tag+length) + complete BF23
|
|
34
|
+
*/
|
|
35
|
+
private buildBppSegment1;
|
|
36
|
+
/**
|
|
37
|
+
* Build sequence header (tag+length only, no children)
|
|
38
|
+
*/
|
|
39
|
+
private buildSequenceHeader;
|
|
40
|
+
/**
|
|
41
|
+
* Send BPP segments with correct P1 handling:
|
|
42
|
+
* - P1=0x11 for all APDUs except the very last
|
|
43
|
+
* - P1=0x91 only on the VERY LAST APDU of the entire BPP
|
|
44
|
+
* - P2 resets at each segment boundary
|
|
45
|
+
*
|
|
46
|
+
* Returns the ProfileInstallationResult (BF37) from the last APDU response.
|
|
47
|
+
*/
|
|
48
|
+
private sendBppSegments;
|
|
49
|
+
/**
|
|
50
|
+
* Check if BPP response data contains a ProfileInstallationResult (BF37).
|
|
51
|
+
* Returns true if BF37 is detected (caller should stop sending and return the data).
|
|
52
|
+
*/
|
|
53
|
+
private isBppResult;
|
|
54
|
+
/**
|
|
55
|
+
* Close the logical channel if open.
|
|
56
|
+
*/
|
|
57
|
+
close(): Promise<void>;
|
|
58
|
+
private ensureChannel;
|
|
59
|
+
private openChannel;
|
|
60
|
+
private selectIsdR;
|
|
61
|
+
private closeChannel;
|
|
62
|
+
private closeAllChannels;
|
|
63
|
+
/**
|
|
64
|
+
* GlobalPlatform CLA byte for the current logical channel.
|
|
65
|
+
*/
|
|
66
|
+
private gpCla;
|
|
67
|
+
/**
|
|
68
|
+
* Send data via STORE DATA chunking and collect the response via
|
|
69
|
+
* GET RESPONSE chaining.
|
|
70
|
+
*/
|
|
71
|
+
private storeDataAndGetResponse;
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=apdu.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apdu.d.ts","sourceRoot":"","sources":["../src/apdu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAmBhD;;;;GAIG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAgB;IAC9B,OAAO,CAAC,OAAO,CAAM;gBAET,MAAM,EAAE,aAAa;IAIjC;;;OAGG;IACG,WAAW,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC;IAKxD;;;;;;;;;;;;;;OAcG;IACG,uBAAuB,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC;IAmE/E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAYxB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAQ3B;;;;;;;OAOG;YACW,eAAe;IAiF7B;;;OAGG;IACH,OAAO,CAAC,WAAW;IAOnB;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YAWd,aAAa;YAiBb,WAAW;YAYX,UAAU;YAuBV,YAAY;YAKZ,gBAAgB;IAc9B;;OAEG;IACH,OAAO,CAAC,KAAK;IAIb;;;OAGG;YACW,uBAAuB;CAyEtC"}
|