1 /* 2 * Copyright 2013 The WebRTC project authors. All Rights Reserved. 3 * 4 * Use of this source code is governed by a BSD-style license 5 * that can be found in the LICENSE file in the root of the source 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #ifndef PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_ 12 #define PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_ 13 14 #include <string> 15 #include <utility> 16 17 #include "absl/types/optional.h" 18 #include "api/peer_connection_interface.h" 19 #include "api/task_queue/task_queue_base.h" 20 #include "api/units/time_delta.h" 21 #include "rtc_base/rtc_certificate.h" 22 #include "rtc_base/rtc_certificate_generator.h" 23 24 // RSA with mod size 1024, pub exp 0x10001. 25 static const rtc::RTCCertificatePEM kRsaPems[] = { 26 rtc::RTCCertificatePEM( 27 "-----BEGIN RSA PRIVATE KEY-----\n" 28 "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMYRkbhmI7kVA/rM\n" 29 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" 30 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" 31 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAECgYAvgOs4FJcgvp+TuREx7YtiYVsH\n" 32 "mwQPTum2z/8VzWGwR8BBHBvIpVe1MbD/Y4seyI2aco/7UaisatSgJhsU46/9Y4fq\n" 33 "2TwXH9QANf4at4d9n/R6rzwpAJOpgwZgKvdQjkfrKTtgLV+/dawvpxUYkRH4JZM1\n" 34 "CVGukMfKNrSVH4Ap4QJBAOJmGV1ASPnB4r4nc99at7JuIJmd7fmuVUwUgYi4XgaR\n" 35 "WhScBsgYwZ/JoywdyZJgnbcrTDuVcWG56B3vXbhdpMsCQQDf9zeJrjnPZ3Cqm79y\n" 36 "kdqANep0uwZciiNiWxsQrCHztywOvbFhdp8iYVFG9EK8DMY41Y5TxUwsHD+67zao\n" 37 "ZNqJAkEA1suLUP/GvL8IwuRneQd2tWDqqRQ/Td3qq03hP7e77XtF/buya3Ghclo5\n" 38 "54czUR89QyVfJEC6278nzA7n2h1uVQJAcG6mztNL6ja/dKZjYZye2CY44QjSlLo0\n" 39 "MTgTSjdfg/28fFn2Jjtqf9Pi/X+50LWI/RcYMC2no606wRk9kyOuIQJBAK6VSAim\n" 40 "1pOEjsYQn0X5KEIrz1G3bfCbB848Ime3U2/FWlCHMr6ch8kCZ5d1WUeJD3LbwMNG\n" 41 "UCXiYxSsu20QNVw=\n" 42 "-----END RSA PRIVATE KEY-----\n", 43 "-----BEGIN CERTIFICATE-----\n" 44 "MIIBmTCCAQKgAwIBAgIEbzBSAjANBgkqhkiG9w0BAQsFADARMQ8wDQYDVQQDEwZX\n" 45 "ZWJSVEMwHhcNMTQwMTAyMTgyNDQ3WhcNMTQwMjAxMTgyNDQ3WjARMQ8wDQYDVQQD\n" 46 "EwZXZWJSVEMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMYRkbhmI7kVA/rM\n" 47 "czsZ+6JDhDvnkF+vn6yCAGuRPV03zuRqZtDy4N4to7PZu9PjqrRl7nDMXrG3YG9y\n" 48 "rlIAZ72KjcKKFAJxQyAKLCIdawKRyp8RdK3LEySWEZb0AV58IadqPZDTNHHRX8dz\n" 49 "5aTSMsbbkZ+C/OzTnbiMqLL/vg6jAgMBAAEwDQYJKoZIhvcNAQELBQADgYEAUflI\n" 50 "VUe5Krqf5RVa5C3u/UTAOAUJBiDS3VANTCLBxjuMsvqOG0WvaYWP3HYPgrz0jXK2\n" 51 "LJE/mGw3MyFHEqi81jh95J+ypl6xKW6Rm8jKLR87gUvCaVYn/Z4/P3AqcQTB7wOv\n" 52 "UD0A8qfhfDM+LK6rPAnCsVN0NRDY3jvd6rzix9M=\n" 53 "-----END CERTIFICATE-----\n"), 54 rtc::RTCCertificatePEM( 55 "-----BEGIN RSA PRIVATE KEY-----\n" 56 "MIICXQIBAAKBgQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgj\n" 57 "Bl8CPZMvDh9EwB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQ\n" 58 "sOR/qPvviJx5I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQAB\n" 59 "AoGARni9eY8/hv+SX+I+05EdXt6MQXNUbQ+cSykBNCfVccLzIFEWUQMT2IHqwl6X\n" 60 "ShIXcq7/n1QzOAEiuzixauM3YHg4xZ1Um2Ha9a7ig5Xg4v6b43bmMkNE6LkoAtYs\n" 61 "qnQdfMh442b1liDud6IMb1Qk0amt3fSrgRMc547TZQVx4QECQQDxUeDm94r3p4ng\n" 62 "5rCLLC1K5/6HSTZsh7jatKPlz7GfP/IZlYV7iE5784/n0wRiCjZOS7hQRy/8m2Gp\n" 63 "pf4aZq+DAkEA6+np4d36FYikydvUrupLT3FkdRHGn/v83qOll/VmeNh+L1xMZlIP\n" 64 "tM26hAXCcQb7O5+J9y3cx2CAQsBS11ZXZQJAfGgTo76WG9p5UEJdXUInD2jOZPwv\n" 65 "XIATolxh6kXKcijLLLlSmT7KB0inNYIpzkkpee+7U1d/u6B3FriGaSHq9QJBAM/J\n" 66 "ICnDdLCgwNvWVraVQC3BpwSB2pswvCFwq7py94V60XFvbw80Ogc6qIv98qvQxVlX\n" 67 "hJIEgA/PjEi+0ng94Q0CQQDm8XSDby35gmjO+6eRmJtAjtB7nguLvrPXM6CPXRmD\n" 68 "sRoBocpHw6j9UdzZ6qYG0FkdXZghezXFY58ro2BYYRR3\n" 69 "-----END RSA PRIVATE KEY-----\n", 70 "-----BEGIN CERTIFICATE-----\n" 71 "MIICWDCCAcGgAwIBAgIJALgDjxMbBOhbMA0GCSqGSIb3DQEBCwUAMEUxCzAJBgNV\n" 72 "BAYTAkFVMRMwEQYDVQQIDApTb21lLVN0YXRlMSEwHwYDVQQKDBhJbnRlcm5ldCBX\n" 73 "aWRnaXRzIFB0eSBMdGQwHhcNMTUxMTEzMjIzMjEzWhcNMTYxMTEyMjIzMjEzWjBF\n" 74 "MQswCQYDVQQGEwJBVTETMBEGA1UECAwKU29tZS1TdGF0ZTEhMB8GA1UECgwYSW50\n" 75 "ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" 76 "gQDeYqlyJ1wuiMsi905e3X81/WA/G3ym50PIDZBVtSwZi7JVQPgjBl8CPZMvDh9E\n" 77 "wB4Ji9ytA8dZZbQ4WbJWPr73zPpJSCvQqz6sOXSlenBRi72acNaQsOR/qPvviJx5\n" 78 "I6Hqo4qemfnjZhAW85a5BpgrAwKgMLIQTHCTLWwVSyrDrwIDAQABo1AwTjAdBgNV\n" 79 "HQ4EFgQUx2tbJdlcSTCepn09UdYORXKuSTAwHwYDVR0jBBgwFoAUx2tbJdlcSTCe\n" 80 "pn09UdYORXKuSTAwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOBgQAmp9Id\n" 81 "E716gHMqeBG4S2FCgVFCr0a0ugkaneQAN/c2L9CbMemEN9W6jvucUIVOtYd90dDW\n" 82 "lXuowWmT/JctPe3D2qt4yvYW3puECHk2tVQmrJOZiZiTRtWm6HxkmoUYHYp/DtaS\n" 83 "1Xe29gSTnZtI5sQCrGMzk3SGRSSs7ejLKiVDBQ==\n" 84 "-----END CERTIFICATE-----\n")}; 85 86 // ECDSA with EC_NIST_P256. 87 // These PEM strings were created by generating an identity with 88 // `SSLIdentity::Create` and invoking `identity->PrivateKeyToPEMString()`, 89 // `identity->PublicKeyToPEMString()` and 90 // `identity->certificate().ToPEMString()`. 91 static const rtc::RTCCertificatePEM kEcdsaPems[] = { 92 rtc::RTCCertificatePEM( 93 "-----BEGIN PRIVATE KEY-----\n" 94 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQg+qaRsR5uHtqG689M\n" 95 "A3PHSJNeVpyi5wUKCft62h0UWy+hRANCAAS5Mjc85q9fVq4ln+zOPlaEC/Rzj5Pb\n" 96 "MVZtf1x/8k2KsbmyZoAMDX2yer/atEuXmItMe3yd6/DXnvboU//D3Lyt\n" 97 "-----END PRIVATE KEY-----\n", 98 "-----BEGIN CERTIFICATE-----\n" 99 "MIIBFTCBu6ADAgECAgkA30tGY5XG7oowCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n" 100 "dGVzdDMwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n" 101 "DAV0ZXN0MzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABLkyNzzmr19WriWf7M4+\n" 102 "VoQL9HOPk9sxVm1/XH/yTYqxubJmgAwNfbJ6v9q0S5eYi0x7fJ3r8Nee9uhT/8Pc\n" 103 "vK0wCgYIKoZIzj0EAwIDSQAwRgIhAIIc3+CqfkZ9lLwTj1PvUtt3KhnqF2kD0War\n" 104 "cCoTBbCxAiEAyp9Cn4vo2ZBhRIVDKyoxmwak8Z0PAVhJAQaWCgoY2D4=\n" 105 "-----END CERTIFICATE-----\n"), 106 rtc::RTCCertificatePEM( 107 "-----BEGIN PRIVATE KEY-----\n" 108 "MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQghL/G4JRYnuDNbQuh\n" 109 "LqkytcE39Alsq6FItDVFgOesfCmhRANCAATd53FjPLyVUcwYguEPbSJM03fP6Rx5\n" 110 "GY1dEZ00+ZykjJI83VfDAyvmpRuGahNtBH0hc+7xkDCbeo6TM0tN35xr\n" 111 "-----END PRIVATE KEY-----\n", 112 "-----BEGIN CERTIFICATE-----\n" 113 "MIIBFDCBu6ADAgECAgkArZYdXMyJ5rswCgYIKoZIzj0EAwIwEDEOMAwGA1UEAwwF\n" 114 "dGVzdDQwHhcNMTYwNTA5MDkxODA4WhcNMTYwNjA5MDkxODA4WjAQMQ4wDAYDVQQD\n" 115 "DAV0ZXN0NDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABN3ncWM8vJVRzBiC4Q9t\n" 116 "IkzTd8/pHHkZjV0RnTT5nKSMkjzdV8MDK+alG4ZqE20EfSFz7vGQMJt6jpMzS03f\n" 117 "nGswCgYIKoZIzj0EAwIDSAAwRQIgb/LBc8OtsC5lEDyjCP6M9xt5mwzUNrQBOFWZ\n" 118 "1fE/g68CIQD7uoFfbiq6dTp8ZwzbwQ8jJf08KjriamqA9OW/4268Dw==\n" 119 "-----END CERTIFICATE-----\n")}; 120 121 class FakeRTCCertificateGenerator 122 : public rtc::RTCCertificateGeneratorInterface { 123 public: FakeRTCCertificateGenerator()124 FakeRTCCertificateGenerator() : should_fail_(false), should_wait_(false) {} 125 set_should_fail(bool should_fail)126 void set_should_fail(bool should_fail) { should_fail_ = should_fail; } 127 128 // If set to true, stalls the generation of the fake certificate until it is 129 // set to false. set_should_wait(bool should_wait)130 void set_should_wait(bool should_wait) { should_wait_ = should_wait; } 131 use_original_key()132 void use_original_key() { key_index_ = 0; } use_alternate_key()133 void use_alternate_key() { key_index_ = 1; } 134 generated_certificates()135 int generated_certificates() { return generated_certificates_; } generated_failures()136 int generated_failures() { return generated_failures_; } 137 GenerateCertificateAsync(const rtc::KeyParams & key_params,const absl::optional<uint64_t> & expires_ms,Callback callback)138 void GenerateCertificateAsync(const rtc::KeyParams& key_params, 139 const absl::optional<uint64_t>& expires_ms, 140 Callback callback) override { 141 // The certificates are created from constant PEM strings and use its coded 142 // expiration time, we do not support modifying it. 143 RTC_DCHECK(!expires_ms); 144 145 // Only supports RSA-1024-0x10001 and ECDSA-P256. 146 if (key_params.type() == rtc::KT_RSA) { 147 RTC_DCHECK_EQ(key_params.rsa_params().mod_size, 1024); 148 RTC_DCHECK_EQ(key_params.rsa_params().pub_exp, 0x10001); 149 } else { 150 RTC_DCHECK_EQ(key_params.type(), rtc::KT_ECDSA); 151 RTC_DCHECK_EQ(key_params.ec_curve(), rtc::EC_NIST_P256); 152 } 153 rtc::KeyType key_type = key_params.type(); 154 webrtc::TaskQueueBase::Current()->PostTask( 155 [this, key_type, callback = std::move(callback)]() mutable { 156 GenerateCertificate(key_type, std::move(callback)); 157 }); 158 } 159 GenerateCertificate()160 static rtc::scoped_refptr<rtc::RTCCertificate> GenerateCertificate() { 161 switch (rtc::KT_DEFAULT) { 162 case rtc::KT_RSA: 163 return rtc::RTCCertificate::FromPEM(kRsaPems[0]); 164 case rtc::KT_ECDSA: 165 return rtc::RTCCertificate::FromPEM(kEcdsaPems[0]); 166 default: 167 RTC_DCHECK_NOTREACHED(); 168 return nullptr; 169 } 170 } 171 172 private: get_pem(const rtc::KeyType & key_type)173 const rtc::RTCCertificatePEM& get_pem(const rtc::KeyType& key_type) const { 174 switch (key_type) { 175 case rtc::KT_RSA: 176 return kRsaPems[key_index_]; 177 case rtc::KT_ECDSA: 178 return kEcdsaPems[key_index_]; 179 default: 180 RTC_DCHECK_NOTREACHED(); 181 return kEcdsaPems[key_index_]; 182 } 183 } get_key(const rtc::KeyType & key_type)184 const std::string& get_key(const rtc::KeyType& key_type) const { 185 return get_pem(key_type).private_key(); 186 } get_cert(const rtc::KeyType & key_type)187 const std::string& get_cert(const rtc::KeyType& key_type) const { 188 return get_pem(key_type).certificate(); 189 } 190 GenerateCertificate(rtc::KeyType key_type,Callback callback)191 void GenerateCertificate(rtc::KeyType key_type, Callback callback) { 192 // If the certificate generation should be stalled, re-post this same 193 // message to the queue with a small delay so as to wait in a loop until 194 // set_should_wait(false) is called. 195 if (should_wait_) { 196 webrtc::TaskQueueBase::Current()->PostDelayedTask( 197 [this, key_type, callback = std::move(callback)]() mutable { 198 GenerateCertificate(key_type, std::move(callback)); 199 }, 200 webrtc::TimeDelta::Millis(1)); 201 return; 202 } 203 if (should_fail_) { 204 ++generated_failures_; 205 std::move(callback)(nullptr); 206 } else { 207 rtc::scoped_refptr<rtc::RTCCertificate> certificate = 208 rtc::RTCCertificate::FromPEM(get_pem(key_type)); 209 RTC_DCHECK(certificate); 210 ++generated_certificates_; 211 std::move(callback)(std::move(certificate)); 212 } 213 } 214 215 bool should_fail_; 216 bool should_wait_; 217 int key_index_ = 0; 218 int generated_certificates_ = 0; 219 int generated_failures_ = 0; 220 }; 221 222 #endif // PC_TEST_FAKE_RTC_CERTIFICATE_GENERATOR_H_ 223