blob: ce269cc0be98a20890cc2507ea126c948dc895a4 [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
Dan Albertdb6fe642015-03-19 15:21:08 -070019#include "adb_auth.h"
Elliott Hughes801066a2016-06-29 17:42:01 -070020#include "adb.h"
Yurii Zubrytskyi70ae70a2016-05-25 15:17:10 -070021#include "adb_utils.h"
Elliott Hughes801066a2016-06-29 17:42:01 -070022#include "sysdeps.h"
Dan Albertdb6fe642015-03-19 15:21:08 -070023
Benoit Goby2cc19e42012-04-12 12:23:49 -070024#include <stdio.h>
Christopher Ferris054d1702014-11-06 14:34:24 -080025#include <stdlib.h>
Dan Albertdb6fe642015-03-19 15:21:08 -070026#include <string.h>
Benoit Goby2cc19e42012-04-12 12:23:49 -070027
Elliott Hughes801066a2016-06-29 17:42:01 -070028#include <mutex>
Benoit Goby2cc19e42012-04-12 12:23:49 -070029
David Pursellc573d522016-01-27 08:52:53 -080030#include <android-base/errors.h>
Elliott Hughese0a6e2a2016-05-26 22:43:19 -070031#include <android-base/file.h>
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -070032#include <android-base/stringprintf.h>
Elliott Hughesf55ead92015-12-04 22:00:26 -080033#include <android-base/strings.h>
Mattias Nisslera947b492016-03-31 16:32:09 +020034#include <crypto_utils/android_pubkey.h>
Elliott Hughesab942fd2016-06-21 16:50:48 -070035#include <openssl/base64.h>
Benoit Goby2cc19e42012-04-12 12:23:49 -070036#include <openssl/evp.h>
37#include <openssl/objects.h>
38#include <openssl/pem.h>
39#include <openssl/rsa.h>
40#include <openssl/sha.h>
41
Elliott Hughes801066a2016-06-29 17:42:01 -070042#include "sysdeps/mutex.h"
Benoit Goby2cc19e42012-04-12 12:23:49 -070043
Elliott Hughes801066a2016-06-29 17:42:01 -070044static std::mutex& g_key_list_mutex = *new std::mutex;
45static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>;
Benoit Goby2cc19e42012-04-12 12:23:49 -070046
Elliott Hughesab942fd2016-06-21 16:50:48 -070047static std::string get_user_info() {
Elliott Hughes801066a2016-06-29 17:42:01 -070048 LOG(INFO) << "get_user_info...";
49
Elliott Hughesab942fd2016-06-21 16:50:48 -070050 std::string hostname;
51 if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
52#if !defined(_WIN32)
53 char buf[64];
54 if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
Benoit Goby2cc19e42012-04-12 12:23:49 -070055#endif
Elliott Hughesab942fd2016-06-21 16:50:48 -070056 if (hostname.empty()) hostname = "unknown";
Benoit Goby2cc19e42012-04-12 12:23:49 -070057
Elliott Hughesab942fd2016-06-21 16:50:48 -070058 std::string username;
59 if (getenv("LOGNAME")) username = getenv("LOGNAME");
Benoit Goby2cc19e42012-04-12 12:23:49 -070060#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
Elliott Hughesab942fd2016-06-21 16:50:48 -070061 if (username.empty() && getlogin()) username = getlogin();
Benoit Goby2cc19e42012-04-12 12:23:49 -070062#endif
Elliott Hughesab942fd2016-06-21 16:50:48 -070063 if (username.empty()) hostname = "unknown";
Benoit Goby2cc19e42012-04-12 12:23:49 -070064
Elliott Hughesab942fd2016-06-21 16:50:48 -070065 return " " + username + "@" + hostname;
Benoit Goby2cc19e42012-04-12 12:23:49 -070066}
67
Elliott Hughesab942fd2016-06-21 16:50:48 -070068static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
Elliott Hughes801066a2016-06-29 17:42:01 -070069 LOG(INFO) << "write_public_keyfile...";
70
Mattias Nisslera947b492016-03-31 16:32:09 +020071 uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
Elliott Hughesab942fd2016-06-21 16:50:48 -070072 if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
73 LOG(ERROR) << "Failed to convert to public key";
74 return false;
Benoit Goby2cc19e42012-04-12 12:23:49 -070075 }
76
Elliott Hughesab942fd2016-06-21 16:50:48 -070077 size_t base64_key_length;
Mattias Nisslera947b492016-03-31 16:32:09 +020078 if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) {
Elliott Hughesab942fd2016-06-21 16:50:48 -070079 LOG(ERROR) << "Public key too large to base64 encode";
80 return false;
Adam Langley29f6cdb2014-09-03 14:34:47 -070081 }
Benoit Goby2cc19e42012-04-12 12:23:49 -070082
Elliott Hughesab942fd2016-06-21 16:50:48 -070083 std::string content;
84 content.resize(base64_key_length);
85 base64_key_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
Mattias Nisslera947b492016-03-31 16:32:09 +020086 sizeof(binary_key_data));
Benoit Goby2cc19e42012-04-12 12:23:49 -070087
Elliott Hughesab942fd2016-06-21 16:50:48 -070088 content += get_user_info();
89
90 std::string path(private_key_path + ".pub");
91 if (!android::base::WriteStringToFile(content, path)) {
92 PLOG(ERROR) << "Failed to write public key to '" << path << "'";
93 return false;
Mattias Nisslera947b492016-03-31 16:32:09 +020094 }
95
Elliott Hughesab942fd2016-06-21 16:50:48 -070096 return true;
Benoit Goby2cc19e42012-04-12 12:23:49 -070097}
98
Elliott Hughes801066a2016-06-29 17:42:01 -070099static int generate_key(const std::string& file) {
100 LOG(INFO) << "generate_key(" << file << ")...";
101
Benoit Gobycb37c502012-08-31 12:14:21 -0700102 mode_t old_mask;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700103 FILE *f = NULL;
104 int ret = 0;
105
Elliott Hughes801066a2016-06-29 17:42:01 -0700106 EVP_PKEY* pkey = EVP_PKEY_new();
107 BIGNUM* exponent = BN_new();
108 RSA* rsa = RSA_new();
Benoit Goby2cc19e42012-04-12 12:23:49 -0700109 if (!pkey || !exponent || !rsa) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700110 LOG(ERROR) << "Failed to allocate key";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700111 goto out;
112 }
113
114 BN_set_word(exponent, RSA_F4);
115 RSA_generate_key_ex(rsa, 2048, exponent, NULL);
116 EVP_PKEY_set1_RSA(pkey, rsa);
117
Benoit Gobycb37c502012-08-31 12:14:21 -0700118 old_mask = umask(077);
119
Elliott Hughes801066a2016-06-29 17:42:01 -0700120 f = fopen(file.c_str(), "w");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700121 if (!f) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700122 PLOG(ERROR) << "Failed to open " << file;
Benoit Gobycb37c502012-08-31 12:14:21 -0700123 umask(old_mask);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700124 goto out;
125 }
126
Benoit Gobycb37c502012-08-31 12:14:21 -0700127 umask(old_mask);
128
Benoit Goby2cc19e42012-04-12 12:23:49 -0700129 if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700130 D("Failed to write key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700131 goto out;
132 }
133
134 if (!write_public_keyfile(rsa, file)) {
Yabin Cui815ad882015-09-02 17:44:28 -0700135 D("Failed to write public key");
Benoit Goby2cc19e42012-04-12 12:23:49 -0700136 goto out;
137 }
138
139 ret = 1;
140
141out:
Elliott Hughes801066a2016-06-29 17:42:01 -0700142 if (f) fclose(f);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700143 EVP_PKEY_free(pkey);
144 RSA_free(rsa);
145 BN_free(exponent);
146 return ret;
147}
148
Elliott Hughes801066a2016-06-29 17:42:01 -0700149static bool read_key(const std::string& file) {
150 LOG(INFO) << "read_key '" << file << "'...";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700151
Elliott Hughes801066a2016-06-29 17:42:01 -0700152 std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700153 if (!fp) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700154 PLOG(ERROR) << "Failed to open '" << file << "'";
155 return false;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700156 }
157
Elliott Hughes801066a2016-06-29 17:42:01 -0700158 RSA* key = RSA_new();
159 if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
160 LOG(ERROR) << "Failed to read key";
161 RSA_free(key);
162 return false;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700163 }
164
Elliott Hughes801066a2016-06-29 17:42:01 -0700165 g_key_list.push_back(key);
166 return true;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700167}
168
Elliott Hughes801066a2016-06-29 17:42:01 -0700169static std::string get_user_key_path() {
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700170 const std::string home = adb_get_homedir_path(true);
Elliott Hughes801066a2016-06-29 17:42:01 -0700171 LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700172
Elliott Hughes801066a2016-06-29 17:42:01 -0700173 const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(),
174 OS_PATH_SEPARATOR);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700175
Yurii Zubrytskyi09ecaa52016-05-26 09:46:10 -0700176 struct stat buf;
Elliott Hughes801066a2016-06-29 17:42:01 -0700177 if (stat(android_dir.c_str(), &buf) == -1) {
178 if (adb_mkdir(android_dir.c_str(), 0750) == -1) {
179 PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'";
180 return "";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700181 }
182 }
183
Elliott Hughes801066a2016-06-29 17:42:01 -0700184 return android_dir + OS_PATH_SEPARATOR + "adbkey";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700185}
186
Elliott Hughes801066a2016-06-29 17:42:01 -0700187static bool get_user_key() {
188 std::string path = get_user_key_path();
189 if (path.empty()) {
190 PLOG(ERROR) << "Error getting user key filename";
191 return false;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700192 }
193
Elliott Hughes801066a2016-06-29 17:42:01 -0700194 struct stat buf;
195 if (stat(path.c_str(), &buf) == -1) {
196 LOG(INFO) << "User key '" << path << "' does not exist...";
Dan Albert3d978e62015-07-09 20:35:09 +0000197 if (!generate_key(path)) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700198 LOG(ERROR) << "Failed to generate new key";
199 return false;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700200 }
201 }
202
Elliott Hughes801066a2016-06-29 17:42:01 -0700203 return read_key(path);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700204}
205
Elliott Hughes801066a2016-06-29 17:42:01 -0700206static void get_vendor_keys() {
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700207 const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
208 if (adb_keys_path == nullptr) {
Benoit Goby2cc19e42012-04-12 12:23:49 -0700209 return;
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700210 }
Benoit Goby2cc19e42012-04-12 12:23:49 -0700211
Elliott Hughes85952832015-10-07 15:59:35 -0700212 for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700213 if (!read_key(path.c_str())) {
214 PLOG(ERROR) << "Failed to read '" << path << "'";
Elliott Hughesfb2ba512015-04-24 23:02:00 -0700215 }
Benoit Goby2cc19e42012-04-12 12:23:49 -0700216 }
217}
218
Elliott Hughes801066a2016-06-29 17:42:01 -0700219std::deque<RSA*> adb_auth_get_private_keys() {
220 std::deque<RSA*> result;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700221
Elliott Hughes801066a2016-06-29 17:42:01 -0700222 // Copy all the currently known keys, increasing their reference count so they're
223 // usable until both we and the caller have freed our pointers.
224 std::lock_guard<std::mutex> lock(g_key_list_mutex);
225 for (const auto& key : g_key_list) {
226 RSA_up_ref(key); // Since we're handing out another pointer to this key...
227 result.push_back(key);
228 }
229
230 // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
231 // but try using the public key" (the empty deque could otherwise mean this _or_
232 // that this function hasn't been called yet to request the keys).
233 result.push_back(nullptr);
234
235 return result;
236}
237
238int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) {
Sami Tolvanenb92a35c2015-01-27 16:48:35 +0000239 if (token_size != TOKEN_SIZE) {
Yabin Cui815ad882015-09-02 17:44:28 -0700240 D("Unexpected token size %zd", token_size);
Sami Tolvanenb92a35c2015-01-27 16:48:35 +0000241 return 0;
242 }
243
Elliott Hughes801066a2016-06-29 17:42:01 -0700244 unsigned int len;
245 if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) {
Benoit Goby2cc19e42012-04-12 12:23:49 -0700246 return 0;
247 }
248
Yabin Cui815ad882015-09-02 17:44:28 -0700249 D("adb_auth_sign len=%d", len);
Benoit Goby2cc19e42012-04-12 12:23:49 -0700250 return (int)len;
251}
252
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700253std::string adb_auth_get_userkey() {
Elliott Hughes801066a2016-06-29 17:42:01 -0700254 std::string path = get_user_key_path();
255 if (path.empty()) {
256 PLOG(ERROR) << "Error getting user key filename";
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700257 return "";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700258 }
Elliott Hughes801066a2016-06-29 17:42:01 -0700259 path += ".pub";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700260
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700261 std::string content;
262 if (!android::base::ReadFileToString(path, &content)) {
Elliott Hughes801066a2016-06-29 17:42:01 -0700263 PLOG(ERROR) << "Can't load '" << path << "'";
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700264 return "";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700265 }
Elliott Hughese0a6e2a2016-05-26 22:43:19 -0700266 return content;
Benoit Goby2cc19e42012-04-12 12:23:49 -0700267}
268
Nick Kralevich6183c962014-11-13 15:17:29 -0800269int adb_auth_keygen(const char* filename) {
Nick Kralevich6183c962014-11-13 15:17:29 -0800270 return (generate_key(filename) == 0);
271}
272
Elliott Hughes801066a2016-06-29 17:42:01 -0700273void adb_auth_init() {
274 LOG(INFO) << "adb_auth_init...";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700275
Elliott Hughes801066a2016-06-29 17:42:01 -0700276 if (!get_user_key()) {
277 LOG(ERROR) << "Failed to get user key";
Benoit Goby2cc19e42012-04-12 12:23:49 -0700278 return;
279 }
280
Elliott Hughes801066a2016-06-29 17:42:01 -0700281 std::lock_guard<std::mutex> lock(g_key_list_mutex);
282 get_vendor_keys();
Benoit Goby2cc19e42012-04-12 12:23:49 -0700283}