X-Git-Url: https://code.wpia.club/?a=blobdiff_plain;f=src%2Fcrypto%2FX509.cpp;h=e304b908abb5a8d0cee172f62961e9697ac25df5;hb=6121035a7d8ea738bc89c2de8e6602fb1099b0e2;hp=ba39b4bcef68287bd15ef8ce5247c44b853f6ccd;hpb=cb4c74b47e6643f15e503067c197f86cbc5e6263;p=cassiopeia.git diff --git a/src/crypto/X509.cpp b/src/crypto/X509.cpp index ba39b4b..e304b90 100644 --- a/src/crypto/X509.cpp +++ b/src/crypto/X509.cpp @@ -7,12 +7,11 @@ #include #include -X509Req::X509Req( X509_REQ* csr ) { - req = std::shared_ptr( csr, X509_REQ_free ); +X509Req::X509Req( X509_REQ* csr ) : req( csr, X509_REQ_free ) { EVP_PKEY* pkt = X509_REQ_get_pubkey( req.get() ); if( !pkt ) { - throw "Error extracting public key"; + throw std::runtime_error( "Error extracting public key" ); } pk = std::shared_ptr( pkt, EVP_PKEY_free ); @@ -20,21 +19,21 @@ X509Req::X509Req( X509_REQ* csr ) { X509Req::X509Req( std::string spkac ) { if( spkac.compare( 0, 6, "SPKAC=" ) != 0 ) { - throw "Error: not a SPKAC"; + throw std::runtime_error( "Error: not a SPKAC" ); } spkac = spkac.substr( 6 ); NETSCAPE_SPKI* spki_p = NETSCAPE_SPKI_b64_decode( spkac.c_str(), spkac.size() ); if( !spki_p ) { - throw "Error: decode failed"; + throw std::runtime_error( "Error: decode failed" ); } spki = std::shared_ptr( spki_p, NETSCAPE_SPKI_free ); EVP_PKEY* pkt_p = NETSCAPE_SPKI_get_pubkey( spki.get() ); if( !pkt_p ) { - throw "Error: reading SPKAC Pubkey failed"; + throw std::runtime_error( "Error: reading SPKAC Pubkey failed" ); } pk = std::shared_ptr( pkt_p, EVP_PKEY_free ); @@ -48,7 +47,7 @@ int X509Req::verify() { return X509_REQ_verify( req.get(), pk.get() ); } -std::shared_ptr X509Req::getPkey() { +std::shared_ptr X509Req::getPkey() const { return pk; } @@ -57,10 +56,10 @@ std::shared_ptr X509Req::parseCSR( std::string content ) { X509_REQ* req = PEM_read_bio_X509_REQ( in.get(), NULL, NULL, NULL ); if( !req ) { - throw "Error parsing CSR"; + throw std::runtime_error( "Error parsing CSR" ); } - return std::shared_ptr( new X509Req( req ) ); + return std::shared_ptr( new X509Req( req ) ); // TODO ask } std::shared_ptr X509Req::parseSPKAC( std::string content ) { @@ -95,19 +94,19 @@ X509Cert::X509Cert() { X509* c = X509_new(); if( !c ) { - throw "malloc failed"; + throw std::runtime_error( "malloc failed" ); } target = std::shared_ptr( c, X509_free ); if( !X509_set_version( c, 2 ) ) { - throw "Setting X509-version to 3 failed"; + throw std::runtime_error( "Setting X509-version to 3 failed" ); } X509_NAME* subjectP = X509_NAME_new(); if( !subjectP ) { - throw "malloc failure"; + throw std::runtime_error( "malloc failure in construct." ); } subject = std::shared_ptr( subjectP, X509_NAME_free ); @@ -115,13 +114,13 @@ X509Cert::X509Cert() { void X509Cert::addRDN( int nid, std::string data ) { if( ! X509_NAME_add_entry_by_NID( subject.get(), nid, MBSTRING_UTF8, ( unsigned char* )const_cast( data.data() ), data.size(), -1, 0 ) ) { - throw "malloc failure"; + throw std::runtime_error( "malloc failure in RDN" ); } } void X509Cert::setIssuerNameFrom( std::shared_ptr caCert ) { if( !X509_set_issuer_name( target.get(), X509_get_subject_name( caCert.get() ) ) ) { - throw "Error setting Issuer name"; + throw std::runtime_error( "Error setting Issuer name" ); } } @@ -129,12 +128,14 @@ void X509Cert::setPubkeyFrom( std::shared_ptr req ) { std::shared_ptr pktmp = req->getPkey(); if( !X509_set_pubkey( target.get(), pktmp.get() ) ) { - throw "Setting public key failed."; + throw std::runtime_error( "Setting public key failed." ); } } void X509Cert::setSerialNumber( BIGNUM* num ) { - BN_to_ASN1_INTEGER( num , target->cert_info->serialNumber ); + ASN1_INTEGER *i = BN_to_ASN1_INTEGER( num, NULL); + X509_set_serialNumber( target.get(), i ); + ASN1_INTEGER_free( i ); } void X509Cert::setTimes( uint32_t before, uint32_t after ) { @@ -155,7 +156,7 @@ static X509_EXTENSION* do_ext_i2d( int ext_nid, int crit, ASN1_VALUE* ext_struc goto merr; } - if( !( ext_oct = M_ASN1_OCTET_STRING_new() ) ) { + if( !( ext_oct = ASN1_OCTET_STRING_new() ) ) { goto merr; } @@ -168,24 +169,24 @@ static X509_EXTENSION* do_ext_i2d( int ext_nid, int crit, ASN1_VALUE* ext_struc goto merr; } - M_ASN1_OCTET_STRING_free( ext_oct ); + ASN1_OCTET_STRING_free( ext_oct ); return ext; merr: - throw "memerr"; + throw std::runtime_error( "memerr" ); } -void X509Cert::setExtensions( std::shared_ptr caCert, std::vector>& sans, Profile& prof ) { +void X509Cert::setExtensions( std::shared_ptr caCert, std::vector>& sans, Profile& prof, std::string crlURL, std::string crtURL ) { add_ext( caCert, target, NID_basic_constraints, "critical,CA:FALSE" ); add_ext( caCert, target, NID_subject_key_identifier, "hash" ); - add_ext( caCert, target, NID_authority_key_identifier, "keyid,issuer:always" ); + add_ext( caCert, target, NID_authority_key_identifier, "keyid:always" ); std::string ku = std::string( "critical," ) + prof.ku; add_ext( caCert, target, NID_key_usage, ku.c_str() ); add_ext( caCert, target, NID_ext_key_usage, prof.eku.c_str() ); - add_ext( caCert, target, NID_info_access, "OCSP;URI:http://ocsp.cacert.org" ); - add_ext( caCert, target, NID_crl_distribution_points, "URI:http://crl.cacert.org/class3-revoke.crl" ); + add_ext( caCert, target, NID_info_access, ( "OCSP;URI:http://ocsp.cacert.org,caIssuers;URI:" + crtURL ).c_str() ); + add_ext( caCert, target, NID_crl_distribution_points, ( "URI:" + crlURL ).c_str() ); - if( sans.size() == 0 ) { + if( sans.empty() ) { return; } @@ -201,16 +202,16 @@ void X509Cert::setExtensions( std::shared_ptr caCert, std::vectortype = name->type == "DNS" ? GEN_DNS : name->type == "email" ? GEN_EMAIL : 0; // GEN_EMAIL; if( !gen->type - || !( gen->d.ia5 = M_ASN1_IA5STRING_new() ) + || !( gen->d.ia5 = ASN1_IA5STRING_new() ) || !ASN1_STRING_set( gen->d.ia5, name->content.data(), name->content.size() ) ) { GENERAL_NAME_free( gen ); - throw "initing iasting5 failed"; + throw std::runtime_error( "initing iasting5 failed" ); } sk_GENERAL_NAME_push( gens.get(), gen ); @@ -224,7 +225,7 @@ void X509Cert::setExtensions( std::shared_ptr caCert, std::vector X509Cert::sign( std::shared_ptr caKey, std::string signAlg ) { if( !X509_set_subject_name( target.get(), subject.get() ) ) { - throw "error setting subject"; + throw std::runtime_error( "error setting subject" ); } const EVP_MD* md; @@ -236,27 +237,45 @@ std::shared_ptr X509Cert::sign( std::shared_ptr caK } else if( signAlg == "sha256" ) { md = EVP_sha256(); } else if( signAlg == "sha1" ) { - md = EVP_sha1(); + throw std::runtime_error( "Refusing to sign with weak signature algorithm (SHA-1)." ); + } else if( signAlg == "md5" ) { + throw std::runtime_error( "Refusing to sign with weak signature algorithm (MD5)." ); } else { - throw "Unknown md-type"; + throw std::runtime_error( "Unknown signature algorithm" ); } if( !X509_sign( target.get(), caKey.get(), md ) ) { - throw "Signing failed."; + throw std::runtime_error( "Signing failed." ); } //X509_print_fp( stdout, target.get() ); std::shared_ptr mem = std::shared_ptr( BIO_new( BIO_s_mem() ), BIO_free ); + + if( !mem ) { + throw std::runtime_error( "Failed to allocate memory for the signed certificate." ); + } + PEM_write_bio_X509( mem.get(), target.get() ); - BUF_MEM* buf; + + BUF_MEM* buf = NULL; BIO_get_mem_ptr( mem.get(), &buf ); - std::shared_ptr res = std::shared_ptr( new SignedCertificate() ); + + auto res = std::make_shared(); res->certificate = std::string( buf->data, buf->data + buf->length ); - BIGNUM* ser = ASN1_INTEGER_to_BN( target->cert_info->serialNumber, NULL ); - char* serStr = BN_bn2hex( ser ); - res->serial = std::string( serStr ); - OPENSSL_free( serStr ); - BN_free( ser ); + + std::shared_ptr ser( ASN1_INTEGER_to_BN( X509_get_serialNumber( target.get() ), NULL ), BN_free ); + + if( !ser ) { + throw std::runtime_error( "Failed to retrieve certificate serial of signed certificate." ); + } + + std::shared_ptr serStr( + BN_bn2hex( ser.get() ), + []( char* p ) { + OPENSSL_free( p ); + } ); // OPENSSL_free is a macro... + res->serial = serStr ? std::string( serStr.get() ) : ""; + return res; }