| OLD | NEW | 
|    1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |    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 |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "net/android/keystore_openssl.h" |    5 #include "net/android/keystore_openssl.h" | 
|    6  |    6  | 
|    7 #include <jni.h> |    7 #include <jni.h> | 
|    8 #include <openssl/bn.h> |    8 #include <openssl/bn.h> | 
|    9 // This include is required to get the ECDSA_METHOD structure definition |  | 
|   10 // which isn't currently part of the OpenSSL official ABI. This should |  | 
|   11 // not be a concern for Chromium which always links against its own |  | 
|   12 // version of the library on Android. |  | 
|   13 #include <openssl/crypto/ecdsa/ecs_locl.h> |  | 
|   14 // And this one is needed for the EC_GROUP definition. |  | 
|   15 #include <openssl/crypto/ec/ec_lcl.h> |  | 
|   16 #include <openssl/dsa.h> |    9 #include <openssl/dsa.h> | 
|   17 #include <openssl/ec.h> |   10 #include <openssl/ec.h> | 
|   18 #include <openssl/engine.h> |   11 #include <openssl/engine.h> | 
 |   12 #include <openssl/err.h> | 
|   19 #include <openssl/evp.h> |   13 #include <openssl/evp.h> | 
|   20 #include <openssl/rsa.h> |   14 #include <openssl/rsa.h> | 
|   21  |   15  | 
|   22 #include "base/android/build_info.h" |   16 #include "base/android/build_info.h" | 
|   23 #include "base/android/jni_android.h" |   17 #include "base/android/jni_android.h" | 
|   24 #include "base/android/scoped_java_ref.h" |   18 #include "base/android/scoped_java_ref.h" | 
|   25 #include "base/basictypes.h" |   19 #include "base/basictypes.h" | 
|   26 #include "base/lazy_instance.h" |   20 #include "base/lazy_instance.h" | 
|   27 #include "base/logging.h" |   21 #include "base/logging.h" | 
|   28 #include "crypto/openssl_util.h" |   22 #include "crypto/openssl_util.h" | 
| (...skipping 24 matching lines...) Expand all  Loading... | 
|   53 // For example, the RSA_sign() function will call "method->rsa_sign()" if |   47 // For example, the RSA_sign() function will call "method->rsa_sign()" if | 
|   54 // method->rsa_sign is not NULL, otherwise, it will perform a regular |   48 // method->rsa_sign is not NULL, otherwise, it will perform a regular | 
|   55 // signing operation using the other fields in the RSA structure (which |   49 // signing operation using the other fields in the RSA structure (which | 
|   56 // are used to hold the typical modulus / exponent / parameters for the |   50 // are used to hold the typical modulus / exponent / parameters for the | 
|   57 // key pair). |   51 // key pair). | 
|   58 // |   52 // | 
|   59 // This source file thus defines a custom RSA_METHOD structure whose |   53 // This source file thus defines a custom RSA_METHOD structure whose | 
|   60 // fields point to static methods used to implement the corresponding |   54 // fields point to static methods used to implement the corresponding | 
|   61 // RSA operation using platform Android APIs. |   55 // RSA operation using platform Android APIs. | 
|   62 // |   56 // | 
|   63 // However, the platform APIs require a jobject JNI reference to work. |   57 // However, the platform APIs require a jobject JNI reference to work. It must | 
|   64 // It must be stored in the RSA instance, or made accessible when the |   58 // be stored in the RSA instance, or made accessible when the custom RSA | 
|   65 // custom RSA methods are called. This is done by using RSA_set_app_data() |   59 // methods are called. This is done by storing it in a |KeyExData| structure | 
|   66 // and RSA_get_app_data(). |   60 // that's referenced by the key using |EX_DATA|. | 
|   67 // |  | 
|   68 // One can thus _directly_ create a new EVP_PKEY that uses a custom RSA |  | 
|   69 // object with the following: |  | 
|   70 // |  | 
|   71 //    RSA* rsa = RSA_new() |  | 
|   72 //    RSA_set_method(&custom_rsa_method); |  | 
|   73 //    RSA_set_app_data(rsa, jni_private_key); |  | 
|   74 // |  | 
|   75 //    EVP_PKEY* pkey = EVP_PKEY_new(); |  | 
|   76 //    EVP_PKEY_assign_RSA(pkey, rsa); |  | 
|   77 // |  | 
|   78 // Note that because EVP_PKEY_assign_RSA() is used, instead of |  | 
|   79 // EVP_PKEY_set1_RSA(), the new EVP_PKEY now owns the RSA object, and |  | 
|   80 // will destroy it when it is itself destroyed. |  | 
|   81 // |  | 
|   82 // Unfortunately, such objects cannot be used with RSA_size(), which |  | 
|   83 // totally ignores the RSA_METHOD pointers. Instead, it is necessary |  | 
|   84 // to manually setup the modulus field (n) in the RSA object, with a |  | 
|   85 // value that matches the wrapped PrivateKey object. See GetRsaPkeyWrapper |  | 
|   86 // for full details. |  | 
|   87 // |  | 
|   88 // Similarly, custom DSA_METHOD and ECDSA_METHOD are defined by this source |  | 
|   89 // file, and appropriate field setups are performed to ensure that |  | 
|   90 // DSA_size() and ECDSA_size() work properly with the wrapper EVP_PKEY. |  | 
|   91 // |  | 
|   92 // Note that there is no need to define an OpenSSL ENGINE here. These |  | 
|   93 // are objects that can be used to expose custom methods (i.e. either |  | 
|   94 // RSA_METHOD, DSA_METHOD, ECDSA_METHOD, and a large number of other ones |  | 
|   95 // for types not related to this source file), and make them used by |  | 
|   96 // default for a lot of operations. Very fortunately, this is not needed |  | 
|   97 // here, which saves a lot of complexity. |  | 
|   98  |   61  | 
|   99 using base::android::ScopedJavaGlobalRef; |   62 using base::android::ScopedJavaGlobalRef; | 
|  100 using base::android::ScopedJavaLocalRef; |   63 using base::android::ScopedJavaLocalRef; | 
|  101  |   64  | 
|  102 namespace net { |   65 namespace net { | 
|  103 namespace android { |   66 namespace android { | 
|  104  |   67  | 
|  105 namespace { |   68 namespace { | 
|  106  |   69  | 
|  107 typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free>::Type ScopedEC_GROUP; |   70 extern const RSA_METHOD android_rsa_method; | 
 |   71 extern const ECDSA_METHOD android_ecdsa_method; | 
|  108  |   72  | 
|  109 // Custom RSA_METHOD that uses the platform APIs. |   73 // KeyExData contains the data that is contained in the EX_DATA of the RSA, DSA | 
|  110 // Note that for now, only signing through RSA_sign() is really supported. |   74 // and ECDSA objects that are created to wrap Android system keys. | 
|  111 // all other method pointers are either stubs returning errors, or no-ops. |   75 struct KeyExData { | 
|  112 // See <openssl/rsa.h> for exact declaration of RSA_METHOD. |   76   // private_key contains a reference to a Java, private-key object. | 
|  113  |  | 
|  114 struct RsaAppData { |  | 
|  115   jobject private_key; |   77   jobject private_key; | 
 |   78   // legacy_rsa, if not NULL, points to an RSA* in the system's OpenSSL (which | 
 |   79   // might not be ABI compatible with Chromium). | 
|  116   AndroidRSA* legacy_rsa; |   80   AndroidRSA* legacy_rsa; | 
 |   81   // cached_size contains the "size" of the key. This is the size of the | 
 |   82   // modulus (in bytes) for RSA, or the group order size for (EC)DSA. This | 
 |   83   // avoids calling into Java to calculate the size. | 
 |   84   size_t cached_size; | 
|  117 }; |   85 }; | 
|  118  |   86  | 
|  119 int RsaMethodPubEnc(int flen, |   87 // ExDataDup is called when one of the RSA, DSA or EC_KEY objects is | 
|  120                     const unsigned char* from, |   88 // duplicated. We don't support this and it should never happen. | 
|  121                     unsigned char* to, |   89 int ExDataDup(CRYPTO_EX_DATA* to, | 
|  122                     RSA* rsa, |   90               const CRYPTO_EX_DATA* from, | 
|  123                     int padding) { |   91               void** from_d, | 
|  124   NOTIMPLEMENTED(); |   92               int index, | 
|  125   RSAerr(RSA_F_RSA_PUBLIC_ENCRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); |   93               long argl, | 
|  126   return -1; |   94               void* argp) { | 
 |   95   CHECK(false); | 
 |   96   return 0; | 
|  127 } |   97 } | 
|  128  |   98  | 
|  129 int RsaMethodPubDec(int flen, |   99 // ExDataFree is called when one of the RSA, DSA or EC_KEY object is freed. | 
|  130                     const unsigned char* from, |  100 void ExDataFree(void* parent, | 
|  131                     unsigned char* to, |  101                 void* ptr, | 
|  132                     RSA* rsa, |  102                 CRYPTO_EX_DATA* ad, | 
|  133                     int padding) { |  103                 int index, | 
|  134   NOTIMPLEMENTED(); |  104                 long argl, | 
|  135   RSAerr(RSA_F_RSA_PUBLIC_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); |  105                 void* argp) { | 
|  136   return -1; |  106   // Ensure the global JNI reference created with this wrapper is | 
 |  107   // properly destroyed with it. | 
 |  108   KeyExData *ex_data = reinterpret_cast<KeyExData*>(ptr); | 
 |  109   if (ex_data != NULL) { | 
 |  110     ReleaseKey(ex_data->private_key); | 
 |  111     delete ex_data; | 
 |  112   } | 
|  137 } |  113 } | 
|  138  |  114  | 
|  139 // See RSA_eay_private_encrypt in |  115 // BoringSSLEngine is a BoringSSL ENGINE that implements RSA, DSA and ECDSA by | 
|  140 // third_party/openssl/openssl/crypto/rsa/rsa_eay.c for the default |  116 // forwarding the requested operations to the Java libraries. | 
|  141 // implementation of this function. |  117 class BoringSSLEngine { | 
|  142 int RsaMethodPrivEnc(int flen, |  118  public: | 
|  143                      const unsigned char *from, |  119   BoringSSLEngine() | 
|  144                      unsigned char *to, |  120       : rsa_index_(RSA_get_ex_new_index(0 /* argl */, | 
|  145                      RSA *rsa, |  121                                         NULL /* argp */, | 
 |  122                                         NULL /* new_func */, | 
 |  123                                         ExDataDup, | 
 |  124                                         ExDataFree)), | 
 |  125         ec_key_index_(EC_KEY_get_ex_new_index(0 /* argl */, | 
 |  126                                               NULL /* argp */, | 
 |  127                                               NULL /* new_func */, | 
 |  128                                               ExDataDup, | 
 |  129                                               ExDataFree)), | 
 |  130         engine_(ENGINE_new()) { | 
 |  131     ENGINE_set_RSA_method( | 
 |  132         engine_, &android_rsa_method, sizeof(android_rsa_method)); | 
 |  133     ENGINE_set_ECDSA_method( | 
 |  134         engine_, &android_ecdsa_method, sizeof(android_ecdsa_method)); | 
 |  135   } | 
 |  136  | 
 |  137   int rsa_ex_index() const { return rsa_index_; } | 
 |  138   int ec_key_ex_index() const { return ec_key_index_; } | 
 |  139  | 
 |  140   const ENGINE* engine() const { return engine_; } | 
 |  141  | 
 |  142  private: | 
 |  143   const int rsa_index_; | 
 |  144   const int ec_key_index_; | 
 |  145   ENGINE* const engine_; | 
 |  146 }; | 
 |  147  | 
 |  148 base::LazyInstance<BoringSSLEngine>::Leaky global_boringssl_engine = | 
 |  149     LAZY_INSTANCE_INITIALIZER; | 
 |  150  | 
 |  151  | 
 |  152 // VectorBignumSize returns the number of bytes needed to represent the bignum | 
 |  153 // given in |v|, i.e. the length of |v| less any leading zero bytes. | 
 |  154 size_t VectorBignumSize(const std::vector<uint8>& v) { | 
 |  155   size_t size = v.size(); | 
 |  156   // Ignore any leading zero bytes. | 
 |  157   for (size_t i = 0; i < v.size() && v[i] == 0; i++) { | 
 |  158     size--; | 
 |  159   } | 
 |  160   return size; | 
 |  161 } | 
 |  162  | 
 |  163 KeyExData* RsaGetExData(const RSA* rsa) { | 
 |  164   return reinterpret_cast<KeyExData*>( | 
 |  165       RSA_get_ex_data(rsa, global_boringssl_engine.Get().rsa_ex_index())); | 
 |  166 } | 
 |  167  | 
 |  168 size_t RsaMethodSize(const RSA *rsa) { | 
 |  169   const KeyExData *ex_data = RsaGetExData(rsa); | 
 |  170   return ex_data->cached_size; | 
 |  171 } | 
 |  172  | 
 |  173 int RsaMethodEncrypt(RSA* rsa, | 
 |  174                      size_t* out_len, | 
 |  175                      uint8_t* out, | 
 |  176                      size_t max_out, | 
 |  177                      const uint8_t* in, | 
 |  178                      size_t in_len, | 
 |  179                      int padding) { | 
 |  180   NOTIMPLEMENTED(); | 
 |  181   OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 
 |  182   return 0; | 
 |  183 } | 
 |  184  | 
 |  185 int RsaMethodSignRaw(RSA* rsa, | 
 |  186                      size_t* out_len, | 
 |  187                      uint8_t* out, | 
 |  188                      size_t max_out, | 
 |  189                      const uint8_t* in, | 
 |  190                      size_t in_len, | 
|  146                      int padding) { |  191                      int padding) { | 
|  147   DCHECK_EQ(RSA_PKCS1_PADDING, padding); |  192   DCHECK_EQ(RSA_PKCS1_PADDING, padding); | 
|  148   if (padding != RSA_PKCS1_PADDING) { |  193   if (padding != RSA_PKCS1_PADDING) { | 
|  149     // TODO(davidben): If we need to, we can implement RSA_NO_PADDING |  194     // TODO(davidben): If we need to, we can implement RSA_NO_PADDING | 
|  150     // by using javax.crypto.Cipher and picking either the |  195     // by using javax.crypto.Cipher and picking either the | 
|  151     // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |  196     // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 
|  152     // appropriate. I believe support for both of these was added in |  197     // appropriate. I believe support for both of these was added in | 
|  153     // the same Android version as the "NONEwithRSA" |  198     // the same Android version as the "NONEwithRSA" | 
|  154     // java.security.Signature algorithm, so the same version checks |  199     // java.security.Signature algorithm, so the same version checks | 
|  155     // for GetRsaLegacyKey should work. |  200     // for GetRsaLegacyKey should work. | 
|  156     RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, RSA_R_UNKNOWN_PADDING_TYPE); |  201     OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE); | 
|  157     return -1; |  202     return 0; | 
|  158   } |  203   } | 
|  159  |  204  | 
|  160   // Retrieve private key JNI reference. |  205   // Retrieve private key JNI reference. | 
|  161   RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); |  206   const KeyExData *ex_data = RsaGetExData(rsa); | 
|  162   if (!app_data || !app_data->private_key) { |  207   if (!ex_data || !ex_data->private_key) { | 
|  163     LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; |  208     LOG(WARNING) << "Null JNI reference passed to RsaMethodPrivEnc!"; | 
|  164     RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |  209     OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 
|  165     return -1; |  210     return 0; | 
|  166   } |  211   } | 
|  167  |  212  | 
|  168   // Pre-4.2 legacy codepath. |  213   // Pre-4.2 legacy codepath. | 
|  169   if (app_data->legacy_rsa) { |  214   if (ex_data->legacy_rsa) { | 
|  170     int ret = app_data->legacy_rsa->meth->rsa_priv_enc( |  215     int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( | 
|  171         flen, from, to, app_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); |  216         in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); | 
|  172     if (ret < 0) { |  217     if (ret < 0) { | 
|  173       LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; |  218       LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; | 
|  174       // System OpenSSL will use a separate error queue, so it is still |  219       // System OpenSSL will use a separate error queue, so it is still | 
|  175       // necessary to push a new error. |  220       // necessary to push a new error. | 
|  176       // |  221       // | 
|  177       // TODO(davidben): It would be good to also clear the system error queue |  222       // TODO(davidben): It would be good to also clear the system error queue | 
|  178       // if there were some way to convince Java to do it. (Without going |  223       // if there were some way to convince Java to do it. (Without going | 
|  179       // through Java, it's difficult to get a handle on a system OpenSSL |  224       // through Java, it's difficult to get a handle on a system OpenSSL | 
|  180       // function; dlopen loads a second copy.) |  225       // function; dlopen loads a second copy.) | 
|  181       RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |  226       OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 
|  182       return -1; |  227       return 0; | 
|  183     } |  228     } | 
|  184     return ret; |  229     *out_len = ret; | 
 |  230     return 1; | 
|  185   } |  231   } | 
|  186  |  232  | 
|  187   base::StringPiece from_piece(reinterpret_cast<const char*>(from), flen); |  233   base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len); | 
|  188   std::vector<uint8> result; |  234   std::vector<uint8> result; | 
|  189   // For RSA keys, this function behaves as RSA_private_encrypt with |  235   // For RSA keys, this function behaves as RSA_private_encrypt with | 
|  190   // PKCS#1 padding. |  236   // PKCS#1 padding. | 
|  191   if (!RawSignDigestWithPrivateKey(app_data->private_key, |  237   if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) { | 
|  192                                    from_piece, &result)) { |  | 
|  193     LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; |  238     LOG(WARNING) << "Could not sign message in RsaMethodPrivEnc!"; | 
|  194     RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |  239     OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 
|  195     return -1; |  240     return 0; | 
|  196   } |  241   } | 
|  197  |  242  | 
|  198   size_t expected_size = static_cast<size_t>(RSA_size(rsa)); |  243   size_t expected_size = static_cast<size_t>(RSA_size(rsa)); | 
|  199   if (result.size() > expected_size) { |  244   if (result.size() > expected_size) { | 
|  200     LOG(ERROR) << "RSA Signature size mismatch, actual: " |  245     LOG(ERROR) << "RSA Signature size mismatch, actual: " | 
|  201                <<  result.size() << ", expected <= " << expected_size; |  246                <<  result.size() << ", expected <= " << expected_size; | 
|  202     RSAerr(RSA_F_RSA_PRIVATE_ENCRYPT, ERR_R_INTERNAL_ERROR); |  247     OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 
|  203     return -1; |  248     return 0; | 
 |  249   } | 
 |  250  | 
 |  251   if (max_out < expected_size) { | 
 |  252     OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE); | 
 |  253     return 0; | 
|  204   } |  254   } | 
|  205  |  255  | 
|  206   // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey |  256   // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey | 
|  207   // should pad with leading 0s, but if it doesn't, pad the result. |  257   // should pad with leading 0s, but if it doesn't, pad the result. | 
|  208   size_t zero_pad = expected_size - result.size(); |  258   size_t zero_pad = expected_size - result.size(); | 
|  209   memset(to, 0, zero_pad); |  259   memset(out, 0, zero_pad); | 
|  210   memcpy(to + zero_pad, &result[0], result.size()); |  260   memcpy(out + zero_pad, &result[0], result.size()); | 
 |  261   *out_len = expected_size; | 
