Changeset View
Changeset View
Standalone View
Standalone View
sys/contrib/openzfs/module/icp/io/sha2_mod.c
Show First 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | |||||
sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data) | sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data) | ||||
{ | { | ||||
off_t offset = data->cd_offset; | off_t offset = data->cd_offset; | ||||
size_t length = data->cd_length; | size_t length = data->cd_length; | ||||
uint_t vec_idx = 0; | uint_t vec_idx = 0; | ||||
size_t cur_len; | size_t cur_len; | ||||
/* we support only kernel buffer */ | /* we support only kernel buffer */ | ||||
if (uio_segflg(data->cd_uio) != UIO_SYSSPACE) | if (zfs_uio_segflg(data->cd_uio) != UIO_SYSSPACE) | ||||
return (CRYPTO_ARGUMENTS_BAD); | return (CRYPTO_ARGUMENTS_BAD); | ||||
/* | /* | ||||
* Jump to the first iovec containing data to be | * Jump to the first iovec containing data to be | ||||
* digested. | * digested. | ||||
*/ | */ | ||||
offset = uio_index_at_offset(data->cd_uio, offset, &vec_idx); | offset = zfs_uio_index_at_offset(data->cd_uio, offset, &vec_idx); | ||||
if (vec_idx == uio_iovcnt(data->cd_uio)) { | if (vec_idx == zfs_uio_iovcnt(data->cd_uio)) { | ||||
/* | /* | ||||
* The caller specified an offset that is larger than the | * The caller specified an offset that is larger than the | ||||
* total size of the buffers it provided. | * total size of the buffers it provided. | ||||
*/ | */ | ||||
return (CRYPTO_DATA_LEN_RANGE); | return (CRYPTO_DATA_LEN_RANGE); | ||||
} | } | ||||
/* | /* | ||||
* Now do the digesting on the iovecs. | * Now do the digesting on the iovecs. | ||||
*/ | */ | ||||
while (vec_idx < uio_iovcnt(data->cd_uio) && length > 0) { | while (vec_idx < zfs_uio_iovcnt(data->cd_uio) && length > 0) { | ||||
cur_len = MIN(uio_iovlen(data->cd_uio, vec_idx) - | cur_len = MIN(zfs_uio_iovlen(data->cd_uio, vec_idx) - | ||||
offset, length); | offset, length); | ||||
SHA2Update(sha2_ctx, (uint8_t *)uio_iovbase(data->cd_uio, | SHA2Update(sha2_ctx, (uint8_t *)zfs_uio_iovbase(data->cd_uio, | ||||
vec_idx) + offset, cur_len); | vec_idx) + offset, cur_len); | ||||
length -= cur_len; | length -= cur_len; | ||||
vec_idx++; | vec_idx++; | ||||
offset = 0; | offset = 0; | ||||
} | } | ||||
if (vec_idx == uio_iovcnt(data->cd_uio) && length > 0) { | if (vec_idx == zfs_uio_iovcnt(data->cd_uio) && length > 0) { | ||||
/* | /* | ||||
* The end of the specified iovec's was reached but | * The end of the specified iovec's was reached but | ||||
* the length requested could not be processed, i.e. | * the length requested could not be processed, i.e. | ||||
* The caller requested to digest more data than it provided. | * The caller requested to digest more data than it provided. | ||||
*/ | */ | ||||
return (CRYPTO_DATA_LEN_RANGE); | return (CRYPTO_DATA_LEN_RANGE); | ||||
} | } | ||||
Show All 10 Lines | |||||
static int | static int | ||||
sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest, | sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest, | ||||
ulong_t digest_len, uchar_t *digest_scratch) | ulong_t digest_len, uchar_t *digest_scratch) | ||||
{ | { | ||||
off_t offset = digest->cd_offset; | off_t offset = digest->cd_offset; | ||||
uint_t vec_idx = 0; | uint_t vec_idx = 0; | ||||
/* we support only kernel buffer */ | /* we support only kernel buffer */ | ||||
if (uio_segflg(digest->cd_uio) != UIO_SYSSPACE) | if (zfs_uio_segflg(digest->cd_uio) != UIO_SYSSPACE) | ||||
return (CRYPTO_ARGUMENTS_BAD); | return (CRYPTO_ARGUMENTS_BAD); | ||||
/* | /* | ||||
* Jump to the first iovec containing ptr to the digest to | * Jump to the first iovec containing ptr to the digest to | ||||
* be returned. | * be returned. | ||||
*/ | */ | ||||
offset = uio_index_at_offset(digest->cd_uio, offset, &vec_idx); | offset = zfs_uio_index_at_offset(digest->cd_uio, offset, &vec_idx); | ||||
if (vec_idx == uio_iovcnt(digest->cd_uio)) { | if (vec_idx == zfs_uio_iovcnt(digest->cd_uio)) { | ||||
/* | /* | ||||
* The caller specified an offset that is | * The caller specified an offset that is | ||||
* larger than the total size of the buffers | * larger than the total size of the buffers | ||||
* it provided. | * it provided. | ||||
*/ | */ | ||||
return (CRYPTO_DATA_LEN_RANGE); | return (CRYPTO_DATA_LEN_RANGE); | ||||
} | } | ||||
if (offset + digest_len <= | if (offset + digest_len <= | ||||
uio_iovlen(digest->cd_uio, vec_idx)) { | zfs_uio_iovlen(digest->cd_uio, vec_idx)) { | ||||
/* | /* | ||||
* The computed SHA2 digest will fit in the current | * The computed SHA2 digest will fit in the current | ||||
* iovec. | * iovec. | ||||
*/ | */ | ||||
if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && | if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) && | ||||
(digest_len != SHA256_DIGEST_LENGTH)) || | (digest_len != SHA256_DIGEST_LENGTH)) || | ||||
((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && | ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) && | ||||
(digest_len != SHA512_DIGEST_LENGTH))) { | (digest_len != SHA512_DIGEST_LENGTH))) { | ||||
/* | /* | ||||
* The caller requested a short digest. Digest | * The caller requested a short digest. Digest | ||||
* into a scratch buffer and return to | * into a scratch buffer and return to | ||||
* the user only what was requested. | * the user only what was requested. | ||||
*/ | */ | ||||
SHA2Final(digest_scratch, sha2_ctx); | SHA2Final(digest_scratch, sha2_ctx); | ||||
bcopy(digest_scratch, (uchar_t *)uio_iovbase(digest-> | bcopy(digest_scratch, (uchar_t *) | ||||
cd_uio, vec_idx) + offset, | zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, | ||||
digest_len); | digest_len); | ||||
} else { | } else { | ||||
SHA2Final((uchar_t *)uio_iovbase(digest-> | SHA2Final((uchar_t *)zfs_uio_iovbase(digest-> | ||||
cd_uio, vec_idx) + offset, | cd_uio, vec_idx) + offset, | ||||
sha2_ctx); | sha2_ctx); | ||||
} | } | ||||
} else { | } else { | ||||
/* | /* | ||||
* The computed digest will be crossing one or more iovec's. | * The computed digest will be crossing one or more iovec's. | ||||
* This is bad performance-wise but we need to support it. | * This is bad performance-wise but we need to support it. | ||||
* Allocate a small scratch buffer on the stack and | * Allocate a small scratch buffer on the stack and | ||||
* copy it piece meal to the specified digest iovec's. | * copy it piece meal to the specified digest iovec's. | ||||
*/ | */ | ||||
uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; | uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; | ||||
off_t scratch_offset = 0; | off_t scratch_offset = 0; | ||||
size_t length = digest_len; | size_t length = digest_len; | ||||
size_t cur_len; | size_t cur_len; | ||||
SHA2Final(digest_tmp, sha2_ctx); | SHA2Final(digest_tmp, sha2_ctx); | ||||
while (vec_idx < uio_iovcnt(digest->cd_uio) && length > 0) { | while (vec_idx < zfs_uio_iovcnt(digest->cd_uio) && length > 0) { | ||||
cur_len = | cur_len = | ||||
MIN(uio_iovlen(digest->cd_uio, vec_idx) - | MIN(zfs_uio_iovlen(digest->cd_uio, vec_idx) - | ||||
offset, length); | offset, length); | ||||
bcopy(digest_tmp + scratch_offset, | bcopy(digest_tmp + scratch_offset, | ||||
uio_iovbase(digest->cd_uio, vec_idx) + offset, | zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, | ||||
cur_len); | cur_len); | ||||
length -= cur_len; | length -= cur_len; | ||||
vec_idx++; | vec_idx++; | ||||
scratch_offset += cur_len; | scratch_offset += cur_len; | ||||
offset = 0; | offset = 0; | ||||
} | } | ||||
if (vec_idx == uio_iovcnt(digest->cd_uio) && length > 0) { | if (vec_idx == zfs_uio_iovcnt(digest->cd_uio) && length > 0) { | ||||
/* | /* | ||||
* The end of the specified iovec's was reached but | * The end of the specified iovec's was reached but | ||||
* the length requested could not be processed, i.e. | * the length requested could not be processed, i.e. | ||||
* The caller requested to digest more data than it | * The caller requested to digest more data than it | ||||
* provided. | * provided. | ||||
*/ | */ | ||||
return (CRYPTO_DATA_LEN_RANGE); | return (CRYPTO_DATA_LEN_RANGE); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 810 Lines • ▼ Show 20 Lines | sha2_mac_verify_atomic(crypto_provider_handle_t provider, | ||||
case CRYPTO_DATA_UIO: { | case CRYPTO_DATA_UIO: { | ||||
off_t offset = mac->cd_offset; | off_t offset = mac->cd_offset; | ||||
uint_t vec_idx = 0; | uint_t vec_idx = 0; | ||||
off_t scratch_offset = 0; | off_t scratch_offset = 0; | ||||
size_t length = digest_len; | size_t length = digest_len; | ||||
size_t cur_len; | size_t cur_len; | ||||
/* we support only kernel buffer */ | /* we support only kernel buffer */ | ||||
if (uio_segflg(mac->cd_uio) != UIO_SYSSPACE) | if (zfs_uio_segflg(mac->cd_uio) != UIO_SYSSPACE) | ||||
return (CRYPTO_ARGUMENTS_BAD); | return (CRYPTO_ARGUMENTS_BAD); | ||||
/* jump to the first iovec containing the expected digest */ | /* jump to the first iovec containing the expected digest */ | ||||
offset = uio_index_at_offset(mac->cd_uio, offset, &vec_idx); | offset = zfs_uio_index_at_offset(mac->cd_uio, offset, &vec_idx); | ||||
if (vec_idx == uio_iovcnt(mac->cd_uio)) { | if (vec_idx == zfs_uio_iovcnt(mac->cd_uio)) { | ||||
/* | /* | ||||
* The caller specified an offset that is | * The caller specified an offset that is | ||||
* larger than the total size of the buffers | * larger than the total size of the buffers | ||||
* it provided. | * it provided. | ||||
*/ | */ | ||||
ret = CRYPTO_DATA_LEN_RANGE; | ret = CRYPTO_DATA_LEN_RANGE; | ||||
break; | break; | ||||
} | } | ||||
/* do the comparison of computed digest vs specified one */ | /* do the comparison of computed digest vs specified one */ | ||||
while (vec_idx < uio_iovcnt(mac->cd_uio) && length > 0) { | while (vec_idx < zfs_uio_iovcnt(mac->cd_uio) && length > 0) { | ||||
cur_len = MIN(uio_iovlen(mac->cd_uio, vec_idx) - | cur_len = MIN(zfs_uio_iovlen(mac->cd_uio, vec_idx) - | ||||
offset, length); | offset, length); | ||||
if (bcmp(digest + scratch_offset, | if (bcmp(digest + scratch_offset, | ||||
uio_iovbase(mac->cd_uio, vec_idx) + offset, | zfs_uio_iovbase(mac->cd_uio, vec_idx) + offset, | ||||
cur_len) != 0) { | cur_len) != 0) { | ||||
ret = CRYPTO_INVALID_MAC; | ret = CRYPTO_INVALID_MAC; | ||||
break; | break; | ||||
} | } | ||||
length -= cur_len; | length -= cur_len; | ||||
vec_idx++; | vec_idx++; | ||||
scratch_offset += cur_len; | scratch_offset += cur_len; | ||||
▲ Show 20 Lines • Show All 116 Lines • Show Last 20 Lines |