now with openssl wrapper
This commit is contained in:
@@ -5,7 +5,7 @@
|
||||
## 1 2 3 4 5 6 7 8
|
||||
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
include_HEADERS = pcsc.hxx cryptoki.hxx
|
||||
include_HEADERS = pcsc.hxx cryptoki.hxx openssl.hxx
|
||||
pkcs11_HEADERS = pkcs11/pkcs11.h pkcs11/pkcs11types.h pkcs11/apiclient.h
|
||||
pkcs11dir = ${includedir}/pkcs11
|
||||
|
||||
|
277
src/openssl.hxx
Normal file
277
src/openssl.hxx
Normal file
@@ -0,0 +1,277 @@
|
||||
/*! @file
|
||||
|
||||
@id $Id$
|
||||
*/
|
||||
// 1 2 3 4 5 6 7 8
|
||||
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||||
|
||||
#ifndef __OPENSSL_HXX__
|
||||
#define __OPENSSL_HXX__
|
||||
|
||||
#include <openssl/pkcs12.h>
|
||||
#include <openssl/x509.h>
|
||||
|
||||
#include "openssl/bio.h"
|
||||
#include "openssl/ssl.h"
|
||||
#include <openssl/err.h>
|
||||
#include <cstdio>
|
||||
|
||||
namespace openssl {
|
||||
|
||||
|
||||
//============================================================================
|
||||
class exception: public std::exception {
|
||||
public:
|
||||
exception(const std::string& reason) throw():
|
||||
_what("openssl: "+reason) {
|
||||
}
|
||||
~exception() throw() {}
|
||||
const char* what() const throw() {
|
||||
return _what.c_str();
|
||||
}
|
||||
private:
|
||||
std::string _what;
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class openssl_error: public exception {
|
||||
public:
|
||||
openssl_error(const std::string& reason) throw():
|
||||
exception(reason+'\n'+ERR_error_string(ERR_get_error(), 0)) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class pkcs12_error: public openssl_error {
|
||||
public:
|
||||
pkcs12_error(const std::string& reason) throw():
|
||||
openssl_error("pkcs12: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class x509_error: public openssl_error {
|
||||
public:
|
||||
x509_error(const std::string& reason) throw():
|
||||
openssl_error("x509: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class bio_error: public openssl_error {
|
||||
public:
|
||||
bio_error(const std::string& reason) throw():
|
||||
openssl_error("bio: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class allocation_failed: public x509_error {
|
||||
public:
|
||||
allocation_failed() throw():
|
||||
x509_error("memory allocation failed") {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class undefined_certificate: public x509_error {
|
||||
public:
|
||||
undefined_certificate() throw():
|
||||
x509_error("certificate must not be 0") {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class x509_parsing_failed: public x509_error {
|
||||
public:
|
||||
x509_parsing_failed() throw():
|
||||
x509_error("parsing DER encoded certificate failed") {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class x509_copy_failed: public x509_error {
|
||||
public:
|
||||
x509_copy_failed() throw():
|
||||
x509_error("certificate object copy failed") {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class pkcs12_reading_failed: public pkcs12_error {
|
||||
public:
|
||||
pkcs12_reading_failed(const std::string& file) throw():
|
||||
pkcs12_error("reading DER encoded p12 file failed: "+file) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class pkcs12_parsing_failed: public pkcs12_error {
|
||||
public:
|
||||
pkcs12_parsing_failed(const std::string& file) throw():
|
||||
pkcs12_error("parsing DER encoded p12 file failed: "+file) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class pkcs12_no_private_key: public pkcs12_error {
|
||||
public:
|
||||
pkcs12_no_private_key() throw(): pkcs12_error("no private key") {}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class pkcs12_no_x509: public pkcs12_error {
|
||||
public:
|
||||
pkcs12_no_x509() throw(): pkcs12_error("no x509 certificate") {}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class cannot_open_file: public exception {
|
||||
public:
|
||||
cannot_open_file(const std::string& file) throw():
|
||||
exception("cannot open file: "+file) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class bio_connection_failed: public bio_error {
|
||||
public:
|
||||
bio_connection_failed(const std::string& hostPort) throw():
|
||||
bio_error("connection failed to: "+hostPort) {
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
class Init {
|
||||
public:
|
||||
Init() {
|
||||
SSL_load_error_strings();
|
||||
ERR_load_BIO_strings();
|
||||
OpenSSL_add_all_algorithms();
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
class X509 {
|
||||
public:
|
||||
//! Construct empty certificate.
|
||||
X509(): _x509(X509_new()) {
|
||||
if (!_x509) throw allocation_failed();
|
||||
}
|
||||
X509(const X509& o) _x509(0) {
|
||||
char* d(0);
|
||||
int len(i2d_X509(o._x509, &d));
|
||||
if (!len) throw x509_copy_failed();
|
||||
char* d1(d);
|
||||
_x509 = d2i_X509(0, &d2, len);
|
||||
if (d2!=d+len || !_x509) throw x509_copy_failed();
|
||||
}
|
||||
//! Take over OpenSSL allocated certificate.
|
||||
X509(::X509 *x509): _x509(x509) {
|
||||
if (!_x509) throw undefined_certificate();
|
||||
}
|
||||
~X509() {
|
||||
X509_free(_x509);
|
||||
}
|
||||
X509& operator=(const X509& o) {
|
||||
X509_free(_x509);
|
||||
_x509 = 0;
|
||||
char* d(0);
|
||||
int len(i2d_X509(o._x509, &d));
|
||||
if (!len) throw x509_copy_failed();
|
||||
char* d1(d);
|
||||
_x509 = d2i_X509(0, &d2, len);
|
||||
if (d2!=d+len || !_x509) throw x509_copy_failed();
|
||||
}
|
||||
private:
|
||||
::X509* _x509;
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
class PrivateKey {
|
||||
public:
|
||||
PrivateKey(EVP_PKEY *) {
|
||||
}
|
||||
};
|
||||
|
||||
//============================================================================
|
||||
class PKCS12 {
|
||||
|
||||
//...............................................................typedefs
|
||||
public:
|
||||
typedef std::vector<X509*> X509List;
|
||||
|
||||
//................................................................methods
|
||||
public:
|
||||
|
||||
//! Read from a PKCS#12 (.p12) file.
|
||||
PKCS12(std::string filename, std::string password):
|
||||
_key(0), _cert(0) {
|
||||
FILE* file(fopen(filename.c_str(), "rb"));
|
||||
if (!file) throw cannot_open_file(filename);
|
||||
::PKCS12 *p12(d2i_PKCS12_fp(file, 0));
|
||||
fclose(file);
|
||||
if (!p12) throw pkcs12_reading_failed(filename);
|
||||
try {
|
||||
EVP_PKEY *pkey(0);
|
||||
::X509 *cert(0);
|
||||
STACK_OF(X509) *ca(0);
|
||||
if (!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &ca))
|
||||
throw pkcs12_parsing_failed(filename);
|
||||
if (pkey) _key = new PrivateKey(pkey);
|
||||
if (cert) _cert = new X509(cert);
|
||||
for (int i(sk_num(ca)); i>0; --i)
|
||||
_ca.push_back(new X509((::X509*)sk_pop(ca)));
|
||||
PKCS12_free(p12);
|
||||
} catch (...) {
|
||||
PKCS12_free(p12);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
~PKCS12() {
|
||||
delete _key;
|
||||
delete _cert;
|
||||
for (X509List::iterator it(_ca.begin()); it!=_ca.end(); ++it)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
bool hasPrivateKey() {
|
||||
return _key;
|
||||
}
|
||||
|
||||
bool hasCert() {
|
||||
return _cert;
|
||||
}
|
||||
|
||||
const PrivateKey& privateKey() {
|
||||
if (!_key) throw pkcs12_no_private_key();
|
||||
return *_key;
|
||||
};
|
||||
|
||||
const X509& x509() {
|
||||
if (!_cert) throw pkcs12_no_x509();
|
||||
return *_cert;
|
||||
};
|
||||
|
||||
const X509List& ca() const {
|
||||
return _ca;
|
||||
}
|
||||
|
||||
private:
|
||||
PrivateKey *_key;
|
||||
X509 *_cert;
|
||||
X509List _ca;
|
||||
};
|
||||
|
||||
class BIO {
|
||||
public:
|
||||
BIO() {}
|
||||
~BIO() {
|
||||
try {
|
||||
close()
|
||||
} catch (...) {
|
||||
if (!std::uncaught_exception()) throw;
|
||||
}
|
||||
}
|
||||
void connect(const std::string& hostPort) {
|
||||
close();
|
||||
if (_bio = BIO_new_connect(hostPort.c_str()))
|
||||
throw bio_connection_failed(hostPort);
|
||||
}
|
||||
void close() {
|
||||
//! @todo tbd
|
||||
}
|
||||
private:
|
||||
BIO* _bio;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user