|  211  |  262  | 
|  212   return expected_size; |  263   return 1; | 
|  213 } |  264 } | 
|  214  |  265  | 
|  215 int RsaMethodPrivDec(int flen, |  266 int RsaMethodDecrypt(RSA* rsa, | 
|  216                      const unsigned char* from, |  267                      size_t* out_len, | 
|  217                      unsigned char* to, |  268                      uint8_t* out, | 
|  218                      RSA* rsa, |  269                      size_t max_out, | 
 |  270                      const uint8_t* in, | 
 |  271                      size_t in_len, | 
|  219                      int padding) { |  272                      int padding) { | 
|  220   NOTIMPLEMENTED(); |  273   NOTIMPLEMENTED(); | 
|  221   RSAerr(RSA_F_RSA_PRIVATE_DECRYPT, RSA_R_RSA_OPERATIONS_NOT_SUPPORTED); |  274   OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 
|  222   return -1; |  | 
|  223 } |  | 
|  224  |  | 
|  225 int RsaMethodInit(RSA* rsa) { |  | 
|  226   return 0; |  275   return 0; | 
|  227 } |  276 } | 
|  228  |  277  | 
|  229 int RsaMethodFinish(RSA* rsa) { |  278 int RsaMethodVerifyRaw(RSA* rsa, | 
|  230   // Ensure the global JNI reference created with this wrapper is |  279                        size_t* out_len, | 
|  231   // properly destroyed with it. |  280                        uint8_t* out, | 
|  232   RsaAppData* app_data = static_cast<RsaAppData*>(RSA_get_app_data(rsa)); |  281                        size_t max_out, | 
|  233   if (app_data != NULL) { |  282                        const uint8_t* in, | 
|  234     RSA_set_app_data(rsa, NULL); |  283                        size_t in_len, | 
|  235     ReleaseKey(app_data->private_key); |  284                        int padding) { | 
|  236     delete app_data; |  285   NOTIMPLEMENTED(); | 
|  237   } |  286   OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 
|  238   // Actual return value is ignored by OpenSSL. There are no docs |  | 
|  239   // explaining what this is supposed to be. |  | 
|  240   return 0; |  287   return 0; | 
|  241 } |  288 } | 
|  242  |  289  | 
|  243 const RSA_METHOD android_rsa_method = { |  290 const RSA_METHOD android_rsa_method = { | 
|  244   /* .name = */ "Android signing-only RSA method", |  291     { | 
|  245   /* .rsa_pub_enc = */ RsaMethodPubEnc, |  292      0 /* references */, | 
|  246   /* .rsa_pub_dec = */ RsaMethodPubDec, |  293      1 /* is_static */ | 
|  247   /* .rsa_priv_enc = */ RsaMethodPrivEnc, |  294     } /* common */, | 
|  248   /* .rsa_priv_dec = */ RsaMethodPrivDec, |  295     NULL /* app_data */, | 
|  249   /* .rsa_mod_exp = */ NULL, |  296  | 
|  250   /* .bn_mod_exp = */ NULL, |  297     NULL /* init */, | 
|  251   /* .init = */ RsaMethodInit, |  298     NULL /* finish */, | 
|  252   /* .finish = */ RsaMethodFinish, |  299     RsaMethodSize, | 
|  253   // This flag is necessary to tell OpenSSL to avoid checking the content |  300     NULL /* sign */, | 
|  254   // (i.e. internal fields) of the private key. Otherwise, it will complain |  301     NULL /* verify */, | 
|  255   // it's not valid for the certificate. |  302     RsaMethodEncrypt, | 
|  256   /* .flags = */ RSA_METHOD_FLAG_NO_CHECK, |  303     RsaMethodSignRaw, | 
|  257   /* .app_data = */ NULL, |  304     RsaMethodDecrypt, | 
|  258   /* .rsa_sign = */ NULL, |  305     RsaMethodVerifyRaw, | 
|  259   /* .rsa_verify = */ NULL, |  306     NULL /* mod_exp */, | 
|  260   /* .rsa_keygen = */ NULL, |  307     NULL /* bn_mod_exp */, | 
 |  308     RSA_FLAG_OPAQUE, | 
 |  309     NULL /* keygen */, | 
|  261 }; |  310 }; | 
|  262  |  311  | 
|  263 // Copy the contents of an encoded big integer into an existing BIGNUM. |  | 
|  264 // This function modifies |*num| in-place. |  | 
|  265 // |new_bytes| is the byte encoding of the new value. |  | 
|  266 // |num| points to the BIGNUM which will be assigned with the new value. |  | 
|  267 // Returns true on success, false otherwise. On failure, |*num| is |  | 
|  268 // not modified. |  | 
|  269 bool CopyBigNumFromBytes(const std::vector<uint8>& new_bytes, |  | 
|  270                          BIGNUM* num) { |  | 
|  271   BIGNUM* ret = BN_bin2bn( |  | 
|  272       reinterpret_cast<const unsigned char*>(&new_bytes[0]), |  | 
|  273       static_cast<int>(new_bytes.size()), |  | 
|  274       num); |  | 
|  275   return (ret != NULL); |  | 
|  276 } |  | 
|  277  |  | 
|  278 // Decode the contents of an encoded big integer and either create a new |  | 
|  279 // BIGNUM object (if |*num_ptr| is NULL on input) or copy it (if |  | 
|  280 // |*num_ptr| is not NULL). |  | 
|  281 // |new_bytes| is the byte encoding of the new value. |  | 
|  282 // |num_ptr| is the address of a BIGNUM pointer. |*num_ptr| can be NULL. |  | 
|  283 // Returns true on success, false otherwise. On failure, |*num_ptr| is |  | 
|  284 // not modified. On success, |*num_ptr| will always be non-NULL and |  | 
|  285 // point to a valid BIGNUM object. |  | 
|  286 bool SwapBigNumPtrFromBytes(const std::vector<uint8>& new_bytes, |  | 
|  287                             BIGNUM** num_ptr) { |  | 
|  288   BIGNUM* old_num = *num_ptr; |  | 
|  289   BIGNUM* new_num = BN_bin2bn( |  | 
|  290       reinterpret_cast<const unsigned char*>(&new_bytes[0]), |  | 
|  291       static_cast<int>(new_bytes.size()), |  | 
|  292       old_num); |  | 
|  293   if (new_num == NULL) |  | 
|  294     return false; |  | 
|  295  |  | 
|  296   if (old_num == NULL) |  | 
|  297     *num_ptr = new_num; |  | 
|  298   return true; |  | 
|  299 } |  | 
|  300  |  | 
|  301 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. |  312 // Setup an EVP_PKEY to wrap an existing platform RSA PrivateKey object. | 
|  302 // |private_key| is the JNI reference (local or global) to the object. |  313 // |private_key| is the JNI reference (local or global) to the object. | 
|  303 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object |  314 // |legacy_rsa|, if non-NULL, is a pointer to the system OpenSSL RSA object | 
|  304 // backing |private_key|. This parameter is only used for Android < 4.2 to |  315 // backing |private_key|. This parameter is only used for Android < 4.2 to | 
|  305 // implement key operations not exposed by the platform. |  316 // implement key operations not exposed by the platform. | 
|  306 // |pkey| is the EVP_PKEY to setup as a wrapper. |  317 // |pkey| is the EVP_PKEY to setup as a wrapper. | 
|  307 // Returns true on success, false otherwise. |  318 // Returns true on success, false otherwise. | 
|  308 // On success, this creates a new global JNI reference to the object |  319 // On success, this creates a new global JNI reference to the object | 
|  309 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can |  320 // that is owned by and destroyed with the EVP_PKEY. I.e. caller can | 
|  310 // free |private_key| after the call. |  321 // free |private_key| after the call. | 
|  311 bool GetRsaPkeyWrapper(jobject private_key, |  322 bool GetRsaPkeyWrapper(jobject private_key, | 
|  312                        AndroidRSA* legacy_rsa, |  323                        AndroidRSA* legacy_rsa, | 
|  313                        EVP_PKEY* pkey) { |  324                        EVP_PKEY* pkey) { | 
|  314   crypto::ScopedRSA rsa(RSA_new()); |  325   crypto::ScopedRSA rsa( | 
|  315   RSA_set_method(rsa.get(), &android_rsa_method); |  326       RSA_new_method(global_boringssl_engine.Get().engine())); | 
|  316  |  | 
|  317   // HACK: RSA_size() doesn't work with custom RSA_METHODs. To ensure that |  | 
|  318   // it will return the right value, set the 'n' field of the RSA object |  | 
|  319   // to match the private key's modulus. |  | 
|  320   // |  | 
|  321   // TODO(davidben): After switching to BoringSSL, consider making RSA_size call |  | 
|  322   // into an RSA_METHOD hook. |  | 
|  323   std::vector<uint8> modulus; |  | 
|  324   if (!GetRSAKeyModulus(private_key, &modulus)) { |  | 
|  325     LOG(ERROR) << "Failed to get private key modulus"; |  | 
|  326     return false; |  | 
|  327   } |  | 
|  328   if (!SwapBigNumPtrFromBytes(modulus, &rsa.get()->n)) { |  | 
|  329     LOG(ERROR) << "Failed to decode private key modulus"; |  | 
|  330     return false; |  | 
|  331   } |  | 
|  332  |  327  | 
|  333   ScopedJavaGlobalRef<jobject> global_key; |  328   ScopedJavaGlobalRef<jobject> global_key; | 
|  334   global_key.Reset(NULL, private_key); |  329   global_key.Reset(NULL, private_key); | 
|  335   if (global_key.is_null()) { |  330   if (global_key.is_null()) { | 
|  336     LOG(ERROR) << "Could not create global JNI reference"; |  331     LOG(ERROR) << "Could not create global JNI reference"; | 
|  337     return false; |  332     return false; | 
|  338   } |  333   } | 
|  339   RsaAppData* app_data = new RsaAppData(); |  334  | 
|  340   app_data->private_key = global_key.Release(); |  335   std::vector<uint8> modulus; | 
|  341   app_data->legacy_rsa = legacy_rsa; |  336   if (!GetRSAKeyModulus(private_key, &modulus)) { | 
|  342   RSA_set_app_data(rsa.get(), app_data); |  337     LOG(ERROR) << "Failed to get private key modulus"; | 
 |  338     return false; | 
 |  339   } | 
 |  340  | 
 |  341   KeyExData* ex_data = new KeyExData; | 
 |  342   ex_data->private_key = global_key.Release(); | 
 |  343   ex_data->legacy_rsa = legacy_rsa; | 
 |  344   ex_data->cached_size = VectorBignumSize(modulus); | 
 |  345   RSA_set_ex_data( | 
 |  346       rsa.get(), global_boringssl_engine.Get().rsa_ex_index(), ex_data); | 
|  343   EVP_PKEY_assign_RSA(pkey, rsa.release()); |  347   EVP_PKEY_assign_RSA(pkey, rsa.release()); | 
|  344   return true; |  348   return true; | 
|  345 } |  349 } | 
|  346  |  350  | 
|  347 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not |  351 // On Android < 4.2, the libkeystore.so ENGINE uses CRYPTO_EX_DATA and is not | 
|  348 // added to the global engine list. If all references to it are dropped, OpenSSL |  352 // added to the global engine list. If all references to it are dropped, OpenSSL | 
|  349 // will dlclose the module, leaving a dangling function pointer in the RSA |  353 // will dlclose the module, leaving a dangling function pointer in the RSA | 
|  350 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the |  354 // CRYPTO_EX_DATA class. To work around this, leak an extra reference to the | 
|  351 // ENGINE we extract in GetRsaLegacyKey. |  355 // ENGINE we extract in GetRsaLegacyKey. | 
|  352 // |  356 // | 
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  391   if (sys_pkey != NULL) { |  395   if (sys_pkey != NULL) { | 
|  392     if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { |  396     if (sys_pkey->type != ANDROID_EVP_PKEY_RSA) { | 
|  393       LOG(ERROR) << "Private key has wrong type!"; |  397       LOG(ERROR) << "Private key has wrong type!"; | 
|  394       return NULL; |  398       return NULL; | 
|  395     } |  399     } | 
|  396  |  400  | 
|  397     AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; |  401     AndroidRSA* sys_rsa = sys_pkey->pkey.rsa; | 
|  398     if (sys_rsa->engine) { |  402     if (sys_rsa->engine) { | 
|  399       // |private_key| may not have an engine if the PrivateKey did not come |  403       // |private_key| may not have an engine if the PrivateKey did not come | 
|  400       // from the key store, such as in unit tests. |  404       // from the key store, such as in unit tests. | 
|  401       if (!strcmp(sys_rsa->engine->id, "keystore")) { |  405       if (strcmp(sys_rsa->engine->id, "keystore") == 0) { | 
|  402         LeakEngine(private_key); |  406         LeakEngine(private_key); | 
|  403       } else { |  407       } else { | 
|  404         NOTREACHED(); |  408         NOTREACHED(); | 
|  405       } |  409       } | 
|  406     } |  410     } | 
|  407  |  411  | 
|  408     crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |  412     crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 
|  409     if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) |  413     if (!GetRsaPkeyWrapper(private_key, sys_rsa, pkey.get())) | 
|  410       return NULL; |  414       return NULL; | 
|  411     return pkey.release(); |  415     return pkey.release(); | 
| (...skipping 12 matching lines...) Expand all  Loading... | 
|  424       reinterpret_cast<const unsigned char*>(&encoded[0]); |  428       reinterpret_cast<const unsigned char*>(&encoded[0]); | 
|  425   int len = static_cast<int>(encoded.size()); |  429   int len = static_cast<int>(encoded.size()); | 
|  426   EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); |  430   EVP_PKEY* pkey = d2i_AutoPrivateKey(NULL, &p, len); | 
|  427   if (pkey == NULL) { |  431   if (pkey == NULL) { | 
|  428     LOG(ERROR) << "Can't convert private key data!"; |  432     LOG(ERROR) << "Can't convert private key data!"; | 
|  429     return NULL; |  433     return NULL; | 
|  430   } |  434   } | 
|  431   return pkey; |  435   return pkey; | 
|  432 } |  436 } | 
|  433  |  437  | 
|  434 // Custom DSA_METHOD that uses the platform APIs. |  | 
|  435 // Note that for now, only signing through DSA_sign() is really supported. |  | 
|  436 // all other method pointers are either stubs returning errors, or no-ops. |  | 
|  437 // See <openssl/dsa.h> for exact declaration of DSA_METHOD. |  | 
|  438 // |  | 
|  439 // Note: There is no DSA_set_app_data() and DSA_get_app_data() functions, |  | 
|  440 //       but RSA_set_app_data() is defined as a simple macro that calls |  | 
|  441 //       RSA_set_ex_data() with a hard-coded index of 0, so this code |  | 
|  442 //       does the same thing here. |  | 
|  443  |  | 
|  444 DSA_SIG* DsaMethodDoSign(const unsigned char* dgst, |  | 
|  445                          int dlen, |  | 
|  446                          DSA* dsa) { |  | 
|  447   // Extract the JNI reference to the PrivateKey object. |  | 
|  448   jobject private_key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa, 0)); |  | 
|  449   if (private_key == NULL) |  | 
|  450     return NULL; |  | 
|  451  |  | 
|  452   // Sign the message with it, calling platform APIs. |  | 
|  453   std::vector<uint8> signature; |  | 
|  454   if (!RawSignDigestWithPrivateKey( |  | 
|  455           private_key, |  | 
|  456           base::StringPiece( |  | 
|  457               reinterpret_cast<const char*>(dgst), |  | 
|  458               static_cast<size_t>(dlen)), |  | 
|  459           &signature)) { |  | 
|  460     return NULL; |  | 
|  461   } |  | 
|  462  |  | 
|  463   // Note: With DSA, the actual signature might be smaller than DSA_size(). |  | 
|  464   size_t max_expected_size = static_cast<size_t>(DSA_size(dsa)); |  | 
|  465   if (signature.size() > max_expected_size) { |  | 
|  466     LOG(ERROR) << "DSA Signature size mismatch, actual: " |  | 
|  467                << signature.size() << ", expected <= " |  | 
|  468                << max_expected_size; |  | 
|  469     return NULL; |  | 
|  470   } |  | 
|  471  |  | 
|  472   // Convert the signature into a DSA_SIG object. |  | 
|  473   const unsigned char* sigbuf = |  | 
|  474       reinterpret_cast<const unsigned char*>(&signature[0]); |  | 
|  475   int siglen = static_cast<size_t>(signature.size()); |  | 
|  476   DSA_SIG* dsa_sig = d2i_DSA_SIG(NULL, &sigbuf, siglen); |  | 
|  477   return dsa_sig; |  | 
|  478 } |  | 
|  479  |  | 
|  480 int DsaMethodSignSetup(DSA* dsa, |  | 
|  481                        BN_CTX* ctx_in, |  | 
|  482                        BIGNUM** kinvp, |  | 
|  483                        BIGNUM** rp) { |  | 
|  484   NOTIMPLEMENTED(); |  | 
|  485   DSAerr(DSA_F_DSA_SIGN_SETUP, DSA_R_INVALID_DIGEST_TYPE); |  | 
|  486   return -1; |  | 
|  487 } |  | 
|  488  |  | 
|  489 int DsaMethodDoVerify(const unsigned char* dgst, |  | 
|  490                       int dgst_len, |  | 
|  491                       DSA_SIG* sig, |  | 
|  492                       DSA* dsa) { |  | 
|  493   NOTIMPLEMENTED(); |  | 
|  494   DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_INVALID_DIGEST_TYPE); |  | 
|  495   return -1; |  | 
|  496 } |  | 
|  497  |  | 
|  498 int DsaMethodFinish(DSA* dsa) { |  | 
|  499   // Free the global JNI reference that was created with this |  | 
|  500   // wrapper key. |  | 
|  501   jobject key = reinterpret_cast<jobject>(DSA_get_ex_data(dsa,0)); |  | 
|  502   if (key != NULL) { |  | 
|  503     DSA_set_ex_data(dsa, 0, NULL); |  | 
|  504     ReleaseKey(key); |  | 
|  505   } |  | 
|  506   // Actual return value is ignored by OpenSSL. There are no docs |  | 
|  507   // explaining what this is supposed to be. |  | 
|  508   return 0; |  | 
|  509 } |  | 
|  510  |  | 
|  511 const DSA_METHOD android_dsa_method = { |  | 
|  512   /* .name = */ "Android signing-only DSA method", |  | 
|  513   /* .dsa_do_sign = */ DsaMethodDoSign, |  | 
|  514   /* .dsa_sign_setup = */ DsaMethodSignSetup, |  | 
|  515   /* .dsa_do_verify = */ DsaMethodDoVerify, |  | 
|  516   /* .dsa_mod_exp = */ NULL, |  | 
|  517   /* .bn_mod_exp = */ NULL, |  | 
|  518   /* .init = */ NULL,  // nothing to do here. |  | 
|  519   /* .finish = */ DsaMethodFinish, |  | 
|  520   /* .flags = */ 0, |  | 
|  521   /* .app_data = */ NULL, |  | 
|  522   /* .dsa_paramgem = */ NULL, |  | 
|  523   /* .dsa_keygen = */ NULL |  | 
|  524 }; |  | 
|  525  |  | 
|  526 // Setup an EVP_PKEY to wrap an existing DSA platform PrivateKey object. |  | 
|  527 // |private_key| is a JNI reference (local or global) to the object. |  | 
|  528 // |pkey| is the EVP_PKEY to setup as a wrapper. |  | 
|  529 // Returns true on success, false otherwise. |  | 
|  530 // On success, this creates a global JNI reference to the same object |  | 
|  531 // that will be owned by and destroyed with the EVP_PKEY. |  | 
|  532 bool GetDsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |  | 
|  533   crypto::ScopedDSA dsa(DSA_new()); |  | 
|  534   DSA_set_method(dsa.get(), &android_dsa_method); |  | 
|  535  |  | 
|  536   // DSA_size() doesn't work with custom DSA_METHODs. To ensure it |  | 
|  537   // returns the right value, set the 'q' field in the DSA object to |  | 
|  538   // match the parameter from the platform key. |  | 
|  539   std::vector<uint8> q; |  | 
|  540   if (!GetDSAKeyParamQ(private_key, &q)) { |  | 
|  541     LOG(ERROR) << "Can't extract Q parameter from DSA private key"; |  | 
|  542     return false; |  | 
|  543   } |  | 
|  544   if (!SwapBigNumPtrFromBytes(q, &dsa.get()->q)) { |  | 
|  545     LOG(ERROR) << "Can't decode Q parameter from DSA private key"; |  | 
|  546     return false; |  | 
|  547   } |  | 
|  548  |  | 
|  549   ScopedJavaGlobalRef<jobject> global_key; |  | 
|  550   global_key.Reset(NULL, private_key); |  | 
|  551   if (global_key.is_null()) { |  | 
|  552     LOG(ERROR) << "Could not create global JNI reference"; |  | 
|  553     return false; |  | 
|  554   } |  | 
|  555   DSA_set_ex_data(dsa.get(), 0, global_key.Release()); |  | 
|  556   EVP_PKEY_assign_DSA(pkey, dsa.release()); |  | 
|  557   return true; |  | 
|  558 } |  | 
|  559  |  | 
|  560 // Custom ECDSA_METHOD that uses the platform APIs. |  438 // Custom ECDSA_METHOD that uses the platform APIs. | 
|  561 // Note that for now, only signing through ECDSA_sign() is really supported. |  439 // Note that for now, only signing through ECDSA_sign() is really supported. | 
|  562 // all other method pointers are either stubs returning errors, or no-ops. |  440 // all other method pointers are either stubs returning errors, or no-ops. | 
|  563 // |  | 
|  564 // Note: The ECDSA_METHOD structure doesn't have init/finish |  | 
|  565 //       methods. As such, the only way to to ensure the global |  | 
|  566 //       JNI reference is properly released when the EVP_PKEY is |  | 
|  567 //       destroyed is to use a custom EX_DATA type. |  | 
|  568  |  441  | 
|  569 // Used to ensure that the global JNI reference associated with a custom |  442 jobject EcKeyGetKey(const EC_KEY* ec_key) { | 
|  570 // EC_KEY + ECDSA_METHOD wrapper is released when its EX_DATA is destroyed |  443   KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 
|  571 // (this function is called when EVP_PKEY_free() is called on the wrapper). |  444       ec_key, global_boringssl_engine.Get().ec_key_ex_index())); | 
|  572 void ExDataFree(void* parent, |  445   return ex_data->private_key; | 
|  573                 void* ptr, |  | 
|  574                 CRYPTO_EX_DATA* ad, |  | 
|  575                 int idx, |  | 
|  576                 long argl, |  | 
|  577                 void* argp) { |  | 
|  578   jobject private_key = reinterpret_cast<jobject>(ptr); |  | 
|  579   if (private_key == NULL) |  | 
|  580     return; |  | 
|  581  |  | 
|  582   CRYPTO_set_ex_data(ad, idx, NULL); |  | 
|  583   ReleaseKey(private_key); |  | 
|  584 } |  446 } | 
|  585  |  447  | 
|  586 int ExDataDup(CRYPTO_EX_DATA* to, |  448 size_t EcdsaMethodGroupOrderSize(const EC_KEY* ec_key) { | 
|  587               CRYPTO_EX_DATA* from, |  449   KeyExData* ex_data = reinterpret_cast<KeyExData*>(EC_KEY_get_ex_data( | 
|  588               void* from_d, |  450       ec_key, global_boringssl_engine.Get().ec_key_ex_index())); | 
|  589               int idx, |  451   return ex_data->cached_size; | 
|  590               long argl, |  | 
|  591               void* argp) { |  | 
|  592   // This callback shall never be called with the current OpenSSL |  | 
|  593   // implementation (the library only ever duplicates EX_DATA items |  | 
|  594   // for SSL and BIO objects). But provide this to catch regressions |  | 
|  595   // in the future. |  | 
|  596   CHECK(false) << "ExDataDup was called for ECDSA custom key !?"; |  | 
|  597   // Return value is currently ignored by OpenSSL. |  | 
|  598   return 0; |  | 
|  599 } |  452 } | 
|  600  |  453  | 
|  601 class EcdsaExDataIndex { |  454 int EcdsaMethodSign(const uint8_t* digest, | 
|  602 public: |  455                     size_t digest_len, | 
|  603   int ex_data_index() { return ex_data_index_; } |  456                     uint8_t* sig, | 
|  604  |  457                     unsigned int* sig_len, | 
|  605   EcdsaExDataIndex() { |  458                     EC_KEY* ec_key) { | 
|  606     ex_data_index_ = ECDSA_get_ex_new_index(0,           // argl |  | 
|  607                                             NULL,        // argp |  | 
|  608                                             NULL,        // new_func |  | 
|  609                                             ExDataDup,   // dup_func |  | 
|  610                                             ExDataFree); // free_func |  | 
|  611   } |  | 
|  612  |  | 
|  613 private: |  | 
|  614   int ex_data_index_; |  | 
|  615 }; |  | 
|  616  |  | 
|  617 // Returns the index of the custom EX_DATA used to store the JNI reference. |  | 
|  618 int EcdsaGetExDataIndex(void) { |  | 
|  619   // Use a LazyInstance to perform thread-safe lazy initialization. |  | 
|  620   // Use a leaky one, since OpenSSL doesn't provide a way to release |  | 
|  621   // allocated EX_DATA indices. |  | 
|  622   static base::LazyInstance<EcdsaExDataIndex>::Leaky s_instance = |  | 
|  623       LAZY_INSTANCE_INITIALIZER; |  | 
|  624   return s_instance.Get().ex_data_index(); |  | 
|  625 } |  | 
|  626  |  | 
|  627 ECDSA_SIG* EcdsaMethodDoSign(const unsigned char* dgst, |  | 
|  628                              int dgst_len, |  | 
|  629                              const BIGNUM* inv, |  | 
|  630                              const BIGNUM* rp, |  | 
|  631                              EC_KEY* eckey) { |  | 
|  632   // Retrieve private key JNI reference. |  459   // Retrieve private key JNI reference. | 
|  633   jobject private_key = reinterpret_cast<jobject>( |  460   jobject private_key = EcKeyGetKey(ec_key); | 
|  634       ECDSA_get_ex_data(eckey, EcdsaGetExDataIndex())); |  | 
|  635   if (!private_key) { |  461   if (!private_key) { | 
|  636     LOG(WARNING) << "Null JNI reference passed to EcdsaMethodDoSign!"; |  462     LOG(WARNING) << "Null JNI reference passed to EcdsaMethodSign!"; | 
|  637     return NULL; |  463     return 0; | 
|  638   } |  464   } | 
|  639   // Sign message with it through JNI. |  465   // Sign message with it through JNI. | 
|  640   std::vector<uint8> signature; |  466   std::vector<uint8> signature; | 
|  641   base::StringPiece digest( |  467   base::StringPiece digest_sp(reinterpret_cast<const char*>(digest), | 
|  642       reinterpret_cast<const char*>(dgst), |  468                               digest_len); | 
|  643       static_cast<size_t>(dgst_len)); |  469   if (!RawSignDigestWithPrivateKey(private_key, digest_sp, &signature)) { | 
|  644   if (!RawSignDigestWithPrivateKey( |  470     LOG(WARNING) << "Could not sign message in EcdsaMethodSign!"; | 
|  645           private_key, digest, &signature)) { |  471     return 0; | 
|  646     LOG(WARNING) << "Could not sign message in EcdsaMethodDoSign!"; |  | 
|  647     return NULL; |  | 
|  648   } |  472   } | 
|  649  |  473  | 
|  650   // Note: With ECDSA, the actual signature may be smaller than |  474   // Note: With ECDSA, the actual signature may be smaller than | 
|  651   // ECDSA_size(). |  475   // ECDSA_size(). | 
|  652   size_t max_expected_size = static_cast<size_t>(ECDSA_size(eckey)); |  476   size_t max_expected_size = ECDSA_size(ec_key); | 
|  653   if (signature.size() > max_expected_size) { |  477   if (signature.size() > max_expected_size) { | 
|  654     LOG(ERROR) << "ECDSA Signature size mismatch, actual: " |  478     LOG(ERROR) << "ECDSA Signature size mismatch, actual: " | 
|  655                <<  signature.size() << ", expected <= " |  479                <<  signature.size() << ", expected <= " | 
|  656                << max_expected_size; |  480                << max_expected_size; | 
|  657     return NULL; |  481     return 0; | 
|  658   } |  482   } | 
|  659  |  483  | 
|  660   // Convert signature to ECDSA_SIG object |  484   memcpy(sig, &signature[0], signature.size()); | 
|  661   const unsigned char* sigbuf = |  485   *sig_len = signature.size(); | 
|  662       reinterpret_cast<const unsigned char*>(&signature[0]); |  486   return 1; | 
|  663   long siglen = static_cast<long>(signature.size()); |  | 
|  664   return d2i_ECDSA_SIG(NULL, &sigbuf, siglen); |  | 
|  665 } |  487 } | 
|  666  |  488  | 
|  667 int EcdsaMethodSignSetup(EC_KEY* eckey, |  489 int EcdsaMethodVerify(const uint8_t* digest, | 
|  668                          BN_CTX* ctx, |  490                       size_t digest_len, | 
|  669                          BIGNUM** kinv, |  491                       const uint8_t* sig, | 
|  670                          BIGNUM** r) { |  492                       size_t sig_len, | 
 |  493                       EC_KEY* ec_key) { | 
|  671   NOTIMPLEMENTED(); |  494   NOTIMPLEMENTED(); | 
|  672   ECDSAerr(ECDSA_F_ECDSA_SIGN_SETUP, ECDSA_R_ERR_EC_LIB); |  495   OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); | 
|  673   return -1; |  496   return 0; | 
|  674 } |  497 } | 
|  675  |  498  | 
|  676 int EcdsaMethodDoVerify(const unsigned char* dgst, |  | 
|  677                         int dgst_len, |  | 
|  678                         const ECDSA_SIG* sig, |  | 
|  679                         EC_KEY* eckey) { |  | 
|  680   NOTIMPLEMENTED(); |  | 
|  681   ECDSAerr(ECDSA_F_ECDSA_DO_VERIFY, ECDSA_R_ERR_EC_LIB); |  | 
|  682   return -1; |  | 
|  683 } |  | 
|  684  |  | 
|  685 const ECDSA_METHOD android_ecdsa_method = { |  | 
|  686   /* .name = */ "Android signing-only ECDSA method", |  | 
|  687   /* .ecdsa_do_sign = */ EcdsaMethodDoSign, |  | 
|  688   /* .ecdsa_sign_setup = */ EcdsaMethodSignSetup, |  | 
|  689   /* .ecdsa_do_verify = */ EcdsaMethodDoVerify, |  | 
|  690   /* .flags = */ 0, |  | 
|  691   /* .app_data = */ NULL, |  | 
|  692 }; |  | 
|  693  |  | 
|  694 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |  499 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 
|  695 // |private_key| is the JNI reference (local or global) to the object. |  500 // |private_key| is the JNI reference (local or global) to the object. | 
|  696 // |pkey| is the EVP_PKEY to setup as a wrapper. |  501 // |pkey| is the EVP_PKEY to setup as a wrapper. | 
|  697 // Returns true on success, false otherwise. |  502 // Returns true on success, false otherwise. | 
|  698 // On success, this creates a global JNI reference to the object that |  503 // On success, this creates a global JNI reference to the object that | 
|  699 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |  504 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 
|  700 // always free |private_key| after the call. |  505 // always free |private_key| after the call. | 
|  701 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { |  506 bool GetEcdsaPkeyWrapper(jobject private_key, EVP_PKEY* pkey) { | 
|  702   crypto::ScopedEC_KEY eckey(EC_KEY_new()); |  507   crypto::ScopedEC_KEY ec_key( | 
|  703   ECDSA_set_method(eckey.get(), &android_ecdsa_method); |  508       EC_KEY_new_method(global_boringssl_engine.Get().engine())); | 
|  704  |  | 
|  705   // To ensure that ECDSA_size() works properly, craft a custom EC_GROUP |  | 
|  706   // that has the same order than the private key. |  | 
|  707   std::vector<uint8> order; |  | 
|  708   if (!GetECKeyOrder(private_key, &order)) { |  | 
|  709     LOG(ERROR) << "Can't extract order parameter from EC private key"; |  | 
|  710     return false; |  | 
|  711   } |  | 
|  712   ScopedEC_GROUP group(EC_GROUP_new(EC_GFp_nist_method())); |  | 
|  713   if (!group.get()) { |  | 
|  714     LOG(ERROR) << "Can't create new EC_GROUP"; |  | 
|  715     return false; |  | 
|  716   } |  | 
|  717   if (!CopyBigNumFromBytes(order, &group.get()->order)) { |  | 
|  718     LOG(ERROR) << "Can't decode order from PrivateKey"; |  | 
|  719     return false; |  | 
|  720   } |  | 
|  721   EC_KEY_set_group(eckey.get(), group.release()); |  | 
|  722  |  509  | 
|  723   ScopedJavaGlobalRef<jobject> global_key; |  510   ScopedJavaGlobalRef<jobject> global_key; | 
|  724   global_key.Reset(NULL, private_key); |  511   global_key.Reset(NULL, private_key); | 
|  725   if (global_key.is_null()) { |  512   if (global_key.is_null()) { | 
|  726     LOG(ERROR) << "Can't create global JNI reference"; |  513     LOG(ERROR) << "Can't create global JNI reference"; | 
|  727     return false; |  514     return false; | 
|  728   } |  515   } | 
|  729   ECDSA_set_ex_data(eckey.get(), |  | 
|  730                     EcdsaGetExDataIndex(), |  | 
|  731                     global_key.Release()); |  | 
|  732  |  516  | 
|  733   EVP_PKEY_assign_EC_KEY(pkey, eckey.release()); |  517   std::vector<uint8> order; | 
 |  518   if (!GetECKeyOrder(private_key, &order)) { | 
 |  519     LOG(ERROR) << "Can't extract order parameter from EC private key"; | 
 |  520     return false; | 
 |  521   } | 
 |  522  | 
 |  523   KeyExData* ex_data = new KeyExData; | 
 |  524   ex_data->private_key = global_key.Release(); | 
 |  525   ex_data->legacy_rsa = NULL; | 
 |  526   ex_data->cached_size = VectorBignumSize(order); | 
 |  527  | 
 |  528   EC_KEY_set_ex_data( | 
 |  529       ec_key.get(), global_boringssl_engine.Get().ec_key_ex_index(), ex_data); | 
 |  530  | 
 |  531   EVP_PKEY_assign_EC_KEY(pkey, ec_key.release()); | 
|  734   return true; |  532   return true; | 
|  735 } |  533 } | 
|  736  |  534  | 
 |  535 const ECDSA_METHOD android_ecdsa_method = { | 
 |  536     { | 
 |  537      0 /* references */, | 
 |  538      1 /* is_static */ | 
 |  539     } /* common */, | 
 |  540     NULL /* app_data */, | 
 |  541  | 
 |  542     NULL /* init */, | 
 |  543     NULL /* finish */, | 
 |  544     EcdsaMethodGroupOrderSize, | 
 |  545     EcdsaMethodSign, | 
 |  546     EcdsaMethodVerify, | 
 |  547     ECDSA_FLAG_OPAQUE, | 
 |  548 }; | 
 |  549  | 
