blob: 79259374c5920a0bc199a261e949b0b7a9695ed0 [file] [log] [blame]
Bruno Rocha7f9aea22011-09-12 14:31:24 -07001// Copyright (c) 2011 The Chromium OS 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#ifndef CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
6#define CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_
7
8#include <string>
9
10#include <base/basictypes.h>
11#include <curl/curl.h>
12#include <gtest/gtest_prod.h> // for FRIEND_TEST
13#include <openssl/ssl.h>
14
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080015#include "update_engine/system_state.h"
Bruno Rocha7f9aea22011-09-12 14:31:24 -070016
17namespace chromeos_update_engine {
18
19// Wrapper for openssl operations with the certificates.
20class OpenSSLWrapper {
21 public:
22 OpenSSLWrapper() {}
23 virtual ~OpenSSLWrapper() {}
24
25 // Takes an openssl X509_STORE_CTX, extracts the corresponding certificate
26 // from it and calculates its fingerprint (SHA256 digest). Returns true on
27 // success and false otherwise.
28 //
29 // |x509_ctx| is the pointer to the openssl object that holds the certificate.
30 // |out_depth| is the depth of the current certificate, in the certificate
31 // chain.
32 // |out_digest_length| is the length of the generated digest.
33 // |out_digest| is the byte array where the digest itself will be written.
34 // It should be big enough to hold a SHA1 digest (e.g. EVP_MAX_MD_SIZE).
35 virtual bool GetCertificateDigest(X509_STORE_CTX* x509_ctx,
36 int* out_depth,
37 unsigned int* out_digest_length,
38 unsigned char* out_digest) const;
39
40 private:
41 DISALLOW_COPY_AND_ASSIGN(OpenSSLWrapper);
42};
43
44// Responsible for checking whether update server certificates change, and
45// reporting to UMA when this happens. Since all state information is persisted,
46// and openssl forces us to use a static callback with no data pointer, this
47// class is entirely static.
48class CertificateChecker {
49 public:
50 // These values are used to generate the keys of files persisted via prefs.
51 // This means that changing these will cause loss of information on metrics
52 // reporting, during the transition.
53 enum ServerToCheck {
54 kUpdate = 0,
55 kDownload = 1,
56 kNone = 2 // This needs to be the last element. Changing its value is ok.
57 };
58
59 CertificateChecker() {}
60 virtual ~CertificateChecker() {}
61
62 // This callback is called by libcurl just before the initialization of an
63 // SSL connection after having processed all other SSL related options. Used
64 // to check if server certificates change. |ptr| is expected to be a
65 // pointer to a ServerToCheck.
66 static CURLcode ProcessSSLContext(CURL* curl_handle, SSL_CTX* ssl_ctx,
67 void* ptr);
68
69 // Flushes to UMA any certificate-related report that was persisted.
70 static void FlushReport();
71
72 // Setters.
Jay Srinivasan6f6ea002012-12-14 11:26:28 -080073 static void set_system_state(SystemState* system_state) {
74 system_state_ = system_state;
Bruno Rocha7f9aea22011-09-12 14:31:24 -070075 }
76
77 static void set_openssl_wrapper(OpenSSLWrapper* openssl_wrapper) {
78 openssl_wrapper_ = openssl_wrapper;
79 }
80
81 private:
82 FRIEND_TEST(CertificateCheckerTest, NewCertificate);
83 FRIEND_TEST(CertificateCheckerTest, SameCertificate);
84 FRIEND_TEST(CertificateCheckerTest, ChangedCertificate);
85 FRIEND_TEST(CertificateCheckerTest, FailedCertificate);
86 FRIEND_TEST(CertificateCheckerTest, FlushReport);
87 FRIEND_TEST(CertificateCheckerTest, FlushNothingToReport);
88
89 // These callbacks are called by openssl after initial SSL verification. They
90 // are used to perform any additional security verification on the connection,
91 // but we use them here to get hold of the server certificate, in order to
92 // determine if it has changed since the last connection. Since openssl forces
93 // us to do this statically, we define two different callbacks for the two
94 // different official update servers, and only assign the correspondent one.
95 // The assigned callback is then called once per each certificate on the
96 // server and returns 1 for success and 0 for failure.
97 static int VerifySSLCallbackUpdateCheck(int preverify_ok,
98 X509_STORE_CTX* x509_ctx);
99 static int VerifySSLCallbackDownload(int preverify_ok,
100 X509_STORE_CTX* x509_ctx);
101
102 // Checks if server certificate for |server_to_check|, stored in |x509_ctx|,
103 // has changed since last connection to that same server. This is called by
104 // one of the two callbacks defined above. If certificate fails to check or
105 // changes, a report is generated and persisted, to be later sent by
106 // FlushReport. Returns true on success and false otherwise.
107 static bool CheckCertificateChange(ServerToCheck server_to_check,
108 int preverify_ok,
109 X509_STORE_CTX* x509_ctx);
110
Jay Srinivasan6f6ea002012-12-14 11:26:28 -0800111 // Global system context.
112 static SystemState* system_state_;
Bruno Rocha7f9aea22011-09-12 14:31:24 -0700113
114 // The wrapper for openssl operations.
115 static OpenSSLWrapper* openssl_wrapper_;
116
117 DISALLOW_COPY_AND_ASSIGN(CertificateChecker);
118};
119
120} // namespace chromeos_update_engine
121
122#endif // CHROMEOS_PLATFORM_UPDATE_ENGINE_CERTIFICATE_CHECKER_H_