SCT *SCT_new_from_base64(unsigned char version, const char *logid_base64, ct_log_entry_type_t entry_type, uint64_t timestamp, const char *extensions_base64, const char *signature_base64) { SCT *sct = SCT_new(); unsigned char *dec = NULL; int declen; if (sct == NULL) { CTerr(CT_F_SCT_NEW_FROM_BASE64, ERR_R_MALLOC_FAILURE); return NULL; } /* * RFC6962 section 4.1 says we "MUST NOT expect this to be 0", but we * can only construct SCT versions that have been defined. */ if (!SCT_set_version(sct, version)) { CTerr(CT_F_SCT_NEW_FROM_BASE64, CT_R_SCT_UNSUPPORTED_VERSION); goto err; } declen = ct_base64_decode(logid_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } if (!SCT_set0_log_id(sct, dec, declen)) goto err; dec = NULL; declen = ct_base64_decode(extensions_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } SCT_set0_extensions(sct, dec, declen); dec = NULL; declen = ct_base64_decode(signature_base64, &dec); if (declen < 0) { CTerr(CT_F_SCT_NEW_FROM_BASE64, X509_R_BASE64_DECODE_ERROR); goto err; } if (o2i_SCT_signature(sct, (const unsigned char **)&dec, declen) <= 0) goto err; OPENSSL_free(dec); dec = NULL; SCT_set_timestamp(sct, timestamp); if (!SCT_set_log_entry_type(sct, entry_type)) goto err; return sct; err: OPENSSL_free(dec); SCT_free(sct); return NULL; }
static int execute_cert_test(CT_TEST_FIXTURE fixture) { int test_failed = 0; X509 *cert = NULL, *issuer = NULL; STACK_OF(SCT) *scts = NULL; SCT *sct = NULL; char expected_sct_text[CT_TEST_MAX_FILE_SIZE]; int sct_text_len = 0; unsigned char *tls_sct = NULL; size_t tls_sct_len = 0; CT_POLICY_EVAL_CTX *ct_policy_ctx = CT_POLICY_EVAL_CTX_new(); if (fixture.sct_text_file_path != NULL) { sct_text_len = read_text_file( fixture.sct_text_file_path, expected_sct_text, CT_TEST_MAX_FILE_SIZE - 1); if (sct_text_len < 0) { test_failed = 1; fprintf(stderr, "Test data file not found: %s\n", fixture.sct_text_file_path); goto end; } expected_sct_text[sct_text_len] = '\0'; } CT_POLICY_EVAL_CTX_set0_log_store(ct_policy_ctx, fixture.ctlog_store); if (fixture.certificate_file_path != NULL) { int sct_extension_index; X509_EXTENSION *sct_extension = NULL; cert = load_pem_cert(fixture.certificate_file_path); if (cert == NULL) { test_failed = 1; fprintf(stderr, "Unable to load certificate: %s\n", fixture.certificate_file_path); goto end; } CT_POLICY_EVAL_CTX_set0_cert(ct_policy_ctx, cert); if (fixture.issuer_file_path != NULL) { issuer = load_pem_cert(fixture.issuer_file_path); if (issuer == NULL) { test_failed = 1; fprintf(stderr, "Unable to load issuer certificate: %s\n", fixture.issuer_file_path); goto end; } CT_POLICY_EVAL_CTX_set0_issuer(ct_policy_ctx, issuer); } sct_extension_index = X509_get_ext_by_NID(cert, NID_ct_precert_scts, -1); sct_extension = X509_get_ext(cert, sct_extension_index); if (fixture.expected_sct_count > 0) { if (sct_extension == NULL) { test_failed = 1; fprintf(stderr, "SCT extension not found in: %s\n", fixture.certificate_file_path); goto end; } if (fixture.sct_text_file_path) { test_failed = compare_extension_printout(sct_extension, expected_sct_text); if (test_failed != 0) goto end; } if (fixture.test_validity) { int are_scts_validated = 0; scts = X509V3_EXT_d2i(sct_extension); SCT_LIST_set_source(scts, SCT_SOURCE_X509V3_EXTENSION); are_scts_validated = SCT_LIST_validate(scts, ct_policy_ctx); if (are_scts_validated < 0) { fprintf(stderr, "Error verifying SCTs\n"); test_failed = 1; } else if (!are_scts_validated) { int invalid_sct_count = 0; int valid_sct_count = 0; int i; for (i = 0; i < sk_SCT_num(scts); ++i) { SCT *sct_i = sk_SCT_value(scts, i); switch (SCT_get_validation_status(sct_i)) { case SCT_VALIDATION_STATUS_VALID: ++valid_sct_count; break; case SCT_VALIDATION_STATUS_INVALID: ++invalid_sct_count; break; default: /* Ignore other validation statuses. */ break; } } if (valid_sct_count != fixture.expected_sct_count) { int unverified_sct_count = sk_SCT_num(scts) - invalid_sct_count - valid_sct_count; fprintf(stderr, "%d SCTs failed verification\n" "%d SCTs passed verification (%d expected)\n" "%d SCTs were unverified\n", invalid_sct_count, valid_sct_count, fixture.expected_sct_count, unverified_sct_count); } test_failed = 1; } if (test_failed != 0) goto end; } } else if (sct_extension != NULL) { test_failed = 1; fprintf(stderr, "Expected no SCTs, but found SCT extension in: %s\n", fixture.certificate_file_path); goto end; } } if (fixture.tls_sct != NULL) { const unsigned char *p = fixture.tls_sct; if (o2i_SCT(&sct, &p, fixture.tls_sct_len) == NULL) { test_failed = 1; fprintf(stderr, "Failed to decode SCT from TLS format\n"); goto end; } if (fixture.sct_text_file_path) { test_failed = compare_sct_printout(sct, expected_sct_text); if (test_failed != 0) goto end; } tls_sct_len = i2o_SCT(sct, &tls_sct); if (tls_sct_len != fixture.tls_sct_len || memcmp(fixture.tls_sct, tls_sct, tls_sct_len) != 0) { test_failed = 1; fprintf(stderr, "Failed to encode SCT into TLS format correctly\n"); goto end; } if (fixture.test_validity && cert != NULL) { int is_sct_validated = SCT_validate(sct, ct_policy_ctx); if (is_sct_validated < 0) { test_failed = 1; fprintf(stderr, "Error validating SCT\n"); goto end; } else if (!is_sct_validated) { test_failed = 1; fprintf(stderr, "SCT failed verification\n"); goto end; } } } end: X509_free(cert); X509_free(issuer); SCT_LIST_free(scts); SCT_free(sct); CT_POLICY_EVAL_CTX_free(ct_policy_ctx); OPENSSL_free(tls_sct); return test_failed; }
SCT *o2i_SCT(SCT **psct, const unsigned char **in, size_t len) { SCT *sct = NULL; const unsigned char *p; if (len == 0 || len > MAX_SCT_SIZE) { CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); goto err; } if ((sct = SCT_new()) == NULL) goto err; p = *in; sct->version = *p; if (sct->version == SCT_VERSION_V1) { int sig_len; size_t len2; /*- * Fixed-length header: * struct { * Version sct_version; (1 byte) * log_id id; (32 bytes) * uint64 timestamp; (8 bytes) * CtExtensions extensions; (2 bytes + ?) * } */ if (len < 43) { CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); goto err; } len -= 43; p++; sct->log_id = BUF_memdup(p, CT_V1_HASHLEN); if (sct->log_id == NULL) goto err; sct->log_id_len = CT_V1_HASHLEN; p += CT_V1_HASHLEN; n2l8(p, sct->timestamp); n2s(p, len2); if (len < len2) { CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); goto err; } if (len2 > 0) { sct->ext = BUF_memdup(p, len2); if (sct->ext == NULL) goto err; } sct->ext_len = len2; p += len2; len -= len2; sig_len = o2i_SCT_signature(sct, &p, len); if (sig_len <= 0) { CTerr(CT_F_O2I_SCT, CT_R_SCT_INVALID); goto err; } len -= sig_len; *in = p + len; } else { /* If not V1 just cache encoding */ sct->sct = BUF_memdup(p, len); if (sct->sct == NULL) goto err; sct->sct_len = len; *in = p + len; } if (psct != NULL) { SCT_free(*psct); *psct = sct; } return sct; err: SCT_free(sct); return NULL; }
static void tear_down(CT_TEST_FIXTURE fixture) { CTLOG_STORE_free(fixture.ctlog_store); SCT_free(fixture.sct); ERR_print_errors_fp(stderr); }