/*
* 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 2012 Milan Jurik. All rights reserved.
*/
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <lber.h>
#include <security/cryptoki.h>
#include "softDSA.h"
#include "softDH.h"
#include "softRSA.h"
#include "softObject.h"
#include "softASN1.h"
/* DH key agreement OID: 1 . 2 . 840 . 113549 . 1 . 3 . 1 */
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x03, 0x01
};
/* DH X9.42 OID: 1 . 2 . 840 . 10046 . 1 */
0x2A, 0x86, 0x48, 0xCE, 0x3E, 0x01
};
/* DSA algorithm OID: 1 . 2 . 840 . 10040 . 4 . 1 */
0x2A, 0x86, 0x48, 0xCE, 0x38, 0x04, 0x01
};
/* RSA algorithm OID: 1 . 2 . 840 . 113549 . 1 . 1 . 1 */
0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x01, 0x01, 0x01
};
/*
* If the first bit of big integer is non-zero (i.e, first byte is
* 0x80 or greater), it may be interpreted as an ASN.1 negative number.
* Add one leading byte of zero-padding only in these cases to ensure
* it is treated as an unsigned integer.
*/
static CK_RV
{
int padding;
/* Src and dst must already by previously allocated. */
return (CKR_HOST_MEMORY);
if (src->big_value_len == 0) {
dst->big_value_len = 0;
return (CKR_OK);
}
/*
* Realloc() may free() or shrink previous memory location, so
* clear out potentially sensitive data before that happens.
*/
return (CKR_HOST_MEMORY);
/* Set zero-pad at first byte, then append actual big_value. */
src->big_value_len);
return (CKR_OK);
}
/*
* Sometimes there is one bytes of zero-padding, if a big integer may
* be interpreted as an ASN.1 negative number (i.e, the first bit is
* non-zero, the first byte is 0x80 or greater). Remove first byte
* of zero-padding in those cases from the decoded octet strings.
*/
static CK_RV
{
int offset;
return (CKR_HOST_MEMORY);
if (src.big_value_len == 0) {
dst->big_value_len = 0;
return (CKR_OK);
}
/*
* Must allocate memory here because subsequent calls to
* copy_bigint_attr() just redirect pointer; it doesn't
* really copy the bigint like the function name implies.
*/
return (CKR_HOST_MEMORY);
dst->big_value_len);
return (CKR_OK);
}
/* Encode RSA private key in ASN.1 BER syntax. */
static CK_RV
{
/*
* The ASN.1 syntax for an RSA private key is:
*
* PKCS#8 \* PrivateKeyInfo *\
* ---------------------------------
* Sequence {
* version INTEGER;
* Sequence { \* PrivateKeyAlgorithm *\
* OID 0x06, \* RSA algorithm OID *\
* param(NULL)
* }
* RSAPrivateKey OCTETSTRING =
* PKCS#1 \* RSAPrivateKey *\
* ---------------------------
* Sequence {
* version INTEGER,
* modulus INTEGER,
* publicExponent INTEGER,
* privateExponent INTEGER,
* prime1 INTEGER,
* prime2 INTEGER,
* exponent1 INTEGER,
* exponent2 INTEGER,
* coefficient INTEGER
* }
* }
*
* The code below starts building the innermost octets
* RSAPrivateKey, and then builds the PrivateKeyInfo
* sequence around that octet string. The BER syntax
* used in this function is (others may be possible):
* { i { to n } { i to to to to to to to to } }
* where "i" is for integers with fixed size
* where "to" is for integers that vary in size (length + value)
* where "n" is for nulls
* where "{}" delimit sequences
*/
/* RSAPrivateKey ... */
return (CKR_HOST_MEMORY);
/* ... begin-sequence { version, */
goto cleanup_rsapri2asn;
}
/* ... modulus, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... public exponent, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... private exponent, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... prime 1, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... prime 2, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... exponent 1, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... exponent 2, */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* ... coefficient } end-sequence */
goto cleanup_rsapri2asn;
goto cleanup_rsapri2asn;
}
/* Convert key ASN.1 to octet string. */
goto cleanup_rsapri2asn;
}
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_rsapri2asn;
}
/*
* Embed key octet string into PKCS#8 object ASN.1:
* begin-sequence {
* version
* begin-sequence {
* OID,
* NULL
* } end-sequence
* RSAPrivateKey
* } end-sequence
*/
goto cleanup_rsapri2asn;
}
/* Convert PKCS#8 object ASN.1 to octet string. */
goto cleanup_rsapri2asn;
}
/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
/*
* If the user passes in a null buf, then buf_len is set.
* If the user passes in a value with buf_len, then it can
* be checked to see if the accompanying buf is big enough.
* If it is, the octet string is copied into a pre-malloc'd
* buf; otherwise the user must resize buf and call again.
* In either case, buf_len is reset to the corrected size.
* See PKCS#11 section 11.2.
*/
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
goto cleanup_rsapri2asn;
}
}
if (p8obj_octs != NULL)
return (rv);
}
/* Encode DSA private key in ASN.1 BER syntax. */
static CK_RV
{
/*
* The ASN.1 syntax for a DSA private key is:
*
* PKCS#8 \* PrivateKeyInfo *\
* ---------------------------------
* Sequence {
* version INTEGER;
* Sequence { \* PrivateKeyAlgorithm *\
* OID 0x06, \* DSA algorithm OID *\
* param(DSS-params) OCTETSTRING =
* PKCS#? \* DSSParameter *\
* ----------------------------------
* Sequence {
* prime INTEGER,
* subprime INTEGER,
* base INTEGER,
* }
* }
* DSAPrivateKey OCTETSTRING =
* PKCS#1 \* DSAPrivateKey *\
* ---------------------------
* value INTEGER
* }
*
* The code below starts building the innermost octets
* DSAPrivateKey, and then builds the PrivateKeyInfo
* sequence around that octet string. The BER syntax
* used in this function is (others may be possible):
* { i { to { to to to } } to }
* where "i" is for integers with fixed size
* where "to" is for integers that vary in size (length + value)
* where "{}" delimit sequences
*/
/* DSAPrivateKey ... */
return (CKR_HOST_MEMORY);
/* ... value */
goto cleanup_dsapri2asn;
goto cleanup_dsapri2asn;
}
/* Convert key ASN.1 to octet string. */
goto cleanup_dsapri2asn;
}
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_dsapri2asn;
}
/*
* Start off the PKCS#8 object ASN.1:
* begin-sequence {
* version
* begin-sequence {
* OID,
* ...
*/
goto cleanup_dsapri2asn;
}
/*
* Add DSS parameters:
* ...
* begin-sequence {
* prime,
* ...
*/
goto cleanup_dsapri2asn;
goto cleanup_dsapri2asn;
}
/*
* ...
* subprime,
* ...
*/
goto cleanup_dsapri2asn;
goto cleanup_dsapri2asn;
}
/*
* ...
* base
* } end-sequence
*/
goto cleanup_dsapri2asn;
goto cleanup_dsapri2asn;
}
/*
* Add the key octet string:
* } end-sequence
* DSAPrivateKey
* } end-sequence
*/
goto cleanup_dsapri2asn;
}
/* Convert PKCS#8 object ASN.1 to octet string. */
goto cleanup_dsapri2asn;
}
/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
/*
* If the user passes in a null buf, then buf_len is set.
* If the user passes in a value with buf_len, then it can
* be checked to see if the accompanying buf is big enough.
* If it is, the octet string is copied into a pre-malloc'd
* buf; otherwise the user must resize buf and call again.
* In either case, buf_len is reset to the corrected size.
* See PKCS#11 section 11.2.
*/
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
goto cleanup_dsapri2asn;
}
}
if (p8obj_octs != NULL)
return (rv);
}
/* Encode DH private key in ASN.1 BER syntax. */
static CK_RV
{
/*
* The ASN.1 syntax for a DH private key is:
*
* PKCS#8 \* PrivateKeyInfo *\
* ---------------------------------
* Sequence {
* version INTEGER;
* Sequence { \* PrivateKeyAlgorithm *\
* OID 0x06, \* DH algorithm OID *\
* param(DH-params) OCTETSTRING =
* PKCS#3 \* DHParameter *\
* -------------------------
* Sequence {
* prime INTEGER,
* base INTEGER
* }
* }
* DHPrivateKey OCTETSTRING =
* PKCS#1 \* DHPrivateKey *\
* --------------------------
* value INTEGER
* }
*
* The code below starts building the innermost octets
* DHPrivateKey, and then builds the PrivateKeyInfo
* sequence around that octet string. The BER syntax
* used in this function is (others may be possible):
* { i { to { to to } } to }
* where "i" is for integers with fixed size
* where "to" is for integers that vary in size (length + value)
* where "{}" delimit sequences
*/
/* DHPrivateKey ... */
return (CKR_HOST_MEMORY);
/* ... value */
goto cleanup_dhpri2asn;
goto cleanup_dhpri2asn;
}
/* Convert key ASN.1 to octet string. */
goto cleanup_dhpri2asn;
}
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_dhpri2asn;
}
/*
* Start off the PKCS#8 object ASN.1:
* begin-sequence {
* version
* begin-sequence {
* OID,
* ...
*/
goto cleanup_dhpri2asn;
}
/*
* Add DH parameters:
* ...
* begin-sequence {
* prime,
* ...
*/
goto cleanup_dhpri2asn;
goto cleanup_dhpri2asn;
}
/*
* ...
* base
* } end-sequence
*/
goto cleanup_dhpri2asn;
goto cleanup_dhpri2asn;
}
/*
* Add the key octet string:
* } end-sequence
* DSAPrivateKey
* } end-sequence
*/
goto cleanup_dhpri2asn;
}
/* Convert PKCS#8 object ASN.1 to octet string. */
goto cleanup_dhpri2asn;
}
/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
/*
* If the user passes in a null buf, then buf_len is set.
* If the user passes in a value with buf_len, then it can
* be checked to see if the accompanying buf is big enough.
* If it is, the octet string is copied into a pre-malloc'd
* buf; otherwise the user must resize buf and call again.
* In either case, buf_len is reset to the corrected size.
* See PKCS#11 section 11.2.
*/
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
goto cleanup_dhpri2asn;
}
}
if (p8obj_octs != NULL)
return (rv);
}
/* Encode DH X9.42 private key in ASN.1 BER syntax. */
static CK_RV
{
/*
* The ASN.1 syntax for a X9.42 DH private key is:
*
* PKCS#8 \* PrivateKeyInfo *\
* ---------------------------------
* Sequence {
* version INTEGER;
* Sequence { \* PrivateKeyAlgorithm *\
* OID 0x06, \* DH X9.42 algorithm OID *\
* param(DH-params) OCTETSTRING =
* PKCS#3 \* DHParameter *\
* -------------------------
* Sequence {
* prime INTEGER,
* base INTEGER,
* subprime INTEGER \* for X9.42 *\
* }
* }
* DHPrivateKey OCTETSTRING =
* PKCS#1 \* DHPrivateKey *\
* --------------------------
* value INTEGER
* }
*
* The code below starts building the innermost octets
* DHPrivateKey, and then builds the PrivateKeyInfo
* sequence around that octet string. The BER syntax
* used in this function is (others may be possible):
* { i { to { to to } } to }
* where "i" is for integers with fixed size
* where "to" is for integers that vary in size (length + value)
* where "{}" delimit sequences
*/
/* DHPrivateKey ... */
return (CKR_HOST_MEMORY);
/* ... value */
goto cleanup_x942dhpri2asn;
goto cleanup_x942dhpri2asn;
}
/* Convert key ASN.1 to octet string. */
goto cleanup_x942dhpri2asn;
}
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_x942dhpri2asn;
}
/*
* Start off the PKCS#8 object ASN.1:
* begin-sequence {
* version
* begin-sequence {
* OID,
* ...
*/
goto cleanup_x942dhpri2asn;
}
/*
* Add DH parameters:
* ...
* begin-sequence {
* prime,
* ...
*/
goto cleanup_x942dhpri2asn;
goto cleanup_x942dhpri2asn;
}
/*
* ...
* base,
* ...
*/
goto cleanup_x942dhpri2asn;
goto cleanup_x942dhpri2asn;
}
/*
* ...
* subprime
* } end-sequence
*/
goto cleanup_x942dhpri2asn;
goto cleanup_x942dhpri2asn;
}
/*
* Add the key octet string:
* } end-sequence
* DHPrivateKey
* } end-sequence
*/
goto cleanup_x942dhpri2asn;
}
/* Convert PKCS#8 object ASN.1 to octet string. */
goto cleanup_x942dhpri2asn;
}
/* Ship out the PKCS#8 object ASN.1 octet string, if possible. */
/*
* If the user passes in a null buf, then buf_len is set.
* If the user passes in a value with buf_len, then it can
* be checked to see if the accompanying buf is big enough.
* If it is, the octet string is copied into a pre-malloc'd
* buf; otherwise the user must resize buf and call again.
* In either case, buf_len is reset to the corrected size.
* See PKCS#11 section 11.2.
*/
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
goto cleanup_x942dhpri2asn;
}
}
if (p8obj_octs != NULL)
return (rv);
}
/*
* Encode the object key from the soft_object_t into ASN.1 format.
*/
{
switch (class) {
case CKO_PRIVATE_KEY:
switch (keytype) {
case CKK_RSA:
case CKK_DSA:
case CKK_DH:
case CKK_X9_42_DH:
default:
return (CKR_FUNCTION_NOT_SUPPORTED);
} /* keytype */
default:
return (CKR_FUNCTION_NOT_SUPPORTED);
} /* class */
}
/* Decode ASN.1 BER syntax into RSA private key. */
static CK_RV
{
char *cookie;
int version;
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
/* Decode PKCS#8 object ASN.1, verifying it is RSA private key. */
return (CKR_GENERAL_ERROR);
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_asn2rsapri;
}
/* ... begin-sequence { version, */
goto cleanup_asn2rsapri;
}
/* ... begin-sequence { */
goto cleanup_asn2rsapri;
}
/* ... OID, \* RSA algorithm OID *\ */
goto cleanup_asn2rsapri;
}
goto cleanup_asn2rsapri;
}
goto cleanup_asn2rsapri;
}
/* ... param(NULL) } end-sequence */
goto cleanup_asn2rsapri;
}
/* ... RSAPrivateKey } end-sequence */
goto cleanup_asn2rsapri;
}
/* Decode key octet string into softtoken key object. */
goto cleanup_asn2rsapri;
}
/* ... begin-sequence { version, */
goto cleanup_asn2rsapri;
}
/* ... modulus, */
goto cleanup_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto cleanup_asn2rsapri;
}
goto cleanup_asn2rsapri;
}
goto cleanup_asn2rsapri;
}
/* ... public exponent, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... private exponent, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... prime 1, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... prime 2, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... exponent 1, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... exponent 2, */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
/* ... coefficient } end-sequence */
goto error_asn2rsapri;
}
if (size > MAX_RSA_KEY) {
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto error_asn2rsapri;
}
goto cleanup_asn2rsapri;
}
return (rv);
}
/* Decode ASN.1 BER syntax into DSA private key. */
static CK_RV
{
char *cookie;
int version;
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
/* Decode PKCS#8 object ASN.1, verifying it is DSA private key. */
return (CKR_GENERAL_ERROR);
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_asn2dsapri;
}
/* ... begin-sequence { version, */
goto cleanup_asn2dsapri;
}
/* ... begin-sequence { */
goto cleanup_asn2dsapri;
}
/* ... OID, \* DSA algorithm OID *\ */
goto cleanup_asn2dsapri;
}
goto cleanup_asn2dsapri;
}
goto cleanup_asn2dsapri;
}
/* ... begin-sequence { */
goto cleanup_asn2dsapri;
}
/* ... prime, */
if (size > MAX_DSA_KEY) {
goto cleanup_asn2dsapri;
}
goto cleanup_asn2dsapri;
}
goto cleanup_asn2dsapri;
}
goto error_asn2dsapri;
}
/* ... subprime, */
if (size > MAX_DSA_KEY) {
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
/* ... base } end-sequence } end-sequence */
if (size > MAX_DSA_KEY) {
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
/* ... DSAPrivateKey } end-sequence */
goto error_asn2dsapri;
}
/* Decode key octet string into softtoken key object. */
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
/* ... value } end-sequence */
if (size > MAX_DSA_KEY) {
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto error_asn2dsapri;
}
goto cleanup_asn2dsapri;
}
return (rv);
}
/* Decode ASN.1 BER syntax into DH private key. */
static CK_RV
{
char *cookie;
int version;
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
/* Decode PKCS#8 object ASN.1, verifying it is DH private key. */
return (CKR_GENERAL_ERROR);
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_asn2dhpri;
}
/* ... begin-sequence { version, */
goto cleanup_asn2dhpri;
}
/* ... begin-sequence { */
goto cleanup_asn2dhpri;
}
/* ... OID, \* DH algorithm OID *\ */
goto cleanup_asn2dhpri;
}
goto cleanup_asn2dhpri;
}
goto cleanup_asn2dhpri;
}
/* ... begin-sequence { */
goto cleanup_asn2dhpri;
}
/* ... prime, */
if (size > MAX_DH_KEY) {
goto cleanup_asn2dhpri;
}
goto cleanup_asn2dhpri;
}
goto cleanup_asn2dhpri;
}
goto error_asn2dhpri;
}
/* ... base } end-sequence } end-sequence */
if (size > MAX_DH_KEY) {
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
/* ... DHPrivateKey } end-sequence */
goto error_asn2dhpri;
}
/* Decode key octet string into softtoken key object. */
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
/* ... value } end-sequence */
if (size > MAX_DH_KEY) {
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
goto error_asn2dhpri;
}
goto cleanup_asn2dhpri;
}
return (rv);
}
/* Decode ASN.1 BER syntax into DH X9.42 private key. */
static CK_RV
{
char *cookie;
int version;
#ifdef _LP64
/* LINTED E_CAST_INT_TO_SMALL_INT */
#else
#endif
/* Decode PKCS#8 object ASN.1, verifying it is DH X9.42 private key. */
return (CKR_GENERAL_ERROR);
/* PKCS#8 PrivateKeyInfo ... */
goto cleanup_asn2x942dhpri;
}
/* ... begin-sequence { version, */
goto cleanup_asn2x942dhpri;
}
/* ... begin-sequence { */
goto cleanup_asn2x942dhpri;
}
/* ... OID, \* DH X9.42 algorithm OID *\ */
goto cleanup_asn2x942dhpri;
}
goto cleanup_asn2x942dhpri;
}
goto cleanup_asn2x942dhpri;
}
/* ... begin-sequence { */
goto cleanup_asn2x942dhpri;
}
/* ... prime, */
if (size > MAX_DH942_KEY) {
goto cleanup_asn2x942dhpri;
}
goto cleanup_asn2x942dhpri;
}
goto cleanup_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
/* ... base, */
if (size > MAX_DH942_KEY) {
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
/* ... subprime } end-sequence } end-sequence */
if (size > MAX_DH942_KEY) {
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
/* ... DHPrivateKey } end-sequence */
goto error_asn2x942dhpri;
}
/* Decode key octet string into softtoken key object. */
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
/* ... value } end-sequence */
if (size > MAX_DH942_KEY) {
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto error_asn2x942dhpri;
}
goto cleanup_asn2x942dhpri;
}
return (rv);
}
/*
* Decode the object key from ASN.1 format into soft_object_t.
*/
{
switch (class) {
case CKO_PRIVATE_KEY:
/* Allocate storage for Private Key Object. */
return (rv);
}
switch (keytype) {
case CKK_RSA:
break;
case CKK_DSA:
break;
case CKK_DH:
break;
case CKK_X9_42_DH:
break;
default:
break;
} /* keytype */
else
break;
default:
break;
} /* class */
return (rv);
}