Skip to content

Instantly share code, notes, and snippets.

@trueroad
Last active November 29, 2020 09:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trueroad/8c55674d25be82c15977d9999096e0fb to your computer and use it in GitHub Desktop.
Save trueroad/8c55674d25be82c15977d9999096e0fb to your computer and use it in GitHub Desktop.
GnuTLS PKCS#7 class
BIN = pkcs7_sign
OBJS = pkcs7_sign.o tr_gnutls_pkcs7.o tr_gnutls_pkcs12.o \
tr_gnutls_x509_crt.o tr_gnutls_x509_privkey.o tr_gnutls_privkey.o \
tr_gnutls_init.o tr_util_suppress_echo_back.o
WGET = wget
all: $(BIN)
.PHONY: all clean
CXXFLAGS_STDCXX = -std=c++11
CXXFLAGS_GNUCXX = -std=gnu++11
LDLIBS += -lgnutls
DEPS = $(OBJS:.o=.d)
CPPFLAGS += -MMD -MP -MF $(@:.o=.d) -MT $@
-include $(DEPS)
$(BIN): $(OBJS)
$(LINK.cc) $^ $(LOADLIBES) $(LDLIBS) -o $@
tr_util_suppress_echo_back.o: tr_util_suppress_echo_back.cc
$(COMPILE.cc) $(CXXFLAGS_GNUCXX) $(OUTPUT_OPTION) $<
%.o: %.cc
$(COMPILE.cc) $(CXXFLAGS_STDCXX) $(OUTPUT_OPTION) $<
clean:
$(RM) *~ $(OBJS) $(DEPS)
pkcs7_sign.o: cmdlineparse.hh
cmdlineparse.hh:
$(WGET) https://github.com/trueroad/cmdlineparse/raw/master/cmdlineparse.hh
//
// GnuTLS PKCS#7 class
// https://gist.github.com/trueroad/8c55674d25be82c15977d9999096e0fb
//
// pkcs7_sign.cc:
// PKCS#7 signing sample for GnuTLS PKCS#7 class
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include <iostream>
#include <stdexcept>
#include "cmdlineparse.hh"
#include "tr_gnutls_init.hh"
#include "tr_gnutls_pkcs12.hh"
#include "tr_gnutls_pkcs7.hh"
#include "tr_gnutls_privkey.hh"
#include "tr_gnutls_x509_crt.hh"
#include "tr_gnutls_x509_privkey.hh"
#include "tr_util_binary.hh"
#include "tr_util_suppress_echo_back.hh"
int main (int argc, char *argv[])
{
cmdlineparse::parser cmd;
cmd.set_version_string (
"PKCS#7 signing sample for GnuTLS PKCS#7 class\n"
"Copyright (C) 2019 Masamichi Hosoda. All rights reserved.\n"
);
cmd.add_default ();
std::string filename_tobe;
cmd.add_string (0, "in", &filename_tobe, "",
" (in) File to be signed",
"FILENAME", "Input/output filenames");
std::string filename_sig;
cmd.add_string (0, "out", &filename_sig, "",
" (out) PKCS#7 signed-data file",
"FILENAME.p7s", "Input/output filenames");
std::string filename_cert;
cmd.add_string (0, "cert", &filename_cert, "",
" (in) Certificate with key",
"FILENAME.{pfx|p12}", "Input/output filenames");
std::string format_out;
cmd.add_string (0, "outform", &format_out, "der",
" Output PKCS#7 signed-data file format",
"{der|pem}", "Format options");
std::string format_cert;
cmd.add_string (0, "certform", &format_cert, "der",
" Input certificate with key format",
"{der|pem}", "Format options");
std::string md;
cmd.add_string (0, "md", &md, "sha256",
" Message digest",
"{sha256|sha384|sha512|sha1|ripemd160}",
"Signature options");
bool btime;
cmd.add_flag (0, "time", &btime,
" Add signed time",
"Signature options");
if (!cmd.parse (argc, argv))
return 1;
if (filename_tobe == "" ||
filename_sig == "" ||
filename_cert == "")
{
std::cout << cmd.build_help ();
return 1;
}
std::cout << cmd.get_version_string () << std::endl;
std::cout << "(in) File to be signed : " << filename_tobe << std::endl
<< "(out) PKCS#7 signed-data : " << filename_sig << std::endl
<< "(in) Certificate with key: " << filename_cert << std::endl
<< std::endl
<< "PKCS#7 signed-data format: " << format_out << std::endl
<< std::endl
<< "Message digest: " << md << std::endl
<< "Signed time : " << (btime ? "Add" : "None") << std::endl
<< std::endl
<< "password: " << std::flush;
std::string password;
{
tr_util::suppress_echo_back seb;
std::getline (std::cin, password);
}
std::cout << std::endl;
try
{
tr_gnutls::global_init g;
tr_gnutls::pkcs12 p12;
tr_gnutls::pkcs12::format f12 {tr_gnutls::pkcs12::format::der};
if (format_cert == "der" || format_cert == "DER")
f12 = tr_gnutls::pkcs12::format::der;
else if (format_cert == "pem" || format_cert == "PEM")
f12 = tr_gnutls::pkcs12::format::pem;
p12.import (filename_cert, f12);
p12.verify_mac (password);
p12.simple_parse (password);
auto pkey {p12.get_privkey ()};
auto chain {p12.get_chain ()};
auto extras {p12.get_extras ()};
tr_gnutls::privkey privkey (pkey);
{
tr_gnutls::pkcs7 p7;
for (auto &c: chain)
p7.set_crt (c);
for (auto &e: extras)
p7.set_crt (e);
p7.set_signflag (tr_gnutls::pkcs7::signflag::include_time, btime);
p7.sign (chain[0], privkey,
tr_util::fileload_binary (filename_tobe), md);
tr_gnutls::pkcs7::format f7 {tr_gnutls::pkcs7::format::der};
if (format_out == "der" || format_out == "DER")
f7 = tr_gnutls::pkcs7::format::der;
else if (format_out == "pem" || format_out == "PEM")
f7 = tr_gnutls::pkcs7::format::pem;
tr_util::filesave (filename_sig, p7.pkcs7_export (f7));
}
}
catch (std::runtime_error &e)
{
std::cout << e.what () << std::endl;
return 1;
}
std::cout << "complete" << std::endl;
return 0;
}
//
// GnuTLS gnutls_datum_t class
//
// tr_gnutls_datum_t.hh:
// Header file / implementation
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_DATUM_T_HH
#define INCLUDE_GUARD_TR_GNUTLS_DATUM_T_HH
#include <gnutls/gnutls.h>
#include "tr_util_binary.hh"
namespace tr_gnutls
{
class datum_t
{
public:
datum_t ()
{
data_.data = nullptr;
data_.size = 0;
}
datum_t (const std::string &filename)
{
buff_ = tr_util::fileload_binary (filename);
if (buff_.size ())
{
data_.data = buff_.data ();
data_.size = buff_.size ();
}
else
{
data_.data = nullptr;
data_.size = 0;
}
}
datum_t (std::vector<unsigned char> &&buff)
{
buff_ = buff;
if (buff_.size ())
{
data_.data = buff_.data ();
data_.size = buff_.size ();
}
else
{
data_.data = nullptr;
data_.size = 0;
}
}
~datum_t ()
{
if (buff_.size () == 0 && data_.data && data_.size != 0)
gnutls_free (data_.data);
}
datum_t (const datum_t &) = delete;
datum_t& operator= (const datum_t &) = delete;
datum_t (datum_t &&) = delete;
datum_t& operator= (datum_t &&) = delete;
gnutls_datum_t *assign ()
{
if (buff_.size () == 0 && data_.data == nullptr)
return &data_;
return nullptr;
}
unsigned char* data ()
{
return data_.data;
}
unsigned int size ()
{
return data_.size;
}
operator const gnutls_datum_t* () const
{
return &data_;
}
private:
gnutls_datum_t data_;
std::vector<unsigned char> buff_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_DATUM_T_HH
//
// Global initializer for GnuTLS
//
// tr_gnutls_init.cc:
// Implementation
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_init.hh"
#include <stdexcept>
#include <sstream>
#include <string>
#include <gnutls/gnutls.h>
namespace tr_gnutls
{
global_init::global_init ()
{
int ret = gnutls_global_init ();
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::global_init: gnutls_global_init failed "
<< ret;
throw std::runtime_error (ss.str ().c_str ());
}
}
global_init::~global_init ()
{
gnutls_global_deinit();
}
}
//
// Global initializer for GnuTLS
//
// tr_gnutls_init.hh:
// Header file
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_INIT_HH
#define INCLUDE_GUARD_TR_GNUTLS_INIT_HH
namespace tr_gnutls
{
class global_init
{
public:
global_init ();
~global_init ();
global_init (const global_init &) = delete;
global_init& operator= (const global_init &) = delete;
global_init (global_init &&) = delete;
global_init& operator= (global_init &&) = delete;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_INIT_HH
//
// GnuTLS PKCS#12 class
// https://gist.github.com/trueroad/5dbf9fce1c71e98d17584db72d9bed7c
//
// tr_gnutls_pkcs12.cc:
// Implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_pkcs12.hh"
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <gnutls/gnutls.h>
#include <gnutls/pkcs12.h>
#include <gnutls/x509.h>
#include "tr_gnutls_datum_t.hh"
#include "tr_gnutls_x509_crt.hh"
#include "tr_gnutls_x509_privkey.hh"
namespace tr_gnutls
{
class pkcs12::impl
{
public:
impl ();
~impl ();
impl (const impl &) = delete;
impl& operator= (const impl &) = delete;
impl (impl &&) = default;
impl& operator= (impl &&) = default;
void import (const std::string &filename, format fmt);
void verify_mac (const std::string &password);
void simple_parse (const std::string &password);
x509_privkey get_privkey () const
{
return privkey_;
}
std::vector<x509_crt> get_chain () const
{
return chain_;
}
std::vector<x509_crt> get_extras () const
{
return extras_;
}
operator const gnutls_pkcs12_t () const
{
return pkcs12_;
}
private:
gnutls_pkcs12_t pkcs12_ = nullptr;
x509_privkey privkey_;
std::vector<x509_crt> chain_;
std::vector<x509_crt> extras_;
};
pkcs12::impl::impl ()
{
int ret = gnutls_pkcs12_init (&pkcs12_);
if (ret > 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs12: gnutls_pkcs12_init failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
pkcs12::impl::~impl ()
{
if (pkcs12_)
gnutls_pkcs12_deinit (pkcs12_);
}
void pkcs12::impl::import (const std::string &filename, format fmt)
{
gnutls_x509_crt_fmt_t fmt_gnutls;
switch (fmt)
{
case pkcs12::format::der:
fmt_gnutls = GNUTLS_X509_FMT_DER;
break;
case pkcs12::format::pem:
fmt_gnutls = GNUTLS_X509_FMT_PEM;
break;
default:
throw std::runtime_error ("tr_gnutls::pkcs12: unknown format");
}
tr_gnutls::datum_t data (filename);
int ret = gnutls_pkcs12_import (pkcs12_, data, fmt_gnutls, 0);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs12: gnutls_pkcs12_import filename \""
<< filename << "\" failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
void pkcs12::impl::verify_mac (const std::string &password)
{
int ret = gnutls_pkcs12_verify_mac (pkcs12_, password.c_str ());
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs12: gnutls_pkcs12_verify_mac failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
void pkcs12::impl::simple_parse (const std::string &password)
{
gnutls_x509_crt_t *chain, *extras;
unsigned int chain_size = 0, extras_size = 0;
gnutls_x509_privkey_t pkey;
int ret = gnutls_pkcs12_simple_parse (pkcs12_, password.c_str (), &pkey,
&chain, &chain_size,
&extras, &extras_size,
nullptr, 0);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs12: gnutls_pkcs12_simple_parse failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
privkey_.set (pkey);
for (int i = 0; i < chain_size; ++i)
chain_.push_back (x509_crt (chain[i]));
gnutls_free (chain);
for (int i = 0; i < extras_size; ++i)
extras_.push_back (x509_crt (extras[i]));
gnutls_free (extras);
}
pkcs12::pkcs12 ():
pimpl_ (new pkcs12::impl ())
{
}
pkcs12::~pkcs12 () = default;
pkcs12::pkcs12 (pkcs12 &&) = default;
pkcs12& pkcs12::operator= (pkcs12 &&) = default;
void pkcs12::import (const std::string &filename, format fmt)
{
pimpl_->import (filename, fmt);
}
void pkcs12::verify_mac (const std::string &password)
{
pimpl_->verify_mac (password);
}
void pkcs12::simple_parse (const std::string &password)
{
pimpl_->simple_parse (password);
}
x509_privkey pkcs12::get_privkey () const
{
return pimpl_->get_privkey ();
}
std::vector<x509_crt> pkcs12::get_chain () const
{
return pimpl_->get_chain ();
}
std::vector<x509_crt> pkcs12::get_extras () const
{
return pimpl_->get_extras ();
}
pkcs12::operator const gnutls_pkcs12_t () const
{
return static_cast<const gnutls_pkcs12_t> (*pimpl_);
}
}
//
// GnuTLS PKCS#12 class
// https://gist.github.com/trueroad/5dbf9fce1c71e98d17584db72d9bed7c
//
// tr_gnutls_pkcs12.hh:
// Header file
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_PKCS12_HH
#define INCLUDE_GUARD_TR_GNUTLS_PKCS12_HH
#include <memory>
#include <string>
#include <vector>
struct gnutls_pkcs12_int;
typedef struct gnutls_pkcs12_int *gnutls_pkcs12_t;
namespace tr_gnutls
{
class x509_crt;
class x509_privkey;
class pkcs12
{
public:
enum class format
{
der,
pem,
};
pkcs12 ();
~pkcs12 ();
pkcs12 (const pkcs12 &) = delete;
pkcs12& operator= (const pkcs12 &) = delete;
pkcs12 (pkcs12 &&);
pkcs12& operator= (pkcs12 &&);
void import (const std::string & /* filename */, format fmt = format::der);
void verify_mac (const std::string & /* password */);
void simple_parse (const std::string & /* password */);
x509_privkey get_privkey () const;
std::vector<x509_crt> get_chain () const;
std::vector<x509_crt> get_extras () const;
operator const gnutls_pkcs12_t () const;
private:
class impl;
std::unique_ptr<impl> pimpl_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_PKCS12_HH
//
// GnuTLS PKCS#7 class
// https://gist.github.com/trueroad/8c55674d25be82c15977d9999096e0fb
//
// tr_gnutls_pkcs7.cc:
// Implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_pkcs7.hh"
#include <memory>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>
#include <gnutls/gnutls.h>
#include <gnutls/pkcs7.h>
#include "tr_gnutls_datum_t.hh"
#include "tr_gnutls_privkey.hh"
#include "tr_gnutls_x509_crt.hh"
namespace tr_gnutls
{
class pkcs7::impl
{
public:
impl ();
~impl ();
impl (const impl &) = delete;
impl& operator= (const impl &) = delete;
impl (impl &&) = default;
impl& operator= (impl &&) = default;
void set_crt (const x509_crt &crt);
void sign (const x509_crt &crt, const privkey &pkey,
std::vector<unsigned char> &&data_tobe_signed,
std::string md);
void set_signflag (signflag f, bool b);
std::vector<unsigned char> pkcs7_export (format fmt);
operator const gnutls_pkcs7_t () const
{
return pkcs7_;
}
private:
gnutls_pkcs7_t pkcs7_ = nullptr;
unsigned sign_flags_ = 0;
};
pkcs7::impl::impl ()
{
int ret = gnutls_pkcs7_init (&pkcs7_);
if (ret > 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs7: gnutls_pkcs7_init failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
pkcs7::impl::~impl ()
{
if (pkcs7_)
gnutls_pkcs7_deinit (pkcs7_);
}
void pkcs7::impl::set_crt (const x509_crt &crt)
{
int ret = gnutls_pkcs7_set_crt (pkcs7_, crt);
if (ret > 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs7: gnutls_pkcs7_set_crt failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
void pkcs7::impl::sign (const x509_crt &crt, const privkey &pkey,
std::vector<unsigned char> &&data_tobe_signed,
std::string md)
{
datum_t d (std::forward<std::vector<unsigned char>> (data_tobe_signed));
gnutls_digest_algorithm_t dig = GNUTLS_DIG_UNKNOWN;
if ( md == "sha256" || md == "2.16.840.1.101.3.4.2.1")
dig = GNUTLS_DIG_SHA256;
else if (md == "sha384" || md == "2.16.840.1.101.3.4.2.2")
dig = GNUTLS_DIG_SHA384;
else if (md == "sha512" || md == "2.16.840.1.101.3.4.2.3")
dig = GNUTLS_DIG_SHA512;
else if (md == "sha1" || md == "1.3.14.3.2.26")
dig = GNUTLS_DIG_SHA1;
else if (md == "ripemd160" || md == "1.3.36.3.2.1")
dig = GNUTLS_DIG_RMD160;
int ret = gnutls_pkcs7_sign (pkcs7_, crt, pkey, d, nullptr, nullptr,
dig, sign_flags_);
if (ret > 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs7: gnutls_pkcs7_sign failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
void pkcs7::impl::set_signflag (signflag f, bool b)
{
unsigned flag;
switch (f)
{
case pkcs7::signflag::include_time:
flag = GNUTLS_PKCS7_INCLUDE_TIME;
break;
case pkcs7::signflag::include_cert:
flag = GNUTLS_PKCS7_INCLUDE_CERT;
break;
default:
throw std::runtime_error ("tr_gnutls::pkcs7: unknown signflag");
}
if (b)
sign_flags_ |= flag;
else
sign_flags_ &= ~flag;
}
std::vector<unsigned char> pkcs7::impl::pkcs7_export (format fmt)
{
gnutls_x509_crt_fmt_t fmt_gnutls;
switch (fmt)
{
case pkcs7::format::der:
fmt_gnutls = GNUTLS_X509_FMT_DER;
break;
case pkcs7::format::pem:
fmt_gnutls = GNUTLS_X509_FMT_PEM;
break;
default:
throw std::runtime_error ("tr_gnutls::pkcs7: unknown format");
}
std::vector<unsigned char> buff;
size_t size {0};
int ret = gnutls_pkcs7_export (pkcs7_, fmt_gnutls,
nullptr, &size);
if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
{
buff.resize (size);
ret = gnutls_pkcs7_export (pkcs7_, fmt_gnutls,
buff.data (), &size);
}
if (ret > 0)
{
std::stringstream ss;
ss << "tr_gnutls::pkcs7: gnutls_pkcs7_export failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
return buff;
}
pkcs7::pkcs7 ():
pimpl_ (new pkcs7::impl ())
{
}
pkcs7::~pkcs7 () = default;
pkcs7::pkcs7 (pkcs7 &&) = default;
pkcs7& pkcs7::operator= (pkcs7 &&) = default;
void pkcs7::set_crt (const x509_crt &crt)
{
pimpl_->set_crt (crt);
}
void pkcs7::sign (const x509_crt &crt, const privkey &pkey,
std::vector<unsigned char> &&data_tobe_signed,
std::string md)
{
pimpl_->sign (crt, pkey,
std::forward<std::vector<unsigned char>> (data_tobe_signed),
md);
}
void pkcs7::set_signflag (signflag f, bool b)
{
pimpl_->set_signflag (f, b);
}
std::vector<unsigned char> pkcs7::pkcs7_export (format fmt)
{
return pimpl_->pkcs7_export (fmt);
}
pkcs7::operator const gnutls_pkcs7_t () const
{
return static_cast<const gnutls_pkcs7_t> (*pimpl_);
}
}
//
// GnuTLS PKCS#7 class
// https://gist.github.com/trueroad/8c55674d25be82c15977d9999096e0fb
//
// tr_gnutls_pkcs7.hh:
// Header file
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_PKCS7_HH
#define INCLUDE_GUARD_TR_GNUTLS_PKCS7_HH
#include <memory>
#include <string>
#include <vector>
struct gnutls_pkcs7_int;
typedef struct gnutls_pkcs7_int *gnutls_pkcs7_t;
namespace tr_gnutls
{
class x509_crt;
class privkey;
class pkcs7
{
public:
enum class signflag
{
include_time,
include_cert,
};
enum class format
{
der,
pem,
};
pkcs7 ();
~pkcs7 ();
pkcs7 (const pkcs7 &) = delete;
pkcs7& operator= (const pkcs7 &) = delete;
pkcs7 (pkcs7 &&);
pkcs7& operator= (pkcs7 &&);
void set_crt (const x509_crt & /* crt */);
void sign (const x509_crt & /* crt */, const privkey & /* pkey */,
std::vector<unsigned char> && /* data_tobe_signed */,
std::string md);
void set_signflag (signflag /* f */, bool /* b */);
std::vector<unsigned char> pkcs7_export (format fmt = format::der);
operator const gnutls_pkcs7_t () const;
private:
class impl;
std::unique_ptr<impl> pimpl_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_PKCS7_HH
//
// GnuTLS abstract private key class
//
// tr_gnutls_privkey.cc:
// Implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_privkey.hh"
#include <memory>
#include <stdexcept>
#include <sstream>
#include <string>
#include <gnutls/abstract.h>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "tr_gnutls_x509_privkey.hh"
namespace tr_gnutls
{
class privkey::impl
{
public:
impl ()
{
init ();
}
~impl () = default;
impl (const impl &) = default;
impl& operator= (const impl &) = default;
impl (impl &&) = default;
impl& operator= (impl &&) = default;
impl (const x509_privkey &privkey)
{
init ();
set (privkey);
}
void set (const x509_privkey &privkey)
{
x509_privkey_ = privkey;
if (privkey_)
{
int ret = gnutls_privkey_import_x509 (privkey_.get (),
x509_privkey_,
0);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::privkey: gnutls_import_x509 failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
}
}
std::shared_ptr<struct gnutls_privkey_st> get ()
{
return privkey_;
}
operator const gnutls_privkey_t () const
{
return privkey_.get ();
}
private:
void init ()
{
gnutls_privkey_t p;
int ret = gnutls_privkey_init (&p);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::privkey: gnutls_privkey_init failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
privkey_.reset (p, gnutls_privkey_deinit);
}
std::shared_ptr<struct gnutls_privkey_st> privkey_;
x509_privkey x509_privkey_;
};
privkey::privkey ():
pimpl_ (new privkey::impl ())
{
}
privkey::privkey (const x509_privkey &privkey):
pimpl_ (new privkey::impl (privkey))
{
}
privkey::~privkey () = default;
privkey::privkey (const privkey &p):
pimpl_ (new privkey::impl (*(p.pimpl_.get ())))
{
}
privkey& privkey::operator= (const privkey &other)
{
if (this != &other)
pimpl_.reset (new privkey::impl (*(other.pimpl_.get ())));
return *this;
}
privkey::privkey (privkey &&) = default;
privkey& privkey::operator= (privkey &&) = default;
void privkey::set (const x509_privkey &privkey)
{
pimpl_->set (privkey);
}
std::shared_ptr<struct gnutls_privkey_st>
privkey::get () const
{
return pimpl_->get ();
}
privkey::operator const gnutls_privkey_t () const
{
return static_cast<const gnutls_privkey_t> (*pimpl_);
}
}
//
// GnuTLS abstract private key class
//
// tr_gnutls_privkey.hh:
// Header file
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_PRIVKEY_HH
#define INCLUDE_GUARD_TR_GNUTLS_PRIVKEY_HH
#include <memory>
struct gnutls_privkey_st;
typedef struct gnutls_privkey_st *gnutls_privkey_t;
namespace tr_gnutls
{
class x509_privkey;
class privkey
{
public:
privkey ();
privkey (const x509_privkey & /* privkey */);
~privkey ();
privkey (const privkey &);
privkey& operator= (const privkey &);
privkey (privkey &&);
privkey& operator= (privkey &&);
void set (const x509_privkey & /* privkey */);
std::shared_ptr<struct gnutls_privkey_st> get () const;
operator const gnutls_privkey_t () const;
private:
class impl;
std::unique_ptr<impl> pimpl_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_PRIVKEY_HH
//
// GnuTLS x509 certificate class
//
// tr_gnutls_x509_crt.cc:
// Implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_x509_crt.hh"
#include <memory>
#include <stdexcept>
#include <sstream>
#include <string>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include "tr_gnutls_datum_t.hh"
namespace tr_gnutls
{
x509_crt::x509_crt () = default;
x509_crt::~x509_crt () = default;
x509_crt::x509_crt (const x509_crt &) = default;
x509_crt& x509_crt::operator= (const x509_crt &) = default;
x509_crt::x509_crt (x509_crt &&) = default;
x509_crt& x509_crt::operator= (x509_crt &&) = default;
x509_crt::x509_crt (gnutls_x509_crt_t crt)
{
set (crt);
}
void x509_crt::set (gnutls_x509_crt_t crt)
{
crt_.reset (crt, gnutls_x509_crt_deinit);
}
std::shared_ptr<struct gnutls_x509_crt_int>
x509_crt::get () const
{
return crt_;
}
x509_crt::operator const gnutls_x509_crt_t () const
{
return crt_.get ();
}
std::string x509_crt::get_dn ()
{
datum_t d;
int ret = gnutls_x509_crt_get_dn3 (crt_.get (), d.assign (),
GNUTLS_X509_DN_FLAG_COMPAT);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::x509_crt: gnutls_x509_crt_get_dn3 failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
std::string str (reinterpret_cast<char*> (d.data ()));
return str;
}
std::string x509_crt::get_issuer_dn ()
{
datum_t d;
int ret = gnutls_x509_crt_get_issuer_dn3 (crt_.get (), d.assign (),
GNUTLS_X509_DN_FLAG_COMPAT);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::x509_crt: gnutls_x509_crt_get_issuer_dn3 failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
std::string str (reinterpret_cast<char*> (d.data ()));
return str;
}
std::string x509_crt::get_pk_oid ()
{
size_t size {0};
std::string buff;
int ret = gnutls_x509_crt_get_pk_oid (crt_.get (), nullptr, &size);
if (ret == GNUTLS_E_SHORT_MEMORY_BUFFER)
{
buff.resize (size);
ret = gnutls_x509_crt_get_pk_oid (crt_.get (), &buff[0], &size);
}
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::x509_crt: gnutls_x509_crt_get_pk_oid failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
buff.pop_back ();
return buff;
}
unsigned int x509_crt::get_pk_bits ()
{
unsigned int bits;
int ret = gnutls_x509_crt_get_pk_algorithm (crt_.get (), &bits);
if (ret < 0)
{
std::stringstream ss;
ss << "tr_gnutls::x509_crt: gnutls_x509_crt_get_algorithm failed: "
<< gnutls_strerror (ret);
throw std::runtime_error (ss.str ().c_str ());
}
return bits;
}
}
//
// GnuTLS x509 certificate class
//
// tr_gnutls_x509_crt.hh:
// Header file
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_X509_CRT_HH
#define INCLUDE_GUARD_TR_GNUTLS_X509_CRT_HH
#include <memory>
struct gnutls_x509_crt_int;
typedef struct gnutls_x509_crt_int *gnutls_x509_crt_t;
namespace tr_gnutls
{
class x509_crt
{
public:
x509_crt ();
x509_crt (gnutls_x509_crt_t /* crt */);
~x509_crt ();
x509_crt (const x509_crt &);
x509_crt& operator= (const x509_crt &);
x509_crt (x509_crt &&);
x509_crt& operator= (x509_crt &&);
void set (gnutls_x509_crt_t /* crt */);
std::shared_ptr<struct gnutls_x509_crt_int> get () const;
operator const gnutls_x509_crt_t () const;
std::string get_dn ();
std::string get_issuer_dn ();
std::string get_pk_oid ();
unsigned int get_pk_bits ();
private:
std::shared_ptr<struct gnutls_x509_crt_int> crt_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_X509_CRT_HH
//
// GnuTLS x509 private key class
//
// tr_gnutls_x509_privkey.cc:
// Implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_gnutls_x509_privkey.hh"
#include <memory>
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
namespace tr_gnutls
{
x509_privkey::x509_privkey () = default;
x509_privkey::~x509_privkey () = default;
x509_privkey::x509_privkey (const x509_privkey &) = default;
x509_privkey& x509_privkey::operator= (const x509_privkey &) = default;
x509_privkey::x509_privkey (x509_privkey &&) = default;
x509_privkey& x509_privkey::operator= (x509_privkey &&) = default;
x509_privkey::x509_privkey (gnutls_x509_privkey_t privkey)
{
set (privkey);
}
void x509_privkey::set (gnutls_x509_privkey_t privkey)
{
privkey_.reset (privkey, gnutls_x509_privkey_deinit);
}
std::shared_ptr<struct gnutls_x509_privkey_int>
x509_privkey::get () const
{
return privkey_;
}
x509_privkey::operator const gnutls_x509_privkey_t () const
{
return privkey_.get ();
}
}
//
// GnuTLS x509 private key class
//
// tr_gnutls_x509_privkey.hh:
// Header file
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_GNUTLS_X509_PRIVKEY_HH
#define INCLUDE_GUARD_TR_GNUTLS_X509_PRIVKEY_HH
#include <memory>
struct gnutls_x509_privkey_int;
typedef struct gnutls_x509_privkey_int *gnutls_x509_privkey_t;
namespace tr_gnutls
{
class x509_privkey
{
public:
x509_privkey ();
x509_privkey (gnutls_x509_privkey_t /* privkey */);
~x509_privkey ();
x509_privkey (const x509_privkey &);
x509_privkey& operator= (const x509_privkey &);
x509_privkey (x509_privkey &&);
x509_privkey& operator= (x509_privkey &&);
void set (gnutls_x509_privkey_t /* privkey */);
std::shared_ptr<struct gnutls_x509_privkey_int> get () const;
operator const gnutls_x509_privkey_t () const;
private:
std::shared_ptr<struct gnutls_x509_privkey_int> privkey_;
};
}
#endif // INCLUDE_GUARD_TR_GNUTLS_X509_PRIVKEY_HH
//
// Utility for binary files / data
//
// tr_util_binary.hh:
// Header file / implementation
//
// Copyright (C) 2019, 2020 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_UTIL_BINARY_HH
#define INCLUDE_GUARD_TR_UTIL_BINARY_HH
#include <fstream>
#include <iomanip>
#include <stdexcept>
#include <sstream>
#include <string>
#include <vector>
namespace tr_util
{
inline
std::string binary_hex (const std::vector<unsigned char> &buff)
{
std::stringstream ss;
ss << std::hex;
for (int i = 0; i < buff.size (); ++i)
{
if ((i % 16) == 0 && i)
ss << std::endl;
ss << std::setw (2) << std::setfill ('0')
<< static_cast<unsigned int> (buff[i]) << " ";
}
ss << std::endl;
return ss.str ();
}
inline
std::vector<unsigned char> fileload_binary (const std::string &filename)
{
std::ifstream ifs (filename, std::ios::binary);
if (!ifs)
throw std::runtime_error ("tr_util::fileload_binary: "
"std::ifstream failed");
ifs.seekg (0, std::ios::end);
auto eof {ifs.tellg ()};
ifs.clear ();
ifs.seekg (0, std::ios::beg);
std::vector<unsigned char> buff (eof);
ifs.read (reinterpret_cast<char*> (buff.data ()), buff.size ());
return buff;
}
inline void filesave (const std::string &filename,
const std::vector<unsigned char> &buff)
{
std::ofstream ofs (filename, std::ios::binary);
if (!ofs)
throw std::runtime_error ("tr_util::filesave: "
"std::ofstream failed");
ofs.write (reinterpret_cast<const char*> (buff.data ()), buff.size ());
}
}
#endif // INCLUDE_GUARD_TR_UTIL_BINARY_HH
//
// Suppress echo back class
// https://gist.github.com/trueroad/75610d634afe25ba6f74c2b21d421952
//
// tr_util_suppress_echo_back.cc:
// suppress_echo_back class implementation
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#include "tr_util_suppress_echo_back.hh"
#include <termios.h>
#include <unistd.h>
namespace tr_util
{
suppress_echo_back::suppress_echo_back ()
{
if (n++ == 0)
{
struct termios tty;
tcgetattr (STDIN_FILENO, &tty);
tty.c_lflag &= ~ECHO;
tcsetattr (STDIN_FILENO, TCSANOW, &tty);
}
}
suppress_echo_back::~suppress_echo_back ()
{
if (--n == 0)
{
struct termios tty;
tcgetattr (STDIN_FILENO, &tty);
tty.c_lflag |= ECHO;
tcsetattr (STDIN_FILENO, TCSANOW, &tty);
}
}
std::atomic<int> suppress_echo_back::n {0};
};
//
// Suppress echo back class
// https://gist.github.com/trueroad/75610d634afe25ba6f74c2b21d421952
//
// tr_util_suppress_echo_back.hh:
// suppress_echo_back class header file
//
// Copyright (C) 2019 Masamichi Hosoda.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED.
// IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
// SUCH DAMAGE.
//
#ifndef INCLUDE_GUARD_TR_UTIL_SUPPRESS_ECHO_BACK_HH
#define INCLUDE_GUARD_TR_UTIL_SUPPRESS_ECHO_BACK_HH
#include <atomic>
namespace tr_util
{
class suppress_echo_back
{
public:
suppress_echo_back ();
~suppress_echo_back ();
suppress_echo_back (const suppress_echo_back &) = delete;
suppress_echo_back& operator= (const suppress_echo_back &) = delete;
suppress_echo_back (suppress_echo_back &&) = delete;
suppress_echo_back& operator= (suppress_echo_back &&) = delete;
private:
static std::atomic<int> n;
};
}
#endif // INCLUDE_GUARD_TR_UTIL_SUPPRESS_ECHO_BACK_HH
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment