1d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby/*
2d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Copyright (C) 2012 The Android Open Source Project
3d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
4d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Licensed under the Apache License, Version 2.0 (the "License");
5d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * you may not use this file except in compliance with the License.
6d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * You may obtain a copy of the License at
7d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
8d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *      http://www.apache.org/licenses/LICENSE-2.0
9d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
10d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Unless required by applicable law or agreed to in writing, software
11d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * distributed under the License is distributed on an "AS IS" BASIS,
12d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * See the License for the specific language governing permissions and
14d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * limitations under the License.
15d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby */
16d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
17aed3c61c4437ebb05eadfb3bf85d6962c30b9935Yabin Cui#define TRACE_TAG AUTH
183313426fad9eaaf53017cdbde889ebcec91358ecDan Albert
192e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include <dirent.h>
20d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <stdio.h>
2167a7a4ae274ebd873a78e791b96da35a210db0ccChristopher Ferris#include <stdlib.h>
223313426fad9eaaf53017cdbde889ebcec91358ecDan Albert#include <string.h>
232e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#if defined(__linux__)
242e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include <sys/inotify.h>
252e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#endif
26d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
272e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include <map>
280aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes#include <mutex>
292e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include <set>
302e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include <string>
31d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
325f787ed2b3b9f6cc02aa5923b95d77e2a5865438David Pursell#include <android-base/errors.h>
33e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes#include <android-base/file.h>
34dace01526996ee221796c4627a615d393eee205bYurii Zubrytskyi#include <android-base/stringprintf.h>
354f71319df011d796a60a43fc1bc68e16fbf7d321Elliott Hughes#include <android-base/strings.h>
36097b6bbc76231f4148c9dd28b6ea0c1189d40fc3Mattias Nissler#include <crypto_utils/android_pubkey.h>
37625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes#include <openssl/base64.h>
38d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/evp.h>
39d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/objects.h>
40d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/pem.h>
41d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/rsa.h>
42d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/sha.h>
43d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
442e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include "adb.h"
452e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include "adb_auth.h"
462e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include "adb_utils.h"
472e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#include "sysdeps.h"
483bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao#include "transport.h"
49d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
502e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic std::mutex& g_keys_mutex = *new std::mutex;
512e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic std::map<std::string, std::shared_ptr<RSA>>& g_keys =
522e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    *new std::map<std::string, std::shared_ptr<RSA>>;
532e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic std::map<int, std::string>& g_monitored_paths = *new std::map<int, std::string>;
54d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
55625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughesstatic std::string get_user_info() {
560aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    LOG(INFO) << "get_user_info...";
570aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
58625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    std::string hostname;
59625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME");
60625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes#if !defined(_WIN32)
61625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    char buf[64];
62625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (hostname.empty() && gethostname(buf, sizeof(buf)) != -1) hostname = buf;
63d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#endif
64625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (hostname.empty()) hostname = "unknown";
65bea3f9c345073069151c9000cd506b9e46b26250Nick Kralevich
66625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    std::string username;
67625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (getenv("LOGNAME")) username = getenv("LOGNAME");
68d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
69625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (username.empty() && getlogin()) username = getlogin();
70d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#endif
71625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (username.empty()) hostname = "unknown";
72d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
73625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    return " " + username + "@" + hostname;
74d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
75d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
76625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughesstatic bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) {
770aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    LOG(INFO) << "write_public_keyfile...";
780aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
79097b6bbc76231f4148c9dd28b6ea0c1189d40fc3Mattias Nissler    uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE];
80625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (!android_pubkey_encode(private_key, binary_key_data, sizeof(binary_key_data))) {
81625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        LOG(ERROR) << "Failed to convert to public key";
82625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        return false;
83d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
84d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
850b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes    size_t expected_length;
860b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes    if (!EVP_EncodedLength(&expected_length, sizeof(binary_key_data))) {
87625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        LOG(ERROR) << "Public key too large to base64 encode";
88625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        return false;
89179d9d6587ff4c46746ea8df5c8a6ffe3f1cda3fAdam Langley    }
90d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
91625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    std::string content;
920b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes    content.resize(expected_length);
930b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes    size_t actual_length = EVP_EncodeBlock(reinterpret_cast<uint8_t*>(&content[0]), binary_key_data,
940b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes                                           sizeof(binary_key_data));
950b771b33fd934db9a7962ad704cdd38f72895c1aElliott Hughes    content.resize(actual_length);
96097b6bbc76231f4148c9dd28b6ea0c1189d40fc3Mattias Nissler
97625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    content += get_user_info();
98097b6bbc76231f4148c9dd28b6ea0c1189d40fc3Mattias Nissler
99625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    std::string path(private_key_path + ".pub");
100625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    if (!android::base::WriteStringToFile(content, path)) {
101625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        PLOG(ERROR) << "Failed to write public key to '" << path << "'";
102625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes        return false;
103179d9d6587ff4c46746ea8df5c8a6ffe3f1cda3fAdam Langley    }
104179d9d6587ff4c46746ea8df5c8a6ffe3f1cda3fAdam Langley
105625faf019648255ba1133a67ad1fa844b6de79ecElliott Hughes    return true;
106d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
107d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1080aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughesstatic int generate_key(const std::string& file) {
1090aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    LOG(INFO) << "generate_key(" << file << ")...";
1100aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
11164b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    mode_t old_mask;
112d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    FILE *f = NULL;
113d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    int ret = 0;
114d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1150aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    EVP_PKEY* pkey = EVP_PKEY_new();
1160aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    BIGNUM* exponent = BN_new();
1170aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    RSA* rsa = RSA_new();
118d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!pkey || !exponent || !rsa) {
1190aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        LOG(ERROR) << "Failed to allocate key";
120d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
121d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
122d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
123d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_set_word(exponent, RSA_F4);
124d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA_generate_key_ex(rsa, 2048, exponent, NULL);
125d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    EVP_PKEY_set1_RSA(pkey, rsa);
126d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
12764b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    old_mask = umask(077);
12864b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby
1290aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    f = fopen(file.c_str(), "w");
130d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!f) {
1310aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        PLOG(ERROR) << "Failed to open " << file;
13264b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby        umask(old_mask);
133d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
134d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
135d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
13664b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    umask(old_mask);
13764b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby
138d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
1397a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("Failed to write key");
140d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
141d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
142d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
143d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!write_public_keyfile(rsa, file)) {
1447a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("Failed to write public key");
145d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
146d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
147d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
148d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = 1;
149d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
150d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyout:
1510aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (f) fclose(f);
152d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    EVP_PKEY_free(pkey);
153d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA_free(rsa);
154d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(exponent);
155d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    return ret;
156d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
157d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1582e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic std::string hash_key(RSA* key) {
1592e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    unsigned char* pubkey = nullptr;
1602e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    int len = i2d_RSA_PUBKEY(key, &pubkey);
1612e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    if (len < 0) {
1622e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        LOG(ERROR) << "failed to encode RSA public key";
1632e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return std::string();
1642e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
1652e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
1662e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::string result;
1672e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    result.resize(SHA256_DIGEST_LENGTH);
1682e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    SHA256(pubkey, len, reinterpret_cast<unsigned char*>(&result[0]));
1692e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    OPENSSL_free(pubkey);
1702e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    return result;
1712e671202c38a9b17b0b034438a305e3067abb4abJosh Gao}
1722e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
1732e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic bool read_key_file(const std::string& file) {
1742e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    LOG(INFO) << "read_key_file '" << file << "'...";
175d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1760aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose);
1778d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (!fp) {
1780aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        PLOG(ERROR) << "Failed to open '" << file << "'";
1790aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        return false;
180d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
181d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1820aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    RSA* key = RSA_new();
1830aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) {
1840aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        LOG(ERROR) << "Failed to read key";
1850aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        RSA_free(key);
1860aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        return false;
187d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
188d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
1892e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::lock_guard<std::mutex> lock(g_keys_mutex);
1902e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::string fingerprint = hash_key(key);
1912e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    if (g_keys.find(fingerprint) != g_keys.end()) {
1922e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        LOG(INFO) << "ignoring already-loaded key: " << file;
1932e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        RSA_free(key);
1942e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    } else {
1952e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        g_keys[fingerprint] = std::shared_ptr<RSA>(key, RSA_free);
1962e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
1972e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
1980aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    return true;
199d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
200d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2012e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic bool read_keys(const std::string& path, bool allow_dir = true) {
2022e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    LOG(INFO) << "read_keys '" << path << "'...";
2032e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2042e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    struct stat st;
2052e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    if (stat(path.c_str(), &st) != 0) {
2062e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        PLOG(ERROR) << "failed to stat '" << path << "'";
2072e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return false;
2082e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
2092e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2102e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    if (S_ISREG(st.st_mode)) {
2112e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return read_key_file(path);
2122e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    } else if (S_ISDIR(st.st_mode)) {
2132e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        if (!allow_dir) {
2142e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            // inotify isn't recursive. It would break expectations to load keys in nested
2152e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            // directories but not monitor them for new keys.
2162e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            LOG(WARNING) << "refusing to recurse into directory '" << path << "'";
2172e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            return false;
2182e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
2192e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2202e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        std::unique_ptr<DIR, decltype(&closedir)> dir(opendir(path.c_str()), closedir);
2212e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        if (!dir) {
2222e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            PLOG(ERROR) << "failed to open directory '" << path << "'";
2232e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            return false;
2242e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
2252e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2262e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        bool result = false;
2272e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        while (struct dirent* dent = readdir(dir.get())) {
2282e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            std::string name = dent->d_name;
2292e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2302e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            // We can't use dent->d_type here because it's not available on Windows.
2312e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            if (name == "." || name == "..") {
2322e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                continue;
2332e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            }
2342e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
235a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao            if (!android::base::EndsWith(name, ".adb_key")) {
236a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao                LOG(INFO) << "skipping non-adb_key '" << path << "/" << name << "'";
237a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao                continue;
238a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao            }
239a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao
240a27666b823b265eeab6cb0e9355fd4bcbc34c6e3Josh Gao            result |= read_key_file((path + OS_PATH_SEPARATOR + name));
2412e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
2422e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return result;
2432e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
2442e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2452e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    LOG(ERROR) << "unexpected type for '" << path << "': 0x" << std::hex << st.st_mode;
2462e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    return false;
2472e671202c38a9b17b0b034438a305e3067abb4abJosh Gao}
2482e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
2490aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughesstatic std::string get_user_key_path() {
250e0b7502c7fb12b0ac03a5903562c74820975b833Josh Gao    return adb_get_android_dir_path() + OS_PATH_SEPARATOR + "adbkey";
251d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
252d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2530aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughesstatic bool get_user_key() {
2540aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    std::string path = get_user_key_path();
2550aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (path.empty()) {
2560aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        PLOG(ERROR) << "Error getting user key filename";
2570aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        return false;
258d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
259d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2600aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    struct stat buf;
2610aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (stat(path.c_str(), &buf) == -1) {
2620aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        LOG(INFO) << "User key '" << path << "' does not exist...";
263286bb6ddbd52584af0c6c76fbe0498f3dea4b944Dan Albert        if (!generate_key(path)) {
2640aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes            LOG(ERROR) << "Failed to generate new key";
2650aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes            return false;
266d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        }
267d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
268d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2692e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    return read_key_file(path);
270d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
271d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2722e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic std::set<std::string> get_vendor_keys() {
2738d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    const char* adb_keys_path = getenv("ADB_VENDOR_KEYS");
2748d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    if (adb_keys_path == nullptr) {
2752e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return std::set<std::string>();
2768d5fa6da44d56511b3e173bc463cbc65ff221b4aElliott Hughes    }
277d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2782e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::set<std::string> result;
27965fe2516b402ed8903f2ce39a86fa0bdc2b263a6Elliott Hughes    for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) {
2802e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        result.emplace(path);
281d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
2822e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    return result;
283d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
284d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
2852e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostd::deque<std::shared_ptr<RSA>> adb_auth_get_private_keys() {
2862e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::deque<std::shared_ptr<RSA>> result;
2870aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
2882e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    // Copy all the currently known keys.
2892e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    std::lock_guard<std::mutex> lock(g_keys_mutex);
2902e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    for (const auto& it : g_keys) {
2912e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        result.push_back(it.second);
2920aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    }
2930aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
2940aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    // Add a sentinel to the list. Our caller uses this to mean "out of private keys,
2950aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    // but try using the public key" (the empty deque could otherwise mean this _or_
2960aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    // that this function hasn't been called yet to request the keys).
2970aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    result.push_back(nullptr);
2980aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes
2990aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    return result;
3000aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes}
301d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
30206d61d4d96d28777f76578fb5d3c823168853166Josh Gaostatic int adb_auth_sign(RSA* key, const char* token, size_t token_size, char* sig) {
3037b9c20d3b2aad8b2f67de9478d3d44cc6deff52cSami Tolvanen    if (token_size != TOKEN_SIZE) {
3047a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui        D("Unexpected token size %zd", token_size);
3057b9c20d3b2aad8b2f67de9478d3d44cc6deff52cSami Tolvanen        return 0;
3067b9c20d3b2aad8b2f67de9478d3d44cc6deff52cSami Tolvanen    }
3077b9c20d3b2aad8b2f67de9478d3d44cc6deff52cSami Tolvanen
3080aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    unsigned int len;
30906d61d4d96d28777f76578fb5d3c823168853166Josh Gao    if (!RSA_sign(NID_sha1, reinterpret_cast<const uint8_t*>(token), token_size,
31006d61d4d96d28777f76578fb5d3c823168853166Josh Gao                  reinterpret_cast<uint8_t*>(sig), &len, key)) {
311d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return 0;
312d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
313d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
3147a3f8d6691b3fbd8014a98de8455dbcfcc9629e4Yabin Cui    D("adb_auth_sign len=%d", len);
315d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    return (int)len;
316d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
317d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
318e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughesstd::string adb_auth_get_userkey() {
3190aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    std::string path = get_user_key_path();
3200aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (path.empty()) {
3210aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        PLOG(ERROR) << "Error getting user key filename";
322e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes        return "";
323d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
3240aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    path += ".pub";
325d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
326e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes    std::string content;
327e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes    if (!android::base::ReadFileToString(path, &content)) {
3280aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        PLOG(ERROR) << "Can't load '" << path << "'";
329e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes        return "";
330d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
331e8b663fec3acfefbef6396a23c6f48d66e1f19fcElliott Hughes    return content;
332d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
333d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
334bea3f9c345073069151c9000cd506b9e46b26250Nick Kralevichint adb_auth_keygen(const char* filename) {
335bea3f9c345073069151c9000cd506b9e46b26250Nick Kralevich    return (generate_key(filename) == 0);
336bea3f9c345073069151c9000cd506b9e46b26250Nick Kralevich}
337bea3f9c345073069151c9000cd506b9e46b26250Nick Kralevich
3382e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#if defined(__linux__)
3392e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic void adb_auth_inotify_update(int fd, unsigned fd_event, void*) {
3402e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    LOG(INFO) << "adb_auth_inotify_update called";
3412e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    if (!(fd_event & FDE_READ)) {
3422e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        return;
3432e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
3442e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3452e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
3462e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    while (true) {
3472e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        ssize_t rc = TEMP_FAILURE_RETRY(unix_read(fd, buf, sizeof(buf)));
3482e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        if (rc == -1) {
3492e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            if (errno == EAGAIN) {
3502e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                LOG(INFO) << "done reading inotify fd";
3512e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                break;
3522e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            }
3532e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            PLOG(FATAL) << "read of inotify event failed";
3542e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
3552e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3562e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        // The read potentially returned multiple events.
3572e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        char* start = buf;
3582e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        char* end = buf + rc;
3592e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3602e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        while (start < end) {
3612e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            inotify_event* event = reinterpret_cast<inotify_event*>(start);
3622e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            auto root_it = g_monitored_paths.find(event->wd);
3632e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            if (root_it == g_monitored_paths.end()) {
3642e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                LOG(FATAL) << "observed inotify event for unmonitored path, wd = " << event->wd;
3652e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            }
3662e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3672e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            std::string path = root_it->second;
3682e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            if (event->len > 0) {
3692e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                path += '/';
3702e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                path += event->name;
3712e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            }
3722e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3732e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            if (event->mask & (IN_CREATE | IN_MOVED_TO)) {
3742e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                if (event->mask & IN_ISDIR) {
3752e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                    LOG(INFO) << "ignoring new directory at '" << path << "'";
3762e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                } else {
3772e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                    LOG(INFO) << "observed new file at '" << path << "'";
3782e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                    read_keys(path, false);
3792e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                }
3802e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            } else {
3812e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                LOG(WARNING) << "unmonitored event for " << path << ": 0x" << std::hex
3822e671202c38a9b17b0b034438a305e3067abb4abJosh Gao                             << event->mask;
3832e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            }
3842e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3852e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            start += sizeof(struct inotify_event) + event->len;
3862e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
3872e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
3882e671202c38a9b17b0b034438a305e3067abb4abJosh Gao}
3892e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
3902e671202c38a9b17b0b034438a305e3067abb4abJosh Gaostatic void adb_auth_inotify_init(const std::set<std::string>& paths) {
3912e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    LOG(INFO) << "adb_auth_inotify_init...";
392fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao
3932e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    int infd = inotify_init1(IN_CLOEXEC | IN_NONBLOCK);
394fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao    if (infd < 0) {
395fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao        PLOG(ERROR) << "failed to create inotify fd";
396fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao        return;
397fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao    }
398fb9a7e5995d2e6c2c7f08080201d41fe0f6c4b53Josh Gao
3992e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    for (const std::string& path : paths) {
4002e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        int wd = inotify_add_watch(infd, path.c_str(), IN_CREATE | IN_MOVED_TO);
4012e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        if (wd < 0) {
4022e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            PLOG(ERROR) << "failed to inotify_add_watch on path '" << path;
4032e671202c38a9b17b0b034438a305e3067abb4abJosh Gao            continue;
4042e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        }
4052e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
4062e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        g_monitored_paths[wd] = path;
4072e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        LOG(INFO) << "watch descriptor " << wd << " registered for " << path;
4082e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
4092e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
4102e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    fdevent* event = fdevent_create(infd, adb_auth_inotify_update, nullptr);
4112e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    fdevent_add(event, FDE_READ);
4122e671202c38a9b17b0b034438a305e3067abb4abJosh Gao}
4132e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#endif
4142e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
4150aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughesvoid adb_auth_init() {
4160aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    LOG(INFO) << "adb_auth_init...";
417d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
4180aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes    if (!get_user_key()) {
4190aeb50500c76ea67d6f452907f5503d590e81a54Elliott Hughes        LOG(ERROR) << "Failed to get user key";
420d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return;
421d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
422d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
4232e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    const auto& key_paths = get_vendor_keys();
4242e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
4252e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#if defined(__linux__)
4262e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    adb_auth_inotify_init(key_paths);
4272e671202c38a9b17b0b034438a305e3067abb4abJosh Gao#endif
4282e671202c38a9b17b0b034438a305e3067abb4abJosh Gao
4292e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    for (const std::string& path : key_paths) {
4302e671202c38a9b17b0b034438a305e3067abb4abJosh Gao        read_keys(path.c_str());
4312e671202c38a9b17b0b034438a305e3067abb4abJosh Gao    }
432d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
4333bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4343bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gaostatic void send_auth_publickey(atransport* t) {
4353bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    LOG(INFO) << "Calling send_auth_publickey";
4363bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4373bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    std::string key = adb_auth_get_userkey();
4383bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    if (key.empty()) {
4393bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        D("Failed to get user public key");
4403bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        return;
4413bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    }
4423bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4433bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    if (key.size() >= MAX_PAYLOAD_V1) {
4443bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        D("User public key too large (%zu B)", key.size());
4453bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        return;
4463bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    }
4473bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4483bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    apacket* p = get_apacket();
4493bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    memcpy(p->data, key.c_str(), key.size() + 1);
4503bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4513bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.command = A_AUTH;
4523bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
4533bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4543bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    // adbd expects a null-terminated string.
4553bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.data_length = key.size() + 1;
4563bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    send_packet(p, t);
4573bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao}
4583bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
45906d61d4d96d28777f76578fb5d3c823168853166Josh Gaovoid send_auth_response(const char* token, size_t token_size, atransport* t) {
4603bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    std::shared_ptr<RSA> key = t->NextKey();
4613bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    if (key == nullptr) {
4623bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        // No more private keys to try, send the public key.
4633bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        send_auth_publickey(t);
4643bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        return;
4653bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    }
4663bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4673bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    LOG(INFO) << "Calling send_auth_response";
4683bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    apacket* p = get_apacket();
4693bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4703bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    int ret = adb_auth_sign(key.get(), token, token_size, p->data);
4713bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    if (!ret) {
4723bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        D("Error signing the token");
4733bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        put_apacket(p);
4743bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao        return;
4753bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    }
4763bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao
4773bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.command = A_AUTH;
4783bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.arg0 = ADB_AUTH_SIGNATURE;
4793bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    p->msg.data_length = ret;
4803bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao    send_packet(p, t);
4813bd2879d8e9bb0c0a1b8045e09f9cf87c2daeef3Josh Gao}
482