File: binary_integrity_analyzer_mac.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 (135 lines) | stat: -rw-r--r-- 6,409 bytes parent folder | download | duplicates (7)
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
132
133
134
135
// Copyright 2015 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/safe_browsing/incident_reporting/binary_integrity_analyzer_mac.h"

#include <stddef.h>

#include <memory>
#include <utility>

#include "base/apple/bundle_locations.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "chrome/browser/safe_browsing/incident_reporting/binary_integrity_incident.h"
#include "chrome/browser/safe_browsing/incident_reporting/incident_receiver.h"
#include "chrome/browser/safe_browsing/signature_evaluator_mac.h"
#include "components/safe_browsing/core/common/proto/csd.pb.h"

namespace safe_browsing {

namespace {

void VerifyBinaryIntegrityHelper(IncidentReceiver* incident_receiver,
                                 const base::FilePath& path,
                                 const std::string& requirement) {
  MacSignatureEvaluator evaluator(path, requirement);
  if (!evaluator.Initialize()) {
    LOG(ERROR) << "Could not initialize mac signature evaluator";
    return;
  }

  std::unique_ptr<ClientIncidentReport_IncidentData_BinaryIntegrityIncident>
      incident(new ClientIncidentReport_IncidentData_BinaryIntegrityIncident());
  if (!evaluator.PerformEvaluation(incident.get())) {
    incident_receiver->AddIncidentForProcess(
        std::make_unique<BinaryIntegrityIncident>(std::move(incident)));
  } else {
    // Clear past incidents involving this bundle if the signature is
    // now valid.
    ClearBinaryIntegrityForFile(incident_receiver, path.BaseName().value());
  }
}

}  // namespace

std::vector<PathAndRequirement> GetCriticalPathsAndRequirements() {
  std::vector<PathAndRequirement> critical_binaries;
  // This requirement describes a developer ID signed application, with Google's
  // team identifier, and the com.Google.Chrome[.channel] identifier.
  //
  // This is the default requirement that codesign normally uses, from 12.0.1
  // Security-60157.40.30.0.1/OSX/libsecurity_codesigning/lib/drmaker.cpp
  // Security::CodeSigning::DRMaker::appleAnchor, in the isDeveloperIDSignature
  // case. The precise requirement here is tailored to Google's Developer ID
  // Application signing certificate by including the correct team ID,
  // DEVELOPER_ID_LEAF_TEAM_ID (EQHXZ8M8AV). It forms the trust chain from Apple
  // to Google's Developer ID Application signing certificate.
  //
  // 1.2.840.113635.100.6 = {iso(1) member-body(2) us(840) apple(113635)
  // appleDataSecurity(100) appleCertificateExtensions(6)}. The .1 that may
  // follow is appleCertificateExtensionCodeSigning(1).
  //
  // DEVELOPER_ID_LEAF_APPLICATION_OID (1.2.840.113635.100.6.1.13) must be
  // present on the leaf certificate (the one issued to the developer). This
  // attribute is defined in the Apple Developer ID Certification Practice
  // Statement document,
  // https://www.apple.com/certificateauthority/Apple_Developer_ID_CPS. It
  // identifies Developer ID Application signing certificates. drmaker.cpp
  // refers to this OID as caspianLeafMarker and devIdLeafMarkerOID, with the
  // comment "Caspian leaf certificate marker". Based on context and other
  // appearances in the Security project's source code, Caspian is a code name
  // for Developer ID.
  //
  // DEVELOPER_ID_INTERMEDIATE_OID (1.2.840.113635.100.6.2.6) must be present on
  // the intermediate certificate. There's no published definition of this
  // attribute, but it is present on the Developer ID Certification Authority
  // certificate. Among Apple-published intermediate certificates at
  // https://www.apple.com/certificateauthority/, the attribute is unique to
  // Developer ID. drmaker.cpp refers to this OID as caspianSdkMarker and
  // devIdSdkMarkerOID, with the comment "Caspian intermediate marker". Even
  // absent a published definition, this is reasonable assurance that the
  // attribute is being used correctly (and, in fact, following codesign's lead
  // is strong evidence).
  //
  // The difference between "anchor apple" and "anchor apple generic" is that
  // "anchor apple" indicates that something was signed by Apple as Apple's own
  // product, where "anchor apple generic" indicates that something was signed
  // by Apple but is not necessarily Apple's own product. 12.0.1
  // Security-60157.40.30.0.1/OSX/libsecurity_codesigning/lib/reqinterp.cpp
  // Security::CodeSigning::Requirement::Interpreter::eval, cases opAppleAnchor
  // and opAppleGenericAnchor.
  //
  // Some code ends up signed with a requirement that "certificate
  // leaf[field.1.2.840.113635.100.6.1.9]" be present. Per the Apple Worldwide
  // Developer Relations Certification Practice Statement document,
  // https://www.apple.com/certificateauthority/WWDR_CPS, this indicates Mac App
  // Store Application signing. As this is out of scope for Chrome, it does not
  // appear in the requirement string here.
#define DEVELOPER_ID_INTERMEDIATE_OID "field.1.2.840.113635.100.6.2.6"
#define DEVELOPER_ID_LEAF_APPLICATION_OID "field.1.2.840.113635.100.6.1.13"
#define DEVELOPER_ID_LEAF_TEAM_ID "EQHXZ8M8AV"
  // clang-format off
  std::string requirement =
      "(identifier \"com.google.Chrome\" or "
      "identifier \"com.google.Chrome.beta\" or "
      "identifier \"com.google.Chrome.dev\" or "
      "identifier \"com.google.Chrome.canary\") and "
      "anchor apple generic and "
      "certificate 1[" DEVELOPER_ID_INTERMEDIATE_OID "] and "
      "certificate leaf[" DEVELOPER_ID_LEAF_APPLICATION_OID "] and "
      "certificate leaf[subject.OU] = " DEVELOPER_ID_LEAF_TEAM_ID;
  // clang-format on

  critical_binaries.push_back(
      PathAndRequirement(base::apple::OuterBundlePath(), requirement));
  critical_binaries.push_back(
      PathAndRequirement(base::apple::FrameworkBundlePath(), requirement));
  return critical_binaries;
}

void VerifyBinaryIntegrityForTesting(IncidentReceiver* incident_receiver,
                                     const base::FilePath& path,
                                     const std::string& requirement) {
  VerifyBinaryIntegrityHelper(incident_receiver, path, requirement);
}

void VerifyBinaryIntegrity(
    std::unique_ptr<IncidentReceiver> incident_receiver) {
  for (const auto& p : GetCriticalPathsAndRequirements()) {
    VerifyBinaryIntegrityHelper(incident_receiver.get(), p.path, p.requirement);
  }
}

}  // namespace