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/*
f317a3a3712d9b82387b437ac621db3733d8c804krishna * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Use is subject to license terms.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#pragma ident "%Z%%M% %I% %E% SMI"
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/crypto/spi.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm#include <sys/crypto/dca.h>
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * DSA implementation.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void dca_dsa_sign_done(dca_request_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void dca_dsa_verify_done(dca_request_t *, int);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_dsa_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *sig,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t req);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_dsa_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *sig,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t req);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint dca_dsainit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, int kmflag, int mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsa_sign(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *sig,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t req)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv = CRYPTO_QUEUED;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t kaddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm size_t buflen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm buflen = dca_length(data);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (buflen != SHA1LEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_dsa_sign: data length != %d", SHA1LEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Return length needed to store the output. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_length(sig) < DSASIGLEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_sign: output buffer too short (%d < %d)",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_length(sig), DSASIGLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm sig->cd_length = DSASIGLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_BUFFER_TOO_SMALL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Don't change the data values of the data crypto_data_t structure
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * yet. Only reset the sig cd_length to zero before writing to it.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_DSASIGN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_byte_stat = -1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in = data;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out = sig;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_callback = dca_dsa_sign_done;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_kcf_req = req;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* dca_gather() increments cd_offset & dec. cd_length by SHA1LEN. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm err = dca_gather(data, reqp->dr_ibuf_kaddr, SHA1LEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (err != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_dsa_sign: dca_gather() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* sync the input buffer */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, SHA1LEN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm 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 rv = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_paddr = reqp->dr_ibuf_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_next = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_len = SHA1LEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length = buflen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * The output requires *two* buffers, r followed by s.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + reqp->dr_offset;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* r */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_paddr = reqp->dr_obuf_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_len = DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_next = reqp->dr_ctx_paddr + reqp->dr_offset;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* s */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_BUFADDR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_obuf_paddr + DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_NEXT, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_RSVD, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_LENGTH, DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_start(dca, reqp, MCR2, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsa_sign_done(dca_request_t *reqp, int errno)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, DSASIGLEN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_DMA_SYNC_FORKERNEL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Set the sig cd_length to zero so it's ready to take the
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * signature. Have already confirmed its size is adequate.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out->cd_length = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_scatter(reqp->dr_obuf_kaddr,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out, DSAPARTLEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_sign_done: dca_scatter() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = dca_scatter(reqp->dr_obuf_kaddr+DSAPARTLEN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out, DSAPARTLEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_sign_done: dca_scatter() failed");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(reqp->dr_kcf_req != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_op_notification(reqp->dr_kcf_req, errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_sign_done: rtn 0x%x to kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_dsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsa_verify(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *sig,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_req_handle_t req)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv = CRYPTO_QUEUED;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t kaddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Impossible for verify to be an in-place operation. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (sig == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_length(data) != SHA1LEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_dsa_verify: input length != %d", SHA1LEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_DATA_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_length(sig) != DSASIGLEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN, "dca_dsa_verify: signature length != %d",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DSASIGLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_SIGNATURE_LEN_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Don't change the data & sig values for verify. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_job_stat = DS_DSAVERIFY;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_byte_stat = -1;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Grab h, r and s.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm err = dca_gather(data, reqp->dr_ibuf_kaddr, SHA1LEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (err != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_vrfy: dca_gather() failed for h");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm err = dca_gather(sig, reqp->dr_ibuf_kaddr+SHA1LEN, DSAPARTLEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (err != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_vrfy: dca_gather() failed for r");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm err = dca_gather(sig, reqp->dr_ibuf_kaddr+SHA1LEN+DSAPARTLEN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DSAPARTLEN, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (err != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(dca, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_vrfy: dca_gather() failed for s");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = err;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * As dca_gather() increments the cd_offset and decrements
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * the cd_length as it copies the data rewind the values ready for
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * the final compare.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm sig->cd_offset -= (DSAPARTLEN * 2);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm sig->cd_length += (DSAPARTLEN * 2);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* sync the input buffer */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_ibuf_dmah, 0, SHA1LEN + DSAPARTLEN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_DMA_SYNC_FORDEV);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(dca, reqp->dr_ibuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in = data;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out = sig;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_kcf_req = req;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_flags |= DR_SCATTER | DR_GATHER;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_callback = dca_dsa_verify_done;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Input requires three buffers. m, followed by r, followed by s.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * In order to deal with things cleanly, we reverse the signature
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * into the buffer and then fix up the pointers.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_pkt_length = SHA1LEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_paddr = reqp->dr_ibuf_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_len = SHA1LEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_in_next = reqp->dr_ctx_paddr + reqp->dr_offset;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_paddr = reqp->dr_obuf_paddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_len = DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_out_next = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* setup 1st chain for r */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + reqp->dr_offset;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_BUFADDR, reqp->dr_ibuf_paddr + SHA1LEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_NEXT,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx_paddr + reqp->dr_offset + DESC_SIZE);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_RSVD, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_LENGTH, DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* and 2nd chain for s */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + reqp->dr_offset + DESC_SIZE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_BUFADDR, reqp->dr_ibuf_paddr +
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm SHA1LEN + DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC32(reqp, kaddr, DESC_NEXT, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_RSVD, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTDESC16(reqp, kaddr, DESC_LENGTH, DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* schedule the work by doing a submit */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_start(dca, reqp, MCR2, 1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_QUEUED && rv != CRYPTO_BUFFER_TOO_SMALL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) dca_free_context(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmstatic void
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsa_verify_done(dca_request_t *reqp, int errno)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (errno == CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int count = DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_data_t *sig = reqp->dr_out;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t daddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void) ddi_dma_sync(reqp->dr_obuf_dmah, 0, count,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DDI_DMA_SYNC_FORKERNEL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_check_dma_handle(reqp->dr_dca, reqp->dr_obuf_dmah,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->destroy = TRUE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_DEVICE_ERROR;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Can only handle a contiguous data buffer currently. */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_sgcheck(reqp->dr_dca, sig, DCA_SG_CONTIG)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_SIGNATURE_INVALID;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((daddr = dca_bufdaddr(sig)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_bcmp_reverse(daddr, reqp->dr_obuf_kaddr,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DSAPARTLEN) != 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* VERIFY FAILED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno = CRYPTO_SIGNATURE_INVALID;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(reqp->dr_kcf_req != NULL);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* notify framework that request is completed */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_op_notification(reqp->dr_kcf_req, errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(reqp->dr_dca, DINTR,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsa_verify_done: rtn 0x%x to kef via crypto_op_notification",
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm errno);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * For non-atomic operations, reqp will be freed in the kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * callback function since it may be needed again if
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * CRYPTO_BUFFER_TOO_SMALL is returned to kCF
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->dr_ctx.atomic) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t ctx;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx.cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_dsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm/* ARGSUSED */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsainit(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, int kmflag, int mode)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_object_attribute_t *attr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned plen = 0, qlen = 0, glen = 0, xlen = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uchar_t *p, *q, *g, *x;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_t *dca = (dca_t *)ctx->cc_provider;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm int rv = CRYPTO_SUCCESS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm unsigned pbits, padjlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm uint16_t ctxlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm caddr_t kaddr;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((reqp = dca_getreq(dca, MCR2, 1)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_error(dca,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsainit: unable to allocate request for DSA");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_HOST_MEMORY;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = reqp;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type = mechanism->cm_type;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if ((attr = dca_get_key_attr(key)) == NULL) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: key attributes missing");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_TYPE_INCONSISTENT;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Prime */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_PRIME,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void *) &p, &plen)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: prime key value not present");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Subprime */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_SUBPRIME,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void *) &q, &qlen)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: subprime key value not present");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Base */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_BASE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void *) &g, &glen)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: base key value not present");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* Value */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (dca_attr_lookup_uint8_array(attr, key->ck_count, CKA_VALUE,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm (void *) &x, &xlen)) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: value key not present");
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (plen == 0 || qlen == 0 || glen == 0 || xlen == 0) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_ARGUMENTS_BAD;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (plen > DSA_MAX_KEY_LEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* maximum 1Kbit key */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: maximum 1Kbit key (%d)", plen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_SIZE_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (qlen > DSAPARTLEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsainit: q is too long (%d)", qlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_SIZE_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_DSA_SIGN && xlen > DSAPARTLEN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm "dca_dsainit: private key is too long (%d)", xlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = CRYPTO_KEY_SIZE_RANGE;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm goto errout;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /*
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm * Setup the key partion of the request.
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm pbits = dca_bitlen(p, plen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm padjlen = dca_padfull(pbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* accounts for leading context words */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_DSA_SIGN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctxlen = CTX_DSABIGNUMS + DSAPARTLEN + (padjlen * 2) +
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_CMD, CMD_DSASIGN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctxlen = CTX_DSABIGNUMS + DSAPARTLEN + (padjlen * 3);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_CMD, CMD_DSAVERIFY);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_LENGTH, ctxlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_DSAMSGTYPE, CTX_DSAMSGTYPE_SHA1);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_DSARSVD, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_DSA_SIGN)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_DSARNG, CTX_DSARNG_GEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_DSARNG, 0);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm PUTCTX16(reqp, CTX_DSAPLEN, pbits);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr = reqp->dr_ctx_kaddr + CTX_DSABIGNUMS;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm /* store the bignums */
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(q, kaddr, qlen, DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(p, kaddr, plen, padjlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += padjlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(g, kaddr, glen, padjlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += padjlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_DSA_SIGN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(x, kaddr, xlen, DSAPARTLEN);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += DSAPARTLEN;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_reverse(x, kaddr, xlen, padjlen);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm kaddr += padjlen;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm }
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (CRYPTO_SUCCESS);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmerrout:
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_dsactxfree(ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmvoid
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsactxfree(void *arg)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm{
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_ctx_t *ctx = (crypto_ctx_t *)arg;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_request_t *reqp = ctx->cc_provider_private;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp == NULL)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.ctx_cm_type = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm reqp->dr_ctx.atomic = 0;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (reqp->destroy)
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_destroyreq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm else
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm dca_freereq(reqp);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ctx->cc_provider_private = NULL;
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmint
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gmdca_dsaatomic(crypto_provider_handle_t provider,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm crypto_key_t *key, crypto_data_t *data, crypto_data_t *sig,
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 rv = dca_dsainit(&ctx, mechanism, key, kmflag, mode);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (rv != CRYPTO_SUCCESS) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm DBG(NULL, DWARN, "dca_dsaatomic: dca_dsainit() 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
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm if (mode == DCA_DSA_SIGN) {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_dsa_sign(&ctx, data, sig, req);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm } else {
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm ASSERT(mode == DCA_DSA_VRFY);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm rv = dca_dsa_verify(&ctx, data, sig, req);
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_dsactxfree(&ctx);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm return (rv);
88f8b78a88cbdc6d8c1af5c3e54bc49d25095c98gm}