Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
static int closeExisting(KSI_DataHasher *hasher, KSI_DataHash *data_hash) {
	int res = KSI_UNKNOWN_ERROR;
	DWORD digest_length = 0;
	DWORD digestLenSize = 0;	//The size of digest_length variable
	DWORD hash_length = 0;
	CRYPTO_HASH_CTX * pCryptoCTX = NULL;	//Crypto helper struct
	HCRYPTHASH pHash = 0;				//Hash object

	if (hasher == NULL || data_hash == NULL){
		res = KSI_INVALID_ARGUMENT;
		goto cleanup;
	}
	KSI_ERR_clearErrors(hasher->ctx);

	pCryptoCTX = (CRYPTO_HASH_CTX*)hasher->hashContext;
	pHash = pCryptoCTX->pt_hHash;

	hash_length = KSI_getHashLength(hasher->algorithm);
	if (hash_length == 0) {
		KSI_pushError(hasher->ctx, res = KSI_UNKNOWN_ERROR, "Error finding digest length.");
		goto cleanup;
	}

	digestLenSize = sizeof(digest_length);
	CryptGetHashParam(pHash, HP_HASHSIZE, (BYTE*)&digest_length, &digestLenSize,0);

	/* Make sure the hash length is the same. */
	if (hash_length != digest_length) {
		KSI_pushError(hasher->ctx, res = KSI_UNKNOWN_ERROR, "Internal hash lengths mismatch.");
		goto cleanup;
	}

	/*After final call pHash is can not be used further*/
	CryptGetHashParam(pHash, HP_HASHVAL, data_hash->imprint + 1, &digest_length, 0);

	if (hasher->algorithm > 0xff) {
		KSI_pushError(hasher->ctx, res = KSI_INVALID_FORMAT, "Hash algorithm ID is larger than one byte.");
		goto cleanup;
	}

	data_hash->imprint[0] = (unsigned char) hasher->algorithm;
	data_hash->imprint_length = digest_length + 1;

	res = KSI_OK;

cleanup:

	return res;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
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;
}