goto loser;
checkkey.data = KEYDB_FAKE_PW_CHECK_STRING; checkkey.size = KEYDB_FAKE_PW_CHECK_LEN; ret = (* handle->db->get)(handle->db, &checkkey, &checkdata, 0 ); if (ret) { goto loser; }  rv = seckey_CheckKeyDB1Password(handle,pwitem); if (rv == SECSuccess) {  SECKEY_UpdateKeyDBPass2(handle,pwitem); } return rv;
SECKEY_CheckKeyDBPassword(SECKEYKeyDBHandle *handle, SECItem *pwitem){    DBT checkkey;    SECAlgorithmID *algid = NULL;    SECStatus rv = SECFailure;    SECKEYDBKey *dbkey = NULL;    SECItem *key = NULL;    SECItem *dest = NULL;    SECOidTag algorithm;    SECItem oid;    SECItem encstring;    PRBool update = PR_FALSE;        if (handle == NULL) {	goto loser;    }    checkkey.data = KEYDB_PW_CHECK_STRING;    checkkey.size = KEYDB_PW_CHECK_LEN;        dbkey = get_dbkey(handle, &checkkey);        if ( dbkey == NULL ) {	goto loser;    }    /* build the oid item */    oid.len = dbkey->derPK.data[0];    oid.data = &dbkey->derPK.data[1];        /* make sure entry is the correct length     * since we are probably using a block cipher, the block will be     * padded, so we may get a bit more than the exact size we need.     */    if ( dbkey->derPK.len < (KEYDB_PW_CHECK_LEN + 1 + oid.len ) ) {	goto loser;    }    /* find the algorithm tag */    algorithm = SECOID_FindOIDTag(&oid);    /* make a secitem of the encrypted check string */    encstring.len = dbkey->derPK.len - ( oid.len + 1 );    encstring.data = &dbkey->derPK.data[oid.len+1];        switch(algorithm)    {	case SEC_OID_RC4:	    key = seckey_create_rc4_key(pwitem, &dbkey->salt);	    if(key != NULL) {		dest = seckey_rc4_cipher(key, &encstring, PR_FALSE);		SECITEM_FreeItem(key, PR_TRUE);	    }	    break;	default:	    algid = SEC_PKCS5CreateAlgorithmID(algorithm, 					       &dbkey->salt, 1);	    if(algid != NULL) {                /* Decrypt - this function implements a workaround for                 * a previous coding error.  It will decrypt values using                 * DES rather than 3DES, if the initial try at 3DES                 * decryption fails.  In this case, the update flag is                 * set to TRUE.  This indication is used later to force                 * an update of the database to "real" 3DES encryption.                 */		dest = SEC_PKCS5CipherData(algid, pwitem, 					   &encstring, PR_FALSE, &update);		SECOID_DestroyAlgorithmID(algid, PR_TRUE);	    }		    break;    }    if(dest == NULL) {	goto loser;    }    if ((dest->len == KEYDB_PW_CHECK_LEN) &&	(PORT_Memcmp(dest->data, 		     KEYDB_PW_CHECK_STRING, KEYDB_PW_CHECK_LEN) == 0)) {	rv = SECSuccess;	/* we succeeded */	if ( algorithm == SEC_OID_RC4 ) {	    /* partially updated database */	    SECKEY_UpdateKeyDBPass2(handle, pwitem);	}        /* Force an update of the password to remove the incorrect DES         * encryption (see the note above)         */	if (update && 	     (algorithm == SEC_OID_PKCS12_PBE_WITH_SHA1_AND_TRIPLE_DES_CBC)) {	    /* data base was encoded with DES not triple des, fix it */	    SECKEY_UpdateKeyDBPass2(handle,pwitem);	}    }			loser:    sec_destroy_dbkey(dbkey);    if(dest != NULL) {    	SECITEM_ZfreeItem(dest, PR_TRUE);    }    return(rv);}