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 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; }
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; }
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; }