1 /*
2  * Copyright (C) 2012 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define TRACE_TAG AUTH
18 
19 #include "sysdeps.h"
20 #include "adb_auth.h"
21 
22 #include <resolv.h>
23 #include <stdio.h>
24 #include <string.h>
25 
26 #include "cutils/list.h"
27 #include "cutils/sockets.h"
28 #include "mincrypt/rsa.h"
29 #include "mincrypt/sha.h"
30 
31 #include "adb.h"
32 #include "fdevent.h"
33 #include "transport.h"
34 
35 struct adb_public_key {
36     struct listnode node;
37     RSAPublicKey key;
38 };
39 
40 static const char *key_paths[] = {
41     "/adb_keys",
42     "/data/misc/adb/adb_keys",
43     NULL
44 };
45 
46 static fdevent listener_fde;
47 static fdevent framework_fde;
48 static int framework_fd = -1;
49 
50 static void usb_disconnected(void* unused, atransport* t);
51 static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
52 static atransport* usb_transport;
53 static bool needs_retry = false;
54 
read_keys(const char * file,struct listnode * list)55 static void read_keys(const char *file, struct listnode *list)
56 {
57     FILE *f;
58     char buf[MAX_PAYLOAD_V1];
59     char *sep;
60     int ret;
61 
62     f = fopen(file, "re");
63     if (!f) {
64         D("Can't open '%s'", file);
65         return;
66     }
67 
68     while (fgets(buf, sizeof(buf), f)) {
69         /* Allocate 4 extra bytes to decode the base64 data in-place */
70         auto key = reinterpret_cast<adb_public_key*>(
71             calloc(1, sizeof(adb_public_key) + 4));
72         if (key == nullptr) {
73             D("Can't malloc key");
74             break;
75         }
76 
77         sep = strpbrk(buf, " \t");
78         if (sep)
79             *sep = '\0';
80 
81         ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
82         if (ret != sizeof(key->key)) {
83             D("%s: Invalid base64 data ret=%d", file, ret);
84             free(key);
85             continue;
86         }
87 
88         if (key->key.len != RSANUMWORDS) {
89             D("%s: Invalid key len %d", file, key->key.len);
90             free(key);
91             continue;
92         }
93 
94         list_add_tail(list, &key->node);
95     }
96 
97     fclose(f);
98 }
99 
free_keys(struct listnode * list)100 static void free_keys(struct listnode *list)
101 {
102     struct listnode *item;
103 
104     while (!list_empty(list)) {
105         item = list_head(list);
106         list_remove(item);
107         free(node_to_item(item, struct adb_public_key, node));
108     }
109 }
110 
load_keys(struct listnode * list)111 static void load_keys(struct listnode *list)
112 {
113     const char* path;
114     const char** paths = key_paths;
115     struct stat buf;
116 
117     list_init(list);
118 
119     while ((path = *paths++)) {
120         if (!stat(path, &buf)) {
121             D("Loading keys from '%s'", path);
122             read_keys(path, list);
123         }
124     }
125 }
126 
adb_auth_generate_token(void * token,size_t token_size)127 int adb_auth_generate_token(void *token, size_t token_size)
128 {
129     FILE *f;
130     int ret;
131 
132     f = fopen("/dev/urandom", "re");
133     if (!f)
134         return 0;
135 
136     ret = fread(token, token_size, 1, f);
137 
138     fclose(f);
139     return ret * token_size;
140 }
141 
adb_auth_verify(uint8_t * token,uint8_t * sig,int siglen)142 int adb_auth_verify(uint8_t* token, uint8_t* sig, int siglen)
143 {
144     struct listnode *item;
145     struct listnode key_list;
146     int ret = 0;
147 
148     if (siglen != RSANUMBYTES)
149         return 0;
150 
151     load_keys(&key_list);
152 
153     list_for_each(item, &key_list) {
154         adb_public_key* key = node_to_item(item, struct adb_public_key, node);
155         ret = RSA_verify(&key->key, sig, siglen, token, SHA_DIGEST_SIZE);
156         if (ret)
157             break;
158     }
159 
160     free_keys(&key_list);
161 
162     return ret;
163 }
164 
usb_disconnected(void * unused,atransport * t)165 static void usb_disconnected(void* unused, atransport* t) {
166     D("USB disconnect");
167     usb_transport = NULL;
168     needs_retry = false;
169 }
170 
framework_disconnected()171 static void framework_disconnected() {
172     D("Framework disconnect");
173     fdevent_remove(&framework_fde);
174     framework_fd = -1;
175 }
176 
adb_auth_event(int fd,unsigned events,void *)177 static void adb_auth_event(int fd, unsigned events, void*) {
178     char response[2];
179     int ret;
180 
181     if (events & FDE_READ) {
182         ret = unix_read(fd, response, sizeof(response));
183         if (ret <= 0) {
184             framework_disconnected();
185         } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
186             if (usb_transport) {
187                 adb_auth_verified(usb_transport);
188             }
189         }
190     }
191 }
192 
adb_auth_confirm_key(unsigned char * key,size_t len,atransport * t)193 void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
194 {
195     char msg[MAX_PAYLOAD_V1];
196     int ret;
197 
198     if (!usb_transport) {
199         usb_transport = t;
200         t->AddDisconnect(&usb_disconnect);
201     }
202 
203     if (framework_fd < 0) {
204         D("Client not connected");
205         needs_retry = true;
206         return;
207     }
208 
209     if (key[len - 1] != '\0') {
210         D("Key must be a null-terminated string");
211         return;
212     }
213 
214     ret = snprintf(msg, sizeof(msg), "PK%s", key);
215     if (ret >= (signed)sizeof(msg)) {
216         D("Key too long. ret=%d", ret);
217         return;
218     }
219     D("Sending '%s'", msg);
220 
221     ret = unix_write(framework_fd, msg, ret);
222     if (ret < 0) {
223         D("Failed to write PK, errno=%d", errno);
224         return;
225     }
226 }
227 
adb_auth_listener(int fd,unsigned events,void * data)228 static void adb_auth_listener(int fd, unsigned events, void* data) {
229     sockaddr_storage addr;
230     socklen_t alen;
231     int s;
232 
233     alen = sizeof(addr);
234 
235     s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
236     if (s < 0) {
237         D("Failed to accept: errno=%d", errno);
238         return;
239     }
240 
241     if (framework_fd >= 0) {
242         LOG(WARNING) << "adb received framework auth socket connection again";
243         framework_disconnected();
244     }
245 
246     framework_fd = s;
247     fdevent_install(&framework_fde, framework_fd, adb_auth_event, nullptr);
248     fdevent_add(&framework_fde, FDE_READ);
249 
250     if (needs_retry) {
251         needs_retry = false;
252         send_auth_request(usb_transport);
253     }
254 }
255 
adbd_cloexec_auth_socket()256 void adbd_cloexec_auth_socket() {
257     int fd = android_get_control_socket("adbd");
258     if (fd == -1) {
259         D("Failed to get adbd socket");
260         return;
261     }
262     fcntl(fd, F_SETFD, FD_CLOEXEC);
263 }
264 
adbd_auth_init(void)265 void adbd_auth_init(void) {
266     int fd = android_get_control_socket("adbd");
267     if (fd == -1) {
268         D("Failed to get adbd socket");
269         return;
270     }
271 
272     if (listen(fd, 4) == -1) {
273         D("Failed to listen on '%d'", fd);
274         return;
275     }
276 
277     fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
278     fdevent_add(&listener_fde, FDE_READ);
279 }
280