Home | History | Annotate | Download | only in base
      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