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