diff options
Diffstat (limited to 'net/base')
-rw-r--r-- | net/base/x509_certificate.cc | 97 | ||||
-rw-r--r-- | net/base/x509_certificate_unittest.cc | 15 |
2 files changed, 62 insertions, 50 deletions
diff --git a/net/base/x509_certificate.cc b/net/base/x509_certificate.cc index 9c69b4a..df62ec8 100644 --- a/net/base/x509_certificate.cc +++ b/net/base/x509_certificate.cc @@ -204,8 +204,56 @@ CertificateList X509Certificate::CreateCertificateListFromBytes( const char* data, int length, int format) { OSCertHandles certificates; + // Check to see if it is in a PEM-encoded form. This check is performed + // first, as both OS X and NSS will both try to convert if they detect + // PEM encoding, except they don't do it consistently between the two. + base::StringPiece data_string(data, length); + std::vector<std::string> pem_headers; + + // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally + // valid PEM block header for any format. + pem_headers.push_back(kCertificateHeader); + if (format & FORMAT_PKCS7) + pem_headers.push_back(kPKCS7Header); + + PEMTokenizer pem_tok(data_string, pem_headers); + while (pem_tok.GetNext()) { + std::string decoded(pem_tok.data()); + + OSCertHandle handle = NULL; + if (format & FORMAT_PEM_CERT_SEQUENCE) + handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size()); + if (handle != NULL) { + // Parsed a DER encoded certificate. All PEM blocks that follow must + // also be DER encoded certificates wrapped inside of PEM blocks. + format = FORMAT_PEM_CERT_SEQUENCE; + certificates.push_back(handle); + continue; + } + + // If the first block failed to parse as a DER certificate, and + // formats other than PEM are acceptable, check to see if the decoded + // data is one of the accepted formats. + if (format & ~FORMAT_PEM_CERT_SEQUENCE) { + for (size_t i = 0; certificates.empty() && + i < arraysize(kFormatDecodePriority); ++i) { + if (format & kFormatDecodePriority[i]) { + certificates = CreateOSCertHandlesFromBytes(decoded.c_str(), + decoded.size(), kFormatDecodePriority[i]); + } + } + } + + // Stop parsing after the first block for any format but a sequence of + // PEM-encoded DER certificates. The case of FORMAT_PEM_CERT_SEQUENCE + // is handled above, and continues processing until a certificate fails + // to parse. + break; + } + // Try each of the formats, in order of parse preference, to see if |data| - // contains the binary representation of a Format. + // contains the binary representation of a Format, if it failed to parse + // as a PEM certificate/chain. for (size_t i = 0; certificates.empty() && i < arraysize(kFormatDecodePriority); ++i) { if (format & kFormatDecodePriority[i]) @@ -213,53 +261,6 @@ CertificateList X509Certificate::CreateCertificateListFromBytes( kFormatDecodePriority[i]); } - // No certs were read. Check to see if it is in a PEM-encoded form. - if (certificates.empty()) { - base::StringPiece data_string(data, length); - std::vector<std::string> pem_headers; - - // To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally - // valid PEM block header for any format. - pem_headers.push_back(kCertificateHeader); - if (format & FORMAT_PKCS7) - pem_headers.push_back(kPKCS7Header); - - PEMTokenizer pem_tok(data_string, pem_headers); - while (pem_tok.GetNext()) { - std::string decoded(pem_tok.data()); - - OSCertHandle handle = NULL; - if (format & FORMAT_PEM_CERT_SEQUENCE) - handle = CreateOSCertHandleFromBytes(decoded.c_str(), decoded.size()); - if (handle != NULL) { - // Parsed a DER encoded certificate. All PEM blocks that follow must - // also be DER encoded certificates wrapped inside of PEM blocks. - format = FORMAT_PEM_CERT_SEQUENCE; - certificates.push_back(handle); - continue; - } - - // If the first block failed to parse as a DER certificate, and - // formats other than PEM are acceptable, check to see if the decoded - // data is one of the accepted formats. - if (format & ~FORMAT_PEM_CERT_SEQUENCE) { - for (size_t i = 0; certificates.empty() && - i < arraysize(kFormatDecodePriority); ++i) { - if (format & kFormatDecodePriority[i]) { - certificates = CreateOSCertHandlesFromBytes(decoded.c_str(), - decoded.size(), kFormatDecodePriority[i]); - } - } - } - - // Stop parsing after the first block for any format but a sequence of - // PEM-encoded DER certificates. The case of FORMAT_PEM_CERT_SEQUENCE - // is handled above, and continues processing until a certificate fails - // to parse. - break; - } - } - CertificateList results; // No certificates parsed. if (certificates.empty()) diff --git a/net/base/x509_certificate_unittest.cc b/net/base/x509_certificate_unittest.cc index ad0b5c6..e1319d7 100644 --- a/net/base/x509_certificate_unittest.cc +++ b/net/base/x509_certificate_unittest.cc @@ -703,8 +703,19 @@ TEST_P(X509CertificateParseTest, CanParseFormat) { kGoogleParseValidFrom, kGoogleParseValidTo); size_t i; - for (i = 0; i < arraysize(test_data_.chain_fingerprints) && - i < certs.size() && test_data_.chain_fingerprints[i] != NULL; ++i) { + for (i = 0; i < arraysize(test_data_.chain_fingerprints); ++i) { + if (test_data_.chain_fingerprints[i] == NULL) { + // No more test certificates expected - make sure no more were + // returned before marking this test a success. + EXPECT_EQ(i, certs.size()); + break; + } + + // A cert is expected - make sure that one was parsed. + ASSERT_LT(i, certs.size()); + + // Compare the parsed certificate with the expected certificate, by + // comparing fingerprints. const X509Certificate* cert = certs[i]; const SHA1Fingerprint& actual_fingerprint = cert->fingerprint(); unsigned char* expected_fingerprint = test_data_.chain_fingerprints[i]; |