Merge "adb: stop using adbkey.pub."
am: fa105049d8

Change-Id: I74631d77b453484aabd5e52efe1e4abbcc6ac5df
diff --git a/adb/adb_auth.h b/adb/adb_auth.h
index 715e04f..2fc8478 100644
--- a/adb/adb_auth.h
+++ b/adb/adb_auth.h
@@ -36,6 +36,7 @@
 void adb_auth_init();
 
 int adb_auth_keygen(const char* filename);
+int adb_auth_pubkey(const char* filename);
 std::string adb_auth_get_userkey();
 std::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys();
 
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index 71c19b8..bcb829b 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -43,6 +43,7 @@
 
 #include "adb.h"
 #include "adb_auth.h"
+#include "adb_io.h"
 #include "adb_utils.h"
 #include "sysdeps.h"
 #include "transport.h"
@@ -52,30 +53,7 @@
     *new std::map<std::string, std::shared_ptr<RSA>>;
 static std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
 
-static std::string get_user_info() {
-    LOG(INFO) << "get_user_info...";
-
-    std::string hostname;
-    if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
-#if !defined(_WIN32)
-    char buf[64];
-    if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
-#endif
-    if (hostname.empty()) hostname = "unknown";
-
-    std::string username;
-    if (getenv("LOGNAME")) username = getenv("LOGNAME");
-#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
-    if (username.empty() && getlogin()) username = getlogin();
-#endif
-    if (username.empty()) hostname = "unknown";
-
-    return " " + username + "@" + hostname;
-}
-
-static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
-    LOG(INFO) << "write_public_keyfile...";
-
+static bool calculate_public_key(std::string* out, RSA* private_key) {
     uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
     if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
         LOG(ERROR) << "Failed to convert to public key";
@@ -88,20 +66,10 @@
         return false;
     }
 
-    std::string content;
-    content.resize(expected_length);
-    size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
+    out->resize(expected_length);
+    size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(out->data()), binary_key_data,
                                            sizeof(binary_key_data));
-    content.resize(actual_length);
-
-    content += get_user_info();
-
-    std::string path(private_key_path + ".pub");
-    if (!android::base::WriteStringToFile(content, path)) {
-        PLOG(ERROR) << "Failed to write public key to '" << path << "'";
-        return false;
-    }
-
+    out->resize(actual_length);
     return true;
 }
 
@@ -140,11 +108,6 @@
         goto out;
     }
 
-    if (!write_public_keyfile(rsa, file)) {
-        D("Failed to write public key");
-        goto out;
-    }
-
     ret = 1;
 
 out:
@@ -170,36 +133,41 @@
     return result;
 }
 
-static bool read_key_file(const std::string& file) {
-    LOG(INFO) << "read_key_file '" << file << "'...";
-
+static std::shared_ptr<RSA> read_key_file(const std::string& file) {
     std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
     if (!fp) {
         PLOG(ERROR) << "Failed to open '" << file << "'";
-        return false;
+        return nullptr;
     }
 
     RSA* key = RSA_new();
     if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
         LOG(ERROR) << "Failed to read key";
         RSA_free(key);
+        return nullptr;
+    }
+
+    return std::shared_ptr<RSA>(key, RSA_free);
+}
+
+static bool load_key(const std::string& file) {
+    std::shared_ptr<RSA> key = read_key_file(file);
+    if (!key) {
         return false;
     }
 
     std::lock_guard<std::mutex> lock(g_keys_mutex);
-    std::string fingerprint = hash_key(key);
+    std::string fingerprint = hash_key(key.get());
     if (g_keys.find(fingerprint) != g_keys.end()) {
         LOG(INFO) << "ignoring already-loaded key: " << file;
-        RSA_free(key);
     } else {
-        g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
+        g_keys[fingerprint] = std::move(key);
     }
-
     return true;
 }
 
-static bool read_keys(const std::string& path, bool allow_dir = true) {
-    LOG(INFO) << "read_keys '" << path << "'...";
+static bool load_keys(const std::string& path, bool allow_dir = true) {
+    LOG(INFO) << "load_keys '" << path << "'...";
 
     struct stat st;
     if (stat(path.c_str(), &st) != 0) {
@@ -208,7 +176,7 @@
     }
 
     if (S_ISREG(st.st_mode)) {
-        return read_key_file(path);
+        return load_key(path);
     } else if (S_ISDIR(st.st_mode)) {
         if (!allow_dir) {
             // inotify isn't recursive. It would break expectations to load keys in nested
@@ -237,7 +205,7 @@
                 continue;
             }
 
-            result |= read_key_file((path + OS_PATH_SEPARATOR + name));
+            result |= load_key((path + OS_PATH_SEPARATOR + name));
         }
         return result;
     }
@@ -250,7 +218,7 @@
     return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
 }
 
