1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
|
// OpenVPN -- An application to securely tunnel IP networks
// over a single port, with support for SSL/TLS-based
// session authentication and key exchange,
// packet encryption, packet authentication, and
// packet compression.
//
// Copyright (C) 2017-2018 OpenVPN Technologies, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License Version 3
// as published by the Free Software Foundation.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program in the COPYING file.
// If not, see <http://www.gnu.org/licenses/>.
// Wrap the OpenSSL PEM API defined in <openssl/pem.h> so
// that it can be used as part of the crypto layer of the OpenVPN core.
#ifndef OPENVPN_OPENSSL_UTIL_PEM_H
#define OPENVPN_OPENSSL_UTIL_PEM_H
#include <openvpn/common/numeric_cast.hpp>
#include <openvpn/openssl/util/error.hpp>
#include <openssl/pem.h>
namespace openvpn {
class OpenSSLPEM
{
public:
static bool pem_encode(BufferAllocated &dst,
const unsigned char *src,
size_t src_len,
const std::string &key_name)
{
bool ret = false;
if (!is_safe_conversion<int>(src_len))
return false;
BIO *bio = BIO_new(BIO_s_mem());
if (!bio)
return false;
if (!PEM_write_bio(bio, key_name.c_str(), "", src, static_cast<int>(src_len)))
goto out;
BUF_MEM *bptr;
BIO_get_mem_ptr(bio, &bptr);
dst.write((unsigned char *)bptr->data, bptr->length);
ret = true;
out:
if (!BIO_free(bio))
ret = false;
return ret;
}
static bool pem_decode(BufferAllocated &dst,
const char *src,
size_t src_len,
const std::string &key_name)
{
bool ret = false;
BIO *bio;
if (!(bio = BIO_new_mem_buf(src, numeric_cast<int>(src_len))))
throw OpenSSLException("Cannot open memory BIO for PEM decode");
char *name_read = NULL;
char *header_read = NULL;
uint8_t *data_read = NULL;
long data_read_len = 0;
if (!PEM_read_bio(bio,
&name_read,
&header_read,
&data_read,
&data_read_len))
{
OPENVPN_LOG("PEM decode failed");
goto out;
}
if (key_name.compare(std::string(name_read)))
{
OPENVPN_LOG("unexpected PEM name (got '" << name_read << "', expected '" << key_name << "')");
goto out;
}
dst.write(data_read, data_read_len);
ret = true;
out:
OPENSSL_free(name_read);
OPENSSL_free(header_read);
OPENSSL_free(data_read);
if (!BIO_free(bio))
ret = false;
return ret;
}
};
}; // namespace openvpn
#endif /* OPENVPN_OPENSSL_UTIL_PEM_H */
|