• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include <stdio.h>
18 #include <string.h>
19 #include <resolv.h>
20 #include <cutils/list.h>
21 #include <cutils/sockets.h>
22 
23 #include "sysdeps.h"
24 #include "adb.h"
25 #include "adb_auth.h"
26 #include "fdevent.h"
27 #include "mincrypt/rsa.h"
28 
29 #define TRACE_TAG TRACE_AUTH
30 
31 
32 struct adb_public_key {
33     struct listnode node;
34     RSAPublicKey key;
35 };
36 
37 static char *key_paths[] = {
38     "/adb_keys",
39     "/data/misc/adb/adb_keys",
40     NULL
41 };
42 
43 static fdevent listener_fde;
44 static int framework_fd = -1;
45 
46 static void usb_disconnected(void* unused, atransport* t);
47 static struct adisconnect usb_disconnect = { usb_disconnected, 0, 0, 0 };
48 static atransport* usb_transport;
49 static bool needs_retry = false;
50 
read_keys(const char * file,struct listnode * list)51 static void read_keys(const char *file, struct listnode *list)
52 {
53     struct adb_public_key *key;
54     FILE *f;
55     char buf[MAX_PAYLOAD];
56     char *sep;
57     int ret;
58 
59     f = fopen(file, "r");
60     if (!f) {
61         D("Can't open '%s'\n", file);
62         return;
63     }
64 
65     while (fgets(buf, sizeof(buf), f)) {
66         /* Allocate 4 extra bytes to decode the base64 data in-place */
67         key = calloc(1, sizeof(*key) + 4);
68         if (!key) {
69             D("Can't malloc key\n");
70             break;
71         }
72 
73         sep = strpbrk(buf, " \t");
74         if (sep)
75             *sep = '\0';
76 
77         ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
78         if (ret != sizeof(key->key)) {
79             D("%s: Invalid base64 data ret=%d\n", file, ret);
80             free(key);
81             continue;
82         }
83 
84         if (key->key.len != RSANUMWORDS) {
85             D("%s: Invalid key len %d\n", file, key->key.len);
86             free(key);
87             continue;
88         }
89 
90         list_add_tail(list, &key->node);
91     }
92 
93     fclose(f);
94 }
95 
free_keys(struct listnode * list)96 static void free_keys(struct listnode *list)
97 {
98     struct listnode *item;
99 
100     while (!list_empty(list)) {
101         item = list_head(list);
102         list_remove(item);
103         free(node_to_item(item, struct adb_public_key, node));
104     }
105 }
106 
load_keys(struct listnode * list)107 static void load_keys(struct listnode *list)
108 {
109     char *path;
110     char **paths = key_paths;
111     struct stat buf;
112 
113     list_init(list);
114 
115     while ((path = *paths++)) {
116         if (!stat(path, &buf)) {
117             D("Loading keys from '%s'\n", path);
118             read_keys(path, list);
119         }
120     }
121 }
122 
adb_auth_generate_token(void * token,size_t token_size)123 int adb_auth_generate_token(void *token, size_t token_size)
124 {
125     FILE *f;
126     int ret;
127 
128     f = fopen("/dev/urandom", "r");
129     if (!f)
130         return 0;
131 
132     ret = fread(token, token_size, 1, f);
133 
134     fclose(f);
135     return ret * token_size;
136 }
137 
adb_auth_verify(void * token,void * sig,int siglen)138 int adb_auth_verify(void *token, void *sig, int siglen)
139 {
140     struct listnode *item;
141     struct adb_public_key *key;
142     struct listnode key_list;
143     int ret = 0;
144 
145     if (siglen != RSANUMBYTES)
146         return 0;
147 
148     load_keys(&key_list);
149 
150     list_for_each(item, &key_list) {
151         key = node_to_item(item, struct adb_public_key, node);
152         ret = RSA_verify(&key->key, sig, siglen, token);
153         if (ret)
154             break;
155     }
156 
157     free_keys(&key_list);
158 
159     return ret;
160 }
161 
usb_disconnected(void * unused,atransport * t)162 static void usb_disconnected(void* unused, atransport* t)
163 {
164     D("USB disconnect\n");
165     remove_transport_disconnect(usb_transport, &usb_disconnect);
166     usb_transport = NULL;
167     needs_retry = false;
168 }
169 
adb_auth_event(int fd,unsigned events,void * data)170 static void adb_auth_event(int fd, unsigned events, void *data)
171 {
172     char response[2];
173     int ret;
174 
175     if (events & FDE_READ) {
176         ret = unix_read(fd, response, sizeof(response));
177         if (ret < 0) {
178             D("Framework disconnect\n");
179             if (usb_transport)
180                 fdevent_remove(&usb_transport->auth_fde);
181             framework_fd = -1;
182         }
183         else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
184             if (usb_transport)
185                 adb_auth_verified(usb_transport);
186         }
187     }
188 }
189 
adb_auth_confirm_key(unsigned char * key,size_t len,atransport * t)190 void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
191 {
192     char msg[MAX_PAYLOAD];
193     int ret;
194 
195     if (!usb_transport) {
196         usb_transport = t;
197         add_transport_disconnect(t, &usb_disconnect);
198     }
199 
200     if (framework_fd < 0) {
201         D("Client not connected\n");
202         needs_retry = true;
203         return;
204     }
205 
206     if (key[len - 1] != '\0') {
207         D("Key must be a null-terminated string\n");
208         return;
209     }
210 
211     ret = snprintf(msg, sizeof(msg), "PK%s", key);
212     if (ret >= (signed)sizeof(msg)) {
213         D("Key too long. ret=%d", ret);
214         return;
215     }
216     D("Sending '%s'\n", msg);
217 
218     ret = unix_write(framework_fd, msg, ret);
219     if (ret < 0) {
220         D("Failed to write PK, errno=%d\n", errno);
221         return;
222     }
223 
224     fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);
225     fdevent_add(&t->auth_fde, FDE_READ);
226 }
227 
adb_auth_listener(int fd,unsigned events,void * data)228 static void adb_auth_listener(int fd, unsigned events, void *data)
229 {
230     struct sockaddr addr;
231     socklen_t alen;
232     int s;
233 
234     alen = sizeof(addr);
235 
236     s = adb_socket_accept(fd, &addr, &alen);
237     if (s < 0) {
238         D("Failed to accept: errno=%d\n", errno);
239         return;
240     }
241 
242     framework_fd = s;
243 
244     if (needs_retry) {
245         needs_retry = false;
246         send_auth_request(usb_transport);
247     }
248 }
249 
adb_auth_init(void)250 void adb_auth_init(void)
251 {
252     int fd, ret;
253 
254     fd = android_get_control_socket("adbd");
255     if (fd < 0) {
256         D("Failed to get adbd socket\n");
257         return;
258     }
259 
260     ret = listen(fd, 4);
261     if (ret < 0) {
262         D("Failed to listen on '%d'\n", fd);
263         return;
264     }
265 
266     fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
267     fdevent_add(&listener_fde, FDE_READ);
268 }
269