Home | History | Annotate | Download | only in cert
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "net/cert/cert_verify_proc_android.h"
      6 
      7 #include <string>
      8 #include <vector>
      9 
     10 #include "base/logging.h"
     11 #include "net/android/cert_verify_result_android.h"
     12 #include "net/android/network_library.h"
     13 #include "net/base/net_errors.h"
     14 #include "net/cert/cert_status_flags.h"
     15 #include "net/cert/cert_verify_result.h"
     16 #include "net/cert/x509_certificate.h"
     17 
     18 namespace net {
     19 
     20 namespace {
     21 
     22 // Returns true if the certificate verification call was successful (regardless
     23 // of its result), i.e. if |verify_result| was set. Otherwise returns false.
     24 bool VerifyFromAndroidTrustManager(const std::vector<std::string>& cert_bytes,
     25                                    CertVerifyResult* verify_result) {
     26   // TODO(joth): Fetch the authentication type from SSL rather than hardcode.
     27   android::CertVerifyResultAndroid android_result =
     28       android::VerifyX509CertChain(cert_bytes, "RSA");
     29   switch (android_result) {
     30     case android::VERIFY_FAILED:
     31       return false;
     32     case android::VERIFY_OK:
     33       break;
     34     case android::VERIFY_NO_TRUSTED_ROOT:
     35       verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
     36       break;
     37     case android::VERIFY_EXPIRED:
     38     case android::VERIFY_NOT_YET_VALID:
     39       verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
     40       break;
     41     case android::VERIFY_UNABLE_TO_PARSE:
     42       verify_result->cert_status |= CERT_STATUS_INVALID;
     43       break;
     44     case android::VERIFY_INCORRECT_KEY_USAGE:
     45       verify_result->cert_status |= CERT_STATUS_INVALID;
     46       break;
     47     default:
     48       NOTREACHED();
     49       verify_result->cert_status |= CERT_STATUS_INVALID;
     50       break;
     51   }
     52   return true;
     53 }
     54 
     55 bool GetChainDEREncodedBytes(X509Certificate* cert,
     56                              std::vector<std::string>* chain_bytes) {
     57   X509Certificate::OSCertHandle cert_handle = cert->os_cert_handle();
     58   X509Certificate::OSCertHandles cert_handles =
     59       cert->GetIntermediateCertificates();
     60 
     61   // Make sure the peer's own cert is the first in the chain, if it's not
     62   // already there.
     63   if (cert_handles.empty() || cert_handles[0] != cert_handle)
     64     cert_handles.insert(cert_handles.begin(), cert_handle);
     65 
     66   chain_bytes->reserve(cert_handles.size());
     67   for (X509Certificate::OSCertHandles::const_iterator it =
     68        cert_handles.begin(); it != cert_handles.end(); ++it) {
     69     std::string cert_bytes;
     70     if(!X509Certificate::GetDEREncoded(*it, &cert_bytes))
     71       return false;
     72     chain_bytes->push_back(cert_bytes);
     73   }
     74   return true;
     75 }
     76 
     77 }  // namespace
     78 
     79 CertVerifyProcAndroid::CertVerifyProcAndroid() {}
     80 
     81 CertVerifyProcAndroid::~CertVerifyProcAndroid() {}
     82 
     83 bool CertVerifyProcAndroid::SupportsAdditionalTrustAnchors() const {
     84   return false;
     85 }
     86 
     87 int CertVerifyProcAndroid::VerifyInternal(
     88     X509Certificate* cert,
     89     const std::string& hostname,
     90     int flags,
     91     CRLSet* crl_set,
     92     const CertificateList& additional_trust_anchors,
     93     CertVerifyResult* verify_result) {
     94   if (!cert->VerifyNameMatch(hostname,
     95                              &verify_result->common_name_fallback_used)) {
     96     verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
     97   }
     98 
     99   std::vector<std::string> cert_bytes;
    100   if (!GetChainDEREncodedBytes(cert, &cert_bytes))
    101     return ERR_CERT_INVALID;
    102   if (!VerifyFromAndroidTrustManager(cert_bytes, verify_result)) {
    103     NOTREACHED();
    104     return ERR_FAILED;
    105   }
    106   if (IsCertStatusError(verify_result->cert_status))
    107     return MapCertStatusToNetError(verify_result->cert_status);
    108 
    109   // TODO(ppi): Implement missing functionality: yielding the constructed trust
    110   // chain, public key hashes of its certificates and |is_issued_by_known_root|
    111   // flag. All of the above require specific support from the platform, missing
    112   // in the Java APIs. See also: http://crbug.com/116838
    113 
    114   // Until the required support is available in the platform, we don't know if
    115   // the trust root at the end of the chain was standard or user-added, so we
    116   // mark all correctly verified certificates as issued by a known root.
    117   verify_result->is_issued_by_known_root = true;
    118 
    119   return OK;
    120 }
    121 
    122 }  // namespace net
    123