/*
* 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 DH helper routines common to
* the PKCS11 soft token code and the kernel DH code.
*/
#include <sys/sysmacros.h>
#include <bignum.h>
#ifdef _KERNEL
#else
#include <strings.h>
#include <cryptoutil.h>
#endif
#include <des/des_impl.h>
#include "dh_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
{
int len;
return (err);
goto ret1;
goto ret2;
goto ret3;
return (BIG_OK);
ret3:
big_finish(&(key->x));
ret2:
big_finish(&(key->g));
ret1:
big_finish(&(key->p));
return (err);
}
static void
{
big_finish(&(key->y));
big_finish(&(key->x));
big_finish(&(key->g));
big_finish(&(key->p));
}
/*
* Generate DH key pair x and y, given prime p and base g.
* Can optionally provided bit length of x, not to exceed bit length of p.
*
* For those not familiar with DH keys, there are 4 components:
* p - a known prime
* g - the base 0 < g < p
* x - a random number 0 < x < p-1, or if a smaller value is desired,
* 2^(len-1) <= x < 2^(len)
* y = g^x mod p, this implies 0 < y < p. That is important!
*/
{
return (CKR_ARGUMENTS_BAD);
/* Must have prime and base set, value bits can be 0 or non-0 */
return (CKR_ARGUMENTS_BAD);
if ((prime_bytes < MIN_DH_KEYLENGTH_IN_BYTES) ||
return (CKR_KEY_SIZE_RANGE);
}
/*
* Initialize the DH key.
* Note: big_extend takes length in words.
*/
goto ret;
}
/* Convert prime p to bignum. */
BIG_OK) {
goto ret;
}
/* Convert base g to bignum. */
goto ret;
}
/* Base g cannot be greater than prime p. */
goto ret;
}
/*
* The intention of selecting a private-value length is to reduce
* the computation time for key agreement, while maintaining a
* given level of security.
*/
/* Maximum bit length for private-value x is bit length of prime p */
if (bkey->value_bits == 0)
goto ret;
}
/* Generate DH key pair private and public values. */
!= BIG_OK) {
goto ret;
}
!= BIG_OK) {
goto ret;
}
/*
* The big integer of the private value shall be generated privately
* and randomly.
*/
#ifdef _KERNEL
#else
#endif
}
goto ret;
}
/*
* The base g shall be raised to the private value x modulo p to
* give an integer y, the integer public value, i.e. y = (g^x) mod p.
*/
goto ret;
}
ret:
return (rv);
}
/*
* DH key derive operation, flag is ignored in userland
*/
int flag)
{
return (CKR_ARGUMENTS_BAD);
/* Must have prime, private value and public value */
return (CKR_ARGUMENTS_BAD);
return (CKR_ARGUMENTS_BAD);
}
/*
* Initialize the DH key.
* Note: big_extend takes length in words.
*/
goto ret;
}
/* Convert prime p to bignum. */
BIG_OK) {
goto ret;
}
/* Convert private-value x to bignum. */
BIG_OK) {
goto ret;
}
/* Convert public-value y to bignum. */
BIG_OK) {
goto ret;
}
/*
* Recycle base g as a temporary variable to compute the derived
* secret value which is "g" = (y^x) mod p. (Not recomputing g.)
*/
BIG_OK) {
goto ret;
}
goto ret;
}
#ifdef _KERNEL
goto ret;
}
#else
goto ret;
}
#endif
switch (key_type) {
case CKK_DES:
break;
case CKK_DES2:
break;
case CKK_DES3:
break;
case CKK_RC4:
case CKK_AES:
case CKK_GENERIC_SECRET:
/* use provided secret key length, if any */
break;
default:
/* invalid key type */
goto ret;
}
if (*secretkey_len == 0) {
*secretkey_len = s_bytes;
}
if (*secretkey_len > s_bytes) {
goto ret;
}
/*
* The truncation removes bytes from the leading end of the
* secret value.
*/
ret:
if (s != NULL)
#ifdef _KERNEL
#else
free(s);
#endif
return (rv);
}