Loading adb/adb.cpp +3 −11 Original line number Diff line number Diff line Loading @@ -354,21 +354,13 @@ void handle_packet(apacket *p, atransport *t) case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->connection_state = kCsUnauthorized; t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { Loading adb/adb_auth.cpp +39 −34 Original line number Diff line number Diff line Loading @@ -16,8 +16,9 @@ #define TRACE_TAG ADB #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "transport.h" #include <errno.h> #include <stdio.h> Loading @@ -25,53 +26,28 @@ #include <sys/types.h> #include <unistd.h> #include "adb.h" #include "transport.h" bool auth_required = true; void send_auth_request(atransport *t) { D("Calling send_auth_request"); apacket *p; int ret; LOG(INFO) << "Calling send_auth_request..."; ret = adb_auth_generate_token(t->token, sizeof(t->token)); if (ret != sizeof(t->token)) { D("Error generating token ret=%d", ret); if (!adb_auth_generate_token(t->token, sizeof(t->token))) { PLOG(ERROR) << "Error generating token"; return; } p = get_apacket(); memcpy(p->data, t->token, ret); apacket* p = get_apacket(); memcpy(p->data, t->token, sizeof(t->token)); p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_TOKEN; p->msg.data_length = ret; p->msg.data_length = sizeof(t->token); send_packet(p, t); } void send_auth_response(uint8_t *token, size_t token_size, atransport *t) { D("Calling send_auth_response"); apacket *p = get_apacket(); int ret; ret = adb_auth_sign(t->key, token, token_size, p->data); if (!ret) { D("Error signing the token"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_publickey(atransport* t) { LOG(INFO) << "Calling send_auth_publickey"; void send_auth_publickey(atransport *t) { D("Calling send_auth_publickey"); std::string key = adb_auth_get_userkey(); if (key.empty()) { D("Failed to get user public key"); Loading @@ -92,6 +68,35 @@ void send_auth_publickey(atransport *t) send_packet(p, t); } void send_auth_response(uint8_t* token, size_t token_size, atransport* t) { RSA* key = t->NextKey(); if (key == nullptr) { // No more private keys to try, send the public key. send_auth_publickey(t); return; } LOG(INFO) << "Calling send_auth_response"; apacket* p = get_apacket(); int ret = adb_auth_sign(key, token, token_size, p->data); // Stop sharing this key. RSA_free(key); key = nullptr; if (!ret) { D("Error signing the token"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } void adb_auth_verified(atransport *t) { handle_online(t); Loading adb/adb_auth.h +15 −23 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ #include "adb.h" #include <deque> #include <openssl/rsa.h> extern bool auth_required; int adb_auth_keygen(const char* filename); Loading @@ -26,7 +30,6 @@ void adb_auth_verified(atransport *t); void send_auth_request(atransport *t); void send_auth_response(uint8_t *token, size_t token_size, atransport *t); void send_auth_publickey(atransport *t); /* AUTH packets first argument */ /* Request */ Loading @@ -37,36 +40,25 @@ void send_auth_publickey(atransport *t); #if ADB_HOST void adb_auth_init(void); int adb_auth_sign(void *key, const unsigned char* token, size_t token_size, unsigned char* sig); void *adb_auth_nextkey(void *current); void adb_auth_init(); int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig); std::string adb_auth_get_userkey(); std::deque<RSA*> adb_auth_get_private_keys(); static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } static inline int adb_auth_verify(void *token, size_t token_size, void *sig, int siglen) { return 0; } static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) {} static inline bool adb_auth_generate_token(void*, size_t) { abort(); } static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); } static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); } #else // !ADB_HOST static inline int adb_auth_sign(void* key, const unsigned char* token, size_t token_size, unsigned char* sig) { return 0; } static inline void *adb_auth_nextkey(void *current) { return NULL; } static inline std::string adb_auth_get_userkey() { return ""; } static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); } static inline std::string adb_auth_get_userkey() { abort(); } static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); } void adbd_auth_init(void); void adbd_cloexec_auth_socket(); int adb_auth_generate_token(void *token, size_t token_size); int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen); bool adb_auth_generate_token(void* token, size_t token_size); bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); #endif // ADB_HOST Loading adb/adb_auth_client.cpp +69 −153 Original line number Diff line number Diff line Loading @@ -16,37 +16,25 @@ #define TRACE_TAG AUTH #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "fdevent.h" #include "sysdeps.h" #include "transport.h" #include <resolv.h> #include <stdio.h> #include <string.h> #include <memory> #include <android-base/file.h> #include <android-base/strings.h> #include <crypto_utils/android_pubkey.h> #include <openssl/obj_mac.h> #include <openssl/rsa.h> #include <openssl/sha.h> #include <crypto_utils/android_pubkey.h> #include "cutils/list.h" #include "cutils/sockets.h" #include "adb.h" #include "fdevent.h" #include "transport.h" struct adb_public_key { struct listnode node; RSA* key; }; static const char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", NULL }; static fdevent listener_fde; static fdevent framework_fde; static int framework_fd = -1; Loading @@ -56,135 +44,71 @@ static struct adisconnect usb_disconnect = { usb_disconnected, nullptr}; static atransport* usb_transport; static bool needs_retry = false; static void read_keys(const char *file, struct listnode *list) { FILE *f; char buf[MAX_PAYLOAD_V1]; char *sep; int ret; bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) { static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr }; f = fopen(file, "re"); if (!f) { D("Can't open '%s'", file); return; } for (const auto& path : key_paths) { if (access(path, R_OK) == 0) { LOG(INFO) << "Loading keys from " << path; while (fgets(buf, sizeof(buf), f)) { auto key = reinterpret_cast<adb_public_key*>( calloc(1, sizeof(adb_public_key))); if (key == nullptr) { D("Can't malloc key"); break; std::string content; if (!android::base::ReadFileToString(path, &content)) { PLOG(ERROR) << "Couldn't read " << path; continue; } sep = strpbrk(buf, " \t"); if (sep) *sep = '\0'; for (const auto& line : android::base::Split(content, "\n")) { // TODO: do we really have to support both ' ' and '\t'? char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t"); if (sep) *sep = '\0'; // b64_pton requires one additional byte in the target buffer for // decoding to succeed. See http://b/28035006 for details. uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; ret = __b64_pton(buf, keybuf, sizeof(keybuf)); if (ret != ANDROID_PUBKEY_ENCODED_SIZE) { D("%s: Invalid base64 data ret=%d", file, ret); free(key); if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path; continue; } if (!android_pubkey_decode(keybuf, ret, &key->key)) { D("%s: Failed to parse key", file); free(key); RSA* key = nullptr; if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) { LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path; continue; } list_add_tail(list, &key->node); } fclose(f); } static void free_keys(struct listnode *list) { struct listnode *item; while (!list_empty(list)) { item = list_head(list); list_remove(item); adb_public_key* key = node_to_item(item, struct adb_public_key, node); RSA_free(key->key); free(key); } } static void load_keys(struct listnode *list) { const char* path; const char** paths = key_paths; struct stat buf; list_init(list); while ((path = *paths++)) { if (!stat(path, &buf)) { D("Loading keys from '%s'", path); read_keys(path, list); bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1); RSA_free(key); if (verified) return true; } } } int adb_auth_generate_token(void *token, size_t token_size) { FILE *f; int ret; f = fopen("/dev/urandom", "re"); if (!f) return 0; ret = fread(token, token_size, 1, f); fclose(f); return ret * token_size; return false; } int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen) { struct listnode *item; struct listnode key_list; int ret = 0; load_keys(&key_list); list_for_each(item, &key_list) { adb_public_key* key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key); if (ret) break; } free_keys(&key_list); return ret; bool adb_auth_generate_token(void* token, size_t token_size) { FILE* fp = fopen("/dev/urandom", "re"); if (!fp) return false; bool okay = (fread(token, token_size, 1, fp) == 1); fclose(fp); return okay; } static void usb_disconnected(void* unused, atransport* t) { D("USB disconnect"); LOG(INFO) << "USB disconnect"; usb_transport = NULL; needs_retry = false; } static void framework_disconnected() { D("Framework disconnect"); LOG(INFO) << "Framework disconnect"; fdevent_remove(&framework_fde); framework_fd = -1; } static void adb_auth_event(int fd, unsigned events, void*) { char response[2]; int ret; if (events & FDE_READ) { ret = unix_read(fd, response, sizeof(response)); char response[2]; int ret = unix_read(fd, response, sizeof(response)); if (ret <= 0) { framework_disconnected(); } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { Loading @@ -195,51 +119,43 @@ static void adb_auth_event(int fd, unsigned events, void*) { } } void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) { char msg[MAX_PAYLOAD_V1]; int ret; void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) { if (!usb_transport) { usb_transport = t; t->AddDisconnect(&usb_disconnect); } if (framework_fd < 0) { D("Client not connected"); LOG(ERROR) << "Client not connected"; needs_retry = true; return; } if (key[len - 1] != '\0') { D("Key must be a null-terminated string"); LOG(ERROR) << "Key must be a null-terminated string"; return; } ret = snprintf(msg, sizeof(msg), "PK%s", key); if (ret >= (signed)sizeof(msg)) { D("Key too long. ret=%d", ret); char msg[MAX_PAYLOAD_V1]; int msg_len = snprintf(msg, sizeof(msg), "PK%s", key); if (msg_len >= static_cast<int>(sizeof(msg))) { LOG(ERROR) << "Key too long (" << msg_len << ")"; return; } D("Sending '%s'", msg); LOG(DEBUG) << "Sending '" << msg << "'"; ret = unix_write(framework_fd, msg, ret); if (ret < 0) { D("Failed to write PK, errno=%d", errno); if (unix_write(framework_fd, msg, msg_len) == -1) { PLOG(ERROR) << "Failed to write PK"; return; } } static void adb_auth_listener(int fd, unsigned events, void* data) { sockaddr_storage addr; socklen_t alen; int s; alen = sizeof(addr); s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen); socklen_t alen = sizeof(addr); int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen); if (s < 0) { D("Failed to accept: errno=%d", errno); PLOG(ERROR) << "Failed to accept"; return; } Loading @@ -261,7 +177,7 @@ static void adb_auth_listener(int fd, unsigned events, void* data) { void adbd_cloexec_auth_socket() { int fd = android_get_control_socket("adbd"); if (fd == -1) { D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket"; return; } fcntl(fd, F_SETFD, FD_CLOEXEC); Loading @@ -270,12 +186,12 @@ void adbd_cloexec_auth_socket() { void adbd_auth_init(void) { int fd = android_get_control_socket("adbd"); if (fd == -1) { D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket"; return; } if (listen(fd, 4) == -1) { D("Failed to listen on '%d'", fd); PLOG(ERROR) << "Failed to listen on '" << fd << "'"; return; } Loading adb/adb_auth_host.cpp +87 −119 Original line number Diff line number Diff line Loading @@ -16,23 +16,22 @@ #define TRACE_TAG AUTH #include "sysdeps.h" #include "adb_auth.h" #include "adb.h" #include "adb_utils.h" #include "sysdeps.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "adb.h" #include <mutex> #include <android-base/errors.h> #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <crypto_utils/android_pubkey.h> #include <cutils/list.h> #include <openssl/base64.h> #include <openssl/evp.h> #include <openssl/objects.h> Loading @@ -40,18 +39,14 @@ #include <openssl/rsa.h> #include <openssl/sha.h> #define ANDROID_PATH ".android" #define ADB_KEY_FILE "adbkey" struct adb_private_key { struct listnode node; RSA *rsa; }; static struct listnode key_list; #include "sysdeps/mutex.h" static std::mutex& g_key_list_mutex = *new std::mutex; static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>; static std::string get_user_info() { LOG(INFO) << "get_user_info..."; std::string hostname; if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME"); #if !defined(_WIN32) Loading @@ -71,6 +66,8 @@ static std::string get_user_info() { } static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) { LOG(INFO) << "write_public_keyfile..."; 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"; Loading Loading @@ -99,19 +96,18 @@ static bool write_public_keyfile(RSA* private_key, const std::string& private_ke return true; } static int generate_key(const char *file) { EVP_PKEY* pkey = EVP_PKEY_new(); BIGNUM* exponent = BN_new(); RSA* rsa = RSA_new(); static int generate_key(const std::string& file) { LOG(INFO) << "generate_key(" << file << ")..."; mode_t old_mask; FILE *f = NULL; int ret = 0; D("generate_key '%s'", file); EVP_PKEY* pkey = EVP_PKEY_new(); BIGNUM* exponent = BN_new(); RSA* rsa = RSA_new(); if (!pkey || !exponent || !rsa) { D("Failed to allocate key"); LOG(ERROR) << "Failed to allocate key"; goto out; } Loading @@ -121,9 +117,9 @@ static int generate_key(const char *file) old_mask = umask(077); f = fopen(file, "w"); f = fopen(file.c_str(), "w"); if (!f) { D("Failed to open '%s'", file); PLOG(ERROR) << "Failed to open " << file; umask(old_mask); goto out; } Loading @@ -143,110 +139,110 @@ static int generate_key(const char *file) ret = 1; out: if (f) fclose(f); if (f) fclose(f); EVP_PKEY_free(pkey); RSA_free(rsa); BN_free(exponent); return ret; } static int read_key(const char *file, struct listnode *list) { D("read_key '%s'", file); static bool read_key(const std::string& file) { LOG(INFO) << "read_key '" << file << "'..."; FILE* fp = fopen(file, "r"); std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose); if (!fp) { D("Failed to open '%s': %s", file, strerror(errno)); return 0; PLOG(ERROR) << "Failed to open '" << file << "'"; return false; } adb_private_key* key = new adb_private_key; key->rsa = RSA_new(); if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) { D("Failed to read key"); fclose(fp); RSA_free(key->rsa); delete key; return 0; RSA* key = RSA_new(); if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) { LOG(ERROR) << "Failed to read key"; RSA_free(key); return false; } fclose(fp); list_add_tail(list, &key->node); return 1; g_key_list.push_back(key); return true; } static int get_user_keyfilepath(char *filename, size_t len) { static std::string get_user_key_path() { const std::string home = adb_get_homedir_path(true); D("home '%s'", home.c_str()); LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'"; const std::string android_dir = android::base::StringPrintf("%s%c%s", home.c_str(), OS_PATH_SEPARATOR, ANDROID_PATH); const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(), OS_PATH_SEPARATOR); struct stat buf; if (stat(android_dir.c_str(), &buf)) { if (adb_mkdir(android_dir.c_str(), 0750) < 0) { D("Cannot mkdir '%s'", android_dir.c_str()); return -1; if (stat(android_dir.c_str(), &buf) == -1) { if (adb_mkdir(android_dir.c_str(), 0750) == -1) { PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'"; return ""; } } return snprintf(filename, len, "%s%c%s", android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE); return android_dir + OS_PATH_SEPARATOR + "adbkey"; } static int get_user_key(struct listnode *list) { struct stat buf; char path[PATH_MAX]; int ret; ret = get_user_keyfilepath(path, sizeof(path)); if (ret < 0 || ret >= (signed)sizeof(path)) { D("Error getting user key filename"); return 0; static bool get_user_key() { std::string path = get_user_key_path(); if (path.empty()) { PLOG(ERROR) << "Error getting user key filename"; return false; } D("user key '%s'", path); if (stat(path, &buf) == -1) { struct stat buf; if (stat(path.c_str(), &buf) == -1) { LOG(INFO) << "User key '" << path << "' does not exist..."; if (!generate_key(path)) { D("Failed to generate new key"); return 0; LOG(ERROR) << "Failed to generate new key"; return false; } } return read_key(path, list); return read_key(path); } static void get_vendor_keys(struct listnode* key_list) { static void get_vendor_keys() { const char* adb_keys_path = getenv("ADB_VENDOR_KEYS"); if (adb_keys_path == nullptr) { return; } for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) { if (!read_key(path.c_str(), key_list)) { D("Failed to read '%s'", path.c_str()); if (!read_key(path.c_str())) { PLOG(ERROR) << "Failed to read '" << path << "'"; } } } int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, unsigned char* sig) { unsigned int len; struct adb_private_key *key = node_to_item(node, struct adb_private_key, node); std::deque<RSA*> adb_auth_get_private_keys() { std::deque<RSA*> result; // Copy all the currently known keys, increasing their reference count so they're // usable until both we and the caller have freed our pointers. std::lock_guard<std::mutex> lock(g_key_list_mutex); for (const auto& key : g_key_list) { RSA_up_ref(key); // Since we're handing out another pointer to this key... result.push_back(key); } // Add a sentinel to the list. Our caller uses this to mean "out of private keys, // but try using the public key" (the empty deque could otherwise mean this _or_ // that this function hasn't been called yet to request the keys). result.push_back(nullptr); return result; } int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) { if (token_size != TOKEN_SIZE) { D("Unexpected token size %zd", token_size); return 0; } if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) { unsigned int len; if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) { return 0; } Loading @@ -254,40 +250,17 @@ int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, return (int)len; } void *adb_auth_nextkey(void *current) { struct listnode *item; if (list_empty(&key_list)) return NULL; if (!current) return list_head(&key_list); list_for_each(item, &key_list) { if (item == current) { /* current is the last item, we tried all the keys */ if (item->next == &key_list) return NULL; return item->next; } } return NULL; } std::string adb_auth_get_userkey() { char path[PATH_MAX]; int ret = get_user_keyfilepath(path, sizeof(path) - 4); if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { D("Error getting user key filename"); std::string path = get_user_key_path(); if (path.empty()) { PLOG(ERROR) << "Error getting user key filename"; return ""; } strcat(path, ".pub"); path += ".pub"; std::string content; if (!android::base::ReadFileToString(path, &content)) { D("Can't load '%s'", path); PLOG(ERROR) << "Can't load '" << path << "'"; return ""; } return content; Loading @@ -297,19 +270,14 @@ int adb_auth_keygen(const char* filename) { return (generate_key(filename) == 0); } void adb_auth_init(void) { int ret; D("adb_auth_init"); list_init(&key_list); void adb_auth_init() { LOG(INFO) << "adb_auth_init..."; ret = get_user_key(&key_list); if (!ret) { D("Failed to get user key"); if (!get_user_key()) { LOG(ERROR) << "Failed to get user key"; return; } get_vendor_keys(&key_list); std::lock_guard<std::mutex> lock(g_key_list_mutex); get_vendor_keys(); } Loading
adb/adb.cpp +3 −11 Original line number Diff line number Diff line Loading @@ -354,21 +354,13 @@ void handle_packet(apacket *p, atransport *t) case A_AUTH: if (p->msg.arg0 == ADB_AUTH_TOKEN) { t->connection_state = kCsUnauthorized; t->key = adb_auth_nextkey(t->key); if (t->key) { send_auth_response(p->data, p->msg.data_length, t); } else { /* No more private keys to try, send the public key */ send_auth_publickey(t); } } else if (p->msg.arg0 == ADB_AUTH_SIGNATURE) { if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { if (adb_auth_verify(t->token, sizeof(t->token), p->data, p->msg.data_length)) { adb_auth_verified(t); t->failed_auth_attempts = 0; } else { if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); if (t->failed_auth_attempts++ > 10) adb_sleep_ms(1000); send_auth_request(t); } } else if (p->msg.arg0 == ADB_AUTH_RSAPUBLICKEY) { Loading
adb/adb_auth.cpp +39 −34 Original line number Diff line number Diff line Loading @@ -16,8 +16,9 @@ #define TRACE_TAG ADB #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "transport.h" #include <errno.h> #include <stdio.h> Loading @@ -25,53 +26,28 @@ #include <sys/types.h> #include <unistd.h> #include "adb.h" #include "transport.h" bool auth_required = true; void send_auth_request(atransport *t) { D("Calling send_auth_request"); apacket *p; int ret; LOG(INFO) << "Calling send_auth_request..."; ret = adb_auth_generate_token(t->token, sizeof(t->token)); if (ret != sizeof(t->token)) { D("Error generating token ret=%d", ret); if (!adb_auth_generate_token(t->token, sizeof(t->token))) { PLOG(ERROR) << "Error generating token"; return; } p = get_apacket(); memcpy(p->data, t->token, ret); apacket* p = get_apacket(); memcpy(p->data, t->token, sizeof(t->token)); p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_TOKEN; p->msg.data_length = ret; p->msg.data_length = sizeof(t->token); send_packet(p, t); } void send_auth_response(uint8_t *token, size_t token_size, atransport *t) { D("Calling send_auth_response"); apacket *p = get_apacket(); int ret; ret = adb_auth_sign(t->key, token, token_size, p->data); if (!ret) { D("Error signing the token"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } static void send_auth_publickey(atransport* t) { LOG(INFO) << "Calling send_auth_publickey"; void send_auth_publickey(atransport *t) { D("Calling send_auth_publickey"); std::string key = adb_auth_get_userkey(); if (key.empty()) { D("Failed to get user public key"); Loading @@ -92,6 +68,35 @@ void send_auth_publickey(atransport *t) send_packet(p, t); } void send_auth_response(uint8_t* token, size_t token_size, atransport* t) { RSA* key = t->NextKey(); if (key == nullptr) { // No more private keys to try, send the public key. send_auth_publickey(t); return; } LOG(INFO) << "Calling send_auth_response"; apacket* p = get_apacket(); int ret = adb_auth_sign(key, token, token_size, p->data); // Stop sharing this key. RSA_free(key); key = nullptr; if (!ret) { D("Error signing the token"); put_apacket(p); return; } p->msg.command = A_AUTH; p->msg.arg0 = ADB_AUTH_SIGNATURE; p->msg.data_length = ret; send_packet(p, t); } void adb_auth_verified(atransport *t) { handle_online(t); Loading
adb/adb_auth.h +15 −23 Original line number Diff line number Diff line Loading @@ -19,6 +19,10 @@ #include "adb.h" #include <deque> #include <openssl/rsa.h> extern bool auth_required; int adb_auth_keygen(const char* filename); Loading @@ -26,7 +30,6 @@ void adb_auth_verified(atransport *t); void send_auth_request(atransport *t); void send_auth_response(uint8_t *token, size_t token_size, atransport *t); void send_auth_publickey(atransport *t); /* AUTH packets first argument */ /* Request */ Loading @@ -37,36 +40,25 @@ void send_auth_publickey(atransport *t); #if ADB_HOST void adb_auth_init(void); int adb_auth_sign(void *key, const unsigned char* token, size_t token_size, unsigned char* sig); void *adb_auth_nextkey(void *current); void adb_auth_init(); int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig); std::string adb_auth_get_userkey(); std::deque<RSA*> adb_auth_get_private_keys(); static inline int adb_auth_generate_token(void *token, size_t token_size) { return 0; } static inline int adb_auth_verify(void *token, size_t token_size, void *sig, int siglen) { return 0; } static inline void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t) {} static inline bool adb_auth_generate_token(void*, size_t) { abort(); } static inline bool adb_auth_verify(void*, size_t, void*, int) { abort(); } static inline void adb_auth_confirm_key(unsigned char*, size_t, atransport*) { abort(); } #else // !ADB_HOST static inline int adb_auth_sign(void* key, const unsigned char* token, size_t token_size, unsigned char* sig) { return 0; } static inline void *adb_auth_nextkey(void *current) { return NULL; } static inline std::string adb_auth_get_userkey() { return ""; } static inline int adb_auth_sign(void*, const unsigned char*, size_t, unsigned char*) { abort(); } static inline std::string adb_auth_get_userkey() { abort(); } static inline std::deque<RSA*> adb_auth_get_private_keys() { abort(); } void adbd_auth_init(void); void adbd_cloexec_auth_socket(); int adb_auth_generate_token(void *token, size_t token_size); int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen); bool adb_auth_generate_token(void* token, size_t token_size); bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len); void adb_auth_confirm_key(unsigned char *data, size_t len, atransport *t); #endif // ADB_HOST Loading
adb/adb_auth_client.cpp +69 −153 Original line number Diff line number Diff line Loading @@ -16,37 +16,25 @@ #define TRACE_TAG AUTH #include "sysdeps.h" #include "adb.h" #include "adb_auth.h" #include "fdevent.h" #include "sysdeps.h" #include "transport.h" #include <resolv.h> #include <stdio.h> #include <string.h> #include <memory> #include <android-base/file.h> #include <android-base/strings.h> #include <crypto_utils/android_pubkey.h> #include <openssl/obj_mac.h> #include <openssl/rsa.h> #include <openssl/sha.h> #include <crypto_utils/android_pubkey.h> #include "cutils/list.h" #include "cutils/sockets.h" #include "adb.h" #include "fdevent.h" #include "transport.h" struct adb_public_key { struct listnode node; RSA* key; }; static const char *key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", NULL }; static fdevent listener_fde; static fdevent framework_fde; static int framework_fd = -1; Loading @@ -56,135 +44,71 @@ static struct adisconnect usb_disconnect = { usb_disconnected, nullptr}; static atransport* usb_transport; static bool needs_retry = false; static void read_keys(const char *file, struct listnode *list) { FILE *f; char buf[MAX_PAYLOAD_V1]; char *sep; int ret; bool adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int sig_len) { static constexpr const char* key_paths[] = { "/adb_keys", "/data/misc/adb/adb_keys", nullptr }; f = fopen(file, "re"); if (!f) { D("Can't open '%s'", file); return; } for (const auto& path : key_paths) { if (access(path, R_OK) == 0) { LOG(INFO) << "Loading keys from " << path; while (fgets(buf, sizeof(buf), f)) { auto key = reinterpret_cast<adb_public_key*>( calloc(1, sizeof(adb_public_key))); if (key == nullptr) { D("Can't malloc key"); break; std::string content; if (!android::base::ReadFileToString(path, &content)) { PLOG(ERROR) << "Couldn't read " << path; continue; } sep = strpbrk(buf, " \t"); if (sep) *sep = '\0'; for (const auto& line : android::base::Split(content, "\n")) { // TODO: do we really have to support both ' ' and '\t'? char* sep = strpbrk(const_cast<char*>(line.c_str()), " \t"); if (sep) *sep = '\0'; // b64_pton requires one additional byte in the target buffer for // decoding to succeed. See http://b/28035006 for details. uint8_t keybuf[ANDROID_PUBKEY_ENCODED_SIZE + 1]; ret = __b64_pton(buf, keybuf, sizeof(keybuf)); if (ret != ANDROID_PUBKEY_ENCODED_SIZE) { D("%s: Invalid base64 data ret=%d", file, ret); free(key); if (__b64_pton(line.c_str(), keybuf, sizeof(keybuf)) != ANDROID_PUBKEY_ENCODED_SIZE) { LOG(ERROR) << "Invalid base64 key " << line.c_str() << " in " << path; continue; } if (!android_pubkey_decode(keybuf, ret, &key->key)) { D("%s: Failed to parse key", file); free(key); RSA* key = nullptr; if (!android_pubkey_decode(keybuf, ANDROID_PUBKEY_ENCODED_SIZE, &key)) { LOG(ERROR) << "Failed to parse key " << line.c_str() << " in " << path; continue; } list_add_tail(list, &key->node); } fclose(f); } static void free_keys(struct listnode *list) { struct listnode *item; while (!list_empty(list)) { item = list_head(list); list_remove(item); adb_public_key* key = node_to_item(item, struct adb_public_key, node); RSA_free(key->key); free(key); } } static void load_keys(struct listnode *list) { const char* path; const char** paths = key_paths; struct stat buf; list_init(list); while ((path = *paths++)) { if (!stat(path, &buf)) { D("Loading keys from '%s'", path); read_keys(path, list); bool verified = (RSA_verify(NID_sha1, token, token_size, sig, sig_len, key) == 1); RSA_free(key); if (verified) return true; } } } int adb_auth_generate_token(void *token, size_t token_size) { FILE *f; int ret; f = fopen("/dev/urandom", "re"); if (!f) return 0; ret = fread(token, token_size, 1, f); fclose(f); return ret * token_size; return false; } int adb_auth_verify(uint8_t* token, size_t token_size, uint8_t* sig, int siglen) { struct listnode *item; struct listnode key_list; int ret = 0; load_keys(&key_list); list_for_each(item, &key_list) { adb_public_key* key = node_to_item(item, struct adb_public_key, node); ret = RSA_verify(NID_sha1, token, token_size, sig, siglen, key->key); if (ret) break; } free_keys(&key_list); return ret; bool adb_auth_generate_token(void* token, size_t token_size) { FILE* fp = fopen("/dev/urandom", "re"); if (!fp) return false; bool okay = (fread(token, token_size, 1, fp) == 1); fclose(fp); return okay; } static void usb_disconnected(void* unused, atransport* t) { D("USB disconnect"); LOG(INFO) << "USB disconnect"; usb_transport = NULL; needs_retry = false; } static void framework_disconnected() { D("Framework disconnect"); LOG(INFO) << "Framework disconnect"; fdevent_remove(&framework_fde); framework_fd = -1; } static void adb_auth_event(int fd, unsigned events, void*) { char response[2]; int ret; if (events & FDE_READ) { ret = unix_read(fd, response, sizeof(response)); char response[2]; int ret = unix_read(fd, response, sizeof(response)); if (ret <= 0) { framework_disconnected(); } else if (ret == 2 && response[0] == 'O' && response[1] == 'K') { Loading @@ -195,51 +119,43 @@ static void adb_auth_event(int fd, unsigned events, void*) { } } void adb_auth_confirm_key(unsigned char *key, size_t len, atransport *t) { char msg[MAX_PAYLOAD_V1]; int ret; void adb_auth_confirm_key(unsigned char* key, size_t len, atransport* t) { if (!usb_transport) { usb_transport = t; t->AddDisconnect(&usb_disconnect); } if (framework_fd < 0) { D("Client not connected"); LOG(ERROR) << "Client not connected"; needs_retry = true; return; } if (key[len - 1] != '\0') { D("Key must be a null-terminated string"); LOG(ERROR) << "Key must be a null-terminated string"; return; } ret = snprintf(msg, sizeof(msg), "PK%s", key); if (ret >= (signed)sizeof(msg)) { D("Key too long. ret=%d", ret); char msg[MAX_PAYLOAD_V1]; int msg_len = snprintf(msg, sizeof(msg), "PK%s", key); if (msg_len >= static_cast<int>(sizeof(msg))) { LOG(ERROR) << "Key too long (" << msg_len << ")"; return; } D("Sending '%s'", msg); LOG(DEBUG) << "Sending '" << msg << "'"; ret = unix_write(framework_fd, msg, ret); if (ret < 0) { D("Failed to write PK, errno=%d", errno); if (unix_write(framework_fd, msg, msg_len) == -1) { PLOG(ERROR) << "Failed to write PK"; return; } } static void adb_auth_listener(int fd, unsigned events, void* data) { sockaddr_storage addr; socklen_t alen; int s; alen = sizeof(addr); s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen); socklen_t alen = sizeof(addr); int s = adb_socket_accept(fd, reinterpret_cast<sockaddr*>(&addr), &alen); if (s < 0) { D("Failed to accept: errno=%d", errno); PLOG(ERROR) << "Failed to accept"; return; } Loading @@ -261,7 +177,7 @@ static void adb_auth_listener(int fd, unsigned events, void* data) { void adbd_cloexec_auth_socket() { int fd = android_get_control_socket("adbd"); if (fd == -1) { D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket"; return; } fcntl(fd, F_SETFD, FD_CLOEXEC); Loading @@ -270,12 +186,12 @@ void adbd_cloexec_auth_socket() { void adbd_auth_init(void) { int fd = android_get_control_socket("adbd"); if (fd == -1) { D("Failed to get adbd socket"); PLOG(ERROR) << "Failed to get adbd socket"; return; } if (listen(fd, 4) == -1) { D("Failed to listen on '%d'", fd); PLOG(ERROR) << "Failed to listen on '" << fd << "'"; return; } Loading
adb/adb_auth_host.cpp +87 −119 Original line number Diff line number Diff line Loading @@ -16,23 +16,22 @@ #define TRACE_TAG AUTH #include "sysdeps.h" #include "adb_auth.h" #include "adb.h" #include "adb_utils.h" #include "sysdeps.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include "adb.h" #include <mutex> #include <android-base/errors.h> #include <android-base/file.h> #include <android-base/stringprintf.h> #include <android-base/strings.h> #include <crypto_utils/android_pubkey.h> #include <cutils/list.h> #include <openssl/base64.h> #include <openssl/evp.h> #include <openssl/objects.h> Loading @@ -40,18 +39,14 @@ #include <openssl/rsa.h> #include <openssl/sha.h> #define ANDROID_PATH ".android" #define ADB_KEY_FILE "adbkey" struct adb_private_key { struct listnode node; RSA *rsa; }; static struct listnode key_list; #include "sysdeps/mutex.h" static std::mutex& g_key_list_mutex = *new std::mutex; static std::deque<RSA*>& g_key_list = *new std::deque<RSA*>; static std::string get_user_info() { LOG(INFO) << "get_user_info..."; std::string hostname; if (getenv("HOSTNAME")) hostname = getenv("HOSTNAME"); #if !defined(_WIN32) Loading @@ -71,6 +66,8 @@ static std::string get_user_info() { } static bool write_public_keyfile(RSA* private_key, const std::string& private_key_path) { LOG(INFO) << "write_public_keyfile..."; 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"; Loading Loading @@ -99,19 +96,18 @@ static bool write_public_keyfile(RSA* private_key, const std::string& private_ke return true; } static int generate_key(const char *file) { EVP_PKEY* pkey = EVP_PKEY_new(); BIGNUM* exponent = BN_new(); RSA* rsa = RSA_new(); static int generate_key(const std::string& file) { LOG(INFO) << "generate_key(" << file << ")..."; mode_t old_mask; FILE *f = NULL; int ret = 0; D("generate_key '%s'", file); EVP_PKEY* pkey = EVP_PKEY_new(); BIGNUM* exponent = BN_new(); RSA* rsa = RSA_new(); if (!pkey || !exponent || !rsa) { D("Failed to allocate key"); LOG(ERROR) << "Failed to allocate key"; goto out; } Loading @@ -121,9 +117,9 @@ static int generate_key(const char *file) old_mask = umask(077); f = fopen(file, "w"); f = fopen(file.c_str(), "w"); if (!f) { D("Failed to open '%s'", file); PLOG(ERROR) << "Failed to open " << file; umask(old_mask); goto out; } Loading @@ -143,110 +139,110 @@ static int generate_key(const char *file) ret = 1; out: if (f) fclose(f); if (f) fclose(f); EVP_PKEY_free(pkey); RSA_free(rsa); BN_free(exponent); return ret; } static int read_key(const char *file, struct listnode *list) { D("read_key '%s'", file); static bool read_key(const std::string& file) { LOG(INFO) << "read_key '" << file << "'..."; FILE* fp = fopen(file, "r"); std::unique_ptr<FILE, decltype(&fclose)> fp(fopen(file.c_str(), "r"), fclose); if (!fp) { D("Failed to open '%s': %s", file, strerror(errno)); return 0; PLOG(ERROR) << "Failed to open '" << file << "'"; return false; } adb_private_key* key = new adb_private_key; key->rsa = RSA_new(); if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) { D("Failed to read key"); fclose(fp); RSA_free(key->rsa); delete key; return 0; RSA* key = RSA_new(); if (!PEM_read_RSAPrivateKey(fp.get(), &key, nullptr, nullptr)) { LOG(ERROR) << "Failed to read key"; RSA_free(key); return false; } fclose(fp); list_add_tail(list, &key->node); return 1; g_key_list.push_back(key); return true; } static int get_user_keyfilepath(char *filename, size_t len) { static std::string get_user_key_path() { const std::string home = adb_get_homedir_path(true); D("home '%s'", home.c_str()); LOG(DEBUG) << "adb_get_homedir_path returned '" << home << "'"; const std::string android_dir = android::base::StringPrintf("%s%c%s", home.c_str(), OS_PATH_SEPARATOR, ANDROID_PATH); const std::string android_dir = android::base::StringPrintf("%s%c.android", home.c_str(), OS_PATH_SEPARATOR); struct stat buf; if (stat(android_dir.c_str(), &buf)) { if (adb_mkdir(android_dir.c_str(), 0750) < 0) { D("Cannot mkdir '%s'", android_dir.c_str()); return -1; if (stat(android_dir.c_str(), &buf) == -1) { if (adb_mkdir(android_dir.c_str(), 0750) == -1) { PLOG(ERROR) << "Cannot mkdir '" << android_dir << "'"; return ""; } } return snprintf(filename, len, "%s%c%s", android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE); return android_dir + OS_PATH_SEPARATOR + "adbkey"; } static int get_user_key(struct listnode *list) { struct stat buf; char path[PATH_MAX]; int ret; ret = get_user_keyfilepath(path, sizeof(path)); if (ret < 0 || ret >= (signed)sizeof(path)) { D("Error getting user key filename"); return 0; static bool get_user_key() { std::string path = get_user_key_path(); if (path.empty()) { PLOG(ERROR) << "Error getting user key filename"; return false; } D("user key '%s'", path); if (stat(path, &buf) == -1) { struct stat buf; if (stat(path.c_str(), &buf) == -1) { LOG(INFO) << "User key '" << path << "' does not exist..."; if (!generate_key(path)) { D("Failed to generate new key"); return 0; LOG(ERROR) << "Failed to generate new key"; return false; } } return read_key(path, list); return read_key(path); } static void get_vendor_keys(struct listnode* key_list) { static void get_vendor_keys() { const char* adb_keys_path = getenv("ADB_VENDOR_KEYS"); if (adb_keys_path == nullptr) { return; } for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) { if (!read_key(path.c_str(), key_list)) { D("Failed to read '%s'", path.c_str()); if (!read_key(path.c_str())) { PLOG(ERROR) << "Failed to read '" << path << "'"; } } } int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, unsigned char* sig) { unsigned int len; struct adb_private_key *key = node_to_item(node, struct adb_private_key, node); std::deque<RSA*> adb_auth_get_private_keys() { std::deque<RSA*> result; // Copy all the currently known keys, increasing their reference count so they're // usable until both we and the caller have freed our pointers. std::lock_guard<std::mutex> lock(g_key_list_mutex); for (const auto& key : g_key_list) { RSA_up_ref(key); // Since we're handing out another pointer to this key... result.push_back(key); } // Add a sentinel to the list. Our caller uses this to mean "out of private keys, // but try using the public key" (the empty deque could otherwise mean this _or_ // that this function hasn't been called yet to request the keys). result.push_back(nullptr); return result; } int adb_auth_sign(RSA* key, const unsigned char* token, size_t token_size, unsigned char* sig) { if (token_size != TOKEN_SIZE) { D("Unexpected token size %zd", token_size); return 0; } if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) { unsigned int len; if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key)) { return 0; } Loading @@ -254,40 +250,17 @@ int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, return (int)len; } void *adb_auth_nextkey(void *current) { struct listnode *item; if (list_empty(&key_list)) return NULL; if (!current) return list_head(&key_list); list_for_each(item, &key_list) { if (item == current) { /* current is the last item, we tried all the keys */ if (item->next == &key_list) return NULL; return item->next; } } return NULL; } std::string adb_auth_get_userkey() { char path[PATH_MAX]; int ret = get_user_keyfilepath(path, sizeof(path) - 4); if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { D("Error getting user key filename"); std::string path = get_user_key_path(); if (path.empty()) { PLOG(ERROR) << "Error getting user key filename"; return ""; } strcat(path, ".pub"); path += ".pub"; std::string content; if (!android::base::ReadFileToString(path, &content)) { D("Can't load '%s'", path); PLOG(ERROR) << "Can't load '" << path << "'"; return ""; } return content; Loading @@ -297,19 +270,14 @@ int adb_auth_keygen(const char* filename) { return (generate_key(filename) == 0); } void adb_auth_init(void) { int ret; D("adb_auth_init"); list_init(&key_list); void adb_auth_init() { LOG(INFO) << "adb_auth_init..."; ret = get_user_key(&key_list); if (!ret) { D("Failed to get user key"); if (!get_user_key()) { LOG(ERROR) << "Failed to get user key"; return; } get_vendor_keys(&key_list); std::lock_guard<std::mutex> lock(g_key_list_mutex); get_vendor_keys(); }