88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER START
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The contents of this file are subject to the terms of the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Common Development and Distribution License (the "License").
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You may not use this file except in compliance with the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * See the License for the specific language governing permissions
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and limitations under the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * When distributing Covered Code, include this CDDL HEADER in each
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If applicable, add the following below this CDDL HEADER, with the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * fields enclosed by brackets "[]" replaced with your own identifying
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * information: Portions Copyright [yyyy] [name of copyright owner]
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER END
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use is subject to license terms.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Deimos - cryptographic acceleration based upon Broadcom 582x.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 3DES implementation.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_3desstart(dca_t *, uint32_t, dca_request_t *);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "input not an integral number of DES blocks");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cd_miscdata non-null then this contains the IV.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "inadequate output space (need %d, got %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Do not free the context since the app will call again */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* special handling for null-sized input buffers */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Make a local copy of the input crypto_data_t structure. This
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * allows it to be manipulated locally and for dealing with in-place
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * data (ie in == out). Note that "nin" has been pre-allocated,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and only fields are copied, not actual data.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Set output to zero ready to take the processed data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Context will be freed in the kCF callback function otherwise */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Return it to the pool */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cd_miscdata non-null then this contains the IV.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[0] = p[0]<<24 | p[1]<<16 | p[2]<<8 | p[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[1] = p[4]<<24 | p[5]<<16 | p[6]<<8 | p[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "not enough output space (need %d, got %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Do not free the context since the app will call again */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * From here on out, we are committed.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * No blocks being encrypted, so we just accumulate the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * input for the next pass and return.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desupdate: dca_getbufbytes() failed for residual only pass");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Do not free the context here since it will be done
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * in the final function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set up rbuf for previous residual data.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm bcopy(des_ctx->dr_ctx.resid, des_ctx->dr_ctx.activeresid,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.activeresidlen = des_ctx->dr_ctx.residlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Locate and save residual data for next encrypt_update.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_getbufbytes(in, len - des_ctx->dr_ctx.residlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rawlen % DESBLOCK, des_ctx->dr_ctx.resid)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_3desupdate: dca_getbufbytes() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Calculate new residual length. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Make a local copy of the input crypto_data_t structure. This
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * allows it to be manipulated locally and for dealing with in-place
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * data (ie in == out).
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Set output to zero ready to take the processed data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * As this is multi-part the context is cleared on success
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * (CRYPTO_QUEUED) in dca_3desfinal().
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desfinal(crypto_ctx_t *ctx, crypto_data_t *out, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * There must be no unprocessed ciphertext/plaintext.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * This happens if the length of the last data is
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * not a multiple of the DES block length.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_3desfinal: invalid nonzero residual");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, crypto_data_t *input, crypto_data_t *output,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Input must be a multiple of the block size. This test only
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * works for non-padded mechanisms when the blocksize is 2^N.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_3desatomic: input not multiple of BS");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_3desctxinit(&ctx, mechanism, key, kmflag, mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_3desatomic: dca_3desctxinit() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set the atomic flag so that the hardware callback function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * will free the context.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
d8dd99136aadc95161b4031565b92214f8bbc8c8gm /* check for inplace ops */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The features of dca_3desfinal() are implemented within
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * dca_3desdone() due to the asynchronous nature of dca_3des().
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The context will be freed in the hardware callback function if it
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * is queued
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desstart(dca_t *dca, uint32_t flags, dca_request_t *reqp)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Preconditions:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 1) in and out point to the "right" buffers.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 2) in->b_bcount - in->b_resid == initial offset
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 3) likewise for out
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 4) there is enough space in the output
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 5) we perform a block for block encrypt
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* collect IVs for this pass */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * And also, for decrypt, collect the IV for the next pass. For
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * decrypt, the IV must be collected BEFORE decryption, or else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * we will lose it. (For encrypt, we grab the IV AFTER encryption,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * in dca_3desdone.
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* get last 8 bytes of ciphertext for IV of next op */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If we're processing only a DESBLOCKS worth of data
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and there is active residual present then it will be
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * needed for the IV also.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Bring the active residual into play */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_getbufbytes() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store as a pair of native 32-bit values */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* For now we force a pullup. Add direct DMA later. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((len < dca_mindma) || (ctx->dr_ctx.activeresidlen > 0) ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Try to do direct DMA. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_bindchains() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* gather the data into the device */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_resid_gather(in, (char *)ctx->dr_ctx.activeresid,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_resid_gather() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup for scattering the result back out
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The output buffer is a multi-entry chain for x86 and
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * a single entry chain for Sparc.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use the actual length if the first entry is sufficient.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup for scattering the result back out
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The output buffer is a multi-entry chain for x86 and
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * a single entry chain for Sparc.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use the actual length if the first entry is sufficient.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Save the offset: this has to be done *before* dca_scatter
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * modifies the buffer. We take the initial offset into the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * first buf, and add that to the total packet size to find
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * the end of the packet.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: dca_scatter() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* we've processed some more data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For encryption only, we have to grab the IV for the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * next pass AFTER encryption.
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* get last 8 bytes for IV of next op */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: dca_getbufbytes() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store as a pair of native 32-bit values */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If there is more to do, then reschedule another
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If this is an atomic operation perform the final function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * tasks (equivalent to to dca_3desfinal()).
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((errno == CRYPTO_SUCCESS) && (ctx->dr_ctx.residlen != 0)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: invalid nonzero residual");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: returning %d to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* This has to be done after notifing the framework */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* ARGSUSED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desctxinit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desctxinit: parameter(IV) length not %d (%d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Identify and store the IV as a pair of native 32-bit words.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cm_param == NULL then the IV comes from the cd_miscdata field
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * in the crypto_data structure.
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desctxinit: only raw crypto key type support with DES/3DES");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* 3DES */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm switch (len) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = 0; i < 6; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (j = 0; j < 4; j++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = 0; i < 4; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (j = 0; j < 4; j++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* single DES */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* for single des just repeat des key */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup the context here so that we do not need to setup it up
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * for every update
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm flags & DR_ENCRYPT ? CTX_3DES_ENCRYPT : CTX_3DES_DECRYPT);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY1HI, des_ctx->dr_ctx.key[0]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY1LO, des_ctx->dr_ctx.key[1]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY2HI, des_ctx->dr_ctx.key[2]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY2LO, des_ctx->dr_ctx.key[3]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY3HI, des_ctx->dr_ctx.key[4]);