tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsskeys.cc (2317B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      5 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "nsskeys.h"
      8 
      9 #include <cstring>
     10 
     11 #include <fstream>
     12 #include <iostream>
     13 #include <string>
     14 
     15 #include "cert.h"
     16 #include "keyhi.h"
     17 #include "nspr.h"
     18 #include "nss.h"
     19 #include "nssb64.h"
     20 #include "pk11pub.h"
     21 
     22 const std::string kPEMBegin = "-----BEGIN ";
     23 const std::string kPEMEnd = "-----END ";
     24 
     25 // Read a PEM file, base64 decode it, and return the result.
     26 static bool ReadPEMFile(const std::string& filename, SECItem* item) {
     27  std::ifstream in(filename);
     28  if (in.bad()) return false;
     29 
     30  char buf[1024];
     31  in.getline(buf, sizeof(buf));
     32  if (in.bad()) return false;
     33 
     34  if (strncmp(buf, kPEMBegin.c_str(), kPEMBegin.size())) return false;
     35 
     36  std::string value = "";
     37  for (;;) {
     38    in.getline(buf, sizeof(buf));
     39    if (in.bad()) return false;
     40 
     41    if (!strncmp(buf, kPEMEnd.c_str(), kPEMEnd.size())) break;
     42 
     43    value += buf;
     44  }
     45 
     46  // Now we have a base64-encoded block.
     47  if (!NSSBase64_DecodeBuffer(nullptr, item, value.c_str(), value.size()))
     48    return false;
     49 
     50  return true;
     51 }
     52 
     53 SECKEYPrivateKey* ReadPrivateKey(const std::string& file) {
     54  SECItem item = {siBuffer, nullptr, 0};
     55 
     56  if (!ReadPEMFile(file, &item)) return nullptr;
     57  SECKEYPrivateKey* privkey = NULL;
     58  PK11SlotInfo* slot = PK11_GetInternalSlot();
     59  SECStatus rv = PK11_ImportDERPrivateKeyInfoAndReturnKey(
     60      slot, &item, nullptr, nullptr, PR_FALSE, PR_FALSE,
     61      KU_KEY_ENCIPHERMENT | KU_DATA_ENCIPHERMENT | KU_DIGITAL_SIGNATURE,
     62      &privkey, nullptr);
     63  PK11_FreeSlot(slot);
     64  SECITEM_FreeItem(&item, PR_FALSE);
     65  if (rv != SECSuccess) {
     66    std::cerr << "Couldn't import key " << PORT_ErrorToString(PORT_GetError())
     67              << "\n";
     68    return nullptr;
     69  }
     70 
     71  return privkey;
     72 }
     73 
     74 CERTCertificate* ReadCertificate(const std::string& file) {
     75  SECItem item = {siBuffer, nullptr, 0};
     76 
     77  if (!ReadPEMFile(file, &item)) return nullptr;
     78 
     79  CERTCertificate* cert = CERT_NewTempCertificate(
     80      CERT_GetDefaultCertDB(), &item, NULL, PR_FALSE, PR_TRUE);
     81  SECITEM_FreeItem(&item, PR_FALSE);
     82  return cert;
     83 }