forked from sanyaade-mobiledev/chromium.src
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Upstream certificate and mime Android implementation.
BUG= TEST= Review URL: http://codereview.chromium.org/7538029 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96401 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
michaelbai@google.com
committed
Aug 11, 2011
1 parent
b20c447
commit 6dbdaa8
Showing
8 changed files
with
329 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
include_rules = [ | ||
"+crypto", | ||
"+jni", | ||
"+third_party/apple_apsl", | ||
"+third_party/libevent", | ||
"+third_party/nss", | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// Copyright (c) 2010 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "net/android/network_library.h" | ||
|
||
#include "base/android/auto_jobject.h" | ||
#include "base/android/jni_android.h" | ||
#include "base/android/jni_array.h" | ||
#include "base/android/jni_string.h" | ||
#include "base/logging.h" | ||
#include "jni/android_network_library_jni.h" | ||
|
||
using base::android::AttachCurrentThread; | ||
using base::android::AutoJObject; | ||
using base::android::CheckException; | ||
using base::android::ConvertJavaStringToUTF8; | ||
using base::android::ConvertUTF8ToJavaString; | ||
using base::android::GetApplicationContext; | ||
using base::android::ToJavaArrayOfByteArray; | ||
using base::android::ToJavaByteArray; | ||
|
||
namespace net { | ||
namespace android { | ||
|
||
VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain, | ||
const std::string& hostname, | ||
const std::string& auth_type) { | ||
JNIEnv* env = AttachCurrentThread(); | ||
if (!env) { | ||
// TODO(husky): Maybe initialize the JVM in unit tests? | ||
LOG(WARNING) << "JNI initialization failed"; | ||
return VERIFY_INVOCATION_ERROR; | ||
} | ||
|
||
AutoJObject chain_byte_array = AutoJObject::FromLocalRef( | ||
env, ToJavaArrayOfByteArray(env, cert_chain)); | ||
DCHECK(chain_byte_array.obj()); | ||
|
||
AutoJObject host_string = AutoJObject::FromLocalRef( | ||
env, ConvertUTF8ToJavaString(env, hostname)); | ||
DCHECK(host_string.obj()); | ||
|
||
AutoJObject auth_string = AutoJObject::FromLocalRef( | ||
env, ConvertUTF8ToJavaString(env, auth_type)); | ||
DCHECK(auth_string.obj()); | ||
|
||
jint error = Java_AndroidNetworkLibrary_verifyServerCertificates( | ||
env, static_cast<jobjectArray>(chain_byte_array.obj()), | ||
static_cast<jstring>(host_string.obj()), | ||
static_cast<jstring>(auth_string.obj())); | ||
|
||
switch (error) { | ||
case 0: | ||
return VERIFY_OK; | ||
case 1: | ||
return VERIFY_BAD_HOSTNAME; | ||
case 2: | ||
return VERIFY_NO_TRUSTED_ROOT; | ||
} | ||
return VERIFY_INVOCATION_ERROR; | ||
} | ||
|
||
bool StoreKeyPair(const uint8* public_key, | ||
size_t public_len, | ||
const uint8* private_key, | ||
size_t private_len) { | ||
JNIEnv* env = AttachCurrentThread(); | ||
AutoJObject public_array = AutoJObject::FromLocalRef( | ||
env, ToJavaByteArray(env, public_key, public_len)); | ||
AutoJObject private_array = AutoJObject::FromLocalRef( | ||
env, ToJavaByteArray(env, private_key, private_len)); | ||
jboolean ret = Java_AndroidNetworkLibrary_storeKeyPair(env, | ||
GetApplicationContext(), | ||
static_cast<jbyteArray>(public_array.obj()), | ||
static_cast<jbyteArray>(private_array.obj())); | ||
if (CheckException(env) || !ret) { | ||
LOG(WARNING) << "Call to Java_AndroidNetworkLibrary_storeKeyPair failed"; | ||
return false; | ||
} | ||
return true; | ||
} | ||
|
||
bool GetMimeTypeFromExtension(const std::string& extension, | ||
std::string* result) { | ||
JNIEnv* env = AttachCurrentThread(); | ||
|
||
AutoJObject extension_string = AutoJObject::FromLocalRef( | ||
env, ConvertUTF8ToJavaString(env, extension)); | ||
AutoJObject ret = AutoJObject::FromLocalRef( | ||
env, Java_AndroidNetworkLibrary_getMimeTypeFromExtension( | ||
env, static_cast<jstring>(extension_string.obj()))); | ||
|
||
if (CheckException(env) || !ret.obj()) { | ||
LOG(WARNING) << "Call to getMimeTypeFromExtension failed"; | ||
return false; | ||
} | ||
*result = ConvertJavaStringToUTF8(env, static_cast<jstring>(ret.obj())); | ||
return true; | ||
} | ||
|
||
bool RegisterNetworkLibrary(JNIEnv* env) { | ||
return RegisterNativesImpl(env); | ||
} | ||
|
||
} // namespace android | ||
} // namespace net | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
// Copyright (c) 2010 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef NET_ANDROID_NETWORK_LIBRARY_H_ | ||
#define NET_ANDROID_NETWORK_LIBRARY_H_ | ||
#pragma once | ||
|
||
#include <jni.h> | ||
|
||
#include <string> | ||
#include <vector> | ||
|
||
#include "base/basictypes.h" | ||
|
||
namespace net { | ||
namespace android { | ||
|
||
enum VerifyResult { | ||
// Certificate verification was successful. | ||
VERIFY_OK, | ||
// Certificate domain name doesn't match host name. | ||
VERIFY_BAD_HOSTNAME, | ||
// Certificate verification was failed. There is no detail error information | ||
// given by Android API. | ||
VERIFY_NO_TRUSTED_ROOT, | ||
// Error occurs when invoke JNI methods. | ||
VERIFY_INVOCATION_ERROR, | ||
}; | ||
|
||
// |cert_chain| is DER encoded chain of certificates, with the server's own | ||
// certificate listed first. | ||
// |hostname| is validated against the supplied cert. |auth_type| is as per | ||
// the Java X509Certificate.checkServerTrusted method. | ||
|
||
VerifyResult VerifyX509CertChain(const std::vector<std::string>& cert_chain, | ||
const std::string& hostname, | ||
const std::string& auth_type); | ||
|
||
// Helper for the <keygen> handler. Passes the DER-encoded key pair via | ||
// JNI to the Credentials store. | ||
bool StoreKeyPair(const uint8* public_key, | ||
size_t public_len, | ||
const uint8* private_key, | ||
size_t private_len); | ||
|
||
// Get the mime type (if any) that is associated with the file extension. | ||
// Returns true if a corresponding mime type exists. | ||
bool GetMimeTypeFromExtension(const std::string& extension, | ||
std::string* result); | ||
|
||
// Register JNI methods | ||
bool RegisterNetworkLibrary(JNIEnv* env); | ||
|
||
} // namespace android | ||
} // namespace net | ||
|
||
#endif // NET_ANDROID_NETWORK_LIBRARY_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
// Copyright (c) 2010 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "net/base/openssl_private_key_store.h" | ||
|
||
#include <openssl/evp.h> | ||
|
||
#include "base/logging.h" | ||
#include "base/memory/singleton.h" | ||
#include "crypto/openssl_util.h" | ||
#include "net/android/network_library.h" | ||
|
||
namespace net { | ||
|
||
namespace { | ||
|
||
class OpenSSLKeyStoreAndroid : public OpenSSLPrivateKeyStore { | ||
public: | ||
~OpenSSLKeyStoreAndroid() {} | ||
|
||
// TODO(joth): Use the |url| to help identify this key to the user. | ||
// Currently Android has no UI to list these stored private keys (and no | ||
// API to associate a name with them), so this is a non-issue. | ||
virtual bool StorePrivateKey(const GURL& url, EVP_PKEY* pkey) { | ||
uint8* public_key = NULL; | ||
int public_len = i2d_PublicKey(pkey, &public_key); | ||
uint8* private_key = NULL; | ||
int private_len = i2d_PrivateKey(pkey, &private_key); | ||
|
||
bool ret = false; | ||
if (public_len && private_len) { | ||
ret = net::android::StoreKeyPair(public_key, public_len, private_key, | ||
private_len); | ||
} | ||
LOG_IF(ERROR, !ret) << "StorePrivateKey failed. pub len = " << public_len | ||
<< " priv len = " << private_len; | ||
OPENSSL_free(public_key); | ||
OPENSSL_free(private_key); | ||
return ret; | ||
} | ||
|
||
virtual EVP_PKEY* FetchPrivateKey(EVP_PKEY* pkey) { | ||
// TODO(joth): Implement when client authentication is required. | ||
NOTIMPLEMENTED(); | ||
return NULL; | ||
} | ||
|
||
static OpenSSLKeyStoreAndroid* GetInstance(); | ||
|
||
private: | ||
OpenSSLKeyStoreAndroid() {} | ||
friend struct DefaultSingletonTraits<OpenSSLKeyStoreAndroid>; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(OpenSSLKeyStoreAndroid); | ||
}; | ||
|
||
} // namespace | ||
|
||
// static | ||
OpenSSLKeyStoreAndroid* OpenSSLKeyStoreAndroid::GetInstance() { | ||
return Singleton<OpenSSLKeyStoreAndroid>::get(); | ||
} | ||
|
||
#if 0 | ||
// TODO(MERGE): Conflict with openssl_memory_private_key_store.cc | ||
OpenSSLPrivateKeyStore* OpenSSLPrivateKeyStore::GetInstance() { | ||
return OpenSSLKeyStoreAndroid::GetInstance(); | ||
} | ||
#endif | ||
} // namespace net |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
// Copyright (c) 2010 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "net/base/x509_certificate.h" | ||
|
||
#include "base/logging.h" | ||
#include "net/android/network_library.h" | ||
#include "net/base/cert_status_flags.h" | ||
#include "net/base/cert_verify_result.h" | ||
#include "net/base/net_errors.h" | ||
|
||
namespace net { | ||
|
||
int X509Certificate::VerifyInternal(const std::string& hostname, | ||
int flags, | ||
CertVerifyResult* verify_result) const { | ||
if (!VerifyNameMatch(hostname)) | ||
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | ||
|
||
std::vector<std::string> cert_bytes; | ||
GetChainDEREncodedBytes(&cert_bytes); | ||
|
||
// TODO(joth): Fetch the authentication type from SSL rather than hardcode. | ||
android::VerifyResult result = | ||
android::VerifyX509CertChain(cert_bytes, hostname, "RSA"); | ||
switch (result) { | ||
case android::VERIFY_OK: | ||
return OK; | ||
case android::VERIFY_BAD_HOSTNAME: | ||
verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | ||
break; | ||
case android::VERIFY_NO_TRUSTED_ROOT: | ||
verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; | ||
break; | ||
case android::VERIFY_INVOCATION_ERROR: | ||
default: | ||
verify_result->cert_status |= ERR_CERT_INVALID; | ||
break; | ||
} | ||
return MapCertStatusToNetError(verify_result->cert_status); | ||
} | ||
|
||
void X509Certificate::GetChainDEREncodedBytes( | ||
std::vector<std::string>* chain_bytes) const { | ||
OSCertHandles cert_handles(intermediate_ca_certs_); | ||
// Make sure the peer's own cert is the first in the chain, if it's not | ||
// already there. | ||
if (cert_handles.empty()) | ||
cert_handles.insert(cert_handles.begin(), cert_handle_); | ||
|
||
chain_bytes->reserve(cert_handles.size()); | ||
for (OSCertHandles::const_iterator it = cert_handles.begin(); | ||
it != cert_handles.end(); ++it) { | ||
DERCache der_cache = {0}; | ||
GetDERAndCacheIfNeeded(*it, &der_cache); | ||
std::string cert_bytes ( | ||
reinterpret_cast<const char*>(der_cache.data), der_cache.data_length); | ||
chain_bytes->push_back(cert_bytes); | ||
} | ||
} | ||
|
||
} // namespace net |