Пример #1
0
/*
 * Find all certs of a given type (public or private)
 */
static int pkcs11_find_certs(PKCS11_TOKEN * token)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = TOKEN2CTX(token);
	CK_SESSION_HANDLE session;
	int rv, res = -1;

	/* Make sure we have a session */
	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 0))
		return -1;
	session = PRIVSLOT(slot)->session;

	/* Tell the PKCS11 lib to enumerate all matching objects */
	cert_search_class = CKO_CERTIFICATE;
	rv = CRYPTOKI_call(ctx, C_FindObjectsInit(session, cert_search_attrs,
						  numof(cert_search_attrs)));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv);

	do {
		res = pkcs11_next_cert(ctx, token, session);
	} while (res == 0);

	CRYPTOKI_call(ctx, C_FindObjectsFinal(session));
	return (res < 0) ? -1 : 0;
}
Пример #2
0
/*
 * Find all keys of a given type (public or private)
 */
static int pkcs11_find_keys(PKCS11_TOKEN *token, unsigned int type)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = TOKEN2CTX(token);
	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
	CK_OBJECT_CLASS key_search_class;
	CK_ATTRIBUTE key_search_attrs[1] = {
		{CKA_CLASS, &key_search_class, sizeof(key_search_class)},
	};
	int rv, res = -1;

	/* Tell the PKCS11 lib to enumerate all matching objects */
	key_search_class = type;
	rv = CRYPTOKI_call(ctx,
		C_FindObjectsInit(spriv->session, key_search_attrs, 1));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);

	keys->num = 0;
	do {
		res = pkcs11_next_key(ctx, token, spriv->session, type);
	} while (res == 0);

	CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));

	return (res < 0) ? -1 : 0;
}
Пример #3
0
/*
 * Find all certs of a given type (public or private)
 */
static int pkcs11_find_certs(PKCS11_TOKEN *token)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	CK_OBJECT_CLASS cert_search_class;
	CK_ATTRIBUTE cert_search_attrs[] = {
		{CKA_CLASS, &cert_search_class, sizeof(cert_search_class)},
	};
	int rv, res = -1;

	/* Tell the PKCS11 lib to enumerate all matching objects */
	cert_search_class = CKO_CERTIFICATE;
	rv = CRYPTOKI_call(ctx, C_FindObjectsInit(spriv->session, cert_search_attrs, 1));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv);

	tpriv->ncerts = 0;
	do {
		res = pkcs11_next_cert(ctx, token, spriv->session);
	} while (res == 0);

	CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));

	return (res < 0) ? -1 : 0;
}
Пример #4
0
/*
 * Return keys of a given type (public or private)
 * Use the cached values if available
 */
int pkcs11_enumerate_keys(PKCS11_TOKEN *token, unsigned int type,
		PKCS11_KEY ** keyp, unsigned int *countp)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = TOKEN2CTX(token);
	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
	PKCS11_keys *keys = (type == CKO_PRIVATE_KEY) ? &tpriv->prv : &tpriv->pub;
	int rv;

	if (keys->num < 0) { /* No cache was built for the specified type */
		/* Make sure we have a session */
		if (!spriv->haveSession && PKCS11_open_session(slot, 0))
			return -1;
		CRYPTO_THREAD_write_lock(cpriv->rwlock);
		rv = pkcs11_find_keys(token, type);
		CRYPTO_THREAD_unlock(cpriv->rwlock);
		if (rv < 0) {
			pkcs11_destroy_keys(token, type);
			return -1;
		}
	}
	if (keyp)
		*keyp = keys->keys;
	if (countp)
		*countp = keys->num;
	return 0;
}
Пример #5
0
/*
 * Initialize the token
 */
int PKCS11_init_token(PKCS11_TOKEN * token, const char *pin, const char *label)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(TOKEN2SLOT(token));
	PKCS11_CTX *ctx = priv->parent;
	int rv;

	CHECK_FORK(ctx);

	if (label == NULL)
		label = "PKCS#11 Token";
	rv = CRYPTOKI_call(ctx,
		C_InitToken(priv->id,
			(CK_UTF8CHAR *) pin, strlen(pin), (CK_UTF8CHAR *) label));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_INIT_TOKEN, rv);

	/* FIXME: how to update the token?
	 * PKCS11_CTX_private *cpriv;
	 * int n;
	 * cpriv = PRIVCTX(ctx);
	 * for (n = 0; n < cpriv->nslots; n++) {
	 * 	if (pkcs11_check_token(ctx, cpriv->slots + n) < 0)
	 * 		return -1;
	 * }
	 */

	return 0;
}
Пример #6
0
/*
 * Enumerate all certs on the card
 */
