コード例 #1
0
ファイル: pk11auth.c プロジェクト: Akin-Net/mozilla-central
/*
 * we can initialize the password if 1) The toke is not inited 
 * (need login == true and see need UserInit) or 2) the token has
 * a NULL password. (slot->needLogin = false & need user Init = false).
 */
PRBool PK11_NeedPWInitForSlot(PK11SlotInfo *slot)
{
    if (slot->needLogin && PK11_NeedUserInit(slot)) {
	return PR_TRUE;
    }
    if (!slot->needLogin && !PK11_NeedUserInit(slot)) {
	return PR_TRUE;
    }
    return PR_FALSE;
}
コード例 #2
0
ファイル: pk11.c プロジェクト: emaldona/nss
/************************************************************************
 *
 * I n i t P W
 */
Error
InitPW(void)
{
    PK11SlotInfo *slot;
    Error ret = UNSPECIFIED_ERR;

    slot = PK11_GetInternalKeySlot();
    if (!slot) {
        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], "internal");
        return NO_SUCH_TOKEN_ERR;
    }

    /* Set the initial password to empty */
    if (PK11_NeedUserInit(slot)) {
        if (PK11_InitPin(slot, NULL, "") != SECSuccess) {
            PR_fprintf(PR_STDERR, errStrings[INITPW_FAILED_ERR]);
            ret = INITPW_FAILED_ERR;
            goto loser;
        }
    }

    ret = SUCCESS;

loser:
    PK11_FreeSlot(slot);

    return ret;
}
コード例 #3
0
ファイル: nsPK11TokenDB.cpp プロジェクト: luke-chang/gecko-1
NS_IMETHODIMP
nsPK11Token::GetNeedsUserInit(bool* aNeedsUserInit)
{
  NS_ENSURE_ARG_POINTER(aNeedsUserInit);
  *aNeedsUserInit = PK11_NeedUserInit(mSlot.get());
  return NS_OK;
}
コード例 #4
0
ファイル: KeyService.cpp プロジェクト: king122909/Firebug
nsresult
KeyService::Init()
{
    // Bring up psm
    nsCOMPtr<nsISupports> nss = do_GetService("@mozilla.org/psm;1");
    SECStatus sv;
    mSlot = PK11_GetInternalKeySlot();
    
    if (PK11_NeedUserInit(mSlot)) {
        NS_ConvertUTF8toUTF16 tokenName(PK11_GetTokenName(mSlot));
        
        nsCOMPtr<nsITokenPasswordDialogs> dialogs;
        dialogs = do_GetService(NS_TOKENPASSWORDSDIALOG_CONTRACTID);
        if (!dialogs)
            return NS_ERROR_FAILURE;
        
        PRBool cancelled;
        nsresult rv = dialogs->SetPassword(nsnull, tokenName.get(), &cancelled);
        NS_ENSURE_SUCCESS(rv, rv);
        
        if (cancelled)
            return NS_ERROR_FAILURE;
    }
    
    if (PK11_NeedLogin(mSlot)) {
        sv = PK11_Authenticate(mSlot, PR_TRUE, NULL);
        if (sv != SECSuccess)
            return NS_ERROR_FAILURE;
    }
    
    return NS_OK;
}
コード例 #5
0
ファイル: crypto.c プロジェクト: esproul/xmlsec
/**
 * xmlSecNssGetInternalKeySlot:
 *
 * Gets internal NSS key slot.
 *
 * Returns: internal key slot and initializes it if needed.
 */
