blob: dff874fd6f21dfd36d380e8ea6a9a946009c11a2 [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"
Yurii Zubrytskyi376b2752016-05-25 15:17:10 -070021#include "adb_utils.h"
Dan Albert33134262015-03-19 15:21:08 -070022
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070023#include <stdio.h>
Christopher Ferris67a7a4a2014-11-06 14:34:24 -080024#include <stdlib.h>
Dan Albert33134262015-03-19 15:21:08 -070025#include <string.h>
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070026
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070027#include "adb.h"
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070028
David Pursell5f787ed2016-01-27 08:52:53 -080029#include <android-base/errors.h>
Elliott Hughese8b663f2016-05-26 22:43:19 -070030#include <android-base/file.h>
Yurii Zubrytskyidace0152016-05-26 09:46:10 -070031#include <android-base/stringprintf.h>
Elliott Hughes4f713192015-12-04 22:00:26 -080032#include <android-base/strings.h>
Mattias Nissler097b6bb2016-03-31 16:32:09 +020033#include <crypto_utils/android_pubkey.h>
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070034#include <cutils/list.h>
35
Elliott Hughes625faf02016-06-21 16:50:48 -070036#include <openssl/base64.h>
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070037#include <openssl/evp.h>
38#include <openssl/objects.h>
39#include <openssl/pem.h>
40#include <openssl/rsa.h>
41#include <openssl/sha.h>
42
Dan Albert286bb6d2015-07-09 20:35:09 +000043#define ANDROID_PATH ".android"
44#define ADB_KEY_FILE "adbkey"
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070045
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070046struct adb_private_key {
47 struct listnode node;
48 RSA *rsa;
49};
50
51static struct listnode key_list;
52
53
Elliott Hughes625faf02016-06-21 16:50:48 -070054static std::string get_user_info() {
55 std::string hostname;
56 if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
57#if !defined(_WIN32)
58 char buf[64];
59 if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070060#endif
Elliott Hughes625faf02016-06-21 16:50:48 -070061 if (hostname.empty()) hostname = "unknown";
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070062
Elliott Hughes625faf02016-06-21 16:50:48 -070063 std::string username;
64 if (getenv("LOGNAME")) username = getenv("LOGNAME");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070065#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
Elliott Hughes625faf02016-06-21 16:50:48 -070066 if (username.empty() && getlogin()) username = getlogin();
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070067#endif
Elliott Hughes625faf02016-06-21 16:50:48 -070068 if (username.empty()) hostname = "unknown";
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070069
Elliott Hughes625faf02016-06-21 16:50:48 -070070 return " " + username + "@" + hostname;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070071}
72
Elliott Hughes625faf02016-06-21 16:50:48 -070073static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
Mattias Nissler097b6bb2016-03-31 16:32:09 +020074 uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
Elliott Hughes625faf02016-06-21 16:50:48 -070075 if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
76 LOG(ERROR) << "Failed to convert to public key";
77 return false;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070078 }
79
Elliott Hughes625faf02016-06-21 16:50:48 -070080 size_t base64_key_length;
Mattias Nissler097b6bb2016-03-31 16:32:09 +020081 if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) {
Elliott Hughes625faf02016-06-21 16:50:48 -070082 LOG(ERROR) << "Public key too large to base64 encode";
83 return false;
Adam Langley179d9d62014-09-03 14:34:47 -070084 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070085
Elliott Hughes625faf02016-06-21 16:50:48 -070086 std::string content;
87 content.resize(base64_key_length);
88 base64_key_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
Mattias Nissler097b6bb2016-03-31 16:32:09 +020089 sizeof(binary_key_data));
Benoit Gobyd5fcafa2012-04-12 12:23:49 -070090
Elliott Hughes625faf02016-06-21 16:50:48 -070091 content += get_user_info();
92
93 std::string path(private_key_path + ".pub");
94 if (!android::base::WriteStringToFile(content, path)) {
95 PLOG(ERROR) << "Failed to write public key to '" << path << "'";
96 return false;
Mattias Nissler097b6bb2016-03-31 16:32:09 +020097 }
98
Elliott Hughes625faf02016-06-21 16:50:48 -070099 return true;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700100}
101
102static int generate_key(const char *file)
103{
104 EVP_PKEY* pkey = EVP_PKEY_new();
105 BIGNUM* exponent = BN_new();
106 RSA* rsa = RSA_new();
Benoit Goby64b31032012-08-31 12:14:21 -0700107 mode_t old_mask;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700108 FILE *f = NULL;
109 int ret = 0;
110
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700111 D("generate_key '%s'", file);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700112
113 if (!pkey || !exponent || !rsa) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700114 D("Failed to allocate key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700115 goto out;
116 }
117
118 BN_set_word(exponent, RSA_F4);
119 RSA_generate_key_ex(rsa, 2048, exponent, NULL);
120 EVP_PKEY_set1_RSA(pkey, rsa);
121
Benoit Goby64b31032012-08-31 12:14:21 -0700122 old_mask = umask(077);
123
Spencer Low9b960312015-05-07 19:08:29 -0700124 f = fopen(file, "w");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700125 if (!f) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700126 D("Failed to open '%s'", file);
Benoit Goby64b31032012-08-31 12:14:21 -0700127 umask(old_mask);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700128 goto out;
129 }
130
Benoit Goby64b31032012-08-31 12:14:21 -0700131 umask(old_mask);
132
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700133 if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700134 D("Failed to write key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700135 goto out;
136 }
137
138 if (!write_public_keyfile(rsa, file)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700139 D("Failed to write public key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700140 goto out;
141 }
142
143 ret = 1;
144
145out:
146 if (f)
147 fclose(f);
148 EVP_PKEY_free(pkey);
149 RSA_free(rsa);
150 BN_free(exponent);
151 return ret;
152}
153
154static int read_key(const char *file, struct listnode *list)
155{
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700156 D("read_key '%s'", file);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700157
Spencer Low9b960312015-05-07 19:08:29 -0700158 FILE* fp = fopen(file, "r");
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700159 if (!fp) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700160 D("Failed to open '%s': %s", file, strerror(errno));
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700161 return 0;
162 }
163
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700164 adb_private_key* key = new adb_private_key;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700165 key->rsa = RSA_new();
166
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700167 if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700168 D("Failed to read key");
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700169 fclose(fp);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700170 RSA_free(key->rsa);
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700171 delete key;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700172 return 0;
173 }
174
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700175 fclose(fp);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700176 list_add_tail(list, &key->node);
177 return 1;
178}
179
Dan Albert286bb6d2015-07-09 20:35:09 +0000180static int get_user_keyfilepath(char *filename, size_t len)
181{
Yurii Zubrytskyidace0152016-05-26 09:46:10 -0700182 const std::string home = adb_get_homedir_path(true);
Yurii Zubrytskyi376b2752016-05-25 15:17:10 -0700183 D("home '%s'", home.c_str());
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700184
Yurii Zubrytskyidace0152016-05-26 09:46:10 -0700185 const std::string android_dir =
186 android::base::StringPrintf("%s%c%s", home.c_str(),
187 OS_PATH_SEPARATOR, ANDROID_PATH);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700188
Yurii Zubrytskyidace0152016-05-26 09:46:10 -0700189 struct stat buf;
190 if (stat(android_dir.c_str(), &buf)) {
191 if (adb_mkdir(android_dir.c_str(), 0750) < 0) {
192 D("Cannot mkdir '%s'", android_dir.c_str());
Dan Albert286bb6d2015-07-09 20:35:09 +0000193 return -1;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700194 }
195 }
196
Yurii Zubrytskyidace0152016-05-26 09:46:10 -0700197 return snprintf(filename, len, "%s%c%s",
198 android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700199}
200
201static int get_user_key(struct listnode *list)
202{
Dan Albert286bb6d2015-07-09 20:35:09 +0000203 struct stat buf;
204 char path[PATH_MAX];
205 int ret;
206
207 ret = get_user_keyfilepath(path, sizeof(path));
208 if (ret < 0 || ret >= (signed)sizeof(path)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700209 D("Error getting user key filename");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700210 return 0;
211 }
212
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700213 D("user key '%s'", path);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700214
Dan Albert286bb6d2015-07-09 20:35:09 +0000215 if (stat(path, &buf) == -1) {
216 if (!generate_key(path)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700217 D("Failed to generate new key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700218 return 0;
219 }
220 }
221
Dan Albert286bb6d2015-07-09 20:35:09 +0000222 return read_key(path, list);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700223}
224
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700225static void get_vendor_keys(struct listnode* key_list) {
226 const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
227 if (adb_keys_path == nullptr) {
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700228 return;
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700229 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700230
Elliott Hughes65fe2512015-10-07 15:59:35 -0700231 for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700232 if (!read_key(path.c_str(), key_list)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700233 D("Failed to read '%s'", path.c_str());
Elliott Hughes8d5fa6d2015-04-24 23:02:00 -0700234 }
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700235 }
236}
237
Dan Albertbac34742015-02-25 17:51:28 -0800238int adb_auth_sign(void *node, const unsigned char* token, size_t token_size,
239 unsigned char* sig)
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700240{
241 unsigned int len;
242 struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
243
Sami Tolvanen7b9c20d2015-01-27 16:48:35 +0000244 if (token_size != TOKEN_SIZE) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700245 D("Unexpected token size %zd", token_size);
Sami Tolvanen7b9c20d2015-01-27 16:48:35 +0000246 return 0;
247 }
248
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700249 if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
250 return 0;
251 }
252
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700253 D("adb_auth_sign len=%d", len);
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700254 return (int)len;
255}
256
257void *adb_auth_nextkey(void *current)
258{
259 struct listnode *item;
260
261 if (list_empty(&key_list))
262 return NULL;
263
264 if (!current)
265 return list_head(&key_list);
266
267 list_for_each(item, &key_list) {
268 if (item == current) {
269 /* current is the last item, we tried all the keys */
270 if (item->next == &key_list)
271 return NULL;
272 return item->next;
273 }
274 }
275
276 return NULL;
277}
278
Elliott Hughese8b663f2016-05-26 22:43:19 -0700279std::string adb_auth_get_userkey() {
Dan Albert286bb6d2015-07-09 20:35:09 +0000280 char path[PATH_MAX];
281 int ret = get_user_keyfilepath(path, sizeof(path) - 4);
282 if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700283 D("Error getting user key filename");
Elliott Hughese8b663f2016-05-26 22:43:19 -0700284 return "";
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700285 }
Dan Albert286bb6d2015-07-09 20:35:09 +0000286 strcat(path, ".pub");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700287
Elliott Hughese8b663f2016-05-26 22:43:19 -0700288 std::string content;
289 if (!android::base::ReadFileToString(path, &content)) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700290 D("Can't load '%s'", path);
Elliott Hughese8b663f2016-05-26 22:43:19 -0700291 return "";
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700292 }
Elliott Hughese8b663f2016-05-26 22:43:19 -0700293 return content;
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700294}
295
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800296int adb_auth_keygen(const char* filename) {
Nick Kralevichbea3f9c2014-11-13 15:17:29 -0800297 return (generate_key(filename) == 0);
298}
299
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700300void adb_auth_init(void)
301{
302 int ret;
303
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700304 D("adb_auth_init");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700305
306 list_init(&key_list);
307
308 ret = get_user_key(&key_list);
309 if (!ret) {
Yabin Cui7a3f8d62015-09-02 17:44:28 -0700310 D("Failed to get user key");
Benoit Gobyd5fcafa2012-04-12 12:23:49 -0700311 return;
312 }
313
314 get_vendor_keys(&key_list);
315}