int pkcs11_enumerate_certs(PKCS11_TOKEN *token,
		PKCS11_CERT **certp, unsigned int *countp)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
	int rv;

	if (tpriv->ncerts < 0) {
		/* Make sure we have a session */
		if (!spriv->haveSession && PKCS11_open_session(slot, 0))
			return -1;
		CRYPTO_THREAD_write_lock(cpriv->rwlock);
		rv = pkcs11_find_certs(token);
		CRYPTO_THREAD_unlock(cpriv->rwlock);
		if (rv < 0) {
			pkcs11_destroy_certs(token);
			return -1;
		}
	}
	if (certp)
		*certp = tpriv->certs;
	if (countp)
		*countp = tpriv->ncerts;
	return 0;
}
Пример #7
0
int
pkcs11_getattr_var(PKCS11_TOKEN * token, CK_OBJECT_HANDLE object,
		   unsigned int type, void *value, size_t * size)
{
	return pkcs11_getattr_int(TOKEN2CTX(token),
				  PRIVSLOT(TOKEN2SLOT(token))->session,
				  object, type, value, size);
}
Пример #8
0
/*
 * Set the User PIN
 */
int PKCS11_init_pin(PKCS11_TOKEN * token, const char *pin)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(TOKEN2SLOT(token));
	PKCS11_CTX *ctx = priv->parent;
	int len, rv;

	CHECK_FORK(ctx);

	if (!priv->haveSession) {
		PKCS11err(PKCS11_F_PKCS11_INIT_PIN, PKCS11_NO_SESSION);
		return -1;
	}

	len = pin ? strlen(pin) : 0;
	rv = CRYPTOKI_call(ctx, C_InitPIN(priv->session, (CK_UTF8CHAR *) pin, len));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_INIT_PIN, rv);

	return pkcs11_check_token(ctx, TOKEN2SLOT(token));
}
Пример #9
0
int
PKCS11_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
		PKCS11_KEY * key, int padding)
{
	CK_RV rv;
	PKCS11_KEY_private *priv;
	PKCS11_SLOT *slot;
	PKCS11_CTX *ctx;
	CK_SESSION_HANDLE session;
	CK_MECHANISM mechanism;
	CK_ULONG size = flen;
								
	if (padding != RSA_PKCS1_PADDING) {
			printf("pkcs11 engine: only RSA_PKCS1_PADDING allowed so far\n");
			return -1;
	}
	if (key == NULL)
			return -1;

	/* PKCS11 calls go here */
										
	ctx = KEY2CTX(key);
	priv = PRIVKEY(key);
	slot = TOKEN2SLOT(priv->parent);
	CHECK_KEY_FORK(key);

	session = PRIVSLOT(slot)->session;
	memset(&mechanism, 0, sizeof(mechanism));
	mechanism.mechanism = CKM_RSA_PKCS;


	pkcs11_w_lock(PRIVSLOT(slot)->lockid);
	rv = CRYPTOKI_call(ctx, C_DecryptInit(session, &mechanism, priv->object)) ||
		CRYPTOKI_call(ctx,
			C_Decrypt(session, (CK_BYTE *) from, (CK_ULONG)flen,
				(CK_BYTE_PTR)to, &size));
	pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

	if (rv) {
		PKCS11err(PKCS11_F_PKCS11_RSA_DECRYPT, pkcs11_map_err(rv));
	}

	return rv ? 0 : size;
}
Пример #10
0
/*
 * Authenticate a private the key operation if needed
 */