PK11SlotInfo *
xmlSecNssGetInternalKeySlot()
{
    PK11SlotInfo *slot = NULL;
    SECStatus rv;

    slot = PK11_GetInternalKeySlot();
    if (slot == NULL) {
        xmlSecNssError("PK11_GetInternalKeySlot", NULL);
        return NULL;
    }

    if (PK11_NeedUserInit(slot)) {
        rv = PK11_InitPin(slot, NULL, NULL);
        if (rv != SECSuccess) {
            xmlSecNssError("PK11_InitPin", NULL);
            return NULL;
        }
    }

    if(PK11_IsLoggedIn(slot, NULL) != PR_TRUE) {
        rv = PK11_Authenticate(slot, PR_TRUE, NULL);
        if (rv != SECSuccess) {
            xmlSecNssError2("PK11_Authenticate", NULL,
                            "token=%s", xmlSecErrorsSafeString(PK11_GetTokenName(slot)));
            return NULL;
        }
    }

    return(slot);
}
コード例 #6
0
ファイル: nsPK11TokenDB.cpp プロジェクト: spatenotte/gecko
NS_IMETHODIMP nsPK11Token::GetNeedsUserInit(bool *aNeedsUserInit)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  *aNeedsUserInit = PK11_NeedUserInit(mSlot);
  return NS_OK;
}
コード例 #7
0
ファイル: nsPK11TokenDB.cpp プロジェクト: luke-chang/gecko-1
NS_IMETHODIMP
nsPK11Token::GetHasPassword(bool* hasPassword)
{
  NS_ENSURE_ARG_POINTER(hasPassword);
  // PK11_NeedLogin returns true if the token is currently configured to require
  // the user to log in (whether or not the user is actually logged in makes no
  // difference).
  *hasPassword = PK11_NeedLogin(mSlot.get()) && !PK11_NeedUserInit(mSlot.get());
  return NS_OK;
}
コード例 #8
0
ファイル: nss.c プロジェクト: tcdog001/apv5sdk-v15
static SECStatus nss_Init_Tokens(struct connectdata * conn)
{
  PK11SlotList *slotList;
  PK11SlotListElement *listEntry;
  SECStatus ret, status = SECSuccess;
  pphrase_arg_t *parg = NULL;

  parg = (pphrase_arg_t *) malloc(sizeof(*parg));
  parg->retryCount = 0;
  parg->data = conn->data;

  PK11_SetPasswordFunc(nss_get_password);

  slotList =
    PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);

  for(listEntry = PK11_GetFirstSafe(slotList);
      listEntry; listEntry = listEntry->next) {
    PK11SlotInfo *slot = listEntry->slot;

    if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
      if(slot == PK11_GetInternalKeySlot()) {
        failf(conn->data, "The NSS database has not been initialized.\n");
      }
      else {
        failf(conn->data, "The token %s has not been initialized.",
              PK11_GetTokenName(slot));
      }
      PK11_FreeSlot(slot);
      continue;
    }

    ret = PK11_Authenticate(slot, PR_TRUE, parg);
    if(SECSuccess != ret) {
      if (PR_GetError() == SEC_ERROR_BAD_PASSWORD)
        infof(conn->data, "The password for token '%s' is incorrect\n",
              PK11_GetTokenName(slot));
      status = SECFailure;
      break;
    }
    parg->retryCount = 0; /* reset counter to 0 for the next token */
    PK11_FreeSlot(slot);
  }

  free(parg);

  return status;
}
コード例 #9
0
ファイル: nsPK11TokenDB.cpp プロジェクト: luke-chang/gecko-1
NS_IMETHODIMP
nsPK11Token::InitPassword(const nsACString& initialPassword)
{
  const nsCString& passwordCStr = PromiseFlatCString(initialPassword);
  // PSM initializes the sqlite-backed softoken with an empty password. The
  // implementation considers this not to be a password (GetHasPassword returns
  // false), but we can't actually call PK11_InitPin again. Instead, we call
  // PK11_ChangePW with the empty password.
  bool hasPassword;
  nsresult rv = GetHasPassword(&hasPassword);
  if (NS_FAILED(rv)) {
    return rv;
  }
  if (!PK11_NeedUserInit(mSlot.get()) && !hasPassword) {
    return MapSECStatus(PK11_ChangePW(mSlot.get(), "", passwordCStr.get()));
  }
  return MapSECStatus(PK11_InitPin(mSlot.get(), "", passwordCStr.get()));
}
コード例 #10
0
SECStatus
InitPKCS11(void)
{
    PK11SlotInfo *keySlot;

    PK11_SetPasswordFunc(SECU_GetModulePassword);

    keySlot    = PK11_GetInternalKeySlot();
    
    if (PK11_NeedUserInit(keySlot) && PK11_NeedLogin(keySlot)) {
        if (SECU_ChangePW(keySlot, NULL, NULL) != SECSuccess) {
	    printf ("Initializing the PINs failed.\n");
	    return SECFailure;
	}
    }

    PK11_FreeSlot(keySlot);
    return SECSuccess;
}
コード例 #11
0
ファイル: nss.c プロジェクト: heavilessrose/my-sync
static SECStatus nss_Init_Tokens(struct connectdata * conn)
{
  PK11SlotList *slotList;
  PK11SlotListElement *listEntry;
  SECStatus ret, status = SECSuccess;

  PK11_SetPasswordFunc(nss_get_password);

  slotList =
    PK11_GetAllTokens(CKM_INVALID_MECHANISM, PR_FALSE, PR_TRUE, NULL);

  for(listEntry = PK11_GetFirstSafe(slotList);
      listEntry; listEntry = listEntry->next) {
    PK11SlotInfo *slot = listEntry->slot;

    if(PK11_NeedLogin(slot) && PK11_NeedUserInit(slot)) {
      if(slot == PK11_GetInternalKeySlot()) {
        failf(conn->data, "The NSS database has not been initialized");
      }
      else {
        failf(conn->data, "The token %s has not been initialized",
              PK11_GetTokenName(slot));
      }
      PK11_FreeSlot(slot);
      continue;
    }

    ret = PK11_Authenticate(slot, PR_TRUE,
                            conn->data->set.str[STRING_KEY_PASSWD]);
    if(SECSuccess != ret) {
      if(PR_GetError() == SEC_ERROR_BAD_PASSWORD)
        infof(conn->data, "The password for token '%s' is incorrect\n",
              PK11_GetTokenName(slot));
      status = SECFailure;
      break;
    }
    PK11_FreeSlot(slot);
  }

  return status;
}
コード例 #12
0
ファイル: nsPKCS11Slot.cpp プロジェクト: AtulKumar2/gecko-dev
NS_IMETHODIMP
nsPKCS11Slot::GetStatus(uint32_t *_retval)
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  if (PK11_IsDisabled(mSlot))
    *_retval = SLOT_DISABLED;
  else if (!PK11_IsPresent(mSlot))
    *_retval = SLOT_NOT_PRESENT;
  else if (PK11_NeedLogin(mSlot) && PK11_NeedUserInit(mSlot))
    *_retval = SLOT_UNINITIALIZED;
  else if (PK11_NeedLogin(mSlot) && !PK11_IsLoggedIn(mSlot, nullptr))
    *_retval = SLOT_NOT_LOGGED_IN;
  else if (PK11_NeedLogin(mSlot))
    *_retval = SLOT_LOGGED_IN;
  else
    *_retval = SLOT_READY;
  return NS_OK;
}
コード例 #13
0
nsresult
LocalCertService::LoginToKeySlot()
{
  nsresult rv;

  // Get access to key slot
  UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
  if (!slot) {
    return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  }

  // If no user password yet, set it an empty one
  if (PK11_NeedUserInit(slot.get())) {
    rv = MapSECStatus(PK11_InitPin(slot.get(), "", ""));
    if (NS_FAILED(rv)) {
      return rv;
    }
  }

  // If user has a password set, prompt to login
  if (PK11_NeedLogin(slot.get()) && !PK11_IsLoggedIn(slot.get(), nullptr)) {
    // Switching to XPCOM to get the UI prompt that PSM owns
    nsCOMPtr<nsIPK11TokenDB> tokenDB =
      do_GetService(NS_PK11TOKENDB_CONTRACTID);
    if (!tokenDB) {
      return NS_ERROR_FAILURE;
    }
    nsCOMPtr<nsIPK11Token> keyToken;
    tokenDB->GetInternalKeyToken(getter_AddRefs(keyToken));
    if (!keyToken) {
      return NS_ERROR_FAILURE;
    }
    // Prompt the user to login
    return keyToken->Login(false /* force */);
  }

  return NS_OK;
}
コード例 #14
0
nsresult
nsNSSCertificate::MarkForPermDeletion()
{
  nsNSSShutDownPreventionLock locker;
  if (isAlreadyShutDown())
    return NS_ERROR_NOT_AVAILABLE;

  // make sure user is logged in to the token
  nsCOMPtr<nsIInterfaceRequestor> ctx = new PipUIContext();

  if (PK11_NeedLogin(mCert->slot)
      && !PK11_NeedUserInit(mCert->slot)
      && !PK11_IsInternal(mCert->slot))
  {
    if (SECSuccess != PK11_Authenticate(mCert->slot, true, ctx))
    {
      return NS_ERROR_FAILURE;
    }
  }

  mPermDelete = true;
  return NS_OK;
}
コード例 #15
0
NS_IMETHODIMP
LocalCertService::GetLoginPromptRequired(bool* aRequired)
{
  nsresult rv;

  // Get access to key slot
  UniquePK11SlotInfo slot(PK11_GetInternalKeySlot());
  if (!slot) {
    return mozilla::psm::GetXPCOMFromNSSError(PR_GetError());
  }

  // If no user password yet, set it an empty one
  if (PK11_NeedUserInit(slot.get())) {
    rv = MapSECStatus(PK11_InitPin(slot.get(), "", ""));
    if (NS_FAILED(rv)) {
      return rv;
    }
  }

  *aRequired = PK11_NeedLogin(slot.get()) &&
               !PK11_IsLoggedIn(slot.get(), nullptr);
  return NS_OK;
}
コード例 #16
0
ファイル: nssgetpassword.cpp プロジェクト: ic-hep/emi3
  bool nss_change_password(PK11SlotInfo* slot, const char* oldpass, const char* newpass) {
    SECStatus rv;
    const char *oldpw = NULL, *newpw = NULL;
    oldpw = oldpass; newpw = newpass;

    if (PK11_NeedUserInit(slot)) {
      rv = PK11_InitPin(slot, (char*)NULL, (char*)newpw);
      return true;
    }

    if (PK11_CheckUserPassword(slot, (char*)oldpw) != SECSuccess) {
      std::cerr<<"Invalid password to nss db"<<std::endl;
      return false;
    }

    if (PK11_ChangePW(slot, (char*)oldpw, (char*)newpw) != SECSuccess) {
      std::cerr<<"Failed to change password of nss db"<<std::endl;
      return false;
    }

    std::cout<<"Succeeded to change password"<<std::endl;

    return true;
  }
