示例#1
0
static isc_boolean_t
pkcs11rsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
	pk11_object_t *rsa1, *rsa2;
	CK_ATTRIBUTE *attr1, *attr2;

	rsa1 = key1->keydata.pkey;
	rsa2 = key2->keydata.pkey;

	if ((rsa1 == NULL) && (rsa2 == NULL))
		return (ISC_TRUE);
	else if ((rsa1 == NULL) || (rsa2 == NULL))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(rsa1, CKA_MODULUS);
	attr2 = pk11_attribute_bytype(rsa2, CKA_MODULUS);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(rsa1, CKA_PUBLIC_EXPONENT);
	attr2 = pk11_attribute_bytype(rsa2, CKA_PUBLIC_EXPONENT);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(rsa1, CKA_PRIVATE_EXPONENT);
	attr2 = pk11_attribute_bytype(rsa2, CKA_PRIVATE_EXPONENT);
	if (((attr1 != NULL) || (attr2 != NULL)) &&
	    ((attr1 == NULL) || (attr2 == NULL) ||
	     (attr1->ulValueLen != attr2->ulValueLen) ||
	     memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
		return (ISC_FALSE);

	if (!rsa1->ontoken && !rsa2->ontoken)
		return (ISC_TRUE);
	else if (rsa1->ontoken || rsa2->ontoken ||
		 (rsa1->object != rsa2->object))
		return (ISC_FALSE);

	return (ISC_TRUE);
}
示例#2
0
static isc_result_t
pkcs11rsa_fromlabel(dst_key_t *key, const char *engine, const char *label,
		    const char *pin)
{
	CK_RV rv;
	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
	CK_OBJECT_CLASS keyClass = CKO_PUBLIC_KEY;
	CK_KEY_TYPE keyType = CKK_RSA;
	CK_ATTRIBUTE searchTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_LABEL, NULL, 0 }
	};
	CK_ULONG cnt;
	CK_ATTRIBUTE *attr;
	pk11_object_t *rsa;
	pk11_context_t *pk11_ctx = NULL;
	isc_result_t ret;
	unsigned int i;

	UNUSED(pin);

	rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
	if (rsa == NULL)
		return (ISC_R_NOMEMORY);
	memset(rsa, 0, sizeof(*rsa));
	rsa->object = CK_INVALID_HANDLE;
	rsa->ontoken = ISC_TRUE;
	rsa->reqlogon = ISC_TRUE;
	key->keydata.pkey = rsa;

	rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
	if (rsa->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(rsa->repr, 0, sizeof(*attr) * 2);
	rsa->attrcnt = 2;
	attr = rsa->repr;
	attr[0].type = CKA_MODULUS;
	attr[1].type = CKA_PUBLIC_EXPONENT;

	ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
	if (ret != ISC_R_SUCCESS)
		goto err;

	pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
						  sizeof(*pk11_ctx));
	if (pk11_ctx == NULL)
		DST_RET(ISC_R_NOMEMORY);
	ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
			       rsa->reqlogon, NULL, rsa->slot);
	if (ret != ISC_R_SUCCESS)
		goto err;

	attr = pk11_attribute_bytype(rsa, CKA_LABEL);
	if (attr == NULL) {
		attr = pk11_attribute_bytype(rsa, CKA_ID);
		INSIST(attr != NULL);
		searchTemplate[3].type = CKA_ID;
	}
	searchTemplate[3].pValue = attr->pValue;
	searchTemplate[3].ulValueLen = attr->ulValueLen;

	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &hKey, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	attr = rsa->repr;
	PK11_RET(pkcs_C_GetAttributeValue,
		 (pk11_ctx->session, hKey, attr, 2),
		 DST_R_CRYPTOFAILURE);
	for (i = 0; i <= 1; i++) {
		attr[i].pValue = isc_mem_get(key->mctx, attr[i].ulValueLen);
		if (attr[i].pValue == NULL)
			DST_RET(ISC_R_NOMEMORY);
		memset(attr[i].pValue, 0, attr[i].ulValueLen);
	}
	PK11_RET(pkcs_C_GetAttributeValue,
		 (pk11_ctx->session, hKey, attr, 2),
		 DST_R_CRYPTOFAILURE);

	keyClass = CKO_PRIVATE_KEY;
	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	if (engine != NULL) {
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
	}

	key->label = isc_mem_strdup(key->mctx, label);
	if (key->label == NULL)
		DST_RET(ISC_R_NOMEMORY);

	attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
	INSIST(attr != NULL);
	if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
		DST_RET(ISC_R_RANGE);

	attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
	INSIST(attr != NULL);
	key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

	pk11_return_session(pk11_ctx);
	memset(pk11_ctx, 0, sizeof(*pk11_ctx));
	isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));

	return (ISC_R_SUCCESS);

    err:
	pkcs11rsa_destroy(key);
	if (pk11_ctx != NULL) {
		pk11_return_session(pk11_ctx);
		memset(pk11_ctx, 0, sizeof(*pk11_ctx));
		isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	}

	return (ret);
}
示例#3
0
static isc_result_t
pkcs11rsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	int i;
	pk11_object_t *rsa;
	CK_ATTRIBUTE *attr;
	isc_mem_t *mctx = key->mctx;
	const char *engine = NULL, *label = NULL;

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_RSA, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		return (ret);

	if (key->external) {
		if (priv.nelements != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		if (pub == NULL)
			DST_RET(DST_R_INVALIDPRIVATEKEY);

		key->keydata.pkey = pub->keydata.pkey;
		pub->keydata.pkey = NULL;
		key->key_size = pub->key_size;

		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));

		return (ISC_R_SUCCESS);
	}

	for (i = 0; i < priv.nelements; i++) {
		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			engine = (char *)priv.elements[i].data;
			break;
		case TAG_RSA_LABEL:
			label = (char *)priv.elements[i].data;
			break;
		default:
			break;
		}
	}
	rsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*rsa));
	if (rsa == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(rsa, 0, sizeof(*rsa));
	key->keydata.pkey = rsa;

	/* Is this key is stored in a HSM? See if we can fetch it. */
	if ((label != NULL) || (engine != NULL)) {
		ret = pkcs11rsa_fetch(key, engine, label, pub);
		if (ret != ISC_R_SUCCESS)
			goto err;
		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));
		return (ret);
	}

	rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 8);
	if (rsa->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(rsa->repr, 0, sizeof(*attr) * 8);
	rsa->attrcnt = 8;
	attr = rsa->repr;
	attr[0].type = CKA_MODULUS;
	attr[1].type = CKA_PUBLIC_EXPONENT;
	attr[2].type = CKA_PRIVATE_EXPONENT;
	attr[3].type = CKA_PRIME_1;
	attr[4].type = CKA_PRIME_2;
	attr[5].type = CKA_EXPONENT_1;
	attr[6].type = CKA_EXPONENT_2;
	attr[7].type = CKA_COEFFICIENT;

	for (i = 0; i < priv.nelements; i++) {
		CK_BYTE *bn;

		switch (priv.elements[i].tag) {
		case TAG_RSA_ENGINE:
			continue;
		case TAG_RSA_LABEL:
			continue;
		default:
			bn = isc_mem_get(key->mctx, priv.elements[i].length);
			if (bn == NULL)
				DST_RET(ISC_R_NOMEMORY);
			memmove(bn, priv.elements[i].data,
				priv.elements[i].length);
		}

		switch (priv.elements[i].tag) {
			case TAG_RSA_MODULUS:
				attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_PUBLICEXPONENT:
				attr = pk11_attribute_bytype(rsa,
						CKA_PUBLIC_EXPONENT);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_PRIVATEEXPONENT:
				attr = pk11_attribute_bytype(rsa,
						CKA_PRIVATE_EXPONENT);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_PRIME1:
				attr = pk11_attribute_bytype(rsa, CKA_PRIME_1);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_PRIME2:
				attr = pk11_attribute_bytype(rsa, CKA_PRIME_2);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_EXPONENT1:
				attr = pk11_attribute_bytype(rsa,
							     CKA_EXPONENT_1);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_EXPONENT2:
				attr = pk11_attribute_bytype(rsa,
							     CKA_EXPONENT_2);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_RSA_COEFFICIENT:
				attr = pk11_attribute_bytype(rsa,
							     CKA_COEFFICIENT);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
		}
	}

	if (rsa_check(rsa, pub->keydata.pkey) != ISC_R_SUCCESS)
		DST_RET(DST_R_INVALIDPRIVATEKEY);

	attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
	INSIST(attr != NULL);
	key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

	attr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
	INSIST(attr != NULL);
	if (pk11_numbits(attr->pValue, attr->ulValueLen) > RSA_MAX_PUBEXP_BITS)
		DST_RET(ISC_R_RANGE);

	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));

	return (ISC_R_SUCCESS);

 err:
	pkcs11rsa_destroy(key);
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}
示例#4
0
static isc_result_t
rsa_check(pk11_object_t *rsa, pk11_object_t *pubrsa) {
	CK_ATTRIBUTE *pubattr, *privattr;
	CK_BYTE *priv_exp = NULL, *priv_mod = NULL;
	CK_BYTE *pub_exp = NULL, *pub_mod = NULL;
	unsigned int priv_explen = 0, priv_modlen = 0;
	unsigned int pub_explen = 0, pub_modlen = 0;

	REQUIRE(rsa != NULL && pubrsa != NULL);

	privattr = pk11_attribute_bytype(rsa, CKA_PUBLIC_EXPONENT);
	INSIST(privattr != NULL);
	priv_exp = privattr->pValue;
	priv_explen = privattr->ulValueLen;

	pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
	INSIST(pubattr != NULL);
	pub_exp = pubattr->pValue;
	pub_explen = pubattr->ulValueLen;

	if (priv_exp != NULL) {
		if (priv_explen != pub_explen)
			return (DST_R_INVALIDPRIVATEKEY);
		if (memcmp(priv_exp, pub_exp, pub_explen) != 0)
			return (DST_R_INVALIDPRIVATEKEY);
	} else {
		privattr->pValue = pub_exp;
		privattr->ulValueLen = pub_explen;
		pubattr->pValue = NULL;
		pubattr->ulValueLen = 0;
	}

	if (privattr->pValue == NULL)
		return (DST_R_INVALIDPRIVATEKEY);

	privattr = pk11_attribute_bytype(rsa, CKA_MODULUS);
	INSIST(privattr != NULL);
	priv_mod = privattr->pValue;
	priv_modlen = privattr->ulValueLen;

	pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
	INSIST(pubattr != NULL);
	pub_mod = pubattr->pValue;
	pub_modlen = pubattr->ulValueLen;

	if (priv_mod != NULL) {
		if (priv_modlen != pub_modlen)
			return (DST_R_INVALIDPRIVATEKEY);
		if (memcmp(priv_mod, pub_mod, pub_modlen) != 0)
			return (DST_R_INVALIDPRIVATEKEY);
	} else {
		privattr->pValue = pub_mod;
		privattr->ulValueLen = pub_modlen;
		pubattr->pValue = NULL;
		pubattr->ulValueLen = 0;
	}

	if (privattr->pValue == NULL)
		return (DST_R_INVALIDPRIVATEKEY);

	return (ISC_R_SUCCESS);
}
示例#5
0
static isc_result_t
pkcs11rsa_fetch(dst_key_t *key, const char *engine, const char *label,
		dst_key_t *pub)
{
	CK_RV rv;
	CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
	CK_KEY_TYPE keyType = CKK_RSA;
	CK_ATTRIBUTE searchTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_TOKEN, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_LABEL, NULL, 0 }
	};
	CK_ULONG cnt;
	CK_ATTRIBUTE *attr;
	CK_ATTRIBUTE *pubattr;
	pk11_object_t *rsa;
	pk11_object_t *pubrsa;
	pk11_context_t *pk11_ctx = NULL;
	isc_result_t ret;

	if (label == NULL)
		return (DST_R_NOENGINE);

	rsa = key->keydata.pkey;
	pubrsa = pub->keydata.pkey;

	rsa->object = CK_INVALID_HANDLE;
	rsa->ontoken = ISC_TRUE;
	rsa->reqlogon = ISC_TRUE;
	rsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 2);
	if (rsa->repr == NULL)
		return (ISC_R_NOMEMORY);
	memset(rsa->repr, 0, sizeof(*attr) * 2);
	rsa->attrcnt = 2;
	attr = rsa->repr;

	attr->type = CKA_MODULUS;
	pubattr = pk11_attribute_bytype(pubrsa, CKA_MODULUS);
	attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
	attr->ulValueLen = pubattr->ulValueLen;
	attr++;

	attr->type = CKA_PUBLIC_EXPONENT;
	pubattr = pk11_attribute_bytype(pubrsa, CKA_PUBLIC_EXPONENT);
	attr->pValue = isc_mem_get(key->mctx, pubattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pubattr->pValue, pubattr->ulValueLen);
	attr->ulValueLen = pubattr->ulValueLen;

	ret = pk11_parse_uri(rsa, label, key->mctx, OP_RSA);
	if (ret != ISC_R_SUCCESS)
		goto err;

	pk11_ctx = (pk11_context_t *) isc_mem_get(key->mctx,
						  sizeof(*pk11_ctx));
	if (pk11_ctx == NULL)
		DST_RET(ISC_R_NOMEMORY);
	ret = pk11_get_session(pk11_ctx, OP_RSA, ISC_TRUE, ISC_FALSE,
			       rsa->reqlogon, NULL, rsa->slot);
	if (ret != ISC_R_SUCCESS)
		goto err;

	attr = pk11_attribute_bytype(rsa, CKA_LABEL);
	if (attr == NULL) {
		attr = pk11_attribute_bytype(rsa, CKA_ID);
		INSIST(attr != NULL);
		searchTemplate[3].type = CKA_ID;
	}
	searchTemplate[3].pValue = attr->pValue;
	searchTemplate[3].ulValueLen = attr->ulValueLen;

	PK11_RET(pkcs_C_FindObjectsInit,
		 (pk11_ctx->session, searchTemplate, (CK_ULONG) 4),
		 DST_R_CRYPTOFAILURE);
	PK11_RET(pkcs_C_FindObjects,
		 (pk11_ctx->session, &rsa->object, (CK_ULONG) 1, &cnt),
		 DST_R_CRYPTOFAILURE);
	(void) pkcs_C_FindObjectsFinal(pk11_ctx->session);
	if (cnt == 0)
		DST_RET(ISC_R_NOTFOUND);
	if (cnt > 1)
		DST_RET(ISC_R_EXISTS);

	if (engine != NULL) {
		key->engine = isc_mem_strdup(key->mctx, engine);
		if (key->engine == NULL)
			DST_RET(ISC_R_NOMEMORY);
	}

	key->label = isc_mem_strdup(key->mctx, label);
	if (key->label == NULL)
		DST_RET(ISC_R_NOMEMORY);

	pk11_return_session(pk11_ctx);
	memset(pk11_ctx, 0, sizeof(*pk11_ctx));
	isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));

	attr = pk11_attribute_bytype(rsa, CKA_MODULUS);
	INSIST(attr != NULL);
	key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

	return (ISC_R_SUCCESS);

    err:
	if (pk11_ctx != NULL) {
		pk11_return_session(pk11_ctx);
		memset(pk11_ctx, 0, sizeof(*pk11_ctx));
		isc_mem_put(key->mctx, pk11_ctx, sizeof(*pk11_ctx));
	}

	return (ret);
}
示例#6
0
static isc_result_t
pkcs11gost_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	pk11_object_t *gost = NULL;
	CK_ATTRIBUTE *attr, *pattr;
	isc_mem_t *mctx = key->mctx;

	if ((pub == NULL) || (pub->keydata.pkey == NULL))
		DST_RET(DST_R_INVALIDPRIVATEKEY);

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		return (ret);

	if (key->external) {
		if (priv.nelements != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);

		key->keydata.pkey = pub->keydata.pkey;
		pub->keydata.pkey = NULL;
		key->key_size = pub->key_size;

		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));

		return (ISC_R_SUCCESS);
	}

	if (priv.elements[0].tag == TAG_GOST_PRIVASN1) {
		int adj = (int) priv.elements[0].length - (39 + 32);
		unsigned char buf[39];

		if ((adj > 0) || (adj < -31))
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		memmove(buf, gost_private_der, 39);
		if (adj != 0) {
			buf[1] += adj;
			buf[36] += adj;
			buf[38] += adj;
		}
		if (memcmp(priv.elements[0].data, buf, 39) != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		priv.elements[0].tag = TAG_GOST_PRIVRAW;
		priv.elements[0].length -= 39;
		memmove(priv.elements[0].data,
			priv.elements[0].data + 39,
			32 + adj);
	}

	gost = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*gost));
	if (gost == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(gost, 0, sizeof(*gost));
	key->keydata.pkey = gost;

	gost->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx,
						  sizeof(*attr) * 2);
	if (gost->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(gost->repr, 0, sizeof(*attr) * 2);
	gost->attrcnt = 2;

	attr = gost->repr;
	attr->type = CKA_VALUE;
	pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
	INSIST(pattr != NULL);
	attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
	attr->ulValueLen = pattr->ulValueLen;

	attr++;
	attr->type = CKA_VALUE2;
	attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length);
	attr->ulValueLen = priv.elements[0].length;

	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));

	return (ISC_R_SUCCESS);

 err:
	pkcs11gost_destroy(key);
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}
示例#7
0
文件: pk11.c 项目: execunix/vinos
isc_result_t
pk11_parse_uri(pk11_object_t *obj, const char *label,
	       isc_mem_t *mctx, pk11_optype_t optype)
{
	CK_ATTRIBUTE *attr;
	pk11_token_t *token = NULL;
	char *uri, *p, *a, *na, *v;
	size_t len, l;
	FILE *stream = NULL;
	char pin[PINLEN + 1];
	isc_boolean_t gotpin = ISC_FALSE;
	isc_result_t ret;

	/* get values to work on */
	len = strlen(label) + 1;
	uri = isc_mem_get(mctx, len);
	if (uri == NULL)
		return (ISC_R_NOMEMORY);
	memmove(uri, label, len);

	/* get the URI scheme */
	p = strchr(uri, ':');
	if (p == NULL)
		DST_RET(PK11_R_NOPROVIDER);
	*p++ = '\0';
	if (strcmp(uri, "pkcs11") != 0)
		DST_RET(PK11_R_NOPROVIDER);

	/* get attributes */
	for (na = p; na != NULL;) {
		a = na;
		p = strchr(a, ';');
		if (p == NULL) {
			/* last attribute */
			na = NULL;
		} else {
			*p++ = '\0';
			na = p;
		}
		p = strchr(a, '=');
		if (p != NULL) {
			*p++ = '\0';
			v = p;
		} else
			v = a;
		l = 0;
		v = percent_decode(v, &l);
		if (v == NULL)
			DST_RET(PK11_R_NOPROVIDER);
		if ((a == v) || (strcmp(a, "object") == 0)) {
			/* object: CKA_LABEL */
			attr = pk11_attribute_bytype(obj, CKA_LABEL);
			if (attr != NULL)
				DST_RET(PK11_R_NOPROVIDER);
			attr = push_attribute(obj, mctx, l);
			if (attr == NULL)
				DST_RET(ISC_R_NOMEMORY);
			attr->type = CKA_LABEL;
			memmove(attr->pValue, v, l);
		} else if (strcmp(a, "token") == 0) {
			/* token: CK_TOKEN_INFO label */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->name, 32))
						break;
		} else if (strcmp(a, "manufacturer") == 0) {
			/* manufacturer: CK_TOKEN_INFO manufacturerID */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->manuf, 32))
						break;
		} else if (strcmp(a, "serial") == 0) {
			/* serial: CK_TOKEN_INFO serialNumber */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->serial, 16))
						break;
		} else if (strcmp(a, "model") == 0) {
			/* model: CK_TOKEN_INFO model */
			if (token == NULL)
				for (token = ISC_LIST_HEAD(tokens);
				     token != NULL;
				     token = ISC_LIST_NEXT(token, link))
					if (pk11strcmp(v, l, token->model, 16))
						break;
		} else if (strcmp(a, "library-manufacturer") == 0) {
			/* ignored */
		} else if (strcmp(a, "library-description") == 0) {
			/* ignored */
		} else if (strcmp(a, "library-version") == 0) {
			/* ignored */
		} else if (strcmp(a, "object-type") == 0) {
			/* object-type: CKA_CLASS */
			/* only private makes sense */
			if (strcmp(v, "private") != 0)
				DST_RET(PK11_R_NOPROVIDER);
		} else if (strcmp(a, "id") == 0) {
			/* id: CKA_ID */
			attr = pk11_attribute_bytype(obj, CKA_ID);
			if (attr != NULL)
				DST_RET(PK11_R_NOPROVIDER);
			attr = push_attribute(obj, mctx, l);
			if (attr == NULL)
				DST_RET(ISC_R_NOMEMORY);
			attr->type = CKA_ID;
			memmove(attr->pValue, v, l);
		} else if (strcmp(a, "pin-source") == 0) {
			/* pin-source: PIN */
			ret = isc_stdio_open(v, "r", &stream);
			if (ret != ISC_R_SUCCESS)
				goto err;
			memset(pin, 0, PINLEN + 1);
			ret = isc_stdio_read(pin, 1, PINLEN + 1, stream, &l);
			if ((ret != ISC_R_SUCCESS) && (ret != ISC_R_EOF))
				goto err;
			if (l > PINLEN)
				DST_RET(ISC_R_RANGE);
			ret = isc_stdio_close(stream);
			stream = NULL;
			if (ret != ISC_R_SUCCESS)
				goto err;
			gotpin = ISC_TRUE;
		} else
			DST_RET(PK11_R_NOPROVIDER);
	}

	if ((pk11_attribute_bytype(obj, CKA_LABEL) == NULL) &&
	    (pk11_attribute_bytype(obj, CKA_ID) == NULL))
		DST_RET(ISC_R_NOTFOUND);

	if (token == NULL) {
		if (optype == OP_RSA)
			token = best_rsa_token;
		else if (optype == OP_DSA)
			token = best_dsa_token;
		else if (optype == OP_DH)
			token = best_dh_token;
		else if (optype == OP_EC)
			token = best_ec_token;
	}
	if (token == NULL)
		DST_RET(ISC_R_NOTFOUND);
	obj->slot = token->slotid;
	if (gotpin) {
		memmove(token->pin, pin, PINLEN + 1);
		obj->reqlogon = ISC_TRUE;
	}

	ret = ISC_R_SUCCESS;

  err:
	if (stream != NULL)
		(void) isc_stdio_close(stream);
	isc_mem_put(mctx, uri, len);
	return (ret);
}
示例#8
0
static isc_result_t
pkcs11ecdsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	pk11_object_t *ec = NULL;
	CK_ATTRIBUTE *attr, *pattr;
	isc_mem_t *mctx = key->mctx;
	unsigned int i;
	const char *engine = NULL, *label = NULL;

	REQUIRE(key->key_alg == DST_ALG_ECDSA256 ||
		key->key_alg == DST_ALG_ECDSA384);

	if ((pub == NULL) || (pub->keydata.pkey == NULL))
		DST_RET(DST_R_INVALIDPRIVATEKEY);

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_ECDSA256, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		return (ret);

	if (key->external) {
		if (priv.nelements != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);

		key->keydata.pkey = pub->keydata.pkey;
		pub->keydata.pkey = NULL;
		key->key_size = pub->key_size;

		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));

		return (ISC_R_SUCCESS);
	}

	for (i = 0; i < priv.nelements; i++) {
		switch (priv.elements[i].tag) {
		case TAG_ECDSA_ENGINE:
			engine = (char *)priv.elements[i].data;
			break;
		case TAG_ECDSA_LABEL:
			label = (char *)priv.elements[i].data;
			break;
		default:
			break;
		}
	}
	ec = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*ec));
	if (ec == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(ec, 0, sizeof(*ec));
	key->keydata.pkey = ec;

	/* Is this key is stored in a HSM? See if we can fetch it. */
	if ((label != NULL) || (engine != NULL)) {
		ret = pkcs11ecdsa_fetch(key, engine, label, pub);
		if (ret != ISC_R_SUCCESS)
			goto err;
		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));
		return (ret);
	}

	ec->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 3);
	if (ec->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(ec->repr, 0, sizeof(*attr) * 3);
	ec->attrcnt = 3;

	attr = ec->repr;
	attr->type = CKA_EC_PARAMS;
	pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_PARAMS);
	INSIST(pattr != NULL);
	attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
	attr->ulValueLen = pattr->ulValueLen;

	attr++;
	attr->type = CKA_EC_POINT;
	pattr = pk11_attribute_bytype(pub->keydata.pkey, CKA_EC_POINT);
	INSIST(pattr != NULL);
	attr->pValue = isc_mem_get(key->mctx, pattr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, pattr->pValue, pattr->ulValueLen);
	attr->ulValueLen = pattr->ulValueLen;

	attr++;
	attr->type = CKA_VALUE;
	attr->pValue = isc_mem_get(key->mctx, priv.elements[0].length);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(attr->pValue, priv.elements[0].data, priv.elements[0].length);
	attr->ulValueLen = priv.elements[0].length;

	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	if (key->key_alg == DST_ALG_ECDSA256)
		key->key_size = DNS_KEY_ECDSA256SIZE * 4;
	else
		key->key_size = DNS_KEY_ECDSA384SIZE * 4;

	return (ISC_R_SUCCESS);

 err:
	pkcs11ecdsa_destroy(key);
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}
示例#9
0
static isc_result_t
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) {
			memset(keyTemplate[i].pValue, 0,
			       keyTemplate[i].ulValueLen);
			isc_mem_put(key->mctx,
				    keyTemplate[i].pValue,
				    keyTemplate[i].ulValueLen);
		}
	return (ret);
}
示例#10
0
static isc_result_t
pkcs11dh_computesecret(const dst_key_t *pub, const dst_key_t *priv,
		       isc_buffer_t *secret)
{
	CK_RV rv;
	CK_MECHANISM mech = { CKM_DH_PKCS_DERIVE, NULL, 0 };
	CK_OBJECT_CLASS keyClass = CKO_SECRET_KEY;
	CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
	CK_OBJECT_HANDLE hDerived = CK_INVALID_HANDLE;
	CK_OBJECT_HANDLE hKey = CK_INVALID_HANDLE;
	CK_ATTRIBUTE *attr;
	CK_ULONG secLen;
	CK_ATTRIBUTE keyTemplate[] =
	{
		{ CKA_CLASS, &keyClass, (CK_ULONG) sizeof(keyClass) },
		{ CKA_KEY_TYPE, &keyType, (CK_ULONG) sizeof(keyType) },
		{ CKA_PRIVATE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_SENSITIVE, &falsevalue, (CK_ULONG) sizeof(falsevalue) },
		{ CKA_EXTRACTABLE, &truevalue, (CK_ULONG) sizeof(truevalue) },
		{ CKA_VALUE_LEN, &secLen, (CK_ULONG) sizeof(secLen) }
	};
	CK_ATTRIBUTE valTemplate[] =
	{
		{ CKA_VALUE, NULL, 0 }
	};
	CK_BYTE *secValue;
	pk11_context_t ctx;
	isc_result_t ret;
	unsigned int i;
	isc_region_t r;

	REQUIRE(pub->keydata.pkey != NULL);
	REQUIRE(priv->keydata.pkey != NULL);
	REQUIRE(priv->keydata.pkey->repr != NULL);
	attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_PRIME);
	if (attr == NULL)
		return (DST_R_INVALIDPUBLICKEY);
	REQUIRE(attr != NULL);
	secLen = attr->ulValueLen;
	attr = pk11_attribute_bytype(pub->keydata.pkey, CKA_VALUE);
	if (attr == NULL)
		return (DST_R_INVALIDPUBLICKEY);

	ret = pk11_get_session(&ctx, OP_DH, ISC_TRUE, ISC_FALSE, ISC_FALSE,
			       NULL, pk11_get_best_token(OP_DH));
	if (ret != ISC_R_SUCCESS)
		return (ret);

	mech.ulParameterLen = attr->ulValueLen;
	mech.pParameter = isc_mem_get(pub->mctx, mech.ulParameterLen);
	if (mech.pParameter == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memmove(mech.pParameter, attr->pValue, mech.ulParameterLen);

	ret = pkcs11dh_loadpriv(priv, ctx.session, &hKey);
	if (ret != ISC_R_SUCCESS)
		goto err;

	PK11_RET(pkcs_C_DeriveKey,
		 (ctx.session, &mech, hKey,
		  keyTemplate, (CK_ULONG) 6, &hDerived),
		 DST_R_COMPUTESECRETFAILURE);

	attr = valTemplate;
	PK11_RET(pkcs_C_GetAttributeValue,
		 (ctx.session, hDerived, attr, (CK_ULONG) 1),
		 DST_R_CRYPTOFAILURE);
	attr->pValue = isc_mem_get(pub->mctx, attr->ulValueLen);
	if (attr->pValue == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(attr->pValue, 0, attr->ulValueLen);
	PK11_RET(pkcs_C_GetAttributeValue,
		 (ctx.session, hDerived, attr, (CK_ULONG) 1),
		 DST_R_CRYPTOFAILURE);

	/* strip leading zeros */
	secValue = (CK_BYTE_PTR) attr->pValue;
	for (i = 0; i < attr->ulValueLen; i++)
		if (secValue[i] != 0)
			break;
	isc_buffer_availableregion(secret, &r);
	if (r.length < attr->ulValueLen - i)
		DST_RET(ISC_R_NOSPACE);
	memmove(r.base, secValue + i, attr->ulValueLen - i);
	isc_buffer_add(secret, attr->ulValueLen - i);
	ret = ISC_R_SUCCESS;

    err:
	if (hDerived != CK_INVALID_HANDLE)
		(void) pkcs_C_DestroyObject(ctx.session, hDerived);
	if (valTemplate[0].pValue != NULL) {
		memset(valTemplate[0].pValue, 0, valTemplate[0].ulValueLen);
		isc_mem_put(pub->mctx,
			    valTemplate[0].pValue,
			    valTemplate[0].ulValueLen);
	}
	if ((hKey != CK_INVALID_HANDLE) && !priv->keydata.pkey->ontoken)
		(void) pkcs_C_DestroyObject(ctx.session, hKey);
	if (mech.pParameter != NULL) {
		memset(mech.pParameter, 0, mech.ulParameterLen);
		isc_mem_put(pub->mctx, mech.pParameter, mech.ulParameterLen);
	}
	pk11_return_session(&ctx);
	return (ret);
}
static isc_result_t
pkcs11dsa_parse(dst_key_t *key, isc_lex_t *lexer, dst_key_t *pub) {
	dst_private_t priv;
	isc_result_t ret;
	int i;
	pk11_object_t *dsa = NULL;
	CK_ATTRIBUTE *attr;
	isc_mem_t *mctx = key->mctx;

	/* read private key file */
	ret = dst__privstruct_parse(key, DST_ALG_DSA, lexer, mctx, &priv);
	if (ret != ISC_R_SUCCESS)
		return (ret);

	if (key->external) {
		if (priv.nelements != 0)
			DST_RET(DST_R_INVALIDPRIVATEKEY);
		if (pub == NULL)
			DST_RET(DST_R_INVALIDPRIVATEKEY);

		key->keydata.pkey = pub->keydata.pkey;
		pub->keydata.pkey = NULL;
		key->key_size = pub->key_size;

		dst__privstruct_free(&priv, mctx);
		memset(&priv, 0, sizeof(priv));

		return (ISC_R_SUCCESS);
	}

	dsa = (pk11_object_t *) isc_mem_get(key->mctx, sizeof(*dsa));
	if (dsa == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(dsa, 0, sizeof(*dsa));
	key->keydata.pkey = dsa;

	dsa->repr = (CK_ATTRIBUTE *) isc_mem_get(key->mctx, sizeof(*attr) * 5);
	if (dsa->repr == NULL)
		DST_RET(ISC_R_NOMEMORY);
	memset(dsa->repr, 0, sizeof(*attr) * 5);
	dsa->attrcnt = 5;
	attr = dsa->repr;
	attr[0].type = CKA_PRIME;
	attr[1].type = CKA_SUBPRIME;
	attr[2].type = CKA_BASE;
	attr[3].type = CKA_VALUE;
	attr[4].type = CKA_VALUE2;

	for (i = 0; i < priv.nelements; i++) {
		CK_BYTE *bn;

		bn = isc_mem_get(key->mctx, priv.elements[i].length);
		if (bn == NULL)
			DST_RET(ISC_R_NOMEMORY);
		memmove(bn, priv.elements[i].data, priv.elements[i].length);

		switch (priv.elements[i].tag) {
			case TAG_DSA_PRIME:
				attr = pk11_attribute_bytype(dsa, CKA_PRIME);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_DSA_SUBPRIME:
				attr = pk11_attribute_bytype(dsa,
							     CKA_SUBPRIME);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_DSA_BASE:
				attr = pk11_attribute_bytype(dsa, CKA_BASE);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_DSA_PRIVATE:
				attr = pk11_attribute_bytype(dsa, CKA_VALUE2);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
			case TAG_DSA_PUBLIC:
				attr = pk11_attribute_bytype(dsa, CKA_VALUE);
				INSIST(attr != NULL);
				attr->pValue = bn;
				attr->ulValueLen = priv.elements[i].length;
				break;
		}
	}
	dst__privstruct_free(&priv, mctx);

	attr = pk11_attribute_bytype(dsa, CKA_PRIME);
	INSIST(attr != NULL);
	key->key_size = pk11_numbits(attr->pValue, attr->ulValueLen);

	return (ISC_R_SUCCESS);

 err:
	pkcs11dsa_destroy(key);
	dst__privstruct_free(&priv, mctx);
	memset(&priv, 0, sizeof(priv));
	return (ret);
}
static isc_boolean_t
pkcs11dsa_compare(const dst_key_t *key1, const dst_key_t *key2) {
	pk11_object_t *dsa1, *dsa2;
	CK_ATTRIBUTE *attr1, *attr2;

	dsa1 = key1->keydata.pkey;
	dsa2 = key2->keydata.pkey;

	if ((dsa1 == NULL) && (dsa2 == NULL))
		return (ISC_TRUE);
	else if ((dsa1 == NULL) || (dsa2 == NULL))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(dsa1, CKA_PRIME);
	attr2 = pk11_attribute_bytype(dsa2, CKA_PRIME);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(dsa1, CKA_SUBPRIME);
	attr2 = pk11_attribute_bytype(dsa2, CKA_SUBPRIME);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(dsa1, CKA_BASE);
	attr2 = pk11_attribute_bytype(dsa2, CKA_BASE);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE);
	attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE);
	if ((attr1 == NULL) && (attr2 == NULL))
		return (ISC_TRUE);
	else if ((attr1 == NULL) || (attr2 == NULL) ||
		 (attr1->ulValueLen != attr2->ulValueLen) ||
		 memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen))
		return (ISC_FALSE);

	attr1 = pk11_attribute_bytype(dsa1, CKA_VALUE2);
	attr2 = pk11_attribute_bytype(dsa2, CKA_VALUE2);
	if (((attr1 != NULL) || (attr2 != NULL)) &&
	    ((attr1 == NULL) || (attr2 == NULL) ||
	     (attr1->ulValueLen != attr2->ulValueLen) ||
	     memcmp(attr1->pValue, attr2->pValue, attr1->ulValueLen)))
		return (ISC_FALSE);

	if (!dsa1->ontoken && !dsa2->ontoken)
		return (ISC_TRUE);
	else if (dsa1->ontoken || dsa2->ontoken ||
		 (dsa1->object != dsa2->object))
		return (ISC_FALSE);

	return (ISC_TRUE);
}