Fixes for OpenSSL 1.1 support

The following tests currently fail due to what seems like different
behavior in OpenSSL 1.1 vs 1.0:

    scripts/base/protocols/rdp/rdp-x509.bro
    bifs/x509_verify.bro
This commit is contained in:
Jon Siwek 2018-06-29 15:58:53 -05:00
parent e33a3a9c02
commit 8f990036f6
5 changed files with 425 additions and 59 deletions

2
cmake

@ -1 +1 @@
Subproject commit 1600554d1d907f4f252f19cf1f55e13d368a936f Subproject commit 064bf442f22e72a2c15b3db6b7995189efaee982

View file

@ -21,7 +21,7 @@
// helper function of sk_X509_value to avoid namespace problem // helper function of sk_X509_value to avoid namespace problem
// sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y) // sk_X509_value(X,Y) = > SKM_sk_value(X509,X,Y)
// X509 => file_analysis::X509 // X509 => file_analysis::X509
X509 *helper_sk_X509_value(STACK_OF(X509) *certs, int i) X509* helper_sk_X509_value(const STACK_OF(X509)* certs, int i)
{ {
return sk_X509_value(certs, i); return sk_X509_value(certs, i);
} }
@ -42,38 +42,84 @@ static Val* get_ocsp_type(RecordVal* args, const char* name)
return rval; return rval;
} }
static void OCSP_RESPID_bio(OCSP_RESPID *resp_id, BIO* bio) static bool OCSP_RESPID_bio(OCSP_BASICRESP* basic_resp, BIO* bio)
{ {
if (resp_id->type == V_OCSP_RESPID_NAME) #if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
X509_NAME_print_ex(bio, resp_id->value.byName, 0, XN_FLAG_ONELINE); ASN1_OCTET_STRING* key = nullptr;
else if (resp_id->type == V_OCSP_RESPID_KEY) X509_NAME* name = nullptr;
i2a_ASN1_STRING(bio, resp_id->value.byKey, V_ASN1_OCTET_STRING);
if ( ! basic_resp->tbsResponseData )
return false;
auto resp_id = basic_resp->tbsResponseData->responderId;
if ( resp_id->type == V_OCSP_RESPID_NAME )
name = resp_id->value.byName;
else if ( resp_id->type == V_OCSP_RESPID_KEY )
key = resp_id->value.byKey;
else
return false;
#else
const ASN1_OCTET_STRING* key = nullptr;
const X509_NAME* name = nullptr;
if ( ! OCSP_resp_get0_id(basic_resp, &key, &name) )
return false;
#endif
if ( name )
X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE);
else
i2a_ASN1_STRING(bio, key, V_ASN1_OCTET_STRING);
return true;
} }
void ocsp_add_cert_id(OCSP_CERTID *cert_id, val_list* vl, BIO* bio) bool ocsp_add_cert_id(const OCSP_CERTID* cert_id, val_list* vl, BIO* bio)
{ {
ASN1_OBJECT* hash_alg = nullptr;
ASN1_OCTET_STRING* issuer_name_hash = nullptr;
ASN1_OCTET_STRING* issuer_key_hash = nullptr;
ASN1_INTEGER* serial_number = nullptr;
auto res = OCSP_id_get0_info(&issuer_name_hash, &hash_alg,
&issuer_key_hash, &serial_number,
const_cast<OCSP_CERTID*>(cert_id));
if ( ! res )
{
reporter->Weird("OpenSSL failed to get OCSP_CERTID info");
vl->append(new StringVal(""));
vl->append(new StringVal(""));
vl->append(new StringVal(""));
vl->append(new StringVal(""));
return false;
}
char buf[OCSP_STRING_BUF_SIZE]; char buf[OCSP_STRING_BUF_SIZE];
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
i2a_ASN1_OBJECT(bio, cert_id->hashAlgorithm->algorithm); i2a_ASN1_OBJECT(bio, hash_alg);
int len = BIO_read(bio, buf, sizeof(buf)); int len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
i2a_ASN1_STRING(bio, cert_id->issuerNameHash, V_ASN1_OCTET_STRING); i2a_ASN1_STRING(bio, issuer_name_hash, V_ASN1_OCTET_STRING);
len = BIO_read(bio, buf, sizeof(buf)); len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
i2a_ASN1_STRING(bio, cert_id->issuerKeyHash, V_ASN1_OCTET_STRING); i2a_ASN1_STRING(bio, issuer_key_hash, V_ASN1_OCTET_STRING);
len = BIO_read(bio, buf, sizeof(buf)); len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
i2a_ASN1_INTEGER(bio, cert_id->serialNumber); i2a_ASN1_INTEGER(bio, serial_number);
len = BIO_read(bio, buf, sizeof(buf)); len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
return true;
} }
file_analysis::Analyzer* OCSP::InstantiateRequest(RecordVal* args, File* file) file_analysis::Analyzer* OCSP::InstantiateRequest(RecordVal* args, File* file)
@ -124,6 +170,7 @@ bool file_analysis::OCSP::EndOfFile()
else else
{ {
OCSP_RESPONSE *resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size()); OCSP_RESPONSE *resp = d2i_OCSP_RESPONSE(NULL, &ocsp_char, ocsp_data.size());
if (!resp) if (!resp)
{ {
reporter->Weird(fmt("OPENSSL Could not parse OCSP response (fuid %s)", GetFile()->GetID().c_str())); reporter->Weird(fmt("OPENSSL Could not parse OCSP response (fuid %s)", GetFile()->GetID().c_str()));
@ -138,22 +185,262 @@ bool file_analysis::OCSP::EndOfFile()
return true; return true;
} }
void file_analysis::OCSP::ParseRequest(OCSP_REQUEST *req, const char* fid) #if ( OPENSSL_VERSION_NUMBER >= 0x10100000L )
// Re-encode and then parse out ASN1 structures to get at what we need...
/*- BasicOCSPResponse ::= SEQUENCE {
* tbsResponseData ResponseData,
* signatureAlgorithm AlgorithmIdentifier,
* signature BIT STRING,
* certs [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
typedef struct ocsp_basic_response_st {
OCSP_RESPDATA *tbsResponseData;
X509_ALGOR *signatureAlgorithm;
ASN1_BIT_STRING *signature;
STACK_OF(X509) *certs;
} OCSP_BASICRESP;
*/
static StringVal* parse_basic_resp_sig_alg(OCSP_BASICRESP* basic_resp,
BIO* bio, char* buf, size_t buf_len)
{ {
OCSP_REQINFO *inf = req->tbsRequest; int der_basic_resp_len = 0;
unsigned char* der_basic_resp_dat = nullptr;
der_basic_resp_len = i2d_OCSP_BASICRESP(basic_resp, &der_basic_resp_dat);
if ( der_basic_resp_len <= 0 )
return new StringVal("");
const unsigned char* const_der_basic_resp_dat = der_basic_resp_dat;
auto bseq = d2i_ASN1_SEQUENCE_ANY(nullptr, &const_der_basic_resp_dat,
der_basic_resp_len);
if ( ! bseq )
{
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
if ( sk_ASN1_TYPE_num(bseq) < 3 )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
auto constexpr sig_alg_idx = 1u;
auto aseq_type = sk_ASN1_TYPE_value(bseq, sig_alg_idx);
if ( ASN1_TYPE_get(aseq_type) != V_ASN1_SEQUENCE )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
auto aseq_str = aseq_type->value.asn1_string;
auto aseq_len = ASN1_STRING_length(aseq_str);
auto aseq_dat = ASN1_STRING_get0_data(aseq_str);
auto aseq = d2i_ASN1_SEQUENCE_ANY(nullptr, &aseq_dat, aseq_len);
if ( ! aseq )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
if ( sk_ASN1_TYPE_num(aseq) < 1 )
{
sk_ASN1_TYPE_free(aseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
auto constexpr alg_obj_idx = 0u;
auto alg_obj_type = sk_ASN1_TYPE_value(aseq, alg_obj_idx);
if ( ASN1_TYPE_get(alg_obj_type) != V_ASN1_OBJECT )
{
sk_ASN1_TYPE_free(aseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
auto alg_obj = alg_obj_type->value.object;
i2a_ASN1_OBJECT(bio, alg_obj);
auto alg_len = BIO_read(bio, buf, buf_len);
auto rval = new StringVal(alg_len, buf);
BIO_reset(bio);
sk_ASN1_TYPE_free(aseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return rval;
}
static Val* parse_basic_resp_data_version(OCSP_BASICRESP* basic_resp)
{
int der_basic_resp_len = 0;
unsigned char* der_basic_resp_dat = nullptr;
der_basic_resp_len = i2d_OCSP_BASICRESP(basic_resp, &der_basic_resp_dat);
if ( der_basic_resp_len <= 0 )
return new Val(-1, TYPE_COUNT);
const unsigned char* const_der_basic_resp_dat = der_basic_resp_dat;
auto bseq = d2i_ASN1_SEQUENCE_ANY(nullptr, &const_der_basic_resp_dat,
der_basic_resp_len);
if ( ! bseq )
{
OPENSSL_free(der_basic_resp_dat);
return new Val(-1, TYPE_COUNT);
}
if ( sk_ASN1_TYPE_num(bseq) < 3 )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new Val(-1, TYPE_COUNT);
}
auto constexpr resp_data_idx = 0u;
auto dseq_type = sk_ASN1_TYPE_value(bseq, resp_data_idx);
if ( ASN1_TYPE_get(dseq_type) != V_ASN1_SEQUENCE )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new Val(-1, TYPE_COUNT);
}
auto dseq_str = dseq_type->value.asn1_string;
auto dseq_len = ASN1_STRING_length(dseq_str);
auto dseq_dat = ASN1_STRING_get0_data(dseq_str);
auto dseq = d2i_ASN1_SEQUENCE_ANY(nullptr, &dseq_dat, dseq_len);
if ( ! dseq )
{
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
if ( sk_ASN1_TYPE_num(dseq) < 1 )
{
sk_ASN1_TYPE_free(dseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new StringVal("");
}
/*- ResponseData ::= SEQUENCE {
* version [0] EXPLICIT Version DEFAULT v1,
* responderID ResponderID,
* producedAt GeneralizedTime,
* responses SEQUENCE OF SingleResponse,
* responseExtensions [1] EXPLICIT Extensions OPTIONAL }
*/
auto constexpr version_idx = 0u;
auto version_type = sk_ASN1_TYPE_value(dseq, version_idx);
if ( ASN1_TYPE_get(version_type) != V_ASN1_INTEGER )
{
sk_ASN1_TYPE_free(dseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
// Not present, use default value.
return new Val(0, TYPE_COUNT);
}
uint64_t asn1_int = ASN1_INTEGER_get(version_type->value.integer);
sk_ASN1_TYPE_free(dseq);
sk_ASN1_TYPE_free(bseq);
OPENSSL_free(der_basic_resp_dat);
return new Val(asn1_int, TYPE_COUNT);
}
static uint64 parse_request_version(OCSP_REQUEST* req)
{
int der_req_len = 0;
unsigned char* der_req_dat = nullptr;
der_req_len = i2d_OCSP_REQUEST(req, &der_req_dat);
const unsigned char* const_der_req_dat = der_req_dat;
if ( ! der_req_dat )
return -1;
auto rseq = d2i_ASN1_SEQUENCE_ANY(nullptr, &const_der_req_dat,
der_req_len);
if ( ! rseq )
{
OPENSSL_free(der_req_dat);
return -1;
}
if ( sk_ASN1_TYPE_num(rseq) < 1 )
{
sk_ASN1_TYPE_free(rseq);
OPENSSL_free(der_req_dat);
return -1;
}
auto constexpr version_idx = 0u;
auto version_type = sk_ASN1_TYPE_value(rseq, version_idx);
if ( ASN1_TYPE_get(version_type) != V_ASN1_INTEGER )
{
sk_ASN1_TYPE_free(rseq);
OPENSSL_free(der_req_dat);
// Not present, use default value.
return 0;
}
uint64_t asn1_int = ASN1_INTEGER_get(version_type->value.integer);
sk_ASN1_TYPE_free(rseq);
OPENSSL_free(der_req_dat);
return asn1_int;
}
#endif
void file_analysis::OCSP::ParseRequest(OCSP_REQUEST* req, const char* fid)
{
char buf[OCSP_STRING_BUF_SIZE]; // we need a buffer for some of the openssl functions char buf[OCSP_STRING_BUF_SIZE]; // we need a buffer for some of the openssl functions
memset(buf, 0, sizeof(buf)); memset(buf, 0, sizeof(buf));
// build up our response as we go along... // build up our response as we go along...
val_list* vl = new val_list(); val_list* vl = new val_list();
vl->append(GetFile()->GetVal()->Ref()); vl->append(GetFile()->GetVal()->Ref());
vl->append(new Val((uint64)ASN1_INTEGER_get(inf->version), TYPE_COUNT));
uint64 version = 0;
GENERAL_NAME* general_name = nullptr;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
if ( req->tbsRequest->version )
version = (uint64)ASN1_INTEGER_get(req->tbsRequest->version);
general_name = req->tbsRequest->requestorName;
#else
version = parse_request_version(req);
// TODO: try to parse out general name ?
#endif
vl->append(new Val(version, TYPE_COUNT));
BIO *bio = BIO_new(BIO_s_mem()); BIO *bio = BIO_new(BIO_s_mem());
if (inf->requestorName != NULL) if ( general_name )
{ {
GENERAL_NAME_print(bio, inf->requestorName); GENERAL_NAME_print(bio, general_name);
int len = BIO_read(bio, buf, sizeof(buf)); int len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
@ -182,10 +469,12 @@ void file_analysis::OCSP::ParseRequest(OCSP_REQUEST *req, const char* fid)
void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid) void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
{ {
OCSP_RESPONSE *resp = resp_val->GetResp(); OCSP_RESPONSE *resp = resp_val->GetResp();
OCSP_RESPBYTES *resp_bytes = resp->responseBytes; //OCSP_RESPBYTES *resp_bytes = resp->responseBytes;
OCSP_BASICRESP *basic_resp = nullptr; OCSP_BASICRESP *basic_resp = nullptr;
OCSP_RESPDATA *resp_data = nullptr; OCSP_RESPDATA *resp_data = nullptr;
OCSP_RESPID *resp_id = nullptr; OCSP_RESPID *resp_id = nullptr;
const ASN1_GENERALIZEDTIME* produced_at = nullptr;
const STACK_OF(X509)* certs = nullptr;
int resp_count, num_ext = 0; int resp_count, num_ext = 0;
VectorVal *certs_vector = nullptr; VectorVal *certs_vector = nullptr;
@ -203,11 +492,11 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
mgr.QueueEvent(ocsp_response_status, vl); mgr.QueueEvent(ocsp_response_status, vl);
vl = nullptr; vl = nullptr;
if (!resp_bytes) //if (!resp_bytes)
{ // {
Unref(status_val); // Unref(status_val);
return; // return;
} // }
BIO *bio = BIO_new(BIO_s_mem()); BIO *bio = BIO_new(BIO_s_mem());
//i2a_ASN1_OBJECT(bio, resp_bytes->responseType); //i2a_ASN1_OBJECT(bio, resp_bytes->responseType);
@ -219,31 +508,53 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
if ( !basic_resp ) if ( !basic_resp )
goto clean_up; goto clean_up;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
resp_data = basic_resp->tbsResponseData; resp_data = basic_resp->tbsResponseData;
if ( !resp_data ) if ( !resp_data )
goto clean_up; goto clean_up;
#endif
vl = new val_list(); vl = new val_list();
vl->append(GetFile()->GetVal()->Ref()); vl->append(GetFile()->GetVal()->Ref());
vl->append(resp_val->Ref()); vl->append(resp_val->Ref());
vl->append(status_val); vl->append(status_val);
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
vl->append(new Val((uint64)ASN1_INTEGER_get(resp_data->version), TYPE_COUNT)); vl->append(new Val((uint64)ASN1_INTEGER_get(resp_data->version), TYPE_COUNT));
#else
vl->append(parse_basic_resp_data_version(basic_resp));
#endif
// responderID // responderID
resp_id = resp_data->responderId; if ( OCSP_RESPID_bio(basic_resp, bio) )
OCSP_RESPID_bio(resp_id, bio); {
len = BIO_read(bio, buf, sizeof(buf)); len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
}
else
{
reporter->Weird("OpenSSL failed to get OCSP responder id");
vl->append(new StringVal(""));
}
// producedAt // producedAt
vl->append(new Val(GetTimeFromAsn1(resp_data->producedAt, fid, reporter), TYPE_TIME)); #if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
produced_at = resp_data->producedAt;
#else
produced_at = OCSP_resp_get0_produced_at(basic_resp);
#endif
vl->append(new Val(GetTimeFromAsn1(produced_at, fid, reporter), TYPE_TIME));
// responses // responses
resp_count = sk_OCSP_SINGLERESP_num(resp_data->responses);
resp_count = OCSP_resp_count(basic_resp);
for ( int i=0; i<resp_count; i++ ) for ( int i=0; i<resp_count; i++ )
{ {
OCSP_SINGLERESP *single_resp = sk_OCSP_SINGLERESP_value(resp_data->responses, i); OCSP_SINGLERESP* single_resp = OCSP_resp_get0(basic_resp, i);
if ( !single_resp ) if ( !single_resp )
continue; continue;
@ -251,24 +562,41 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
rvl->append(GetFile()->GetVal()->Ref()); rvl->append(GetFile()->GetVal()->Ref());
// cert id // cert id
OCSP_CERTID *cert_id = single_resp->certId; const OCSP_CERTID* cert_id = nullptr;
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
cert_id = single_resp->certId;
#else
cert_id = OCSP_SINGLERESP_get0_id(single_resp);
#endif
ocsp_add_cert_id(cert_id, rvl, bio); ocsp_add_cert_id(cert_id, rvl, bio);
BIO_reset(bio); BIO_reset(bio);
// certStatus // certStatus
OCSP_CERTSTATUS *cert_status = single_resp->certStatus; int status = V_OCSP_CERTSTATUS_UNKNOWN;
const char* cert_status_str = OCSP_cert_status_str(cert_status->type); int reason = OCSP_REVOKED_STATUS_NOSTATUS;
ASN1_GENERALIZEDTIME* revoke_time = nullptr;
ASN1_GENERALIZEDTIME* this_update = nullptr;
ASN1_GENERALIZEDTIME* next_update = nullptr;
if ( ! OCSP_resp_find_status(basic_resp,
const_cast<OCSP_CERTID*>(cert_id),
&status, &reason, &revoke_time,
&this_update, &next_update) )
reporter->Weird("OpenSSL failed to find status of OCSP response");
const char* cert_status_str = OCSP_cert_status_str(status);
rvl->append(new StringVal(strlen(cert_status_str), cert_status_str)); rvl->append(new StringVal(strlen(cert_status_str), cert_status_str));
// revocation time and reason if revoked // revocation time and reason if revoked
if ( cert_status->type == V_OCSP_CERTSTATUS_REVOKED ) if ( status == V_OCSP_CERTSTATUS_REVOKED )
{ {
OCSP_REVOKEDINFO *revoked_info = cert_status->value.revoked; rvl->append(new Val(GetTimeFromAsn1(revoke_time, fid, reporter), TYPE_TIME));
rvl->append(new Val(GetTimeFromAsn1(revoked_info->revocationTime, fid, reporter), TYPE_TIME));
if ( revoked_info->revocationReason ) if ( reason != OCSP_REVOKED_STATUS_NOSTATUS )
{ {
const char* revoke_reason = OCSP_crl_reason_str(ASN1_ENUMERATED_get(revoked_info->revocationReason)); const char* revoke_reason = OCSP_crl_reason_str(reason);
rvl->append(new StringVal(strlen(revoke_reason), revoke_reason)); rvl->append(new StringVal(strlen(revoke_reason), revoke_reason));
} }
else else
@ -280,9 +608,13 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
rvl->append(new StringVal(0, "")); rvl->append(new StringVal(0, ""));
} }
rvl->append(new Val(GetTimeFromAsn1(single_resp->thisUpdate, fid, reporter), TYPE_TIME)); if ( this_update )
if ( single_resp->nextUpdate ) rvl->append(new Val(GetTimeFromAsn1(this_update, fid, reporter), TYPE_TIME));
rvl->append(new Val(GetTimeFromAsn1(single_resp->nextUpdate, fid, reporter), TYPE_TIME)); else
rvl->append(new Val(0, TYPE_TIME));
if ( next_update )
rvl->append(new Val(GetTimeFromAsn1(next_update, fid, reporter), TYPE_TIME));
else else
rvl->append(new Val(0, TYPE_TIME)); rvl->append(new Val(0, TYPE_TIME));
@ -299,10 +631,14 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
} }
} }
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
i2a_ASN1_OBJECT(bio, basic_resp->signatureAlgorithm->algorithm); i2a_ASN1_OBJECT(bio, basic_resp->signatureAlgorithm->algorithm);
len = BIO_read(bio, buf, sizeof(buf)); len = BIO_read(bio, buf, sizeof(buf));
vl->append(new StringVal(len, buf)); vl->append(new StringVal(len, buf));
BIO_reset(bio); BIO_reset(bio);
#else
vl->append(parse_basic_resp_sig_alg(basic_resp, bio, buf, sizeof(buf)));
#endif
//i2a_ASN1_OBJECT(bio, basic_resp->signature); //i2a_ASN1_OBJECT(bio, basic_resp->signature);
//len = BIO_read(bio, buf, sizeof(buf)); //len = BIO_read(bio, buf, sizeof(buf));
@ -311,13 +647,20 @@ void file_analysis::OCSP::ParseResponse(OCSP_RESPVal *resp_val, const char* fid)
certs_vector = new VectorVal(internal_type("x509_opaque_vector")->AsVectorType()); certs_vector = new VectorVal(internal_type("x509_opaque_vector")->AsVectorType());
vl->append(certs_vector); vl->append(certs_vector);
if ( basic_resp->certs )
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
certs = basic_resp->certs;
#else
certs = OCSP_resp_get0_certs(basic_resp);
#endif
if ( certs )
{ {
int num_certs = sk_X509_num(basic_resp->certs); int num_certs = sk_X509_num(certs);
for ( int i=0; i<num_certs; i++ ) for ( int i=0; i<num_certs; i++ )
{ {
::X509 *this_cert = X509_dup(helper_sk_X509_value(basic_resp->certs, i)); ::X509 *this_cert = X509_dup(helper_sk_X509_value(certs, i));
//::X509 *this_cert = X509_dup(sk_X509_value(basic_resp->certs, i)); //::X509 *this_cert = X509_dup(sk_X509_value(certs, i));
if (this_cert) if (this_cert)
certs_vector->Assign(i, new file_analysis::X509Val(this_cert)); certs_vector->Assign(i, new file_analysis::X509Val(this_cert));
else else

View file

@ -29,8 +29,8 @@ protected:
OCSP(RecordVal* args, File* file, bool request); OCSP(RecordVal* args, File* file, bool request);
private: private:
void ParseResponse(OCSP_RESPVal *, const char* fid = 0); void ParseResponse(OCSP_RESPVal*, const char* fid = 0);
void ParseRequest(OCSP_REQUEST *, const char* fid = 0); void ParseRequest(OCSP_REQUEST*, const char* fid = 0);
void ParseExtensionsSpecific(X509_EXTENSION* ex, bool, ASN1_OBJECT*, const char*) override; void ParseExtensionsSpecific(X509_EXTENSION* ex, bool, ASN1_OBJECT*, const char*) override;
std::string ocsp_data; std::string ocsp_data;

View file

@ -290,7 +290,11 @@ void file_analysis::X509::ParseSAN(X509_EXTENSION* ext)
continue; continue;
} }
#if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
const char* name = (const char*) ASN1_STRING_data(gen->d.ia5); const char* name = (const char*) ASN1_STRING_data(gen->d.ia5);
#else
const char* name = (const char*) ASN1_STRING_get0_data(gen->d.ia5);
#endif
StringVal* bs = new StringVal(name); StringVal* bs = new StringVal(name);
switch ( gen->type ) switch ( gen->type )

View file

@ -109,21 +109,36 @@ STACK_OF(X509)* x509_get_untrusted_stack(VectorVal* certs_vec)
// We need this function to be able to identify the signer certificate of an // We need this function to be able to identify the signer certificate of an
// OCSP request out of a list of possible certificates. // OCSP request out of a list of possible certificates.
X509* x509_get_ocsp_signer(STACK_OF(X509) *certs, OCSP_RESPID *rid) X509* x509_get_ocsp_signer(const STACK_OF(X509)* certs,
OCSP_BASICRESP* basic_resp)
{ {
// We support two lookup types - either by response id or by key. const ASN1_OCTET_STRING* key = nullptr;
if ( rid->type == V_OCSP_RESPID_NAME ) const X509_NAME* name = nullptr;
return X509_find_by_subject(certs, rid->value.byName);
// There only should be name and type - but let's be sure... #if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
if ( rid->type != V_OCSP_RESPID_KEY ) OCSP_RESPID* resp_id = basic_resp->tbsResponseData->responderId;
if ( resp_id->type == V_OCSP_RESPID_NAME )
name = resp_id->value.byName;
else if ( resp_id->type == V_OCSP_RESPID_KEY )
key = resp_id->value.byKey;
else
return 0; return 0;
#else
if ( ! OCSP_resp_get0_id(basic_resp, &key, &name) )
return 0;
#endif
if ( name )
return X509_find_by_subject(const_cast<STACK_OF(X509)*>(certs),
const_cast<X509_NAME*>(name));
// Just like OpenSSL, we just support SHA-1 lookups and bail out otherwhise. // Just like OpenSSL, we just support SHA-1 lookups and bail out otherwhise.
if ( rid->value.byKey->length != SHA_DIGEST_LENGTH ) if ( key->length != SHA_DIGEST_LENGTH )
return 0; return 0;
unsigned char* key_hash = rid->value.byKey->data; unsigned char* key_hash = key->data;
for ( int i = 0; i < sk_X509_num(certs); ++i ) for ( int i = 0; i < sk_X509_num(certs); ++i )
{ {
unsigned char digest[SHA_DIGEST_LENGTH]; unsigned char digest[SHA_DIGEST_LENGTH];
@ -328,15 +343,19 @@ function x509_ocsp_verify%(certs: x509_opaque_vector, ocsp_reply: string, root_c
// Because we actually want to be able to give nice error messages that show why we were // Because we actually want to be able to give nice error messages that show why we were
// not able to verify the OCSP response - do our own verification logic first. // not able to verify the OCSP response - do our own verification logic first.
signer = x509_get_ocsp_signer(basic->certs, basic->tbsResponseData->responderId); #if ( OPENSSL_VERSION_NUMBER < 0x10100000L )
signer = x509_get_ocsp_signer(basic->certs, basic);
#else
signer = x509_get_ocsp_signer(OCSP_resp_get0_certs(basic), basic);
#endif
/* /*
Do this perhaps - OpenSSL also cannot do it, so I do not really feel bad about it. Do this perhaps - OpenSSL also cannot do it, so I do not really feel bad about it.
Needs a different lookup because the root store is no stack of X509 certs Needs a different lookup because the root store is no stack of X509 certs
if ( !s igner ) if ( ! signer )
// if we did not find it in the certificates that were sent, search in the root store // if we did not find it in the certificates that were sent, search in the root store
signer = x509_get_ocsp_signer(ocsp_certs, basic->tbsResponseData->responderId); signer = x509_get_ocsp_signer(ocsp_certs, basic);
*/ */
if ( ! signer ) if ( ! signer )