blob: a4ad18fd930d13501e91245cce807dbd0f804fb4 [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
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
32struct adb_public_key {
33 struct listnode node;
34 RSAPublicKey key;
35};
36
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070037static char *key_paths[] = {
38 "/adb_keys",
39 "/data/misc/adb/adb_keys",
40 NULL
41};
42
43static fdevent listener_fde;
44static int framework_fd = -1;
45
46
47static void read_keys(const char *file, struct listnode *list)
48{
49 struct adb_public_key *key;
50 FILE *f;
51 char buf[MAX_PAYLOAD];
52 char *sep;
53 int ret;
54
55 f = fopen(file, "r");
56 if (!f) {
57 D("Can't open '%s'\n", file);
58 return;
59 }
60
61 while (fgets(buf, sizeof(buf), f)) {
62 /* Allocate 4 extra bytes to decode the base64 data in-place */
63 key = calloc(1, sizeof(*key) + 4);
64 if (!key) {
65 D("Can't malloc key\n");
66 break;
67 }
68
69 sep = strpbrk(buf, " \t");
70 if (sep)
71 *sep = '\0';
72
73 ret = __b64_pton(buf, (u_char *)&key->key, sizeof(key->key) + 4);
74 if (ret != sizeof(key->key)) {
75 D("%s: Invalid base64 data ret=%d\n", file, ret);
76 free(key);
77 continue;
78 }
79
80 if (key->key.len != RSANUMWORDS) {
81 D("%s: Invalid key len %d\n", file, key->key.len);
82 free(key);
83 continue;
84 }
85
86 list_add_tail(list, &key->node);
87 }
88
89 fclose(f);
90}
91
92static void free_keys(struct listnode *list)
93{
94 struct listnode *item;
95
96 while (!list_empty(list)) {
97 item = list_head(list);
98 list_remove(item);
99 free(node_to_item(item, struct adb_public_key, node));
100 }
101}
102
Benoit Goby345cb062013-01-14 21:26:30 -0800103static void load_keys(struct listnode *list)
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700104{
105 char *path;
106 char **paths = key_paths;
107 struct stat buf;
108
Benoit Goby345cb062013-01-14 21:26:30 -0800109 list_init(list);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700110
111 while ((path = *paths++)) {
112 if (!stat(path, &buf)) {
113 D("Loading keys from '%s'\n", path);
Benoit Goby345cb062013-01-14 21:26:30 -0800114 read_keys(path, list);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700115 }
116 }
117}
118
119int adb_auth_generate_token(void *token, size_t token_size)
120{
121 FILE *f;
122 int ret;
123
124 f = fopen("/dev/urandom", "r");
125 if (!f)
126 return 0;
127
128 ret = fread(token, token_size, 1, f);
129
130 fclose(f);
131 return ret * token_size;
132}
133
134int adb_auth_verify(void *token, void *sig, int siglen)
135{
136 struct listnode *item;
137 struct adb_public_key *key;
Benoit Goby345cb062013-01-14 21:26:30 -0800138 struct listnode key_list;
139 int ret = 0;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700140
141 if (siglen != RSANUMBYTES)
142 return 0;
143
Benoit Goby345cb062013-01-14 21:26:30 -0800144 load_keys(&key_list);
145
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700146 list_for_each(item, &key_list) {
147 key = node_to_item(item, struct adb_public_key, node);
148 ret = RSA_verify(&key->key, sig, siglen, token);
149 if (ret)
Benoit Goby345cb062013-01-14 21:26:30 -0800150 break;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700151 }
152
Benoit Goby345cb062013-01-14 21:26:30 -0800153 free_keys(&key_list);
154
155 return ret;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700156}
157
158static void adb_auth_event(int fd, unsigned events, void *data)
159{
160 atransport *t = data;
161 char response[2];
162 int ret;
163
164 if (events & FDE_READ) {
165 ret = unix_read(fd, response, sizeof(response));
166 if (ret < 0) {
167 D("Disconnect");
168 fdevent_remove(&t->auth_fde);
169 framework_fd = -1;
170 }
171 else if (ret == 2 && response[0] == 'O' && response[1] == 'K') {
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700172 adb_auth_verified(t);
173 }
174 }
175}
176
177void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t)
178{
179 char msg[MAX_PAYLOAD];
180 int ret;
181
182 if (framework_fd < 0) {
183 D("Client not connected\n");
184 return;
185 }
186
187 if (key[len - 1] != '\0') {
188 D("Key must be a null-terminated string\n");
189 return;
190 }
191
192 ret = snprintf(msg, sizeof(msg), "PK%s", key);
193 if (ret >= (signed)sizeof(msg)) {
194 D("Key too long. ret=%d", ret);
195 return;
196 }
197 D("Sending '%s'\n", msg);
198
199 ret = unix_write(framework_fd, msg, ret);
200 if (ret < 0) {
201 D("Failed to write PK, errno=%d\n", errno);
202 return;
203 }
204
205 fdevent_install(&t->auth_fde, framework_fd, adb_auth_event, t);
206 fdevent_add(&t->auth_fde, FDE_READ);
207}
208
209static void adb_auth_listener(int fd, unsigned events, void *data)
210{
211 struct sockaddr addr;
212 socklen_t alen;
213 int s;
214
215 alen = sizeof(addr);
216
217 s = adb_socket_accept(fd, &addr, &alen);
218 if (s < 0) {
219 D("Failed to accept: errno=%d\n", errno);
220 return;
221 }
222
223 framework_fd = s;
224}
225
226void adb_auth_init(void)
227{
228 int fd, ret;
229
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700230 fd = android_get_control_socket("adbd");
231 if (fd < 0) {
232 D("Failed to get adbd socket\n");
233 return;
234 }
235
236 ret = listen(fd, 4);
237 if (ret < 0) {
238 D("Failed to listen on '%d'\n", fd);
239 return;
240 }
241
242 fdevent_install(&listener_fde, fd, adb_auth_listener, NULL);
243 fdevent_add(&listener_fde, FDE_READ);
244}