Skip to content

Commit

Permalink
Gracefully handle missing dynlock callbacks
Browse files Browse the repository at this point in the history
  • Loading branch information
mtrojnar committed Jan 15, 2016
1 parent 39c15d8 commit c219965
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 18 deletions.
12 changes: 12 additions & 0 deletions src/libp11-int.h
Expand Up @@ -146,6 +146,18 @@ typedef struct pkcs11_cert_private {
#define PKCS11_DUP(s) \
pkcs11_strdup((char *) s, sizeof(s))

int pkcs11_get_new_dynlockid();
void pkcs11_destroy_dynlockid(int);

#define pkcs11_w_lock(type) \
if(type) CRYPTO_lock(CRYPTO_LOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
#define pkcs11_w_unlock(type) \
if(type) CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_WRITE,type,__FILE__,__LINE__)
#define pkcs11_r_lock(type) \
if(type) CRYPTO_lock(CRYPTO_LOCK|CRYPTO_READ,type,__FILE__,__LINE__)
#define pkcs11_r_unlock(type) \
if(type) CRYPTO_lock(CRYPTO_UNLOCK|CRYPTO_READ,type,__FILE__,__LINE__)

extern int pkcs11_enumerate_slots(PKCS11_CTX *, PKCS11_SLOT **, unsigned int *);
extern void pkcs11_release_slot(PKCS11_CTX *, PKCS11_SLOT *slot);

Expand Down
4 changes: 2 additions & 2 deletions src/p11_key.c
Expand Up @@ -331,9 +331,9 @@ static int pkcs11_enumerate_keys(PKCS11_TOKEN * token, unsigned int type,
int rv;

if (keys->num < 0) { /* No cache was built for the specified type */
CRYPTO_w_lock(cpriv->lockid);
pkcs11_w_lock(cpriv->lockid);
rv = pkcs11_find_keys(token, type);
CRYPTO_w_unlock(cpriv->lockid);
pkcs11_w_unlock(cpriv->lockid);
if (rv < 0) {
pkcs11_destroy_keys(token, type);
return -1;
Expand Down
5 changes: 2 additions & 3 deletions src/p11_load.c
Expand Up @@ -43,8 +43,7 @@ PKCS11_CTX *PKCS11_CTX_new(void)
memset(ctx, 0, sizeof(PKCS11_CTX));
ctx->_private = priv;
priv->forkid = _P11_get_forkid();
priv->lockid = CRYPTO_get_new_dynlockid();
ERR_clear_error(); /* Dynamic locks are optional */
priv->lockid = pkcs11_get_new_dynlockid();

return ctx;
fail:
Expand Down Expand Up @@ -168,7 +167,7 @@ void PKCS11_CTX_free(PKCS11_CTX * ctx)
if (priv->init_args) {
OPENSSL_free(priv->init_args);
}
CRYPTO_destroy_dynlockid(priv->lockid);
pkcs11_destroy_dynlockid(priv->lockid);
OPENSSL_free(ctx->manufacturer);
OPENSSL_free(ctx->description);
OPENSSL_free(ctx->_private);
Expand Down
31 changes: 27 additions & 4 deletions src/p11_misc.c
Expand Up @@ -129,9 +129,9 @@ int check_fork(PKCS11_CTX *ctx)
PKCS11_CTX_private *priv = PRIVCTX(ctx);
int rv;

CRYPTO_w_lock(priv->lockid);
pkcs11_w_lock(priv->lockid);
rv = check_fork_int(ctx);
CRYPTO_w_unlock(priv->lockid);
pkcs11_w_unlock(priv->lockid);
return rv;
}

Expand All @@ -144,9 +144,9 @@ int check_slot_fork(PKCS11_SLOT *slot)
PKCS11_CTX_private *priv = PRIVCTX(ctx);
int rv;

CRYPTO_w_lock(priv->lockid);
pkcs11_w_lock(priv->lockid);
rv = check_slot_fork_int(slot);
CRYPTO_w_unlock(priv->lockid);
pkcs11_w_unlock(priv->lockid);
return rv;
}

Expand All @@ -165,4 +165,27 @@ int check_key_fork(PKCS11_KEY *key)
return rv;
}

/*
* CRYPTO dynlock wrappers: 0 is an invalid dynamic lock ID
*/
int pkcs11_get_new_dynlockid()
{
int i;

if (CRYPTO_get_dynlock_create_callback() == NULL ||
CRYPTO_get_dynlock_lock_callback() == NULL ||
CRYPTO_get_dynlock_destroy_callback() == NULL)
return 0; /* Dynamic callbacks not set */
i = CRYPTO_get_new_dynlockid();
if (i == 0)
ERR_clear_error(); /* Dynamic locks are optional -> ignore */
return i;
}

void pkcs11_destroy_dynlockid(int i)
{
if(i)
CRYPTO_destroy_dynlockid(i);
}

/* vim: set noexpandtab: */
12 changes: 6 additions & 6 deletions src/p11_ops.c
Expand Up @@ -51,11 +51,11 @@ PKCS11_ecdsa_sign(const unsigned char *m, unsigned int m_len,
memset(&mechanism, 0, sizeof(mechanism));
mechanism.mechanism = CKM_ECDSA;

CRYPTO_w_lock(PRIVSLOT(slot)->lockid);
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));
CRYPTO_w_unlock(PRIVSLOT(slot)->lockid);
pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

