return map;
}
-int parseConfig( std::string path ) {
-
- auto masterConf = parseConf( path );
-
- keyDir = masterConf->at( "key.directory" );
- sqlHost = masterConf->at( "sql.host" );
- sqlUser = masterConf->at( "sql.user" );
- sqlPass = masterConf->at( "sql.password" );
- sqlDB = masterConf->at( "sql.database" );
- serialPath = masterConf->at( "serialPath" );
-
+int parseProfiles() {
CAs = std::unordered_map<std::string, std::shared_ptr<CAConfig>>();
DIR* dp;
std::cout << profiles.size() << " profiles loaded." << std::endl;
+ return 0;
+}
+
+int parseConfig( std::string path ) {
+
+ auto masterConf = parseConf( path );
+
+ keyDir = masterConf->at( "key.directory" );
+ sqlHost = masterConf->at( "sql.host" );
+ sqlUser = masterConf->at( "sql.user" );
+ sqlPass = masterConf->at( "sql.password" );
+ sqlDB = masterConf->at( "sql.database" );
+ serialPath = masterConf->at( "serialPath" );
+
if( keyDir == "" ) {
std::cerr << "Missing config property key.directory" << std::endl;
return -1;
}
+ if( parseProfiles() != 0 ) {
+ return -1;
+ }
+
return 0;
}
#include <string>
int parseConfig( std::string path );
+void parseProfiles();
--- /dev/null
+#include "CRL.h"
+
+#include <openssl/ssl.h>
+
+CRL::CRL( std::string path ) {
+ std::shared_ptr<BIO> bio( BIO_new_file( path.c_str(), "r" ), free );
+ crl = std::shared_ptr<X509_CRL>( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free );
+
+ if( !crl ) {
+ crl = std::shared_ptr<X509_CRL>( X509_CRL_new(), X509_CRL_free );
+ }
+}
+
+std::string CRL::revoke( std::string serial, std::string time ) {
+ BIGNUM* serBN = 0;
+
+ if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
+ throw "hex2bn malloc fail";
+ }
+
+ std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
+ std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
+
+ if( !ser ) {
+ throw "BN Malloc fail";
+ }
+
+ std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
+
+ if( !tmptm ) {
+ throw "ASN1-Time Malloc fail";
+ }
+
+ X509_gmtime_adj( tmptm.get(), 0 );
+
+ X509_REVOKED* rev = X509_REVOKED_new();
+ X509_REVOKED_set_serialNumber( rev, ser.get() );
+
+ if( time != "" ) {
+ const unsigned char* data = ( unsigned char* )( time.data() );
+ d2i_ASN1_UTCTIME( &rev->revocationDate, &data, time.size() );
+ } else {
+ X509_REVOKED_set_revocationDate( rev, tmptm.get() );
+ }
+
+ X509_CRL_add0_revoked( crl.get(), rev );
+
+ int len = i2d_ASN1_UTCTIME( tmptm.get(), NULL );
+ unsigned char* buffer = ( unsigned char* ) OPENSSL_malloc( len );
+ unsigned char* pos = buffer;
+ i2d_ASN1_UTCTIME( tmptm.get(), &pos );
+ std::string rettime = std::string( ( char* ) buffer, len );
+ OPENSSL_free( buffer );
+ return rettime;
+}
+
+void CRL::sign( std::shared_ptr<CAConfig> ca ) {
+ // Updating necessary CRL props
+ std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
+
+ if( !tmptm ) {
+ throw "ASN1-Time Malloc fail";
+ }
+
+ X509_gmtime_adj( tmptm.get(), 0 );
+
+ if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) {
+ throw "Setting issuer failed";
+ }
+
+ X509_CRL_set_lastUpdate( crl.get(), tmptm.get() );
+
+ if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) {
+ throw "Updating time failed";
+ }
+
+ X509_CRL_set_nextUpdate( crl.get(), tmptm.get() );
+
+ // Sorting and signing
+ X509_CRL_sort( crl.get() );
+ X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() );
+}
+
+bool CRL::verify( std::shared_ptr<CAConfig> ca ) {
+ std::shared_ptr<EVP_PKEY> pk( X509_get_pubkey( ca->ca.get() ), EVP_PKEY_free );
+ return X509_CRL_verify( crl.get(), pk.get() ) > 0;
+}
+
+std::string CRL::toString() {
+ // Write out the new CRL
+ std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
+ PEM_write_bio_X509_CRL( mem.get(), crl.get() );
+ BUF_MEM* bptr;
+ BIO_get_mem_ptr( mem.get(), &bptr );
+ std::string newCRL( bptr->data, bptr->length );
+ return newCRL;
+}
+
+std::string CRL::getSignature() {
+ int len = i2d_X509_ALGOR( crl->sig_alg, NULL );
+ len += i2d_ASN1_BIT_STRING( crl->signature, NULL );
+ len += i2d_ASN1_UTCTIME( crl->crl->lastUpdate, NULL );
+ len += i2d_ASN1_UTCTIME( crl->crl->nextUpdate, NULL );
+
+ unsigned char* buffer = ( unsigned char* ) OPENSSL_malloc( len );
+ unsigned char* pos = buffer;
+ i2d_X509_ALGOR( crl->sig_alg, &pos );
+ i2d_ASN1_BIT_STRING( crl->signature, &pos );
+ i2d_ASN1_UTCTIME( crl->crl->lastUpdate, &pos );
+ i2d_ASN1_UTCTIME( crl->crl->nextUpdate, &pos );
+ std::string res = std::string( ( char* ) buffer, len );
+ OPENSSL_free( buffer );
+
+ return res;
+}
+
+void CRL::setSignature( std::string signature ) {
+ const unsigned char* data = ( unsigned char* )( signature.data() );
+ const unsigned char* buffer = data;
+ d2i_X509_ALGOR( &crl->sig_alg, &buffer, signature.size() );
+ d2i_ASN1_BIT_STRING( &crl->signature, &buffer, signature.size() + buffer - data );
+ d2i_ASN1_UTCTIME( &crl->crl->lastUpdate, &buffer, signature.size() + buffer - data );
+ d2i_ASN1_UTCTIME( &crl->crl->nextUpdate, &buffer, signature.size() + buffer - data );
+}
--- /dev/null
+#pragma once
+
+#include <string>
+#include <memory>
+
+#include "crypto/sslUtil.h"
+
+class CRL {
+private:
+ std::shared_ptr<X509_CRL> crl;
+public:
+ CRL( std::string path );
+
+ /**
+ * Adds the serial to this serial.
+ * @param serial the serial to remove (as hex string)
+ * @param time the "revokation time" (der-encoded)
+ * @returns DER-encoded UTCTIME of the revoked time
+ */
+ std::string revoke( std::string serial, std::string time );
+
+ /**
+ * Signs this CRL.
+ * @param ca the CA to sign with
+ */
+ void sign( std::shared_ptr<CAConfig> ca );
+
+ bool verify( std::shared_ptr<CAConfig> ca );
+
+ std::string getSignature();
+ void setSignature( std::string signature );
+
+ std::string toString();
+};
#include "remoteSigner.h"
+#include "util.h"
#include <iostream>
return result;
}
-std::shared_ptr<X509_CRL> RemoteSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
+std::shared_ptr<CRL> RemoteSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
( void )BIO_reset( target.get() );
std::shared_ptr<SSL> ssl( SSL_new( ctx.get() ), SSL_free );
if( length <= 0 ) {
std::cout << "Error, no response data" << std::endl;
- return std::shared_ptr<X509_CRL>();
+ return std::shared_ptr<CRL>();
}
payload = parseCommand( head, std::string( buffer.data(), length ), log );
throw "Invalid response command.";
}
+ writeFile( ca->path + "/ca.crl", payload );
+
if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) { // need to close the connection twice
std::cout << "SSL shutdown failed" << std::endl;
}
- return std::shared_ptr<X509_CRL>();
+ return std::shared_ptr<CRL>();
}
void RemoteSigner::setLog( std::shared_ptr<std::ostream> target ) {
RemoteSigner( std::shared_ptr<BIO> target, std::shared_ptr<SSL_CTX> ctx );
~RemoteSigner();
std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
- std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
+ std::shared_ptr<CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
void setLog( std::shared_ptr<std::ostream> target );
};
#include "db/database.h"
#include "crypto/sslUtil.h"
+#include "crypto/CRL.h"
class Signer {
public:
virtual std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert ) = 0;
- virtual std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial ) = 0;
+ virtual std::shared_ptr<CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial ) = 0;
};
[]( char* ref ) {
OPENSSL_free( ref );
} );
+
writeFile( prof.ca->path + "/serial", serStr.get() );
return std::pair<std::shared_ptr<BIGNUM>, std::string>( std::shared_ptr<BIGNUM>( BN_bin2bn( data.get(), len + 4 + 16 , 0 ), BN_free ), std::string( serStr.get() ) );
return output;
}
-
-std::shared_ptr<X509_CRL> SimpleOpensslSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
+std::shared_ptr<CRL> SimpleOpensslSigner::revoke( std::shared_ptr<CAConfig> ca, std::string serial ) {
std::string crlpath = ca->path + "/ca.crl";
- std::shared_ptr<BIO> bio( BIO_new_file( crlpath.c_str(), "r" ), free );
- std::shared_ptr<X509_CRL> crl( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free );
- std::cout << "Starting revocation" << std::endl;
-
- if( !crl ) {
- std::cout << "CRL was not loaded" << std::endl;
- crl = std::shared_ptr<X509_CRL>( X509_CRL_new(), X509_CRL_free );
- }
-
- BIGNUM* serBN = 0;
-
- if( ! BN_hex2bn( &serBN, serial.c_str() ) ) {
- //error
- }
-
- std::shared_ptr<BIGNUM> serBNP( serBN, BN_free );
- std::shared_ptr<ASN1_INTEGER> ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free );
-
- if( !ser ) {
- // error
- }
-
- std::shared_ptr<ASN1_TIME> tmptm( ASN1_TIME_new(), ASN1_TIME_free );
-
- if( !tmptm ) {
- // error
- }
-
- X509_gmtime_adj( tmptm.get(), 0 );
-
- X509_REVOKED* rev = X509_REVOKED_new();
- X509_REVOKED_set_serialNumber( rev, ser.get() );
- X509_REVOKED_set_revocationDate( rev, tmptm.get() );
-
- X509_CRL_add0_revoked( crl.get(), rev );
-
- if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) {
- // error
- }
-
- X509_CRL_set_lastUpdate( crl.get(), tmptm.get() );
-
- if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) {
- // error
- }
-
- X509_CRL_set_nextUpdate( crl.get(), tmptm.get() );
-
-
- std::cout << "Signing" << std::endl;
- X509_CRL_sort( crl.get() );
- X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() );
-
- std::cout << "writing bio" << std::endl;
- std::shared_ptr<BIO> bioOut( BIO_new_file( crlpath.c_str(), "w" ), BIO_free );
- PEM_write_bio_X509_CRL( bioOut.get(), crl.get() );
- std::cout << "finished crl" << std::endl;
+ std::shared_ptr<CRL> crl( new CRL( crlpath ) );
+ crl->revoke( serial, "" );
+ crl->sign( ca );
return crl;
}
#include "db/database.h"
#include "crypto/sslUtil.h"
#include "crypto/signer.h"
+#include "crypto/CRL.h"
class SimpleOpensslSigner : public Signer {
private:
SimpleOpensslSigner();
~SimpleOpensslSigner();
std::shared_ptr<SignedCertificate> sign( std::shared_ptr<TBSCertificate> cert );
- std::shared_ptr<X509_CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
+ std::shared_ptr<CRL> revoke( std::shared_ptr<CAConfig> ca, std::string serial );
};
auto reqCA = CAs.at( ca );
( *log ) << "CA found" << std::endl;
- std::shared_ptr<X509_CRL> crl = signer->revoke( reqCA, serial );
+ std::shared_ptr<CRL> crl = signer->revoke( reqCA, serial );
- std::shared_ptr<BIO> mem( BIO_new( BIO_s_mem() ), BIO_free );
-
- PEM_write_bio_X509_CRL( mem.get(), crl.get() );
- BUF_MEM* bptr;
- BIO_get_mem_ptr( mem.get(), &bptr );
-
- std::string newCRL( bptr->data, bptr->length );
- respondCommand( RecordHeader::SignerResult::REVOKED, newCRL );
+ respondCommand( RecordHeader::SignerResult::REVOKED, crl->toString() );
if( !SSL_shutdown( ssl.get() ) && !SSL_shutdown( ssl.get() ) ) {
( *log ) << "ERROR: SSL close failed" << std::endl;
openssl req -new -newkey rsa:2048 -nodes -subj "/CN=cn" -keyout testdata/server.key -out testdata/server.csr 2> /dev/null
openssl x509 -in testdata/server.csr -signkey testdata/server.key -req -out testdata/server.crt 2> /dev/null
+
+mkdir profiles
+cat > profiles/0001-type1.cfg <<EOF
+ca=unassured
+eku=
+ku=
+EOF
+
+mkdir -p ca/unassured
+cp testdata/server.key ca/unassured/ca.key
+cp testdata/server.crt ca/unassured/ca.crt
--- /dev/null
+#include "crypto/CRL.h"
+#include "config.h"
+
+#include <boost/test/unit_test.hpp>
+
+#include <iostream>
+#include <unordered_map>
+
+extern std::unordered_map<std::string, std::shared_ptr<CAConfig>> CAs;
+
+BOOST_AUTO_TEST_SUITE( TestCRL )
+BOOST_AUTO_TEST_CASE( SeperateSignature ) {
+ parseProfiles();
+ std::shared_ptr<CAConfig> ca = CAs.at( "unassured" );
+
+ CRL c( "" );
+ c.setSignature( c.getSignature() );
+ c.sign( ca );
+ std::string oldsig = c.getSignature();
+ BOOST_CHECK( c.verify( ca ) );
+ std::string date = c.revoke( "1234", "" );
+ BOOST_CHECK( !c.verify( ca ) );
+ c.sign( ca );
+ BOOST_CHECK( c.verify( ca ) );
+ std::string newsig = c.getSignature();
+ c.setSignature( oldsig );
+ BOOST_CHECK( !c.verify( ca ) );
+ c.setSignature( newsig );
+ BOOST_CHECK( c.verify( ca ) );
+
+ CRL c2( "" );
+ c2.sign( ca );
+
+ std::string date2 = c2.revoke( "1234", date );
+ BOOST_CHECK_EQUAL( date, date2 );
+ c2.setSignature( newsig );
+ BOOST_CHECK( c2.verify( ca ) );
+
+ BOOST_CHECK_EQUAL( c.toString(), c2.toString() );
+
+}
+
+BOOST_AUTO_TEST_SUITE_END()