@yume-chan/adb 0.0.20 → 0.0.22
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/CHANGELOG.json +45 -0
- package/CHANGELOG.md +22 -1
- package/README.md +46 -364
- package/esm/adb.d.ts +9 -5
- package/esm/adb.d.ts.map +1 -1
- package/esm/adb.js +21 -11
- package/esm/adb.js.map +1 -1
- package/esm/banner.d.ts.map +1 -1
- package/esm/banner.js +1 -1
- package/esm/banner.js.map +1 -1
- package/esm/commands/base.d.ts.map +1 -1
- package/esm/commands/base.js.map +1 -1
- package/esm/commands/framebuffer.d.ts +9 -0
- package/esm/commands/framebuffer.d.ts.map +1 -1
- package/esm/commands/framebuffer.js +27 -3
- package/esm/commands/framebuffer.js.map +1 -1
- package/esm/commands/power.d.ts.map +1 -1
- package/esm/commands/power.js.map +1 -1
- package/esm/commands/reverse.d.ts.map +1 -1
- package/esm/commands/reverse.js.map +1 -1
- package/esm/commands/subprocess/command.d.ts +1 -1
- package/esm/commands/subprocess/command.d.ts.map +1 -1
- package/esm/commands/subprocess/command.js +15 -13
- package/esm/commands/subprocess/command.js.map +1 -1
- package/esm/commands/subprocess/protocols/none.d.ts +2 -1
- package/esm/commands/subprocess/protocols/none.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/none.js +11 -14
- package/esm/commands/subprocess/protocols/none.js.map +1 -1
- package/esm/commands/subprocess/protocols/shell.d.ts.map +1 -1
- package/esm/commands/subprocess/protocols/shell.js +21 -17
- package/esm/commands/subprocess/protocols/shell.js.map +1 -1
- package/esm/commands/subprocess/utils.js.map +1 -1
- package/esm/commands/sync/list.d.ts +2 -1
- package/esm/commands/sync/list.d.ts.map +1 -1
- package/esm/commands/sync/list.js +2 -2
- package/esm/commands/sync/list.js.map +1 -1
- package/esm/commands/sync/pull.d.ts.map +1 -1
- package/esm/commands/sync/pull.js +4 -0
- package/esm/commands/sync/pull.js.map +1 -1
- package/esm/commands/sync/push.js +1 -1
- package/esm/commands/sync/push.js.map +1 -1
- package/esm/commands/sync/request.js +1 -1
- package/esm/commands/sync/request.js.map +1 -1
- package/esm/commands/sync/response.d.ts +3 -1
- package/esm/commands/sync/response.d.ts.map +1 -1
- package/esm/commands/sync/response.js +5 -3
- package/esm/commands/sync/response.js.map +1 -1
- package/esm/commands/sync/socket.d.ts +1 -1
- package/esm/commands/sync/socket.d.ts.map +1 -1
- package/esm/commands/sync/socket.js +7 -3
- package/esm/commands/sync/socket.js.map +1 -1
- package/esm/commands/sync/stat.js +2 -2
- package/esm/commands/sync/stat.js.map +1 -1
- package/esm/commands/sync/sync.d.ts +15 -0
- package/esm/commands/sync/sync.d.ts.map +1 -1
- package/esm/commands/sync/sync.js +17 -2
- package/esm/commands/sync/sync.js.map +1 -1
- package/esm/commands/tcpip.d.ts +21 -0
- package/esm/commands/tcpip.d.ts.map +1 -1
- package/esm/commands/tcpip.js +18 -0
- package/esm/commands/tcpip.js.map +1 -1
- package/esm/daemon/auth.d.ts +11 -9
- package/esm/daemon/auth.d.ts.map +1 -1
- package/esm/daemon/auth.js +21 -12
- package/esm/daemon/auth.js.map +1 -1
- package/esm/daemon/crypto.js +2 -2
- package/esm/daemon/crypto.js.map +1 -1
- package/esm/daemon/dispatcher.d.ts +6 -5
- package/esm/daemon/dispatcher.d.ts.map +1 -1
- package/esm/daemon/dispatcher.js +69 -58
- package/esm/daemon/dispatcher.js.map +1 -1
- package/esm/daemon/packet.d.ts +5 -5
- package/esm/daemon/packet.d.ts.map +1 -1
- package/esm/daemon/packet.js +2 -2
- package/esm/daemon/packet.js.map +1 -1
- package/esm/daemon/socket.d.ts +7 -14
- package/esm/daemon/socket.d.ts.map +1 -1
- package/esm/daemon/socket.js +58 -46
- package/esm/daemon/socket.js.map +1 -1
- package/esm/daemon/transport.d.ts +16 -4
- package/esm/daemon/transport.d.ts.map +1 -1
- package/esm/daemon/transport.js +11 -7
- package/esm/daemon/transport.js.map +1 -1
- package/esm/features.js +1 -1
- package/esm/features.js.map +1 -1
- package/esm/server/client.d.ts +12 -8
- package/esm/server/client.d.ts.map +1 -1
- package/esm/server/client.js +41 -22
- package/esm/server/client.js.map +1 -1
- package/esm/server/transport.d.ts.map +1 -1
- package/esm/server/transport.js.map +1 -1
- package/esm/utils/auto-reset-event.d.ts.map +1 -1
- package/esm/utils/auto-reset-event.js.map +1 -1
- package/esm/utils/base64.js.map +1 -1
- package/esm/utils/conditional-variable.d.ts.map +1 -1
- package/esm/utils/conditional-variable.js.map +1 -1
- package/esm/utils/hex.js.map +1 -1
- package/package.json +13 -14
- package/src/adb.ts +49 -35
- package/src/banner.ts +7 -7
- package/src/commands/base.ts +1 -1
- package/src/commands/framebuffer.ts +31 -3
- package/src/commands/power.ts +9 -9
- package/src/commands/reverse.ts +13 -13
- package/src/commands/subprocess/command.ts +24 -25
- package/src/commands/subprocess/protocols/none.ts +23 -27
- package/src/commands/subprocess/protocols/shell.ts +42 -37
- package/src/commands/sync/list.ts +11 -7
- package/src/commands/sync/pull.ts +7 -4
- package/src/commands/sync/push.ts +6 -6
- package/src/commands/sync/request.ts +3 -3
- package/src/commands/sync/response.ts +8 -6
- package/src/commands/sync/socket.ts +19 -14
- package/src/commands/sync/stat.ts +5 -5
- package/src/commands/sync/sync.ts +32 -17
- package/src/commands/tcpip.ts +46 -2
- package/src/daemon/auth.ts +49 -30
- package/src/daemon/crypto.ts +9 -9
- package/src/daemon/dispatcher.ts +104 -88
- package/src/daemon/packet.ts +2 -2
- package/src/daemon/socket.ts +106 -115
- package/src/daemon/transport.ts +49 -29
- package/src/server/client.ts +88 -77
- package/src/server/transport.ts +13 -13
- package/src/utils/auto-reset-event.ts +4 -4
- package/src/utils/base64.ts +5 -5
- package/src/utils/conditional-variable.ts +4 -4
- package/tsconfig.build.tsbuildinfo +1 -1
- package/esm/daemon/connection.d.ts +0 -11
- package/esm/daemon/connection.d.ts.map +0 -1
- package/esm/daemon/connection.js +0 -2
- package/esm/daemon/connection.js.map +0 -1
|
@@ -48,27 +48,27 @@ export class AdbSync extends AutoDisposable {
|
|
|
48
48
|
readonly #supportsSendReceiveV2: boolean;
|
|
49
49
|
readonly #needPushMkdirWorkaround: boolean;
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
get supportsStat(): boolean {
|
|
52
52
|
return this.#supportsStat;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
get supportsListV2(): boolean {
|
|
56
56
|
return this.#supportsListV2;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
get fixedPushMkdir(): boolean {
|
|
60
60
|
return this.#fixedPushMkdir;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
|
|
63
|
+
get supportsSendReceiveV2(): boolean {
|
|
64
64
|
return this.#supportsSendReceiveV2;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
get needPushMkdirWorkaround(): boolean {
|
|
68
68
|
return this.#needPushMkdirWorkaround;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
-
|
|
71
|
+
constructor(adb: Adb, socket: AdbSocket) {
|
|
72
72
|
super();
|
|
73
73
|
|
|
74
74
|
this._adb = adb;
|
|
@@ -78,7 +78,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
78
78
|
this.#supportsListV2 = adb.supportsFeature(AdbFeature.ListV2);
|
|
79
79
|
this.#fixedPushMkdir = adb.supportsFeature(AdbFeature.FixedPushMkdir);
|
|
80
80
|
this.#supportsSendReceiveV2 = adb.supportsFeature(
|
|
81
|
-
AdbFeature.SendReceiveV2
|
|
81
|
+
AdbFeature.SendReceiveV2,
|
|
82
82
|
);
|
|
83
83
|
// https://android.googlesource.com/platform/packages/modules/adb/+/91768a57b7138166e0a3d11f79cd55909dda7014/client/file_sync_client.cpp#1361
|
|
84
84
|
this.#needPushMkdirWorkaround =
|
|
@@ -86,19 +86,34 @@ export class AdbSync extends AutoDisposable {
|
|
|
86
86
|
!this.fixedPushMkdir;
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
|
|
90
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Gets information of a file or folder.
|
|
91
|
+
*
|
|
92
|
+
* If `path` points to a symbolic link, the returned information is about the link itself (with `type` being `LinuxFileType.Link`).
|
|
93
|
+
*/
|
|
94
|
+
async lstat(path: string): Promise<AdbSyncStat> {
|
|
95
|
+
return await adbSyncLstat(this._socket, path, this.#supportsStat);
|
|
91
96
|
}
|
|
92
97
|
|
|
93
|
-
|
|
94
|
-
|
|
98
|
+
/**
|
|
99
|
+
* Gets the information of a file or folder.
|
|
100
|
+
*
|
|
101
|
+
* If `path` points to a symbolic link, it will be resolved and the returned information is about the target (with `type` being `LinuxFileType.File` or `LinuxFileType.Directory`).
|
|
102
|
+
*/
|
|
103
|
+
async stat(path: string) {
|
|
104
|
+
if (!this.#supportsStat) {
|
|
95
105
|
throw new Error("Not supported");
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
return await adbSyncStat(this._socket, path);
|
|
99
109
|
}
|
|
100
110
|
|
|
101
|
-
|
|
111
|
+
/**
|
|
112
|
+
* Checks if `path` is a directory, or a symbolic link to a directory.
|
|
113
|
+
*
|
|
114
|
+
* This uses `lstat` internally, thus works on all Android versions.
|
|
115
|
+
*/
|
|
116
|
+
async isDirectory(path: string): Promise<boolean> {
|
|
102
117
|
try {
|
|
103
118
|
await this.lstat(path + "/");
|
|
104
119
|
return true;
|
|
@@ -107,11 +122,11 @@ export class AdbSync extends AutoDisposable {
|
|
|
107
122
|
}
|
|
108
123
|
}
|
|
109
124
|
|
|
110
|
-
|
|
125
|
+
opendir(path: string): AsyncGenerator<AdbSyncEntry, void, void> {
|
|
111
126
|
return adbSyncOpenDir(this._socket, path, this.supportsListV2);
|
|
112
127
|
}
|
|
113
128
|
|
|
114
|
-
|
|
129
|
+
async readdir(path: string) {
|
|
115
130
|
const results: AdbSyncEntry[] = [];
|
|
116
131
|
for await (const entry of this.opendir(path)) {
|
|
117
132
|
results.push(entry);
|
|
@@ -125,7 +140,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
125
140
|
* @param filename The full path of the file on device to read.
|
|
126
141
|
* @returns A `ReadableStream` that contains the file content.
|
|
127
142
|
*/
|
|
128
|
-
|
|
143
|
+
read(filename: string): ReadableStream<Uint8Array> {
|
|
129
144
|
return adbSyncPull(this._socket, filename);
|
|
130
145
|
}
|
|
131
146
|
|
|
@@ -134,7 +149,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
134
149
|
*
|
|
135
150
|
* @param options The content and options of the file to write.
|
|
136
151
|
*/
|
|
137
|
-
|
|
152
|
+
async write(options: AdbSyncWriteOptions): Promise<void> {
|
|
138
153
|
if (this.needPushMkdirWorkaround) {
|
|
139
154
|
// It may fail if the path is already existed.
|
|
140
155
|
// Ignore the result.
|
|
@@ -153,7 +168,7 @@ export class AdbSync extends AutoDisposable {
|
|
|
153
168
|
});
|
|
154
169
|
}
|
|
155
170
|
|
|
156
|
-
|
|
171
|
+
override async dispose() {
|
|
157
172
|
super.dispose();
|
|
158
173
|
await this._socket.close();
|
|
159
174
|
}
|
package/src/commands/tcpip.ts
CHANGED
|
@@ -1,7 +1,51 @@
|
|
|
1
1
|
import { AdbCommandBase } from "./base.js";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* ADB daemon checks for the following properties in the order of
|
|
5
|
+
*
|
|
6
|
+
* * `serviceListenAddresses` (`service.adb.listen_addrs`)
|
|
7
|
+
* * `servicePort` (`service.adb.tcp.port`)
|
|
8
|
+
* * `persistPort` (`persist.adb.tcp.port`)
|
|
9
|
+
*
|
|
10
|
+
* Once it finds a non-empty value, it will use it and ignore the rest.
|
|
11
|
+
*
|
|
12
|
+
* `serviceListenAddresses` and `persistPort` are fixed at build time,
|
|
13
|
+
* only `servicePort` can be changed using `setPort` and `disable`.
|
|
14
|
+
* This means if either `serviceListenAddresses` or `persistPort` is non-empty,
|
|
15
|
+
* ADB over WiFi is always enabled.
|
|
16
|
+
*/
|
|
17
|
+
export interface AdbTcpIpListenAddresses {
|
|
18
|
+
serviceListenAddresses: string[];
|
|
19
|
+
servicePort: number | undefined;
|
|
20
|
+
persistPort: number | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
3
23
|
export class AdbTcpIpCommand extends AdbCommandBase {
|
|
4
|
-
|
|
24
|
+
#parsePort(value: string): number | undefined {
|
|
25
|
+
if (!value || value === "0") {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return Number.parseInt(value, 10);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async getListenAddresses(): Promise<AdbTcpIpListenAddresses> {
|
|
32
|
+
const serviceListenAddresses = await this.adb.getProp(
|
|
33
|
+
"service.adb.listen_addrs",
|
|
34
|
+
);
|
|
35
|
+
const servicePort = await this.adb.getProp("service.adb.tcp.port");
|
|
36
|
+
const persistPort = await this.adb.getProp("persist.adb.tcp.port");
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
serviceListenAddresses:
|
|
40
|
+
serviceListenAddresses != ""
|
|
41
|
+
? serviceListenAddresses.split(",")
|
|
42
|
+
: [],
|
|
43
|
+
servicePort: this.#parsePort(servicePort),
|
|
44
|
+
persistPort: this.#parsePort(persistPort),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
async setPort(port: number): Promise<string> {
|
|
5
49
|
if (port <= 0) {
|
|
6
50
|
throw new Error(`Invalid port ${port}`);
|
|
7
51
|
}
|
|
@@ -13,7 +57,7 @@ export class AdbTcpIpCommand extends AdbCommandBase {
|
|
|
13
57
|
return output;
|
|
14
58
|
}
|
|
15
59
|
|
|
16
|
-
|
|
60
|
+
async disable(): Promise<string> {
|
|
17
61
|
const output = await this.adb.createSocketAndWait("usb:");
|
|
18
62
|
if (output !== "restarting in USB mode\n") {
|
|
19
63
|
throw new Error(output);
|
package/src/daemon/auth.ts
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
import { PromiseResolver } from "@yume-chan/async";
|
|
2
2
|
import type { Disposable } from "@yume-chan/event";
|
|
3
3
|
import type { ValueOrPromise } from "@yume-chan/struct";
|
|
4
|
+
import { EMPTY_UINT8_ARRAY } from "@yume-chan/struct";
|
|
4
5
|
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
calculateBase64EncodedLength,
|
|
8
|
+
encodeBase64,
|
|
9
|
+
encodeUtf8,
|
|
10
|
+
} from "../utils/index.js";
|
|
6
11
|
|
|
7
12
|
import {
|
|
8
13
|
adbGeneratePublicKey,
|
|
@@ -12,18 +17,26 @@ import {
|
|
|
12
17
|
import type { AdbPacketData } from "./packet.js";
|
|
13
18
|
import { AdbCommand } from "./packet.js";
|
|
14
19
|
|
|
15
|
-
export
|
|
20
|
+
export interface AdbPrivateKey {
|
|
21
|
+
/**
|
|
22
|
+
* The private key in PKCS #8 format.
|
|
23
|
+
*/
|
|
24
|
+
buffer: Uint8Array;
|
|
25
|
+
name?: string | undefined;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export type AdbKeyIterable =
|
|
29
|
+
| Iterable<AdbPrivateKey>
|
|
30
|
+
| AsyncIterable<AdbPrivateKey>;
|
|
16
31
|
|
|
17
32
|
export interface AdbCredentialStore {
|
|
18
33
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* The returned `Uint8Array` is the private key in PKCS #8 format.
|
|
34
|
+
* Generates and stores a RSA private key with modulus length `2048` and public exponent `65537`.
|
|
22
35
|
*/
|
|
23
|
-
generateKey(): ValueOrPromise<
|
|
36
|
+
generateKey(): ValueOrPromise<AdbPrivateKey>;
|
|
24
37
|
|
|
25
38
|
/**
|
|
26
|
-
* Synchronously or asynchronously
|
|
39
|
+
* Synchronously or asynchronously iterates through all stored RSA private keys.
|
|
27
40
|
*
|
|
28
41
|
* Each call to `iterateKeys` must return a different iterator that iterate through all stored keys.
|
|
29
42
|
*/
|
|
@@ -50,13 +63,13 @@ export interface AdbAuthenticator {
|
|
|
50
63
|
*/
|
|
51
64
|
(
|
|
52
65
|
credentialStore: AdbCredentialStore,
|
|
53
|
-
getNextRequest: () => Promise<AdbPacketData
|
|
66
|
+
getNextRequest: () => Promise<AdbPacketData>,
|
|
54
67
|
): AsyncIterable<AdbPacketData>;
|
|
55
68
|
}
|
|
56
69
|
|
|
57
70
|
export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
|
|
58
71
|
credentialStore: AdbCredentialStore,
|
|
59
|
-
getNextRequest: () => Promise<AdbPacketData
|
|
72
|
+
getNextRequest: () => Promise<AdbPacketData>,
|
|
60
73
|
): AsyncIterable<AdbPacketData> {
|
|
61
74
|
for await (const key of credentialStore.iterateKeys()) {
|
|
62
75
|
const packet = await getNextRequest();
|
|
@@ -65,7 +78,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
|
|
|
65
78
|
return;
|
|
66
79
|
}
|
|
67
80
|
|
|
68
|
-
const signature = rsaSign(key, packet.payload);
|
|
81
|
+
const signature = rsaSign(key.buffer, packet.payload);
|
|
69
82
|
yield {
|
|
70
83
|
command: AdbCommand.Auth,
|
|
71
84
|
arg0: AdbAuthType.Signature,
|
|
@@ -77,7 +90,7 @@ export const AdbSignatureAuthenticator: AdbAuthenticator = async function* (
|
|
|
77
90
|
|
|
78
91
|
export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
79
92
|
credentialStore: AdbCredentialStore,
|
|
80
|
-
getNextRequest: () => Promise<AdbPacketData
|
|
93
|
+
getNextRequest: () => Promise<AdbPacketData>,
|
|
81
94
|
): AsyncIterable<AdbPacketData> {
|
|
82
95
|
const packet = await getNextRequest();
|
|
83
96
|
|
|
@@ -85,7 +98,7 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
|
85
98
|
return;
|
|
86
99
|
}
|
|
87
100
|
|
|
88
|
-
let privateKey:
|
|
101
|
+
let privateKey: AdbPrivateKey | undefined;
|
|
89
102
|
for await (const key of credentialStore.iterateKeys()) {
|
|
90
103
|
privateKey = key;
|
|
91
104
|
break;
|
|
@@ -99,13 +112,23 @@ export const AdbPublicKeyAuthenticator: AdbAuthenticator = async function* (
|
|
|
99
112
|
const [publicKeyBase64Length] =
|
|
100
113
|
calculateBase64EncodedLength(publicKeyLength);
|
|
101
114
|
|
|
115
|
+
const nameBuffer = privateKey.name?.length
|
|
116
|
+
? encodeUtf8(privateKey.name)
|
|
117
|
+
: EMPTY_UINT8_ARRAY;
|
|
102
118
|
const publicKeyBuffer = new Uint8Array(
|
|
103
|
-
publicKeyBase64Length +
|
|
119
|
+
publicKeyBase64Length +
|
|
120
|
+
(nameBuffer.length ? nameBuffer.length + 1 : 0) + // Space character + name
|
|
121
|
+
1, // Null character
|
|
104
122
|
);
|
|
105
123
|
|
|
106
|
-
adbGeneratePublicKey(privateKey, publicKeyBuffer);
|
|
124
|
+
adbGeneratePublicKey(privateKey.buffer, publicKeyBuffer);
|
|
107
125
|
encodeBase64(publicKeyBuffer.subarray(0, publicKeyLength), publicKeyBuffer);
|
|
108
126
|
|
|
127
|
+
if (nameBuffer.length) {
|
|
128
|
+
publicKeyBuffer[publicKeyBase64Length] = 0x20;
|
|
129
|
+
publicKeyBuffer.set(nameBuffer, publicKeyBase64Length + 1);
|
|
130
|
+
}
|
|
131
|
+
|
|
109
132
|
yield {
|
|
110
133
|
command: AdbCommand.Auth,
|
|
111
134
|
arg0: AdbAuthType.PublicKey,
|
|
@@ -120,34 +143,30 @@ export const ADB_DEFAULT_AUTHENTICATORS: AdbAuthenticator[] = [
|
|
|
120
143
|
];
|
|
121
144
|
|
|
122
145
|
export class AdbAuthenticationProcessor implements Disposable {
|
|
123
|
-
|
|
146
|
+
readonly authenticators: readonly AdbAuthenticator[];
|
|
124
147
|
|
|
125
|
-
|
|
148
|
+
readonly #credentialStore: AdbCredentialStore;
|
|
126
149
|
|
|
127
150
|
#pendingRequest = new PromiseResolver<AdbPacketData>();
|
|
128
151
|
#iterator: AsyncIterator<AdbPacketData, void, void> | undefined;
|
|
129
152
|
|
|
130
|
-
|
|
153
|
+
constructor(
|
|
131
154
|
authenticators: readonly AdbAuthenticator[],
|
|
132
|
-
credentialStore: AdbCredentialStore
|
|
155
|
+
credentialStore: AdbCredentialStore,
|
|
133
156
|
) {
|
|
134
157
|
this.authenticators = authenticators;
|
|
135
|
-
this
|
|
158
|
+
this.#credentialStore = credentialStore;
|
|
136
159
|
}
|
|
137
160
|
|
|
138
|
-
|
|
161
|
+
#getNextRequest = (): Promise<AdbPacketData> => {
|
|
139
162
|
return this.#pendingRequest.promise;
|
|
140
163
|
};
|
|
141
164
|
|
|
142
|
-
|
|
143
|
-
AdbPacketData,
|
|
144
|
-
void,
|
|
145
|
-
void
|
|
146
|
-
> {
|
|
165
|
+
async *#invokeAuthenticator(): AsyncGenerator<AdbPacketData, void, void> {
|
|
147
166
|
for (const authenticator of this.authenticators) {
|
|
148
167
|
for await (const packet of authenticator(
|
|
149
|
-
this
|
|
150
|
-
this
|
|
168
|
+
this.#credentialStore,
|
|
169
|
+
this.#getNextRequest,
|
|
151
170
|
)) {
|
|
152
171
|
// If the authenticator yielded a response
|
|
153
172
|
// Prepare `nextRequest` for next authentication request
|
|
@@ -162,9 +181,9 @@ export class AdbAuthenticationProcessor implements Disposable {
|
|
|
162
181
|
}
|
|
163
182
|
}
|
|
164
183
|
|
|
165
|
-
|
|
184
|
+
async process(packet: AdbPacketData): Promise<AdbPacketData> {
|
|
166
185
|
if (!this.#iterator) {
|
|
167
|
-
this.#iterator = this
|
|
186
|
+
this.#iterator = this.#invokeAuthenticator();
|
|
168
187
|
}
|
|
169
188
|
|
|
170
189
|
this.#pendingRequest.resolve(packet);
|
|
@@ -177,7 +196,7 @@ export class AdbAuthenticationProcessor implements Disposable {
|
|
|
177
196
|
return result.value;
|
|
178
197
|
}
|
|
179
198
|
|
|
180
|
-
|
|
199
|
+
dispose() {
|
|
181
200
|
void this.#iterator?.return?.();
|
|
182
201
|
}
|
|
183
202
|
}
|
package/src/daemon/crypto.ts
CHANGED
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
export function getBigUint(
|
|
14
14
|
dataView: DataView,
|
|
15
15
|
byteOffset: number,
|
|
16
|
-
length: number
|
|
16
|
+
length: number,
|
|
17
17
|
): bigint {
|
|
18
18
|
let result = 0n;
|
|
19
19
|
|
|
@@ -40,7 +40,7 @@ export function setBigUint(
|
|
|
40
40
|
dataView: DataView,
|
|
41
41
|
byteOffset: number,
|
|
42
42
|
value: bigint,
|
|
43
|
-
littleEndian?: boolean
|
|
43
|
+
littleEndian?: boolean,
|
|
44
44
|
) {
|
|
45
45
|
const start = byteOffset;
|
|
46
46
|
|
|
@@ -135,11 +135,11 @@ export function adbGetPublicKeySize() {
|
|
|
135
135
|
export function adbGeneratePublicKey(privateKey: Uint8Array): Uint8Array;
|
|
136
136
|
export function adbGeneratePublicKey(
|
|
137
137
|
privateKey: Uint8Array,
|
|
138
|
-
output: Uint8Array
|
|
138
|
+
output: Uint8Array,
|
|
139
139
|
): number;
|
|
140
140
|
export function adbGeneratePublicKey(
|
|
141
141
|
privateKey: Uint8Array,
|
|
142
|
-
output?: Uint8Array
|
|
142
|
+
output?: Uint8Array,
|
|
143
143
|
): Uint8Array | number {
|
|
144
144
|
// Android has its own public key generation algorithm
|
|
145
145
|
// See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#111
|
|
@@ -158,9 +158,6 @@ export function adbGeneratePublicKey(
|
|
|
158
158
|
// (All in little endian)
|
|
159
159
|
// See https://android.googlesource.com/platform/system/core.git/+/91784040db2b9273687f88d8b95f729d4a61ecc2/libcrypto_utils/android_pubkey.cpp#38
|
|
160
160
|
|
|
161
|
-
// extract `n` from private key
|
|
162
|
-
const [n] = rsaParsePrivateKey(privateKey);
|
|
163
|
-
|
|
164
161
|
let outputType: "Uint8Array" | "number";
|
|
165
162
|
const outputLength = adbGetPublicKeySize();
|
|
166
163
|
if (!output) {
|
|
@@ -177,7 +174,7 @@ export function adbGeneratePublicKey(
|
|
|
177
174
|
const outputView = new DataView(
|
|
178
175
|
output.buffer,
|
|
179
176
|
output.byteOffset,
|
|
180
|
-
output.byteLength
|
|
177
|
+
output.byteLength,
|
|
181
178
|
);
|
|
182
179
|
let outputOffset = 0;
|
|
183
180
|
|
|
@@ -185,6 +182,9 @@ export function adbGeneratePublicKey(
|
|
|
185
182
|
outputView.setUint32(outputOffset, 2048 / 8 / 4, true);
|
|
186
183
|
outputOffset += 4;
|
|
187
184
|
|
|
185
|
+
// extract `n` from private key
|
|
186
|
+
const [n] = rsaParsePrivateKey(privateKey);
|
|
187
|
+
|
|
188
188
|
// Calculate `n0inv`
|
|
189
189
|
// Don't know why need to multiply by -1
|
|
190
190
|
// Didn't exist in Android codebase
|
|
@@ -221,7 +221,7 @@ export function adbGeneratePublicKey(
|
|
|
221
221
|
export function powMod(
|
|
222
222
|
base: bigint,
|
|
223
223
|
exponent: bigint,
|
|
224
|
-
modulus: bigint
|
|
224
|
+
modulus: bigint,
|
|
225
225
|
): bigint {
|
|
226
226
|
if (modulus === 1n) {
|
|
227
227
|
return 0n;
|