-static bool get_user_key() {
+static bool generate_userkey() {
     std::string path = get_user_key_path();
     if (path.empty()) {
         PLOG(ERROR) << "Error getting user key filename";
@@ -266,7 +234,7 @@
         }
     }
 
-    return read_key_file(path);
+    return load_key(path);
 }
 
 static std::set<std::string> get_vendor_keys() {
@@ -320,26 +288,42 @@
     return result;
 }
 
+static bool pubkey_from_privkey(std::string* out, const std::string& path) {
+    std::shared_ptr<RSA> privkey = read_key_file(path);
+    if (!privkey) {
+        return false;
+    }
+    return calculate_public_key(out, privkey.get());
+}
+
 std::string adb_auth_get_userkey() {
     std::string path = get_user_key_path();
     if (path.empty()) {
         PLOG(ERROR) << "Error getting user key filename";
         return "";
     }
-    path += ".pub";
 
-    std::string content;
-    if (!android::base::ReadFileToString(path, &content)) {
-        PLOG(ERROR) << "Can't load '" << path << "'";
+    std::string result;
+    if (!pubkey_from_privkey(&result, path)) {
         return "";
     }
-    return content;
+    return result;
 }
 
 int adb_auth_keygen(const char* filename) {
     return (generate_key(filename) == 0);
 }
 
+int adb_auth_pubkey(const char* filename) {
+    std::string pubkey;
+    if (!pubkey_from_privkey(&pubkey, filename)) {
+        return 1;
+    }
+    pubkey.push_back('\n');
+
+    return WriteFdExactly(STDOUT_FILENO, pubkey.data(), pubkey.size()) ? 0 : 1;
+}
+
 #if defined(__linux__)
 static void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
     LOG(INFO) << "adb_auth_inotify_update called";
@@ -380,7 +364,7 @@
                     LOG(INFO) << "ignoring new directory at '" << path << "'";
                 } else {
                     LOG(INFO) << "observed new file at '" << path << "'";
-                    read_keys(path, false);
+                    load_keys(path, false);
                 }
             } else {
                 LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
@@ -420,8 +404,8 @@
 void adb_auth_init() {
     LOG(INFO) << "adb_auth_init...";
 
-    if (!get_user_key()) {
-        LOG(ERROR) << "Failed to get user key";
+    if (!generate_userkey()) {
+        LOG(ERROR) << "Failed to generate user key";
         return;
     }
 
@@ -432,7 +416,7 @@
 #endif
 
     for (const std::string& path : key_paths) {
-        read_keys(path.c_str());
+        load_keys(path.c_str());
     }
 }
 
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index b5bed28..c11052d 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -185,7 +185,6 @@
         " enable-verity            re-enable dm-verity checking on userdebug builds\n"
         " keygen FILE\n"
         "     generate adb public/private key; private key stored in FILE,\n"
-        "     public key stored in FILE.pub (existing files overwritten)\n"
         "\n"
         "scripting:\n"
         " wait-for[-TRANSPORT]-STATE\n"
@@ -1756,14 +1755,14 @@
         // Always print key generation information for keygen command.
         adb_trace_enable(AUTH);
         return adb_auth_keygen(argv[1]);
-    }
-    else if (!strcmp(argv[0], "jdwp")) {
+    } else if (!strcmp(argv[0], "pubkey")) {
+        if (argc != 2) error_exit("pubkey requires an argument");
+        return adb_auth_pubkey(argv[1]);
+    } else if (!strcmp(argv[0], "jdwp")) {
         return adb_connect_command("jdwp");
-    }
-    else if (!strcmp(argv[0], "track-jdwp")) {
+    } else if (!strcmp(argv[0], "track-jdwp")) {
         return adb_connect_command("track-jdwp");
-    }
-    else if (!strcmp(argv[0], "track-devices")) {
+    } else if (!strcmp(argv[0], "track-devices")) {
         return adb_connect_command("host:track-devices");
     } else if (!strcmp(argv[0], "raw")) {
         if (argc != 2) {
@@ -1772,13 +1771,11 @@
         return adb_connect_command(argv[1]);
     }
 
-
     /* "adb /?" is a common idiom under Windows */
     else if (!strcmp(argv[0], "--help") || !strcmp(argv[0], "help") || !strcmp(argv[0], "/?")) {
         help();
         return 0;
-    }
-    else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
+    } else if (!strcmp(argv[0], "--version") || !strcmp(argv[0], "version")) {
         fprintf(stdout, "%s", adb_version().c_str());
         return 0;
     } else if (!strcmp(argv[0], "features")) {