summaryrefslogtreecommitdiff
path: root/chromium/net/android
diff options
context:
space:
mode:
authorZeno Albisser <zeno.albisser@digia.com>2013-11-21 14:09:57 +0100
committerAndras Becsi <andras.becsi@digia.com>2013-11-29 15:14:36 +0100
commiteb32ba6f51d0c21d58cd7d89785285ff8fa64624 (patch)
tree2c7c940e1dbee81b89d935626110816b494aa32c /chromium/net/android
parent9427c1a0222ebd67efef1a2c7990a0fa5c9aac84 (diff)
downloadqtwebengine-chromium-eb32ba6f51d0c21d58cd7d89785285ff8fa64624.tar.gz
Update chromium to branch 1599.
Change-Id: I04e775a946a208bb4500d3b722bcb05c82b9d7cb Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/net/android')
-rw-r--r--chromium/net/android/java/src/org/chromium/net/AndroidKeyStore.java19
-rw-r--r--chromium/net/android/keystore_openssl.cc79
2 files changed, 75 insertions, 23 deletions
diff --git a/chromium/net/android/java/src/org/chromium/net/AndroidKeyStore.java b/chromium/net/android/java/src/org/chromium/net/AndroidKeyStore.java
index 2edaa895b7e..de5d8f2d5f0 100644
--- a/chromium/net/android/java/src/org/chromium/net/AndroidKeyStore.java
+++ b/chromium/net/android/java/src/org/chromium/net/AndroidKeyStore.java
@@ -112,20 +112,21 @@ public class AndroidKeyStore {
* shall only be used to implement signing in the context of SSL
* client certificate support.
*
- * The message will actually be a hash, computed and padded by OpenSSL,
- * itself, depending on the type of the key. The result should match
- * exactly what the vanilla implementations of the following OpenSSL
- * function calls do:
+ * The message will actually be a hash, computed by OpenSSL itself,
+ * depending on the type of the key. The result should match exactly
+ * what the vanilla implementations of the following OpenSSL function
+ * calls do:
*
* - For a RSA private key, this should be equivalent to calling
- * RSA_sign(NDI_md5_sha1,....), i.e. it must generate a raw RSA
- * signature. The message must a combined, 36-byte MD5+SHA1 message
- * digest padded to the length of the modulus using PKCS#1 padding.
+ * RSA_private_encrypt(..., RSA_PKCS1_PADDING), i.e. it must
+ * generate a raw RSA signature. The message must be either a
+ * combined, 36-byte MD5+SHA1 message digest or a DigestInfo
+ * value wrapping a message digest.
*
* - For a DSA and ECDSA private keys, this should be equivalent to
* calling DSA_sign(0,...) and ECDSA_sign(0,...) respectively. The
- * message must be a 20-byte SHA1 hash and the function shall
- * compute a direct DSA/ECDSA signature for it.
+ * message must be a hash and the function shall compute a direct
+ * DSA/ECDSA signature for it.
*
* @param privateKey The PrivateKey handle.
* @param message The message to sign.
diff --git a/chromium/net/android/keystore_openssl.cc b/chromium/net/android/keystore_openssl.cc
index cc463f49539..cd55ece3336 100644
--- a/chromium/net/android/keystore_openssl.cc
+++ b/chromium/net/android/keystore_openssl.cc
@@ -35,7 +35,7 @@
//
// Generally speaking, OpenSSL provides many different ways to sign
// digests. This code doesn't support all these cases, only the ones that
-// are required to sign the MAC during the OpenSSL handshake for TLS < 1.2.
+// are required to sign the MAC during the OpenSSL handshake for TLS.
//
// The OpenSSL EVP_PKEY type is a generic wrapper around key pairs.
// Internally, it can hold a pointer to a RSA, DSA or ECDSA structure,
@@ -54,8 +54,8 @@
// are used to hold the typical modulus / exponent / parameters for the
// key pair).
//
-// This source file thus defines a custom RSA_METHOD structure, which
-// fields points to static methods used to implement the corresponding
+// This source file thus defines a custom RSA_METHOD structure whose
+// fields point to static methods used to implement the corresponding
// RSA operation using platform Android APIs.
//
// However, the platform APIs require a jobject JNI reference to work.
@@ -106,6 +106,7 @@ typedef crypto::ScopedOpenSSL<RSA, RSA_free> ScopedRSA;
typedef crypto::ScopedOpenSSL<DSA, DSA_free> ScopedDSA;
typedef crypto::ScopedOpenSSL<EC_KEY, EC_KEY_free> ScopedEC_KEY;
typedef crypto::ScopedOpenSSL<EC_GROUP, EC_GROUP_free> ScopedEC_GROUP;
+typedef crypto::ScopedOpenSSL<X509_SIG, X509_SIG_free> ScopedX509_SIG;
// Custom RSA_METHOD that uses the platform APIs.
// Note that for now, only signing through RSA_sign() is really supported.
@@ -172,28 +173,79 @@ int RsaMethodFinish(RSA* rsa) {
return 0;
}
+// Although these parameters are, per OpenSSL, named |message| and
+// |message_len|, RsaMethodSign is actually passed a message digest,
+// not the original message.
int RsaMethodSign(int type,
const unsigned char* message,
unsigned int message_len,
unsigned char* signature,
unsigned int* signature_len,
const RSA* rsa) {
- // This is only used for client certificate support, which
- // will always pass the NID_md5_sha1 |type| value.
- DCHECK_EQ(NID_md5_sha1, type);
- if (type != NID_md5_sha1) {
- RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
- return 0;
- }
// Retrieve private key JNI reference.
jobject private_key = reinterpret_cast<jobject>(RSA_get_app_data(rsa));
if (!private_key) {
LOG(WARNING) << "Null JNI reference passed to RsaMethodSign!";
return 0;
}
- // Sign message with it through JNI.
- base::StringPiece message_piece(reinterpret_cast<const char*>(message),
- static_cast<size_t>(message_len));
+
+ // See RSA_sign in third_party/openssl/openssl/crypto/rsa/rsa_sign.c.
+ base::StringPiece message_piece;
+ std::vector<uint8> buffer; // To store |message| wrapped in a DigestInfo.
+ if (type == NID_md5_sha1) {
+ // For TLS < 1.2, sign just |message|.
+ message_piece.set(message, static_cast<size_t>(message_len));
+ } else {
+ // For TLS 1.2, wrap |message| in a PKCS #1 DigestInfo before signing.
+ ScopedX509_SIG sig(X509_SIG_new());
+ if (!sig.get())
+ return 0;
+ if (X509_ALGOR_set0(sig.get()->algor,
+ OBJ_nid2obj(type), V_ASN1_NULL, 0) != 1) {
+ return 0;
+ }
+ if (sig.get()->algor->algorithm == NULL) {
+ RSAerr(RSA_F_RSA_SIGN, RSA_R_UNKNOWN_ALGORITHM_TYPE);
+ return 0;
+ }
+ if (sig.get()->algor->algorithm->length == 0) {
+ RSAerr(RSA_F_RSA_SIGN,
+ RSA_R_THE_ASN1_OBJECT_IDENTIFIER_IS_NOT_KNOWN_FOR_THIS_MD);
+ return 0;
+ }
+ if (ASN1_OCTET_STRING_set(sig.get()->digest, message, message_len) != 1)
+ return 0;
+
+ int len = i2d_X509_SIG(sig.get(), NULL);
+ if (len < 0) {
+ LOG(WARNING) << "Couldn't encode X509_SIG structure";
+ return 0;
+ }
+ buffer.resize(len);
+ // OpenSSL takes a pointer to a pointer so it can kindly increment
+ // it for you.
+ unsigned char* p = &buffer[0];
+ len = i2d_X509_SIG(sig.get(), &p);
+ if (len < 0) {
+ LOG(WARNING) << "Couldn't encode X509_SIG structure";
+ return 0;
+ }
+
+ message_piece.set(&buffer[0], static_cast<size_t>(len));
+ }
+
+ // Sanity-check the size.
+ //
+ // TODO(davidben): Do we need to do this? OpenSSL does, but
+ // RawSignDigestWithPrivateKey does error on sufficiently large
+ // input. However, it doesn't take the padding into account.
+ size_t expected_size = static_cast<size_t>(RSA_size(rsa));
+ if (message_piece.size() > expected_size - RSA_PKCS1_PADDING_SIZE) {
+ RSAerr(RSA_F_RSA_SIGN, RSA_R_DIGEST_TOO_BIG_FOR_RSA_KEY);
+ return 0;
+ }
+
+ // Sign |message_piece| with the private key through JNI.
std::vector<uint8> result;
if (!RawSignDigestWithPrivateKey(
@@ -202,7 +254,6 @@ int RsaMethodSign(int type,
return 0;
}
- size_t expected_size = static_cast<size_t>(RSA_size(rsa));
if (result.size() > expected_size) {
LOG(ERROR) << "RSA Signature size mismatch, actual: "
<< result.size() << ", expected <= " << expected_size;