Ejemplo n.º 1
0
/*
 * Reopens the object associated with the key
 */
int pkcs11_reload_key(PKCS11_KEY *key)
{
	PKCS11_KEY_private *kpriv = PRIVKEY(key);
	PKCS11_SLOT *slot = KEY2SLOT(key);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	CK_OBJECT_CLASS key_search_class =
		key->isPrivate ? CKO_PRIVATE_KEY : CKO_PUBLIC_KEY;
	CK_ATTRIBUTE key_search_attrs[2] = {
		{CKA_CLASS, &key_search_class, sizeof(key_search_class)},
		{CKA_ID, kpriv->id, kpriv->id_len},
	};
	CK_ULONG count;
	int rv;

	/* this is already covered with a per-ctx lock */

	rv = CRYPTOKI_call(ctx,
		C_FindObjectsInit(spriv->session, key_search_attrs, 2));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);

	rv = CRYPTOKI_call(ctx,
		C_FindObjects(spriv->session, &kpriv->object, 1, &count));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_KEYS, rv);

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

	return 0;
}
Ejemplo n.º 2
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;
}
Ejemplo n.º 3
0
/*
 * Load the shared library, and initialize it.
 */
int PKCS11_CTX_load(PKCS11_CTX * ctx, const char *name)
{
    PKCS11_CTX_private *priv = PRIVCTX(ctx);
    CK_C_INITIALIZE_ARGS args;
    CK_INFO ck_info;
    int rv;

    if (priv->libinfo != NULL) {
        PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_MODULE_LOADED_ERROR);
        return -1;
    }
    handle = C_LoadModule(name, &priv->method);
    if (!handle) {
        PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_LOAD_MODULE_ERROR);
        return -1;
    }

    /* Tell the PKCS11 to initialize itself */
    memset(&args, 0, sizeof(args));
    args.pReserved = priv->init_args;
    rv = priv->method->C_Initialize(&args);
    if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
        PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv);
        return -1;
    }

    /* Get info on the library */
    rv = priv->method->C_GetInfo(&ck_info);
    CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv);

    ctx->manufacturer = PKCS11_DUP(ck_info.manufacturerID);
    ctx->description = PKCS11_DUP(ck_info.libraryDescription);

    return 0;
}
Ejemplo n.º 4
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;
}
Ejemplo n.º 5
0
/*
 * Helper functions
 */
static int pkcs11_init_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot, CK_SLOT_ID id)
{
	PKCS11_SLOT_private *priv;
	CK_SLOT_INFO info;
	int rv;

	rv = CRYPTOKI_call(ctx, C_GetSlotInfo(id, &info));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);

	priv = OPENSSL_malloc(sizeof(PKCS11_SLOT_private));
	if (priv == NULL)
		return -1;
	memset(priv, 0, sizeof(PKCS11_SLOT_private));

	priv->parent = ctx;
	priv->id = id;
	priv->forkid = PRIVCTX(ctx)->forkid;
	priv->prev_rw = 0;
	priv->prev_pin = NULL;
	priv->prev_so = 0;
	priv->lockid = CRYPTO_get_new_dynlockid();

	slot->description = PKCS11_DUP(info.slotDescription);
	slot->manufacturer = PKCS11_DUP(info.manufacturerID);
	slot->removable = (info.flags & CKF_REMOVABLE_DEVICE) ? 1 : 0;
	slot->_private = priv;

	if ((info.flags & CKF_TOKEN_PRESENT) && pkcs11_check_token(ctx, slot))
		return -1;

	return 0;
}
Ejemplo n.º 6
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;
}
Ejemplo n.º 7
0
/*
 * Determines if user is authenticated with token
 */
int PKCS11_is_logged_in(PKCS11_SLOT * slot, int so, int * res)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	CK_SESSION_INFO session_info;
	int rv;

	if (priv->loggedIn) {
		*res = 1;
		return 0;
	}
	if (!priv->haveSession) {
		/* SO gets a r/w session by default,
		 * user gets a r/o session by default. */
		if (PKCS11_open_session(slot, so))
			return -1;
	}

	rv = CRYPTOKI_call(ctx, C_GetSessionInfo(priv->session, &session_info));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_GETSESSIONINFO, rv);
	if (so) {
		*res = session_info.state == CKS_RW_SO_FUNCTIONS;
	} else {
		*res = session_info.state == CKS_RO_USER_FUNCTIONS || session_info.state == CKS_RW_USER_FUNCTIONS;
	}
	return 0;
}
Ejemplo n.º 8
0
/*
 * Open a session with this slot
 */