コード例 #17
0
ファイル: TLSServer.cpp プロジェクト: leplatrem/gecko-dev
SECStatus
AddKeyFromFile(const char* basePath, const char* filename)
{
  const char* PRIVATE_KEY_HEADER = "-----BEGIN PRIVATE KEY-----";
  const char* PRIVATE_KEY_FOOTER = "-----END PRIVATE KEY-----";

  char buf[16384] = { 0 };
  SECStatus rv = ReadFileToBuffer(basePath, filename, buf);
  if (rv != SECSuccess) {
    return rv;
  }
  if (strncmp(buf, PRIVATE_KEY_HEADER, strlen(PRIVATE_KEY_HEADER)) != 0) {
    PR_fprintf(PR_STDERR, "invalid key - not importing\n");
    return SECFailure;
  }
  const char* bufPtr = buf + strlen(PRIVATE_KEY_HEADER);
  size_t bufLen = strlen(buf);
  char base64[16384] = { 0 };
  char* base64Ptr = base64;
  while (bufPtr < buf + bufLen) {
    if (strncmp(bufPtr, PRIVATE_KEY_FOOTER, strlen(PRIVATE_KEY_FOOTER)) == 0) {
      break;
    }
    if (*bufPtr != '\r' && *bufPtr != '\n') {
      *base64Ptr = *bufPtr;
      base64Ptr++;
    }
    bufPtr++;
  }

  unsigned int binLength;
  UniquePORTString bin(
    reinterpret_cast<char*>(ATOB_AsciiToData(base64, &binLength)));
  if (!bin || binLength == 0) {
    PrintPRError("ATOB_AsciiToData failed");
    return SECFailure;
  }
  ScopedSECItem secitem(::SECITEM_AllocItem(nullptr, nullptr, binLength));
  if (!secitem) {
    PrintPRError("SECITEM_AllocItem failed");
    return SECFailure;
  }
  PORT_Memcpy(secitem->data, bin.get(), binLength);
  ScopedPK11SlotInfo slot(PK11_GetInternalKeySlot());
  if (!slot) {
    PrintPRError("PK11_GetInternalKeySlot failed");
    return SECFailure;
  }
  if (PK11_NeedUserInit(slot)) {
    if (PK11_InitPin(slot, nullptr, nullptr) != SECSuccess) {
      PrintPRError("PK11_InitPin failed");
      return SECFailure;
    }
  }
  SECKEYPrivateKey* privateKey;
  if (PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, secitem, nullptr, nullptr,
                                               true, false, KU_ALL,
                                               &privateKey, nullptr)
        != SECSuccess) {
    PrintPRError("PK11_ImportDERPrivateKeyInfoAndReturnKey failed");
    return SECFailure;
  }
  SECKEY_DestroyPrivateKey(privateKey);
  return SECSuccess;
}
コード例 #18
0
ファイル: pk11auth.c プロジェクト: Akin-Net/mozilla-central
/*
 * authenticate to a slot. This loops until we can't recover, the user
 * gives up, or we succeed. If we're already logged in and this function
 * is called we will still prompt for a password, but we will probably
 * succeed no matter what the password was (depending on the implementation
 * of the PKCS 11 module.
 */
