Home | History | Annotate | Download | only in keymaster
      1 /*
      2  * Copyright 2018 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 #include "export_key.h"
     18 #include "proto_utils.h"
     19 
     20 #include <android-base/logging.h>
     21 
     22 #include <openssl/bn.h>
     23 #include <openssl/bytestring.h>
     24 #include <openssl/ec.h>
     25 #include <openssl/evp.h>
     26 #include <openssl/rsa.h>
     27 
     28 namespace android {
     29 namespace hardware {
     30 namespace keymaster {
     31 
     32 // HAL
     33 using ::android::hardware::keymaster::V4_0::Algorithm;
     34 using ::android::hardware::keymaster::V4_0::EcCurve;
     35 using ::android::hardware::keymaster::V4_0::KeyFormat;
     36 using ::android::hardware::keymaster::V4_0::Tag;
     37 using ::android::hardware::keymaster::V4_0::TagType;
     38 
     39 // App
     40 namespace nosapp = nugget::app::keymaster;
     41 
     42 // BoringSSL
     43 using bssl::UniquePtr;
     44 
     45 // std
     46 using std::unique_ptr;
     47 
     48 ErrorCode export_key_der(const ExportKeyResponse& response,
     49                           hidl_vec<uint8_t> *der) {
     50 
     51   if (response.algorithm() == nosapp::Algorithm::RSA) {
     52       bssl::UniquePtr<BIGNUM> n(BN_new());
     53       BN_le2bn(
     54           reinterpret_cast<const uint8_t *>(response.rsa().n().data()),
     55           response.rsa().n().size(), n.get());
     56 
     57       bssl::UniquePtr<BIGNUM> e(BN_new());
     58       if (!BN_set_word(e.get(), response.rsa().e())) {
     59           LOG(ERROR) << "ExportKey: BN_set_word failed";
     60           return ErrorCode::UNKNOWN_ERROR;
     61       }
     62 
     63       bssl::UniquePtr<RSA> rsa(RSA_new());
     64       if (!RSA_set0_key(rsa.get(), n.get(), e.get(), NULL)) {
     65           LOG(ERROR) << "ExportKey: RSA_set0_key failed";
     66           return ErrorCode::UNKNOWN_ERROR;
     67       }
     68 
     69       CBB cbb;
     70       uint8_t *data = new uint8_t[1024];  /* Plenty for RSA 4-k. */
     71       CBB_init_fixed(&cbb, data, 1024);
     72       bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
     73       EVP_PKEY_set1_RSA(pkey.get(), rsa.get());
     74       if (!EVP_marshal_public_key(&cbb, pkey.get())) {
     75           LOG(ERROR) << "ExportKey: EVP_marshal_public_key failed";
     76           return ErrorCode::UNKNOWN_ERROR;
     77       }
     78 
     79       der->setToExternal(
     80           const_cast<uint8_t*>(
     81               data), CBB_len(&cbb), true /* Transfer ownership. */);
     82       for (size_t i = 0; i < der->size(); i++) {
     83           LOG(ERROR) << "exporting: " << std::hex << (int)der->data()[i];
     84       }
     85       CBB_cleanup(&cbb);
     86   } else {
     87       EcCurve ec_curve;
     88       /* TODO: eliminate this type-cast. */
     89       if (translate_ec_curve(
     90               (nosapp::EcCurve)response.ec().curve_id(),
     91               &ec_curve) != ErrorCode::OK) {
     92           LOG(ERROR) << "Failed to parse response device ec curve_id: "
     93                      << response.ec().curve_id();
     94           return ErrorCode::UNKNOWN_ERROR;
     95       }
     96     int curve_nid;
     97     switch (ec_curve) {
     98     case EcCurve::P_224:
     99         curve_nid = NID_secp224r1;
    100         break;
    101     case EcCurve::P_256:
    102         curve_nid = NID_X9_62_prime256v1;
    103         break;
    104     case EcCurve::P_384:
    105         curve_nid = NID_secp384r1;
    106         break;
    107     case EcCurve::P_521:
    108         curve_nid = NID_secp521r1;
    109         break;
    110     default:
    111         LOG(ERROR) << "ExportKey: received invalid EcCurve id: "
    112                    << (uint32_t) ec_curve;
    113         return ErrorCode::UNKNOWN_ERROR;
    114     }
    115 
    116     bssl::UniquePtr<EC_GROUP> ec_group(EC_GROUP_new_by_curve_name(curve_nid));
    117     if (!ec_group.get()) {
    118         LOG(ERROR) << "EC_GROUP_new_by_name("
    119                    << (uint32_t)curve_nid << ") failed";
    120         return ErrorCode::UNKNOWN_ERROR;
    121     }
    122     bssl::UniquePtr<EC_POINT> ec_point(EC_POINT_new(ec_group.get()));
    123     if (!ec_point.get()) {
    124         LOG(ERROR) << "EC_POINT_new() failed";
    125         return ErrorCode::UNKNOWN_ERROR;
    126     }
    127     bssl::UniquePtr<BIGNUM> x(BN_new());
    128     BN_le2bn(
    129         reinterpret_cast<const uint8_t *>(response.ec().x().data()),
    130         response.ec().x().size(), x.get());
    131     bssl::UniquePtr<BIGNUM> y(BN_new());
    132     BN_le2bn(
    133         reinterpret_cast<const uint8_t *>(response.ec().y().data()),
    134         response.ec().y().size(), y.get());
    135     if (!EC_POINT_set_affine_coordinates_GFp(
    136             ec_group.get(), ec_point.get(), x.get(), y.get(), NULL)) {
    137         LOG(ERROR) << "EC_POINT_set_affine_coordinates() failed";
    138         return ErrorCode::UNKNOWN_ERROR;
    139     }
    140 
    141     bssl::UniquePtr<EC_KEY> ec_key(EC_KEY_new_by_curve_name(curve_nid));
    142     if (!ec_key.get()) {
    143         LOG(ERROR) << "EC_KEY_new() failed";
    144         return ErrorCode::UNKNOWN_ERROR;
    145     }
    146 
    147     if (!EC_KEY_set_public_key(ec_key.get(), ec_point.get())) {
    148         LOG(ERROR) << "EC_KEY_set_public_key() failed";
    149         return ErrorCode::UNKNOWN_ERROR;
    150     }
    151 
    152     bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
    153     if (!pkey.get()) {
    154         LOG(ERROR) << "EVP_PKEY_new() failed";
    155         return ErrorCode::UNKNOWN_ERROR;
    156     }
    157     if (!EVP_PKEY_set1_EC_KEY(pkey.get(), ec_key.get())) {
    158         LOG(ERROR) << "EVP_PKEY_set1_EC_KEY() failed";
    159         return ErrorCode::UNKNOWN_ERROR;
    160     }
    161     CBB cbb;
    162     uint8_t *data = new uint8_t[256];  /* Plenty for EC-521. */
    163     CBB_init_fixed(&cbb, data, 256);
    164     if (!EVP_marshal_public_key(&cbb, pkey.get())) {
    165       LOG(ERROR) << "ExportKey: EVP_marshal_public_key failed";
    166       return ErrorCode::UNKNOWN_ERROR;
    167     }
    168 
    169     der->setToExternal(
    170             const_cast<uint8_t*>(
    171                 data), CBB_len(&cbb), true /* Transfer ownership. */);
    172     for (size_t i = 0; i < der->size(); i++) {
    173       LOG(ERROR) << "exporting: " << std::hex << (int)der->data()[i];
    174     }
    175     CBB_cleanup(&cbb);
    176   }
    177 
    178   return ErrorCode::OK;
    179 }
    180 
    181 }  // namespace keymaster
    182 }  // hardware
    183 }  // android
    184