static
int pkcs11_open_session(PKCS11_SLOT * slot, int rw, int relogin)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	int rv;

	if (relogin == 0) {
		CHECK_SLOT_FORK(slot);

		if (priv->haveSession) {
			CRYPTOKI_call(ctx, C_CloseSession(priv->session));
			priv->haveSession = 0;
		}
	}
	rv = CRYPTOKI_call(ctx,
		C_OpenSession(priv->id,
			CKF_SERIAL_SESSION | (rw ? CKF_RW_SESSION : 0),
			NULL, NULL, &priv->session));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_OPEN_SESSION, rv);
	priv->haveSession = 1;
	priv->prev_rw = rw;

	return 0;
}
Ejemplo n.º 9
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;
}
Ejemplo n.º 10
0
static int pkcs11_check_token(PKCS11_CTX * ctx, PKCS11_SLOT * slot)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_TOKEN_private *tpriv;
	CK_TOKEN_INFO info;
	int rv;

	if (slot->token) {
		pkcs11_destroy_token(slot->token);
	} else {
		slot->token = OPENSSL_malloc(sizeof(PKCS11_TOKEN));
		if (slot->token == NULL)
			return -1;
		memset(slot->token, 0, sizeof(PKCS11_TOKEN));
	}

	rv = CRYPTOKI_call(ctx, C_GetTokenInfo(priv->id, &info));
	if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED) {
		OPENSSL_free(slot->token);
		slot->token = NULL;
		return 0;
	}
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_CHECK_TOKEN, rv);

	/* We have a token */
	tpriv = OPENSSL_malloc(sizeof(PKCS11_TOKEN_private));
	if (tpriv == NULL)
		return -1;
	memset(tpriv, 0, sizeof(PKCS11_TOKEN_private));
	tpriv->parent = slot;
	tpriv->prv.keys = NULL;
	tpriv->prv.num = -1;
	tpriv->pub.keys = NULL;
	tpriv->pub.num = -1;
	tpriv->ncerts = -1;

	slot->token->label = PKCS11_DUP(info.label);
	slot->token->manufacturer = PKCS11_DUP(info.manufacturerID);
	slot->token->model = PKCS11_DUP(info.model);
	slot->token->serialnr = PKCS11_DUP(info.serialNumber);
	slot->token->initialized = (info.flags & CKF_TOKEN_INITIALIZED) ? 1 : 0;
	slot->token->loginRequired = (info.flags & CKF_LOGIN_REQUIRED) ? 1 : 0;
	slot->token->secureLogin = (info.flags & CKF_PROTECTED_AUTHENTICATION_PATH) ? 1 : 0;
	slot->token->userPinSet = (info.flags & CKF_USER_PIN_INITIALIZED) ? 1 : 0;
	slot->token->readOnly = (info.flags & CKF_WRITE_PROTECTED) ? 1 : 0;
	slot->token->hasRng = (info.flags & CKF_RNG) ? 1 : 0;
	slot->token->userPinCountLow = (info.flags & CKF_USER_PIN_COUNT_LOW) ? 1 : 0;
	slot->token->userPinFinalTry = (info.flags & CKF_USER_PIN_FINAL_TRY) ? 1 : 0;
	slot->token->userPinLocked = (info.flags & CKF_USER_PIN_LOCKED) ? 1 : 0;
	slot->token->userPinToBeChanged = (info.flags & CKF_USER_PIN_TO_BE_CHANGED) ? 1 : 0;
	slot->token->soPinCountLow = (info.flags & CKF_SO_PIN_COUNT_LOW) ? 1 : 0;
	slot->token->soPinFinalTry = (info.flags & CKF_SO_PIN_FINAL_TRY) ? 1 : 0;
	slot->token->soPinLocked = (info.flags & CKF_SO_PIN_LOCKED) ? 1 : 0;
	slot->token->soPinToBeChanged = (info.flags & CKF_SO_PIN_TO_BE_CHANGED) ? 1 : 0;
	slot->token->_private = tpriv;

	return 0;
}
Ejemplo n.º 11
0
int
pkcs11_enumerate_slots(PKCS11_CTX * ctx, PKCS11_SLOT ** slotp, unsigned int *countp)
{
	PKCS11_CTX_private *priv;
	CK_SLOT_ID *slotid;
	CK_ULONG nslots, n;
	PKCS11_SLOT *slots;
	int rv;

	priv = PRIVCTX(ctx);

	rv = priv->method->C_GetSlotList(FALSE, NULL_PTR, &nslots);
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);

	slotid = OPENSSL_malloc(nslots * sizeof(CK_SLOT_ID));
	if (slotid == NULL)
		return -1;

	rv = priv->method->C_GetSlotList(FALSE, slotid, &nslots);
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_SLOTS, rv);

	slots = OPENSSL_malloc(nslots * sizeof(PKCS11_SLOT));
	if (slots == NULL)
		return -1;
	memset(slots, 0, nslots * sizeof(PKCS11_SLOT));
	for (n = 0; n < nslots; n++) {
		if (pkcs11_init_slot(ctx, &slots[n], slotid[n])) {
			while (n--)
				pkcs11_release_slot(ctx, slots + n);
			OPENSSL_free(slotid);
			OPENSSL_free(slots);
			return -1;
		}
	}

	if (slotp)
		*slotp = slots;
	else
		OPENSSL_free(slots);
	if (countp)
		*countp = nslots;
	OPENSSL_free(slotid);
	return 0;
}
Ejemplo n.º 12
0
int PKCS11_reopen_session(PKCS11_SLOT * slot)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = SLOT2CTX(slot);
	int rv;

	rv = CRYPTOKI_call(ctx,
		C_OpenSession(priv->id,
			CKF_SERIAL_SESSION | (priv->prev_rw ? CKF_RW_SESSION : 0),
			NULL, NULL, &priv->session));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_OPEN_SESSION, rv);
	priv->haveSession = 1;

	return 0;
}
Ejemplo n.º 13
0
/*
 * Authenticate with the card. relogin should be set if we automatically
 * relogin after a fork.
 */
