blob: 415ab8ed317d96e94eaa780f6a718c8c9bc67032 [file] [log] [blame]
Benoit Gobyd5fcafa2012-04-12 12:23:49 -07001/*
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
Yabin Cuiaed3c612015-09-22 15:52:57 -070017#define TRACE_TAG AUTH
Dan Albert33134262015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20#include "adb_auth.h"
21
Dan Albert76649012015-02-24 15:51:19 -080022#include <resolv.h>
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070023#include <stdio.h>
24#include <string.h>
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070025
Mattias Nissler097b6bb2016-03-31 16:32:09 +020026#include <openssl/obj_mac.h>
27#include <openssl/rsa.h>
28#include <openssl/sha.h>
29
30#include <crypto_utils/android_pubkey.h>
31
Dan Albert76649012015-02-24 15:51:19 -080032#include "cutils/list.h"
33#include "cutils/sockets.h"
Dan Albert33134262015-03-19 15:21:08 -070034
35#include "adb.h"
36#include "fdevent.h"
Dan Albert76649012015-02-24 15:51:19 -080037#include "transport.h"
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070038
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070039struct adb_public_key {
40 struct listnode node;
Mattias Nissler097b6bb2016-03-31 16:32:09 +020041 RSA* key;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070042};
43
Dan Albertbac34742015-02-25 17:51:28 -080044static const char *key_paths[] = {
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070045 "/adb_keys",
46 "/data/misc/adb/adb_keys",
47 NULL
48};
49
50static fdevent listener_fde;
Josh Gao9f486112016-02-23 18:05:57 -080051static fdevent framework_fde;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070052static int framework_fd = -1;
53
Benoit Goby045a4a92013-01-15 19:59:14 -080054static void usb_disconnected(void* unused, atransport* t);
Yabin Cuib3298242015-08-28 15:09:44 -070055static struct adisconnect usb_disconnect = { usb_disconnected, nullptr};
Benoit Goby045a4a92013-01-15 19:59:14 -080056static atransport* usb_transport;
57static bool needs_retry = false;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070058
59static void read_keys(const char *file, struct listnode *list)
60{
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070061 FILE *f;
Tamas Berghammer3d2904c2015-07-13 19:12:28 +010062 char buf[MAX_PAYLOAD_V1];
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070063 char *sep;
64 int ret;
65
Nick Kralevichfe8d7f42014-07-18 20:57:35 -070066 f = fopen(file, "re");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070067 if (!f) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -070068 D("Can't open '%s'", file);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070069 return;
70 }
71
72 while (fgets(buf, sizeof(buf), f)) {
Dan Albertbac34742015-02-25 17:51:28 -080073 auto key = reinterpret_cast<adb_public_key*>(
Mattias Nissler097b6bb2016-03-31 16:32:09 +020074 calloc(1, sizeof(adb_public_key)));
Dan Albertbac34742015-02-25 17:51:28 -080075 if (key == nullptr) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -070076 D("Can't malloc key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070077 break;
78 }
79
80 sep = strpbrk(buf, " \t");
81 if (sep)
82 *sep = '\0';
83
Mattias Nissler097b6bb2016-03-31 16:32:09 +020084 // b64_pton requires one additional byte in the target buffer for
85 // decoding to succeed. See http://b/28035006 for details.
86 uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1];
87 ret = __b64_pton(buf, keybuf, sizeof(keybuf));
88 if (ret != ANDROID_PUBKEY_ENCODED_SIZE) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -070089 D("%s: Invalid base64 data ret=%d", file, ret);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070090 free(key);
91 continue;
92 }
93
Mattias Nissler097b6bb2016-03-31 16:32:09 +020094 if (!android_pubkey_decode(keybuf, ret, &key->key)) {
95 D("%s: Failed to parse key", file);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070096 free(key);
97 continue;
98 }
99
100 list_add_tail(list, &key->node);
101 }
102
103 fclose(f);
104}
105
106static void free_keys(struct listnode *list)
107{
108 struct listnode *item;
109
110 while (!list_empty(list)) {
111 item = list_head(list);
112 list_remove(item);
Mattias Nissler097b6bb2016-03-31 16:32:09 +0200113 adb_public_key* key = node_to_item(item, struct adb_public_key, node);
114 RSA_free(key->key);
115 free(key);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700116 }
117}
118
Benoit Goby345cb062013-01-14 21:26:30 -0800119static void load_keys(struct listnode *list)
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700120{
Dan Albertbac34742015-02-25 17:51:28 -0800121 const char* path;
122 const char** paths = key_paths;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700123 struct stat buf;
124
Benoit Goby345cb062013-01-14 21:26:30 -0800125 list_init(list);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700126
127 while ((path = *paths++)) {
128 if (!stat(path, &buf)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700129 D("Loading keys from '%s'", path);
Benoit Goby345cb062013-01-14 21:26:30 -0800130 read_keys(path, list);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700131 }
132 }
133}
134
135int adb_auth_generate_token(void *token, size_t token_size)
136{
137 FILE *f;
138 int ret;
139
Nick Kralevichfe8d7f42014-07-18 20:57:35 -0700140 f = fopen("/dev/urandom", "re");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700141 if (!f)
142 return 0;
143
144 ret = fread(token, token_size, 1, f);
145
146 fclose(f);
147 return ret * token_size;
148}
149
Mattias Nissler097b6bb2016-03-31 16:32:09 +0200150int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen)
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700151{
152 struct listnode *item;
Benoit Goby345cb062013-01-14 21:26:30 -0800153 struct listnode key_list;
154 int ret = 0;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700155
Benoit Goby345cb062013-01-14 21:26:30 -0800156 load_keys(&key_list);
157
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700158 list_for_each(item, &key_list) {
Dan Albertbac34742015-02-25 17:51:28 -0800159 adb_public_key* key = node_to_item(item, struct adb_public_key, node);
Mattias Nissler097b6bb2016-03-31 16:32:09 +0200160 ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700161 if (ret)
Benoit Goby345cb062013-01-14 21:26:30 -0800162 break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700163 }
164
Benoit Goby345cb062013-01-14 21:26:30 -0800165 free_keys(&key_list);
166
167 return ret;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700168}
169
Josh Gao9f486112016-02-23 18:05:57 -0800170static void usb_disconnected(void* unused, atransport* t) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700171 D("USB disconnect");
Benoit Goby045a4a92013-01-15 19:59:14 -0800172 usb_transport = NULL;
173 needs_retry = false;
174}
175
Josh Gao9f486112016-02-23 18:05:57 -0800176static void framework_disconnected() {
177 D("Framework disconnect");
178 fdevent_remove(&framework_fde);
179 framework_fd = -1;
180}
181
182static void adb_auth_event(int fd, unsigned events, void*) {
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700183 char response[2];
184 int ret;
185
186 if (events & FDE_READ) {
187 ret = unix_read(fd, response, sizeof(response));
Vince Harronaf436b12014-09-25 21:51:15 -0700188 if (ret <= 0) {
Josh Gao9f486112016-02-23 18:05:57 -0800189 framework_disconnected();
190 } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
191 if (usb_transport) {
Benoit Goby045a4a92013-01-15 19:59:14 -0800192 adb_auth_verified(usb_transport);
Josh Gao9f486112016-02-23 18:05:57 -0800193 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700194 }
195 }
196}
197
198void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
199{
Tamas Berghammer3d2904c2015-07-13 19:12:28 +0100200 char msg[MAX_PAYLOAD_V1];
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700201 int ret;
202
Benoit Gobyb66356c2013-04-01 17:39:06 -0700203 if (!usb_transport) {
204 usb_transport = t;
Yabin Cuib3298242015-08-28 15:09:44 -0700205 t->AddDisconnect(&usb_disconnect);
Benoit Gobyb66356c2013-04-01 17:39:06 -0700206 }
Benoit Goby045a4a92013-01-15 19:59:14 -0800207
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700208 if (framework_fd < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700209 D("Client not connected");
Benoit Goby045a4a92013-01-15 19:59:14 -0800210 needs_retry = true;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700211 return;
212 }
213
214 if (key[len - 1] != '\0') {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700215 D("Key must be a null-terminated string");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700216 return;
217 }
218
219 ret = snprintf(msg, sizeof(msg), "PK%s", key);
220 if (ret >= (signed)sizeof(msg)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700221 D("Key too long. ret=%d", ret);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700222 return;
223 }
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700224 D("Sending '%s'", msg);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700225
226 ret = unix_write(framework_fd, msg, ret);
227 if (ret < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700228 D("Failed to write PK, errno=%d", errno);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700229 return;
230 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700231}
232
Josh Gao9f486112016-02-23 18:05:57 -0800233static void adb_auth_listener(int fd, unsigned events, void* data) {
Erik Kline7e16cc12015-12-01 17:27:59 +0900234 sockaddr_storage addr;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700235 socklen_t alen;
236 int s;
237
238 alen = sizeof(addr);
239
Erik Kline7e16cc12015-12-01 17:27:59 +0900240 s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700241 if (s < 0) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700242 D("Failed to accept: errno=%d", errno);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700243 return;
244 }
245
Josh Gao9f486112016-02-23 18:05:57 -0800246 if (framework_fd >= 0) {
Josh Gao443a52c2016-02-25 14:11:32 -0800247 LOG(WARNING) << "adb received framework auth socket connection again";
Josh Gao9f486112016-02-23 18:05:57 -0800248 framework_disconnected();
249 }
250
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700251 framework_fd = s;
Josh Gao9f486112016-02-23 18:05:57 -0800252 fdevent_install(&framework_fde, framework_fd, adb_auth_event, nullptr);
253 fdevent_add(&framework_fde, FDE_READ);
Benoit Goby045a4a92013-01-15 19:59:14 -0800254
255 if (needs_retry) {
256 needs_retry = false;
257 send_auth_request(usb_transport);
258 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700259}
260
Pavel Labath64d9adc2015-03-17 11:03:36 -0700261void adbd_cloexec_auth_socket() {
262 int fd = android_get_control_socket("adbd");
263 if (fd == -1) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700264 D("Failed to get adbd socket");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700265 return;
266 }
Nick Kralevichfe8d7f42014-07-18 20:57:35 -0700267 fcntl(fd, F_SETFD, FD_CLOEXEC);
Pavel Labath64d9adc2015-03-17 11:03:36 -0700268}
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700269
Pavel Labath64d9adc2015-03-17 11:03:36 -0700270void adbd_auth_init(void) {
271 int fd = android_get_control_socket("adbd");
272 if (fd == -1) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700273 D("Failed to get adbd socket");
Pavel Labath64d9adc2015-03-17 11:03:36 -0700274 return;
275 }
276
277 if (listen(fd, 4) == -1) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700278 D("Failed to listen on '%d'", fd);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700279 return;
280 }
281
282 fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
283 fdevent_add(&listener_fde, FDE_READ);
284}