|  737 }  // namespace |  550 }  // namespace | 
|  738  |  551  | 
|  739 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { |  552 EVP_PKEY* GetOpenSSLPrivateKeyWrapper(jobject private_key) { | 
|  740   // Create new empty EVP_PKEY instance. |  553   // Create new empty EVP_PKEY instance. | 
|  741   crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); |  554   crypto::ScopedEVP_PKEY pkey(EVP_PKEY_new()); | 
|  742   if (!pkey.get()) |  555   if (!pkey.get()) | 
|  743     return NULL; |  556     return NULL; | 
|  744  |  557  | 
|  745   // Create sub key type, depending on private key's algorithm type. |  558   // Create sub key type, depending on private key's algorithm type. | 
|  746   PrivateKeyType key_type = GetPrivateKeyType(private_key); |  559   PrivateKeyType key_type = GetPrivateKeyType(private_key); | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
|  758           if (legacy_key == NULL) |  571           if (legacy_key == NULL) | 
|  759             return NULL; |  572             return NULL; | 
|  760           pkey.reset(legacy_key); |  573           pkey.reset(legacy_key); | 
|  761         } else { |  574         } else { | 
|  762           // Running on Android 4.2. |  575           // Running on Android 4.2. | 
|  763           if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get())) |  576           if (!GetRsaPkeyWrapper(private_key, NULL, pkey.get())) | 
|  764             return NULL; |  577             return NULL; | 
|  765         } |  578         } | 
|  766       } |  579       } | 
|  767       break; |  580       break; | 
|  768     case PRIVATE_KEY_TYPE_DSA: |  | 
|  769       if (!GetDsaPkeyWrapper(private_key, pkey.get())) |  | 
|  770         return NULL; |  | 
|  771       break; |  | 
|  772     case PRIVATE_KEY_TYPE_ECDSA: |  581     case PRIVATE_KEY_TYPE_ECDSA: | 
|  773       if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) |  582       if (!GetEcdsaPkeyWrapper(private_key, pkey.get())) | 
|  774         return NULL; |  583         return NULL; | 
|  775       break; |  584       break; | 
|  776     default: |  585     default: | 
|  777       LOG(WARNING) |  586       LOG(WARNING) | 
|  778           << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |  587           << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 
|  779       return NULL; |  588       return NULL; | 
|  780   } |  589   } | 
|  781   return pkey.release(); |  590   return pkey.release(); | 
|  782 } |  591 } | 
|  783  |  592  | 
|  784 }  // namespace android |  593 }  // namespace android | 
|  785 }  // namespace net |  594 }  // namespace net | 
| OLD | NEW |