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 36namespace rtc { 37 38const char kPemTypeCertificate[] = "CERTIFICATE"; 39const char kPemTypeRsaPrivateKey[] = "RSA PRIVATE KEY"; 40 41bool 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 66std::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 93SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 94 return NULL; 95} 96 97SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 98 return NULL; 99} 100 101SSLIdentity* GenerateForTest(const SSLIdentityParams& params) { 102 return NULL; 103} 104 105SSLIdentity* 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 112SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 113 return OpenSSLCertificate::FromPEMString(pem_string); 114} 115 116SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 117 return OpenSSLIdentity::Generate(common_name); 118} 119 120SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) { 121 return OpenSSLIdentity::GenerateForTest(params); 122} 123 124SSLIdentity* 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 131SSLCertificate* SSLCertificate::FromPEMString(const std::string& pem_string) { 132 return NSSCertificate::FromPEMString(pem_string); 133} 134 135SSLIdentity* SSLIdentity::Generate(const std::string& common_name) { 136 return NSSIdentity::Generate(common_name); 137} 138 139SSLIdentity* SSLIdentity::GenerateForTest(const SSLIdentityParams& params) { 140 return NSSIdentity::GenerateForTest(params); 141} 142 143SSLIdentity* 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