summaryrefslogtreecommitdiff
path: root/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c')
-rw-r--r--usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c358
1 files changed, 84 insertions, 274 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c
index 7991f7c267..06d9c22757 100644
--- a/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c
+++ b/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDH.c
@@ -18,59 +18,39 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include <sys/crypto/common.h>
-#include <bignum.h>
#include <des_impl.h>
+#include <cryptoutil.h>
#include "softGlobal.h"
#include "softSession.h"
#include "softObject.h"
#include "softDH.h"
-#include "softRandom.h"
#include "softCrypt.h"
/*
- * This function converts the big integer of the specified attribute
- * to an octet string and store it in the corresponding key object.
+ * This function takes a converted big integer of the specified attribute
+ * as an octet string and stores it in the corresponding key object.
*/
-CK_RV
-soft_genDHkey_set_attribute(soft_object_t *key, BIGNUM *bn,
- CK_ATTRIBUTE_TYPE type, uint32_t prime_len, boolean_t public)
+static CK_RV
+soft_genDHkey_set_attribute(soft_object_t *key, CK_ATTRIBUTE_TYPE type,
+ uchar_t *buf, uint32_t buflen, boolean_t public)
{
- uchar_t *buf;
- uint32_t buflen;
CK_RV rv = CKR_OK;
biginteger_t *dst = NULL;
biginteger_t src;
- /*
- * Allocate the buffer used to store the value of key fields
- * for bignum2bytestring. Since bignum only deals with a buffer
- * whose size is multiple of 4, prime_len is rounded up to be
- * multiple of 4.
- */
- if ((buf = malloc((prime_len + sizeof (BIG_CHUNK_TYPE) - 1) &
- ~(sizeof (BIG_CHUNK_TYPE) - 1))) == NULL) {
- rv = CKR_HOST_MEMORY;
- goto cleanexit;
- }
-
- buflen = bn->len * (int)sizeof (BIG_CHUNK_TYPE);
- bignum2bytestring(buf, bn, buflen);
-
switch (type) {
case CKA_VALUE:
@@ -89,19 +69,14 @@ soft_genDHkey_set_attribute(soft_object_t *key, BIGNUM *bn,
break;
}
- src.big_value_len = buflen;
-
- if ((src.big_value = malloc(buflen)) == NULL) {
- rv = CKR_HOST_MEMORY;
+ if ((rv = dup_bigint_attr(&src, buf, buflen)) != CKR_OK)
goto cleanexit;
- }
- (void) memcpy(src.big_value, buf, buflen);
/* Copy the attribute in the key object. */
copy_bigint_attr(&src, dst);
cleanexit:
- free(buf);
+ /* No need to free big_value because dst holds it now after copy. */
return (rv);
}
@@ -113,18 +88,15 @@ CK_RV
soft_dh_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey)
{
CK_RV rv;
- BIG_ERR_CODE brv;
+ CK_ATTRIBUTE template;
uchar_t prime[MAX_KEY_ATTR_BUFLEN];
uint32_t prime_len = sizeof (prime);
- uint32_t primebit_len;
- uint32_t value_bits;
uchar_t base[MAX_KEY_ATTR_BUFLEN];
uint32_t base_len = sizeof (base);
- BIGNUM bnprime;
- BIGNUM bnbase;
- BIGNUM bnprival;
- BIGNUM bnpubval;
- CK_ATTRIBUTE template;
+ uint32_t value_bits;
+ uchar_t private_x[MAX_KEY_ATTR_BUFLEN];
+ uchar_t public_y[MAX_KEY_ATTR_BUFLEN];
+ DHbytekey k;
if ((pubkey->class != CKO_PUBLIC_KEY) ||
(pubkey->key_type != CKK_DH)) {
@@ -136,74 +108,19 @@ soft_dh_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey)
return (CKR_KEY_TYPE_INCONSISTENT);
}
- /*
- * The input to the first phase shall be the Diffie-Hellman
- * parameters, which include prime, base, and private-value length.
- */
- rv = soft_get_public_value(pubkey, CKA_PRIME, prime, &prime_len);
-
- if (rv != CKR_OK) {
- return (rv);
- }
-
- if ((prime_len < (MIN_DH_KEYLENGTH / 8)) ||
- (prime_len > (MAX_DH_KEYLENGTH / 8))) {
- rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto ret0;
- }
-
- if ((brv = big_init(&bnprime, CHARLEN2BIGNUMLEN(prime_len))) !=
- BIG_OK) {
- rv = convert_rv(brv);
- goto ret0;
- }
-
- /* Convert the prime octet string to big integer format. */
- bytestring2bignum(&bnprime, prime, prime_len);
-
- rv = soft_get_public_value(pubkey, CKA_BASE, base, &base_len);
-
- if (rv != CKR_OK) {
- goto ret1;
- }
-
- if ((brv = big_init(&bnbase, CHARLEN2BIGNUMLEN(base_len))) != BIG_OK) {
- rv = convert_rv(brv);
- goto ret1;
- }
-
- /* Convert the base octet string to big integer format. */
- bytestring2bignum(&bnbase, base, base_len);
-
- if (big_cmp_abs(&bnbase, &bnprime) >= 0) {
- rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto ret2;
- }
-
- primebit_len = big_bitlength(&bnprime);
-
+ /* Get private-value length in bits */
template.pValue = malloc(sizeof (CK_ULONG));
-
if (template.pValue == NULL) {
- rv = CKR_HOST_MEMORY;
- goto ret2;
+ return (CKR_HOST_MEMORY);
}
-
template.ulValueLen = sizeof (CK_ULONG);
-
rv = get_ulong_attr_from_object(OBJ_PRI_DH_VAL_BITS(prikey),
&template);
-
if (rv != CKR_OK) {
- goto ret2;
+ free(template.pValue);
+ return (rv);
}
- /*
- * The intention of selecting a private-value length is to reduce
- * the computation time for key agreement, while maintaining a
- * given level of security.
- */
-
#ifdef __sparcv9
/* LINTED */
value_bits = (uint32_t)(*((CK_ULONG *)(template.pValue)));
@@ -211,109 +128,87 @@ soft_dh_genkey_pair(soft_object_t *pubkey, soft_object_t *prikey)
value_bits = *((CK_ULONG *)(template.pValue));
#endif /* __sparcv9 */
- if (value_bits > primebit_len) {
- rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto ret3;
- }
+ free(template.pValue);
- /* Generate DH key pair private and public values. */
- if ((brv = big_init(&bnprival, CHARLEN2BIGNUMLEN(prime_len)))
- != BIG_OK) {
- rv = convert_rv(brv);
- goto ret3;
+ /*
+ * The input to the first phase shall be the Diffie-Hellman
+ * parameters, which include prime, base, and private-value length.
+ */
+ rv = soft_get_public_value(pubkey, CKA_PRIME, prime, &prime_len);
+ if (rv != CKR_OK) {
+ return (rv);
}
- if ((brv = big_init(&bnpubval, CHARLEN2BIGNUMLEN(prime_len)))
- != BIG_OK) {
- rv = convert_rv(brv);
- goto ret4;
+ rv = soft_get_public_value(pubkey, CKA_BASE, base, &base_len);
+ if (rv != CKR_OK) {
+ goto ret;
}
- /*
- * The big integer of the private value shall be generated privately
- * and randomly.
- */
- if ((brv = random_bignum(&bnprival, (value_bits == 0) ?
- primebit_len : value_bits, (IS_TOKEN_OBJECT(pubkey) ||
- IS_TOKEN_OBJECT(prikey)))) != BIG_OK) {
- rv = convert_rv(brv);
- goto ret5;
- }
+ /* Inputs to DH key pair generation. */
+ k.prime = prime;
+ k.prime_bits = CRYPTO_BYTES2BITS(prime_len);
+ k.base = base;
+ k.base_bytes = base_len;
+ k.value_bits = value_bits;
+ k.rfunc = (IS_TOKEN_OBJECT(pubkey) || IS_TOKEN_OBJECT(prikey)) ?
+ pkcs11_get_random : pkcs11_get_urandom;
- /*
- * The base g shall be raised to the private value x modulo p to
- * give an integer y, the integer public value.
- */
- if ((brv = big_modexp(&bnpubval,
- &bnbase, &bnprival, &bnprime, NULL)) != BIG_OK) {
- rv = convert_rv(brv);
- goto ret5;
+ /* Outputs from DH key pair generation. */
+ k.private_x = private_x;
+ k.public_y = public_y;
+
+ /* If value_bits is 0, it will return as same size as prime */
+ if ((rv = dh_genkey_pair(&k)) != CKR_OK) {
+ goto ret;
}
/*
* The integer public value y shall be converted to an octet
* string PV of length k, the public value.
*/
- if ((rv = soft_genDHkey_set_attribute(pubkey, &bnpubval,
- CKA_VALUE, prime_len, B_TRUE)) != CKR_OK) {
- goto ret5;
+ if ((rv = soft_genDHkey_set_attribute(pubkey, CKA_VALUE, public_y,
+ CRYPTO_BITS2BYTES(k.value_bits), B_TRUE)) != CKR_OK) {
+ goto ret;
}
/* Convert the big integer private value to an octet string. */
- if ((rv = soft_genDHkey_set_attribute(prikey, &bnprival,
- CKA_VALUE, prime_len, B_FALSE)) != CKR_OK) {
- goto ret5;
+ if ((rv = soft_genDHkey_set_attribute(prikey, CKA_VALUE, private_x,
+ CRYPTO_BITS2BYTES(k.value_bits), B_FALSE)) != CKR_OK) {
+ goto ret;
}
/* Convert the big integer prime to an octet string. */
- if ((rv = soft_genDHkey_set_attribute(prikey, &bnprime,
- CKA_PRIME, prime_len, B_FALSE)) != CKR_OK) {
- goto ret5;
+ if ((rv = soft_genDHkey_set_attribute(prikey, CKA_PRIME, prime,
+ CRYPTO_BITS2BYTES(k.prime_bits), B_FALSE)) != CKR_OK) {
+ goto ret;
}
/* Convert the big integer base to an octet string. */
- if ((rv = soft_genDHkey_set_attribute(prikey, &bnbase,
- CKA_BASE, prime_len, B_FALSE)) != CKR_OK) {
- goto ret5;
- }
-
- if (value_bits == 0) {
- OBJ_PRI_DH_VAL_BITS(prikey) = primebit_len;
+ if ((rv = soft_genDHkey_set_attribute(prikey, CKA_BASE, base,
+ k.base_bytes, B_FALSE)) != CKR_OK) {
+ goto ret;
}
+ /* Update private-value length in bits; could have been 0 before */
+ OBJ_PRI_DH_VAL_BITS(prikey) = k.value_bits;
-ret5:
- big_finish(&bnpubval);
-ret4:
- big_finish(&bnprival);
-ret3:
- free(template.pValue);
-ret2:
- big_finish(&bnbase);
-ret1:
- big_finish(&bnprime);
-ret0:
+ret:
return (rv);
}
+/* ARGSUSED3 */
CK_RV
soft_dh_key_derive(soft_object_t *basekey, soft_object_t *secretkey,
void *publicvalue, size_t publicvaluelen)
{
+ CK_RV rv;
uchar_t privatevalue[MAX_KEY_ATTR_BUFLEN];
uint32_t privatevaluelen = sizeof (privatevalue);
uchar_t privateprime[MAX_KEY_ATTR_BUFLEN];
uint32_t privateprimelen = sizeof (privateprime);
- uchar_t *value;
- uint32_t valuelen;
+ uchar_t key[MAX_KEY_ATTR_BUFLEN];
uint32_t keylen;
- uchar_t *buf = NULL;
- CK_RV rv;
- BIG_ERR_CODE brv;
- BIGNUM bnprime;
- BIGNUM bnpublic;
- BIGNUM bnprivate;
- BIGNUM bnsecret;
+ DHbytekey k;
rv = soft_get_private_value(basekey, CKA_VALUE, privatevalue,
&privatevaluelen);
@@ -324,123 +219,38 @@ soft_dh_key_derive(soft_object_t *basekey, soft_object_t *secretkey,
rv = soft_get_private_value(basekey, CKA_PRIME, privateprime,
&privateprimelen);
if (rv != CKR_OK) {
- goto ret0;
- }
-
- if ((brv = big_init(&bnprime, CHARLEN2BIGNUMLEN(privateprimelen))) !=
- BIG_OK) {
- rv = convert_rv(brv);
- goto ret0;
- }
-
- bytestring2bignum(&bnprime, privateprime, privateprimelen);
-
- if ((brv = big_init(&bnprivate, CHARLEN2BIGNUMLEN(privatevaluelen))) !=
- BIG_OK) {
- rv = convert_rv(brv);
- goto ret1;
- }
-
- bytestring2bignum(&bnprivate, privatevalue, privatevaluelen);
-
-#ifdef __sparcv9
- if ((brv = big_init(&bnpublic,
- (int)CHARLEN2BIGNUMLEN(publicvaluelen))) != BIG_OK) {
-#else /* !__sparcv9 */
- if ((brv = big_init(&bnpublic,
- CHARLEN2BIGNUMLEN(publicvaluelen))) != BIG_OK) {
-#endif /* __sparcv9 */
- rv = convert_rv(brv);
- goto ret2;
- }
-
- bytestring2bignum(&bnpublic, (uchar_t *)publicvalue, publicvaluelen);
-
- if ((brv = big_init(&bnsecret,
- CHARLEN2BIGNUMLEN(privateprimelen))) != BIG_OK) {
- rv = convert_rv(brv);
- goto ret3;
- }
-
- if ((brv = big_modexp(&bnsecret, &bnpublic, &bnprivate, &bnprime,
- NULL)) != BIG_OK) {
- rv = convert_rv(brv);
- goto ret4;
+ goto ret;
}
- if ((buf = malloc((privateprimelen + sizeof (BIG_CHUNK_TYPE) - 1) &
- ~(sizeof (BIG_CHUNK_TYPE) - 1))) == NULL) {
- rv = CKR_HOST_MEMORY;
- goto ret4;
+ /* keylen may be 0 if CKA_VALUE_LEN did not specify */
+ keylen = OBJ_SEC_VALUE_LEN(secretkey);
+ if (keylen > sizeof (key)) { /* check for overflow */
+ rv = CKR_ATTRIBUTE_VALUE_INVALID;
+ goto ret;
}
- value = buf;
- valuelen = bnsecret.len * (int)sizeof (BIG_CHUNK_TYPE);
- bignum2bytestring(value, &bnsecret, valuelen);
-
- switch (secretkey->key_type) {
-
- case CKK_DES:
- keylen = DES_KEYSIZE;
- break;
- case CKK_DES2:
- keylen = DES2_KEYSIZE;
- break;
- case CKK_DES3:
- keylen = DES3_KEYSIZE;
- break;
- case CKK_RC4:
- case CKK_AES:
- case CKK_GENERIC_SECRET:
-#ifdef __sparcv9
- /* LINTED */
- keylen = (uint32_t)OBJ_SEC_VALUE_LEN(secretkey);
-#else /* !__sparcv9 */
- keylen = OBJ_SEC_VALUE_LEN(secretkey);
-#endif /* __sparcv9 */
- break;
- }
+ k.prime = privateprime;
+ k.prime_bits = CRYPTO_BYTES2BITS(privateprimelen);
+ k.value_bits = CRYPTO_BYTES2BITS(privatevaluelen);
+ k.private_x = privatevalue;
+ k.public_y = publicvalue;
+ k.rfunc = NULL;
- if (keylen == 0) {
- /*
- * keylen == 0 only if CKA_VALUE_LEN did not specify.
- */
- keylen = valuelen;
- }
- /*
- * Note: No need to have "default:" case here since invalid key type
- * if any has been detected at function soft_build_secret_key_object()
- * before it gets here.
- */
+ /* keylen may be modified if it was 0 or conflicts with key type */
+ rv = dh_key_derive(&k, secretkey->key_type, key, &keylen);
- if (keylen > valuelen) {
- rv = CKR_ATTRIBUTE_VALUE_INVALID;
- goto ret5;
+ if (rv != CKR_OK) {
+ goto ret;
}
if ((OBJ_SEC_VALUE(secretkey) = malloc(keylen)) == NULL) {
rv = CKR_HOST_MEMORY;
- goto ret5;
+ goto ret;
}
+
OBJ_SEC_VALUE_LEN(secretkey) = keylen;
+ (void) memcpy(OBJ_SEC_VALUE(secretkey), key, keylen);
- /*
- * The truncation removes bytes from the leading end of the
- * secret value.
- */
- (void) memcpy(OBJ_SEC_VALUE(secretkey), (value + valuelen - keylen),
- keylen);
-
-ret5:
- free(buf);
-ret4:
- big_finish(&bnsecret);
-ret3:
- big_finish(&bnpublic);
-ret2:
- big_finish(&bnprivate);
-ret1:
- big_finish(&bnprime);
-ret0:
+ret:
return (rv);
}