SECStatus
PK11_DoPassword(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
{
    SECStatus rv = SECFailure;
    char * password;
    PRBool attempt = PR_FALSE;

    if (PK11_NeedUserInit(slot)) {
	PORT_SetError(SEC_ERROR_IO);
	return SECFailure;
    }


    /*
     * Central server type applications which control access to multiple
     * slave applications to single crypto devices need to virtuallize the
     * login state. This is done by a callback out of PK11_IsLoggedIn and
     * here. If we are actually logged in, then we got here because the
     * higher level code told us that the particular client application may
     * still need to be logged in. If that is the case, we simply tell the
     * server code that it should now verify the clients password and tell us
     * the results.
     */
    if (PK11_IsLoggedIn(slot,NULL) && 
    			(PK11_Global.verifyPass != NULL)) {
	if (!PK11_Global.verifyPass(slot,wincx)) {
	    PORT_SetError(SEC_ERROR_BAD_PASSWORD);
	    return SECFailure;
	}
	return SECSuccess;
    }

    /* get the password. This can drop out of the while loop
     * for the following reasons:
     * 	(1) the user refused to enter a password. 
     *			(return error to caller)
     *	(2) the token user password is disabled [usually due to
     *	   too many failed authentication attempts].
     *			(return error to caller)
     *	(3) the password was successful.
     */
    while ((password = pk11_GetPassword(slot, attempt, wincx)) != NULL) {
	/* if the token has a protectedAuthPath, the application may have
         * already issued the C_Login as part of it's pk11_GetPassword call.
         * In this case the application will tell us what the results were in 
         * the password value (retry or the authentication was successful) so
	 * we can skip our own C_Login call (which would force the token to
	 * try to login again).
	 * 
	 * Applications that don't know about protectedAuthPath will return a 
	 * password, which we will ignore and trigger the token to 
	 * 'authenticate' itself anyway. Hopefully the blinking display on 
	 * the reader, or the flashing light under the thumbprint reader will 
	 * attract the user's attention */
	attempt = PR_TRUE;
	if (slot->protectedAuthPath) {
	    /* application tried to authenticate and failed. it wants to try
	     * again, continue looping */
	    if (strcmp(password, PK11_PW_RETRY) == 0) {
		rv = SECWouldBlock;
		PORT_Free(password);
		continue;
	    }
	    /* applicaton tried to authenticate and succeeded we're done */
	    if (strcmp(password, PK11_PW_AUTHENTICATED) == 0) {
		rv = SECSuccess;
		PORT_Free(password);
		break;
	    }
	}
	rv = pk11_CheckPassword(slot,password);
	PORT_Memset(password, 0, PORT_Strlen(password));
	PORT_Free(password);
	if (rv != SECWouldBlock) break;
    }
    if (rv == SECSuccess) {
	if (!PK11_IsFriendly(slot)) {
	    nssTrustDomain_UpdateCachedTokenCerts(slot->nssToken->trustDomain,
	                                      slot->nssToken);
	}
    } else if (!attempt) PORT_SetError(SEC_ERROR_BAD_PASSWORD);
    return rv;
}
コード例 #19
0
ファイル: pk11.c プロジェクト: emaldona/nss
/************************************************************************
 *
 * C h a n g e P W
 */
Error
ChangePW(char *tokenName, char *pwFile, char *newpwFile)
{
    char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL;
    PK11SlotInfo *slot;
    Error ret = UNSPECIFIED_ERR;
    PRBool matching;

    slot = PK11_FindSlotByName(tokenName);
    if (!slot) {
        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName);
        return NO_SUCH_TOKEN_ERR;
    }

    /* Get old password */
    if (!PK11_NeedUserInit(slot)) {
        if (pwFile) {
            oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile);
            if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
                PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]);
                ret = BAD_PW_ERR;
                goto loser;
            }
        } else if (PK11_NeedLogin(slot)) {
            for (matching = PR_FALSE; !matching;) {
                oldpw = SECU_GetPasswordString(NULL, "Enter old password: "******"Enter new password: "******"Re-enter new password: ");
            if (strcmp(newpw, newpw2)) {
                PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]);
                PORT_ZFree(newpw, strlen(newpw));
                PORT_ZFree(newpw2, strlen(newpw2));
            } else {
                matching = PR_TRUE;
            }
        }
    }

    /* Change the password */
    if (PK11_NeedUserInit(slot)) {
        if (PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) {
            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
            ret = CHANGEPW_FAILED_ERR;
            goto loser;
        }
    } else {
        if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
            ret = CHANGEPW_FAILED_ERR;
            goto loser;
        }
    }

    PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName);
    ret = SUCCESS;

