Chromium Code Reviews| 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 #include <openssl/ec.h> | 9 #include <openssl/ec.h> |
| 10 #include <openssl/engine.h> | 10 #include <openssl/engine.h> |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 169 } | 169 } |
| 170 | 170 |
| 171 int RsaMethodEncrypt(RSA* rsa, | 171 int RsaMethodEncrypt(RSA* rsa, |
| 172 size_t* out_len, | 172 size_t* out_len, |
| 173 uint8_t* out, | 173 uint8_t* out, |
| 174 size_t max_out, | 174 size_t max_out, |
| 175 const uint8_t* in, | 175 const uint8_t* in, |
| 176 size_t in_len, | 176 size_t in_len, |
| 177 int padding) { | 177 int padding) { |
| 178 NOTIMPLEMENTED(); | 178 NOTIMPLEMENTED(); |
| 179 OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 179 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
|
davidben
2015/07/21 18:27:56
This will be going away once the Chrome/Android co
agl
2015/07/21 19:25:58
You mean that the code to bridge BoringSSL to Java
davidben
2015/07/21 19:43:25
Just the Conscrypt stuff. You'll need to make the
| |
| 180 return 0; | 180 return 0; |
| 181 } | 181 } |
| 182 | 182 |
| 183 int RsaMethodSignRaw(RSA* rsa, | 183 int RsaMethodSignRaw(RSA* rsa, |
| 184 size_t* out_len, | 184 size_t* out_len, |
| 185 uint8_t* out, | 185 uint8_t* out, |
| 186 size_t max_out, | 186 size_t max_out, |
| 187 const uint8_t* in, | 187 const uint8_t* in, |
| 188 size_t in_len, | 188 size_t in_len, |
| 189 int padding) { | 189 int padding) { |
| 190 DCHECK_EQ(RSA_PKCS1_PADDING, padding); | 190 DCHECK_EQ(RSA_PKCS1_PADDING, padding); |
| 191 if (padding != RSA_PKCS1_PADDING) { | 191 if (padding != RSA_PKCS1_PADDING) { |
| 192 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING | 192 // TODO(davidben): If we need to, we can implement RSA_NO_PADDING |
| 193 // by using javax.crypto.Cipher and picking either the | 193 // by using javax.crypto.Cipher and picking either the |
| 194 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as | 194 // "RSA/ECB/NoPadding" or "RSA/ECB/PKCS1Padding" transformation as |
| 195 // appropriate. I believe support for both of these was added in | 195 // appropriate. I believe support for both of these was added in |
| 196 // the same Android version as the "NONEwithRSA" | 196 // the same Android version as the "NONEwithRSA" |
| 197 // java.security.Signature algorithm, so the same version checks | 197 // java.security.Signature algorithm, so the same version checks |
| 198 // for GetRsaLegacyKey should work. | 198 // for GetRsaLegacyKey should work. |
| 199 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE); | 199 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE); |
| 200 return 0; | 200 return 0; |
| 201 } | 201 } |
| 202 | 202 |
| 203 // Retrieve private key JNI reference. | 203 // Retrieve private key JNI reference. |
| 204 const KeyExData *ex_data = RsaGetExData(rsa); | 204 const KeyExData *ex_data = RsaGetExData(rsa); |
| 205 if (!ex_data || !ex_data->private_key) { | 205 if (!ex_data || !ex_data->private_key) { |
| 206 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!"; | 206 LOG(WARNING) << "Null JNI reference passed to RsaMethodSignRaw!"; |
| 207 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 207 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 208 return 0; | 208 return 0; |
| 209 } | 209 } |
| 210 | 210 |
| 211 // Pre-4.2 legacy codepath. | 211 // Pre-4.2 legacy codepath. |
| 212 if (ex_data->legacy_rsa) { | 212 if (ex_data->legacy_rsa) { |
| 213 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( | 213 int ret = ex_data->legacy_rsa->meth->rsa_priv_enc( |
| 214 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); | 214 in_len, in, out, ex_data->legacy_rsa, ANDROID_RSA_PKCS1_PADDING); |
| 215 if (ret < 0) { | 215 if (ret < 0) { |
| 216 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; | 216 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; |
| 217 // System OpenSSL will use a separate error queue, so it is still | 217 // System OpenSSL will use a separate error queue, so it is still |
| 218 // necessary to push a new error. | 218 // necessary to push a new error. |
| 219 // | 219 // |
| 220 // TODO(davidben): It would be good to also clear the system error queue | 220 // TODO(davidben): It would be good to also clear the system error queue |
| 221 // if there were some way to convince Java to do it. (Without going | 221 // if there were some way to convince Java to do it. (Without going |
| 222 // through Java, it's difficult to get a handle on a system OpenSSL | 222 // through Java, it's difficult to get a handle on a system OpenSSL |
| 223 // function; dlopen loads a second copy.) | 223 // function; dlopen loads a second copy.) |
| 224 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 224 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 225 return 0; | 225 return 0; |
| 226 } | 226 } |
| 227 *out_len = ret; | 227 *out_len = ret; |
| 228 return 1; | 228 return 1; |
| 229 } | 229 } |
| 230 | 230 |
| 231 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len); | 231 base::StringPiece from_piece(reinterpret_cast<const char*>(in), in_len); |
| 232 std::vector<uint8_t> result; | 232 std::vector<uint8_t> result; |
| 233 // For RSA keys, this function behaves as RSA_private_encrypt with | 233 // For RSA keys, this function behaves as RSA_private_encrypt with |
| 234 // PKCS#1 padding. | 234 // PKCS#1 padding. |
| 235 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) { | 235 if (!RawSignDigestWithPrivateKey(ex_data->private_key, from_piece, &result)) { |
| 236 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; | 236 LOG(WARNING) << "Could not sign message in RsaMethodSignRaw!"; |
| 237 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 237 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 238 return 0; | 238 return 0; |
| 239 } | 239 } |
| 240 | 240 |
| 241 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); | 241 size_t expected_size = static_cast<size_t>(RSA_size(rsa)); |
| 242 if (result.size() > expected_size) { | 242 if (result.size() > expected_size) { |
| 243 LOG(ERROR) << "RSA Signature size mismatch, actual: " | 243 LOG(ERROR) << "RSA Signature size mismatch, actual: " |
| 244 << result.size() << ", expected <= " << expected_size; | 244 << result.size() << ", expected <= " << expected_size; |
| 245 OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_INTERNAL_ERROR); | 245 OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR); |
| 246 return 0; | 246 return 0; |
| 247 } | 247 } |
| 248 | 248 |
| 249 if (max_out < expected_size) { | 249 if (max_out < expected_size) { |
| 250 OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_DATA_TOO_LARGE); | 250 OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE); |
| 251 return 0; | 251 return 0; |
| 252 } | 252 } |
| 253 | 253 |
| 254 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey | 254 // Copy result to OpenSSL-provided buffer. RawSignDigestWithPrivateKey |
| 255 // should pad with leading 0s, but if it doesn't, pad the result. | 255 // should pad with leading 0s, but if it doesn't, pad the result. |
| 256 size_t zero_pad = expected_size - result.size(); | 256 size_t zero_pad = expected_size - result.size(); |
| 257 memset(out, 0, zero_pad); | 257 memset(out, 0, zero_pad); |
| 258 memcpy(out + zero_pad, &result[0], result.size()); | 258 memcpy(out + zero_pad, &result[0], result.size()); |
| 259 *out_len = expected_size; | 259 *out_len = expected_size; |
| 260 | 260 |
| 261 return 1; | 261 return 1; |
| 262 } | 262 } |
| 263 | 263 |
| 264 int RsaMethodDecrypt(RSA* rsa, | 264 int RsaMethodDecrypt(RSA* rsa, |
| 265 size_t* out_len, | 265 size_t* out_len, |
| 266 uint8_t* out, | 266 uint8_t* out, |
| 267 size_t max_out, | 267 size_t max_out, |
| 268 const uint8_t* in, | 268 const uint8_t* in, |
| 269 size_t in_len, | 269 size_t in_len, |
| 270 int padding) { | 270 int padding) { |
| 271 NOTIMPLEMENTED(); | 271 NOTIMPLEMENTED(); |
| 272 OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 272 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 273 return 0; | 273 return 0; |
| 274 } | 274 } |
| 275 | 275 |
| 276 int RsaMethodVerifyRaw(RSA* rsa, | 276 int RsaMethodVerifyRaw(RSA* rsa, |
| 277 size_t* out_len, | 277 size_t* out_len, |
| 278 uint8_t* out, | 278 uint8_t* out, |
| 279 size_t max_out, | 279 size_t max_out, |
| 280 const uint8_t* in, | 280 const uint8_t* in, |
| 281 size_t in_len, | 281 size_t in_len, |
| 282 int padding) { | 282 int padding) { |
| 283 NOTIMPLEMENTED(); | 283 NOTIMPLEMENTED(); |
| 284 OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_ALGORITHM_TYPE); | 284 OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_ALGORITHM_TYPE); |
| 285 return 0; | 285 return 0; |
| 286 } | 286 } |
| 287 | 287 |
| 288 const RSA_METHOD android_rsa_method = { | 288 const RSA_METHOD android_rsa_method = { |
| 289 { | 289 { |
| 290 0 /* references */, | 290 0 /* references */, |
| 291 1 /* is_static */ | 291 1 /* is_static */ |
| 292 } /* common */, | 292 } /* common */, |
| 293 nullptr /* app_data */, | 293 nullptr /* app_data */, |
| 294 | 294 |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 478 *sig_len = signature.size(); | 478 *sig_len = signature.size(); |
| 479 return 1; | 479 return 1; |
| 480 } | 480 } |
| 481 | 481 |
| 482 int EcdsaMethodVerify(const uint8_t* digest, | 482 int EcdsaMethodVerify(const uint8_t* digest, |
| 483 size_t digest_len, | 483 size_t digest_len, |
| 484 const uint8_t* sig, | 484 const uint8_t* sig, |
| 485 size_t sig_len, | 485 size_t sig_len, |
| 486 EC_KEY* ec_key) { | 486 EC_KEY* ec_key) { |
| 487 NOTIMPLEMENTED(); | 487 NOTIMPLEMENTED(); |
| 488 OPENSSL_PUT_ERROR(ECDSA, ECDSA_do_verify, ECDSA_R_NOT_IMPLEMENTED); | 488 OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_NOT_IMPLEMENTED); |
| 489 return 0; | 489 return 0; |
| 490 } | 490 } |
| 491 | 491 |
| 492 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. | 492 // Setup an EVP_PKEY to wrap an existing platform PrivateKey object. |
| 493 // |private_key| is the JNI reference (local or global) to the object. | 493 // |private_key| is the JNI reference (local or global) to the object. |
| 494 // Returns a new EVP_PKEY on success, NULL otherwise. | 494 // Returns a new EVP_PKEY on success, NULL otherwise. |
| 495 // On success, this creates a global JNI reference to the object that | 495 // On success, this creates a global JNI reference to the object that |
| 496 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall | 496 // is owned by and destroyed with the EVP_PKEY. I.e. the caller shall |
| 497 // always free |private_key| after the call. | 497 // always free |private_key| after the call. |
| 498 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) { | 498 crypto::ScopedEVP_PKEY GetEcdsaPkeyWrapper(jobject private_key) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 556 return GetEcdsaPkeyWrapper(private_key); | 556 return GetEcdsaPkeyWrapper(private_key); |
| 557 default: | 557 default: |
| 558 LOG(WARNING) | 558 LOG(WARNING) |
| 559 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; | 559 << "GetOpenSSLPrivateKeyWrapper() called with invalid key type"; |
| 560 return nullptr; | 560 return nullptr; |
| 561 } | 561 } |
| 562 } | 562 } |
| 563 | 563 |
| 564 } // namespace android | 564 } // namespace android |
| 565 } // namespace net | 565 } // namespace net |
| OLD | NEW |