android_system_core/adb/adb_auth_host.c

484 lines
11 KiB
C
Raw Normal View History

adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
/*
* Copyright (C) 2012 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdlib.h>
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#ifdef _WIN32
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
# include "windows.h"
# include "shlobj.h"
#else
# include <sys/types.h>
# include <sys/stat.h>
# include <unistd.h>
#endif
#include <string.h>
#include "sysdeps.h"
#include "adb.h"
#include "adb_auth.h"
/* HACK: we need the RSAPublicKey struct
* but RSA_verify conflits with openssl */
#define RSA_verify RSA_verify_mincrypt
#include "mincrypt/rsa.h"
#undef RSA_verify
#include <cutils/list.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/pem.h>
#include <openssl/rsa.h>
#include <openssl/sha.h>
#if defined(OPENSSL_IS_BORINGSSL)
#include <openssl/base64.h>
#endif
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#define TRACE_TAG TRACE_AUTH
#define ANDROID_PATH ".android"
#define ADB_KEY_FILE "adbkey"
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
struct adb_private_key {
struct listnode node;
RSA *rsa;
};
static struct listnode key_list;
/* Convert OpenSSL RSA private key to android pre-computed RSAPublicKey format */
static int RSA_to_RSAPublicKey(RSA *rsa, RSAPublicKey *pkey)
{
int ret = 1;
unsigned int i;
BN_CTX* ctx = BN_CTX_new();
BIGNUM* r32 = BN_new();
BIGNUM* rr = BN_new();
BIGNUM* r = BN_new();
BIGNUM* rem = BN_new();
BIGNUM* n = BN_new();
BIGNUM* n0inv = BN_new();
if (RSA_size(rsa) != RSANUMBYTES) {
ret = 0;
goto out;
}
BN_set_bit(r32, 32);
BN_copy(n, rsa->n);
BN_set_bit(r, RSANUMWORDS * 32);
BN_mod_sqr(rr, r, n, ctx);
BN_div(NULL, rem, n, r32, ctx);
BN_mod_inverse(n0inv, rem, r32, ctx);
pkey->len = RSANUMWORDS;
pkey->n0inv = 0 - BN_get_word(n0inv);
for (i = 0; i < RSANUMWORDS; i++) {
BN_div(rr, rem, rr, r32, ctx);
pkey->rr[i] = BN_get_word(rem);
BN_div(n, rem, n, r32, ctx);
pkey->n[i] = BN_get_word(rem);
}
pkey->exponent = BN_get_word(rsa->e);
out:
BN_free(n0inv);
BN_free(n);
BN_free(rem);
BN_free(r);
BN_free(rr);
BN_free(r32);
BN_CTX_free(ctx);
return ret;
}
static void get_user_info(char *buf, size_t len)
{
char hostname[1024], username[1024];
int ret = -1;
if (getenv("HOSTNAME") != NULL) {
strncpy(hostname, getenv("HOSTNAME"), sizeof(hostname));
hostname[sizeof(hostname)-1] = '\0';
ret = 0;
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#ifndef _WIN32
if (ret < 0)
ret = gethostname(hostname, sizeof(hostname));
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#endif
if (ret < 0)
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
strcpy(hostname, "unknown");
ret = -1;
if (getenv("LOGNAME") != NULL) {
strncpy(username, getenv("LOGNAME"), sizeof(username));
username[sizeof(username)-1] = '\0';
ret = 0;
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
if (ret < 0)
ret = getlogin_r(username, sizeof(username));
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
#endif
if (ret < 0)
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
strcpy(username, "unknown");
ret = snprintf(buf, len, " %s@%s", username, hostname);
if (ret >= (signed)len)
buf[len - 1] = '\0';
}
static int write_public_keyfile(RSA *private_key, const char *private_key_path)
{
RSAPublicKey pkey;
FILE *outfile = NULL;
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
char path[PATH_MAX], info[MAX_PAYLOAD];
uint8_t *encoded = NULL;
size_t encoded_length;
int ret = 0;
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >=
(int)sizeof(path)) {
D("Path too long while writing public key\n");
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
return 0;
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
if (!RSA_to_RSAPublicKey(private_key, &pkey)) {
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
D("Failed to convert to publickey\n");
return 0;
}
outfile = fopen(path, "w");
if (!outfile) {
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
D("Failed to open '%s'\n", path);
return 0;
}
D("Writing public key to '%s'\n", path);
#if defined(OPENSSL_IS_BORINGSSL)
if (!EVP_EncodedLength(&encoded_length, sizeof(pkey))) {
D("Public key too large to base64 encode");
goto out;
}
#else
/* While we switch from OpenSSL to BoringSSL we have to implement
* |EVP_EncodedLength| here. */
encoded_length = 1 + ((sizeof(pkey) + 2) / 3 * 4);
#endif
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
encoded = malloc(encoded_length);
if (encoded == NULL) {
D("Allocation failure");
goto out;
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
encoded_length = EVP_EncodeBlock(encoded, (uint8_t*) &pkey, sizeof(pkey));
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
get_user_info(info, sizeof(info));
if (fwrite(encoded, encoded_length, 1, outfile) != 1 ||
fwrite(info, strlen(info), 1, outfile) != 1) {
D("Write error while writing public key");
goto out;
}
ret = 1;
out:
if (outfile != NULL) {
fclose(outfile);
}
if (encoded != NULL) {
free(encoded);
}
return ret;
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
}
static int generate_key(const char *file)
{
EVP_PKEY* pkey = EVP_PKEY_new();
BIGNUM* exponent = BN_new();
RSA* rsa = RSA_new();
mode_t old_mask;
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
FILE *f = NULL;
int ret = 0;
D("generate_key '%s'\n", file);
if (!pkey || !exponent || !rsa) {
D("Failed to allocate key\n");
goto out;
}
BN_set_word(exponent, RSA_F4);
RSA_generate_key_ex(rsa, 2048, exponent, NULL);
EVP_PKEY_set1_RSA(pkey, rsa);
old_mask = umask(077);
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
f = fopen(file, "w");
if (!f) {
D("Failed to open '%s'\n", file);
umask(old_mask);
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
goto out;
}
umask(old_mask);
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
D("Failed to write key\n");
goto out;
}
if (!write_public_keyfile(rsa, file)) {
D("Failed to write public key\n");
goto out;
}
ret = 1;
out:
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)
{
struct adb_private_key *key;
FILE *f;
D("read_key '%s'\n", file);
f = fopen(file, "r");
if (!f) {
D("Failed to open '%s'\n", file);
return 0;
}
key = malloc(sizeof(*key));
if (!key) {
D("Failed to alloc key\n");
fclose(f);
return 0;
}
key->rsa = RSA_new();
if (!PEM_read_RSAPrivateKey(f, &key->rsa, NULL, NULL)) {
D("Failed to read key\n");
fclose(f);
RSA_free(key->rsa);
free(key);
return 0;
}
fclose(f);
list_add_tail(list, &key->node);
return 1;
}
static int get_user_keyfilepath(char *filename, size_t len)
{
const char *format, *home;
char android_dir[PATH_MAX];
struct stat buf;
#ifdef _WIN32
char path[PATH_MAX];
home = getenv("ANDROID_SDK_HOME");
if (!home) {
SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path);
home = path;
}
format = "%s\\%s";
#else
home = getenv("HOME");
if (!home)
return -1;
format = "%s/%s";
#endif
D("home '%s'\n", home);
if (snprintf(android_dir, sizeof(android_dir), format, home,
ANDROID_PATH) >= (int)sizeof(android_dir))
return -1;
if (stat(android_dir, &buf)) {
if (adb_mkdir(android_dir, 0750) < 0) {
D("Cannot mkdir '%s'", android_dir);
return -1;
}
}
return snprintf(filename, len, format, android_dir, ADB_KEY_FILE);
}
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;
}
D("user key '%s'\n", path);
if (stat(path, &buf) == -1) {
if (!generate_key(path)) {
D("Failed to generate new key\n");
return 0;
}
}
return read_key(path, list);
}
static void get_vendor_keys(struct listnode *list)
{
const char *adb_keys_path;
char keys_path[MAX_PAYLOAD];
char *path;
char *save;
struct stat buf;
adb_keys_path = getenv("ADB_VENDOR_KEYS");
if (!adb_keys_path)
return;
strncpy(keys_path, adb_keys_path, sizeof(keys_path));
path = adb_strtok_r(keys_path, ENV_PATH_SEPARATOR_STR, &save);
while (path) {
D("Reading: '%s'\n", path);
if (stat(path, &buf))
D("Can't read '%s'\n", path);
else if (!read_key(path, list))
D("Failed to read '%s'\n", path);
path = adb_strtok_r(NULL, ENV_PATH_SEPARATOR_STR, &save);
}
}
int adb_auth_sign(void *node, void *token, size_t token_size, void *sig)
{
unsigned int len;
struct adb_private_key *key = node_to_item(node, struct adb_private_key, node);
if (token_size != TOKEN_SIZE) {
D("Unexpected token size %zd\n", token_size);
return 0;
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) {
return 0;
}
D("adb_auth_sign len=%d\n", len);
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;
}
int adb_auth_get_userkey(unsigned char *data, size_t len)
{
char path[PATH_MAX];
char *file;
int ret;
ret = get_user_keyfilepath(path, sizeof(path) - 4);
if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) {
D("Error getting user key filename");
return 0;
}
strcat(path, ".pub");
file = load_file(path, (unsigned*)&ret);
if (!file) {
D("Can't load '%s'\n", path);
return 0;
}
if (len < (size_t)(ret + 1)) {
D("%s: Content too large ret=%d\n", path, ret);
return 0;
}
memcpy(data, file, ret);
data[ret] = '\0';
return ret + 1;
}
int adb_auth_keygen(const char* filename) {
adb_trace_mask |= (1 << TRACE_AUTH);
return (generate_key(filename) == 0);
}
adb: Add public key authentification Secure adb using a public key authentication, to allow USB debugging only from authorized hosts. When a device is connected to an unauthorized host, the adb daemon sends the user public key to the device. A popup is shown to ask the user to allow debugging once or permanantly from the host. The public key is installed on the device in the later case. Other keys may be installed at build time. On the host, the user public/private key pair is automatically generated, if it does not exist, when the adb daemon starts and is stored in $HOME/.android/adb_key(.pub) or in $ANDROID_SDK_HOME on windows. If needed, the ADB_KEYS_PATH env variable may be set to a :-separated (; under Windows) list of private keys, e.g. company-wide or vendor keys. On the device, vendors public keys are installed at build time in /adb_keys. User-installed keys are stored in /data/misc/adb/adb_keys. ADB Protocol change: If the device needs to authenticate the host, it replies to CNXN packets with an AUTH packet. The AUTH packet payload is a random token. The host signs the token with one of its private keys and sends an AUTH(0) packet. If the signature verification succeeds, the device replies with a CNXN packet. Otherwise, it sends a new AUTH packet with a new token so that the host can retry with another private key. Once the host has tried all its keys, it can send an AUTH(1) packet with a public key as payload. adbd then sends the public key to the framework (if it has been started) for confirmation. Change-Id: I4e84d7621da956f66ff657245901bdaefead8395
2012-04-12 19:23:49 +00:00
void adb_auth_init(void)
{
int ret;
D("adb_auth_init\n");
list_init(&key_list);
ret = get_user_key(&key_list);
if (!ret) {
D("Failed to get user key\n");
return;
}
get_vendor_keys(&key_list);
}