/* nsISimpleEnumerator enumerateKeys (); */ NS_IMETHODIMP KeyService::EnumerateKeys(nsISimpleEnumerator **_retval) { SECKEYPrivateKeyList *list; SECKEYPrivateKeyListNode *node; nsCOMArray<nsIKeyPair> keys; // Retrieve all the private keys list = PK11_ListPrivKeysInSlot(mSlot, NULL, NULL); if (!list) return NS_NewArrayEnumerator(_retval, keys); // Walk the list for (node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node,list); node = PRIVKEY_LIST_NEXT(node)) { KeyPair *key = new KeyPair(node->key); keys.AppendObject(key); } SECKEY_DestroyPrivateKeyList(list); return NS_NewArrayEnumerator(_retval, keys); }
struct private_key_stuff *lsw_nss_foreach_private_key_stuff(secret_eval func, void *uservoid, lsw_nss_buf_t err) { /* * So test for error with "if (err[0]) ..." works. */ err[0] = '\0'; PK11SlotInfo *slot = lsw_nss_get_authenticated_slot(err); if (slot == NULL) { return NULL; } SECKEYPrivateKeyList *list = PK11_ListPrivateKeysInSlot(slot); if (list == NULL) { snprintf(err, sizeof(lsw_nss_buf_t), "no list"); PK11_FreeSlot(slot); return NULL; } int line = 1; struct private_key_stuff *result = NULL; SECKEYPrivateKeyListNode *node; for (node = PRIVKEY_LIST_HEAD(list); !PRIVKEY_LIST_END(node, list); node = PRIVKEY_LIST_NEXT(node)) { if (SECKEY_GetPrivateKeyType(node->key) != rsaKey) { /* only rsa for now */ continue; } struct private_key_stuff pks = { .kind = PPK_RSA, .on_heap = TRUE, }; { SECItem *nss_ckaid = PK11_GetLowLevelKeyIDForPrivateKey(node->key); if (nss_ckaid == NULL) { // fprintf(stderr, "ckaid not found\n"); continue; } const char *err = form_ckaid_nss(nss_ckaid, &pks.u.RSA_private_key.pub.ckaid); SECITEM_FreeItem(nss_ckaid, PR_TRUE); if (err) { // fprintf(stderr, "ckaid not found\n"); continue; } } { SECKEYPublicKey *pubkey = SECKEY_ConvertToPublicKey(node->key); if (pubkey != NULL) { fill_RSA_public_key(&pks.u.RSA_private_key.pub, pubkey); SECKEY_DestroyPublicKey(pubkey); } } /* * Only count private keys that get processed. */ pks.line = line++; int ret = func(NULL, &pks, uservoid); if (ret == 0) { /* * save/return the result. * * XXX: Potential Memory leak. * * lsw_foreach_secret() + lsw_get_pks() * returns an object that must not be freed * BUT lsw_nss_foreach_private_key_stuff() * returns an object that must be freed. * * For moment ignore this - as only caller is * showhostkey.c which quickly exits. */ result = clone_thing(pks, "pks"); break; } freeanyckaid(&pks.u.RSA_private_key.pub.ckaid); freeanychunk(pks.u.RSA_private_key.pub.e); freeanychunk(pks.u.RSA_private_key.pub.n); if (ret < 0) { break; } } SECKEY_DestroyPrivateKeyList(list); PK11_FreeSlot(slot); return result; }
/* * objectType is bitwise-OR of all the object types you want to traverse. */ static PRStatus traverseTokenObjects (JNIEnv *env, PK11SlotInfo *slot, TokenObjectTraversalCallback cb, int objectTypes, void *data) { PRStatus status = PR_FAILURE; JSSTraversalStatus travstat = INIT_TRAVSTAT; SECKEYPrivateKeyList* privkList = NULL; SECKEYPublicKeyList* pubkList = NULL; PK11SymKey *symKey = NULL; CERTCertList *certList = NULL; SECStatus secstat; /* * Get all private keys */ if( objectTypes & PRIVKEY ) { SECKEYPrivateKeyListNode *node = NULL; privkList = PK11_ListPrivKeysInSlot(slot, NULL /*nickname*/, NULL /*wincx*/); if( privkList != NULL ) { for( node = PRIVKEY_LIST_HEAD(privkList); ! PRIVKEY_LIST_END(node, privkList); node = PRIVKEY_LIST_NEXT(node) ) { travstat = cb(env, slot, PRIVKEY, (void*) node->key, data); if( travstat.status == PR_FAILURE ) { goto finish; } if( travstat.deleteIt ) { /* Setting "force" to PR_FALSE means that if there is a * matching cert, the key won't be deleted. * If the KeyStore API is being followed, the cert * should have the same nickname as the key. So * both will get deleted when we scan for matching * certs later. */ PK11_DeleteTokenPrivateKey(node->key, PR_FALSE /*force*/); node->key = NULL; PR_REMOVE_LINK(&node->links); /* we don't free node because it is allocated from * the list's arena and will get freed when the list * is freed. */ } if( travstat.stopIterating ) { goto stop_early; } } } } /* * Get all symmetric keys */ if(objectTypes & SYMKEY) { /* this function returns a chained list of symmetric keys */ symKey = PK11_ListFixedKeysInSlot(slot, NULL /*nickname*/, NULL/*wincx*/); while( symKey != NULL ) { PK11SymKey *deadKey; travstat = cb(env, slot, SYMKEY, (void*) symKey, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* this just deletes the PKCS #11 object. The data structure * is NOT deleted. */ PK11_DeleteTokenSymKey(symKey); } if( travstat.stopIterating ) { goto stop_early; } deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } } /* * get all public keys */ if( objectTypes & PUBKEY ) { SECKEYPublicKeyListNode *node = NULL; pubkList = PK11_ListPublicKeysInSlot(slot, NULL /*nickname*/); if( pubkList != NULL ) { for( node = PUBKEY_LIST_HEAD(pubkList); ! PUBKEY_LIST_END(node, pubkList); node = PUBKEY_LIST_NEXT(node) ) { if( node->key == NULL ) { /* workaround NSS bug 130699: PK11_ListPublicKeysInSlot * returns NULL if slot contains token symmetric key */ continue; } travstat = cb(env, slot, PUBKEY, (void*) node->key, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* XXX!!! * Workaround for 125408: PK11_DeleteTokenPublic key asserts * Don't delete the public key. * PK11_DeleteTokenPublicKey(node->key); * node->key = NULL; * PR_REMOVE_LINK(&node->links); */ /* node is allocated from the list's arena, it will get * freed with the list */ } if( travstat.stopIterating ) { goto stop_early; } } /* * XXX!!! * Destroy the list before we move on. Why bother, since we'll * do it anyway in the finish block? Because of bug 125408. * If we delete the cert and private key while traversing certs, * we'll delete the public key too, and then we'll crash when * we free the same public key while destroying the list. */ SECKEY_DestroyPublicKeyList(pubkList); pubkList = NULL; } } /* * Get all certs */ if( objectTypes & CERT ) { CERTCertListNode *node = NULL; certList = PK11_ListCertsInSlot(slot); if( certList == NULL ) { JSS_throwMsgPrErr(env, TOKEN_EXCEPTION, "Failed to list certificates on token"); goto finish; } for( node = CERT_LIST_HEAD(certList); ! CERT_LIST_END(node, certList); node = CERT_LIST_NEXT(node) ) { travstat = cb(env, slot, CERT, (void*) node->cert, data); if( travstat.status != PR_SUCCESS ) { goto finish; } if( travstat.deleteIt ) { /* * Since, in a KeyStore, certs and private keys go together, * remove the private key too, if there is one. * * The hack here is that PK11_DeleteTokenCertAndKey will * not delete the cert if there is no matching private key. * We want to the cert to be deleted even if the key isn't * there. So we only call that function if we're sure the * key is there. Otherwise we delete the cert directly. */ SECKEYPrivateKey *privKey = PK11_FindKeyByAnyCert(node->cert, NULL /*wincx*/); PRBool keyPresent = (privKey != NULL); SECKEY_DestroyPrivateKey(privKey); if( keyPresent ) { PK11_DeleteTokenCertAndKey(node->cert, NULL /*wincx*/); } else { SEC_DeletePermCertificate(node->cert); } PR_REMOVE_LINK(&node->links); /* node is allocated from the list's arena, it will get freed * with the list */ } if( travstat.stopIterating ) { goto stop_early; } } } stop_early: status = PR_SUCCESS; finish: if( privkList != NULL ) { SECKEY_DestroyPrivateKeyList(privkList); } if( pubkList != NULL ) { SECKEY_DestroyPublicKeyList(pubkList); } while( symKey != NULL ) { PK11SymKey *deadKey; deadKey = symKey; symKey = PK11_GetNextSymKey(symKey); PK11_FreeSymKey(deadKey); } if( certList != NULL ) { CERT_DestroyCertList(certList); } return status; }