static
int pkcs11_login(PKCS11_SLOT * slot, int so, const char *pin, int relogin)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	int rv;

	if (relogin == 0) {
		CHECK_SLOT_FORK(slot);

		/* Calling PKCS11_login invalidates all cached
		 * keys we have */
		if (slot->token) {
			pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY);
			pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY);
		}
		if (priv->loggedIn) {
			/* already logged in, log out first */
			if (PKCS11_logout(slot))
				return -1;
		}
	}
	if (!priv->haveSession) {
		/* SO gets a r/w session by default,
		 * user gets a r/o session by default. */
		if (pkcs11_open_session(slot, so, relogin))
			return -1;
	}

	rv = CRYPTOKI_call(ctx,
		C_Login(priv->session, so ? CKU_SO : CKU_USER,
			(CK_UTF8CHAR *) pin, pin ? strlen(pin) : 0));
	if (rv && rv != CKR_USER_ALREADY_LOGGED_IN)  /* logged in -> OK   */
		CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGIN, rv);
	priv->loggedIn = 1;

	if (priv->prev_pin != pin) {
		if (priv->prev_pin) {
			OPENSSL_cleanse(priv->prev_pin, strlen(priv->prev_pin));
			OPENSSL_free(priv->prev_pin);
		}
		priv->prev_pin = BUF_strdup(pin);
	}
	priv->prev_so = so;
	return 0;
}
Ejemplo n.º 14
0
/*
 * Query pkcs11 attributes
 */
static int
pkcs11_getattr_int(PKCS11_CTX * ctx, CK_SESSION_HANDLE session,
		   CK_OBJECT_HANDLE o, CK_ATTRIBUTE_TYPE type, void *value,
		   size_t * size)
{
	CK_ATTRIBUTE templ;
	int rv;

	templ.type = type;
	templ.pValue = value;
	templ.ulValueLen = *size;

	rv = CRYPTOKI_call(ctx, C_GetAttributeValue(session, o, &templ, 1));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_GETATTR, rv);

	*size = templ.ulValueLen;
	return 0;
}
Ejemplo n.º 15
0
static int pkcs11_next_cert(PKCS11_CTX * ctx, PKCS11_TOKEN * token,
		CK_SESSION_HANDLE session)
{
	CK_OBJECT_HANDLE obj;
	CK_ULONG count;
	int rv;

	/* Get the next matching object */
	rv = CRYPTOKI_call(ctx, C_FindObjects(session, &obj, 1, &count));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_ENUM_CERTS, rv);

	if (count == 0)
		return 1;

	if (pkcs11_init_cert(ctx, token, session, obj, NULL))
		return -1;

	return 0;
}
Ejemplo n.º 16
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));
}
Ejemplo n.º 17
0
/*
 * Generate random numbers
 */
