88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER START
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
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 *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * or http://www.opensolaris.org/os/licensing.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * See the License for the specific language governing permissions
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * and limitations under the License.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
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 *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CDDL HEADER END
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use is subject to license terms.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Deimos - cryptographic acceleration based upon Broadcom 582x.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/types.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/ddi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/sunddi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/kmem.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/note.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/common.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/spi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/dca.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#if defined(__i386) || defined(__amd64)
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#include <sys/byteorder.h>
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#define UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * 3DES implementation.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic int dca_3desstart(dca_t *, uint32_t, dca_request_t *);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void dca_3desdone(dca_request_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3des(crypto_ctx_t *ctx, crypto_data_t *in,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *out, crypto_req_handle_t req, int flags)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *des_ctx = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *nin = &reqp->dr_ctx.in_dup;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = dca_length(in);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len % DESBLOCK) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "input not an integral number of DES blocks");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (flags & DR_DECRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cd_miscdata non-null then this contains the IV.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (in->cd_miscdata != NULL) {
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *p = (uint32_t *)in->cd_miscdata;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[0] = htonl(p[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[1] = htonl(p[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *p = (uchar_t *)in->cd_miscdata;
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 }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len > dca_length(out)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "inadequate output space (need %d, got %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len, dca_length(out));
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Do not free the context since the app will call again */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_BUFFER_TOO_SMALL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* special handling for null-sized input buffers */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Set output to zero ready to take the processed data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_kcf_req = req;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in = nin;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out = out;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_3DESJOBS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_byte_stat = DS_3DESBYTES;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_3desstart(dca, flags, reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Context will be freed in the kCF callback function otherwise */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desctxfree(void *arg)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t *ctx = (crypto_ctx_t *)arg;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *des_ctx = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (des_ctx == NULL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.atomic = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.ctx_cm_type = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (des_ctx->destroy)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_destroyreq(des_ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Return it to the pool */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_freereq(des_ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desupdate(crypto_ctx_t *ctx, crypto_data_t *in,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *out, crypto_req_handle_t req, int flags)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rawlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *des_ctx = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *nin = &reqp->dr_ctx.in_dup;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rawlen = dca_length(in) + des_ctx->dr_ctx.residlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = ROUNDDOWN(rawlen, DESBLOCK);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cd_miscdata non-null then this contains the IV.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (in->cd_miscdata != NULL) {
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *p = (uint32_t *)in->cd_miscdata;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[0] = htonl(p[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[1] = htonl(p[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *p = (uchar_t *)in->cd_miscdata;
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 }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len > dca_length(out)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "not enough output space (need %d, got %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len, dca_length(out));
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Do not free the context since the app will call again */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_BUFFER_TOO_SMALL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_verifyio(in, out)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_kcf_req = req;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * From here on out, we are committed.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * No blocks being encrypted, so we just accumulate the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * input for the next pass and return.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_getbufbytes(in, 0,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (rawlen % DESBLOCK) - des_ctx->dr_ctx.residlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.resid + des_ctx->dr_ctx.residlen)) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desupdate: dca_getbufbytes() failed for residual only pass");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_freereq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Do not free the context here since it will be done
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * in the final function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set up rbuf for previous residual data.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (des_ctx->dr_ctx.residlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm bcopy(des_ctx->dr_ctx.resid, des_ctx->dr_ctx.activeresid,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.residlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.activeresidlen = des_ctx->dr_ctx.residlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Locate and save residual data for next encrypt_update.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
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 (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Calculate new residual length. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.residlen = rawlen % DESBLOCK;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv = dca_dupcrypto(in, nin)) != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Set output to zero ready to take the processed data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in = nin;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out = out;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_3DESJOBS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_byte_stat = DS_3DESBYTES;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_3desstart(dca, flags, reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * As this is multi-part the context is cleared on success
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * (CRYPTO_QUEUED) in dca_3desfinal().
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desfinal(crypto_ctx_t *ctx, crypto_data_t *out, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *des_ctx = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv = CRYPTO_SUCCESS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(ctx->cc_provider_private != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (des_ctx->dr_ctx.residlen != 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_3desfinal: invalid nonzero residual");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode & DR_DECRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desatomic(crypto_provider_handle_t provider,
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 int kmflag, crypto_req_handle_t req, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx; /* on the stack */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider = provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_session = session_id;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((dca_length(input) & (DESBLOCK - 1)) != 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_3desatomic: input not multiple of BS");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode & DR_DECRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_DATA_LEN_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_3desctxinit(&ctx, mechanism, key, kmflag, mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_3desatomic: dca_3desctxinit() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set the atomic flag so that the hardware callback function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * will free the context.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ((dca_request_t *)ctx.cc_provider_private)->dr_ctx.atomic = 1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
d8dd99136aadc95161b4031565b92214f8bbc8c8gm /* check for inplace ops */
d8dd99136aadc95161b4031565b92214f8bbc8c8gm if (input == output) {
d8dd99136aadc95161b4031565b92214f8bbc8c8gm ((dca_request_t *)ctx.cc_provider_private)->dr_flags
d8dd99136aadc95161b4031565b92214f8bbc8c8gm |= DR_INPLACE;
d8dd99136aadc95161b4031565b92214f8bbc8c8gm }
d8dd99136aadc95161b4031565b92214f8bbc8c8gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_3des(&ctx, input, output, req, mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((rv != CRYPTO_QUEUED) && (rv != CRYPTO_SUCCESS)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_3desatomic: dca_3des() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm output->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The features of dca_3desfinal() are implemented within
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * dca_3desdone() due to the asynchronous nature of dca_3des().
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The context will be freed in the hardware callback function if it
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * is queued
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_3desctxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desstart(dca_t *dca, uint32_t flags, dca_request_t *reqp)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm size_t len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *in = reqp->dr_in;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *ctx = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uint32_t iv[2];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = ctx->dr_ctx.activeresidlen + dca_length(in);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = ROUNDDOWN(min(len, MAXPACKET), DESBLOCK);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length = (uint16_t)len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* collect IVs for this pass */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm iv[0] = ctx->dr_ctx.iv[0];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm iv[1] = ctx->dr_ctx.iv[1];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (flags & DR_DECRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t ivstore[DESBLOCK];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *ivp = (uint32_t *)ivstore;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *ivp = ivstore;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* get last 8 bytes of ciphertext for IV of next op */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((len == DESBLOCK) && ctx->dr_ctx.activeresidlen) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Bring the active residual into play */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm bcopy(ctx->dr_ctx.activeresid, ivstore,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->dr_ctx.activeresidlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_getbufbytes(in, 0,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DESBLOCK - ctx->dr_ctx.activeresidlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ivstore + ctx->dr_ctx.activeresidlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_getbufbytes(in,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len - DESBLOCK - ctx->dr_ctx.activeresidlen,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DESBLOCK, ivstore);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_getbufbytes() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store as a pair of native 32-bit values */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson ctx->dr_ctx.iv[0] = htonl(ivp[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson ctx->dr_ctx.iv[1] = htonl(ivp[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->dr_ctx.iv[0] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ivp[0]<<24 | ivp[1]<<16 | ivp[2]<<8 | ivp[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->dr_ctx.iv[1] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ivp[4]<<24 | ivp[5]<<16 | ivp[6]<<8 | ivp[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* For now we force a pullup. Add direct DMA later. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_flags &= ~(DR_SCATTER | DR_GATHER);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((len < dca_mindma) || (ctx->dr_ctx.activeresidlen > 0) ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_sgcheck(dca, reqp->dr_in, DCA_SG_CONTIG) ||
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_sgcheck(dca, reqp->dr_out, DCA_SG_WALIGN)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_flags |= DR_SCATTER | DR_GATHER;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Try to do direct DMA. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (!(reqp->dr_flags & (DR_SCATTER | DR_GATHER))) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_bindchains(reqp, len, len) == DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in->cd_offset += len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in->cd_length -= len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_bindchains() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_DEVICE_ERROR);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* gather the data into the device */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_flags & DR_GATHER) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_resid_gather(in, (char *)ctx->dr_ctx.activeresid,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm &ctx->dr_ctx.activeresidlen, reqp->dr_ibuf_kaddr, len);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desstart: dca_resid_gather() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, len,
d8dd99136aadc95161b4031565b92214f8bbc8c8gm DDI_DMA_SYNC_FORDEV);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(dca, reqp->dr_ibuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_DEVICE_ERROR);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_paddr = reqp->dr_ibuf_head.dc_buffer_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_next = reqp->dr_ibuf_head.dc_next_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len > reqp->dr_ibuf_head.dc_buffer_length)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_len = reqp->dr_ibuf_head.dc_buffer_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_len = len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_flags & DR_SCATTER) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_paddr = reqp->dr_obuf_head.dc_buffer_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_next = reqp->dr_obuf_head.dc_next_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len > reqp->dr_obuf_head.dc_buffer_length)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_len = reqp->dr_obuf_head.dc_buffer_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_len = len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_flags |= flags;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_callback = dca_3desdone;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* write out the context structure */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(reqp, CTX_3DESIVHI, iv[0]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(reqp, CTX_3DESIVLO, iv[1]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (dca_start(dca, reqp, MCR1, 1));
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desdone(dca_request_t *reqp, int errno)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *out = reqp->dr_out;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *ctx = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(ctx != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm size_t off;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
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 */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm off = dca_length(out) + reqp->dr_pkt_length - DESBLOCK;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_flags & DR_SCATTER) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0,
d8dd99136aadc95161b4031565b92214f8bbc8c8gm reqp->dr_out_len, DDI_DMA_SYNC_FORKERNEL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_dmah, DCA_FM_ECLASS_NONE) !=
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_scatter(reqp->dr_obuf_kaddr,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out, reqp->dr_out_len, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: dca_scatter() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* we've processed some more data */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm out->cd_length += reqp->dr_pkt_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For encryption only, we have to grab the IV for the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * next pass AFTER encryption.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_flags & DR_ENCRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t ivstore[DESBLOCK];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *iv = (uint32_t *)ivstore;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *iv = ivstore;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* get last 8 bytes for IV of next op */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson errno = dca_getbufbytes(out, off, DESBLOCK,
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson (uchar_t *)iv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: dca_getbufbytes() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store as a pair of native 32-bit values */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson ctx->dr_ctx.iv[0] = htonl(iv[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson ctx->dr_ctx.iv[1] = htonl(iv[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->dr_ctx.iv[0] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm iv[0]<<24 | iv[1]<<16 | iv[2]<<8 | iv[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->dr_ctx.iv[1] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm iv[4]<<24 | iv[5]<<16 | iv[6]<<8 | iv[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If there is more to do, then reschedule another
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * pass.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_length(reqp->dr_in) >= 8) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_3desstart(reqp->dr_dca, reqp->dr_flags,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_QUEUED) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If this is an atomic operation perform the final function
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * tasks (equivalent to to dca_3desfinal()).
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((errno == CRYPTO_SUCCESS) && (ctx->dr_ctx.residlen != 0)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: invalid nonzero residual");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_flags & DR_DECRYPT) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(reqp->dr_kcf_req != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_op_notification(reqp->dr_kcf_req, errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desdone: returning %d to the kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* This has to be done after notifing the framework */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_context = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.atomic = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->destroy)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_destroyreq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_freereq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* ARGSUSED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_3desctxinit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, int kmflag, int flags)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *des_ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *param;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson uint32_t *value32;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *param;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *value;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm size_t paramsz;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned len;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int i, j;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm paramsz = mechanism->cm_param_len;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson param = (uint32_t *)mechanism->cm_param;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm param = (uchar_t *)mechanism->cm_param;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((paramsz != 0) && (paramsz != DES_IV_LEN)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desctxinit: parameter(IV) length not %d (%d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DES_IV_LEN, paramsz);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_MECHANISM_PARAM_INVALID);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((des_ctx = dca_getreq(dca, MCR1, 1)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_error(dca, "unable to allocate request for 3DES");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_HOST_MEMORY);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Identify and store the IV as a pair of native 32-bit words.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm *
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * If cm_param == NULL then the IV comes from the cd_miscdata field
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * in the crypto_data structure.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (param != NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(paramsz == DES_IV_LEN);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[0] = htonl(param[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.iv[1] = htonl(param[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[0] = param[0]<<24 | param[1]<<16 |
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm param[2]<<8 | param[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.iv[1] = param[4]<<24 | param[5]<<16 |
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm param[6]<<8 | param[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.residlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.activeresidlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.ctx_cm_type = mechanism->cm_type;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = des_ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (key->ck_format != CRYPTO_KEY_RAW) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_3desctxinit: only raw crypto key type support with DES/3DES");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_3desctxfree(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_KEY_TYPE_INCONSISTENT);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm len = key->ck_length;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm value = (uchar_t *)key->ck_data;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (flags & DR_TRIPLE) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* 3DES */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm switch (len) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm case 192:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = 0; i < 6; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (j = 0; j < 4; j++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] <<= 8;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] |= *value;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm value++;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm break;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm case 128:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (i = 0; i < 4; i++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm for (j = 0; j < 4; j++) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] <<= 8;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[i] |= *value;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm value++;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[4] = des_ctx->dr_ctx.key[0];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[5] = des_ctx->dr_ctx.key[1];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm break;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm default:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "Incorrect 3DES keysize (%d)", len);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_3desctxfree(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_KEY_SIZE_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* single DES */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (len != 64) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "Incorrect DES keysize (%d)", len);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_3desctxfree(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_KEY_SIZE_RANGE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#ifdef UNALIGNED_POINTERS_PERMITTED
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson value32 = (uint32_t *)value;
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.key[0] = htonl(value32[0]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson des_ctx->dr_ctx.key[1] = htonl(value32[1]);
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[0] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm value[0]<<24 | value[1]<<16 | value[2]<<8 | value[3];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[1] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm value[4]<<24 | value[5]<<16 | value[6]<<8 | value[7];
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson#endif /* UNALIGNED_POINTERS_PERMITTED */
4b56a00321e0ce508e55cc5e43e3ad7b00005a39Daniel Anderson
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* for single des just repeat des key */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[4] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[2] = des_ctx->dr_ctx.key[0];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[5] =
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm des_ctx->dr_ctx.key[3] = des_ctx->dr_ctx.key[1];
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup the context here so that we do not need to setup it up
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * for every update
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(des_ctx, CTX_LENGTH, CTX_3DES_LENGTH);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(des_ctx, CTX_CMD, CMD_3DES);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESDIRECTION,
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]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX32(des_ctx, CTX_3DESKEY3LO, des_ctx->dr_ctx.key[5]);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}