blob: 11703f2f1bc5a327ed2c595bc0500bb062ba2941 [file] [log] [blame]
Alex Deymoaea4c1c2015-08-19 20:24:43 -07001//
2// Copyright (C) 2011 The Android Open Source Project
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
Bruno Rocha7f9aea22011-09-12 14:31:24 -070016
Gilad Arnoldcf175a02014-07-10 16:48:47 -070017#ifndef UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
18#define UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
Bruno Rocha7f9aea22011-09-12 14:31:24 -070019
Ben Chan05735a12014-09-03 07:48:22 -070020#include <curl/curl.h>
21#include <openssl/ssl.h>
22
Bruno Rocha7f9aea22011-09-12 14:31:24 -070023#include <string>
24
Ben Chan05735a12014-09-03 07:48:22 -070025#include <base/macros.h>
Bruno Rocha7f9aea22011-09-12 14:31:24 -070026#include <gtest/gtest_prod.h> // for FRIEND_TEST
Bruno Rocha7f9aea22011-09-12 14:31:24 -070027
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080028#include "update_engine/system_state.h"
Bruno Rocha7f9aea22011-09-12 14:31:24 -070029
30namespace chromeos_update_engine {
31
32// Wrapper for openssl operations with the certificates.
33class OpenSSLWrapper {
34 public:
35 OpenSSLWrapper() {}
36 virtual ~OpenSSLWrapper() {}
37
38 // Takes an openssl X509_STORE_CTX, extracts the corresponding certificate
39 // from it and calculates its fingerprint (SHA256 digest). Returns true on
40 // success and false otherwise.
41 //
42 // |x509_ctx| is the pointer to the openssl object that holds the certificate.
43 // |out_depth| is the depth of the current certificate, in the certificate
44 // chain.
45 // |out_digest_length| is the length of the generated digest.
46 // |out_digest| is the byte array where the digest itself will be written.
47 // It should be big enough to hold a SHA1 digest (e.g. EVP_MAX_MD_SIZE).
48 virtual bool GetCertificateDigest(X509_STORE_CTX* x509_ctx,
49 int* out_depth,
50 unsigned int* out_digest_length,
Alex Vakulenkof68bbbc2015-02-09 12:53:18 -080051 uint8_t* out_digest) const;
Bruno Rocha7f9aea22011-09-12 14:31:24 -070052
53 private:
54 DISALLOW_COPY_AND_ASSIGN(OpenSSLWrapper);
55};
56
57// Responsible for checking whether update server certificates change, and
58// reporting to UMA when this happens. Since all state information is persisted,
59// and openssl forces us to use a static callback with no data pointer, this
60// class is entirely static.
61class CertificateChecker {
62 public:
63 // These values are used to generate the keys of files persisted via prefs.
64 // This means that changing these will cause loss of information on metrics
65 // reporting, during the transition.
66 enum ServerToCheck {
67 kUpdate = 0,
68 kDownload = 1,
69 kNone = 2 // This needs to be the last element. Changing its value is ok.
70 };
71
72 CertificateChecker() {}
73 virtual ~CertificateChecker() {}
74
75 // This callback is called by libcurl just before the initialization of an
76 // SSL connection after having processed all other SSL related options. Used
77 // to check if server certificates change. |ptr| is expected to be a
78 // pointer to a ServerToCheck.
79 static CURLcode ProcessSSLContext(CURL* curl_handle, SSL_CTX* ssl_ctx,
80 void* ptr);
81
82 // Flushes to UMA any certificate-related report that was persisted.
83 static void FlushReport();
84
85 // Setters.
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080086 static void set_system_state(SystemState* system_state) {
87 system_state_ = system_state;
Bruno Rocha7f9aea22011-09-12 14:31:24 -070088 }
89
90 static void set_openssl_wrapper(OpenSSLWrapper* openssl_wrapper) {
91 openssl_wrapper_ = openssl_wrapper;
92 }
93
94 private:
95 FRIEND_TEST(CertificateCheckerTest, NewCertificate);
96 FRIEND_TEST(CertificateCheckerTest, SameCertificate);
97 FRIEND_TEST(CertificateCheckerTest, ChangedCertificate);
98 FRIEND_TEST(CertificateCheckerTest, FailedCertificate);
99 FRIEND_TEST(CertificateCheckerTest, FlushReport);
100 FRIEND_TEST(CertificateCheckerTest, FlushNothingToReport);
101
102 // These callbacks are called by openssl after initial SSL verification. They
103 // are used to perform any additional security verification on the connection,
104 // but we use them here to get hold of the server certificate, in order to
105 // determine if it has changed since the last connection. Since openssl forces
106 // us to do this statically, we define two different callbacks for the two
107 // different official update servers, and only assign the correspondent one.
108 // The assigned callback is then called once per each certificate on the
109 // server and returns 1 for success and 0 for failure.
110 static int VerifySSLCallbackUpdateCheck(int preverify_ok,
111 X509_STORE_CTX* x509_ctx);
112 static int VerifySSLCallbackDownload(int preverify_ok,
113 X509_STORE_CTX* x509_ctx);
114
115 // Checks if server certificate for |server_to_check|, stored in |x509_ctx|,
116 // has changed since last connection to that same server. This is called by
117 // one of the two callbacks defined above. If certificate fails to check or
118 // changes, a report is generated and persisted, to be later sent by
119 // FlushReport. Returns true on success and false otherwise.
120 static bool CheckCertificateChange(ServerToCheck server_to_check,
121 int preverify_ok,
122 X509_STORE_CTX* x509_ctx);
123
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800124 // Global system context.
125 static SystemState* system_state_;
Bruno Rocha7f9aea22011-09-12 14:31:24 -0700126
127 // The wrapper for openssl operations.
128 static OpenSSLWrapper* openssl_wrapper_;
129
130 DISALLOW_COPY_AND_ASSIGN(CertificateChecker);
131};
132
133} // namespace chromeos_update_engine
134
Gilad Arnoldcf175a02014-07-10 16:48:47 -0700135#endif // UPDATE_ENGINE_CERTIFICATE_CHECKER_H_