int PKCS11_generate_random(PKCS11_SLOT *slot, unsigned char *r,
		unsigned int r_len)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	int rv;

	CHECK_SLOT_FORK(slot);

	if (!priv->haveSession && PKCS11_open_session(slot, 0)) {
		PKCS11err(PKCS11_F_PKCS11_GENERATE_RANDOM, PKCS11_NO_SESSION);
		return -1;
	}

	rv = CRYPTOKI_call(ctx,
		C_GenerateRandom(priv->session, (CK_BYTE_PTR) r, r_len));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_GENERATE_RANDOM, rv);

	return pkcs11_check_token(ctx, slot);
}
Ejemplo n.º 18
0
/*
 * Seed the random number generator
 */
int PKCS11_seed_random(PKCS11_SLOT *slot, const unsigned char *s,
		unsigned int s_len)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	int rv;

	CHECK_SLOT_FORK(slot);

	if (!priv->haveSession && PKCS11_open_session(slot, 0)) {
		PKCS11err(PKCS11_F_PKCS11_SEED_RANDOM, PKCS11_NO_SESSION);
		return -1;
	}

	rv = CRYPTOKI_call(ctx,
		C_SeedRandom(priv->session, (CK_BYTE_PTR) s, s_len));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_SEED_RANDOM, rv);

	return pkcs11_check_token(ctx, slot);
}
Ejemplo n.º 19
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);
}
Ejemplo n.º 20
0
/*
 * Change the User PIN
 */
int PKCS11_change_pin(PKCS11_SLOT * slot, const char *old_pin,
		const char *new_pin)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	int old_len, new_len, rv;

	CHECK_SLOT_FORK(slot);

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

	old_len = old_pin ? strlen(old_pin) : 0;
	new_len = new_pin ? strlen(new_pin) : 0;
	rv = CRYPTOKI_call(ctx,
		C_SetPIN(priv->session, (CK_UTF8CHAR *) old_pin, old_len,
			(CK_UTF8CHAR *) new_pin, new_len));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_CHANGE_PIN, rv);

	return pkcs11_check_token(ctx, slot);
}
Ejemplo n.º 21
0
/*
 * Load the shared library, and initialize it.
 */
int pkcs11_CTX_load(PKCS11_CTX * ctx, const char *name)
{
	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
	CK_C_INITIALIZE_ARGS _args;
	CK_C_INITIALIZE_ARGS *args = NULL;
	CK_INFO ck_info;
	int rv;

	cpriv->handle = C_LoadModule(name, &cpriv->method);
	if (cpriv->handle == NULL) {
		PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, PKCS11_LOAD_MODULE_ERROR);
		return -1;
	}

	/* Tell the PKCS11 to initialize itself */
	if (cpriv->init_args != NULL) {
		memset(&_args, 0, sizeof(_args));
		args = &_args;
		/* Unconditionally say using OS locking primitives is OK */
		args->flags |= CKF_OS_LOCKING_OK;
		args->pReserved = cpriv->init_args;
	}
	rv = cpriv->method->C_Initialize(args);
	if (rv && rv != CKR_CRYPTOKI_ALREADY_INITIALIZED) {
		PKCS11err(PKCS11_F_PKCS11_CTX_LOAD, rv);
		return -1;
	}

	/* Get info on the library */
	rv = cpriv->method->C_GetInfo(&ck_info);
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_CTX_LOAD, rv);

	ctx->manufacturer = PKCS11_DUP(ck_info.manufacturerID);
	ctx->description = PKCS11_DUP(ck_info.libraryDescription);

	return 0;
}
Ejemplo n.º 22
0
/*
 * Log out
 */
