• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# SE Access Development
2
3## Introduction
4An electronic device may have one or more secure elements (SEs), such as the embedded SE (eSE) and SIM card. Access control for SEs is implemented in accordance with the Global Platform Access Control (GPAC) specification.
5
6## When to Use
7An application may need to write data to an SE to emulate an NFC card on the device. The NFC card data may be stored on an eSE or a SIM card. Generally, SEs are preset with rules for access control. An application must have related permissions and can access an SE only after a successful permission verification.
8
9## Available APIs
10For details about the APIs and sample code, see [SE Management](../../reference/apis-connectivity-kit/js-apis-secureElement.md).
11
12The following table describes the APIs for SE access.
13
14| API                            | Description                                                                      |
15| ---------------------------------- | ------------------------------------------------------------------------------ |
16| createService(): Promise\<SEService>                    | Creates an **SEService** instance for connecting to all available SEs in the system.                                                               |
17| getReaders(): Reader[]                      | Obtains available SE readers, which include all the SEs on the device.                                                               |
18| openSession(): Session                 | Opens a session to connect to an SE in this reader. This API returns a session instance.                                                               |
19| openLogicalChannel(aid: number[]): Promise\<Channel>                  | Opens a logical channel. This API returns a logical channel instance.                                                               |
20| transmit(command: number[]): Promise\<number[]> | Transmits application protocol data units (APDUs) to this SE.                                                               |
21| close(): void | Closes this channel.                                                           |
22
23
24## How to Develop
25
26### Accessing an SE
271. Import related modules.
282. Check whether the device supports SEs.
293. Access an SE and read or write data.
304. Release channel resources.
31
32```ts
33import { omapi } from '@kit.ConnectivityKit';
34import { BusinessError } from '@kit.BasicServicesKit';
35import { hilog } from '@kit.PerformanceAnalysisKit';
36import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
37
38let seService : omapi.SEService;
39let seReaders : omapi.Reader[];
40let seSession : omapi.Session;
41let seChannel : omapi.Channel;
42let testSelectedAid : number[] = [0xA0, 0x00, 0x00, 0x00, 0x03, 0x10, 0x10];
43let p2 : number = 0x00;
44
45export default class EntryAbility extends UIAbility {
46  onCreate(want: Want, launchParam: AbilityConstant.LaunchParam) {
47    hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onCreate');
48
49    // Check whether the device supports SEs.
50    if (!canIUse("SystemCapability.Communication.SecureElement")) {
51      hilog.error(0x0000, 'testTag', 'secure element unavailable.');
52      return;
53    }
54    hilog.info(0x0000, 'testTag', 'secure element available.');
55    this.omaTest();
56  }
57
58  private async omaTest () {
59    // Create an SEService instance for SE access.
60    await omapi.createService().then((data) => {
61      if (data == undefined || !data.isConnected()) {
62        hilog.error(0x0000, 'testTag', 'secure element service disconnected.');
63        return;
64      }
65      seService = data;
66      hilog.info(0x0000, 'testTag', 'secure element service connected.');
67    }).catch((error: BusinessError) => {
68      hilog.error(0x0000, 'testTag', 'createService error %{public}s', JSON.stringify(error));
69      return;
70    });
71
72    // Obtain all supported readers on the device, that is, the list of all SEs.
73    try {
74      seReaders = seService.getReaders();
75    } catch (error) {
76      hilog.error(0x0000, 'testTag', 'getReaders error %{public}s', JSON.stringify(error));
77    }
78    if (seReaders == undefined || seReaders.length == 0) {
79      hilog.error(0x0000, 'testTag', 'no valid reader found.');
80      seService.shutdown();
81      return;
82    }
83
84    // Select an SE (eSE or SIM card) for access based on the service requirements.
85    let reader: (omapi.Reader | undefined);
86    for (let i = 0; i < seReaders.length; ++i) {
87      let r = seReaders[i];
88      // Distinguish the SE by name, for example, eSE or SIM.
89      if (r.getName().includes("SIM")) {
90        reader = r;
91        break;
92      }
93    }
94    if (reader == undefined) {
95      hilog.error(0x0000, 'testTag', 'no valid sim reader.');
96      seService.shutdown();
97      return;
98    }
99    hilog.info(0x0000, 'testTag', 'reader is %{public}s', reader?.getName());
100
101    // Open a session on a specified SE instance.
102    try {
103      seSession = reader?.openSession() as omapi.Session;
104    } catch (error) {
105      hilog.error(0x0000, 'testTag', 'openSession error %{public}s', JSON.stringify(error));
106    }
107    if (seSession == undefined) {
108      hilog.error(0x0000, 'testTag', 'seSession invalid.');
109      seService.shutdown();
110      return;
111    }
112
113    // Create a logical channel or basic channel via the session instance. Generally, the logical channel is used for access, as the basic channel may be restricted.
114    try {
115      // Change the value of testSelectedAid to the AID of the application that opens the logical channel.
116      seChannel = await seSession.openLogicalChannel(testSelectedAid, p2);
117    } catch (exception) {
118      hilog.error(0x0000, 'testTag', 'openLogicalChannel exception %{public}s', JSON.stringify(exception));
119    }
120
121    if (seChannel == undefined) {
122      hilog.error(0x0000, 'testTag', 'seChannel invalid.');
123      seService.shutdown();
124      return;
125    }
126
127    // Send APDUs to the SE over the logical channel. Set testApduData correctly based on actual service requirements, and ensue that the APDU format complies with the APDU specification.
128    let testApduData = [0x01, 0x02, 0x03, 0x04];
129    try {
130      let response: number[] = await seChannel.transmit(testApduData);
131      hilog.info(0x0000, 'testTag', 'seChannel.transmit() response = %{public}s.', JSON.stringify(response));
132    } catch (exception) {
133      hilog.error(0x0000, 'testTag', 'seChannel.transmit() exception = %{public}s.', JSON.stringify(exception));
134    }
135
136    // Close the channel to release resources when the SE access is complete.
137    try {
138      seChannel.close();
139    } catch (exception) {
140      hilog.error(0x0000, 'testTag', 'seChannel.close() exception = %{public}s.', JSON.stringify(exception));
141    }
142
143    // Close the service, and disable the binding relationship between the application and the SE service.
144    seService.shutdown();
145  }
146}
147
148```
149