static void testMaskingWithMetaDataMultiSig(CuTest *tc) { #define TEST_AGGR_RESPONSE_FILE "resource/tlv/test_meta_data_masking.tlv" static const unsigned char diceRolls[] = {0xd5, 0x58, 0xaf, 0xfa, 0x80, 0x67, 0xf4, 0x2c, 0xd9, 0x48, 0x36, 0x21, 0xd1, 0xab, 0xae, 0x23, 0xed, 0xd6, 0xca, 0x04, 0x72, 0x7e, 0xcf, 0xc7, 0xdb, 0xc7, 0x6b, 0xde, 0x34, 0x77, 0x1e, 0x53}; int res = KSI_UNKNOWN_ERROR; KSI_BlockSigner *bs = NULL; KSI_MultiSignature *ms = NULL; size_t i; KSI_DataHash *hsh = NULL; KSI_Signature *sig = NULL; KSI_DataHash *zero = NULL; KSI_OctetString *iv = NULL; /* Create zero hash. */ res = KSI_DataHash_createZero(ctx, KSI_HASHALG_SHA2_512, &zero); CuAssert(tc, "Unable to create zero hash.", res == KSI_OK && zero != NULL); /* Create random initial vector. */ res = KSI_OctetString_new(ctx, diceRolls, sizeof(diceRolls), &iv); CuAssert(tc, "Unable to create initial vector.", res == KSI_OK && iv != NULL); res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA1, zero, iv, &bs); CuAssert(tc, "Unable to create block signer instance with masking.", res == KSI_OK && bs != NULL); addInput(tc, bs, 1); res = KSI_CTX_setAggregator(ctx, getFullResourcePathUri(TEST_AGGR_RESPONSE_FILE), TEST_USER, TEST_PASS); CuAssert(tc, "Unable to set aggregator file URI.", res == KSI_OK); res = KSI_BlockSigner_close(bs, &ms); CuAssert(tc, "Unable to close block signer and extract multi signature.", res == KSI_OK && ms != NULL); res = KSITest_setDefaultPubfileAndVerInfo(ctx); CuAssert(tc, "Unable to set default pubfile, default cert and default pki constraints.", res == KSI_OK); /* Lets loop over all the inputs and try to verify them. */ for (i = 0; input_data[i] != NULL; i++) { res = KSI_DataHash_create(ctx, input_data[i], strlen(input_data[i]), KSI_HASHALG_SHA2_256, &hsh); CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to extract signature from the multi signature container.", res == KSI_OK && sig != NULL); res = KSI_Signature_verifyDocument(sig, ctx, (void *)input_data[i], strlen(input_data[i])); CuAssert(tc, "Unable to verify the input data.", res == KSI_OK); KSI_Signature_free(sig); sig = NULL; KSI_DataHash_free(hsh); hsh = NULL; } KSI_OctetString_free(iv); KSI_DataHash_free(zero); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); KSI_BlockSigner_free(bs); #undef TEST_AGGR_RESPONSE_FILE }
static void testVerifyDocumentHash(CuTest *tc) { int res; unsigned char in[0x1ffff]; unsigned in_len = 0; char doc[] = "LAPTOP"; KSI_DataHash *hsh = NULL; FILE *f = NULL; KSI_Signature *sig = NULL; KSI_ERR_clearErrors(ctx); f = fopen(getFullResourcePath(TEST_SIGNATURE_FILE), "rb"); CuAssert(tc, "Unable to open signature file.", f != NULL); in_len = (unsigned)fread(in, 1, sizeof(in), f); CuAssert(tc, "Nothing read from signature file.", in_len > 0); fclose(f); res = KSI_Signature_parse(ctx, in, in_len, &sig); CuAssert(tc, "Failed to parse signature", res == KSI_OK && sig != NULL); /* Chech correct document. */ res = KSI_DataHash_create(ctx, doc, strlen(doc), KSI_HASHALG_SHA2_256, &hsh); CuAssert(tc, "Failed to create data hash", res == KSI_OK && hsh != NULL); res = KSI_Signature_verifyDataHash(sig, ctx, hsh); CuAssert(tc, "Failed to verify valid document", res == KSI_OK); KSI_DataHash_free(hsh); hsh = NULL; /* Chech wrong document. */ res = KSI_DataHash_create(ctx, doc, sizeof(doc), KSI_HASHALG_SHA2_256, &hsh); CuAssert(tc, "Failed to create data hash", res == KSI_OK && hsh != NULL); res = KSI_Signature_verifyDataHash(sig, ctx, hsh); CuAssert(tc, "Verification did not fail with expected error.", res == KSI_VERIFICATION_FAILURE); KSI_DataHash_free(hsh); hsh = NULL; /* Check correct document with wrong hash algorithm. */ res = KSI_DataHash_create(ctx, doc, strlen(doc), KSI_HASHALG_SHA2_512, &hsh); CuAssert(tc, "Failed to create data hash", res == KSI_OK && hsh != NULL); res = KSI_Signature_verifyDataHash(sig, ctx, hsh); CuAssert(tc, "Verification did not fail with expected error.", res == KSI_VERIFICATION_FAILURE); KSI_DataHash_free(hsh); KSI_Signature_free(sig); }
static void testExtend(CuTest *tc) { int res; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_Signature *sig = NULL; KSI_PublicationRecord *pubRec = NULL; res = KSI_MultiSignature_fromFile(ctx, getFullResourcePath("resource/multi_sig/test2.mksi"), &ms); CuAssert(tc, "Unable to read multi signature container from file.", res == KSI_OK && ms != NULL); res = KSI_CTX_setExtender(ctx, getFullResourcePathUri("resource/multi_sig/test2-extend_response-multiple.tlv"), "anon", "anon"); CuAssert(tc, "Unable to set extender response from file", res == KSI_OK); res = KSI_MultiSignature_extend(ms); CuAssert(tc, "Unable to perform multi signature container extension.", res == KSI_OK); KSITest_DataHash_fromStr(ctx, "0111a700b0c8066c47ecba05ed37bc14dcadb238552d86c659342d1d7e87b8772d", &hsh); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to get signature from container.", res == KSI_OK && sig != NULL); res = KSI_verifySignature(ctx, sig); CuAssert(tc, "Unable to verify signature extracted from container.", res == KSI_OK); res = KSI_Signature_getPublicationRecord(sig, &pubRec); CuAssert(tc, "Signature should be extended.", res == KSI_OK && pubRec != NULL); KSI_Signature_free(sig); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); }
static void testGetOldest(CuTest *tc) { int res; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_Signature *sig = NULL; KSI_Integer *tm = NULL; res = KSI_MultiSignature_fromFile(ctx, getFullResourcePath("resource/multi_sig/test2.mksi"), &ms); CuAssert(tc, "Unable to read multi signature container from file.", res == KSI_OK && ms != NULL); KSITest_DataHash_fromStr(ctx, "0111a700b0c8066c47ecba05ed37bc14dcadb238552d86c659342d1d7e87b8772d", &hsh); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to get signature from container.", res == KSI_OK && sig != NULL); res = KSI_verifySignature(ctx, sig); CuAssert(tc, "Unable to verify signature extracted from container.", res == KSI_OK); res = KSI_Signature_getSigningTime(sig, &tm); CuAssert(tc, "Wrong signing time (probably returning the newer signature).", res == KSI_OK && KSI_Integer_equalsUInt(tm, 1398866256)); KSI_Signature_free(sig); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); }
static void addInput(CuTest *tc, KSI_BlockSigner *bs, int genMeta) { int res = KSI_UNKNOWN_ERROR; size_t i; KSI_DataHash *hsh = NULL; KSI_MetaData *md = NULL; for (i = 0; input_data[i] != NULL; i++) { res = KSI_DataHash_create(ctx, input_data[i], strlen(input_data[i]), KSI_HASHALG_SHA2_256, &hsh); CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL); if (genMeta) { char clientId[100]; KSI_snprintf(clientId, sizeof(clientId), "Client-%d", i); res = createMetaData(clientId, &md); CuAssert(tc, "Unable to create metadata.", res == KSI_OK && md != NULL); res = KSI_BlockSigner_addLeaf(bs, hsh, 0, md, NULL); CuAssert(tc, "Unable to add leaf with meta data.", res == KSI_OK); KSI_MetaData_free(md); md = NULL; } else { res = KSI_BlockSigner_add(bs, hsh); CuAssert(tc, "Unable to add data hash to the block signer.", res == KSI_OK); } KSI_DataHash_free(hsh); hsh = NULL; } }
static void testDeleteSignatureAppendedFromFile(CuTest *tc, const char *fname) { int res; KSI_MultiSignature *ms = NULL; KSI_Signature *sig = NULL; KSI_HashAlgorithm *arr = NULL; KSI_DataHash *hsh = NULL; res = KSI_MultiSignature_new(ctx, &ms); CuAssert(tc, "Unable to create multi signature container.", res == KSI_OK && ms != NULL); res = KSI_Signature_fromFile(ctx, fname, &sig); CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL); res = KSI_Signature_getDocumentHash(sig, &hsh); CuAssert(tc, "Unable to retrieve signed document hash from the signature.", res == KSI_OK && hsh != NULL); KSI_DataHash_ref(hsh); res = KSI_MultiSignature_add(ms, sig); CuAssert(tc, "Unable to add signature to multi signature container.", res == KSI_OK); KSI_Signature_free(sig); sig = NULL; res = KSI_MultiSignature_remove(ms, hsh); CuAssert(tc, "Unable to remove signature.", res == KSI_OK); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "There should not be a signature with this hash value anymore.", res == KSI_MULTISIG_NOT_FOUND && sig == NULL); /* TimeMapper list functions are not exported so we need to cast to generic list. */ CuAssert(tc, "The internal structure should be empty", KSI_List_length((KSI_List *)ms->timeList) == 0); KSI_MultiSignature_free(ms); KSI_DataHash_free(hsh); KSI_free(arr); }
int KSI_DataHash_createZero(KSI_CTX *ctx, KSI_HashAlgorithm algo_id, KSI_DataHash **hsh) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *tmp = NULL; unsigned char buf[KSI_MAX_IMPRINT_LEN]; if (ctx == NULL || hsh == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } memset(buf, 0, sizeof(buf)); buf[0] = algo_id; if (!KSI_isHashAlgorithmSupported(algo_id)) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, "Hash algorithm not supported."); goto cleanup; } res = KSI_DataHash_fromImprint(ctx, buf, (KSI_hashAlgorithmInfo[algo_id].outputBitCount >> 3) + 1, &tmp); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *hsh = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_DataHash_free(tmp); return res; }
static void testExtractingNotExisting(CuTest* tc) { int res; KSI_Signature *sig = NULL; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_ERR_clearErrors(ctx); res = KSI_Signature_fromFile(ctx, getFullResourcePath(TEST_SIGNATURE_FILE), &sig); CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL); res = KSI_MultiSignature_new(ctx, &ms); CuAssert(tc, "Unable to create multi signature container.", res == KSI_OK && ms != NULL); res = KSI_MultiSignature_add(ms, sig); CuAssert(tc, "Unable to add signature to multi signature container.", res == KSI_OK); KSI_Signature_free(sig); sig = NULL; KSITest_DataHash_fromStr(ctx, "01db27c0db0aebb8d3963c3a720985cedb600f91854cdb1e45ad631611c39284dd", &hsh); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Get should fail with KSI_MULTISIG_NOT_FOUND", res == KSI_MULTISIG_NOT_FOUND && sig == NULL); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); KSI_Signature_free(sig); }
static int verifyCalendarChainWithPublication(KSI_Signature *sig){ int res = KSI_UNKNOWN_ERROR; KSI_CalendarHashChain *calChain = NULL; KSI_Integer *pubTime = NULL; KSI_DataHash *rootHash = NULL; KSI_PublicationRecord *sigPubRec = NULL; KSI_PublicationData *sigPubData = NULL; KSI_DataHash *publishedHash = NULL; KSI_Integer *publishedTime = NULL; KSI_VerificationStep step = KSI_VERIFY_CALCHAIN_WITH_PUBLICATION; KSI_VerificationResult *info = &sig->verificationResult; if (sig->publication == NULL) { res = KSI_OK; goto cleanup; } KSI_LOG_debug(sig->ctx, "Verifying calendar chain with publication."); calChain = sig->calendarChain; res = KSI_CalendarHashChain_getPublicationTime(calChain, &pubTime); if (res != KSI_OK) goto cleanup; res = KSI_CalendarHashChain_aggregate(calChain, &rootHash); if (res != KSI_OK) goto cleanup; sigPubRec = sig->publication; res = KSI_PublicationRecord_getPublishedData(sigPubRec, &sigPubData); if (res != KSI_OK) goto cleanup; res = KSI_PublicationData_getImprint(sigPubData, &publishedHash); if (res != KSI_OK) goto cleanup; res = KSI_PublicationData_getTime(sigPubData, &publishedTime); if (res != KSI_OK) goto cleanup; if (!KSI_DataHash_equals(rootHash, publishedHash)){ KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Calendar root hash", rootHash); KSI_LOG_logDataHash(sig->ctx, KSI_LOG_DEBUG, "Published hash", publishedHash); res = KSI_VerificationResult_addFailure(info, step, "Published hash and calendar hash chain root hash mismatch."); goto cleanup; } if (!KSI_Integer_equals(pubTime, publishedTime)){ KSI_LOG_debug(sig->ctx, "Calendar hash chain publication time: %i.", KSI_Integer_getUInt64(pubTime)); KSI_LOG_debug(sig->ctx, "Published publication time: %i.", KSI_Integer_getUInt64(publishedTime)); res = KSI_VerificationResult_addFailure(info, step, "Calendar hash chain publication time mismatch."); goto cleanup; } res = KSI_VerificationResult_addSuccess(info, step, "Calendar chain verified with publication."); cleanup: KSI_DataHash_free(rootHash); return res; }
/** * 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 GetDocumentHash(char *fileName, KSI_Signature *sig, KSI_DataHash **hsh) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *tmp = NULL; KSI_DataHasher *hsr = NULL; FILE *in = NULL; unsigned char buf[1024]; size_t buf_len; if (fileName == NULL || sig == NULL || hsh == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } /* Create hasher. */ res = KSI_Signature_createDataHasher(sig, &hsr); if (res != KSI_OK) { fprintf(stderr, "Unable to create data hasher.\n"); goto cleanup; } /* Open the document for reading. */ in = fopen(fileName, "rb"); if (in == NULL) { fprintf(stderr, "Unable to open data file '%s'.\n", fileName); goto cleanup; } /* Calculate the hash of the document. */ while (!feof(in)) { buf_len = fread(buf, 1, sizeof(buf), in); res = KSI_DataHasher_add(hsr, buf, buf_len); if (res != KSI_OK) { fprintf(stderr, "Unable hash the document.\n"); goto cleanup; } } /* Finalize the hash computation. */ res = KSI_DataHasher_close(hsr, &tmp); if (res != KSI_OK) { fprintf(stderr, "Failed to close the hashing process.\n"); goto cleanup; } *hsh = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_DataHasher_free(hsr); KSI_DataHash_free(tmp); if (in != NULL) fclose(in); return res; }
static void testMultiSig(CuTest *tc) { #define TEST_AGGR_RESPONSE_FILE "resource/tlv/ok-aggr-resp-1460631424.tlv" int res = KSI_UNKNOWN_ERROR; KSI_BlockSigner *bs = NULL; KSI_MultiSignature *ms = NULL; size_t i; KSI_DataHash *hsh = NULL; KSI_Signature *sig = NULL; res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA1, NULL, NULL, &bs); CuAssert(tc, "Unable to create block signer instance.", res == KSI_OK && bs != NULL); addInput(tc, bs, 0); res = KSI_CTX_setAggregator(ctx, getFullResourcePathUri(TEST_AGGR_RESPONSE_FILE), TEST_USER, TEST_PASS); CuAssert(tc, "Unable to set aggregator file URI.", res == KSI_OK); res = KSI_BlockSigner_close(bs, &ms); CuAssert(tc, "Unable to close block signer and extract multi signature.", res == KSI_OK && ms != NULL); /* Lets loop over all the inputs and try to verify them. */ for (i = 0; input_data[i] != NULL; i++) { res = KSI_DataHash_create(ctx, input_data[i], strlen(input_data[i]), KSI_HASHALG_SHA2_256, &hsh); CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to extract signature from the multi signature container.", res == KSI_OK && sig != NULL); res = KSI_Signature_verifyDocument(sig, ctx, (void *)input_data[i], strlen(input_data[i])); CuAssert(tc, "Unable to verify the input data.", res == KSI_OK); KSI_Signature_free(sig); sig = NULL; KSI_DataHash_free(hsh); hsh = NULL; } KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); KSI_BlockSigner_free(bs); #undef TEST_AGGR_RESPONSE_FILE }
static void testMaskingInput(CuTest *tc) { static const unsigned char diceRolls[] = {0xd5, 0x58, 0xaf, 0xfa, 0x80, 0x67, 0xf4, 0x2c, 0xd9, 0x48, 0x36, 0x21, 0xd1, 0xab, 0xae, 0x23, 0xed, 0xd6, 0xca, 0x04, 0x72, 0x7e, 0xcf, 0xc7, 0xdb, 0xc7, 0x6b, 0xde, 0x34, 0x77, 0x1e, 0x53}; int res; KSI_BlockSigner *bs = NULL; KSI_OctetString *iv = NULL; KSI_DataHash *zero = NULL; size_t i; struct { KSI_CTX *ctx; KSI_HashAlgorithm algo_id; KSI_DataHash *prevHash; KSI_OctetString *iv; KSI_BlockSigner **bs; int expectedRes; } tests[] = { {NULL, KSI_HASHALG_SHA3_512, NULL, NULL, NULL, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA3_512, NULL, NULL, &bs, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA3_512, NULL, iv, &bs, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA3_512, zero, NULL, &bs, KSI_INVALID_ARGUMENT}, {ctx, KSI_HASHALG_SHA3_512, NULL, NULL, &bs, KSI_UNAVAILABLE_HASH_ALGORITHM}, {NULL, KSI_HASHALG_SHA2_512, NULL, NULL, NULL, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA2_512, NULL, NULL, &bs, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA2_512, NULL, iv, &bs, KSI_INVALID_ARGUMENT}, {NULL, KSI_HASHALG_SHA2_512, zero, NULL, &bs, KSI_INVALID_ARGUMENT}, {ctx, KSI_HASHALG_SHA2_512, zero, NULL, &bs, KSI_OK}, {NULL, -1, NULL, NULL, NULL, -1} }; /* Create zero hash. */ res = KSI_DataHash_createZero(ctx, KSI_HASHALG_SHA2_512, &zero); CuAssert(tc, "Unable to create zero hash.", res == KSI_OK && zero != NULL); /* Create random initial vector. */ res = KSI_OctetString_new(ctx, diceRolls, sizeof(diceRolls), &iv); CuAssert(tc, "Unable to create initial vector.", res == KSI_OK && iv != NULL); res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA1, zero, iv, &bs); CuAssert(tc, "Unable to create block signer instance with masking.", res == KSI_OK && bs != NULL); for (i = 0; tests[i].expectedRes != -1; i++) { res = KSI_BlockSigner_new(tests[i].ctx, tests[i].algo_id, tests[i].prevHash, tests[i].iv, tests[i].bs); KSI_BlockSigner_free(bs); bs = NULL; if (res != tests[i].expectedRes) { char buf[1000]; KSI_snprintf(buf, sizeof(buf), "Unexpected result @%i (expected = '%s', but was '%s').", i, KSI_getErrorString(tests[i].expectedRes), KSI_getErrorString(res)); CuFail(tc, buf); } } KSI_OctetString_free(iv); KSI_DataHash_free(zero); }
static void testFindPublicationByPubStr(CuTest *tc) { static const char publication[] = "AAAAAA-CTJR3I-AANBWU-RY76YF-7TH2M5-KGEZVA-WLLRGD-3GKYBG-AM5WWV-4MCLSP-XPRDDI-UFMHBA"; 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; 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_PublicationsFile_getPublicationDataByPublicationString(pubFile, publication, &pubRec); CuAssert(tc, "Unable to get publication record by publication string.", 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); 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 data hash 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)); KSI_DataHash_free(expHsh); KSI_PublicationsFile_free(pubFile); KSI_CTX_free(ctx); }
static void testReset(CuTest *tc) { #define TEST_AGGR_RESPONSE_FILE "resource/tlv/ok-sig-2014-07-01.1-aggr_response.tlv" int res = KSI_UNKNOWN_ERROR; KSI_BlockSigner *bs = NULL; KSI_DataHash *hsh = NULL; KSI_BlockSignerHandle *h = NULL; KSI_Signature *sig = NULL; unsigned char *raw = NULL; size_t len = 0; res = KSI_CTX_setAggregator(ctx, getFullResourcePathUri(TEST_AGGR_RESPONSE_FILE), TEST_USER, TEST_PASS); CuAssert(tc, "Unable to set aggregator file URI.", res == KSI_OK); res = KSITest_DataHash_fromStr(ctx, "0111a700b0c8066c47ecba05ed37bc14dcadb238552d86c659342d1d7e87b8772d", &hsh); CuAssert(tc, "Unable to create data hash.", res == KSI_OK && hsh != NULL); res = KSI_BlockSigner_new(ctx, KSI_HASHALG_SHA1, NULL, NULL, &bs); CuAssert(tc, "Unable to create block signer instance.", res == KSI_OK && bs != NULL); /* Add the temporary leafs. */ res = KSI_BlockSigner_addLeaf(bs, hsh, 0, NULL, NULL); CuAssert(tc, "Unable to add 1st mock hash to the blocksigner.", res == KSI_OK); res = KSI_BlockSigner_addLeaf(bs, hsh, 0, NULL, NULL); CuAssert(tc, "Unable to add 2nd hash to the blocksigner.", res == KSI_OK); res = KSI_BlockSigner_addLeaf(bs, hsh, 0, NULL, NULL); CuAssert(tc, "Unable to add 3rd hash to the blocksigner.", res == KSI_OK); res = KSI_BlockSigner_reset(bs); CuAssert(tc, "Unable to reset the block signer.", res == KSI_OK); res = KSI_BlockSigner_addLeaf(bs, hsh, 0, NULL, &h); CuAssert(tc, "Unable to add actual hash to the blocksigner.", res == KSI_OK && h != NULL); res = KSI_BlockSigner_close(bs, NULL); CuAssert(tc, "Unable to close blocksigner.", res == KSI_OK); res = KSI_BlockSignerHandle_getSignature(h, &sig); CuAssert(tc, "Unable to extract signature from the blocksigner.", res == KSI_OK && sig != NULL); res = KSI_Signature_serialize(sig, &raw, &len); CuAssert(tc, "Unable to serialize signature.", res == KSI_OK && raw != NULL && len > 0); KSI_LOG_logBlob(ctx, KSI_LOG_DEBUG, "Serialized single signature from block signer.", raw, len); KSI_BlockSignerHandle_free(h); KSI_Signature_free(sig); KSI_BlockSigner_free(bs); KSI_DataHash_free(hsh); KSI_free(raw); #undef TEST_AGGR_RESPONSE_FILE }
static int verifyCalendarChain(KSI_Signature *sig) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *rootHash = NULL; KSI_Integer *calendarPubTm = NULL; KSI_PublicationData *pubData = NULL; KSI_DataHash *pubHash = NULL; KSI_Integer *pubTime = NULL; KSI_VerificationStep step = KSI_VERIFY_CALCHAIN_WITH_CALAUTHREC; KSI_VerificationResult *info = &sig->verificationResult; if (sig->calendarAuthRec == NULL) { res = KSI_OK; goto cleanup; } KSI_LOG_info(sig->ctx, "Verifying calendar hash chain."); /* Calculate the root hash value. */ res = KSI_CalendarHashChain_aggregate(sig->calendarChain, &rootHash); if (res != KSI_OK) goto cleanup; /* Get the publication time from calendar hash chain. */ res = KSI_CalendarHashChain_getPublicationTime(sig->calendarChain, &calendarPubTm); if (res != KSI_OK) goto cleanup; /* Get publication data. */ res = KSI_CalendarAuthRec_getPublishedData(sig->calendarAuthRec, &pubData); if (res != KSI_OK) goto cleanup; /* Get published hash value. */ res = KSI_PublicationData_getImprint(pubData, &pubHash); if (res != KSI_OK) goto cleanup; /* Get publication time. */ res = KSI_PublicationData_getTime(pubData, &pubTime); if (res != KSI_OK) goto cleanup; if (KSI_Integer_equals(calendarPubTm, pubTime) && KSI_DataHash_equals(rootHash, pubHash)) { res = KSI_VerificationResult_addSuccess(info, step, "Calendar chain and authentication record match."); } else { res = KSI_VerificationResult_addFailure(info, step, "Calendar chain and authentication record mismatch."); } if (res != KSI_OK) goto cleanup; res = KSI_OK; cleanup: KSI_DataHash_free(rootHash); return res; }
int KSI_DataHash_fromDigest(KSI_CTX *ctx, KSI_HashAlgorithm algo_id, const unsigned char *digest, size_t digest_length, KSI_DataHash **hash) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *tmp_hash = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || digest == NULL || digest_length == 0 || hash == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } /* Make sure the algorithm is supported. */ if (!KSI_isHashAlgorithmSupported(algo_id)) { KSI_pushError(ctx, res = KSI_UNAVAILABLE_HASH_ALGORITHM, "Hash algorithm not supported."); goto cleanup; } /* Verify the length of the digest with the algorithm. */ if (KSI_getHashLength(algo_id) != digest_length) { KSI_pushError(ctx, res = KSI_INVALID_FORMAT, "Digest length does not match with algorithm."); goto cleanup; } /* Make sure it fits. */ if (digest_length > KSI_MAX_IMPRINT_LEN) { KSI_pushError(ctx, res = KSI_CRYPTO_FAILURE, "Internal buffer too short to hold imprint"); goto cleanup; } tmp_hash = KSI_new(KSI_DataHash); if (tmp_hash == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } tmp_hash->ref = 1; tmp_hash->ctx = ctx; tmp_hash->imprint[0] = (unsigned char)algo_id; memcpy(tmp_hash->imprint + 1, digest, digest_length); tmp_hash->imprint_length = digest_length + 1; *hash = tmp_hash; tmp_hash = NULL; res = KSI_OK; cleanup: KSI_DataHash_free(tmp_hash); 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]; 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); }
int KSI_DataHash_create(KSI_CTX *ctx, const void *data, size_t data_length, KSI_HashAlgorithm algo_id, KSI_DataHash **hash) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *hsh = NULL; KSI_DataHasher *hsr = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || hash == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } res = KSI_DataHasher_open(ctx, algo_id, &hsr); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (data != NULL && data_length > 0) { res = KSI_DataHasher_add(hsr, data, data_length); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } } res = KSI_DataHasher_close(hsr, &hsh); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *hash = hsh; hsh = NULL; res = KSI_OK; cleanup: KSI_DataHash_free(hsh); KSI_DataHasher_free(hsr); return res; }
static void testParseAndVerifySingle(CuTest *tc) { int res; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_Signature *sig = NULL; createMultiSignatureFromFile(tc, getFullResourcePath("resource/multi_sig/test1.mksi"), &ms); KSITest_DataHash_fromStr(ctx, "0111a700b0c8066c47ecba05ed37bc14dcadb238552d86c659342d1d7e87b8772d", &hsh); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to get signature from container.", res == KSI_OK && sig != NULL); res = KSI_verifySignature(ctx, sig); CuAssert(tc, "Unable to verify signature extracted from container.", res == KSI_OK); KSI_Signature_free(sig); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); }
static void testExtractingFromEmpty(CuTest* tc) { int res; KSI_Signature *sig = NULL; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_ERR_clearErrors(ctx); KSITest_DataHash_fromStr(ctx, "01db27c0db0aebb8d3963c3a720985cedb600f91854cdb1e45ad631611c39284dd", &hsh); res = KSI_MultiSignature_new(ctx, &ms); CuAssert(tc, "Unable to create multi signature container.", res == KSI_OK && ms != NULL); res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Get should fail with KSI_MULTISIG_NOT_FOUND", res == KSI_MULTISIG_NOT_FOUND && sig == NULL); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); KSI_Signature_free(sig); }
int KSI_HMAC_create(KSI_CTX *ctx, KSI_HashAlgorithm algo_id, const char *key, const unsigned char *data, size_t data_len, KSI_DataHash **hmac) { int res = KSI_UNKNOWN_ERROR; KSI_HmacHasher *hasher = NULL; KSI_DataHash *tmp_hmac = NULL; KSI_ERR_clearErrors(ctx); if (ctx == NULL || hmac == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } res = KSI_HmacHasher_open(ctx, algo_id, key, &hasher); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_HmacHasher_add(hasher, data, data_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_HmacHasher_close(hasher, &tmp_hmac); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *hmac = tmp_hmac; tmp_hmac = NULL; res = KSI_OK; cleanup: KSI_DataHash_free(tmp_hmac); KSI_HmacHasher_free(hasher); return res; }
static void testFindPublicationByPubStr(CuTest *tc) { static const char publication[] = "AAAAAA-CTJR3I-AANBWU-RY76YF-7TH2M5-KGEZVA-WLLRGD-3GKYBG-AM5WWV-4MCLSP-XPRDDI-UFMHBA"; 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; 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_PublicationsFile_getPublicationDataByPublicationString(pubFile, publication, &pubRec); CuAssert(tc, "Unable to get publication record by publication string.", 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); 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 data hash 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)); KSI_DataHash_free(expHsh); }
int KSI_DataHash_fromTlv(KSI_TLV *tlv, KSI_DataHash **hsh) { int res = KSI_UNKNOWN_ERROR; KSI_CTX *ctx = NULL; const unsigned char *raw = NULL; size_t raw_len = 0; KSI_DataHash *tmp = NULL; ctx = KSI_TLV_getCtx(tlv); KSI_ERR_clearErrors(ctx); if (tlv == NULL || hsh == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } res = KSI_TLV_getRawValue(tlv, &raw, &raw_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_DataHash_fromImprint(ctx, raw, raw_len, &tmp); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *hsh = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_nofree(ctx); KSI_nofree(raw); KSI_DataHash_free(tmp); return res; }
int KSI_DataHasher_close(KSI_DataHasher *hasher, KSI_DataHash **data_hash) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *hsh = NULL; if (hasher == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(hasher->ctx); hsh = KSI_new(KSI_DataHash); if (hsh == NULL) { KSI_pushError(hasher->ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } hsh->ref = 1; hsh->ctx = hasher->ctx; res = hasher->closeExisting(hasher, hsh); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } if (data_hash != NULL) { *data_hash = hsh; hsh = NULL; } res = KSI_OK; cleanup: KSI_DataHash_free(hsh); return res; }
static void testExtractingSingleLegacy(CuTest* tc) { int res; KSI_Signature *sig = NULL; KSI_MultiSignature *ms = NULL; KSI_DataHash *hsh = NULL; KSI_ERR_clearErrors(ctx); res = KSI_Signature_fromFile(ctx, getFullResourcePath("resource/tlv/ok-legacy-sig-2014-06.gtts.ksig"), &sig); CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL); res = KSI_Signature_getDocumentHash(sig, &hsh); CuAssert(tc, "Unable to get signed hash value.", res == KSI_OK && hsh != NULL); KSI_DataHash_ref(hsh); res = KSI_MultiSignature_new(ctx, &ms); CuAssert(tc, "Unable to create multi signature container.", res == KSI_OK && ms != NULL); res = KSI_MultiSignature_add(ms, sig); CuAssert(tc, "Unable to add signature to multi signature container.", res == KSI_OK); KSI_Signature_free(sig); sig = NULL; res = KSI_MultiSignature_get(ms, hsh, &sig); CuAssert(tc, "Unable to extract signature from multi signature container.", res == KSI_OK && sig != NULL); res = KSI_verifySignature(ctx, sig); CuAssert(tc, "Unable to verify extracted signature.", res == KSI_OK); KSI_DataHash_free(hsh); KSI_MultiSignature_free(ms); KSI_Signature_free(sig); }
KSI_END_TLV_TEMPLATE static int replaceCalendarChain(KSI_Signature *sig, KSI_CalendarHashChain *calendarHashChain) { int res; KSI_DataHash *aggrOutputHash = NULL; KSI_TLV *oldCalChainTlv = NULL; KSI_TLV *newCalChainTlv = NULL; KSI_LIST(KSI_TLV) *nestedList = NULL; size_t i; if (sig == NULL || calendarHashChain == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(sig->ctx); res = KSI_TLV_getNestedList(sig->baseTlv, &nestedList); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } if (sig->calendarChain != NULL) { for (i = 0; i < KSI_TLVList_length(nestedList); i++) { res = KSI_TLVList_elementAt(nestedList,i, &oldCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } if (oldCalChainTlv == NULL) { KSI_pushError(sig->ctx, res = KSI_INVALID_SIGNATURE, "Signature TLV element missing."); goto cleanup; } if (KSI_TLV_getTag(oldCalChainTlv) == 0x0802) break; } } res = KSI_TLV_new(sig->ctx, 0x0802, 0, 0, &newCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } res = KSI_TlvTemplate_construct(sig->ctx, newCalChainTlv, calendarHashChain, KSI_TLV_TEMPLATE(KSI_CalendarHashChain)); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } res = (sig->calendarChain == NULL) ? /* In case there is no calendar hash chain attached, append a new one. */ KSI_TLV_appendNestedTlv(sig->baseTlv, newCalChainTlv) : /* Otherwise replace the calendar hash chain. */ KSI_TLV_replaceNestedTlv(sig->baseTlv, oldCalChainTlv, newCalChainTlv); if (res != KSI_OK) { KSI_pushError(sig->ctx, res, NULL); goto cleanup; } newCalChainTlv = NULL; /* The memory was freed within KSI_TLV_replaceNestedTlv. */ oldCalChainTlv = NULL; KSI_CalendarHashChain_free(sig->calendarChain); sig->calendarChain = calendarHashChain; res = KSI_OK; cleanup: KSI_nofree(nestedList); KSI_DataHash_free(aggrOutputHash); KSI_TLV_free(newCalChainTlv); 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); }
int main(int argc, char **argv) { KSI_CTX *ksi = NULL; int res = KSI_UNKNOWN_ERROR; FILE *in = NULL; FILE *out = NULL; KSI_DataHasher *hsr = NULL; KSI_DataHash *hsh = NULL; KSI_Signature *sign = NULL; unsigned char *raw = NULL; unsigned raw_len; unsigned char buf[1024]; unsigned buf_len; char *signerIdentity = NULL; FILE *logFile = NULL; /* Handle command line parameters */ /* Handle command line parameters */ if (argc != 7) { fprintf(stderr, "Usage:\n" " %s <in-data-file> <out-sign-file> <aggregator-uri> <user> <pass> <pub-file url | -> \n", argv[0]); res = KSI_INVALID_ARGUMENT; goto cleanup; } /* Input file */ in = fopen(argv[1], "rb"); if (in == NULL) { fprintf(stderr, "Unable to open input file '%s'\n", argv[1]); res = KSI_IO_ERROR; goto cleanup; } /* Create new KSI context for this thread. */ res = KSI_CTX_new(&ksi); if (res != KSI_OK) { fprintf(stderr, "Unable to create context.\n"); goto cleanup; } logFile = fopen("ksi_sign.log", "w"); if (logFile == NULL) { fprintf(stderr, "Unable to open log file.\n"); } KSI_CTX_setLoggerCallback(ksi, KSI_LOG_StreamLogger, logFile); KSI_CTX_setLogLevel(ksi, KSI_LOG_DEBUG); KSI_LOG_info(ksi, "Using KSI version: '%s'", KSI_getVersion()); res = KSI_CTX_setAggregator(ksi, argv[3], argv[4], argv[5]); if (res != KSI_OK) goto cleanup; /* Check publications file url. */ if (strncmp("-", argv[6], 1)) { res = KSI_CTX_setPublicationUrl(ksi, argv[6]); if (res != KSI_OK) { fprintf(stderr, "Unable to set publications file url.\n"); goto cleanup; } } /* Create a data hasher using default algorithm. */ res = KSI_DataHasher_open(ksi, KSI_getHashAlgorithmByName("default"), &hsr); if (res != KSI_OK) { fprintf(stderr, "Unable to create hasher.\n"); goto cleanup; } /* Read the input file and calculate the hash of its contents. */ while (!feof(in)) { buf_len = (unsigned)fread(buf, 1, sizeof(buf), in); /* Add next block to the calculation. */ res = KSI_DataHasher_add(hsr, buf, buf_len); if (res != KSI_OK) { fprintf(stderr, "Unable to add data to hasher.\n"); goto cleanup; } } /* Close the data hasher and retreive the data hash. */ res = KSI_DataHasher_close(hsr, &hsh); if (res != KSI_OK) { fprintf(stderr, "Unable to create hash.\n"); goto cleanup; } /* Sign the data hash. */ res = KSI_createSignature(ksi, hsh, &sign); if (res != KSI_OK) { fprintf(stderr, "Unable to sign %d.\n", res); goto cleanup; } res = KSI_Signature_verify(sign, ksi); if (res != KSI_OK) { fprintf(stderr, "Failed to verify signature.\n"); goto cleanup; } /* Output the signer id */ res = KSI_Signature_getSignerIdentity(sign, &signerIdentity); if (res == KSI_OK) { printf("Signer id: %s\n", signerIdentity); } else { fprintf(stderr, "Unable to extract signer identity.\n"); } /* Serialize the signature. */ res = KSI_Signature_serialize(sign, &raw, &raw_len); if (res != KSI_OK) { fprintf(stderr, "Unable to serialize signature."); goto cleanup; } /* Output file */ out = fopen(argv[2], "wb"); if (out == NULL) { fprintf(stderr, "Unable to open input file '%s'\n", argv[2]); res = KSI_IO_ERROR; goto cleanup; } /* Write the signature file. */ if (!fwrite(raw, 1, raw_len, out)) { fprintf(stderr, "Unable to write output file.\n"); res = KSI_IO_ERROR; goto cleanup; } /* Only print message when signature output is not stdout. */ if (out != NULL) { printf("Signature saved.\n"); } res = KSI_OK; cleanup: if (logFile != NULL) fclose(logFile); if (res != KSI_OK && ksi != NULL) { KSI_ERR_statusDump(ksi, stderr); } if (in != NULL) fclose(in); if (out != NULL) fclose(out); KSI_free(signerIdentity); KSI_Signature_free(sign); KSI_DataHash_free(hsh); KSI_DataHasher_free(hsr); KSI_free(raw); KSI_CTX_free(ksi); return res; }