int pkcs11_authenticate(PKCS11_KEY *key)
{
	PKCS11_KEY_private *kpriv = PRIVKEY(key);
	PKCS11_TOKEN *token = KEY2TOKEN(key);
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	char pin[MAX_PIN_LENGTH+1];
	UI *ui;
	int rv;

	/* Handle CKF_PROTECTED_AUTHENTICATION_PATH */
	if (token->secureLogin) {
		rv = CRYPTOKI_call(ctx,
			C_Login(spriv->session, CKU_CONTEXT_SPECIFIC, NULL, 0));
		return rv == CKR_USER_ALREADY_LOGGED_IN ? 0 : rv;
	}

	/* Call UI to ask for a PIN */
	ui = UI_new_method(kpriv->ui_method);
	if (ui == NULL)
		return PKCS11_UI_FAILED;
	if (kpriv->ui_user_data != NULL)
		UI_add_user_data(ui, kpriv->ui_user_data);
	memset(pin, 0, MAX_PIN_LENGTH+1);
	if (!UI_add_input_string(ui, "PKCS#11 key PIN: ",
			UI_INPUT_FLAG_DEFAULT_PWD, pin, 4, MAX_PIN_LENGTH)) {
		UI_free(ui);
		return PKCS11_UI_FAILED;
	}
	if (UI_process(ui)) {
		UI_free(ui);
		return PKCS11_UI_FAILED;
	}
	UI_free(ui);

	/* Login with the PIN */
	rv = CRYPTOKI_call(ctx,
		C_Login(spriv->session, CKU_CONTEXT_SPECIFIC,
			(CK_UTF8CHAR *)pin, strlen(pin)));
	OPENSSL_cleanse(pin, MAX_PIN_LENGTH+1);
	return rv == CKR_USER_ALREADY_LOGGED_IN ? 0 : rv;
}
Пример #11
0
int
PKCS11_ecdsa_sign(const unsigned char *m, unsigned int m_len,
		unsigned char *sigret, unsigned int *siglen, PKCS11_KEY * key)
{
/* signature size is the issue, will assume caller has a big buffer ! */
/* No padding or other stuff needed, we can cal PKCS11 from here */
	int rv;
	PKCS11_KEY_private *priv;
	PKCS11_SLOT *slot;
	PKCS11_CTX *ctx;
	CK_SESSION_HANDLE session;
	CK_MECHANISM mechanism;
	CK_ULONG ck_sigsize;

	ctx = KEY2CTX(key);
	priv = PRIVKEY(key);
	slot = TOKEN2SLOT(priv->parent);

	CHECK_KEY_FORK(key);

	session = PRIVSLOT(slot)->session;

	ck_sigsize = *siglen;

	memset(&mechanism, 0, sizeof(mechanism));
	mechanism.mechanism = CKM_ECDSA;

	pkcs11_w_lock(PRIVSLOT(slot)->lockid);
	rv = CRYPTOKI_call(ctx, C_SignInit(session, &mechanism, priv->object)) ||
		CRYPTOKI_call(ctx,
			C_Sign(session, (CK_BYTE *) m, m_len, sigret, &ck_sigsize));
	pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

	if (rv) {
		PKCS11err(PKCS11_F_PKCS11_EC_KEY_SIGN, pkcs11_map_err(rv));
		return -1;
	}
	*siglen = ck_sigsize;

	return ck_sigsize;
}
Пример #12
0
/*
 * Store certificate
 */
int
PKCS11_store_certificate(PKCS11_TOKEN * token, X509 * x509, char *label,
			 unsigned char *id, size_t id_len,
			 PKCS11_CERT ** ret_cert)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = TOKEN2CTX(token);
	CK_SESSION_HANDLE session;
	CK_OBJECT_HANDLE object;
	CK_ATTRIBUTE attrs[32];
	unsigned int n = 0;
	int rv;

	/* First, make sure we have a session */
	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
		return -1;
	session = PRIVSLOT(slot)->session;

	/* Now build the template */
	pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_CERTIFICATE);
	pkcs11_addattr_bool(attrs + n++, CKA_TOKEN, TRUE);
	pkcs11_addattr_int(attrs + n++, CKA_CERTIFICATE_TYPE, CKC_X_509);
	pkcs11_addattr_obj(attrs + n++, CKA_VALUE, (pkcs11_i2d_fn) i2d_X509, x509);
	if (label)
		pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
	if (id && id_len)
		pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);

	/* Now call the pkcs11 module to create the object */
	rv = CRYPTOKI_call(ctx, C_CreateObject(session, attrs, n, &object));

	/* Zap all memory allocated when building the template */
	pkcs11_zap_attrs(attrs, n);

	CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_CERTIFICATE, rv);

	/* Gobble the key object */
	return pkcs11_init_cert(ctx, token, session, object, ret_cert);
}
Пример #13
0
/*
 * Store private key
 */
static int pkcs11_store_key(PKCS11_TOKEN *token, EVP_PKEY *pk,
		unsigned int type, char *label, unsigned char *id, size_t id_len,
		PKCS11_KEY ** ret_key)
{
	PKCS11_SLOT *slot = TOKEN2SLOT(token);
	PKCS11_CTX *ctx = TOKEN2CTX(token);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	CK_OBJECT_HANDLE object;
	CK_ATTRIBUTE attrs[32];
	unsigned int n = 0;
	int rv;
	const BIGNUM *rsa_n, *rsa_e, *rsa_d, *rsa_p, *rsa_q;

	/* First, make sure we have a session */
	if (!spriv->haveSession && PKCS11_open_session(slot, 1))
		return -1;

	/* Now build the key attrs */
	pkcs11_addattr_int(attrs + n++, CKA_CLASS, type);
	if (label)
		pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
	if (id && id_len)
		pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);
	pkcs11_addattr_bool(attrs + n++, CKA_TOKEN, TRUE);
	if (type == CKO_PRIVATE_KEY) {
		pkcs11_addattr_bool(attrs + n++, CKA_PRIVATE, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_SENSITIVE, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_DECRYPT, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_SIGN, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_UNWRAP, TRUE);
	} else { /* CKO_PUBLIC_KEY */
		pkcs11_addattr_bool(attrs + n++, CKA_ENCRYPT, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_VERIFY, TRUE);
		pkcs11_addattr_bool(attrs + n++, CKA_WRAP, TRUE);
	}
