adb_auth_host.cpp revision e8b663fec3acfefbef6396a23c6f48d66e1f19fc
1/* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#define TRACE_TAG AUTH 18 19#include "sysdeps.h" 20#include "adb_auth.h" 21#include "adb_utils.h" 22 23#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26 27#include "adb.h" 28 29#include <android-base/errors.h> 30#include <android-base/file.h> 31#include <android-base/stringprintf.h> 32#include <android-base/strings.h> 33#include <crypto_utils/android_pubkey.h> 34#include <cutils/list.h> 35 36#include <openssl/evp.h> 37#include <openssl/objects.h> 38#include <openssl/pem.h> 39#include <openssl/rsa.h> 40#include <openssl/sha.h> 41 42#if defined(OPENSSL_IS_BORINGSSL) 43#include <openssl/base64.h> 44#endif 45 46#define ANDROID_PATH ".android" 47#define ADB_KEY_FILE "adbkey" 48 49struct adb_private_key { 50 struct listnode node; 51 RSA *rsa; 52}; 53 54static struct listnode key_list; 55 56 57static void get_user_info(char *buf, size_t len) 58{ 59 char hostname[1024], username[1024]; 60 int ret = -1; 61 62 if (getenv("HOSTNAME") != NULL) { 63 strncpy(hostname, getenv("HOSTNAME"), sizeof(hostname)); 64 hostname[sizeof(hostname)-1] = '\0'; 65 ret = 0; 66 } 67 68#ifndef _WIN32 69 if (ret < 0) 70 ret = gethostname(hostname, sizeof(hostname)); 71#endif 72 if (ret < 0) 73 strcpy(hostname, "unknown"); 74 75 ret = -1; 76 77 if (getenv("LOGNAME") != NULL) { 78 strncpy(username, getenv("LOGNAME"), sizeof(username)); 79 username[sizeof(username)-1] = '\0'; 80 ret = 0; 81 } 82 83#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET 84 if (ret < 0) 85 ret = getlogin_r(username, sizeof(username)); 86#endif 87 if (ret < 0) 88 strcpy(username, "unknown"); 89 90 ret = snprintf(buf, len, " %s@%s", username, hostname); 91 if (ret >= (signed)len) 92 buf[len - 1] = '\0'; 93} 94 95static int write_public_keyfile(RSA *private_key, const char *private_key_path) 96{ 97 uint8_t binary_key_data[ANDROID_PUBKEY_ENCODED_SIZE]; 98 uint8_t* base64_key_data = nullptr; 99 size_t base64_key_length = 0; 100 FILE *outfile = NULL; 101 char path[PATH_MAX], info[MAX_PAYLOAD_V1]; 102 int ret = 0; 103 104 if (!android_pubkey_encode(private_key, binary_key_data, 105 sizeof(binary_key_data))) { 106 D("Failed to convert to publickey"); 107 goto out; 108 } 109 110 D("Writing public key to '%s'", path); 111 112#if defined(OPENSSL_IS_BORINGSSL) 113 if (!EVP_EncodedLength(&base64_key_length, sizeof(binary_key_data))) { 114 D("Public key too large to base64 encode"); 115 goto out; 116 } 117#else 118 /* While we switch from OpenSSL to BoringSSL we have to implement 119 * |EVP_EncodedLength| here. */ 120 base64_key_length = 1 + ((sizeof(binary_key_data) + 2) / 3 * 4); 121#endif 122 123 base64_key_data = new uint8_t[base64_key_length]; 124 if (base64_key_data == nullptr) { 125 D("Allocation failure"); 126 goto out; 127 } 128 129 base64_key_length = EVP_EncodeBlock(base64_key_data, binary_key_data, 130 sizeof(binary_key_data)); 131 get_user_info(info, sizeof(info)); 132 133 if (snprintf(path, sizeof(path), "%s.pub", private_key_path) >= 134 (int)sizeof(path)) { 135 D("Path too long while writing public key"); 136 goto out; 137 } 138 139 outfile = fopen(path, "w"); 140 if (!outfile) { 141 D("Failed to open '%s'", path); 142 goto out; 143 } 144 145 if (fwrite(base64_key_data, base64_key_length, 1, outfile) != 1 || 146 fwrite(info, strlen(info), 1, outfile) != 1) { 147 D("Write error while writing public key"); 148 goto out; 149 } 150 151 ret = 1; 152 153 out: 154 if (outfile != NULL) { 155 fclose(outfile); 156 } 157 delete[] base64_key_data; 158 return ret; 159} 160 161static int generate_key(const char *file) 162{ 163 EVP_PKEY* pkey = EVP_PKEY_new(); 164 BIGNUM* exponent = BN_new(); 165 RSA* rsa = RSA_new(); 166 mode_t old_mask; 167 FILE *f = NULL; 168 int ret = 0; 169 170 D("generate_key '%s'", file); 171 172 if (!pkey || !exponent || !rsa) { 173 D("Failed to allocate key"); 174 goto out; 175 } 176 177 BN_set_word(exponent, RSA_F4); 178 RSA_generate_key_ex(rsa, 2048, exponent, NULL); 179 EVP_PKEY_set1_RSA(pkey, rsa); 180 181 old_mask = umask(077); 182 183 f = fopen(file, "w"); 184 if (!f) { 185 D("Failed to open '%s'", file); 186 umask(old_mask); 187 goto out; 188 } 189 190 umask(old_mask); 191 192 if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) { 193 D("Failed to write key"); 194 goto out; 195 } 196 197 if (!write_public_keyfile(rsa, file)) { 198 D("Failed to write public key"); 199 goto out; 200 } 201 202 ret = 1; 203 204out: 205 if (f) 206 fclose(f); 207 EVP_PKEY_free(pkey); 208 RSA_free(rsa); 209 BN_free(exponent); 210 return ret; 211} 212 213static int read_key(const char *file, struct listnode *list) 214{ 215 D("read_key '%s'", file); 216 217 FILE* fp = fopen(file, "r"); 218 if (!fp) { 219 D("Failed to open '%s': %s", file, strerror(errno)); 220 return 0; 221 } 222 223 adb_private_key* key = new adb_private_key; 224 key->rsa = RSA_new(); 225 226 if (!PEM_read_RSAPrivateKey(fp, &key->rsa, NULL, NULL)) { 227 D("Failed to read key"); 228 fclose(fp); 229 RSA_free(key->rsa); 230 delete key; 231 return 0; 232 } 233 234 fclose(fp); 235 list_add_tail(list, &key->node); 236 return 1; 237} 238 239static int get_user_keyfilepath(char *filename, size_t len) 240{ 241 const std::string home = adb_get_homedir_path(true); 242 D("home '%s'", home.c_str()); 243 244 const std::string android_dir = 245 android::base::StringPrintf("%s%c%s", home.c_str(), 246 OS_PATH_SEPARATOR, ANDROID_PATH); 247 248 struct stat buf; 249 if (stat(android_dir.c_str(), &buf)) { 250 if (adb_mkdir(android_dir.c_str(), 0750) < 0) { 251 D("Cannot mkdir '%s'", android_dir.c_str()); 252 return -1; 253 } 254 } 255 256 return snprintf(filename, len, "%s%c%s", 257 android_dir.c_str(), OS_PATH_SEPARATOR, ADB_KEY_FILE); 258} 259 260static int get_user_key(struct listnode *list) 261{ 262 struct stat buf; 263 char path[PATH_MAX]; 264 int ret; 265 266 ret = get_user_keyfilepath(path, sizeof(path)); 267 if (ret < 0 || ret >= (signed)sizeof(path)) { 268 D("Error getting user key filename"); 269 return 0; 270 } 271 272 D("user key '%s'", path); 273 274 if (stat(path, &buf) == -1) { 275 if (!generate_key(path)) { 276 D("Failed to generate new key"); 277 return 0; 278 } 279 } 280 281 return read_key(path, list); 282} 283 284static void get_vendor_keys(struct listnode* key_list) { 285 const char* adb_keys_path = getenv("ADB_VENDOR_KEYS"); 286 if (adb_keys_path == nullptr) { 287 return; 288 } 289 290 for (const auto& path : android::base::Split(adb_keys_path, ENV_PATH_SEPARATOR_STR)) { 291 if (!read_key(path.c_str(), key_list)) { 292 D("Failed to read '%s'", path.c_str()); 293 } 294 } 295} 296 297int adb_auth_sign(void *node, const unsigned char* token, size_t token_size, 298 unsigned char* sig) 299{ 300 unsigned int len; 301 struct adb_private_key *key = node_to_item(node, struct adb_private_key, node); 302 303 if (token_size != TOKEN_SIZE) { 304 D("Unexpected token size %zd", token_size); 305 return 0; 306 } 307 308 if (!RSA_sign(NID_sha1, token, token_size, sig, &len, key->rsa)) { 309 return 0; 310 } 311 312 D("adb_auth_sign len=%d", len); 313 return (int)len; 314} 315 316void *adb_auth_nextkey(void *current) 317{ 318 struct listnode *item; 319 320 if (list_empty(&key_list)) 321 return NULL; 322 323 if (!current) 324 return list_head(&key_list); 325 326 list_for_each(item, &key_list) { 327 if (item == current) { 328 /* current is the last item, we tried all the keys */ 329 if (item->next == &key_list) 330 return NULL; 331 return item->next; 332 } 333 } 334 335 return NULL; 336} 337 338std::string adb_auth_get_userkey() { 339 char path[PATH_MAX]; 340 int ret = get_user_keyfilepath(path, sizeof(path) - 4); 341 if (ret < 0 || ret >= (signed)(sizeof(path) - 4)) { 342 D("Error getting user key filename"); 343 return ""; 344 } 345 strcat(path, ".pub"); 346 347 std::string content; 348 if (!android::base::ReadFileToString(path, &content)) { 349 D("Can't load '%s'", path); 350 return ""; 351 } 352 return content; 353} 354 355int adb_auth_keygen(const char* filename) { 356 return (generate_key(filename) == 0); 357} 358 359void adb_auth_init(void) 360{ 361 int ret; 362 363 D("adb_auth_init"); 364 365 list_init(&key_list); 366 367 ret = get_user_key(&key_list); 368 if (!ret) { 369 D("Failed to get user key"); 370 return; 371 } 372 373 get_vendor_keys(&key_list); 374} 375