int GTHTTP_verifyTimestampHash(const GTTimestamp *ts, const GTDataHash *hash, const char *ext_url, GTTimestamp **ext_ts, const GTPublicationsFile *pub, const char *pub_url, int parse, GTVerificationInfo **ver) { int res = GT_UNKNOWN_ERROR; GTPublicationsFile *pub_tmp = NULL; GTPubFileVerificationInfo *pub_ver = NULL; GTVerificationInfo *ver_tmp = NULL; GTTimestamp *ext = NULL; int is_ext = 0, is_new = 0; if (ts == NULL || hash == NULL || ver == NULL) { res = GT_INVALID_ARGUMENT; goto cleanup; } if ((pub != NULL) + (pub_url != NULL) != 1) { res = GT_INVALID_ARGUMENT; goto cleanup; } /* Ensure we have a valid publications file. */ if (pub == NULL) { res = GTHTTP_getPublicationsFile(pub_url, &pub_tmp); if (res != GT_OK) { goto cleanup; } pub = pub_tmp; } res = GTPublicationsFile_verify(pub, &pub_ver); if (res != GT_OK) { goto cleanup; } /* Check internal consistency of the timestamp. */ res = GTTimestamp_verify(ts, parse, &ver_tmp); if (res != GT_OK) { goto cleanup; } if (ver_tmp == NULL || ver_tmp->implicit_data == NULL) { res = GT_UNKNOWN_ERROR; goto cleanup; } if (ver_tmp->verification_errors != GT_NO_FAILURES) { goto cleanup; } /* Check document hash. * GT_WRONG_DOCUMENT means the hash did not match. * Everything else is some sort of system error. */ res = GTTimestamp_checkDocumentHash(ts, hash); if (res == GT_OK) { ver_tmp->verification_status |= GT_DOCUMENT_HASH_CHECKED; } else if (res == GT_WRONG_DOCUMENT) { ver_tmp->verification_status |= GT_DOCUMENT_HASH_CHECKED; ver_tmp->verification_errors |= GT_WRONG_DOCUMENT_FAILURE; res = GT_OK; goto cleanup; } else { goto cleanup; } /* Whether the timestamp is extended. */ is_ext = ((ver_tmp->verification_status & GT_PUBLIC_KEY_SIGNATURE_PRESENT) == 0); /* Whether it is too new to be extended. */ is_new = (ver_tmp->implicit_data->registered_time > pub_ver->last_publication_time); /* If the timestamp is already extended, "promote" it. * If it is not extended, but is old enough, attempt to extend it. */ if (is_ext) { ext = (GTTimestamp *) ts; } else if (!is_new && ext_url != NULL) { res = GTHTTP_extendTimestamp(ts, ext_url, &ext); /* If extending fails because of infrastructure failure, fall * back to signing key check. Else report errors. */ if (res == GT_NONSTD_EXTEND_LATER || res == GT_NONSTD_EXTENSION_OVERDUE || (res >= GTHTTP_IMPL_BASE && res <= GTHTTP_HIGHEST)) { res = GT_OK; } if (res != GT_OK) { goto cleanup; } } /* If we now have a new timestamp, check internal consistency and document hash. */ if (ext != NULL && ext != ts) { /* Release the old verification info. */ GTVerificationInfo_free(ver_tmp); ver_tmp = NULL; /* Re-check consistency. */ res = GTTimestamp_verify(ext, parse, &ver_tmp); if (res != GT_OK) { goto cleanup; } if (ver_tmp == NULL || ver_tmp->implicit_data == NULL) { res = GT_UNKNOWN_ERROR; goto cleanup; } if (ver_tmp->verification_errors != GT_NO_FAILURES) { goto cleanup; } /* Re-check document hash. */ res = GTTimestamp_checkDocumentHash(ts, hash); if (res == GT_OK) { ver_tmp->verification_status |= GT_DOCUMENT_HASH_CHECKED; } else if (res == GT_WRONG_DOCUMENT) { ver_tmp->verification_status |= GT_DOCUMENT_HASH_CHECKED; ver_tmp->verification_errors |= GT_WRONG_DOCUMENT_FAILURE; res = GT_OK; goto cleanup; } else { goto cleanup; } } if (ext != NULL) { /* If we now have an extended timestamp, check publication. * GT_TRUST_POINT_NOT_FOUND and GT_INVALID_TRUST_POINT mean it did not match. * Everything else is some sort of system error. */ res = GTTimestamp_checkPublication(ext, pub); if (res == GT_OK) { ver_tmp->verification_status |= GT_PUBLICATION_CHECKED; } else if (res == GT_TRUST_POINT_NOT_FOUND || res == GT_INVALID_TRUST_POINT) { ver_tmp->verification_status |= GT_PUBLICATION_CHECKED; ver_tmp->verification_errors |= GT_NOT_VALID_PUBLICATION; res = GT_OK; } } else { /* Otherwise, check signing key. * GT_KEY_NOT_PUBLISHED and GT_CERT_TICKET_TOO_OLD mean key not valid. * Everything else is some sort of system error. */ res = GTTimestamp_checkPublicKey(ts, ver_tmp->implicit_data->registered_time, pub); if (res == GT_OK) { ver_tmp->verification_status |= GT_PUBLICATION_CHECKED; } else if (res == GT_KEY_NOT_PUBLISHED || res == GT_CERT_TICKET_TOO_OLD) { ver_tmp->verification_status |= GT_PUBLICATION_CHECKED; ver_tmp->verification_errors |= GT_NOT_VALID_PUBLIC_KEY_FAILURE; res = GT_OK; } } cleanup: if (res == GT_OK) { if (ext_ts != NULL && ext != NULL && ext != ts && ver_tmp->verification_errors == GT_NO_FAILURES) { *ext_ts = ext; ext = NULL; } *ver = ver_tmp; ver_tmp = NULL; } if (ext != ts) { GTTimestamp_free(ext); } GTVerificationInfo_free(ver_tmp); GTPubFileVerificationInfo_free(pub_ver); GTPublicationsFile_free(pub_tmp); return res; }
int GTPublicationsFile_DERDecode(const void *data, size_t data_length, GTPublicationsFile **publications_file) { int retval = GT_UNKNOWN_ERROR; GTPublicationsFile *tmp_publications_file = NULL; if ((data == NULL && data_length != 0) || publications_file == NULL) { retval = GT_INVALID_ARGUMENT; goto cleanup; } tmp_publications_file = GT_malloc(sizeof(GTPublicationsFile)); if (tmp_publications_file == NULL) { retval = GT_OUT_OF_MEMORY; goto cleanup; } /* Do not waste time with copying of data until we are sure that input data * is correct. */ tmp_publications_file->data = data; tmp_publications_file->data_length = data_length; tmp_publications_file->data_owner = 0; tmp_publications_file->publication_cells = NULL; tmp_publications_file->key_hash_cells = NULL; tmp_publications_file->pub_reference = NULL; tmp_publications_file->signature = NULL; retval = decodeHeader(tmp_publications_file); if (retval != GT_OK) { goto cleanup; } retval = decodePublicationCells(tmp_publications_file); if (retval != GT_OK) { goto cleanup; } retval = decodeKeyHashCells(tmp_publications_file); if (retval != GT_OK) { goto cleanup; } retval = decodePubReference(tmp_publications_file); if (retval != GT_OK) { goto cleanup; } retval = decodeSignature(tmp_publications_file); if (retval != GT_OK) { goto cleanup; } retval = GT_UNKNOWN_ERROR; tmp_publications_file->data = GT_malloc(data_length); if (tmp_publications_file->data == NULL) { retval = GT_OUT_OF_MEMORY; goto cleanup; } memcpy((void*) tmp_publications_file->data, data, data_length); tmp_publications_file->data_owner = 1; *publications_file = tmp_publications_file; tmp_publications_file = NULL; retval = GT_OK; cleanup: GTPublicationsFile_free(tmp_publications_file); return retval; }