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 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 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 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 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 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 165 static void usb_disconnected(void* unused, atransport* t) { 166 D("USB disconnect"); 167 usb_transport = NULL; 168 needs_retry = false; 169 } 170 171 static void framework_disconnected() { 172 D("Framework disconnect"); 173 fdevent_remove(&framework_fde); 174 framework_fd = -1; 175 } 176 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 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 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 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 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