Home | History | Annotate | Download | only in adb
      1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/devtools/adb/android_rsa.h"
      6 
      7 #include "base/base64.h"
      8 #include "base/memory/scoped_ptr.h"
      9 #include "chrome/browser/prefs/pref_service_syncable.h"
     10 #include "chrome/browser/profiles/profile.h"
     11 #include "chrome/common/pref_names.h"
     12 #include "crypto/rsa_private_key.h"
     13 #include "crypto/signature_creator.h"
     14 #include "net/cert/asn1_util.h"
     15 
     16 namespace {
     17 
     18 const size_t kRSANumWords = 64;
     19 const size_t kBigIntSize = 1024;
     20 
     21 static const char kDummyRSAPublicKey[] =
     22     "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6OSJ64q+ZLg7VV2ojEPh5TRbYjwbT"
     23     "TifSPeFIV45CHnbTWYiiIn41wrozpYizNsMWZUBjdah1N78WVhbyDrnr0bDgFp+gXjfVppa3I"
     24     "gjiohEcemK3omXi3GDMK8ERhriLUKfQS842SXtQ8I+KoZtpCkGM//0h7+P+Rhm0WwdipIRMhR"
     25     "8haNAeyDiiCvqJcvevv2T52vqKtS3aWz+GjaTJJLVWydEpz9WdvWeLfFVhe2ZnqwwZNa30Qoj"
     26     "fsnvjaMwK2MU7uYfRBPuvLyK5QESWBpArNDd6ULl8Y+NU6kwNOVDc87OASCVEM1gw2IMi2mo2"
     27     "WO5ywp0UWRiGZCkK+wOFQIDAQAB";
     28 
     29 typedef struct RSAPublicKey {
     30     int len;                // Length of n[] in number of uint32
     31     uint32 n0inv;           // -1 / n[0] mod 2^32
     32     uint32 n[kRSANumWords];  // modulus as little endian array
     33     uint32 rr[kRSANumWords]; // R^2 as little endian array
     34     int exponent;           // 3 or 65537
     35 } RSAPublicKey;
     36 
     37 // http://en.wikipedia.org/wiki/Extended_Euclidean_algorithm
     38 // a * x + b * y = gcd(a, b) = d
     39 void ExtendedEuclid(uint64 a, uint64 b, uint64 *x, uint64 *y, uint64 *d) {
     40   uint64 x1 = 0, x2 = 1, y1 = 1, y2 = 0;
     41 
     42   while (b > 0) {
     43     uint64 q = a / b;
     44     uint64 r = a % b;
     45     *x = x2 - q * x1;
     46     *y = y2 - q * y1;
     47     a = b;
     48     b = r;
     49     x2 = x1;
     50     x1 = *x;
     51     y2 = y1;
     52     y1 = *y;
     53   }
     54 
     55   *d = a;
     56   *x = x2;
     57   *y = y2;
     58 }
     59 
     60 uint32 ModInverse(uint64 a, uint64 m)
     61 {
     62   uint64 d, x, y;
     63   ExtendedEuclid(a, m, &x, &y, &d);
     64   if (d == 1)
     65     return static_cast<uint32>(x);
     66   return 0;
     67 }
     68 
     69 uint32* BnNew() {
     70   uint32* result = new uint32[kBigIntSize];
     71   memset(result, 0, kBigIntSize * sizeof(uint32));
     72   return result;
     73 }
     74 
     75 void BnFree(uint32* a) {
     76   delete[] a;
     77 }
     78 
     79 uint32* BnCopy(uint32* a) {
     80   uint32* result = new uint32[kBigIntSize];
     81   memcpy(result, a, kBigIntSize * sizeof(uint32));
     82   return result;
     83 }
     84 
     85 uint32* BnMul(uint32* a, uint32 b) {
     86   uint32* result = BnNew();
     87   uint64 carry_over = 0;
     88   for (size_t i = 0; i < kBigIntSize; ++i) {
     89     carry_over += static_cast<uint64>(a[i]) * b;
     90     result[i] = carry_over & kuint32max;
     91     carry_over >>= 32;
     92   }
     93   return result;
     94 }
     95 
     96 void BnSub(uint32* a, uint32* b) {
     97   int carry_over = 0;
     98   for (size_t i = 0; i < kBigIntSize; ++i) {
     99     int64 sub = static_cast<int64>(a[i]) - b[i] - carry_over;
    100     carry_over = 0;
    101     if (sub < 0) {
    102       carry_over = 1;
    103       sub += GG_LONGLONG(0x100000000);
    104     }
    105     a[i] = static_cast<uint32>(sub);
    106   }
    107 }
    108 
    109 void BnLeftShift(uint32* a, int offset) {
    110   for (int i = kBigIntSize - offset - 1; i >= 0; --i)
    111     a[i + offset] = a[i];
    112   for (int i = 0; i < offset; ++i)
    113     a[i] = 0;
    114 }
    115 
    116 int BnCompare(uint32* a, uint32* b) {
    117   for (int i = kBigIntSize - 1; i >= 0; --i) {
    118     if (a[i] > b[i])
    119       return 1;
    120     if (a[i] < b[i])
    121       return -1;
    122   }
    123   return 0;
    124 }
    125 
    126 uint64 BnGuess(uint32* a, uint32* b, uint64 from, uint64 to) {
    127   if (from + 1 >= to)
    128     return from;
    129 
    130   uint64 guess = (from + to) / 2;
    131   uint32* t = BnMul(b, static_cast<uint32>(guess));
    132   int result = BnCompare(a, t);
    133   BnFree(t);
    134   if (result > 0)
    135     return BnGuess(a, b, guess, to);
    136   if (result < 0)
    137     return BnGuess(a, b, from, guess);
    138   return guess;
    139 }
    140 
    141 void BnDiv(uint32* a, uint32* b, uint32** pq, uint32** pr) {
    142   if (BnCompare(a, b) < 0) {
    143     if (pq)
    144       *pq = BnNew();
    145     if (pr)
    146       *pr = BnCopy(a);
    147     return;
    148   }
    149 
    150   int oa = kBigIntSize - 1;
    151   int ob = kBigIntSize - 1;
    152   for (; oa > 0 && !a[oa]; --oa) {}
    153   for (; ob > 0 && !b[ob]; --ob) {}
    154   uint32* q = BnNew();
    155   uint32* ca = BnCopy(a);
    156 
    157   int digit = a[oa] < b[ob] ? oa - ob - 1 : oa - ob;
    158 
    159   for (; digit >= 0; --digit) {
    160     uint32* shifted_b = BnCopy(b);
    161     BnLeftShift(shifted_b, digit);
    162     uint32 value = static_cast<uint32>(
    163         BnGuess(ca, shifted_b, 0, static_cast<uint64>(kuint32max) + 1));
    164     q[digit] = value;
    165     uint32* t = BnMul(shifted_b, value);
    166     BnSub(ca, t);
    167     BnFree(t);
    168     BnFree(shifted_b);
    169   }
    170 
    171   if (pq)
    172     *pq = q;
    173   else
    174     BnFree(q);
    175   if (pr)
    176     *pr = ca;
    177   else
    178     BnFree(ca);
    179 }
    180 
    181 }  // namespace
    182 
    183 crypto::RSAPrivateKey* AndroidRSAPrivateKey(Profile* profile) {
    184   std::string encoded_key =
    185       profile->GetPrefs()->GetString(prefs::kDevToolsAdbKey);
    186   std::string decoded_key;
    187   scoped_ptr<crypto::RSAPrivateKey> key;
    188   if (!encoded_key.empty() && base::Base64Decode(encoded_key, &decoded_key)) {
    189     std::vector<uint8> key_info(decoded_key.begin(), decoded_key.end());
    190     key.reset(crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_info));
    191   }
    192   if (!key) {
    193     key.reset(crypto::RSAPrivateKey::Create(2048));
    194     std::vector<uint8> key_info;
    195     if (!key || !key->ExportPrivateKey(&key_info))
    196       return NULL;
    197 
    198     std::string key_string(key_info.begin(), key_info.end());
    199     base::Base64Encode(key_string, &encoded_key);
    200     profile->GetPrefs()->SetString(prefs::kDevToolsAdbKey,
    201                                    encoded_key);
    202   }
    203   return key.release();
    204 }
    205 
    206 std::string AndroidRSAPublicKey(crypto::RSAPrivateKey* key) {
    207   std::vector<uint8> public_key;
    208   if (!key)
    209     return kDummyRSAPublicKey;
    210 
    211   key->ExportPublicKey(&public_key);
    212   std::string asn1(public_key.begin(), public_key.end());
    213 
    214   base::StringPiece pk;
    215   if (!net::asn1::ExtractSubjectPublicKeyFromSPKI(asn1, &pk))
    216     return kDummyRSAPublicKey;
    217 
    218   // Skip 10 byte asn1 prefix to the modulus.
    219   std::vector<uint8> pk_data(pk.data() + 10, pk.data() + pk.length());
    220   uint32* n = BnNew();
    221   for (size_t i = 0; i < kRSANumWords; ++i) {
    222     uint32 t = pk_data[4 * i];
    223     t = t << 8;
    224     t += pk_data[4 * i + 1];
    225     t = t << 8;
    226     t += pk_data[4 * i + 2];
    227     t = t << 8;
    228     t += pk_data[4 * i + 3];
    229     n[kRSANumWords - i - 1] = t;
    230   }
    231   uint64 n0 = n[0];
    232 
    233   RSAPublicKey pkey;
    234   pkey.len = kRSANumWords;
    235   pkey.exponent = 65537; // Fixed public exponent
    236   pkey.n0inv = 0 - ModInverse(n0, GG_LONGLONG(0x100000000));
    237   if (pkey.n0inv == 0)
    238     return kDummyRSAPublicKey;
    239 
    240   uint32* r = BnNew();
    241   r[kRSANumWords * 2] = 1;
    242 
    243   uint32* rr;
    244   BnDiv(r, n, NULL, &rr);
    245 
    246   for (size_t i = 0; i < kRSANumWords; ++i) {
    247     pkey.n[i] = n[i];
    248     pkey.rr[i] = rr[i];
    249   }
    250 
    251   BnFree(n);
    252   BnFree(r);
    253   BnFree(rr);
    254 
    255   std::string output;
    256   std::string input(reinterpret_cast<char*>(&pkey), sizeof(pkey));
    257   base::Base64Encode(input, &output);
    258   return output;
    259 }
    260 
    261 std::string AndroidRSASign(crypto::RSAPrivateKey* key,
    262                            const std::string& body) {
    263   std::vector<uint8> digest(body.begin(), body.end());
    264   std::vector<uint8> result;
    265   if (!crypto::SignatureCreator::Sign(key, vector_as_array(&digest),
    266                                       digest.size(), &result)) {
    267     return std::string();
    268   }
    269   return std::string(result.begin(), result.end());
    270 }
    271