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