/** * Calculate hash digest for the passed buffer. * * This should be used when computing the hash on a single contiguous buffer. * It combines the hash initialization, computation, and cleanup. * * \param[in] hash_alg id of hash algorithm (CFS_HASH_ALG_*) * \param[in] buf data buffer on which to compute hash * \param[in] buf_len length of \a buf in bytes * \param[in] key initial value/state for algorithm, if \a key = NULL * use default initial value * \param[in] key_len length of \a key in bytes * \param[out] hash pointer to computed hash value, if \a hash = NULL then * \a hash_len is to digest size in bytes, retval -ENOSPC * \param[in,out] hash_len size of \a hash buffer * * \retval -EINVAL \a buf, \a buf_len, \a hash_len, \a hash_alg invalid * \retval -ENOENT \a hash_alg is unsupported * \retval -ENOSPC \a hash is NULL, or \a hash_len less than digest size * \retval 0 for success * \retval negative errno for other errors from lower layers. */ int cfs_crypto_hash_digest(enum cfs_crypto_hash_alg hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len) { struct scatterlist sl; struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; if (!buf || buf_len == 0 || !hash_len) return -EINVAL; err = cfs_crypto_hash_alloc(hash_alg, &type, &req, key, key_len); if (err != 0) return err; if (!hash || *hash_len < type->cht_size) { *hash_len = type->cht_size; crypto_free_ahash(crypto_ahash_reqtfm(req)); ahash_request_free(req); return -ENOSPC; } sg_init_one(&sl, (void *)buf, buf_len); ahash_request_set_crypt(req, &sl, hash, sl.length); err = crypto_ahash_digest(req); crypto_free_ahash(crypto_ahash_reqtfm(req)); ahash_request_free(req); return err; }
/** * Calculate hash digest for the passed buffer. * * This should be used when computing the hash on a single contiguous buffer. * It combines the hash initialization, computation, and cleanup. * * \param[in] hash_alg id of hash algorithm (CFS_HASH_ALG_*) * \param[in] buf data buffer on which to compute hash * \param[in] buf_len length of \a buf in bytes * \param[in] key initial value/state for algorithm, if \a key = NULL * use default initial value * \param[in] key_len length of \a key in bytes * \param[out] hash pointer to computed hash value, if \a hash = NULL then * \a hash_len is to digest size in bytes, retval -ENOSPC * \param[in,out] hash_len size of \a hash buffer * * \retval -EINVAL \a buf, \a buf_len, \a hash_len, \a alg_id invalid * \retval -ENOENT \a hash_alg is unsupported * \retval -ENOSPC \a hash is NULL, or \a hash_len less than digest size * \retval 0 for success * \retval negative errno for other errors from lower layers. */ int cfs_crypto_hash_digest(enum cfs_crypto_hash_alg hash_alg, const void *buf, unsigned int buf_len, unsigned char *key, unsigned int key_len, unsigned char *hash, unsigned int *hash_len) { struct scatterlist sl; struct hash_desc hdesc; int err; const struct cfs_crypto_hash_type *type; if (buf == NULL || buf_len == 0 || hash_len == NULL) return -EINVAL; err = cfs_crypto_hash_alloc(hash_alg, &type, &hdesc, key, key_len); if (err != 0) return err; if (hash == NULL || *hash_len < type->cht_size) { *hash_len = type->cht_size; crypto_free_hash(hdesc.tfm); return -ENOSPC; } sg_init_one(&sl, (void *)buf, buf_len); hdesc.flags = 0; err = crypto_hash_digest(&hdesc, &sl, sl.length, hash); crypto_free_hash(hdesc.tfm); return err; }
/** * Allocate and initialize desriptor for hash algorithm. * * This should be used to initialize a hash descriptor for multiple calls * to a single hash function when computing the hash across multiple * separate buffers or pages using cfs_crypto_hash_update{,_page}(). * * The hash descriptor should be freed with cfs_crypto_hash_final(). * * \param[in] hash_alg algorithm id (CFS_HASH_ALG_*) * \param[in] key initial value/state for algorithm, if \a key = NULL * use default initial value * \param[in] key_len length of \a key in bytes * * \retval pointer to ahash request * \retval ERR_PTR(errno) in case of error */ struct ahash_request * cfs_crypto_hash_init(enum cfs_crypto_hash_alg hash_alg, unsigned char *key, unsigned int key_len) { struct ahash_request *req; int err; const struct cfs_crypto_hash_type *type; err = cfs_crypto_hash_alloc(hash_alg, &type, &req, key, key_len); if (err) return ERR_PTR(err); return req; }
/** * Allocate and initialize desriptor for hash algorithm. * * This should be used to initialize a hash descriptor for multiple calls * to a single hash function when computing the hash across multiple * separate buffers or pages using cfs_crypto_hash_update{,_page}(). * * The hash descriptor should be freed with cfs_crypto_hash_final(). * * \param[in] hash_alg algorithm id (CFS_HASH_ALG_*) * \param[in] key initial value/state for algorithm, if \a key = NULL * use default initial value * \param[in] key_len length of \a key in bytes * * \retval pointer to descriptor of hash instance * \retval ERR_PTR(errno) in case of error */ struct cfs_crypto_hash_desc * cfs_crypto_hash_init(enum cfs_crypto_hash_alg hash_alg, unsigned char *key, unsigned int key_len) { struct hash_desc *hdesc; int err; const struct cfs_crypto_hash_type *type; hdesc = kmalloc(sizeof(*hdesc), 0); if (hdesc == NULL) return ERR_PTR(-ENOMEM); err = cfs_crypto_hash_alloc(hash_alg, &type, hdesc, key, key_len); if (err) { kfree(hdesc); hdesc = ERR_PTR(err); } return (struct cfs_crypto_hash_desc *)hdesc; }