int PKCS11_logout(PKCS11_SLOT * slot)
{
	PKCS11_SLOT_private *priv = PRIVSLOT(slot);
	PKCS11_CTX *ctx = priv->parent;
	int rv;

	CHECK_SLOT_FORK(slot);

	/* Calling PKCS11_logout invalidates all cached
	 * keys we have */
	if (slot->token) {
		pkcs11_destroy_keys(slot->token, CKO_PRIVATE_KEY);
		pkcs11_destroy_keys(slot->token, CKO_PUBLIC_KEY);
	}
	if (!priv->haveSession) {
		PKCS11err(PKCS11_F_PKCS11_LOGOUT, PKCS11_NO_SESSION);
		return -1;
	}

	rv = CRYPTOKI_call(ctx, C_Logout(priv->session));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_LOGOUT, rv);
	priv->loggedIn = 0;
	return 0;
}
Ejemplo n.º 23
0
/* initial code will only support what is needed for pkcs11_ec_ckey
 * i.e. CKM_ECDH1_DERIVE, CKM_ECDH1_COFACTOR_DERIVE
 * and CK_EC_KDF_TYPE  supported by token
 * The secret key object is deleted
 *
 * In future CKM_ECMQV_DERIVE with CK_ECMQV_DERIVE_PARAMS
 * could also be supported, and the secret key object could be returned.
 */
static int pkcs11_ecdh_derive(unsigned char **out, size_t *outlen,
		const unsigned long ecdh_mechanism,
		const void * ec_params,
		void *outnewkey,
		PKCS11_KEY * key)
{
	PKCS11_SLOT *slot = KEY2SLOT(key);
	PKCS11_CTX *ctx = KEY2CTX(key);
	PKCS11_TOKEN *token = KEY2TOKEN(key);
	PKCS11_KEY_private *kpriv = PRIVKEY(key);
	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
	CK_MECHANISM mechanism;
	int rv;

	CK_BBOOL true = TRUE;
	CK_BBOOL false = FALSE;
	CK_OBJECT_HANDLE newkey = CK_INVALID_HANDLE;
	CK_OBJECT_CLASS newkey_class= CKO_SECRET_KEY;
	CK_KEY_TYPE newkey_type = CKK_GENERIC_SECRET;
	CK_OBJECT_HANDLE * tmpnewkey = (CK_OBJECT_HANDLE *)outnewkey;
	CK_ATTRIBUTE newkey_template[] = {
		{CKA_TOKEN, &false, sizeof(false)}, /* session only object */
		{CKA_CLASS, &newkey_class, sizeof(newkey_class)},
		{CKA_KEY_TYPE, &newkey_type, sizeof(newkey_type)},
		{CKA_ENCRYPT, &true, sizeof(true)},
		{CKA_DECRYPT, &true, sizeof(true)}
	};

	memset(&mechanism, 0, sizeof(mechanism));
	mechanism.mechanism  = ecdh_mechanism;
	mechanism.pParameter =  (void*)ec_params;
	switch (ecdh_mechanism) {
		case CKM_ECDH1_DERIVE:
		case CKM_ECDH1_COFACTOR_DERIVE:
			mechanism.ulParameterLen  = sizeof(CK_ECDH1_DERIVE_PARAMS);
			break;
#if 0
		/* TODO */
		case CK_ECMQV_DERIVE_PARAMS:
			mechanism.ulParameterLen  = sizeof(CK_ECMQV_DERIVE_PARAMS);
			break;
#endif
		default:
			PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, pkcs11_map_err(PKCS11_NOT_SUPPORTED));
			return -1;
	}

	rv = CRYPTOKI_call(ctx, C_DeriveKey(spriv->session, &mechanism, kpriv->object, newkey_template, 5, &newkey));
	CRYPTOKI_checkerr(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY, rv);

	/* Return the value of the secret key and/or the object handle of the secret key */
	if (out && outlen) { /* pkcs11_ec_ckey only asks for the value */
		if (pkcs11_getattr_alloc(token, newkey, CKA_VALUE, out, outlen)) {
			PKCS11err(PKCS11_F_PKCS11_EC_KEY_COMPUTE_KEY,
				pkcs11_map_err(CKR_ATTRIBUTE_VALUE_INVALID));
			CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey));
			return -1;
		}
	}
	if (tmpnewkey) /* For future use (not used by pkcs11_ec_ckey) */
		*tmpnewkey = newkey;
	else /* Destroy the temporary key */
		CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, newkey));

	return 0;
}
Ejemplo n.º 24
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;
}