pkcs11dh_loadpriv(const dst_key_t *key,
		  CK_SESSION_HANDLE session,
		  CK_OBJECT_HANDLE *hKey)
{
	CK_RV rv;
	CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
	CK_KEY_TYPE keyType = CKK_DH;
	CK_ATTRIBUTE keyTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_PRIME, NULL, 0 },
		{ CKA_BASE, NULL, 0 },
		{ CKA_VALUE, NULL, 0 }
	};
	CK_ATTRIBUTE *attr;
	const pk11_object_t *priv;
	isc_result_t ret;
	unsigned int i;

	priv = key->keydata.pkey;
	if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
		*hKey = priv->object;
		return (ISC_R_SUCCESS);
	}

	attr = pk11_attribute_bytype(priv, CKA_PRIME);
	if (attr == NULL)
		return (DST_R_INVALIDPRIVATEKEY);
	keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[6].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[6].ulValueLen = attr->ulValueLen;

	attr = pk11_attribute_bytype(priv, CKA_BASE);
	if (attr == NULL)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[7].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[7].ulValueLen = attr->ulValueLen;

	attr = pk11_attribute_bytype(priv, CKA_VALUE2);
	if (attr == NULL)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[8].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[8].ulValueLen = attr->ulValueLen;

	PK11_CALL(pkcs_C_CreateObject,
		  (session, keyTemplate, (CK_ULONG) 9, hKey),
		  DST_R_COMPUTESECRETFAILURE);
	if (rv == CKR_OK)
		ret = ISC_R_SUCCESS;

    err:
	for (i = 6; i <= 8; i++)
		if (keyTemplate[i].pValue != NULL) {
			isc_safe_memwipe(keyTemplate[i].pValue,
					 keyTemplate[i].ulValueLen);
			isc_mem_put(key->mctx,
				    keyTemplate[i].pValue,
				    keyTemplate[i].ulValueLen);
		}
	return (ret);
}
pkcs11dh_loadpriv(const dst_key_t *key,
		  CK_SESSION_HANDLE session,
		  CK_OBJECT_HANDLE *hKey)
{
	CK_RV rv;
	CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
	CK_KEY_TYPE keyType = CKK_DH;
	CK_ATTRIBUTE keyTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_DERIVE, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_PRIME, NULL, 0 },
		{ CKA_BASE, NULL, 0 },
		{ CKA_VALUE, NULL, 0 }
	};
	CK_ATTRIBUTE *attr;
	const pk11_object_t *priv;
	isc_result_t ret;
	unsigned int i;

	priv = key->keydata.pkey;
	if ((priv->object != CK_INVALID_HANDLE) && priv->ontoken) {
		*hKey = priv->object;
		return (ISC_R_SUCCESS);
	}

	attr = pk11_attribute_bytype(priv, CKA_PRIME);
	if (attr == NULL)
		return (DST_R_INVALIDPRIVATEKEY);
	keyTemplate[6].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[6].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[6].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[6].ulValueLen = attr->ulValueLen;

	attr = pk11_attribute_bytype(priv, CKA_BASE);
	if (attr == NULL)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	keyTemplate[7].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[7].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[7].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[7].ulValueLen = attr->ulValueLen;

	attr = pk11_attribute_bytype(priv, CKA_VALUE2);
	if (attr == NULL)
		DST_RET(DST_R_INVALIDPRIVATEKEY);
	keyTemplate[8].pValue = isc_mem_get(key->mctx, attr->ulValueLen);
	if (keyTemplate[8].pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(keyTemplate[8].pValue, attr->pValue, attr->ulValueLen);
	keyTemplate[8].ulValueLen = attr->ulValueLen;

	PK11_CALL(pkcs_C_CreateObject,
		  (session, keyTemplate, (CK_ULONG) 9, hKey),
		  DST_R_COMPUTESECRETFAILURE);
	if (rv == CKR_OK)
		ret = ISC_R_SUCCESS;

    err:
	for (i = 6; i <= 8; i++)
		if (keyTemplate[i].pValue != NULL) {
			isc_safe_memwipe(keyTemplate[i].pValue,
					 keyTemplate[i].ulValueLen);
			isc_mem_put(key->mctx,
				    keyTemplate[i].pValue,
				    keyTemplate[i].ulValueLen);
		}
	return (ret);
}