/*
* 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
*/
/*
*/
/*
* This file contains DSA helper routines common to
* the PKCS11 soft token code and the kernel DSA code.
*/
#include <bignum.h>
#ifdef _KERNEL
#else
#include <strings.h>
#include <cryptoutil.h>
#endif
#include "dsa_impl.h"
static CK_RV
{
switch (err) {
case BIG_OK:
return (CKR_OK);
case BIG_NO_MEM:
return (CKR_HOST_MEMORY);
case BIG_NO_RANDOM:
return (CKR_DEVICE_ERROR);
case BIG_INVALID_ARGS:
return (CKR_ARGUMENTS_BAD);
case BIG_DIV_BY_0:
default:
return (CKR_GENERAL_ERROR);
}
}
/* size is in bits */
static BIG_ERR_CODE
{
return (err);
goto ret1;
goto ret2;
goto ret3;
goto ret4;
goto ret5;
goto ret6;
goto ret7;
goto ret8;
return (BIG_OK);
ret8:
big_finish(&(key->s));
ret7:
big_finish(&(key->r));
ret6:
big_finish(&(key->k));
ret5:
big_finish(&(key->y));
ret4:
big_finish(&(key->x));
ret3:
big_finish(&(key->g));
ret2:
big_finish(&(key->p));
ret1:
big_finish(&(key->q));
return (err);
}
static void
{
big_finish(&(key->v));
big_finish(&(key->s));
big_finish(&(key->r));
big_finish(&(key->k));
big_finish(&(key->y));
big_finish(&(key->x));
big_finish(&(key->g));
big_finish(&(key->p));
big_finish(&(key->q));
}
/*
* Generate DSA private x and public y from prime p, subprime q, and base g.
*/
static CK_RV
{
#ifdef _KERNEL
#else
#endif
}
do {
BIG_OK) {
return (convert_rv(err));
}
return (convert_rv(err));
return (CKR_OK);
}
{
if ((prime_bytes < MIN_DSA_KEY_LEN) ||
(prime_bytes > MAX_DSA_KEY_LEN)) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
/*
* There is no check here that prime_bits must be a multiple of 64,
* and thus that prime_bytes must be a multiple of 8.
*/
if (subprime_bytes != DSA_SUBPRIME_BYTES) {
return (CKR_ATTRIBUTE_VALUE_INVALID);
}
return (CKR_ARGUMENTS_BAD);
}
/*
* Initialize the DSA key.
* Note: big_extend takes length in words.
*/
goto cleanexit;
}
/* Convert prime p to bignum. */
goto cleanexit;
}
/* Convert prime q to bignum. */
goto cleanexit;
}
/* Convert base g to bignum. */
goto cleanexit;
}
/*
* Generate DSA key pair.
* Note: bignum.len is length of value in words.
*/
CKR_OK) {
goto cleanexit;
}
return (rv);
}
/*
* DSA sign operation
*/
{
if (DSA_SUBPRIME_BYTES != subprime_bytes) {
return (CKR_KEY_SIZE_RANGE);
}
if (DSA_SUBPRIME_BYTES < value_bytes) {
return (CKR_KEY_SIZE_RANGE);
}
/*
* Initialize the DH key.
* Note: big_extend takes length in words.
*/
return (CKR_HOST_MEMORY);
}
goto clean1;
}
goto clean1;
}
goto clean1;
}
goto clean1;
}
goto clean1;
}
/*
* Compute signature.
*/
goto clean2;
}
goto clean3;
}
#ifdef _KERNEL
#else
#endif
}
goto clean4;
}
goto clean4;
}
goto clean4;
}
BIG_OK) {
goto clean4;
}
goto clean4;
}
goto clean4; /* tmp <- k^-1 */
}
goto clean4;
}
goto clean4;
}
goto clean4;
}
BIG_OK) {
goto clean4;
}
/*
* Signature is in DSA key r and s values, copy to out
*/
big_finish(&tmp1);
big_finish(&tmp);
big_finish(&msg);
return (rv);
}
/*
* DSA verify operation
*/
{
if (DSA_SUBPRIME_BYTES != subprime_bytes) {
return (CKR_KEY_SIZE_RANGE);
}
return (CKR_KEY_SIZE_RANGE);
}
if (prime_bytes < value_bytes) {
return (CKR_KEY_SIZE_RANGE);
}
/*
* Initialize the DSA key.
* Note: big_extend takes length in words.
*/
return (CKR_HOST_MEMORY);
}
goto clean1;
}
goto clean1;
}
goto clean1;
}
goto clean1;
}
/*
* Copy signature to DSA key r and s values
*/
goto clean1;
}
goto clean1;
}
goto clean1;
}
goto clean2;
}
goto clean3;
}
goto clean4;
}
/*
* Verify signature against msg.
*/
BIG_OK) {
goto clean5;
}
goto clean5; /* tmp2 <- w */
}
goto clean5;
}
goto clean5; /* tmp1 <- u_1 */
}
goto clean5;
}
goto clean5; /* tmp2 <- u_2 */
}
BIG_OK) {
goto clean5;
}
BIG_OK) {
goto clean5;
}
goto clean5;
}
goto clean5;
}
goto clean5;
}
else
big_finish(&tmp3);
big_finish(&tmp2);
big_finish(&tmp1);
big_finish(&msg);
return (rv);
}