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; }
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; }
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; }
int main(int argc, char **argv) { int res = KSI_UNKNOWN_ERROR; /* Signature read from the file. */ KSI_Signature *sig = NULL; /* Signature extended to the publication. */ KSI_Signature *ext = NULL; /* Hash of the data file. */ KSI_DataHash *hsh = NULL; /* Hash value extracted from the signature. */ KSI_DataHash *signHsh = NULL; /* Data file hasher. */ KSI_DataHasher *hsr = NULL; /* Input file descriptor. */ FILE *in = NULL; /* Buffer for reading the input. */ unsigned char buf[1024]; /* Length of the buffer content. */ size_t buf_len; /* Verification info object. */ const KSI_VerificationResult *info = NULL; /* File descriptor for logging. */ FILE *logFile = NULL; const KSI_CertConstraint pubFileCertConstr[] = { { KSI_CERT_EMAIL, "*****@*****.**"}, { NULL, NULL } }; /* Init context. */ res = KSI_CTX_new(&ksi); if (res != KSI_OK) { fprintf(stderr, "Unable to init KSI context.\n"); goto cleanup; } logFile = fopen("ksi_verify.log", "w"); if (logFile == NULL) { fprintf(stderr, "Unable to open log file.\n"); } res = KSI_CTX_setDefaultPubFileCertConstraints(ksi, pubFileCertConstr); if (res != KSI_OK) { fprintf(stderr, "Unable to configure publications file cert constraints.\n"); goto cleanup; } /* Configure the logger. */ 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()); /* Check parameters. */ if (argc != 6) { fprintf(stderr, "Usage\n" " %s <data file | -> <signature> <publication-str> <extender url> <pub-file url>\n", argv[0]); goto cleanup; } /* Configure extender. */ res = KSI_CTX_setExtender(ksi, argv[4], "anon", "anon"); if (res != KSI_OK) { fprintf(stderr, "Unable to set extender parameters.\n"); goto cleanup; } /* Set the publications file url. */ res = KSI_CTX_setPublicationUrl(ksi, argv[4]); if (res != KSI_OK) { fprintf(stderr, "Unable to set publications file url.\n"); goto cleanup; } printf("Reading signature... "); /* Read the signature. */ res = KSI_Signature_fromFile(ksi, argv[2], &sig); if (res != KSI_OK) { printf("failed (%s)\n", KSI_getErrorString(res)); goto cleanup; } printf("ok\n"); printf("Verifying the signature with the publication... "); res = extendToPublication(sig, argv[3], &ext); switch (res) { case KSI_OK: printf("ok\n"); break; case KSI_VERIFICATION_FAILURE: printf("failed\n"); break; default: printf("failed (%s)\n", KSI_getErrorString(res)); goto cleanup; } /* Create hasher. */ res = KSI_Signature_createDataHasher(ext, &hsr); if (res != KSI_OK) { fprintf(stderr, "Unable to create data hasher.\n"); goto cleanup; } if (strcmp(argv[1], "-")) { in = fopen(argv[1], "rb"); if (in == NULL) { fprintf(stderr, "Unable to open data file '%s'.\n", argv[1]); 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, &hsh); if (res != KSI_OK) { fprintf(stderr, "Failed to close the hashing process.\n"); goto cleanup; } res = KSI_Signature_getDocumentHash(sig, &signHsh); if (res != KSI_OK) goto cleanup; printf("Verifying document hash... "); if (!KSI_DataHash_equals(hsh, signHsh)) { printf("Wrong document!\n"); goto cleanup; } printf("ok\n"); } res = KSI_Signature_getVerificationResult(ext, &info); if (res != KSI_OK) goto cleanup; if (info != NULL) { size_t i; printf("Verification info:\n"); for (i = 0; i < KSI_VerificationResult_getStepResultCount(info); i++) { const KSI_VerificationStepResult *result = NULL; const char *desc = NULL; res = KSI_VerificationResult_getStepResult(info, i, &result); if (res != KSI_OK) goto cleanup; printf("\t0x%02x:\t%s", KSI_VerificationStepResult_getStep(result), KSI_VerificationStepResult_isSuccess(result) ? "OK" : "FAIL"); desc = KSI_VerificationStepResult_getDescription(result); if (desc && *desc) { printf(" (%s)", desc); } printf("\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); KSI_Signature_free(sig); KSI_Signature_free(ext); KSI_DataHasher_free(hsr); KSI_DataHash_free(hsh); KSI_CTX_free(ksi); return res; }
KSI_VERIFY_PUBFILE_SIGNATURE | KSI_VERIFY_AGGRCHAIN_INTERNALLY | KSI_VERIFY_AGGRCHAIN_WITH_CALENDAR_CHAIN | KSI_VERIFY_CALCHAIN_ONLINE KSI_END_VERIFICATION_POLICY static int rfc3161_preSufHasher(KSI_CTX *ctx, const KSI_OctetString *prefix, const KSI_DataHash *hsh, const KSI_OctetString *suffix, int hsh_id, KSI_DataHash **out) { int res; KSI_DataHasher *hsr = NULL; KSI_DataHash *tmp = NULL; const unsigned char *imprint = NULL; size_t imprint_len = 0; const unsigned char *data = NULL; size_t data_len = 0; KSI_ERR_clearErrors(ctx); if (ctx == NULL || prefix == NULL || hsh == NULL || suffix == NULL || out == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } /*Generate TST Info structure and get its hash*/ res = KSI_DataHasher_open(ctx, hsh_id, &hsr); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_OctetString_extract(prefix, &data, &data_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (data != NULL) { res = KSI_DataHasher_add(hsr, data, data_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } } res = KSI_DataHash_getImprint(hsh, &imprint, &imprint_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_DataHasher_add(hsr, imprint + 1, imprint_len - 1); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_OctetString_extract(suffix, &data, &data_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (data != NULL) { res = KSI_DataHasher_add(hsr, data, data_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } } /*Get hash and its imprint*/ res = KSI_DataHasher_close(hsr, &tmp); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *out = tmp; tmp = NULL; res = KSI_OK; cleanup: KSI_DataHasher_free(hsr); KSI_DataHash_free(tmp); return res; }
int KSI_HmacHasher_open(KSI_CTX *ctx, KSI_HashAlgorithm algo_id, const char *key, KSI_HmacHasher **hasher) { int res = KSI_UNKNOWN_ERROR; KSI_HmacHasher *tmp_hasher = NULL; KSI_DataHash *hashedKey = NULL; unsigned blockSize = 0; size_t key_len; const unsigned char *bufKey = NULL; size_t buf_len; const unsigned char *digest = NULL; size_t digest_len = 0; size_t i; KSI_ERR_clearErrors(ctx); if (ctx == NULL || key == NULL || hasher == NULL) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, NULL); goto cleanup; } key_len = strlen(key); if (key_len == 0 || key_len > 0xffff) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "Invalid key length."); goto cleanup; } blockSize = KSI_HashAlgorithm_getBlockSize(algo_id); if (blockSize == 0) { KSI_pushError(ctx, res = KSI_UNKNOWN_ERROR, "Unknown buffer length for hash algorithm."); goto cleanup; } if (KSI_getHashLength(algo_id) > MAX_BUF_LEN || blockSize > MAX_BUF_LEN) { KSI_pushError(ctx, res = KSI_BUFFER_OVERFLOW, "Internal buffer too short to calculate HMAC."); goto cleanup; } tmp_hasher = KSI_new(KSI_HmacHasher); if (tmp_hasher == NULL) { KSI_pushError(ctx, res = KSI_OUT_OF_MEMORY, NULL); goto cleanup; } /* Open the data hasher. */ res = KSI_DataHasher_open(ctx, algo_id, &tmp_hasher->dataHasher); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } tmp_hasher->ctx = ctx; tmp_hasher->blockSize = blockSize; /* Prepare the key for hashing. */ /* If the key is longer than 64, hash it. If the key or its hash is shorter than 64 bit, append zeros. */ if (key_len > blockSize) { res = KSI_DataHasher_add(tmp_hasher->dataHasher, key, key_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_DataHasher_close(tmp_hasher->dataHasher, &hashedKey); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } res = KSI_DataHash_extract(hashedKey, NULL, &digest, &digest_len); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } if (digest == NULL || digest_len > blockSize) { KSI_pushError(ctx, res = KSI_INVALID_ARGUMENT, "The hash of the key is invalid"); goto cleanup; } bufKey = digest; buf_len = digest_len; } else { bufKey = (const unsigned char *) key; buf_len = key_len; } for (i = 0; i < buf_len; i++) { tmp_hasher->ipadXORkey[i] = 0x36 ^ bufKey[i]; tmp_hasher->opadXORkey[i] = 0x5c ^ bufKey[i]; } for (; i < blockSize; i++) { tmp_hasher->ipadXORkey[i] = 0x36; tmp_hasher->opadXORkey[i] = 0x5c; } res = KSI_HmacHasher_reset(tmp_hasher); if (res != KSI_OK) { KSI_pushError(ctx, res, NULL); goto cleanup; } *hasher = tmp_hasher; tmp_hasher = NULL; res = KSI_OK; cleanup: KSI_DataHash_free(hashedKey); KSI_HmacHasher_free(tmp_hasher); return res; }
int KSI_HmacHasher_close(KSI_HmacHasher *hasher, KSI_DataHash **hmac) { int res = KSI_UNKNOWN_ERROR; KSI_DataHash *innerHash = NULL; KSI_DataHash *outerHash = NULL; const unsigned char *digest = NULL; size_t digest_len = 0; if (hasher == NULL || hmac == NULL) { res = KSI_INVALID_ARGUMENT; goto cleanup; } KSI_ERR_clearErrors(hasher->ctx); KSI_LOG_debug(hasher->ctx, "Closing inner hasher"); res = KSI_DataHasher_close(hasher->dataHasher, &innerHash); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } /* Hash outer data. */ res = KSI_DataHasher_reset(hasher->dataHasher); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } KSI_LOG_logBlob(hasher->ctx, KSI_LOG_DEBUG, "Adding opad", hasher->opadXORkey, hasher->blockSize); res = KSI_DataHasher_add(hasher->dataHasher, hasher->opadXORkey, hasher->blockSize); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } res = KSI_DataHash_extract(innerHash, NULL, &digest, &digest_len); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } KSI_LOG_logBlob(hasher->ctx, KSI_LOG_DEBUG, "Adding inner hash", digest, digest_len); res = KSI_DataHasher_add(hasher->dataHasher, digest, digest_len); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } KSI_LOG_debug(hasher->ctx, "Closing outer hasher"); res = KSI_DataHasher_close(hasher->dataHasher, &outerHash); if (res != KSI_OK) { KSI_pushError(hasher->ctx, res, NULL); goto cleanup; } *hmac = KSI_DataHash_ref(outerHash); res = KSI_OK; cleanup: KSI_DataHash_free(innerHash); KSI_DataHash_free(outerHash); return res; }