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