blob: 07356947def7e430d67555ec64bd3f5699297707 [file] [log] [blame]
Benoit Goby2cc19e42012-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 Cui19bec5b2015-09-22 15:52:57 -070017#define TRACE_TAG AUTH
Dan Albertdb6fe642015-03-19 15:21:08 -070018
19#include "sysdeps.h"
20#include "adb_auth.h"
Yurii Zubrytskyi70ae70a2016-05-25 15:17:10 -070021#include "adb_utils.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070022
Benoit Goby2cc19e42012-04-12 12:23:49 -070023#include <stdio.h>
Christopher Ferris054d1702014-11-06 14:34:24 -080024#include <stdlib.h>
Dan Albertdb6fe642015-03-19 15:21:08 -070025#include <string.h>
Benoit Goby2cc19e42012-04-12 12:23:49 -070026
Benoit Goby2cc19e42012-04-12 12:23:49 -070027#include "adb.h"
Benoit Goby2cc19e42012-04-12 12:23:49 -070028
David Pursellc573d522016-01-27 08:52:53 -080029#include <android-base/errors.h>
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -070030#include <android-base/stringprintf.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080031#include <android-base/strings.h>
Mattias Nisslera947b492016-03-31 16:32:09 +020032#include <crypto_utils/android_pubkey.h>
Benoit Goby2cc19e42012-04-12 12:23:49 -070033#include <cutils/list.h>
34
35#include <openssl/evp.h>
36#include <openssl/objects.h>
37#include <openssl/pem.h>
38#include <openssl/rsa.h>
39#include <openssl/sha.h>
40
Adam Langley29f6cdb2014-09-03 14:34:47 -070041#if defined(OPENSSL_IS_BORINGSSL)
42#include <openssl/base64.h>
43#endif
44
Dan Albert3d978e62015-07-09 20:35:09 +000045#define ANDROID_PATH ".android"
46#define ADB_KEY_FILE "adbkey"
Benoit Goby2cc19e42012-04-12 12:23:49 -070047
Benoit Goby2cc19e42012-04-12 12:23:49 -070048struct adb_private_key {
49 struct listnode node;
50 RSA *rsa;
51};
52
53static struct listnode key_list;
54
55
Benoit Goby2cc19e42012-04-12 12:23:49 -070056static void get_user_info(char *buf, size_t len)
57{
58 char hostname[1024], username[1024];
Nick Kralevich6183c962014-11-13 15:17:29 -080059 int ret = -1;
60
61 if (getenv("HOSTNAME") != NULL) {
62 strncpy(hostname, getenv("HOSTNAME"), sizeof(hostname));
63 hostname[sizeof(hostname)-1] = '\0';
64 ret = 0;
65 }
Benoit Goby2cc19e42012-04-12 12:23:49 -070066
67#ifndef _WIN32
Benoit Goby2cc19e42012-04-12 12:23:49 -070068 if (ret < 0)
Nick Kralevich6183c962014-11-13 15:17:29 -080069 ret = gethostname(hostname, sizeof(hostname));
Benoit Goby2cc19e42012-04-12 12:23:49 -070070#endif
Nick Kralevich6183c962014-11-13 15:17:29 -080071 if (ret < 0)
Benoit Goby2cc19e42012-04-12 12:23:49 -070072 strcpy(hostname, "unknown");
73
Nick Kralevich6183c962014-11-13 15:17:29 -080074 ret = -1;
75
76 if (getenv("LOGNAME") != NULL) {
77 strncpy(username, getenv("LOGNAME"), sizeof(username));
78 username[sizeof(username)-1] = '\0';
79 ret = 0;
80 }
81
Benoit Goby2cc19e42012-04-12 12:23:49 -070082#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
Benoit Goby2cc19e42012-04-12 12:23:49 -070083 if (ret < 0)
Nick Kralevich6183c962014-11-13 15:17:29 -080084 ret = getlogin_r(username, sizeof(username));
Benoit Goby2cc19e42012-04-12 12:23:49 -070085#endif
Nick Kralevich6183c962014-11-13 15:17:29 -080086 if (ret < 0)
Benoit Goby2cc19e42012-04-12 12:23:49 -070087 strcpy(username, "unknown");
88
89 ret = snprintf(buf, len, " %s@%s", username, hostname);
90 if (ret >= (signed)len)
91 buf[len - 1] = '\0';
92}
93
94static int write_public_keyfile(RSA *private_key, const char *private_key_path)
95{
Mattias Nisslera947b492016-03-31 16:32:09 +020096 uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
97 uint8_t* base64_key_data = nullptr;
98 size_t base64_key_length = 0;
Adam Langley29f6cdb2014-09-03 14:34:47 -070099 FILE *outfile = NULL;
Tamas Berghammera1c60c02015-07-13 19:12:28 +0100100 char path[PATH_MAX], info[MAX_PAYLOAD_V1];
Adam Langley29f6cdb2014-09-03 14:34:47 -0700101 int ret = 0;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700102
Mattias Nisslera947b492016-03-31 16:32:09 +0200103 if (!android_pubkey_encode(private_key, binary_key_data,
104 sizeof(binary_key_data))) {
Yabin Cui815ad882015-09-02 17:44:28 -0700105 D("Failed to convert to publickey");
Mattias Nisslera947b492016-03-31 16:32:09 +0200106 goto out;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700107 }
108
Yabin Cui815ad882015-09-02 17:44:28 -0700109 D("Writing public key to '%s'", path);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700110
Adam Langley29f6cdb2014-09-03 14:34:47 -0700111#if defined(OPENSSL_IS_BORINGSSL)
Mattias Nisslera947b492016-03-31 16:32:09 +0200112 if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) {
Yabin Cui815ad882015-09-02 17:44:28 -0700113 D("Public key too large to base64 encode");
Adam Langley29f6cdb2014-09-03 14:34:47 -0700114 goto out;
115 }
116#else
117 /* While we switch from OpenSSL to BoringSSL we have to implement
118 * |EVP_EncodedLength| here. */
Mattias Nisslera947b492016-03-31 16:32:09 +0200119 base64_key_length = 1 + ((sizeof(binary_key_data) + 2) / 3 * 4);
Adam Langley29f6cdb2014-09-03 14:34:47 -0700120#endif
Benoit Goby2cc19e42012-04-12 12:23:49 -0700121
Mattias Nisslera947b492016-03-31 16:32:09 +0200122 base64_key_data = new uint8_t[base64_key_length];
123 if (base64_key_data == nullptr) {
Yabin Cui815ad882015-09-02 17:44:28 -0700124 D("Allocation failure");
Adam Langley29f6cdb2014-09-03 14:34:47 -0700125 goto out;
126 }
Benoit Goby2cc19e42012-04-12 12:23:49 -0700127
Mattias Nisslera947b492016-03-31 16:32:09 +0200128 base64_key_length = EVP_EncodeBlock(base64_key_data, binary_key_data,
129 sizeof(binary_key_data));
Benoit Goby2cc19e42012-04-12 12:23:49 -0700130 get_user_info(info, sizeof(info));
Benoit Goby2cc19e42012-04-12 12:23:49 -0700131
Mattias Nisslera947b492016-03-31 16:32:09 +0200132 if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >=
133 (int)sizeof(path)) {
134 D("Path too long while writing public key");
135 goto out;
136 }
137
138 outfile = fopen(path, "w");
139 if (!outfile) {
140 D("Failed to open '%s'", path);
141 goto out;
142 }
143
144 if (fwrite(base64_key_data, base64_key_length, 1, outfile) != 1 ||
Adam Langley29f6cdb2014-09-03 14:34:47 -0700145 fwrite(info, strlen(info), 1, outfile) != 1) {
Yabin Cui815ad882015-09-02 17:44:28 -0700146 D("Write error while writing public key");
Adam Langley29f6cdb2014-09-03 14:34:47 -0700147 goto out;
148 }
149
150 ret = 1;
151
152 out:
153 if (outfile != NULL) {
154 fclose(outfile);
155 }
Mattias Nisslera947b492016-03-31 16:32:09 +0200156 delete[] base64_key_data;
Adam Langley29f6cdb2014-09-03 14:34:47 -0700157 return ret;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700158}
159
160static int generate_key(const char *file)
161{
162 EVP_PKEY* pkey = EVP_PKEY_new();
163 BIGNUM* exponent = BN_new();
164 RSA* rsa = RSA_new();
Benoit Gobycb37c502012-08-31 12:14:21 -0700165 mode_t old_mask;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700166 FILE *f = NULL;
167 int ret = 0;
168
Yabin Cui815ad882015-09-02 17:44:28 -0700169 D("generate_key '%s'", file);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700170
171 if (!pkey || !exponent || !rsa) {
Yabin Cui815ad882015-09-02 17:44:28 -0700172 D("Failed to allocate key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700173 goto out;
174 }
175
176 BN_set_word(exponent, RSA_F4);
177 RSA_generate_key_ex(rsa, 2048, exponent, NULL);
178 EVP_PKEY_set1_RSA(pkey, rsa);
179
Benoit Gobycb37c502012-08-31 12:14:21 -0700180 old_mask = umask(077);
181
Spencer Low60bca2d2015-05-07 19:08:29 -0700182 f = fopen(file, "w");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700183 if (!f) {
Yabin Cui815ad882015-09-02 17:44:28 -0700184 D("Failed to open '%s'", file);
Benoit Gobycb37c502012-08-31 12:14:21 -0700185 umask(old_mask);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700186 goto out;
187 }
188
Benoit Gobycb37c502012-08-31 12:14:21 -0700189 umask(old_mask);
190
Benoit Goby2cc19e42012-04-12 12:23:49 -0700191 if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700192 D("Failed to write key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700193 goto out;
194 }
195
196 if (!write_public_keyfile(rsa, file)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700197 D("Failed to write public key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700198 goto out;
199 }
200
201 ret = 1;
202
203out:
204 if (f)
205 fclose(f);
206 EVP_PKEY_free(pkey);
207 RSA_free(rsa);
208 BN_free(exponent);
209 return ret;
210}
211
212static int read_key(const char *file, struct listnode *list)
213{
Yabin Cui815ad882015-09-02 17:44:28 -0700214 D("read_key '%s'", file);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700215
Spencer Low60bca2d2015-05-07 19:08:29 -0700216 FILE* fp = fopen(file, "r");
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700217 if (!fp) {
Yabin Cui815ad882015-09-02 17:44:28 -0700218 D("Failed to open '%s': %s", file, strerror(errno));
Benoit Goby2cc19e42012-04-12 12:23:49 -0700219 return 0;
220 }
221
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700222 adb_private_key* key = new adb_private_key;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700223 key->rsa = RSA_new();
224
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700225 if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700226 D("Failed to read key");
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700227 fclose(fp);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700228 RSA_free(key->rsa);
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700229 delete key;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700230 return 0;
231 }
232
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700233 fclose(fp);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700234 list_add_tail(list, &key->node);
235 return 1;
236}
237
Dan Albert3d978e62015-07-09 20:35:09 +0000238static int get_user_keyfilepath(char *filename, size_t len)
239{
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700240 const std::string home = adb_get_homedir_path(true);
Yurii Zubrytskyi70ae70a2016-05-25 15:17:10 -0700241 D("home '%s'", home.c_str());
Benoit Goby2cc19e42012-04-12 12:23:49 -0700242
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700243 const std::string android_dir =
244 android::base::StringPrintf("%s%c%s", home.c_str(),
245 OS_PATH_SEPARATOR, ANDROID_PATH);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700246
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700247 struct stat buf;
248 if (stat(android_dir.c_str(), &buf)) {
249 if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
250 D("Cannot mkdir '%s'", android_dir.c_str());
Dan Albert3d978e62015-07-09 20:35:09 +0000251 return -1;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700252 }
253 }
254
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700255 return snprintf(filename, len, "%s%c%s",
256 android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700257}
258
259static int get_user_key(struct listnode *list)
260{
Dan Albert3d978e62015-07-09 20:35:09 +0000261 struct stat buf;
262 char path[PATH_MAX];
263 int ret;
264
265 ret = get_user_keyfilepath(path, sizeof(path));
266 if (ret < 0 || ret >= (signed)sizeof(path)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700267 D("Error getting user key filename");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700268 return 0;
269 }
270
Yabin Cui815ad882015-09-02 17:44:28 -0700271 D("user key '%s'", path);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700272
Dan Albert3d978e62015-07-09 20:35:09 +0000273 if (stat(path, &buf) == -1) {
274 if (!generate_key(path)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700275 D("Failed to generate new key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700276 return 0;
277 }
278 }
279
Dan Albert3d978e62015-07-09 20:35:09 +0000280 return read_key(path, list);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700281}
282
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700283static void get_vendor_keys(struct listnode* key_list) {
284 const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
285 if (adb_keys_path == nullptr) {
Benoit Goby2cc19e42012-04-12 12:23:49 -0700286 return;
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700287 }
Benoit Goby2cc19e42012-04-12 12:23:49 -0700288
Elliott Hughes85952832015-10-07 15:59:35 -0700289 for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700290 if (!read_key(path.c_str(), key_list)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700291 D("Failed to read '%s'", path.c_str());
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700292 }
Benoit Goby2cc19e42012-04-12 12:23:49 -0700293 }
294}
295
Dan Albertf30d73c2015-02-25 17:51:28 -0800296int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
297 unsigned char* sig)
Benoit Goby2cc19e42012-04-12 12:23:49 -0700298{
299 unsigned int len;
300 struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
301
Sami Tolvanenb92a35c2015-01-27 16:48:35 +0000302 if (token_size != TOKEN_SIZE) {
Yabin Cui815ad882015-09-02 17:44:28 -0700303 D("Unexpected token size %zd", token_size);
Sami Tolvanenb92a35c2015-01-27 16:48:35 +0000304 return 0;
305 }
306
Benoit Goby2cc19e42012-04-12 12:23:49 -0700307 if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
308 return 0;
309 }
310
Yabin Cui815ad882015-09-02 17:44:28 -0700311 D("adb_auth_sign len=%d", len);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700312 return (int)len;
313}
314
315void *adb_auth_nextkey(void *current)
316{
317 struct listnode *item;
318
319 if (list_empty(&key_list))
320 return NULL;
321
322 if (!current)
323 return list_head(&key_list);
324
325 list_for_each(item, &key_list) {
326 if (item == current) {
327 /* current is the last item, we tried all the keys */
328 if (item->next == &key_list)
329 return NULL;
330 return item->next;
331 }
332 }
333
334 return NULL;
335}
336
337int adb_auth_get_userkey(unsigned char *data, size_t len)
338{
Dan Albert3d978e62015-07-09 20:35:09 +0000339 char path[PATH_MAX];
340 int ret = get_user_keyfilepath(path, sizeof(path) - 4);
341 if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700342 D("Error getting user key filename");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700343 return 0;
344 }
Dan Albert3d978e62015-07-09 20:35:09 +0000345 strcat(path, ".pub");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700346
Dan Albertf30d73c2015-02-25 17:51:28 -0800347 // TODO(danalbert): ReadFileToString
Spencer Low3a2421b2015-05-22 20:09:06 -0700348 // Note that on Windows, load_file() does not do CR/LF translation, but
349 // ReadFileToString() uses the C Runtime which uses CR/LF translation by
350 // default (by is overridable with _setmode()).
Dan Albertf30d73c2015-02-25 17:51:28 -0800351 unsigned size;
Dan Albert3d978e62015-07-09 20:35:09 +0000352 char* file_data = reinterpret_cast<char*>(load_file(path, &size));
Dan Albertf30d73c2015-02-25 17:51:28 -0800353 if (file_data == nullptr) {
Yabin Cui815ad882015-09-02 17:44:28 -0700354 D("Can't load '%s'", path);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700355 return 0;
356 }
357
Dan Albertf30d73c2015-02-25 17:51:28 -0800358 if (len < (size_t)(size + 1)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700359 D("%s: Content too large ret=%d", path, size);
Dan Albertf30d73c2015-02-25 17:51:28 -0800360 free(file_data);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700361 return 0;
362 }
363
Dan Albertf30d73c2015-02-25 17:51:28 -0800364 memcpy(data, file_data, size);
365 free(file_data);
366 file_data = nullptr;
367 data[size] = '\0';
Benoit Goby2cc19e42012-04-12 12:23:49 -0700368
Dan Albertf30d73c2015-02-25 17:51:28 -0800369 return size + 1;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700370}
371
Nick Kralevich6183c962014-11-13 15:17:29 -0800372int adb_auth_keygen(const char* filename) {
Nick Kralevich6183c962014-11-13 15:17:29 -0800373 return (generate_key(filename) == 0);
374}
375
Benoit Goby2cc19e42012-04-12 12:23:49 -0700376void adb_auth_init(void)
377{
378 int ret;
379
Yabin Cui815ad882015-09-02 17:44:28 -0700380 D("adb_auth_init");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700381
382 list_init(&key_list);
383
384 ret = get_user_key(&key_list);
385 if (!ret) {
Yabin Cui815ad882015-09-02 17:44:28 -0700386 D("Failed to get user key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700387 return;
388 }
389
390 get_vendor_keys(&key_list);
391}