File: nss_temp_certs_cache_chromeos_unittest.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (131 lines) | stat: -rw-r--r-- 5,059 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/net/nss_temp_certs_cache_chromeos.h"

#include <cert.h>
#include <certdb.h>
#include <secitem.h>

#include <string>
#include <vector>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "net/cert/x509_certificate.h"
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/pki/cert_errors.h"
#include "third_party/boringssl/src/pki/input.h"
#include "third_party/boringssl/src/pki/parse_certificate.h"
#include "third_party/boringssl/src/pki/pem.h"

namespace network {

namespace {

class NSSTempCertsCacheChromeOSTest : public testing::Test {
 public:
  NSSTempCertsCacheChromeOSTest() = default;

  NSSTempCertsCacheChromeOSTest(const NSSTempCertsCacheChromeOSTest&) = delete;
  NSSTempCertsCacheChromeOSTest& operator=(
      const NSSTempCertsCacheChromeOSTest&) = delete;

  ~NSSTempCertsCacheChromeOSTest() override = default;

 protected:
  // Checks if the certificate stored in |pem_cert_file| can be found in the
  // default NSS certificate database using CERT_FindCertByName.
  // Stores the result in *|out_available|.
  // Note: This funcion uses ASSERT_ macros, so the caller must verify for
  // failures after it returns.
  void CheckIsCertificateAvailable(const base::FilePath& pem_cert_file,
                                   bool* out_available) {
    std::string cert_contents_buffer;
    bssl::der::Input subject;
    ASSERT_NO_FATAL_FAILURE(GetCertificateSubjectDN(
        pem_cert_file, &cert_contents_buffer, &subject));

    SECItem subject_item;
    subject_item.len = subject.size();
    subject_item.data = const_cast<unsigned char*>(subject.data());

    net::ScopedCERTCertificate found_cert(
        CERT_FindCertByName(CERT_GetDefaultCertDB(), &subject_item));
    *out_available = static_cast<bool>(found_cert);
  }

  // Determines the subject DN of the certificate stored in
  // |pem_cert_file|. Stores the result in *|out_subject|.
  // The der::Input data structure contains unowned pointers into the
  // certificate data buffer. The caller must pass a buffer in
  // |cert_contents_buffer| and ensure to only use *|out_subject| while
  // *|cert_contents_buffer| is in scope.
  // Note: This function uses ASSERT_ macros, so the caller must verify for
  // failures after it returns.
  void GetCertificateSubjectDN(const base::FilePath& pem_cert_file,
                               std::string* cert_contents_buffer,
                               bssl::der::Input* out_subject) {
    std::string file_data;
    ASSERT_TRUE(base::ReadFileToString(pem_cert_file, &file_data));

    std::vector<std::string> pem_headers;
    pem_headers.push_back("CERTIFICATE");
    bssl::PEMTokenizer pem_tokenizer(file_data, pem_headers);
    ASSERT_TRUE(pem_tokenizer.GetNext());
    *cert_contents_buffer = pem_tokenizer.data();

    // Parsing the certificate.
    bssl::der::Input tbs_certificate_tlv;
    bssl::der::Input signature_algorithm_tlv;
    bssl::der::BitString signature_value;
    bssl::CertErrors errors;
    ASSERT_TRUE(bssl::ParseCertificate(
        bssl::der::Input(*cert_contents_buffer), &tbs_certificate_tlv,
        &signature_algorithm_tlv, &signature_value, &errors));

    bssl::ParsedTbsCertificate tbs;
    bssl::ParseCertificateOptions options;
    options.allow_invalid_serial_numbers = true;
    ASSERT_TRUE(
        bssl::ParseTbsCertificate(tbs_certificate_tlv, options, &tbs, nullptr));
    *out_subject = tbs.subject_tlv;
  }
};

// Checks that a certificate made available through the
// NSSTempCertsCacheChromeOS can be found by NSS. We specifically check for
// lookup through the CERT_FindCertByName function, as this is what is used in
// client certificate matching (see MatchClientCertificateIssuers in
// net/third_party/nss/ssl/cmpcert.cc). Additionally, checks that the
// certificate is not available after the NSSTempCertsCacheChromeOS goes out of
// scope.
TEST_F(NSSTempCertsCacheChromeOSTest, CertMadeAvailable) {
  base::FilePath cert_file_path =
      net::GetTestCertsDirectory().AppendASCII("client_1_ca.pem");
  {
    std::string x509_authority_cert;
    ASSERT_TRUE(base::ReadFileToString(cert_file_path, &x509_authority_cert));
    net::CertificateList x509_authority_certs =
        net::X509Certificate::CreateCertificateListFromBytes(
            base::as_byte_span(x509_authority_cert),
            net::X509Certificate::Format::FORMAT_AUTO);

    NSSTempCertsCacheChromeOS cache(x509_authority_certs);

    bool cert_available = false;
    ASSERT_NO_FATAL_FAILURE(
        CheckIsCertificateAvailable(cert_file_path, &cert_available));
    EXPECT_TRUE(cert_available);
  }

  bool cert_available_no_cache = true;
  ASSERT_NO_FATAL_FAILURE(
      CheckIsCertificateAvailable(cert_file_path, &cert_available_no_cache));
  EXPECT_FALSE(cert_available_no_cache);
}

}  // namespace
}  // namespace network