From 62032fcd59c4518891cc392e60478065165eee52 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Felix=20D=C3=B6rre?= Date: Sun, 2 Nov 2014 00:50:54 +0100 Subject: [PATCH] add: Make the OpenSSL library initialization work --- src/main.cpp | 5 +- src/simpleOpensslSigner.cpp | 174 +++++++++++++++++++++++++++++++----- src/simpleOpensslSigner.h | 5 ++ 3 files changed, 159 insertions(+), 25 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6523166..b57d343 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,11 +40,8 @@ int main( int argc, const char* argv[] ) { } if( job->task == "sign" ) { - std::cout << "signing" << std::endl; std::shared_ptr cert = jp->fetchTBSCert( job ); - std::cout << cert->CN << std::endl; - std::cout << cert->md << std::endl; - std::cout << cert->csr << std::endl; + std::cout << "Found a CSR at '" << cert->csr << "' signing" << std::endl; std::ifstream t( cert->csr ); cert->csr_content = std::string( std::istreambuf_iterator( t ), std::istreambuf_iterator() ); sign->sign( cert ); diff --git a/src/simpleOpensslSigner.cpp b/src/simpleOpensslSigner.cpp index 08471bc..3ef4b5e 100644 --- a/src/simpleOpensslSigner.cpp +++ b/src/simpleOpensslSigner.cpp @@ -7,40 +7,172 @@ #include #include #include +#include + +std::shared_ptr SimpleOpensslSigner::lib_ref( + new int( SSL_library_init() ), + []( int* ref ) { + ( void ) ref; + } ); + +std::shared_ptr loadX509FromFile( std::string filename ) { + FILE* f = fopen( filename.c_str(), "r" ); + + if( !f ) { + return std::shared_ptr(); + } + + X509* key = PEM_read_X509( f, NULL, NULL, 0 ); + fclose( f ); + + if( !key ) { + return std::shared_ptr(); + } + + return std::shared_ptr( + key, + []( X509 * ref ) { + X509_free( ref ); + } ); +} + +std::shared_ptr loadPkeyFromFile( std::string filename ) { + FILE* f = fopen( filename.c_str(), "r" ); + + if( !f ) { + return std::shared_ptr(); + } + + EVP_PKEY* key = PEM_read_PrivateKey( f, NULL, NULL, 0 ); + fclose( f ); + + if( !key ) { + return std::shared_ptr(); + } + + return std::shared_ptr( + key, + []( EVP_PKEY * ref ) { + EVP_PKEY_free( ref ); + } ); +} + +std::shared_ptr SimpleOpensslSigner::caCert = loadX509FromFile( "assured.crt" ); + +std::shared_ptr SimpleOpensslSigner::caKey = loadPkeyFromFile( "assured.key" ); + +int add_ext( std::shared_ptr issuer, X509* subj, int nid, const char* value ) { + X509_EXTENSION* ex; + X509V3_CTX ctx; + /* This sets the 'context' of the extensions. */ + /* No configuration database */ + X509V3_set_ctx_nodb( &ctx ); + /* Issuer and subject certs: both the target since it is self signed, + * no request and no CRL + */ + X509V3_set_ctx( &ctx, issuer.get(), subj, NULL, NULL, 0 ); + ex = X509V3_EXT_conf_nid( NULL, &ctx, nid, const_cast( value ) ); + + if( !ex ) { + return 0; + } + + X509_add_ext( subj, ex, -1 ); + X509_EXTENSION_free( ex ); + return 1; +} void SimpleOpensslSigner::sign( std::shared_ptr cert ) { - std::cout << cert->CN << std::endl; - BIO* in; - in = BIO_new_mem_buf( const_cast( cert->csr_content.c_str() ), -1 ); - X509_REQ* req = PEM_read_bio_X509_REQ( in, NULL, NULL, NULL ); + if( !caKey ) { + throw "CA-key not found"; + } - if( req == NULL ) { - std::cerr << "Error parsing CSR" << std::endl; - return; + std::shared_ptr in = std::shared_ptr( + BIO_new_mem_buf( const_cast( cert->csr_content.c_str() ), -1 ), + []( BIO * ref ) { + BIO_free( ref ); + } ); + std::shared_ptr req = std::shared_ptr( + PEM_read_bio_X509_REQ( in.get(), NULL, NULL, NULL ), + []( X509_REQ * ref ) { + if( ref ) { + X509_REQ_free( ref ); + } + } ); + + if( !req ) { + throw "Error parsing CSR"; } - EVP_PKEY* pktmp = X509_REQ_get_pubkey( req ); + EVP_PKEY* pktmp = X509_REQ_get_pubkey( req.get() ); - if( pktmp == NULL ) { - std::cerr << "Error extracting pubkey" << std::endl; - return; + if( !pktmp ) { + throw "Error extracting pubkey"; } - std::cout << req << ";" << pktmp << std::endl; - SSL_library_init(); - int i = X509_REQ_verify( req, pktmp ); - ERR_load_crypto_strings(); - ERR_print_errors_fp( stderr ); - std::cout << ERR_get_error() << std::endl; + EVP_PKEY_free( pktmp ); + + int i = X509_REQ_verify( req.get(), pktmp ); if( i < 0 ) { - std::cerr << "Signature problems ... " << i << std::endl; - return; + throw "Signature problems ... "; } else if( i == 0 ) { - std::cerr << "Signature did not match" << std::endl; - return; + throw "Signature did not match"; } else { std::cerr << "Signature ok" << std::endl; } + // Construct the Certificate + + std::shared_ptr ret = std::shared_ptr( X509_new(), X509_free ); + + if( !ret ) { + throw "Creating X509 failed."; + } + + X509_CINF* ci = ret->cert_info; + + if( !X509_set_version( ret.get(), 2 ) ) { + throw "Setting X509-version to 3 failed"; + } + + if( !X509_set_issuer_name( ret.get(), X509_get_subject_name( caCert.get() ) ) ) { + throw "Error setting Issuer name"; + } + + // Serial and Pubkey + ASN1_INTEGER_set( ci->serialNumber, 4711 ); + pktmp = X509_REQ_get_pubkey( req.get() ); + + if( !X509_set_pubkey( ret.get(), pktmp ) ) { + EVP_PKEY_free( pktmp ); + throw "Setting public key failed."; + } else { + EVP_PKEY_free( pktmp ); + } + + // Dates + X509_gmtime_adj( X509_get_notBefore( ret.get() ), 0 ); + X509_gmtime_adj( X509_get_notAfter( ret.get() ), ( long )60 * 60 * 24 * 10 ); + + // Extensions + add_ext( caCert, ret.get(), NID_basic_constraints, "critical,CA:FALSE" ); + add_ext( caCert, ret.get(), NID_subject_key_identifier, "hash" ); + add_ext( caCert, ret.get(), NID_authority_key_identifier, "keyid,issuer:always" ); + add_ext( caCert, ret.get(), NID_key_usage, "critical,nonRepudiation,digitalSignature,keyEncipherment" ); + add_ext( caCert, ret.get(), NID_ext_key_usage, "clientAuth, serverAut" ); + add_ext( caCert, ret.get(), NID_info_access, "OCSP;URI:http://ocsp.cacert.org" ); + add_ext( caCert, ret.get(), NID_crl_distribution_points, "URI:http://crl.cacert.org/class3-revoke.crl" ); + + if( !X509_sign( ret.get(), caKey.get(), EVP_sha512() ) ) { + throw "Signing failed."; + } + + X509_print_fp( stdout, ret.get() ); + std::shared_ptr mem = std::shared_ptr( BIO_new( BIO_s_mem() ), BIO_free ); + PEM_write_bio_X509( mem.get(), ret.get() ); + BUF_MEM* buf; + BIO_get_mem_ptr( mem.get(), &buf ); + std::string output( buf->data, buf->data + buf->length ); + std::cout << "Certificate:" << std::endl << output << std::endl; } diff --git a/src/simpleOpensslSigner.h b/src/simpleOpensslSigner.h index 2eb300d..586e6e2 100644 --- a/src/simpleOpensslSigner.h +++ b/src/simpleOpensslSigner.h @@ -2,8 +2,13 @@ #include "database.h" #include "signer.h" +#include class SimpleOpensslSigner : public Signer { +private: + static std::shared_ptr lib_ref; + static std::shared_ptr caKey; + static std::shared_ptr caCert; public: void sign( std::shared_ptr cert ); }; -- 2.39.5