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; }
static inline int rsgt_extendSig(GTTimestamp *timestamp, tlvrecord_t *rec, gterrctx_t *ectx) { GTTimestamp *out_timestamp; uint8_t *der; size_t lenDer; int r, rgt; tlvrecord_t newrec, subrec; uint16_t iRd, iWr; rgt = GTHTTP_extendTimestamp(timestamp, rsgt_extend_puburl, &out_timestamp); if(rgt != GT_OK) { ectx->gtstate = rgt; r = RSGTE_TS_EXTEND; goto done; } r = GTTimestamp_getDEREncoded(out_timestamp, &der, &lenDer); if(r != GT_OK) { r = RSGTE_TS_DERENCODE; ectx->gtstate = rgt; goto done; } /* update block_sig tlv record with new extended timestamp */ /* we now need to copy all tlv records before the actual der * encoded part. */ iRd = iWr = 0; // TODO; check tlvtypes at comment places below! if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done; /* HASH_ALGO */ COPY_SUBREC_TO_NEWREC if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done; /* BLOCK_IV */ COPY_SUBREC_TO_NEWREC if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done; /* LAST_HASH */ COPY_SUBREC_TO_NEWREC if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done; /* REC_COUNT */ COPY_SUBREC_TO_NEWREC if ((r = rsgt_tlvDecodeSUBREC(rec, &iRd, &subrec)) != 0) goto done; /* actual sig! */ newrec.data[iWr++] = 0x09 | RSGT_FLAG_TLV16; newrec.data[iWr++] = 0x06; newrec.data[iWr++] = (lenDer >> 8) & 0xff; newrec.data[iWr++] = lenDer & 0xff; /* now we know how large the new main record is */ newrec.tlvlen = (uint16_t) iWr+lenDer; newrec.tlvtype = rec->tlvtype; newrec.hdr[0] = rec->hdr[0]; newrec.hdr[1] = rec->hdr[1]; newrec.hdr[2] = (newrec.tlvlen >> 8) & 0xff; newrec.hdr[3] = newrec.tlvlen & 0xff; newrec.lenHdr = 4; memcpy(newrec.data+iWr, der, lenDer); /* and finally copy back new record to existing one */ memcpy(rec, &newrec, sizeof(newrec)-sizeof(newrec.data)+newrec.tlvlen+4); r = 0; done: return r; }
int main(int argc, char* argv[]) { int res = GT_OK; char *in_file = NULL; char *out_file = NULL; char *tsa_url = NULL; unsigned char *der_in = NULL; size_t der_in_len; unsigned char *der_out = NULL; size_t der_out_len; GTTimestamp *in_timestamp = NULL; GTTimestamp *out_timestamp = NULL; /* Read arguments. */ if (argc != 4) { printf("Usage: %s timestamp_in_file timestamp_out_file verifier_url\n", argv[0]); goto cleanup; } in_file = argv[1]; out_file = argv[2]; tsa_url = argv[3]; /* Init GuardTime libraries. */ res = GT_init(); if (res != GT_OK) { fprintf(stderr, "GT_init() failed: %d (%s)\n", res, GT_getErrorString(res)); goto cleanup; } res = GTHTTP_init("C SDK example", 1); if (res != GT_OK) { fprintf(stderr, "GTHTTP_init() failed: %d (%s)\n", res, GTHTTP_getErrorString(res)); goto cleanup; } /* Read timestamp file. */ res = GT_loadFile(in_file, &der_in, &der_in_len); if (res != GT_OK) { fprintf(stderr, "Cannot load timestamp file %s: %d (%s)\n", in_file, res, GT_getErrorString(res)); if (res == GT_IO_ERROR) { fprintf(stderr, "\t%d (%s)\n", errno, strerror(errno)); } goto cleanup; } /* Decode timestamp. */ res = GTTimestamp_DERDecode(der_in, der_in_len, &in_timestamp); if (res != GT_OK) { fprintf(stderr, "GTTimestamp_DERDecode() failed: %d (%s)\n", res, GT_getErrorString(res)); goto cleanup; } /* Extend timestamp. */ res = GTHTTP_extendTimestamp(in_timestamp, tsa_url, &out_timestamp); if (res != GT_OK) { fprintf(stderr, "GTHTTP_extendTimestamp() failed: %d (%s)\n", res, GTHTTP_getErrorString(res)); goto cleanup; } /* Encode timestamp. */ res = GTTimestamp_getDEREncoded(out_timestamp, &der_out, &der_out_len); if (res != GT_OK) { fprintf(stderr, "GTTimestamp_getDEREncoded() returned %d (%s)\n", res, GT_getErrorString(res)); goto cleanup; } /* Save DER-encoded timestamp to file. */ res = GT_saveFile(out_file, der_out, der_out_len); if (res != GT_OK) { fprintf(stderr, "Cannot save extended timestamp to file %s: %d (%s)\n", out_file, res, GT_getErrorString(res)); if (res == GT_IO_ERROR) { fprintf(stderr, "\t%d (%s)\n", errno, strerror(errno)); } goto cleanup; } printf("Extending succeeded!\n"); cleanup: GT_free(der_out); GTTimestamp_free(out_timestamp); GTTimestamp_free(in_timestamp); GT_free(der_in); /* Finalize GuardTime libraries. */ GTHTTP_finalize(); GT_finalize(); return res == GT_OK ? EXIT_SUCCESS : EXIT_FAILURE; }