Ejemplo n.º 1
0
/* 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);
}
Ejemplo n.º 2
0
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;
}