static void testGetLatestPublicationOfLast(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *tm = NULL; KSI_PublicationData *pubDat = NULL; KSI_Integer *pubTm = NULL; res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile); CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL); res = KSI_Integer_new(ctx, 1405382400, &tm); CuAssert(tc, "Unable to create integer", res == KSI_OK && tm != NULL); res = KSI_PublicationsFile_getLatestPublication(pubFile, tm, &pubRec); CuAssert(tc, "Unable to find nearest publication", res == KSI_OK && pubRec != NULL); res = KSI_PublicationRecord_getPublishedData(pubRec, &pubDat); CuAssert(tc, "Unable to get published data", res == KSI_OK && pubDat != NULL); res = KSI_PublicationData_getTime(pubDat, &pubTm); CuAssert(tc, "Unable to get publication time", res == KSI_OK && pubTm != NULL); CuAssert(tc, "Unexpected publication time (this test might fail, if you have recently updated the publications file in the tests)", KSI_Integer_equalsUInt(pubTm, 1405382400)); KSI_PublicationsFile_free(pubFile); KSI_Integer_free(tm); }
static void testGetNearestPublicationWithPubTime(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *tm = NULL; KSI_PublicationData *pubDat = NULL; KSI_Integer *pubTm = NULL; res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile); CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL); /* With time set to 0, the result should be the first publication record in the publications file. */ res = KSI_Integer_new(ctx, 1208217600, &tm); CuAssert(tc, "Unable to create integer", res == KSI_OK && tm != NULL); res = KSI_PublicationsFile_getNearestPublication(pubFile, tm, &pubRec); CuAssert(tc, "Unable to find nearest publication", res == KSI_OK && pubRec != NULL); res = KSI_PublicationRecord_getPublishedData(pubRec, &pubDat); CuAssert(tc, "Unable to get published data", res == KSI_OK && pubDat != NULL); res = KSI_PublicationData_getTime(pubDat, &pubTm); CuAssert(tc, "Unable to get publication time", res == KSI_OK && pubTm != NULL); CuAssert(tc, "Unexpected publication time", KSI_Integer_equalsUInt(pubTm, 1208217600)); KSI_PublicationRecord_free(pubRec); KSI_PublicationsFile_free(pubFile); KSI_Integer_free(tm); }
/** * KSI_PublicationData */ void KSI_PublicationData_free(KSI_PublicationData *t) { if (t != NULL && --t->ref == 0) { KSI_Integer_free(t->time); KSI_DataHash_free(t->imprint); KSI_TLV_free(t->baseTlv); KSI_free(t); } }
int KSI_Integer_fromTlv(KSI_TLV *tlv, KSI_Integer **o) { int res = KSI_UNKNOWN_ERROR; KSI_CTX *ctx = NULL; KSI_Integer *tmp = NULL; const unsigned char *raw = NULL; size_t len; size_t i; KSI_uint64_t val = 0; ctx = KSI_TLV_getCtx(tlv); KSI_ERR_clearErrors(ctx); if (tlv == NULL || o == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } res = KSI_TLV_getRawValue(tlv, &raw, &len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (len > 8) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Integer larger than 64bit"); goto cleanup; } /* Encode the up-to 64bit unsigned integer. */ for (i = 0; i < len; i++) { val = val << 8 | raw[i]; } /* Make sure the integer was coded properly. */ if (len != KSI_UINT64_MINSIZE(val)) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Integer not properly formated."); goto cleanup; } res = KSI_Integer_new(ctx, val, &tmp); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *o = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_nofree(ctx); KSI_Integer_free(tmp); return res; }
static int parseStructure(KSI_TLV *tlv, int indent) { int res; KSI_TLV *nested = NULL; KSI_LIST(KSI_TLV) *list = NULL; size_t i; KSI_Utf8String *utf = NULL; KSI_Integer *integer = NULL; KSI_OctetString *octet = NULL; switch (KSI_TLV_getTag(tlv)) { case 0x01: /* Cast as numeric TLV */ /* Parse number */ res = KSI_Integer_fromTlv(tlv, &integer); if (res != KSI_OK) goto cleanup; break; case 0x02: /* Cast as string TLV */ res = KSI_Utf8String_fromTlv(tlv, &utf); if (res != KSI_OK) goto cleanup; break; case 0x03: case 0x1003: res = KSI_TLV_getNestedList(tlv, &list); if (res != KSI_OK) goto cleanup; /* Parse nested */ for (i = 0; i < KSI_TLVList_length(list); i++) { res = KSI_TLVList_elementAt(list, i, &nested); if (res != KSI_OK) goto cleanup; if (nested == NULL) break; res = parseStructure(nested, indent); if (res != KSI_OK) goto cleanup; } break; case 0x04: /* Cast as octet string*/ res = KSI_OctetString_fromTlv(tlv, &octet); if (res != KSI_OK) goto cleanup; break; default: res = KSI_INVALID_FORMAT; goto cleanup; } cleanup: KSI_OctetString_free(octet); KSI_Utf8String_free(utf); KSI_Integer_free(integer); return res; }
static void testFindPublicationRef(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *pubTime = NULL; KSI_LIST(KSI_Utf8String) *pubRefList = NULL; size_t i; int isPubRefFound = 0; KSI_CTX *ctx = NULL; res = KSITest_CTX_clone(&ctx); CuAssert(tc, "Unable to create KSI context.", res == KSI_OK && ctx != NULL); res = KSITest_setDefaultPubfileAndVerInfo(ctx); CuAssert(tc, "Unable to set default values to context.", res == KSI_OK); KSI_ERR_clearErrors(ctx); res = KSI_CTX_setPublicationUrl(ctx, getFullResourcePathUri(TEST_PUBLICATIONS_FILE)); CuAssert(tc, "Unable to set pubfile URI.", res == KSI_OK); res = KSI_receivePublicationsFile(ctx, &pubFile); CuAssert(tc, "Unable to get publications file.", res == KSI_OK && pubFile != NULL); res = KSI_verifyPublicationsFile(ctx, pubFile); CuAssert(tc, "Unable to verify publications file.", res == KSI_OK); res = KSI_Integer_new(ctx, 1397520000, &pubTime); CuAssert(tc, "Unable to create ksi integer object.", res == KSI_OK && pubTime != NULL); res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, pubTime, &pubRec); CuAssert(tc, "Unable to get publication record by publication date.", res == KSI_OK && pubRec != NULL); KSI_Integer_free(pubTime); pubTime = NULL; res = KSI_PublicationRecord_getPublicationRefList(pubRec, &pubRefList); CuAssert(tc, "Unable to get publications ref list", res == KSI_OK && pubRefList != NULL); for (i = 0; i < KSI_Utf8StringList_length(pubRefList); i++) { KSI_Utf8String *pubRef = NULL; res = KSI_Utf8StringList_elementAt(pubRefList, i, &pubRef); CuAssert(tc, "Unable to get element from list", res == KSI_OK && pubRef != NULL); if (!strcmp("Financial Times, ISSN: 0307-1766, 2014-04-17", KSI_Utf8String_cstr(pubRef))) { isPubRefFound = 1; } } CuAssert(tc, "Financial times publication not found", isPubRefFound); KSI_PublicationsFile_free(pubFile); KSI_CTX_free(ctx); }
static void testFindPublicationByTime(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_PublicationData *pub = NULL; KSI_DataHash *pubHsh = NULL; KSI_Integer *pubTime = NULL; KSI_DataHash *expHsh = NULL; KSI_LIST(KSI_Utf8String) *pubRefList = NULL; unsigned char buf[0xff]; unsigned len; KSI_ERR_clearErrors(ctx); res = KSI_receivePublicationsFile(ctx, &pubFile); CuAssert(tc, "Unable to get publications file.", res == KSI_OK && pubFile != NULL); res = KSI_Integer_new(ctx, 1397520000, &pubTime); CuAssert(tc, "Unable to create ksi integer object.", res == KSI_OK && pubTime != NULL); res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, pubTime, &pubRec); CuAssert(tc, "Unable to get publication record by publication date.", res == KSI_OK && pubRec != NULL); res = KSI_PublicationRecord_getPublishedData(pubRec, &pub); CuAssert(tc, "Unable to get published data", res == KSI_OK && pub != NULL); res = KSI_PublicationData_getImprint(pub, &pubHsh); CuAssert(tc, "Unable to get published hash", res == KSI_OK && pubHsh != NULL); KSI_Integer_free(pubTime); pubTime = NULL; res = KSI_PublicationData_getTime(pub, &pubTime); CuAssert(tc, "Unable to get publication time.", res == KSI_OK && pubTime != NULL); KSITest_decodeHexStr("01a1b5238ffb05fccfa67546266a0b2d7130f6656026033b6b578c12e4fbbe231a", buf, sizeof(buf), &len); res = KSI_DataHash_fromImprint(ctx, buf, len, &expHsh); CuAssert(tc, "Unable to get datahash from imprint", res == KSI_OK && expHsh != NULL); CuAssert(tc, "Publication hash mismatch.", KSI_DataHash_equals(expHsh, pubHsh)); CuAssert(tc, "Publication time mismatch", KSI_Integer_equalsUInt(pubTime, 1397520000)); res = KSI_PublicationRecord_getPublicationRefList(pubRec, &pubRefList); CuAssert(tc, "Unable to get publications ref list", res == KSI_OK && pubRefList != NULL); KSI_DataHash_free(expHsh); }
static void testGetLatestPublicationOfFuture(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *tm = NULL; res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile); CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL); res = KSI_Integer_new(ctx, 2405382400, &tm); CuAssert(tc, "Unable to create integer", res == KSI_OK && tm != NULL); res = KSI_PublicationsFile_getLatestPublication(pubFile, tm, &pubRec); CuAssert(tc, "This publication should not exist.", res == KSI_OK && pubRec == NULL); KSI_PublicationsFile_free(pubFile); KSI_Integer_free(tm); }
static void testGetNearestPublicationOfFuture(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *tm = NULL; res = KSI_PublicationsFile_fromFile(ctx, getFullResourcePath(TEST_PUBLICATIONS_FILE), &pubFile); CuAssert(tc, "Unable to read publications file", res == KSI_OK && pubFile != NULL); /* With time set to 0, the result should be the first publication record in the publications file. */ res = KSI_Integer_new(ctx, 2208217600, &tm); CuAssert(tc, "Unable to create integer", res == KSI_OK && tm != NULL); res = KSI_PublicationsFile_getNearestPublication(pubFile, tm, &pubRec); CuAssert(tc, "There should not be a valid publication", res == KSI_OK && pubRec == NULL); KSI_PublicationRecord_free(pubRec); KSI_PublicationsFile_free(pubFile); KSI_Integer_free(tm); }
static void testFindPublicationRef(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_Integer *pubTime = NULL; KSI_LIST(KSI_Utf8String) *pubRefList = NULL; size_t i; int isPubRefFound = 0; KSI_ERR_clearErrors(ctx); res = KSI_receivePublicationsFile(ctx, &pubFile); CuAssert(tc, "Unable to get publications file.", res == KSI_OK && pubFile != NULL); res = KSI_Integer_new(ctx, 1397520000, &pubTime); CuAssert(tc, "Unable to create ksi integer object.", res == KSI_OK && pubTime != NULL); res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, pubTime, &pubRec); CuAssert(tc, "Unable to get publication record by publication date.", res == KSI_OK && pubRec != NULL); KSI_Integer_free(pubTime); pubTime = NULL; res = KSI_PublicationRecord_getPublicationRefList(pubRec, &pubRefList); CuAssert(tc, "Unable to get publications ref list", res == KSI_OK && pubRefList != NULL); for (i = 0; i < KSI_Utf8StringList_length(pubRefList); i++) { KSI_Utf8String *pubRef = NULL; res = KSI_Utf8StringList_elementAt(pubRefList, i, &pubRef); CuAssert(tc, "Unable to get element from list", res == KSI_OK && pubRef != NULL); if (!strcmp("Financial Times, ISSN: 0307-1766, 2014-04-17", KSI_Utf8String_cstr(pubRef))) { isPubRefFound = 1; } } CuAssert(tc, "Financial times publication not found", isPubRefFound); }
int KSI_Integer_new(KSI_CTX *ctx, KSI_uint64_t value, KSI_Integer **o) { int res = KSI_UNKNOWN_ERROR; KSI_Integer *tmp = NULL; static size_t poolSize = sizeof(integerPool) / sizeof(KSI_Integer); KSI_ERR_clearErrors(ctx); if (o == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } if (value < poolSize) { tmp = integerPool + value; } else { tmp = KSI_new(KSI_Integer); if (tmp == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp->staticAlloc = 0; tmp->value = value; tmp->ref = 1; } *o = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_Integer_free(tmp); return res; }
int KSI_PublicationData_fromBase32(KSI_CTX *ctx, const char *publication, KSI_PublicationData **published_data) { int res = KSI_UNKNOWN_ERROR; unsigned char *binary_publication = NULL; size_t binary_publication_length; KSI_PublicationData *tmp_published_data = NULL; unsigned i; unsigned long tmp_ulong; KSI_uint64_t tmp_uint64; KSI_HashAlgorithm algo_id; size_t hash_size; KSI_DataHash *pubHash = NULL; KSI_Integer *pubTime = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || publication == NULL || published_data == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } res = KSI_base32Decode(publication, &binary_publication, &binary_publication_length); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (binary_publication_length < 13) { res = KSI_INVALID_FORMAT; goto cleanup; } tmp_ulong = 0; for (i = 0; i < 4; ++i) { tmp_ulong <<= 8; tmp_ulong |= binary_publication[binary_publication_length - 4 + i]; } if (KSI_crc32(binary_publication, binary_publication_length - 4, 0) != tmp_ulong) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "CRC mismatch."); goto cleanup; } res = KSI_PublicationData_new(ctx, &tmp_published_data); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } tmp_uint64 = 0; for (i = 0; i < 8; ++i) { tmp_uint64 <<= 8; tmp_uint64 |= binary_publication[i]; } res = KSI_Integer_new(ctx, tmp_uint64, &pubTime); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_PublicationData_setTime(tmp_published_data, pubTime); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } pubTime = NULL; algo_id = binary_publication[8]; if (!KSI_isHashAlgorithmSupported(algo_id)) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, NULL); goto cleanup; } hash_size = KSI_getHashLength(algo_id); if (binary_publication_length != 8 + 1 + hash_size + 4) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Hash algorithm length mismatch."); goto cleanup; } res = KSI_DataHash_fromImprint(ctx, binary_publication + 8, hash_size + 1, &pubHash); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_PublicationData_setImprint(tmp_published_data, pubHash); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } pubHash = NULL; *published_data = tmp_published_data; tmp_published_data = NULL; res = KSI_OK; cleanup: KSI_Integer_free(pubTime); KSI_DataHash_free(pubHash); KSI_free(binary_publication); KSI_PublicationData_free(tmp_published_data); return res; }
static void testFindPublicationByTime(CuTest *tc) { int res; KSI_PublicationsFile *pubFile = NULL; KSI_PublicationRecord *pubRec = NULL; KSI_PublicationData *pub = NULL; KSI_DataHash *pubHsh = NULL; KSI_Integer *pubTime = NULL; KSI_DataHash *expHsh = NULL; KSI_LIST(KSI_Utf8String) *pubRefList = NULL; unsigned char buf[0xff]; size_t len; KSI_CTX *ctx = NULL; res = KSITest_CTX_clone(&ctx); CuAssert(tc, "Unable to create KSI context.", res == KSI_OK && ctx != NULL); res = KSITest_setDefaultPubfileAndVerInfo(ctx); CuAssert(tc, "Unable to set default values to context.", res == KSI_OK); KSI_ERR_clearErrors(ctx); res = KSI_CTX_setPublicationUrl(ctx, getFullResourcePathUri(TEST_PUBLICATIONS_FILE)); CuAssert(tc, "Unable to set pubfile URI.", res == KSI_OK); res = KSI_receivePublicationsFile(ctx, &pubFile); CuAssert(tc, "Unable to get publications file.", res == KSI_OK && pubFile != NULL); res = KSI_verifyPublicationsFile(ctx, pubFile); CuAssert(tc, "Unable to verify publications file.", res == KSI_OK); res = KSI_Integer_new(ctx, 1397520000, &pubTime); CuAssert(tc, "Unable to create ksi integer object.", res == KSI_OK && pubTime != NULL); res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, pubTime, &pubRec); CuAssert(tc, "Unable to get publication record by publication date.", res == KSI_OK && pubRec != NULL); res = KSI_PublicationRecord_getPublishedData(pubRec, &pub); CuAssert(tc, "Unable to get published data", res == KSI_OK && pub != NULL); res = KSI_PublicationData_getImprint(pub, &pubHsh); CuAssert(tc, "Unable to get published hash", res == KSI_OK && pubHsh != NULL); KSI_Integer_free(pubTime); pubTime = NULL; res = KSI_PublicationData_getTime(pub, &pubTime); CuAssert(tc, "Unable to get publication time.", res == KSI_OK && pubTime != NULL); KSITest_decodeHexStr("01a1b5238ffb05fccfa67546266a0b2d7130f6656026033b6b578c12e4fbbe231a", buf, sizeof(buf), &len); res = KSI_DataHash_fromImprint(ctx, buf, len, &expHsh); CuAssert(tc, "Unable to get datahash from imprint", res == KSI_OK && expHsh != NULL); CuAssert(tc, "Publication hash mismatch.", KSI_DataHash_equals(expHsh, pubHsh)); CuAssert(tc, "Publication time mismatch", KSI_Integer_equalsUInt(pubTime, 1397520000)); res = KSI_PublicationRecord_getPublicationRefList(pubRec, &pubRefList); CuAssert(tc, "Unable to get publications ref list", res == KSI_OK && pubRefList != NULL); KSI_DataHash_free(expHsh); KSI_PublicationsFile_free(pubFile); KSI_CTX_free(ctx); }
static void getExtResponse(CuTest* tc, KSI_uint64_t id, KSI_uint64_t aggrTime, KSI_uint64_t pubTime, KSI_ExtendResp **response) { int res; KSI_ExtendReq *request = NULL; KSI_Integer *ID = NULL; KSI_Integer *aggr_time = NULL; KSI_Integer *pub_time = NULL; KSI_RequestHandle *handle = NULL; KSI_ExtendResp *tmp = NULL; KSI_ERR_clearErrors(ctx); /*Create objects*/ res = KSI_ExtendReq_new(ctx, &request); CuAssert(tc, "Unable to create extend request.", res == KSI_OK && request != NULL); res = KSI_Integer_new(ctx, id, &ID); CuAssert(tc, "Unable to create request ID.", res == KSI_OK && ID != NULL); res = KSI_Integer_new(ctx, aggrTime, &aggr_time); CuAssert(tc, "Unable to aggr time.", res == KSI_OK && aggr_time != NULL); res = KSI_Integer_new(ctx, pubTime, &pub_time); CuAssert(tc, "Unable to pub time.", res == KSI_OK && pub_time != NULL); /*Combine objects*/ res = KSI_ExtendReq_setRequestId(request, ID); CuAssert(tc, "Unable set request ID.", res == KSI_OK); ID = NULL; res = KSI_ExtendReq_setAggregationTime(request, aggr_time); CuAssert(tc, "Unable set aggre time.", res == KSI_OK); aggr_time = NULL; res = KSI_ExtendReq_setPublicationTime(request, pub_time); CuAssert(tc, "Unable set pub time.", res == KSI_OK); pub_time = NULL; /*Send request and get response*/ res = KSI_sendExtendRequest(ctx, request, &handle); CuAssert(tc, "Unable to send (prepare) sign request.", res == KSI_OK); res = KSI_RequestHandle_perform(handle); CuAssert(tc, "Unable to send perform (send) sign request.", res == KSI_OK); res = KSI_RequestHandle_getExtendResponse(handle, &tmp); CuAssert(tc, "Unable to get (send and get) sign request.", res == KSI_OK && tmp != NULL); *response = tmp; tmp = NULL; res = KSI_OK; KSI_ExtendReq_free(request); KSI_Integer_free(aggr_time); KSI_Integer_free(pub_time); KSI_Integer_free(ID); KSI_ExtendResp_free(tmp); KSI_RequestHandle_free(handle); }
static int verifyOnline(KSI_CTX *ctx, KSI_Signature *sig) { int res = KSI_UNKNOWN_ERROR; KSI_ExtendReq *req = NULL; KSI_Integer *start = NULL; KSI_Integer *end = NULL; KSI_RequestHandle *handle = NULL; KSI_DataHash *extHash = NULL; KSI_DataHash *calHash = NULL; KSI_ExtendResp *resp = NULL; KSI_Integer *status = NULL; KSI_CalendarHashChain *calChain = NULL; KSI_DataHash *rootHash = NULL; KSI_DataHash *pubHash = NULL; KSI_VerificationStep step = KSI_VERIFY_CALCHAIN_ONLINE; KSI_VerificationResult *info = &sig->verificationResult; KSI_LOG_info(sig->ctx, "Verifying signature online."); /* Extract start time */ res = KSI_CalendarHashChain_getAggregationTime(sig->calendarChain, &start); if (res != KSI_OK) goto cleanup; /* Clone the start time object */ KSI_Integer_ref(start); if (sig->verificationResult.useUserPublication) { /* Extract end time. */ res = KSI_PublicationData_getTime(sig->verificationResult.userPublication, &end); if (res != KSI_OK) goto cleanup; } res = KSI_createExtendRequest(sig->ctx, start, end, &req); if (res != KSI_OK) goto cleanup; res = KSI_sendExtendRequest(ctx, req, &handle); if (res != KSI_OK) goto cleanup; res = KSI_RequestHandle_perform(handle); if (res != KSI_OK) { KSI_pushError(ctx,res, NULL); goto cleanup; } res = KSI_RequestHandle_getExtendResponse(handle, &resp); if (res != KSI_OK) goto cleanup; /* Verify the correctness of the response. */ res = KSI_ExtendResp_verifyWithRequest(resp, req); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_ExtendResp_getStatus(resp, &status); if (res != KSI_OK) goto cleanup; /* Verify status. */ if (status != NULL && !KSI_Integer_equalsUInt(status, 0)) { KSI_Utf8String *respErr = NULL; char errm[1024]; res = KSI_ExtendResp_getErrorMsg(resp, &respErr); if (res != KSI_OK) goto cleanup; KSI_snprintf(errm, sizeof(errm), "Extend failure from server: '%s'", KSI_Utf8String_cstr(respErr)); res = KSI_VerificationResult_addFailure(info, step, errm); goto cleanup; } res = KSI_ExtendResp_getCalendarHashChain(resp, &calChain); if (res != KSI_OK) goto cleanup; res = KSI_CalendarHashChain_getInputHash(calChain, &extHash); if (res != KSI_OK) goto cleanup; res = KSI_CalendarHashChain_getInputHash(sig->calendarChain, &calHash); if (res != KSI_OK) goto cleanup; if (!KSI_DataHash_equals(extHash, calHash)) { res = KSI_VerificationResult_addFailure(info, step, "Extender returned different input hash for calendar hash chain."); goto cleanup; } if (sig->verificationResult.useUserPublication) { res = KSI_CalendarHashChain_aggregate(calChain, &rootHash); if (res != KSI_OK) goto cleanup; if (!KSI_DataHash_equals(rootHash, pubHash)) { res = KSI_VerificationResult_addFailure(info, step, "External publication imprint mismatch."); goto cleanup; } } res = KSI_VerificationResult_addSuccess(info, step, "Verified online."); cleanup: KSI_Integer_free(start); KSI_ExtendReq_free(req); KSI_RequestHandle_free(handle); KSI_ExtendResp_free(resp); return res; }