X-Git-Url: https://code.wpia.club/?a=blobdiff_plain;f=src%2Fcrypto%2FsimpleOpensslSigner.cpp;h=fa51a9e1ccd85c5c086a323b439c9779d9ea3338;hb=2fc4b5f8d5400f6ebd284a0e6fbaad23a345b585;hp=cd02a969d6553c2441f8889a55f645af089b7606;hpb=9e866a1a2facc8cb1565cd660c6b6d482f18ecb1;p=cassiopeia.git diff --git a/src/crypto/simpleOpensslSigner.cpp b/src/crypto/simpleOpensslSigner.cpp index cd02a96..fa51a9e 100644 --- a/src/crypto/simpleOpensslSigner.cpp +++ b/src/crypto/simpleOpensslSigner.cpp @@ -1,6 +1,5 @@ #include "simpleOpensslSigner.h" -#include #include #include @@ -11,6 +10,8 @@ #include #include +#include "log/logger.hpp" + #include "X509.h" #include "util.h" #include "sslUtil.h" @@ -25,20 +26,20 @@ SimpleOpensslSigner::SimpleOpensslSigner() { SimpleOpensslSigner::~SimpleOpensslSigner() { } -std::pair, std::string> SimpleOpensslSigner::nextSerial( Profile& prof ) { +std::pair, std::string> SimpleOpensslSigner::nextSerial( Profile& prof, std::shared_ptr ca ) { uint16_t profile = prof.id; - std::string res = readFile( prof.ca->path + "/serial" ); + std::string res = readFile( ca->path + "/serial" ); BIGNUM* bn = 0; if( res == "" ) { bn = BN_new(); - if( !bn ) { + if( !bn || !BN_hex2bn( &bn, "1" )) { throw "Initing serial failed"; } } else { - if( !BN_hex2bn( &bn, res.c_str() + 1 ) ) { + if( !BN_hex2bn( &bn, res.c_str() ) ) { throw "Parsing serial failed."; } } @@ -55,7 +56,7 @@ std::pair, std::string> SimpleOpensslSigner::nextSerial( data.get()[len + 3] = profile & 0xFF; // profile id if( !RAND_bytes( data.get() + len + 4, 16 ) || !BN_add_word( serial.get(), 1 ) ) { - throw "Big number math failed while calcing serials."; + throw "Big number math failed while fetching random data for serial number."; } std::shared_ptr serStr = std::shared_ptr( @@ -63,26 +64,35 @@ std::pair, std::string> SimpleOpensslSigner::nextSerial( []( char* ref ) { OPENSSL_free( ref ); } ); - writeFile( prof.ca->path + "/serial", serStr.get() ); + + writeFile( ca->path + "/serial", serStr.get() ); return std::pair, std::string>( std::shared_ptr( BN_bin2bn( data.get(), len + 4 + 16 , 0 ), BN_free ), std::string( serStr.get() ) ); } std::shared_ptr SimpleOpensslSigner::sign( std::shared_ptr cert ) { std::stringstream signlog; + logger::logger_set log_set_sign({logger::log_target(signlog, logger::level::debug)}, logger::auto_register::on); - signlog << "FINE: profile is " << cert->profile << std::endl; + logger::note( "FINE: Profile name is: ", cert->profile ); Profile& prof = profiles.at( cert->profile ); + logger::note( "FINE: Profile ID is: ", prof.id ); + + std::shared_ptr ca = prof.getCA(); - if( !prof.ca ) { + if( !ca ) { + logger::error( "ERROR: Signing CA specified in profile could not be loaded." ); throw "CA-key not found"; } - signlog << "FINE: CA-key is correctly loaded." << std::endl; - signlog << "FINE: Profile id is: " << prof.id << std::endl; - signlog << "FINE: ku is: " << prof.ku << std::endl; - signlog << "FINE: eku is: " << prof.eku << std::endl; + logger::note( "FINE: Key for Signing CA is correctly loaded." ); + + logger::note( "INFO: Baseline Key Usage is: ", prof.ku ); + logger::note( "INFO: Extended Key Usage is: ", prof.eku ); + + logger::note( "FINE: Signing is wanted by: ", cert->wishFrom ); + logger::note( "FINE: Signing is wanted for: ", cert->wishTo ); std::shared_ptr req; @@ -91,37 +101,31 @@ std::shared_ptr SimpleOpensslSigner::sign( std::shared_ptrcsr_type == "CSR" ) { req = X509Req::parseCSR( cert->csr_content ); } else { - throw "Error, unknown REQ rype " + ( cert->csr_type ); + logger::errorf( "ERROR: Unknown type (\"%s\") of certification in request.", cert->csr_type ); + throw "Error, unknown REQ rype " + ( cert->csr_type ); //! \fixme: Pointer instead of string, please use proper exception classes } int i = req->verify(); if( i < 0 ) { - throw "Signature problems ... "; + throw "Request contains a Signature with problems ... "; } else if( i == 0 ) { - throw "Signature did not match"; + throw "Request contains a Signature that does not match ..."; } else { - signlog << "FINE: Signature ok" << std::endl; + logger::note( "FINE: Request contains valid self-signature." ); } // Construct the Certificate X509Cert c = X509Cert(); - std::shared_ptr retsh = std::shared_ptr( X509_new(), X509_free ); - X509* ret = retsh.get(); - if( !ret ) { - throw "Creating X509 failed."; - } - - X509_NAME* subjectP = X509_NAME_new(); - - if( !subjectP ) { - throw "malloc failure"; - } + logger::note( "INFO: Populating RDN ..." ); for( std::shared_ptr a : cert->AVAs ) { - signlog << "Addings RDN: " << a->name << ": " << a->value << std::endl; - + logger::notef( "INFO: Trying to add RDN: %s: %s", a->name, a->value ); + if( a-> value == "") { + logger::notef( "INFO: Removing empty RDN: %s", a->name); + continue; + } if( a->name == "CN" ) { c.addRDN( NID_commonName, a->value ); } else if( a->name == "EMAIL" ) { @@ -137,89 +141,136 @@ std::shared_ptr SimpleOpensslSigner::sign( std::shared_ptrname == "OU" ) { c.addRDN( NID_organizationalUnitName, a->value ); } else { - throw "unknown AVA-type"; + logger::error( "ERROR: Trying to add illegal RDN/AVA type: ", a->name ); + throw "Unhandled/Illegal AVA type"; } } - c.setIssuerNameFrom( prof.ca->ca ); - c.setPubkeyFrom( req ); - - std::shared_ptr ser; - std::string num; - std::tie( ser, num ) = nextSerial( prof ); - c.setSerialNumber( ser.get() ); - c.setTimes( 0, 60 * 60 * 24 * 10 ); - signlog << "FINE: Setting extensions." << std::endl; - c.setExtensions( prof.ca->ca, cert->SANs, prof ); - signlog << "FINE: Signed" << std::endl; - std::shared_ptr output = c.sign( prof.ca->caKey, cert->md ); - signlog << "FINE: all went well" << std::endl; - signlog << "FINE: crt went to: " << writeBackFile( num, output->certificate, prof.ca->path ) << std::endl; - output->log = signlog.str(); - return output; -} + logger::note( "INFO: Populating Issuer ..." ); + c.setIssuerNameFrom( ca->ca ); + logger::note( "INFO: Validating Public key for use in certificate" ); + logger::note( "INFO: - Checking generic key parameters" ); + logger::note( "FINE: ->Public Key parameters are okay" ); -std::shared_ptr SimpleOpensslSigner::revoke( std::shared_ptr ca, std::string serial ) { - std::string crlpath = ca->path + "/ca.crl"; + logger::note( "INFO: - Checking blacklists" ); + logger::note( "FINE: ->Does not appear on any blacklist" ); - std::shared_ptr bio( BIO_new_file( crlpath.c_str(), "r" ), free ); - std::shared_ptr crl( PEM_read_bio_X509_CRL( bio.get(), 0, NULL, 0 ), X509_CRL_free ); - std::cout << "Starting revocation" << std::endl; + logger::note( "INFO: - Checking trivial factorization" ); + logger::note( "FINE: ->Trivial factorization not possible" ); - if( !crl ) { - std::cout << "CRL was not loaded" << std::endl; - crl = std::shared_ptr( X509_CRL_new(), X509_CRL_free ); - } + logger::note( "INFO: - Checking astrological signs" ); + logger::note( "FINE: ->The stars look good for this one" ); + logger::note( "FINE: Public key is fine for use in certificate" ); - BIGNUM* serBN = 0; + logger::note( "INFO: Copying Public Key from Request ..." ); + c.setPubkeyFrom( req ); + logger::note( "FINE: Public Key successfully copied from Request." ); + + { + logger::note( "INFO: Determining Validity Period ..." ); + std::time_t from, to; + std::time_t now = time( 0 ); + std::pair parsed; + + if( ( parsed = parseDate( cert->wishFrom ) ).first /* is of yyyy-mm-dd */ ) { + if( parsed.second > now ) { + from = parsed.second; + } else { // fail + from = now; + } + } else { + from = now; + } - if( ! BN_hex2bn( &serBN, serial.c_str() ) ) { - //error - } + if( ( ( from - now ) > /* 2 Weeks */ ( 2 * 7 * 24 * 60 * 60 ) ) || ( ( now - from ) >= 0 ) ) { + from = now; + } - std::shared_ptr serBNP( serBN, BN_free ); - std::shared_ptr ser( BN_to_ASN1_INTEGER( serBN, NULL ), ASN1_INTEGER_free ); + if( ( parsed = parseDate( cert->wishTo ) ).first /*is of yyyy-mm-dd */ ) { + if( parsed.second > from ) { + to = parsed.second; + } else { + to = from + /*2 Years */ 2 * 365 * 24 * 60 * 60; + } + } else if( ( parsed = parseYearInterval( from, cert->wishTo ) ).first /*is of [0-9]+y */ ) { + to = parsed.second; + } else if( ( parsed = parseMonthInterval( from, cert->wishTo ) ).first /*is of [0-9]+m */ ) { + to = parsed.second; + } else { + to = from + /*2 Years */ 2 * 365 * 24 * 60 * 60; + } - if( !ser ) { - // error - } + time_t limit = prof.maxValidity; - std::shared_ptr tmptm( ASN1_TIME_new(), ASN1_TIME_free ); + if( ( to - from > limit ) || ( to - from < 0 ) ) { + to = from + limit; + } - if( !tmptm ) { - // error + c.setTimes( from, to ); + logger::note( "FINE: Setting validity period successful:" ); + { + struct tm* timeobj; + std::vector timebuf; + + timeobj = gmtime( &from ); + timebuf.resize( 128 ); + timebuf.resize( std::strftime( const_cast( timebuf.data() ), timebuf.size(), "%F %T %Z", timeobj ) ); + logger::note( "FINE: - Valid not before: ", std::string( timebuf.cbegin(), timebuf.cend() ) ); + + timeobj = gmtime( &to ); + timebuf.resize( 128 ); + timebuf.resize( std::strftime( const_cast( timebuf.data() ), timebuf.size(), "%F %T %Z", timeobj ) ); + logger::note( "FINE: - Valid not after: ", std::string( timebuf.cbegin(), timebuf.cend() ) ); + } } - X509_gmtime_adj( tmptm.get(), 0 ); + logger::note( "INFO: Setting extensions:" ); + c.setExtensions( ca->ca, cert->SANs, prof, ca->crlURL, ca->crtURL ); + logger::note( "FINE: Setting extensions successful." ); - X509_REVOKED* rev = X509_REVOKED_new(); - X509_REVOKED_set_serialNumber( rev, ser.get() ); - X509_REVOKED_set_revocationDate( rev, tmptm.get() ); + logger::note( "INFO: Generating next Serial Number ..." ); + std::shared_ptr ser; + std::string num; + std::tie( ser, num ) = nextSerial( prof, ca ); + c.setSerialNumber( ser.get() ); + logger::note( "FINE: Certificate Serial Number set to: ", num ); - X509_CRL_add0_revoked( crl.get(), rev ); + { + logger::note( "INFO: Trying to sign Certificate:" ); + std::shared_ptr output = c.sign( ca->caKey, cert->md ); + logger::note( "INFO: Writing certificate to local file." ); + std::string fn = writeBackFile( num, output->certificate, ca->path ); - if( !X509_CRL_set_issuer_name( crl.get(), X509_get_subject_name( ca->ca.get() ) ) ) { - // error - } + if( fn.empty() ) { + logger::error( "ERROR: failed to get filename for storage of signed certificate." ); + throw "Storage location could not be determined"; + } - X509_CRL_set_lastUpdate( crl.get(), tmptm.get() ); + logger::note( "FINE: Certificate signed successfully." ); + logger::note( "FINE: - Certificate written to: ", fn ); - if( !X509_time_adj_ex( tmptm.get(), 1, 10, NULL ) ) { - // error + output->ca_name = ca->name; + output->log = signlog.str(); + return output; } +} - X509_CRL_set_nextUpdate( crl.get(), tmptm.get() ); - +std::pair, std::string> SimpleOpensslSigner::revoke( std::shared_ptr ca, std::vector serials ) { + logger::note( "revoking" ); + std::string crlpath = ca->path + "/ca.crl"; - std::cout << "Signing" << std::endl; - X509_CRL_sort( crl.get() ); - X509_CRL_sign( crl.get(), ca->caKey.get(), EVP_sha256() ); + auto crl = std::make_shared( crlpath ); + std::string date = ""; - std::cout << "writing bio" << std::endl; - std::shared_ptr 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; + logger::note( "adding serials" ); + for( std::string serial : serials ) { + date = crl->revoke( serial, "" ); + } - return crl; + logger::note( "signing CRL" ); + crl->sign( ca ); + writeFile( crlpath, crl->toString() ); + logger::note( "wrote CRL" ); + return std::pair, std::string>( crl, date ); }