#if OPENSSL_VERSION_NUMBER >= 0x10100003L
	if (EVP_PKEY_base_id(pk) == EVP_PKEY_RSA) {
		RSA *rsa = EVP_PKEY_get1_RSA(pk);
#else
	if (pk->type == EVP_PKEY_RSA) {
		RSA *rsa = pk->pkey.rsa;
#endif
		pkcs11_addattr_int(attrs + n++, CKA_KEY_TYPE, CKK_RSA);
#if OPENSSL_VERSION_NUMBER >= 0x10100005L
		RSA_get0_key(rsa, &rsa_n, &rsa_e, &rsa_d);
		RSA_get0_factors(rsa, &rsa_p, &rsa_q);
#else
		rsa_n=rsa->n;
		rsa_e=rsa->e;
		rsa_d=rsa->d;
		rsa_p=rsa->p;
		rsa_q=rsa->q;
#endif
		pkcs11_addattr_bn(attrs + n++, CKA_MODULUS, rsa_n);
		pkcs11_addattr_bn(attrs + n++, CKA_PUBLIC_EXPONENT, rsa_e);
		if (type == CKO_PRIVATE_KEY) {
			pkcs11_addattr_bn(attrs + n++, CKA_PRIVATE_EXPONENT, rsa_d);
			pkcs11_addattr_bn(attrs + n++, CKA_PRIME_1, rsa_p);
			pkcs11_addattr_bn(attrs + n++, CKA_PRIME_2, rsa_q);
		}
	} else {
		pkcs11_zap_attrs(attrs, n);
		PKCS11err(type == CKO_PRIVATE_KEY ?
				PKCS11_F_PKCS11_STORE_PRIVATE_KEY :
				PKCS11_F_PKCS11_STORE_PUBLIC_KEY,
			PKCS11_NOT_SUPPORTED);
		return -1;
	}

	/* Now call the pkcs11 module to create the object */
	rv = CRYPTOKI_call(ctx, C_CreateObject(spriv->session, attrs, n, &object));

	/* Zap all memory allocated when building the template */
	pkcs11_zap_attrs(attrs, n);

	CRYPTOKI_checkerr(PKCS11_F_PKCS11_STORE_PRIVATE_KEY, rv);

	/* Gobble the key object */
	return pkcs11_init_key(ctx, token, spriv->session, object, type, ret_key);
}

/*
 * Get the key type
 */
int pkcs11_get_key_type(PKCS11_KEY *key)
{
	PKCS11_KEY_private *kpriv = PRIVKEY(key);

	return kpriv->ops->type;
}
Пример #14
0
int
PKCS11_private_encrypt(int flen, const unsigned char *from, unsigned char *to,
		PKCS11_KEY * key, int padding)
{
	PKCS11_KEY_private *priv;
	PKCS11_SLOT *slot;
	PKCS11_CTX *ctx;
	CK_SESSION_HANDLE session;
	CK_MECHANISM mechanism;
	int rv;
	int sigsize;
	CK_ULONG ck_sigsize;

	if (key == NULL)
		return -1;

	sigsize=PKCS11_get_key_size(key);
	ck_sigsize=sigsize;

	memset(&mechanism, 0, sizeof(mechanism));

	switch (padding) {

		case RSA_NO_PADDING:
			mechanism.mechanism = CKM_RSA_X_509;
			break;

		case RSA_PKCS1_PADDING:
			if ((flen + RSA_PKCS1_PADDING_SIZE) > sigsize) {
				return -1; /* the size is wrong */
			}
			mechanism.mechanism = CKM_RSA_PKCS;
			break;

		default:
			printf("pkcs11 engine: only RSA_NO_PADDING or RSA_PKCS1_PADDING allowed so far\n");
			return -1;
	}

	ctx = KEY2CTX(key);
	priv = PRIVKEY(key);
	slot = TOKEN2SLOT(priv->parent);

	CHECK_KEY_FORK(key);

	session = PRIVSLOT(slot)->session;

	pkcs11_w_lock(PRIVSLOT(slot)->lockid);
	/* API is somewhat fishy here. *siglen is 0 on entry (cleared
	 * by OpenSSL). The library assumes that the memory passed
	 * by the caller is always big enough */
	rv = CRYPTOKI_call(ctx, C_SignInit(session, &mechanism, priv->object)) ||
		CRYPTOKI_call(ctx,
			C_Sign(session, (CK_BYTE *) from, flen, to, &ck_sigsize));
	pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

	if (rv) {
		PKCS11err(PKCS11_F_PKCS11_RSA_SIGN, pkcs11_map_err(rv));
		return -1;
	}

	if ((unsigned)sigsize != ck_sigsize)
		return -1;

	return sigsize;
}