1d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby/*
2d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Copyright (C) 2012 The Android Open Source Project
3d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
4d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Licensed under the Apache License, Version 2.0 (the "License");
5d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * you may not use this file except in compliance with the License.
6d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * You may obtain a copy of the License at
7d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
8d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *      http://www.apache.org/licenses/LICENSE-2.0
9d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby *
10d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * Unless required by applicable law or agreed to in writing, software
11d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * distributed under the License is distributed on an "AS IS" BASIS,
12d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * See the License for the specific language governing permissions and
14d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * limitations under the License.
15d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby */
16d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
17d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <stdio.h>
18d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
19d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#ifdef _WIN32
20d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  define WIN32_LEAN_AND_MEAN
21d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  include "windows.h"
22d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  include "shlobj.h"
23d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#else
24d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  include <sys/types.h>
25d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  include <sys/stat.h>
26d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#  include <unistd.h>
27d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#endif
28d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <string.h>
29d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
30d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "sysdeps.h"
31d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb.h"
32d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "adb_auth.h"
33d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
34d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby/* HACK: we need the RSAPublicKey struct
35d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby * but RSA_verify conflits with openssl */
36d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#define RSA_verify RSA_verify_mincrypt
37d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include "mincrypt/rsa.h"
38d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#undef RSA_verify
39d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
40d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <cutils/list.h>
41d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
42d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/evp.h>
43d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/objects.h>
44d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/pem.h>
45d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/rsa.h>
46d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#include <openssl/sha.h>
47d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
48d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#define TRACE_TAG TRACE_AUTH
49d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
50d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#define ANDROID_PATH   ".android"
5164b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby#define ADB_KEY_FILE   "adbkey"
52d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
53d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
54d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystruct adb_private_key {
55d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    struct listnode node;
56d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA *rsa;
57d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby};
58d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
59d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic struct listnode key_list;
60d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
61d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
62d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby/* Convert OpenSSL RSA private key to android pre-computed RSAPublicKey format */
63d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int RSA_to_RSAPublicKey(RSA *rsa, RSAPublicKey *pkey)
64d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
65d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    int ret = 1;
66d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    unsigned int i;
67d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
68d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_CTX* ctx = BN_CTX_new();
69d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* r32 = BN_new();
70d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* rr = BN_new();
71d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* r = BN_new();
72d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* rem = BN_new();
73d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* n = BN_new();
74d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* n0inv = BN_new();
75d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
76d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (RSA_size(rsa) != RSANUMBYTES) {
77d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        ret = 0;
78d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
79d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
80d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
81d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_set_bit(r32, 32);
82d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_copy(n, rsa->n);
83d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_set_bit(r, RSANUMWORDS * 32);
84d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_mod_sqr(rr, r, n, ctx);
85d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_div(NULL, rem, n, r32, ctx);
86d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_mod_inverse(n0inv, rem, r32, ctx);
87d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
88d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    pkey->len = RSANUMWORDS;
89d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    pkey->n0inv = 0 - BN_get_word(n0inv);
90d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    for (i = 0; i < RSANUMWORDS; i++) {
91d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        BN_div(rr, rem, rr, r32, ctx);
92d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        pkey->rr[i] = BN_get_word(rem);
93d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        BN_div(n, rem, n, r32, ctx);
94d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        pkey->n[i] = BN_get_word(rem);
95d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
96d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    pkey->exponent = BN_get_word(rsa->e);
97d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
98d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyout:
99d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(n0inv);
100d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(n);
101d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(rem);
102d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(r);
103d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(rr);
104d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(r32);
105d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_CTX_free(ctx);
106d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
107d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    return ret;
108d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
109d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
110d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic void get_user_info(char *buf, size_t len)
111d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
112d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    char hostname[1024], username[1024];
113d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    int ret;
114d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
115d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#ifndef _WIN32
116d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = gethostname(hostname, sizeof(hostname));
117d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (ret < 0)
118d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#endif
119d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        strcpy(hostname, "unknown");
120d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
121d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#if !defined _WIN32 && !defined ADB_HOST_ON_TARGET
122d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = getlogin_r(username, sizeof(username));
123d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (ret < 0)
124d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby#endif
125d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        strcpy(username, "unknown");
126d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
127d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = snprintf(buf, len, " %s@%s", username, hostname);
128d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (ret >= (signed)len)
129d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        buf[len - 1] = '\0';
130d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
131d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
132d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int write_public_keyfile(RSA *private_key, const char *private_key_path)
133d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
134d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSAPublicKey pkey;
135d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO *bio, *b64, *bfile;
136d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    char path[PATH_MAX], info[MAX_PAYLOAD];
137d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    int ret;
138d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
139d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = snprintf(path, sizeof(path), "%s.pub", private_key_path);
140d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (ret >= (signed)sizeof(path))
141d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return 0;
142d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
143d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = RSA_to_RSAPublicKey(private_key, &pkey);
144d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!ret) {
145d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to convert to publickey\n");
146d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return 0;
147d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
148d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
149d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    bfile = BIO_new_file(path, "w");
150d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!bfile) {
151d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to open '%s'\n", path);
152d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return 0;
153d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
154d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
155d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    D("Writing public key to '%s'\n", path);
156d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
157d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    b64 = BIO_new(BIO_f_base64());
158d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
159d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
160d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    bio = BIO_push(b64, bfile);
161d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_write(bio, &pkey, sizeof(pkey));
162d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_flush(bio);
163d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_pop(b64);
164d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_free(b64);
165d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
166d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    get_user_info(info, sizeof(info));
167d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_write(bfile, info, strlen(info));
168d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_flush(bfile);
169d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIO_free_all(bfile);
170d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
171d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    return 1;
172d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
173d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
174d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int generate_key(const char *file)
175d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
176d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    EVP_PKEY* pkey = EVP_PKEY_new();
177d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BIGNUM* exponent = BN_new();
178d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA* rsa = RSA_new();
17964b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    mode_t old_mask;
180d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    FILE *f = NULL;
181d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    int ret = 0;
182d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
183d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    D("generate_key '%s'\n", file);
184d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
185d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!pkey || !exponent || !rsa) {
186d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to allocate key\n");
187d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
188d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
189d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
190d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_set_word(exponent, RSA_F4);
191d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA_generate_key_ex(rsa, 2048, exponent, NULL);
192d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    EVP_PKEY_set1_RSA(pkey, rsa);
193d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
19464b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    old_mask = umask(077);
19564b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby
196d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    f = fopen(file, "w");
197d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!f) {
198d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to open '%s'\n", file);
19964b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby        umask(old_mask);
200d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
201d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
202d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
20364b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby    umask(old_mask);
20464b3103017cb9038c5fb7e3601f51c6a458bed06Benoit Goby
205d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!PEM_write_PrivateKey(f, pkey, NULL, NULL, 0, NULL, NULL)) {
206d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to write key\n");
207d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
208d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
209d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
210d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!write_public_keyfile(rsa, file)) {
211d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to write public key\n");
212d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        goto out;
213d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
214d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
215d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    ret = 1;
216d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
217d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobyout:
218d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (f)
219d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        fclose(f);
220d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    EVP_PKEY_free(pkey);
221d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    RSA_free(rsa);
222d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    BN_free(exponent);
223d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    return ret;
224d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby}
225d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
226d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Gobystatic int read_key(const char *file, struct listnode *list)
227d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby{
228d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    struct adb_private_key *key;
229d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    FILE *f;
230d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
231d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    D("read_key '%s'\n", file);
232d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby
233d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    f = fopen(file, "r");
234d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    if (!f) {
235d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        D("Failed to open '%s'\n", file);
236d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby        return 0;
237d5fcafaf41f8ec90986c813f75ec78402096af2dBenoit Goby    }
238