/* * 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; }
/* * 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; }
/* * 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; }
/* * 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; }
/* * 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); }
/* * 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); }
/* * 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); }
/* * 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; }
static int tap11_store_cert( const char *libp11, const char *pin, const char *certid, const char *certfile) { int rc; unsigned int nslots; PKCS11_CTX *p11ctx; PKCS11_SLOT *slots, *slot; PKCS11_CERT *cert; X509 *x509; BIO *bio; p11ctx = PKCS11_CTX_new(); /* load pkcs #11 module */ rc = PKCS11_CTX_load(p11ctx,libp11); if (rc) { fprintf(stderr,"PKCS11_CTX_load\n"); return -1; } /* get information on all slots */ rc = PKCS11_enumerate_slots(p11ctx, &slots, &nslots); if (rc < 0) { fprintf(stderr,"PKCS11_enumerate_slots\n"); return -1; } /* get first slot with a token */ slot = PKCS11_find_token(p11ctx, slots, nslots); if (!slot || !slot->token) { fprintf(stderr,"PKCS11_find_token\n"); return -1; } fprintf(stderr,"Slot manufacturer......: %s\n", slot->manufacturer); fprintf(stderr,"Slot description.......: %s\n", slot->description); fprintf(stderr,"Slot token label.......: %s\n", slot->token->label); fprintf(stderr,"Slot token manufacturer: %s\n", slot->token->manufacturer); fprintf(stderr,"Slot token model.......: %s\n", slot->token->model); fprintf(stderr,"Slot token serialnr....: %s\n", slot->token->serialnr); rc = PKCS11_open_session(slot, 1); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_open_session %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } rc = PKCS11_login(slot, 0, pin); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_login %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } /* load cert */ if ((bio = BIO_new(BIO_s_file())) == NULL) { fprintf(stderr,"BIO_new\n"); return -1; } if (BIO_read_filename(bio,certfile) <= 0) { fprintf(stderr,"BIO_read_filename\n"); return -1; } x509 = PEM_read_bio_X509_AUX(bio,NULL, NULL, NULL); if (x509 == NULL) { fprintf(stderr,"PKCS11_enumerate_certs\n"); return -1; } /* store cert */ rc = PKCS11_store_certificate(slot->token,x509, (char*)certid,(unsigned char*)certid,strlen(certid),&cert); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_store_certificate %s rc:%d\n", ERR_reason_error_string(ERR_get_error()),rc); return -1; } X509_free(x509); BIO_free(bio); PKCS11_logout(slot); PKCS11_release_all_slots(p11ctx, slots, nslots); PKCS11_CTX_unload(p11ctx); PKCS11_CTX_free(p11ctx); fprintf(stderr,"\n\nstore cert succeed\n"); return 0; }
static int tap11_change_pin( const char *p11lib, int is_so, const char *pin, const char *newpin) { int rc = 0; unsigned int nslots; PKCS11_CTX *p11ctx; PKCS11_SLOT *slots, *slot; p11ctx = PKCS11_CTX_new(); /* load pkcs #11 module */ rc = PKCS11_CTX_load(p11ctx,p11lib); if (rc) { fprintf(stderr,"PKCS11_CTX_load\n"); return -1; } /* get information on all slots */ rc = PKCS11_enumerate_slots(p11ctx, &slots, &nslots); if (rc < 0) { fprintf(stderr,"PKCS11_enumerate_slots\n"); return -1; } /* get first slot with a token */ slot = PKCS11_find_token(p11ctx, slots, nslots); if (!slot || !slot->token) { fprintf(stderr,"PKCS11_find_token\n"); return -1; } fprintf(stderr,"Slot manufacturer......: %s\n", slot->manufacturer); fprintf(stderr,"Slot description.......: %s\n", slot->description); fprintf(stderr,"Slot token label.......: %s\n", slot->token->label); fprintf(stderr,"Slot token manufacturer: %s\n", slot->token->manufacturer); fprintf(stderr,"Slot token model.......: %s\n", slot->token->model); fprintf(stderr,"Slot token serialnr....: %s\n", slot->token->serialnr); /* rw mode */ rc = PKCS11_open_session(slot, 1); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_open_session %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } rc = PKCS11_login(slot, is_so, pin); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_init_login %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } rc = PKCS11_change_pin(slot,pin,newpin); if (rc != 0) { ERR_load_PKCS11_strings(); fprintf(stderr,"PKCS11_change_pin %s\n", ERR_reason_error_string(ERR_get_error())); return -1; } PKCS11_logout(slot); PKCS11_release_all_slots(p11ctx, slots, nslots); PKCS11_CTX_unload(p11ctx); PKCS11_CTX_free(p11ctx); fprintf(stderr,"\n\npin change succeed\n"); return 0; }