unit-tests: Update test_serial_gen suite

This commit is contained in:
Andreas Steffen 2023-06-15 16:39:25 +02:00 committed by Tobias Brunner
parent 00ab8d62c0
commit a0f672d3d1

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2022 Andreas Steffen, strongSec GmbH
* Copyright (C) 2022-2023 Andreas Steffen, strongSec GmbH
*
* Copyright (C) secunet Security Networks AG
*
@ -18,7 +18,9 @@
#include <credentials/certificates/x509.h>
#include <credentials/certificates/crl.h>
#include <credentials/certificates/ocsp_request.h>
#include <credentials/certificates/ocsp_response.h>
#include <credentials/certificates/ocsp_single_response.h>
#include <credentials/certificates/ac.h>
#include <time.h>
@ -182,6 +184,83 @@ static certificate_t* create_ocsp_request(certificate_t *cert)
return ocsp_req;
}
/**
* Parse an ASN.1 encoded OCSP request
*/
static certificate_t* parse_ocsp_request(chunk_t encoding)
{
certificate_t *ocsp_req;
ocsp_req = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509_OCSP_REQUEST,
BUILD_BLOB_ASN1_DER, encoding,
BUILD_END);
ck_assert(ocsp_req);
return ocsp_req;
}
/**
* Create an OCSP response based on an OCSP request
*/
static certificate_t* create_ocsp_response(ocsp_request_t *ocsp_request,
cert_validation_t status,
certificate_t *cert)
{
private_key_t *privkey;
certificate_t *ocsp_rsp;
ocsp_status_t ocsp_status = OCSP_SUCCESSFUL;
ocsp_single_response_t *response;
chunk_t issuerNameHash, issuerKeyHash, serialNumber, nonce;
hash_algorithm_t hashAlgorithm;
linked_list_t *responses = linked_list_create();
enumerator_t *enumerator;
privkey = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_BLOB_ASN1_DER, chunk_from_thing(keydata),
BUILD_END);
ck_assert(privkey);
/* generate OCSP single response */
enumerator = ocsp_request->create_request_enumerator(ocsp_request);
ck_assert(enumerator->enumerate(enumerator, &hashAlgorithm, &issuerNameHash,
&issuerKeyHash, &serialNumber));
response = ocsp_single_response_create();
response->hashAlgorithm = hashAlgorithm;
response->issuerNameHash = chunk_clone(issuerNameHash);
response->issuerKeyHash = chunk_clone(issuerKeyHash);
response->serialNumber = chunk_clone(serialNumber);
response->thisUpdate = time(NULL);
response->status = status;
if (status == VALIDATION_REVOKED)
{
response->revocationReason = CRL_REASON_KEY_COMPROMISE;
response->revocationTime = time(NULL);
}
responses->insert_last(responses, response);
enumerator->destroy(enumerator);
nonce = ocsp_request->get_nonce(ocsp_request);
/* generate OCSP response */
enumerator = responses->create_enumerator(responses);
ocsp_rsp = lib->creds->create(lib->creds, CRED_CERTIFICATE,
CERT_X509_OCSP_RESPONSE,
BUILD_OCSP_STATUS, ocsp_status,
BUILD_OCSP_RESPONSES, enumerator,
BUILD_SIGNING_KEY, privkey,
BUILD_SIGNING_CERT, cert,
BUILD_NONCE, nonce,
BUILD_END);
enumerator->destroy(enumerator);
ck_assert(ocsp_rsp);
privkey->destroy(privkey);
responses->destroy_offset(responses, offsetof(ocsp_single_response_t, destroy));
return ocsp_rsp;
}
/**
* Parse an ASN.1 encoded OCSP response
*/
@ -290,72 +369,22 @@ static serial_number_t serial_numbers[] = {
chunk_from_chars(0x05,0x00,0xff,0xff,0xff,0xff) },
};
static chunk_t ocsp_responses[] = {
chunk_from_chars(
0x30,0x82,0x01,0x85,0x0a,0x01,0x00,0xa0,0x82,0x01,0x7e,0x30,0x82,0x01,0x7a,0x06,
0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0x6b,0x30,0x82,
0x01,0x67,0x30,0x81,0xd1,0xa1,0x33,0x30,0x31,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,
0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0d,0x30,0x0b,0x06,
0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x18,0x0f,0x32,0x30,0x32,0x32,
0x31,0x31,0x32,0x32,0x30,0x39,0x31,0x36,0x34,0x37,0x5a,0x30,0x64,0x30,0x62,0x30,
0x3a,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0xbd,0x25,
0xa0,0xdf,0xc3,0x21,0xf2,0xd8,0xed,0x19,0x63,0x0a,0x4b,0x90,0x6d,0xc3,0x0f,0xe7,
0x79,0x20,0x04,0x14,0xe2,0x6d,0x1e,0xdf,0x83,0x8e,0xa2,0x1f,0xc3,0x00,0xdd,0x44,
0x6f,0x8a,0x4d,0x70,0x0c,0x02,0xe3,0x1f,0x02,0x01,0x7f,0x80,0x00,0x18,0x0f,0x32,
0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x30,0x39,0x31,0x36,0x34,0x37,0x5a,0xa0,0x11,
0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x31,0x39,0x31,0x36,0x34,0x37,
0x5a,0xa1,0x23,0x30,0x21,0x30,0x1f,0x06,0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,
0x01,0x02,0x04,0x12,0x04,0x10,0x86,0x45,0x82,0x11,0xe6,0x62,0x43,0x83,0xbc,0x01,
0xe4,0x5c,0x48,0x87,0xcd,0x2e,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
0x01,0x01,0x0b,0x05,0x00,0x03,0x81,0x81,0x00,0x42,0x32,0xa9,0x24,0x97,0x8c,0xc5,
0x35,0x37,0xe7,0x14,0xf0,0x84,0x7e,0x69,0xf1,0x99,0xf8,0xf0,0x02,0x7d,0xe4,0xd8,
0x25,0x78,0x65,0x86,0x40,0xf6,0x30,0xc1,0x50,0x57,0x16,0x13,0xe9,0xe5,0xbc,0xa9,
0xbb,0x87,0xce,0xb8,0x0d,0x35,0x5d,0xad,0x68,0x3b,0x34,0x9f,0x82,0x2b,0xe5,0x1f,
0xcc,0xd5,0x54,0x8a,0xe3,0xd7,0xed,0xc9,0x7d,0xb6,0x50,0xd2,0xcb,0xc2,0xff,0x03,
0x24,0x8c,0xcf,0x49,0x40,0xd4,0x7f,0xcb,0xc0,0x20,0x75,0x78,0x45,0xb8,0x50,0x3c,
0x84,0xdd,0xdc,0xb7,0xfc,0xcd,0x64,0xc3,0x81,0xc6,0xb6,0xcd,0xc5,0xe9,0xc4,0x70,
0x31,0x30,0x7c,0xff,0x93,0xc3,0x9d,0x55,0x7b,0x32,0x77,0x53,0x07,0x45,0xc2,0x80,
0x7b,0x9b,0xfb,0x0e,0x45,0x27,0xf2,0xc5,0x16),
chunk_from_chars(
0x30,0x82,0x01,0x9c,0x0a,0x01,0x00,0xa0,0x82,0x01,0x95,0x30,0x82,0x01,0x91,0x06,
0x09,0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x01,0x04,0x82,0x01,0x82,0x30,0x82,
0x01,0x7e,0x30,0x81,0xe8,0xa1,0x33,0x30,0x31,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,
0x04,0x06,0x13,0x02,0x43,0x48,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x0a,0x13,
0x0a,0x73,0x74,0x72,0x6f,0x6e,0x67,0x53,0x77,0x61,0x6e,0x31,0x0d,0x30,0x0b,0x06,
0x03,0x55,0x04,0x03,0x13,0x04,0x74,0x65,0x73,0x74,0x18,0x0f,0x32,0x30,0x32,0x32,
0x31,0x31,0x32,0x32,0x30,0x39,0x32,0x32,0x32,0x34,0x5a,0x30,0x7b,0x30,0x79,0x30,
0x3b,0x30,0x09,0x06,0x05,0x2b,0x0e,0x03,0x02,0x1a,0x05,0x00,0x04,0x14,0xbd,0x25,
0xa0,0xdf,0xc3,0x21,0xf2,0xd8,0xed,0x19,0x63,0x0a,0x4b,0x90,0x6d,0xc3,0x0f,0xe7,
0x79,0x20,0x04,0x14,0xe2,0x6d,0x1e,0xdf,0x83,0x8e,0xa2,0x1f,0xc3,0x00,0xdd,0x44,
0x6f,0x8a,0x4d,0x70,0x0c,0x02,0xe3,0x1f,0x02,0x02,0x00,0x80,0xa1,0x16,0x18,0x0f,
0x32,0x30,0x32,0x32,0x31,0x31,0x31,0x35,0x31,0x38,0x34,0x30,0x35,0x34,0x5a,0xa0,
0x03,0x0a,0x01,0x01,0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,0x32,0x30,0x39,
0x32,0x32,0x32,0x34,0x5a,0xa0,0x11,0x18,0x0f,0x32,0x30,0x32,0x32,0x31,0x31,0x32,
0x32,0x31,0x39,0x32,0x32,0x32,0x34,0x5a,0xa1,0x23,0x30,0x21,0x30,0x1f,0x06,0x09,
0x2b,0x06,0x01,0x05,0x05,0x07,0x30,0x01,0x02,0x04,0x12,0x04,0x10,0xf2,0x47,0xbd,
0xd2,0xdd,0x6d,0x58,0xba,0xa4,0x6f,0xa5,0xed,0x31,0xb1,0x37,0x89,0x30,0x0d,0x06,
0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x0b,0x05,0x00,0x03,0x81,0x81,0x00,
0x17,0x96,0x3b,0x5a,0x4d,0x4e,0x90,0x8a,0xdf,0xe9,0x2b,0x1c,0x48,0x15,0x5d,0x8e,
0xed,0xf0,0xa6,0x42,0x3a,0x9c,0x71,0xd9,0x6a,0xa6,0xc1,0xfd,0xef,0xe8,0x0a,0xa1,
0x61,0x46,0xe4,0x04,0x5c,0x64,0xaf,0x47,0x95,0xdd,0x4c,0xba,0x8e,0x53,0xf6,0x9b,
0xbc,0x16,0xcb,0xeb,0xfe,0x80,0x6a,0x70,0x54,0x10,0x59,0x40,0x5b,0xa0,0x2b,0xb3,
0x62,0x27,0x9e,0x5d,0xd2,0xd6,0x15,0x2a,0x9d,0xa3,0xb1,0xcb,0x44,0x09,0xd8,0x29,
0xb5,0x55,0xd9,0x63,0x86,0xd5,0xb3,0x3c,0x4b,0x78,0x14,0x5a,0x27,0x37,0x3a,0x28,
0xd8,0xae,0x69,0x51,0x2e,0x7d,0xf1,0x06,0xc1,0xac,0x4e,0x5d,0x25,0x7a,0xd2,0xf4,
0x41,0xfd,0x9f,0xbf,0x05,0xc1,0x70,0xa5,0x3f,0x7a,0x53,0x06,0x85,0x7b,0xeb,0x94)
};
START_TEST(test_gen_serial_numbers)
{
chunk_t encoding, serial, serial_asn1;
certificate_t *cert, *crl, *ocsp_req, *acert, *acert1;
enumerator_t *enumerator;
certificate_t *cert, *crl, *ocsp_req, *ocsp_rsp, *acert, *acert1;
time_t revocation_time, this_update, next_update;
ocsp_request_t *ocsp_request;
ocsp_response_t *ocsp_resp;
cert_validation_t status;
crl_reason_t revocation_reason;
crl_t *x509_crl;
x509_t *x509;
ac_t *ac;
size_t offset;
u_char *pos;
enumerator_t *enumerator;
/**
* Use serial number with canonical encoding (no leading zeroes)
@ -502,50 +531,92 @@ START_TEST(test_gen_serial_numbers)
pos = encoding.ptr + 68;
serial_asn1 = chunk_create(pos, 1 + *pos);
ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
ocsp_req->destroy(ocsp_req);
/* parse ocsp request */
ocsp_req = parse_ocsp_request(encoding);
ocsp_request = (ocsp_request_t*)ocsp_req;
/* test ocsp request */
enumerator = ocsp_request->create_request_enumerator(ocsp_request);
ck_assert(enumerator->enumerate(enumerator, NULL, NULL, NULL, &serial));
ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
enumerator->destroy(enumerator);
chunk_free(&encoding);
/* create ocsp response */
status = (_i % 2) ? VALIDATION_GOOD : VALIDATION_REVOKED;
ocsp_rsp = create_ocsp_response(ocsp_request, status, cert);
/* the ASN.1 TLV (Type-Length-Value) encoding of an OCSP response is
*
* 0 "OCSPResponse", ASN1_SEQUENCE
* 1 "responseStatus", ASN1_ENUMERATED
* 1 "responseBytesContext", ASN1_CONTEXT_C_0
* 2 "responseBytes", ASN1_SEQUENCE
* 3 "responseType", ASN1_OID
* 3 "response", ASN1_OCTET_STRING
* 4 "BasicOCSPResponse", ASN1_SEQUENCE
* 5 "tbsResponseData", ASN1_SEQUENCE
* 6 "responderIdContext", ASN1_CONTEXT_C_1
* 6 "producedAt", ASN1_GENERALIZEDTIME
* 6 "responses", ASN1_SEQUENCE
* 7 "singleResponse", ASN1_SEQUENCE
* 8 "certID", ASN1_SEQUENCE
* 9 "algorithm", ASN1_SEQUENCE
* 9 "issuerNameHash", ASN1_OCTET_STRING
* 9 "issuerKeyHash", ASN1_OCTET_STRING
* 9 "serialNumber", ASN1_INTEGER
*
* The one octet length field of the serialNumber (8) is at
* pos = 4 (TL0) + 3 (TLV1) + 4 (TL1) + 4 (TL2) + 11 (TLV3) + 4 (TL3) +
4 (TL4) + 3 (TL5) + 53 (TLV6) + 17 (TVL6) + 2 (TL6) + 2 (TL7) +
2 (TL8) + 11 (TLV9) + 22 (TLV9) + 22 (TLV9) + 1 (T9) = 169
*/
ck_assert(ocsp_rsp->get_encoding(ocsp_rsp, CERT_ASN1_DER, &encoding));
DBG2(DBG_LIB, "ocsp response: %B", &encoding);
/* check ASN.1 integer encoding of requested serial number */
pos = encoding.ptr + 169;
serial_asn1 = chunk_create(pos, 1 + *pos);
ck_assert_chunk_eq(serial_asn1, serial_numbers[_i].serial_asn1);
ocsp_rsp->destroy(ocsp_rsp);
/* parse ocsp response */
ocsp_rsp = parse_ocsp_response(encoding);
ocsp_resp = (ocsp_response_t*)ocsp_rsp;
/* test ocsp response */
if (_i == 2 || _i == 3)
ck_assert_chunk_eq(ocsp_request->get_nonce(ocsp_request),
ocsp_resp->get_nonce(ocsp_resp));
status = ocsp_resp->get_status(ocsp_resp, x509, x509, &revocation_time,
&revocation_reason, &this_update, &next_update);
if (_i % 2)
{
certificate_t *ocsp_rsp;
ocsp_response_t *ocsp_resp;
cert_validation_t status;
crl_reason_t revocation_reason;
time_t revocation_time, this_update, next_update;
enumerator_t *enumerator;
ocsp_rsp = parse_ocsp_response(ocsp_responses[_i-2]);
ocsp_resp = (ocsp_response_t*)ocsp_rsp;
status = ocsp_resp->get_status(ocsp_resp, x509, x509, &revocation_time,
&revocation_reason, &this_update, &next_update);
if (_i == 2)
{
ck_assert(status == VALIDATION_GOOD);
}
else
{
ck_assert(status == VALIDATION_REVOKED);
ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
}
enumerator = ocsp_resp->create_response_enumerator(ocsp_resp);
ck_assert(enumerator->enumerate(enumerator, &serial, &status,
&revocation_time, &revocation_reason));
ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
if (_i == 2)
{
ck_assert(status == VALIDATION_GOOD);
}
else
{
ck_assert(status == VALIDATION_REVOKED);
ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
}
enumerator->destroy(enumerator);
ocsp_rsp->destroy(ocsp_rsp);
ck_assert(status == VALIDATION_GOOD);
}
else
{
ck_assert(status == VALIDATION_REVOKED);
ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
}
enumerator = ocsp_resp->create_response_enumerator(ocsp_resp);
ck_assert(enumerator->enumerate(enumerator, &serial, &status,
&revocation_time, &revocation_reason));
ck_assert_chunk_eq(serial, serial_numbers[_i].serial);
if (_i % 2)
{
ck_assert(status == VALIDATION_GOOD);
}
else
{
ck_assert(status == VALIDATION_REVOKED);
ck_assert(revocation_reason == CRL_REASON_KEY_COMPROMISE);
}
enumerator->destroy(enumerator);
chunk_free(&encoding);
/* create attribute certificate */
acert = create_acert(serial_numbers[_i].serial, cert);
@ -633,6 +704,7 @@ START_TEST(test_gen_serial_numbers)
cert->destroy(cert);
crl->destroy(crl);
ocsp_req->destroy(ocsp_req);
ocsp_rsp->destroy(ocsp_rsp);
acert->destroy(acert);
acert1->destroy(acert1);