1 /* 2 * Copyright 2004 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 // Handling of certificates and keypairs for SSLStreamAdapter's peer mode. 12 #if HAVE_CONFIG_H 13 #include "config.h" 14 #endif // HAVE_CONFIG_H 15 16 #include "webrtc/base/sslidentity.h" 17 18 #include <string> 19 20 #include "webrtc/base/base64.h" 21 #include "webrtc/base/logging.h" 22 #include "webrtc/base/sslconfig.h" 23 24 #if SSL_USE_SCHANNEL 25 26 #elif SSL_USE_OPENSSL // !SSL_USE_SCHANNEL 27 28 #include "webrtc/base/opensslidentity.h" 29 30 #elif SSL_USE_NSS // !SSL_USE_SCHANNEL && !SSL_USE_OPENSSL 31 32 #include "webrtc/base/nssidentity.h" 33 34 #endif // SSL_USE_SCHANNEL 35 36 namespace rtc { 37 38 const char kPemTypeCertificate[] = "CERTIFICATE"; 39 const char kPemTypeRsaPrivateKey[] = "RSA PRIVATE KEY"; 40 41 bool SSLIdentity::PemToDer(const std::string& pem_type, 42 const std::string& pem_string, 43 std::string* der) { 44 // Find the inner body. We need this to fulfill the contract of 45 // returning pem_length. 46 size_t header = pem_string.find("-----BEGIN " + pem_type + "-----"); 47 if (header == std::string::npos) 48 return false; 49 50 size_t body = pem_string.find("\n", header); 51 if (body == std::string::npos) 52 return false; 53 54 size_t trailer = pem_string.find("-----END " + pem_type + "-----"); 55 if (trailer == std::string::npos) 56 return false; 57 58 std::string inner = pem_string.substr(body + 1, trailer - (body + 1)); 59 60 *der = Base64::Decode(inner, Base64::DO_PARSE_WHITE | 61 Base64::DO_PAD_ANY | 62 Base64::DO_TERM_BUFFER); 63 return true; 64 } 65 66 std::string SSLIdentity::DerToPem(const std::string& pem_type, 67 const unsigned char* data, 68 size_t length) { 69 std::stringstream result; 70 71 result << "-----BEGIN " << pem_type << "-----\n"; 72 73 std::string b64_encoded; 74 Base64::EncodeFromArray(data, length, &b64_encoded); 75 76 // Divide the Base-64 encoded data into 64-character chunks, as per 77 // 4.3.2.4 of RFC 1421. 78 static const size_t kChunkSize = 64; 79 size_t chunks = (b64_encoded.size() + (kChunkSize - 1)) / kChunkSize; 80 for (size_t i = 0, chunk_offset = 0; i < chunks; 81 ++i, chunk_offset += kChunkSize) { 82 result << b64_encoded.substr(chunk_offset, kChunkSize); 83 result << "\n"; 84 } 85 86 result << "-----END " << pem_type << "-----\n"; 87 88 return result.str(); 89 } 90 91 #if SSL_USE_SCHANNEL 92 93 SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 94 return NULL; 95 } 96 97 SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 98 return NULL; 99 } 100 101 SSLIdentity* GenerateForTest(const SSLIdentityParams& params) { 102 return NULL; 103 } 104 105 SSLIdentity* SSLIdentity::FromPEMStrings(const std::string& private_key, 106 const std::string& certificate) { 107 return NULL; 108 } 109 110 #elif SSL_USE_OPENSSL // !SSL_USE_SCHANNEL 111 112 SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 113 return OpenSSLCertificate::FromPEMString(pem_string); 114 } 115 116 SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 117 return OpenSSLIdentity::Generate(common_name); 118 } 119 120 SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) { 121 return OpenSSLIdentity::GenerateForTest(params); 122 } 123 124 SSLIdentity* SSLIdentity::FromPEMStrings(const std::string& private_key, 125 const std::string& certificate) { 126 return OpenSSLIdentity::FromPEMStrings(private_key, certificate); 127 } 128 129 #elif SSL_USE_NSS // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL 130 131 SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 132 return NSSCertificate::FromPEMString(pem_string); 133 } 134 135 SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 136 return NSSIdentity::Generate(common_name); 137 } 138 139 SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) { 140 return NSSIdentity::GenerateForTest(params); 141 } 142 143 SSLIdentity* SSLIdentity::FromPEMStrings(const std::string& private_key, 144 const std::string& certificate) { 145 return NSSIdentity::FromPEMStrings(private_key, certificate); 146 } 147 148 #else // !SSL_USE_OPENSSL && !SSL_USE_SCHANNEL && !SSL_USE_NSS 149 150 #error "No SSL implementation" 151 152 #endif // SSL_USE_SCHANNEL 153 154 } // namespace rtc 155