static void testVerifySignatureWithUserPublication(CuTest *tc) { int res; KSI_Signature *sig = NULL; const char pubStr[] = "AAAAAA-CTOQBY-AAMJYH-XZPM6T-UO6U6V-2WJMHQ-EJMVXR-JEAGID-2OY7P5-XFFKYI-QIF2LG-YOV7SO"; const char pubStr_bad[] = "AAAAAA-CT5VGY-AAPUCF-L3EKCC-NRSX56-AXIDFL-VZJQK4-WDCPOE-3KIWGB-XGPPM3-O5BIMW-REOVR4"; KSI_PublicationData *pubData = NULL; KSI_PublicationData *pubData_bad = NULL; KSI_ERR_clearErrors(ctx); res = KSI_PublicationData_fromBase32(ctx, pubStr, &pubData); CuAssert(tc, "Unable to parse publication string.", res == KSI_OK && pubData != NULL); res = KSI_PublicationData_fromBase32(ctx, pubStr_bad, &pubData_bad); CuAssert(tc, "Unable to parse publication string.", res == KSI_OK && pubData_bad != NULL); res = KSI_Signature_fromFile(ctx, getFullResourcePath("resource/tlv/ok-sig-2014-04-30.1-extended.ksig"), &sig); CuAssert(tc, "Unable to read signature from file.", res == KSI_OK && sig != NULL); res = KSI_Signature_verifyWithPublication(sig, ctx, pubData); CuAssert(tc, "Unable to verify signature with publication.", res == KSI_OK); res = KSI_Signature_verifyWithPublication(sig, ctx, pubData_bad); CuAssert(tc, "Unable to verify signature with publication.", res != KSI_OK); KSI_PublicationData_free(pubData); KSI_PublicationData_free(pubData_bad); KSI_Signature_free(sig); }
static void testPublicationStringEncodingAndDecoding(CuTest *tc) { static const char publication[] = "AAAAAA-CTJR3I-AANBWU-RY76YF-7TH2M5-KGEZVA-WLLRGD-3GKYBG-AM5WWV-4MCLSP-XPRDDI-UFMHBA"; char *out = NULL; int res; KSI_PublicationData *pub = NULL; KSI_ERR_clearErrors(ctx); res = KSI_PublicationData_fromBase32(ctx, publication, &pub); CuAssert(tc, "Failed decoding publication string.", res == KSI_OK && pub != NULL); res = KSI_PublicationData_toBase32(pub, &out); CuAssert(tc, "Failed encoding the published data object", res == KSI_OK && out != NULL); CuAssert(tc, "Invalid encoded publication string does not match original.", !strncmp(publication, out, strlen(publication))); KSI_PublicationData_free(pub); KSI_free(out); }
int KSI_PublicationsFile_getPublicationDataByPublicationString(const KSI_PublicationsFile *pubFile, const char *pubString, KSI_PublicationRecord **pubRec) { int res; KSI_PublicationData *findPubData = NULL; KSI_DataHash *findImprint = NULL; KSI_Integer *findTime = NULL; KSI_PublicationRecord *tmpPubRec = NULL; KSI_PublicationData *tmpPubData = NULL; KSI_DataHash *tmpImprint = NULL; if (pubFile == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(pubFile->ctx); if (pubString == NULL || pubRec == NULL) { KSI_pushError(pubFile->ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } /* Decode the publication string. */ res = KSI_PublicationData_fromBase32(pubFile->ctx, pubString, &findPubData); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } /* Extract the expected imprint. */ res = KSI_PublicationData_getImprint(findPubData, &findImprint); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } /* Extract the expected publication time. */ res = KSI_PublicationData_getTime(findPubData, &findTime); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } /* Find the publication using the publication time. */ res = KSI_PublicationsFile_getPublicationDataByTime(pubFile, findTime, &tmpPubRec); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } if (tmpPubRec != NULL) { /* Extract published data. */ res = KSI_PublicationRecord_getPublishedData(tmpPubRec, &tmpPubData); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } /* Extract the time. */ res = KSI_PublicationData_getImprint(tmpPubData, &tmpImprint); if (res != KSI_OK) { KSI_pushError(pubFile->ctx, res, NULL); goto cleanup; } if (!KSI_DataHash_equals(findImprint, tmpImprint)) { KSI_pushError(pubFile->ctx, res = KSI_INVALID_PUBLICATION, NULL); goto cleanup; } } *pubRec = tmpPubRec; res = KSI_OK; cleanup: KSI_PublicationData_free(findPubData); KSI_nofree(findImprint); KSI_nofree(findTime); KSI_nofree(tmpPubRec); KSI_nofree(tmpPubData); KSI_nofree(tmpImprint); return res; }
/** * This function extends the signature to the given publication. * \param[in] sig Initial signature. * \param[in] pubStr Null-terminated c string of the publication. * \param[out] ext Pointer to the receiving pointer to the extended signature. * \return Returns KSI_OK if successful. */ static int extendToPublication(KSI_Signature *sig, const char *pubStr, KSI_Signature **ext) { int res = KSI_UNKNOWN_ERROR; /* Only the published data. */ KSI_PublicationData *pubData = NULL; /* Published data and the references to the actual publications. */ KSI_PublicationRecord *pubRec = NULL; /* Publication time. */ KSI_Integer *pubTime = NULL; /* Signature signing time. */ KSI_Integer *signTime = NULL; /* Parse the publications string. */ res = KSI_PublicationData_fromBase32(ksi, pubStr, &pubData); if (res != KSI_OK) { fprintf(stderr, "Invalid publication: '%s'\n", pubStr); goto cleanup; } /* Verify the publication is newer than the signature. */ res = KSI_Signature_getSigningTime(sig, &signTime); if (res != KSI_OK) goto cleanup; res = KSI_PublicationData_getTime(pubData, &pubTime); if (res != KSI_OK) goto cleanup; if (KSI_Integer_compare(signTime, pubTime) > 0) { fprintf(stderr, "Signature created after publication.\n"); res = KSI_INVALID_ARGUMENT; goto cleanup; } /* Create a publication record. */ res = KSI_PublicationRecord_new(ksi, &pubRec); if (res != KSI_OK) goto cleanup; /* Set the published data value. */ res = KSI_PublicationRecord_setPublishedData(pubRec, pubData); if (res != KSI_OK) goto cleanup; /* The pointer will be free by KSI_PublicatioinRecord_free. */ pubData = NULL; /* NB! If the user wants to store the extended signature, some publication references should * be added to the publication reference. As we are going to discard the signature after * verification, the references are not important. */ /* Extend the signature to the publication. */ res = KSI_Signature_extend(sig, ksi, pubRec, ext); if (res != KSI_OK) { fprintf(stderr, "Unable to to extend the signature to the given publication: '%s'\n", pubStr); goto cleanup; } res = KSI_OK; cleanup: /* We can cleanup the values. */ KSI_PublicationData_free(pubData); KSI_PublicationRecord_free(pubRec); return res; }