if (rv) {
PKCS11err(PKCS11_F_PKCS11_EC_KEY_SIGN, pkcs11_map_err(rv));
Expand Down Expand Up @@ -173,14 +173,14 @@ PKCS11_private_encrypt(int flen, const unsigned char *from, unsigned char *to,

session = PRIVSLOT(slot)->session;

CRYPTO_w_lock(PRIVSLOT(slot)->lockid);
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));
CRYPTO_w_unlock(PRIVSLOT(slot)->lockid);
pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

if (rv) {
PKCS11err(PKCS11_F_PKCS11_RSA_SIGN, pkcs11_map_err(rv));
Expand Down Expand Up @@ -224,12 +224,12 @@ PKCS11_private_decrypt(int flen, const unsigned char *from, unsigned char *to,
mechanism.mechanism = CKM_RSA_PKCS;


CRYPTO_w_lock(PRIVSLOT(slot)->lockid);
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));
CRYPTO_w_unlock(PRIVSLOT(slot)->lockid);
pkcs11_w_unlock(PRIVSLOT(slot)->lockid);

if (rv) {
PKCS11err(PKCS11_F_PKCS11_RSA_DECRYPT, pkcs11_map_err(rv));
Expand Down
5 changes: 2 additions & 3 deletions src/p11_slot.c
Expand Up @@ -447,8 +447,7 @@ static int pkcs11_init_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot, CK_SLOT_ID id)
priv->prev_rw = 0;
priv->prev_pin = NULL;
priv->prev_so = 0;
priv->lockid = CRYPTO_get_new_dynlockid();
ERR_clear_error(); /* Dynamic locks are optional */
priv->lockid = pkcs11_get_new_dynlockid();

slot->description = PKCS11_DUP(info.slotDescription);
slot->manufacturer = PKCS11_DUP(info.manufacturerID);
Expand Down Expand Up @@ -479,7 +478,7 @@ void pkcs11_release_slot(PKCS11_CTX * ctx, PKCS11_SLOT * slot)
OPENSSL_cleanse(priv->prev_pin, strlen(priv->prev_pin));
OPENSSL_free(priv->prev_pin);
}
CRYPTO_destroy_dynlockid(priv->lockid);
pkcs11_destroy_dynlockid(priv->lockid);
CRYPTOKI_call(ctx, C_CloseAllSessions(priv->id));
}
OPENSSL_free(slot->_private);
Expand Down

0 comments on commit c219965

Please sign in to comment.