/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Deimos - cryptographic acceleration based upon Broadcom 582x.
*/
/*
* DSA implementation.
*/
static void dca_dsa_sign_done(dca_request_t *, int);
static void dca_dsa_verify_done(dca_request_t *, int);
int
{
int err;
goto errout;
}
/* Return length needed to store the output. */
"dca_dsa_sign: output buffer too short (%d < %d)",
goto errout;
}
/*
* Don't change the data values of the data crypto_data_t structure
* yet. Only reset the sig cd_length to zero before writing to it.
*/
/* dca_gather() increments cd_offset & dec. cd_length by SHA1LEN. */
if (err != CRYPTO_SUCCESS) {
goto errout;
}
/* sync the input buffer */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto errout;
}
reqp->dr_in_next = 0;
/*
* The output requires *two* buffers, r followed by s.
*/
/* r */
/* s */
/* schedule the work by doing a submit */
(void) dca_free_context(ctx);
return (rv);
}
static void
{
if (errno == CRYPTO_SUCCESS) {
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto errout;
}
/*
* Set the sig cd_length to zero so it's ready to take the
* signature. Have already confirmed its size is adequate.
*/
if (errno != CRYPTO_SUCCESS) {
"dca_dsa_sign_done: dca_scatter() failed");
goto errout;
}
if (errno != CRYPTO_SUCCESS) {
"dca_dsa_sign_done: dca_scatter() failed");
}
}
/* notify framework that request is completed */
"dca_dsa_sign_done: rtn 0x%x to kef via crypto_op_notification",
errno);
/*
* For non-atomic operations, reqp will be freed in the kCF
* callback function since it may be needed again if
* CRYPTO_BUFFER_TOO_SMALL is returned to kCF
*/
}
}
int
{
int err;
/* Impossible for verify to be an in-place operation. */
goto errout;
}
goto errout;
}
goto errout;
}
/* Don't change the data & sig values for verify. */
/*
* Grab h, r and s.
*/
if (err != CRYPTO_SUCCESS) {
"dca_dsa_vrfy: dca_gather() failed for h");
goto errout;
}
if (err != CRYPTO_SUCCESS) {
"dca_dsa_vrfy: dca_gather() failed for r");
goto errout;
}
DSAPARTLEN, 1);
if (err != CRYPTO_SUCCESS) {
"dca_dsa_vrfy: dca_gather() failed for s");
goto errout;
}
/*
* As dca_gather() increments the cd_offset and decrements
* the cd_length as it copies the data rewind the values ready for
* the final compare.
*/
/* sync the input buffer */
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto errout;
}
/*
* Input requires three buffers. m, followed by r, followed by s.
* In order to deal with things cleanly, we reverse the signature
* into the buffer and then fix up the pointers.
*/
reqp->dr_out_next = 0;
/* setup 1st chain for r */
/* and 2nd chain for s */
SHA1LEN + DSAPARTLEN);
/* schedule the work by doing a submit */
(void) dca_free_context(ctx);
}
return (rv);
}
static void
{
if (errno == CRYPTO_SUCCESS) {
DCA_FM_ECLASS_NONE) != DDI_SUCCESS) {
goto errout;
}
/* Can only handle a contiguous data buffer currently. */
goto errout;
}
goto errout;
}
DSAPARTLEN) != 0) {
/* VERIFY FAILED */
}
}
/* notify framework that request is completed */
"dca_dsa_verify_done: rtn 0x%x to kef via crypto_op_notification",
errno);
/*
* For non-atomic operations, reqp will be freed in the kCF
* callback function since it may be needed again if
* CRYPTO_BUFFER_TOO_SMALL is returned to kCF
*/
}
}
/* ARGSUSED */
int
{
uchar_t *p, *q, *g, *x;
"dca_dsainit: unable to allocate request for DSA");
goto errout;
}
goto errout;
}
/* Prime */
(void *) &p, &plen)) {
goto errout;
}
/* Subprime */
(void *) &q, &qlen)) {
goto errout;
}
/* Base */
(void *) &g, &glen)) {
goto errout;
}
/* Value */
(void *) &x, &xlen)) {
goto errout;
}
goto errout;
}
if (plen > DSA_MAX_KEY_LEN) {
/* maximum 1Kbit key */
goto errout;
}
if (qlen > DSAPARTLEN) {
goto errout;
}
"dca_dsainit: private key is too long (%d)", xlen);
goto errout;
}
/*
* Setup the key partion of the request.
*/
/* accounts for leading context words */
if (mode == DCA_DSA_SIGN) {
} else {
}
if (mode == DCA_DSA_SIGN)
else
/* store the bignums */
kaddr += DSAPARTLEN;
if (mode == DCA_DSA_SIGN) {
kaddr += DSAPARTLEN;
} else {
}
return (CRYPTO_SUCCESS);
return (rv);
}
void
{
return;
else
}
int
{
int rv;
if (rv != CRYPTO_SUCCESS) {
return (rv);
}
/*
* Set the atomic flag so that the hardware callback function
* will free the context.
*/
if (mode == DCA_DSA_SIGN) {
} else {
}
/*
* The context will be freed in the hardware callback function if it
* is queued
*/
if (rv != CRYPTO_QUEUED)
return (rv);
}