/*ARGSUSED*/ static int skein_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) { int error = CRYPTO_SUCCESS; ASSERT(SKEIN_CTX(ctx) != NULL); switch (data->cd_format) { case CRYPTO_DATA_RAW: SKEIN_OP(SKEIN_CTX(ctx), Update, (uint8_t *)data->cd_raw.iov_base + data->cd_offset, data->cd_length); break; case CRYPTO_DATA_UIO: error = skein_digest_update_uio(SKEIN_CTX(ctx), data); break; case CRYPTO_DATA_MBLK: error = skein_digest_update_mblk(SKEIN_CTX(ctx), data); break; default: error = CRYPTO_ARGUMENTS_BAD; } return (error); }
/* * Initializes a skein digest context to the configuration in `mechanism'. * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param * field may contain a skein_param_t structure indicating the length of the * digest the algorithm should produce. Otherwise the default output lengths * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes * for Skein-1024). */ static int skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, crypto_req_handle_t req) { int error = CRYPTO_SUCCESS; if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) return (CRYPTO_MECHANISM_INVALID); SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), crypto_kmflag(req)); if (SKEIN_CTX(ctx) == NULL) return (CRYPTO_HOST_MEMORY); SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type; error = skein_get_digest_bitlen(mechanism, &SKEIN_CTX(ctx)->sc_digest_bitlen); if (error != CRYPTO_SUCCESS) goto errout; SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen); return (CRYPTO_SUCCESS); errout: bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); SKEIN_CTX_LVALUE(ctx) = NULL; return (error); }
/* * Initializes a skein MAC context. You may pass a ctx_template, in which * case the template will be reused to make initialization more efficient. * Otherwise a new context will be constructed. The mechanism cm_type must * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you * may pass a skein_param_t in cm_param to configure the length of the * digest. The key must be in raw format. */ static int skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) { int error; SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), crypto_kmflag(req)); if (SKEIN_CTX(ctx) == NULL) return (CRYPTO_HOST_MEMORY); if (ctx_template != NULL) { bcopy(ctx_template, SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); } else { error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key); if (error != CRYPTO_SUCCESS) goto errout; } return (CRYPTO_SUCCESS); errout: bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); return (error); }
/* * Frees a skein context in a parent crypto context. */ static int skein_free_context(crypto_ctx_t *ctx) { if (SKEIN_CTX(ctx) != NULL) { bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); SKEIN_CTX_LVALUE(ctx) = NULL; } return (CRYPTO_SUCCESS); }
/* * Executes a skein_update and skein_digest on a pre-initialized crypto * context in a single step. See the documentation to these functions to * see what to pass here. */ static int skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, crypto_req_handle_t req) { int error = CRYPTO_SUCCESS; ASSERT(SKEIN_CTX(ctx) != NULL); if (digest->cd_length < CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { digest->cd_length = CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); return (CRYPTO_BUFFER_TOO_SMALL); } error = skein_update(ctx, data, req); if (error != CRYPTO_SUCCESS) { bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); SKEIN_CTX_LVALUE(ctx) = NULL; digest->cd_length = 0; return (error); } error = skein_final(ctx, digest, req); return (error); }
/*ARGSUSED*/ static int skein_final(crypto_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req) { int error = CRYPTO_SUCCESS; ASSERT(SKEIN_CTX(ctx) != NULL); if (digest->cd_length < CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { digest->cd_length = CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); return (CRYPTO_BUFFER_TOO_SMALL); } switch (digest->cd_format) { case CRYPTO_DATA_RAW: SKEIN_OP(SKEIN_CTX(ctx), Final, (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset); break; case CRYPTO_DATA_UIO: error = skein_digest_final_uio(SKEIN_CTX(ctx), digest, req); break; default: error = CRYPTO_ARGUMENTS_BAD; } if (error == CRYPTO_SUCCESS) digest->cd_length = CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); else digest->cd_length = 0; bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx)))); SKEIN_CTX_LVALUE(ctx) = NULL; return (error); }