xref: /aosp_15_r20/external/openscreen/cast/receiver/channel/static_credentials.cc (revision 3f982cf4871df8771c9d4abe6e9a6f8d829b2736)
1*3f982cf4SFabien Sanglard // Copyright 2020 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard 
5*3f982cf4SFabien Sanglard #include "cast/receiver/channel/static_credentials.h"
6*3f982cf4SFabien Sanglard 
7*3f982cf4SFabien Sanglard #include <openssl/mem.h>
8*3f982cf4SFabien Sanglard #include <openssl/pem.h>
9*3f982cf4SFabien Sanglard 
10*3f982cf4SFabien Sanglard #include <cstdio>
11*3f982cf4SFabien Sanglard #include <memory>
12*3f982cf4SFabien Sanglard #include <string>
13*3f982cf4SFabien Sanglard #include <utility>
14*3f982cf4SFabien Sanglard #include <vector>
15*3f982cf4SFabien Sanglard 
16*3f982cf4SFabien Sanglard #include "platform/base/tls_credentials.h"
17*3f982cf4SFabien Sanglard #include "util/crypto/certificate_utils.h"
18*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
19*3f982cf4SFabien Sanglard 
20*3f982cf4SFabien Sanglard namespace openscreen {
21*3f982cf4SFabien Sanglard namespace cast {
22*3f982cf4SFabien Sanglard namespace {
23*3f982cf4SFabien Sanglard using FileUniquePtr = std::unique_ptr<FILE, decltype(&fclose)>;
24*3f982cf4SFabien Sanglard 
25*3f982cf4SFabien Sanglard constexpr char kGeneratedRootCertificateName[] =
26*3f982cf4SFabien Sanglard     "generated_root_cast_receiver.crt";
27*3f982cf4SFabien Sanglard constexpr char kGeneratedPrivateKey[] = "generated_root_cast_receiver.key";
28*3f982cf4SFabien Sanglard constexpr int kThreeDaysInSeconds = 3 * 24 * 60 * 60;
29*3f982cf4SFabien Sanglard constexpr auto kCertificateDuration = std::chrono::seconds(kThreeDaysInSeconds);
30*3f982cf4SFabien Sanglard 
GenerateCredentials(std::string device_certificate_id,EVP_PKEY * root_key,X509 * root_cert)31*3f982cf4SFabien Sanglard ErrorOr<GeneratedCredentials> GenerateCredentials(
32*3f982cf4SFabien Sanglard     std::string device_certificate_id,
33*3f982cf4SFabien Sanglard     EVP_PKEY* root_key,
34*3f982cf4SFabien Sanglard     X509* root_cert) {
35*3f982cf4SFabien Sanglard   OSP_CHECK(root_key);
36*3f982cf4SFabien Sanglard   OSP_CHECK(root_cert);
37*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> intermediate_key = GenerateRsaKeyPair();
38*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> device_key = GenerateRsaKeyPair();
39*3f982cf4SFabien Sanglard   OSP_CHECK(intermediate_key);
40*3f982cf4SFabien Sanglard   OSP_CHECK(device_key);
41*3f982cf4SFabien Sanglard 
42*3f982cf4SFabien Sanglard   ErrorOr<bssl::UniquePtr<X509>> intermediate_cert_or_error =
43*3f982cf4SFabien Sanglard       CreateSelfSignedX509Certificate(
44*3f982cf4SFabien Sanglard           "Cast Intermediate", kCertificateDuration, *intermediate_key,
45*3f982cf4SFabien Sanglard           GetWallTimeSinceUnixEpoch(), true, root_cert, root_key);
46*3f982cf4SFabien Sanglard   OSP_CHECK(intermediate_cert_or_error);
47*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> intermediate_cert =
48*3f982cf4SFabien Sanglard       std::move(intermediate_cert_or_error.value());
49*3f982cf4SFabien Sanglard 
50*3f982cf4SFabien Sanglard   ErrorOr<bssl::UniquePtr<X509>> device_cert_or_error =
51*3f982cf4SFabien Sanglard       CreateSelfSignedX509Certificate(
52*3f982cf4SFabien Sanglard           device_certificate_id, kCertificateDuration, *device_key,
53*3f982cf4SFabien Sanglard           GetWallTimeSinceUnixEpoch(), false, intermediate_cert.get(),
54*3f982cf4SFabien Sanglard           intermediate_key.get());
55*3f982cf4SFabien Sanglard   OSP_CHECK(device_cert_or_error);
56*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> device_cert = std::move(device_cert_or_error.value());
57*3f982cf4SFabien Sanglard 
58*3f982cf4SFabien Sanglard   // Device cert chain plumbing + serialization.
59*3f982cf4SFabien Sanglard   DeviceCredentials device_creds;
60*3f982cf4SFabien Sanglard   device_creds.private_key = std::move(device_key);
61*3f982cf4SFabien Sanglard 
62*3f982cf4SFabien Sanglard   int cert_length = i2d_X509(device_cert.get(), nullptr);
63*3f982cf4SFabien Sanglard   std::string cert_serial(cert_length, 0);
64*3f982cf4SFabien Sanglard   uint8_t* out = reinterpret_cast<uint8_t*>(&cert_serial[0]);
65*3f982cf4SFabien Sanglard   i2d_X509(device_cert.get(), &out);
66*3f982cf4SFabien Sanglard   device_creds.certs.emplace_back(std::move(cert_serial));
67*3f982cf4SFabien Sanglard 
68*3f982cf4SFabien Sanglard   cert_length = i2d_X509(intermediate_cert.get(), nullptr);
69*3f982cf4SFabien Sanglard   cert_serial.resize(cert_length);
70*3f982cf4SFabien Sanglard   out = reinterpret_cast<uint8_t*>(&cert_serial[0]);
71*3f982cf4SFabien Sanglard   i2d_X509(intermediate_cert.get(), &out);
72*3f982cf4SFabien Sanglard   device_creds.certs.emplace_back(std::move(cert_serial));
73*3f982cf4SFabien Sanglard 
74*3f982cf4SFabien Sanglard   cert_length = i2d_X509(root_cert, nullptr);
75*3f982cf4SFabien Sanglard   std::vector<uint8_t> trust_anchor_der(cert_length);
76*3f982cf4SFabien Sanglard   out = &trust_anchor_der[0];
77*3f982cf4SFabien Sanglard   i2d_X509(root_cert, &out);
78*3f982cf4SFabien Sanglard 
79*3f982cf4SFabien Sanglard   // TLS key pair + certificate generation.
80*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> tls_key = GenerateRsaKeyPair();
81*3f982cf4SFabien Sanglard   OSP_CHECK_EQ(EVP_PKEY_id(tls_key.get()), EVP_PKEY_RSA);
82*3f982cf4SFabien Sanglard   ErrorOr<bssl::UniquePtr<X509>> tls_cert_or_error =
83*3f982cf4SFabien Sanglard       CreateSelfSignedX509Certificate("Test Device TLS", kCertificateDuration,
84*3f982cf4SFabien Sanglard                                       *tls_key, GetWallTimeSinceUnixEpoch());
85*3f982cf4SFabien Sanglard   OSP_CHECK(tls_cert_or_error);
86*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> tls_cert = std::move(tls_cert_or_error.value());
87*3f982cf4SFabien Sanglard 
88*3f982cf4SFabien Sanglard   // TLS private key serialization.
89*3f982cf4SFabien Sanglard   RSA* rsa_key = EVP_PKEY_get0_RSA(tls_key.get());
90*3f982cf4SFabien Sanglard   size_t pkey_len = 0;
91*3f982cf4SFabien Sanglard   uint8_t* pkey_bytes = nullptr;
92*3f982cf4SFabien Sanglard   OSP_CHECK(RSA_private_key_to_bytes(&pkey_bytes, &pkey_len, rsa_key));
93*3f982cf4SFabien Sanglard   OSP_CHECK_GT(pkey_len, 0u);
94*3f982cf4SFabien Sanglard   std::vector<uint8_t> tls_key_serial(pkey_bytes, pkey_bytes + pkey_len);
95*3f982cf4SFabien Sanglard   OPENSSL_free(pkey_bytes);
96*3f982cf4SFabien Sanglard 
97*3f982cf4SFabien Sanglard   // TLS public key serialization.
98*3f982cf4SFabien Sanglard   pkey_len = 0;
99*3f982cf4SFabien Sanglard   pkey_bytes = nullptr;
100*3f982cf4SFabien Sanglard   OSP_CHECK(RSA_public_key_to_bytes(&pkey_bytes, &pkey_len, rsa_key));
101*3f982cf4SFabien Sanglard   OSP_CHECK_GT(pkey_len, 0u);
102*3f982cf4SFabien Sanglard   std::vector<uint8_t> tls_pub_serial(pkey_bytes, pkey_bytes + pkey_len);
103*3f982cf4SFabien Sanglard   OPENSSL_free(pkey_bytes);
104*3f982cf4SFabien Sanglard 
105*3f982cf4SFabien Sanglard   // TLS cert serialization.
106*3f982cf4SFabien Sanglard   cert_length = 0;
107*3f982cf4SFabien Sanglard   cert_length = i2d_X509(tls_cert.get(), nullptr);
108*3f982cf4SFabien Sanglard   OSP_CHECK_GT(cert_length, 0);
109*3f982cf4SFabien Sanglard   std::vector<uint8_t> tls_cert_serial(cert_length);
110*3f982cf4SFabien Sanglard   out = &tls_cert_serial[0];
111*3f982cf4SFabien Sanglard   i2d_X509(tls_cert.get(), &out);
112*3f982cf4SFabien Sanglard 
113*3f982cf4SFabien Sanglard   auto provider = std::make_unique<StaticCredentialsProvider>(
114*3f982cf4SFabien Sanglard       std::move(device_creds), tls_cert_serial);
115*3f982cf4SFabien Sanglard   return GeneratedCredentials{
116*3f982cf4SFabien Sanglard       std::move(provider),
117*3f982cf4SFabien Sanglard       TlsCredentials{std::move(tls_key_serial), std::move(tls_pub_serial),
118*3f982cf4SFabien Sanglard                      std::move(tls_cert_serial)},
119*3f982cf4SFabien Sanglard       std::move(trust_anchor_der)};
120*3f982cf4SFabien Sanglard }
121*3f982cf4SFabien Sanglard 
GeneratePrivateKey()122*3f982cf4SFabien Sanglard bssl::UniquePtr<EVP_PKEY> GeneratePrivateKey() {
123*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> root_key = GenerateRsaKeyPair();
124*3f982cf4SFabien Sanglard   OSP_CHECK(root_key);
125*3f982cf4SFabien Sanglard   return root_key;
126*3f982cf4SFabien Sanglard }
127*3f982cf4SFabien Sanglard 
GenerateRootCert(const EVP_PKEY & root_key)128*3f982cf4SFabien Sanglard bssl::UniquePtr<X509> GenerateRootCert(const EVP_PKEY& root_key) {
129*3f982cf4SFabien Sanglard   ErrorOr<bssl::UniquePtr<X509>> root_cert_or_error =
130*3f982cf4SFabien Sanglard       CreateSelfSignedX509Certificate("Cast Root CA", kCertificateDuration,
131*3f982cf4SFabien Sanglard                                       root_key, GetWallTimeSinceUnixEpoch(),
132*3f982cf4SFabien Sanglard                                       true);
133*3f982cf4SFabien Sanglard   OSP_CHECK(root_cert_or_error);
134*3f982cf4SFabien Sanglard   return std::move(root_cert_or_error.value());
135*3f982cf4SFabien Sanglard }
136*3f982cf4SFabien Sanglard }  // namespace
137*3f982cf4SFabien Sanglard 
138*3f982cf4SFabien Sanglard StaticCredentialsProvider::StaticCredentialsProvider() = default;
StaticCredentialsProvider(DeviceCredentials device_creds,std::vector<uint8_t> tls_cert_der)139*3f982cf4SFabien Sanglard StaticCredentialsProvider::StaticCredentialsProvider(
140*3f982cf4SFabien Sanglard     DeviceCredentials device_creds,
141*3f982cf4SFabien Sanglard     std::vector<uint8_t> tls_cert_der)
142*3f982cf4SFabien Sanglard     : device_creds(std::move(device_creds)),
143*3f982cf4SFabien Sanglard       tls_cert_der(std::move(tls_cert_der)) {}
144*3f982cf4SFabien Sanglard 
145*3f982cf4SFabien Sanglard StaticCredentialsProvider::StaticCredentialsProvider(
146*3f982cf4SFabien Sanglard     StaticCredentialsProvider&&) noexcept = default;
147*3f982cf4SFabien Sanglard StaticCredentialsProvider& StaticCredentialsProvider::operator=(
148*3f982cf4SFabien Sanglard     StaticCredentialsProvider&&) = default;
149*3f982cf4SFabien Sanglard StaticCredentialsProvider::~StaticCredentialsProvider() = default;
150*3f982cf4SFabien Sanglard 
GenerateDeveloperCredentialsToFile()151*3f982cf4SFabien Sanglard void GenerateDeveloperCredentialsToFile() {
152*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> root_key = GeneratePrivateKey();
153*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> root_cert = GenerateRootCert(*root_key);
154*3f982cf4SFabien Sanglard 
155*3f982cf4SFabien Sanglard   FileUniquePtr f(fopen(kGeneratedPrivateKey, "w"), &fclose);
156*3f982cf4SFabien Sanglard   if (PEM_write_PrivateKey(f.get(), root_key.get(), nullptr, nullptr, 0, 0,
157*3f982cf4SFabien Sanglard                            nullptr) != 1) {
158*3f982cf4SFabien Sanglard     OSP_LOG_ERROR << "Failed to write private key, check permissions?";
159*3f982cf4SFabien Sanglard     return;
160*3f982cf4SFabien Sanglard   }
161*3f982cf4SFabien Sanglard   OSP_LOG_INFO << "Generated new private key for session: ./"
162*3f982cf4SFabien Sanglard                << kGeneratedPrivateKey;
163*3f982cf4SFabien Sanglard 
164*3f982cf4SFabien Sanglard   FileUniquePtr cert_file(fopen(kGeneratedRootCertificateName, "w"), &fclose);
165*3f982cf4SFabien Sanglard   if (PEM_write_X509(cert_file.get(), root_cert.get()) != 1) {
166*3f982cf4SFabien Sanglard     OSP_LOG_ERROR << "Failed to write root certificate, check permissions?";
167*3f982cf4SFabien Sanglard     return;
168*3f982cf4SFabien Sanglard   }
169*3f982cf4SFabien Sanglard   OSP_LOG_INFO << "Generated new root certificate for session: ./"
170*3f982cf4SFabien Sanglard                << kGeneratedRootCertificateName;
171*3f982cf4SFabien Sanglard }
172*3f982cf4SFabien Sanglard 
GenerateCredentialsForTesting(const std::string & device_certificate_id)173*3f982cf4SFabien Sanglard ErrorOr<GeneratedCredentials> GenerateCredentialsForTesting(
174*3f982cf4SFabien Sanglard     const std::string& device_certificate_id) {
175*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> root_key = GeneratePrivateKey();
176*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> root_cert = GenerateRootCert(*root_key);
177*3f982cf4SFabien Sanglard   return GenerateCredentials(device_certificate_id, root_key.get(),
178*3f982cf4SFabien Sanglard                              root_cert.get());
179*3f982cf4SFabien Sanglard }
180*3f982cf4SFabien Sanglard 
GenerateCredentials(const std::string & device_certificate_id,const std::string & private_key_path,const std::string & server_certificate_path)181*3f982cf4SFabien Sanglard ErrorOr<GeneratedCredentials> GenerateCredentials(
182*3f982cf4SFabien Sanglard     const std::string& device_certificate_id,
183*3f982cf4SFabien Sanglard     const std::string& private_key_path,
184*3f982cf4SFabien Sanglard     const std::string& server_certificate_path) {
185*3f982cf4SFabien Sanglard   if (private_key_path.empty() || server_certificate_path.empty()) {
186*3f982cf4SFabien Sanglard     return Error(Error::Code::kParameterInvalid,
187*3f982cf4SFabien Sanglard                  "Missing either private key or server certificate");
188*3f982cf4SFabien Sanglard   }
189*3f982cf4SFabien Sanglard 
190*3f982cf4SFabien Sanglard   FileUniquePtr key_file(fopen(private_key_path.c_str(), "r"), &fclose);
191*3f982cf4SFabien Sanglard   if (!key_file) {
192*3f982cf4SFabien Sanglard     return Error(Error::Code::kParameterInvalid,
193*3f982cf4SFabien Sanglard                  "Missing private key file path");
194*3f982cf4SFabien Sanglard   }
195*3f982cf4SFabien Sanglard   bssl::UniquePtr<EVP_PKEY> root_key =
196*3f982cf4SFabien Sanglard       bssl::UniquePtr<EVP_PKEY>(PEM_read_PrivateKey(
197*3f982cf4SFabien Sanglard           key_file.get(), nullptr /* x */, nullptr /* cb */, nullptr /* u */));
198*3f982cf4SFabien Sanglard 
199*3f982cf4SFabien Sanglard   FileUniquePtr cert_file(fopen(server_certificate_path.c_str(), "r"), &fclose);
200*3f982cf4SFabien Sanglard   if (!cert_file) {
201*3f982cf4SFabien Sanglard     return Error(Error::Code::kParameterInvalid,
202*3f982cf4SFabien Sanglard                  "Missing server certificate file path");
203*3f982cf4SFabien Sanglard   }
204*3f982cf4SFabien Sanglard   bssl::UniquePtr<X509> root_cert = bssl::UniquePtr<X509>(PEM_read_X509(
205*3f982cf4SFabien Sanglard       cert_file.get(), nullptr /* x */, nullptr /* cb */, nullptr /* u */));
206*3f982cf4SFabien Sanglard 
207*3f982cf4SFabien Sanglard   return GenerateCredentials(device_certificate_id, root_key.get(),
208*3f982cf4SFabien Sanglard                              root_cert.get());
209*3f982cf4SFabien Sanglard }
210*3f982cf4SFabien Sanglard 
211*3f982cf4SFabien Sanglard }  // namespace cast
212*3f982cf4SFabien Sanglard }  // namespace openscreen
213