loser:
    if (oldpw) {
        PORT_ZFree(oldpw, strlen(oldpw));
    }
    if (newpw) {
        PORT_ZFree(newpw, strlen(newpw));
    }
    if (newpw2) {
        PORT_ZFree(newpw2, strlen(newpw2));
    }
    PK11_FreeSlot(slot);

    return ret;
}
コード例 #20
0
ファイル: sdrtest.c プロジェクト: MekliCZ/positron
int
main (int argc, char **argv)
{
    int		 retval = 0;  /* 0 - test succeeded.  -1 - test failed */
    SECStatus	 rv;
    PLOptState	*optstate;
    PLOptStatus  optstatus;
    char	*program_name;
    const char  *input_file = NULL; 	/* read encrypted data from here (or create) */
    const char  *output_file = NULL;	/* write new encrypted data here */
    const char  *value = default_value;	/* Use this for plaintext */
    SECItem     data;
    SECItem     result = {0, 0, 0};
    SECItem     text;
    PRBool      ascii = PR_FALSE;
    secuPWData  pwdata = { PW_NONE, 0 };

    pr_stderr = PR_STDERR;
    result.data = 0;
    text.data = 0; text.len = 0;

    program_name = PL_strrchr(argv[0], '/');
    program_name = program_name ? (program_name + 1) : argv[0];

    optstate = PL_CreateOptState (argc, argv, "?Had:i:o:t:vf:p:");
    if (optstate == NULL) {
	SECU_PrintError (program_name, "PL_CreateOptState failed");
	return -1;
    }

    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
	switch (optstate->option) {
	  case '?':
	    short_usage (program_name);
	    return retval;

	  case 'H':
	    long_usage (program_name);
	    return retval;

	  case 'a':
	    ascii = PR_TRUE;
	    break;

	  case 'd':
	    SECU_ConfigDirectory(optstate->value);
	    break;

          case 'i':
            input_file = optstate->value;
            break;

          case 'o':
            output_file = optstate->value;
            break;

          case 't':
            value = optstate->value;
            break;

	  case 'f':
	    if (pwdata.data) {
		PORT_Free(pwdata.data);
		short_usage(program_name);
		return -1;
	    }
	    pwdata.source = PW_FROMFILE;
	    pwdata.data = PORT_Strdup(optstate->value);
	    break;

	  case 'p':
	    if (pwdata.data) {
		PORT_Free(pwdata.data);
		short_usage(program_name);
		return -1;
	    }
	    pwdata.source = PW_PLAINTEXT;
	    pwdata.data = PORT_Strdup(optstate->value);
	    break;

          case 'v':
            verbose = PR_TRUE;
            break;
	}
    }
    PL_DestroyOptState(optstate);
    if (optstatus == PL_OPT_BAD) {
	short_usage (program_name);
	return -1;
    }
    if (!output_file && !input_file && value == default_value) {
	short_usage (program_name);
	PR_fprintf (pr_stderr, "Must specify at least one of -t, -i or -o \n");
	return -1;
    }

    /*
     * Initialize the Security libraries.
     */
    PK11_SetPasswordFunc(SECU_GetModulePassword);

    if (output_file) {
	rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
    } else {
	rv = NSS_Init(SECU_ConfigDirectory(NULL));
    }
    if (rv != SECSuccess) {
	SECU_PrintError(program_name, "NSS_Init failed");
	retval = -1;
	goto prdone;
    }

    /* Convert value into an item */
    data.data = (unsigned char *)value;
    data.len = strlen(value);

    /* Get the encrypted result, either from the input file
     * or from encrypting the plaintext value
     */
    if (input_file)
    {
      if (verbose) printf("Reading data from %s\n", input_file);

      if (!strcmp(input_file, "-")) {
	retval = readStdin(&result);
        ascii = PR_TRUE;
      } else {
        retval = readInputFile(input_file, &result);
      }
      if (retval != 0) 
	goto loser;
      if (ascii) {
	/* input was base64 encoded.  Decode it. */
	SECItem newResult = {0, 0, 0};
	SECItem *ok = NSSBase64_DecodeBuffer(NULL, &newResult, 
	                       (const char *)result.data, result.len);
	if (!ok) {
	  SECU_PrintError(program_name, "Base 64 decode failed");
	  retval = -1;
	  goto loser;
	}
	SECITEM_ZfreeItem(&result, PR_FALSE);
	result = *ok;
      }
    }
    else
    {
      SECItem keyid = { 0, 0, 0 };
      SECItem outBuf = { 0, 0, 0 };
      PK11SlotInfo *slot = NULL;

      /* sigh, initialize the key database */
      slot = PK11_GetInternalKeySlot();
      if (slot && PK11_NeedUserInit(slot)) {
	switch (pwdata.source) {
	case PW_FROMFILE:
	    rv = SECU_ChangePW(slot, 0, pwdata.data);
	    break;
	case PW_PLAINTEXT:
	    rv = SECU_ChangePW(slot, pwdata.data, 0);
	    break;
	default:
            rv = SECU_ChangePW(slot, "", 0);
	    break;
	}
        if (rv != SECSuccess) {
            SECU_PrintError(program_name, "Failed to initialize slot \"%s\"",
                                    PK11_GetSlotName(slot));
            return SECFailure;
        }
      }
      if (slot) {
	PK11_FreeSlot(slot);
      }

      rv = PK11SDR_Encrypt(&keyid, &data, &result, &pwdata);
      if (rv != SECSuccess) {
        if (verbose) 
	  SECU_PrintError(program_name, "Encrypt operation failed\n");
        retval = -1;
        goto loser;
      }

      if (verbose) printf("Encrypted result is %d bytes long\n", result.len);

      if (!strcmp(output_file, "-")) {
        ascii = PR_TRUE;
      }

      if (ascii) {
      	/* base64 encode output. */
	char * newResult = NSSBase64_EncodeItem(NULL, NULL, 0, &result);
	if (!newResult) {
	  SECU_PrintError(program_name, "Base 64 encode failed\n");
	  retval = -1;
	  goto loser;
	}
	outBuf.data = (unsigned char *)newResult;
	outBuf.len  = strlen(newResult);
	if (verbose) 
	  printf("Base 64 encoded result is %d bytes long\n", outBuf.len);
      } else {
	outBuf = result;
      }

      /* -v printf("Result is %.*s\n", text.len, text.data); */
      if (output_file) {
         PRFileDesc *file;
         PRInt32 count;

         if (verbose) printf("Writing result to %s\n", output_file);
	 if (!strcmp(output_file, "-")) {
	   file = PR_STDOUT;
	 } else {
	   /* Write to file */
	   file = PR_Open(output_file, PR_CREATE_FILE|PR_WRONLY, 0666);
	 }
         if (!file) {
            if (verbose) 
		SECU_PrintError(program_name, 
                                "Open of output file %s failed\n",
                                output_file);
            retval = -1;
            goto loser;
         }

         count = PR_Write(file, outBuf.data, outBuf.len);

	 if (file == PR_STDOUT) {
	   puts("");
	 } else {
	   PR_Close(file);
	 }

         if (count != outBuf.len) {
           if (verbose) SECU_PrintError(program_name, "Write failed\n");
           retval = -1;
           goto loser;
         }
	 if (ascii) {
	   free(outBuf.data);
	 }
      }
    }

    /* Decrypt the value */
    rv = PK11SDR_Decrypt(&result, &text, &pwdata);
    if (rv != SECSuccess) {
      if (verbose) SECU_PrintError(program_name, "Decrypt operation failed\n");
      retval = -1; 
      goto loser;
    }

    if (verbose) printf("Decrypted result is \"%.*s\"\n", text.len, text.data);

    /* Compare to required value */
    if (text.len != data.len || memcmp(data.data, text.data, text.len) != 0)
    {
      if (verbose) PR_fprintf(pr_stderr, "Comparison failed\n");
      retval = -1;
      goto loser;
    }

loser:
    if (text.data) SECITEM_ZfreeItem(&text, PR_FALSE);
    if (result.data) SECITEM_ZfreeItem(&result, PR_FALSE);
    if (NSS_Shutdown() != SECSuccess) {
       exit(1);
    }

prdone:
    PR_Cleanup ();
    if (pwdata.data) {
	PORT_Free(pwdata.data);
    }
    return retval;
}