Skip to content

Commit ad150d6

Browse files
committed
!
1 parent 37900b5 commit ad150d6

2 files changed

Lines changed: 543 additions & 329 deletions

File tree

esim/uicc-parameter/index.html

Lines changed: 14 additions & 329 deletions
Original file line numberDiff line numberDiff line change
@@ -4,339 +4,24 @@
44
<head>
55
<meta charset="utf-8" />
66
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7-
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/water.css@2/out/water.min.css">
7+
8+
<!-- Tailwind CSS -->
9+
<script src="https://cdn.tailwindcss.com"></script>
10+
11+
<!-- React -->
812
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
913
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
10-
<script crossorigin src="https://unpkg.com/@babel/standalone/babel.min.js"></script>
11-
12-
<style>
13-
label.config {
14-
display: flex;
15-
align-items: baseline;
16-
}
17-
label.config > div:first-child {
18-
padding-right: 0.5rem;
19-
}
20-
</style>
14+
15+
<!-- Flowbite -->
16+
<link href="https://cdn.jsdelivr.net/npm/flowbite@2.5.2/dist/flowbite.min.css" rel="stylesheet" />
17+
18+
<title>UICC system specific parameters generator</title>
2119
</head>
2220

23-
<body>
21+
<body class="bg-gray-50 dark:bg-gray-900">
2422
<div id="app"></div>
25-
<script type="text/babel">
26-
const params = new URLSearchParams(location.search);
27-
28-
const toHex = (val) => val.toString(16).padStart(2, "0").toUpperCase();
29-
const strToHexStream = (str) => str.split("").map((c) => c.charCodeAt(0).toString(16)).join("").toUpperCase();
30-
// expose to devtool
31-
window.toHex = toHex;
32-
window.strToHexStream = strToHexStream;
33-
34-
const copyToClipboard = (text) => {
35-
const p = document.createElement("p");
36-
p.style.opacity = "0";
37-
p.style.position = "absolute";
38-
p.style.top = "0";
39-
p.style.left = "0";
40-
document.body.appendChild(p);
41-
p.innerHTML = text;
42-
43-
let result;
44-
try {
45-
const range = document.createRange();
46-
range.selectNode(p);
47-
window.getSelection().removeAllRanges();
48-
window.getSelection().addRange(range);
49-
result = document.execCommand("copy");
50-
window.getSelection().removeAllRanges();
51-
} finally {
52-
document.body.removeChild(p);
53-
}
54-
return result;
55-
}
56-
57-
const App = (props) => {
58-
const [priority, setPriority] = React.useState(255);
59-
const [timer, setTimer] = React.useState(5);
60-
const [channel, setChannel] = React.useState(5);
61-
const [menuCount, setMenuCount] = React.useState(6);
62-
const [entryLabelLength, setEntryLabelLength] = React.useState(32);
63-
const [useUiccFs, setUseUiccFs] = React.useState((params.get("useuiccfs") == null) || (params.get("useuiccfs") === "true") || false);
64-
const [adf1Aid, setAdf1Aid] = React.useState(params.get("adf1aid") || "");
65-
66-
const [generatedUssp, setGeneratedUssp] = React.useState("");
67-
const [generatedUsspWithTag, setGeneratedUsspWithTag] = React.useState("");
68-
69-
const [ramQuota, setRAMQuota] = React.useState(1);
70-
const [nvramQuota, setNVRAMQuota] = React.useState(1);
71-
72-
const [generatedSspWithTag, setGeneratedSspWithTag] = React.useState("");
73-
74-
const [serverFQDN, setServerFQDN] = React.useState(params.get("serverfqdn") || "proxy.develop.sim-applet.com");
75-
const [serverPort, setServerPort] = React.useState(80);
76-
const [connectInterval, setConnectInterval] = React.useState("005132");
77-
const [encrypt, setEncrypt] = React.useState("01");
78-
const [strOemEncKey, setStrOemEncKey] = React.useState("PlsCngThisEncKey");
79-
const [hexOemEncKey, setHexOemEncKey] = React.useState(strToHexStream(strOemEncKey));
80-
const [oemEncKeyType, setOemEncKeyType] = React.useState("str");
81-
const [useDigestAuth, setUseDigestAuth] = React.useState(false);
82-
const [changeOemEncKey, setChangeOemEncKey] = React.useState(false);
83-
84-
const [generatedAsp, setGeneratedAsp] = React.useState("");
85-
const [generatedAspWithTag, setGeneratedAspWithTag] = React.useState("");
86-
87-
const generateSsp = () => {
88-
let ssp = "";
89-
ssp += "C702" + ramQuota.toString(16).padStart(4,"0")
90-
ssp += "C802" + nvramQuota.toString(16).padStart(4,"0")
91-
ssp = "EF" + toHex(ssp.length/2) + ssp;
92-
ssp = ssp.toUpperCase();
93-
94-
setGeneratedSspWithTag(ssp);
95-
}
96-
97-
const generateAsp = () => {
98-
let asp = "";
99-
asp += "80" + toHex(serverFQDN.length) + strToHexStream(serverFQDN)
100-
asp += "8102" + serverPort.toString(16).padStart(4,"0")
101-
if (changeOemEncKey) {
102-
if (oemEncKeyType === "hex") {
103-
asp += "82" + toHex(hexOemEncKey.length/2) + hexOemEncKey;
104-
} else {
105-
const tmpOemEncKey = strToHexStream(strOemEncKey);
106-
asp += "82" + toHex(tmpOemEncKey.length/2) + tmpOemEncKey;
107-
}
108-
}
109-
asp += "8303" + connectInterval;
110-
asp += "8401" + encrypt;
111-
asp = asp.toUpperCase();
112-
setGeneratedAsp(asp);
113-
114-
asp = "C9" + toHex(asp.length/2) + asp
115-
setGeneratedAspWithTag(asp);
116-
}
117-
118-
const generateUssp = () => {
119-
let ussp = "";
120-
121-
ussp += "80"; // Tag of **UICC Toolkit** Application specific parameters field
122-
123-
let utasp = "";
124-
utasp += toHex(priority); // Priority level of the Toolkit application instance
125-
utasp += toHex(timer); // Maximum number of timers allowed for this application instance
126-
utasp += toHex(entryLabelLength); // Maximum text length for a menu entry
127-
utasp += toHex(menuCount); // Maximum number of menu entries allowed for this application instance
128-
for (let i = 0; i < menuCount; i++) {
129-
utasp += toHex(i+1); // Position of the n-th menu entry
130-
utasp += "00"; // Identifier of the n-th menu entry ('00' means do not care)
131-
}
132-
utasp += toHex(channel); // Maximum number of channels for this application instance
133-
utasp += "00"; // Length of Minimum Security Level field
134-
135-
ussp += toHex(utasp.length / 2); // Length of UICC Toolkit Application specific parameters field
136-
ussp += utasp;
137-
138-
if (useUiccFs) {
139-
ussp += "81"; // Tag of **UICC Access** Application specific parameters field
140-
141-
let uiccFs = "";
142-
uiccFs += "00"; // Length of UICC file system AID
143-
uiccFs += "01"; // Length of Access Domain for UICC file system
144-
uiccFs += "00"; // Access Domain for UICC file system
145-
uiccFs += "00"; // Length of Access Domain DAP
146-
uiccFs += toHex(adf1Aid.length / 2); // Length of ADF#1 AID
147-
uiccFs += adf1Aid;
148-
uiccFs += "01"; // Length of Access Domain for ADF#1
149-
uiccFs += "00"; // Access Domain for ADF#1
150-
uiccFs += "00"; // Length of Access Domain DAP#1
151-
152-
ussp += toHex(uiccFs.length / 2); // Length of UICC Access Application specific parameters field
153-
ussp += uiccFs;
154-
}
155-
ussp = ussp.toUpperCase();
156-
157-
setGeneratedUssp(ussp);
158-
159-
let usspWithTag = "EA" + toHex(ussp.length/2) + ussp;
160-
setGeneratedUsspWithTag(usspWithTag);
161-
162-
}
163-
164-
React.useEffect(() => {
165-
generateUssp();
166-
generateSsp();
167-
generateAsp();
168-
}, [priority, timer, channel, menuCount, entryLabelLength, useUiccFs, adf1Aid,
169-
ramQuota, nvramQuota,
170-
serverFQDN, serverPort, connectInterval, encrypt, hexOemEncKey, strOemEncKey, useDigestAuth, changeOemEncKey]);
171-
172-
React.useEffect(() => {
173-
if (oemEncKeyType === "hex") {
174-
setHexOemEncKey(strToHexStream(strOemEncKey));
175-
} else {
176-
setStrOemEncKey(hexOemEncKey.match(/.{1,2}/g)?.map((hex) => String.fromCharCode(parseInt(hex, 16))).join("") || "");
177-
}
178-
}, [oemEncKeyType]);
179-
180-
const gpParams = generatedAspWithTag + generatedSspWithTag + generatedUsspWithTag;
181-
182-
return (
183-
<div>
184-
<h1>UICC system specific parameters generator</h1>
185-
186-
<h2>設定</h2>
187-
<div>
188-
<label className="config">
189-
<div>Toolkit アプリケーション インスタンスの優先度: </div>
190-
<div>
191-
<input type="number" value={priority} onChange={(e) => setPriority(parseInt(e.target.value, 10))} min={0} max={255} />
192-
</div>
193-
</label>
194-
<label className="config">
195-
<div>タイマーの数: </div>
196-
<div>
197-
<input type="number" value={timer} onChange={(e) => setTimer(parseInt(e.target.value, 10))} min={0} max={255} />
198-
</div>
199-
</label>
200-
<label className="config">
201-
<div>チャネルの数: </div>
202-
<div>
203-
<input type="number" value={channel} onChange={(e) => setChannel(parseInt(e.target.value, 10))} min={0} max={255} />
204-
</div>
205-
</label>
206-
<label className="config">
207-
<div>メニューに表示するエントリーの数: </div>
208-
<div>
209-
<input type="number" value={menuCount} onChange={(e) => setMenuCount(parseInt(e.target.value, 10))} min={0} max={255} />
210-
</div>
211-
</label>
212-
<label className="config">
213-
<div>メニュー エントリーの文字数: </div>
214-
<div>
215-
<input type="number" value={entryLabelLength} onChange={(e) => setEntryLabelLength(parseInt(e.target.value, 10))} min={0} max={255} />
216-
</div>
217-
</label>
218-
<label className="config">
219-
<div>
220-
<input type="checkbox" checked={useUiccFs} onChange={(e) => setUseUiccFs(e.target.checked)} />
221-
</div>
222-
<div>UICC AIDファイルシステムを使用する</div>
223-
</label>
224-
{useUiccFs && (
225-
<>
226-
<label className="config">
227-
<div>ADF#1 AID (hex): </div>
228-
<div style={{ flex: 1 }}>
229-
<input style={{ width: "80%" }} value={adf1Aid} onChange={(e) => setAdf1Aid(e.target.value)} />
230-
</div>
231-
</label>
232-
</>
233-
)}
234-
</div>
235-
236-
<h2>設定(System Specific Parameters)</h2>
237-
<div>
238-
<label className="config">
239-
<div>Volatile Memory Quota(C7): </div>
240-
<div>
241-
<input type="number" value={ramQuota} onChange={(e) => setRAMQuota(parseInt(e.target.value, 10))} min={0} max={65535} />
242-
</div>
243-
</label>
244-
<label className="config">
245-
<div>Nonv-volatile Memory Quota(C8): </div>
246-
<div>
247-
<input type="number" value={nvramQuota} onChange={(e) => setNVRAMQuota(parseInt(e.target.value, 10))} min={0} max={65535} />
248-
</div>
249-
</label>
250-
</div>
251-
252-
<h2>設定(Application Specific Parameters)</h2>
253-
<div>
254-
<label className="config">
255-
<div>(tag80)server FQDN: </div>
256-
<div style={{ flex: 1 }}>
257-
<input style={{ width: "80%" }} value={serverFQDN} maxLength="127" onChange={(e) => setServerFQDN(e.target.value) } />
258-
</div>
259-
</label>
260-
<label className="config">
261-
<div>(tag81)Port: </div>
262-
<div>
263-
<input type="number" value={serverPort} onChange={(e) => setServerPort(parseInt(e.target.value, 10))} min={1} max={65535} />
264-
</div>
265-
</label>
266-
<label className="config">
267-
<div>
268-
<input type="checkbox" checked={changeOemEncKey} onChange={(e) => setChangeOemEncKey(e.target.checked)} />
269-
</div>
270-
<div>(tag82)OEMEncKeyを指定する</div>
271-
</label>
272-
<div style={{ marginLeft: "2rem", marginBottom: "0.5rem" }}><i>※telemetryの暗号化 と ダイジェスト認証時のPW として使用します</i></div>
273-
{changeOemEncKey && (
274-
<label className="config" style={{ marginLeft: "2rem", marginBottom: "0.5rem" }}>
275-
<div>OEMEncKey: </div>
276-
{["str", "hex"].map(type => {
277-
return (
278-
<label style={{ marginRight: "0.5rem" }}>
279-
<input type="radio" value={type} checked={type === oemEncKeyType} onChange={(e) => setOemEncKeyType(e.target.value)}/>
280-
<span>{type}</span>
281-
</label>
282-
)
283-
})}
284-
<div style={{ flex: 1, display: "flex", alignItems: "baseline" }}>
285-
{oemEncKeyType === "hex" ? (
286-
<>
287-
<input style={{ width: "80%" }} value={hexOemEncKey} onChange={(e) => setHexOemEncKey(e.target.value) } />
288-
<span style={{ color: hexOemEncKey.length === 32 ? "inherit" : "red" }}> {hexOemEncKey.length}/32</span>
289-
</>
290-
) : (
291-
<>
292-
<input style={{ width: "80%" }} value={strOemEncKey} onChange={(e) => setStrOemEncKey(e.target.value) } />
293-
<span style={{ color: strOemEncKey.length === 16 ? "inherit" : "red" }}> {strOemEncKey.length}/16</span>
294-
</>
295-
)}
296-
</div>
297-
</label>
298-
)}
299-
<label className="config">
300-
<div>(tag83)接続間隔: </div>
301-
<div>
302-
<input type="text" value={connectInterval} onChange={(e) => setConnectInterval(e.target.value)} pattern="\d{6}" maxLength="6" />
303-
</div><div>hHmMsS(例:15分23秒)</div>
304-
</label>
305-
306-
<label className="config">
307-
<div>
308-
<input type="checkbox" checked={encrypt === "01"} onChange={(e) => setEncrypt(e.target.checked ? "01" : "00")} />
309-
</div>
310-
<div>(tag84)テレメトリデータを暗号化する</div>
311-
</label>
312-
</div>
313-
314-
<h2>UICC_SYSTEM_SPECIFIC_PARAMETERS</h2>
315-
<code>{generatedUssp}</code>
316-
<div style={{ display: "flex", justifyContent: "end", marginTop: "0.5rem" }}>
317-
<button onClick={() => copyToClipboard(generatedUssp)}>クリップボードにコピー</button>
318-
</div>
319-
320-
<h2>APP_SPECIFIC_PARAMETERS (STORE DATA)</h2>
321-
<code>{generatedAsp}</code>
322-
<div style={{ display: "flex", justifyContent: "end", marginTop: "0.5rem" }}>
323-
<button onClick={() => copyToClipboard(generatedAsp)}>クリップボードにコピー</button>
324-
</div>
325-
326-
<h2>--params for GlobalPlatformPro (C9)</h2>
327-
<code>{gpParams}</code>
328-
<div style={{ display: "flex", justifyContent: "end", marginTop: "0.5rem" }}>
329-
<div>
330-
<div style={{ display: "flex", justifyContent: "end", color: gpParams.length > 255 ? "red" : "inherit", marginBottom: "0.5rem" }}>{gpParams.length}/255</div>
331-
<button onClick={() => copyToClipboard(gpParams)} disabled={gpParams.length > 255}>クリップボードにコピー</button>
332-
</div>
333-
</div>
334-
</div>
335-
);
336-
};
337-
338-
ReactDOM.createRoot(document.querySelector("#app")).render(<App />);
339-
</script>
23+
<script type="module" src="./script.mjs"></script>
24+
<script src="https://cdn.jsdelivr.net/npm/flowbite@2.5.2/dist/flowbite.min.js"></script>
34025
</body>
34126

342-
</html>
27+
</html>

0 commit comments

Comments
 (0)