import FIREFOX_52_6_0esr_RELEASE from mozilla-esr52 hg repo

This commit is contained in:
Roy Tam 2018-01-19 03:59:58 +08:00
commit dcd9973243
150858 changed files with 23884658 additions and 0 deletions

View file

@ -0,0 +1,62 @@
#! gmake
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#######################################################################
# (1) Include initial platform-independent assignments (MANDATORY). #
#######################################################################
include manifest.mn
#######################################################################
# (2) Include "global" configuration information. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/config.mk
#######################################################################
# (3) Include "component" configuration information. (OPTIONAL) #
#######################################################################
#######################################################################
# (4) Include "local" platform-dependent assignments (OPTIONAL). #
#######################################################################
-include config.mk
#######################################################################
# (5) Execute "global" rules. (OPTIONAL) #
#######################################################################
include $(CORE_DEPTH)/coreconf/rules.mk
#######################################################################
# (6) Execute "component" rules. (OPTIONAL) #
#######################################################################
#######################################################################
# (7) Execute "local" rules. (OPTIONAL). #
#######################################################################
export:: private_export
$(OBJDIR)/pk11load$(OBJ_SUFFIX): debug_module.c
# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile
# pk11slot.c in 64-bit mode for unknown reasons. A workaround is
# to compile it with optimizations turned on. (Bugzilla bug #63815)
ifeq ($(OS_TARGET)$(OS_RELEASE),AIX4.3)
ifeq ($(USE_64),1)
ifndef BUILD_OPT
$(OBJDIR)/pk11slot.o: pk11slot.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
endif
endif
endif

View file

@ -0,0 +1,15 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,279 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef PKIT_H
#include "pkit.h"
#endif /* PKIT_H */
#ifndef DEVM_H
#include "devm.h"
#endif /* DEVM_H */
#include "pki3hack.h"
#include "dev3hack.h"
#include "pkim.h"
#ifndef BASE_H
#include "base.h"
#endif /* BASE_H */
#include "pk11func.h"
#include "secmodti.h"
#include "secerr.h"
NSS_IMPLEMENT nssSession *
nssSession_ImportNSS3Session(NSSArena *arenaOpt,
CK_SESSION_HANDLE session,
PZLock *lock, PRBool rw)
{
nssSession *rvSession = NULL;
if (session != CK_INVALID_SESSION) {
rvSession = nss_ZNEW(arenaOpt, nssSession);
if (rvSession) {
rvSession->handle = session;
rvSession->lock = lock;
rvSession->ownLock = PR_FALSE;
rvSession->isRW = rw;
}
}
return rvSession;
}
NSS_IMPLEMENT nssSession *
nssSlot_CreateSession(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readWrite)
{
nssSession *rvSession;
if (!readWrite) {
/* nss3hack version only returns rw swssions */
return NULL;
}
rvSession = nss_ZNEW(arenaOpt, nssSession);
if (!rvSession) {
return (nssSession *)NULL;
}
rvSession->handle = PK11_GetRWSession(slot->pk11slot);
if (rvSession->handle == CK_INVALID_HANDLE) {
nss_ZFreeIf(rvSession);
return NULL;
}
rvSession->isRW = PR_TRUE;
rvSession->slot = slot;
/*
* The session doesn't need its own lock. Here's why.
* 1. If we are reusing the default RW session of the slot,
* the slot lock is already locked to protect the session.
* 2. If the module is not thread safe, the slot (or rather
* module) lock is already locked.
* 3. If the module is thread safe and we are using a new
* session, no higher-level lock has been locked and we
* would need a lock for the new session. However, the
* current usage of the session is that it is always
* used and destroyed within the same function and never
* shared with another thread.
* So the session is either already protected by another
* lock or only used by one thread.
*/
rvSession->lock = NULL;
rvSession->ownLock = PR_FALSE;
return rvSession;
}
NSS_IMPLEMENT PRStatus
nssSession_Destroy(nssSession *s)
{
PRStatus rv = PR_SUCCESS;
if (s) {
if (s->isRW) {
PK11_RestoreROSession(s->slot->pk11slot, s->handle);
}
rv = nss_ZFreeIf(s);
}
return rv;
}
static NSSSlot *
nssSlot_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot)
{
NSSSlot *rvSlot;
NSSArena *arena;
arena = nssArena_Create();
if (!arena) {
return NULL;
}
rvSlot = nss_ZNEW(arena, NSSSlot);
if (!rvSlot) {
nssArena_Destroy(arena);
return NULL;
}
rvSlot->base.refCount = 1;
rvSlot->base.lock = PZ_NewLock(nssILockOther);
rvSlot->base.arena = arena;
rvSlot->pk11slot = nss3slot;
rvSlot->epv = nss3slot->functionList;
rvSlot->slotID = nss3slot->slotID;
/* Grab the slot name from the PKCS#11 fixed-length buffer */
rvSlot->base.name = nssUTF8_Duplicate(nss3slot->slot_name, td->arena);
rvSlot->lock = (nss3slot->isThreadSafe) ? NULL : nss3slot->sessionLock;
return rvSlot;
}
NSSToken *
nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot)
{
NSSToken *rvToken;
NSSArena *arena;
/* Don't create a token object for a disabled slot */
if (nss3slot->disabled) {
PORT_SetError(SEC_ERROR_NO_TOKEN);
return NULL;
}
arena = nssArena_Create();
if (!arena) {
return NULL;
}
rvToken = nss_ZNEW(arena, NSSToken);
if (!rvToken) {
nssArena_Destroy(arena);
return NULL;
}
rvToken->base.refCount = 1;
rvToken->base.lock = PZ_NewLock(nssILockOther);
if (!rvToken->base.lock) {
nssArena_Destroy(arena);
return NULL;
}
rvToken->base.arena = arena;
rvToken->pk11slot = nss3slot;
rvToken->epv = nss3slot->functionList;
rvToken->defaultSession = nssSession_ImportNSS3Session(td->arena,
nss3slot->session,
nss3slot->sessionLock,
nss3slot->defRWSession);
#if 0 /* we should do this instead of blindly continuing. */
if (!rvToken->defaultSession) {
PORT_SetError(SEC_ERROR_NO_TOKEN);
goto loser;
}
#endif
if (!PK11_IsInternal(nss3slot) && PK11_IsHW(nss3slot)) {
rvToken->cache = nssTokenObjectCache_Create(rvToken,
PR_TRUE, PR_TRUE, PR_TRUE);
if (!rvToken->cache)
goto loser;
}
rvToken->trustDomain = td;
/* Grab the token name from the PKCS#11 fixed-length buffer */
rvToken->base.name = nssUTF8_Duplicate(nss3slot->token_name, td->arena);
rvToken->slot = nssSlot_CreateFromPK11SlotInfo(td, nss3slot);
if (!rvToken->slot) {
goto loser;
}
rvToken->slot->token = rvToken;
if (rvToken->defaultSession)
rvToken->defaultSession->slot = rvToken->slot;
return rvToken;
loser:
PZ_DestroyLock(rvToken->base.lock);
nssArena_Destroy(arena);
return NULL;
}
NSS_IMPLEMENT void
nssToken_UpdateName(NSSToken *token)
{
if (!token) {
return;
}
token->base.name = nssUTF8_Duplicate(token->pk11slot->token_name, token->base.arena);
}
NSS_IMPLEMENT PRBool
nssSlot_IsPermanent(NSSSlot *slot)
{
return slot->pk11slot->isPerm;
}
NSS_IMPLEMENT PRBool
nssSlot_IsFriendly(NSSSlot *slot)
{
return PK11_IsFriendly(slot->pk11slot);
}
NSS_IMPLEMENT PRStatus
nssToken_Refresh(NSSToken *token)
{
PK11SlotInfo *nss3slot;
if (!token) {
return PR_SUCCESS;
}
nss3slot = token->pk11slot;
token->defaultSession =
nssSession_ImportNSS3Session(token->slot->base.arena,
nss3slot->session,
nss3slot->sessionLock,
nss3slot->defRWSession);
return token->defaultSession ? PR_SUCCESS : PR_FAILURE;
}
NSS_IMPLEMENT PRStatus
nssSlot_Refresh(NSSSlot *slot)
{
PK11SlotInfo *nss3slot = slot->pk11slot;
PRBool doit = PR_FALSE;
if (slot->token && slot->token->base.name[0] == 0) {
doit = PR_TRUE;
}
if (PK11_InitToken(nss3slot, PR_FALSE) != SECSuccess) {
return PR_FAILURE;
}
if (doit) {
nssTrustDomain_UpdateCachedTokenCerts(slot->token->trustDomain,
slot->token);
}
return nssToken_Refresh(slot->token);
}
NSS_IMPLEMENT PRStatus
nssToken_GetTrustOrder(NSSToken *tok)
{
PK11SlotInfo *slot;
SECMODModule *module;
slot = tok->pk11slot;
module = PK11_GetModule(slot);
return module->trustOrder;
}
NSS_IMPLEMENT PRBool
nssSlot_IsLoggedIn(NSSSlot *slot)
{
if (!slot->pk11slot->needLogin) {
return PR_TRUE;
}
return PK11_IsLoggedIn(slot->pk11slot, NULL);
}
NSSTrustDomain *
nssToken_GetTrustDomain(NSSToken *token)
{
return token->trustDomain;
}
NSS_EXTERN PRStatus
nssTrustDomain_RemoveTokenCertsFromCache(
NSSTrustDomain *td,
NSSToken *token);
NSS_IMPLEMENT PRStatus
nssToken_NotifyCertsNotVisible(
NSSToken *tok)
{
return nssTrustDomain_RemoveTokenCertsFromCache(tok->trustDomain, tok);
}

View file

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef DEVNSS3HACK_H
#define DEVNSS3HACK_H
#include "cert.h"
PR_BEGIN_EXTERN_C
NSS_EXTERN NSSToken *
nssToken_CreateFromPK11SlotInfo(NSSTrustDomain *td, PK11SlotInfo *nss3slot);
NSS_EXTERN void
nssToken_UpdateName(NSSToken *);
NSS_EXTERN PRStatus
nssToken_Refresh(NSSToken *);
NSSTrustDomain *
nssToken_GetTrustDomain(NSSToken *token);
void PK11Slot_SetNSSToken(PK11SlotInfo *sl, NSSToken *nsst);
NSSToken *PK11Slot_GetNSSToken(PK11SlotInfo *sl);
PR_END_EXTERN_C
#endif /* DEVNSS3HACK_H */

View file

@ -0,0 +1,39 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'includes': [
'../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'lib_pk11wrap_exports',
'type': 'none',
'copies': [
{
'files': [
'pk11func.h',
'pk11pqg.h',
'pk11priv.h',
'pk11pub.h',
'pk11sdr.h',
'secmod.h',
'secmodt.h',
'secpkcs5.h'
],
'destination': '<(nss_public_dist_dir)/<(module)'
},
{
'files': [
'dev3hack.h',
'secmodi.h'
],
'destination': '<(nss_private_dist_dir)/<(module)'
}
]
}
],
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,63 @@
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
CORE_DEPTH = ../..
EXPORTS = \
secmod.h \
secmodt.h \
secpkcs5.h \
pk11func.h \
pk11pub.h \
pk11priv.h \
pk11sdr.h \
pk11pqg.h \
$(NULL)
PRIVATE_EXPORTS = \
secmodi.h \
dev3hack.h \
$(NULL)
MODULE = nss
CSRCS = \
dev3hack.c \
pk11akey.c \
pk11auth.c \
pk11cert.c \
pk11cxt.c \
pk11err.c \
pk11kea.c \
pk11list.c \
pk11load.c \
pk11mech.c \
pk11merge.c \
pk11nobj.c \
pk11obj.c \
pk11pars.c \
pk11pbe.c \
pk11pk12.c \
pk11pqg.c \
pk11sdr.c \
pk11skey.c \
pk11slot.c \
pk11util.c \
$(NULL)
LIBRARY_NAME = pk11wrap
LIBRARY_VERSION = 3
SOFTOKEN_LIBRARY_VERSION = 3
DEFINES += -DSHLIB_SUFFIX=\"$(DLL_SUFFIX)\" -DSHLIB_PREFIX=\"$(DLL_PREFIX)\" \
-DSHLIB_VERSION=\"$(LIBRARY_VERSION)\" \
-DSOFTOKEN_SHLIB_VERSION=\"$(SOFTOKEN_LIBRARY_VERSION)\"
# only add module debugging in opt builds if DEBUG_PKCS11 is set
ifdef DEBUG_PKCS11
DEFINES += -DDEBUG_MODULE -DFORCE_PR_LOG
endif
# This part of the code, including all sub-dirs, can be optimized for size
export ALLOW_OPT_CODE_SIZE = 1

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,807 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file deals with PKCS #11 passwords and authentication.
*/
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "pkcs11t.h"
#include "pk11func.h"
#include "secitem.h"
#include "secerr.h"
#include "pkim.h"
/*************************************************************
* local static and global data
*************************************************************/
/*
* This structure keeps track of status that spans all the Slots.
* NOTE: This is a global data structure. It semantics expect thread crosstalk
* be very careful when you see it used.
* It's major purpose in life is to allow the user to log in one PER
* Tranaction, even if a transaction spans threads. The problem is the user
* may have to enter a password one just to be able to look at the
* personalities/certificates (s)he can use. Then if Auth every is one, they
* may have to enter the password again to use the card. See PK11_StartTransac
* and PK11_EndTransaction.
*/
static struct PK11GlobalStruct {
int transaction;
PRBool inTransaction;
char *(PR_CALLBACK *getPass)(PK11SlotInfo *, PRBool, void *);
PRBool(PR_CALLBACK *verifyPass)(PK11SlotInfo *, void *);
PRBool(PR_CALLBACK *isLoggedIn)(PK11SlotInfo *, void *);
} PK11_Global = { 1, PR_FALSE, NULL, NULL, NULL };
/***********************************************************
* Password Utilities
***********************************************************/
/*
* Check the user's password. Log into the card if it's correct.
* succeed if the user is already logged in.
*/
static SECStatus
pk11_CheckPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
char *pw, PRBool alreadyLocked, PRBool contextSpecific)
{
int len = 0;
CK_RV crv;
SECStatus rv;
PRTime currtime = PR_Now();
PRBool mustRetry;
int retry = 0;
if (slot->protectedAuthPath) {
len = 0;
pw = NULL;
} else if (pw == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
} else {
len = PORT_Strlen(pw);
}
do {
if (!alreadyLocked)
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_Login(session,
contextSpecific ? CKU_CONTEXT_SPECIFIC : CKU_USER,
(unsigned char *)pw, len);
slot->lastLoginCheck = 0;
mustRetry = PR_FALSE;
if (!alreadyLocked)
PK11_ExitSlotMonitor(slot);
switch (crv) {
/* if we're already logged in, we're good to go */
case CKR_OK:
/* TODO If it was for CKU_CONTEXT_SPECIFIC should we do this */
slot->authTransact = PK11_Global.transaction;
/* Fall through */
case CKR_USER_ALREADY_LOGGED_IN:
slot->authTime = currtime;
rv = SECSuccess;
break;
case CKR_PIN_INCORRECT:
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
break;
/* someone called reset while we fetched the password, try again once
* if the token is still there. */
case CKR_SESSION_HANDLE_INVALID:
case CKR_SESSION_CLOSED:
if (session != slot->session) {
/* don't bother retrying, we were in a middle of an operation,
* which is now lost. Just fail. */
PORT_SetError(PK11_MapError(crv));
rv = SECFailure;
break;
}
if (retry++ == 0) {
rv = PK11_InitToken(slot, PR_FALSE);
if (rv == SECSuccess) {
if (slot->session != CK_INVALID_SESSION) {
session = slot->session; /* we should have
* a new session now */
mustRetry = PR_TRUE;
} else {
PORT_SetError(PK11_MapError(crv));
rv = SECFailure;
}
}
break;
}
/* Fall through */
default:
PORT_SetError(PK11_MapError(crv));
rv = SECFailure; /* some failure we can't fix by retrying */
}
} while (mustRetry);
return rv;
}
/*
* Check the user's password. Logout before hand to make sure that
* we are really checking the password.
*/
SECStatus
PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw)
{
int len = 0;
CK_RV crv;
SECStatus rv;
PRTime currtime = PR_Now();
if (slot->protectedAuthPath) {
len = 0;
pw = NULL;
} else if (pw == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
} else {
len = PORT_Strlen(pw);
}
/*
* If the token doesn't need a login, don't try to relogin because the
* effect is undefined. It's not clear what it means to check a non-empty
* password with such a token, so treat that as an error.
*/
if (!slot->needLogin) {
if (len == 0) {
rv = SECSuccess;
} else {
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
rv = SECFailure;
}
return rv;
}
/* force a logout */
PK11_EnterSlotMonitor(slot);
PK11_GETTAB(slot)->C_Logout(slot->session);
crv = PK11_GETTAB(slot)->C_Login(slot->session, CKU_USER,
(unsigned char *)pw, len);
slot->lastLoginCheck = 0;
PK11_ExitSlotMonitor(slot);
switch (crv) {
/* if we're already logged in, we're good to go */
case CKR_OK:
slot->authTransact = PK11_Global.transaction;
slot->authTime = currtime;
rv = SECSuccess;
break;
case CKR_PIN_INCORRECT:
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
break;
default:
PORT_SetError(PK11_MapError(crv));
rv = SECFailure; /* some failure we can't fix by retrying */
}
return rv;
}
SECStatus
PK11_Logout(PK11SlotInfo *slot)
{
CK_RV crv;
/* force a logout */
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_Logout(slot->session);
slot->lastLoginCheck = 0;
PK11_ExitSlotMonitor(slot);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
return SECSuccess;
}
/*
* transaction stuff is for when we test for the need to do every
* time auth to see if we already did it for this slot/transaction
*/
void
PK11_StartAuthTransaction(void)
{
PK11_Global.transaction++;
PK11_Global.inTransaction = PR_TRUE;
}
void
PK11_EndAuthTransaction(void)
{
PK11_Global.transaction++;
PK11_Global.inTransaction = PR_FALSE;
}
/*
* before we do a private key op, we check to see if we
* need to reauthenticate.
*/
void
PK11_HandlePasswordCheck(PK11SlotInfo *slot, void *wincx)
{
int askpw = slot->askpw;
PRBool NeedAuth = PR_FALSE;
if (!slot->needLogin)
return;
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
if (def_slot) {
askpw = def_slot->askpw;
PK11_FreeSlot(def_slot);
}
}
/* timeouts are handled by isLoggedIn */
if (!PK11_IsLoggedIn(slot, wincx)) {
NeedAuth = PR_TRUE;
} else if (askpw == -1) {
if (!PK11_Global.inTransaction ||
(PK11_Global.transaction != slot->authTransact)) {
PK11_EnterSlotMonitor(slot);
PK11_GETTAB(slot)->C_Logout(slot->session);
slot->lastLoginCheck = 0;
PK11_ExitSlotMonitor(slot);
NeedAuth = PR_TRUE;
}
}
if (NeedAuth)
PK11_DoPassword(slot, slot->session, PR_TRUE,
wincx, PR_FALSE, PR_FALSE);
}
void
PK11_SlotDBUpdate(PK11SlotInfo *slot)
{
SECMOD_UpdateModule(slot->module);
}
/*
* set new askpw and timeout values
*/
void
PK11_SetSlotPWValues(PK11SlotInfo *slot, int askpw, int timeout)
{
slot->askpw = askpw;
slot->timeout = timeout;
slot->defaultFlags |= PK11_OWN_PW_DEFAULTS;
PK11_SlotDBUpdate(slot);
}
/*
* Get the askpw and timeout values for this slot
*/
void
PK11_GetSlotPWValues(PK11SlotInfo *slot, int *askpw, int *timeout)
{
*askpw = slot->askpw;
*timeout = slot->timeout;
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
if (def_slot) {
*askpw = def_slot->askpw;
*timeout = def_slot->timeout;
PK11_FreeSlot(def_slot);
}
}
}
/*
* Returns true if the token is needLogin and isn't logged in.
* This function is used to determine if authentication is needed
* before attempting a potentially privelleged operation.
*/
PRBool
pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx)
{
return slot->needLogin && !PK11_IsLoggedIn(slot, wincx);
}
/*
* make sure a slot is authenticated...
* This function only does the authentication if it is needed.
*/
SECStatus
PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
{
if (!slot) {
return SECFailure;
}
if (pk11_LoginStillRequired(slot, wincx)) {
return PK11_DoPassword(slot, slot->session, loadCerts, wincx,
PR_FALSE, PR_FALSE);
}
return SECSuccess;
}
/*
* Authenticate to "unfriendly" tokens (tokens which need to be logged
* in to find the certs.
*/
SECStatus
pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts, void *wincx)
{
SECStatus rv = SECSuccess;
if (!PK11_IsFriendly(slot)) {
rv = PK11_Authenticate(slot, loadCerts, wincx);
}
return rv;
}
/*
* NOTE: this assumes that we are logged out of the card before hand
*/
SECStatus
PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw)
{
CK_SESSION_HANDLE rwsession;
CK_RV crv;
SECStatus rv = SECFailure;
int len = 0;
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
if (rwsession == CK_INVALID_SESSION) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return rv;
}
if (slot->protectedAuthPath) {
len = 0;
ssopw = NULL;
} else if (ssopw == NULL) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
} else {
len = PORT_Strlen(ssopw);
}
/* check the password */
crv = PK11_GETTAB(slot)->C_Login(rwsession, CKU_SO,
(unsigned char *)ssopw, len);
slot->lastLoginCheck = 0;
switch (crv) {
/* if we're already logged in, we're good to go */
case CKR_OK:
rv = SECSuccess;
break;
case CKR_PIN_INCORRECT:
PORT_SetError(SEC_ERROR_BAD_PASSWORD);
rv = SECWouldBlock; /* everything else is ok, only the pin is bad */
break;
default:
PORT_SetError(PK11_MapError(crv));
rv = SECFailure; /* some failure we can't fix by retrying */
}
PK11_GETTAB(slot)->C_Logout(rwsession);
slot->lastLoginCheck = 0;
/* release rwsession */
PK11_RestoreROSession(slot, rwsession);
return rv;
}
/*
* make sure the password conforms to your token's requirements.
*/
SECStatus
PK11_VerifyPW(PK11SlotInfo *slot, char *pw)
{
int len = PORT_Strlen(pw);
if ((slot->minPassword > len) || (slot->maxPassword < len)) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return SECFailure;
}
return SECSuccess;
}
/*
* initialize a user PIN Value
*/
SECStatus
PK11_InitPin(PK11SlotInfo *slot, const char *ssopw, const char *userpw)
{
CK_SESSION_HANDLE rwsession = CK_INVALID_SESSION;
CK_RV crv;
SECStatus rv = SECFailure;
int len;
int ssolen;
if (userpw == NULL)
userpw = "";
if (ssopw == NULL)
ssopw = "";
len = PORT_Strlen(userpw);
ssolen = PORT_Strlen(ssopw);
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
if (rwsession == CK_INVALID_SESSION) {
PORT_SetError(SEC_ERROR_BAD_DATA);
slot->lastLoginCheck = 0;
return rv;
}
if (slot->protectedAuthPath) {
len = 0;
ssolen = 0;
ssopw = NULL;
userpw = NULL;
}
/* check the password */
crv = PK11_GETTAB(slot)->C_Login(rwsession, CKU_SO,
(unsigned char *)ssopw, ssolen);
slot->lastLoginCheck = 0;
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
goto done;
}
crv = PK11_GETTAB(slot)->C_InitPIN(rwsession, (unsigned char *)userpw, len);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
} else {
rv = SECSuccess;
}
done:
PK11_GETTAB(slot)->C_Logout(rwsession);
slot->lastLoginCheck = 0;
PK11_RestoreROSession(slot, rwsession);
if (rv == SECSuccess) {
/* update our view of the world */
PK11_InitToken(slot, PR_TRUE);
if (slot->needLogin) {
PK11_EnterSlotMonitor(slot);
PK11_GETTAB(slot)->C_Login(slot->session, CKU_USER,
(unsigned char *)userpw, len);
slot->lastLoginCheck = 0;
PK11_ExitSlotMonitor(slot);
}
}
return rv;
}
/*
* Change an existing user password
*/
SECStatus
PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw, const char *newpw)
{
CK_RV crv;
SECStatus rv = SECFailure;
int newLen = 0;
int oldLen = 0;
CK_SESSION_HANDLE rwsession;
/* use NULL values to trigger the protected authentication path */
if (!slot->protectedAuthPath) {
if (newpw == NULL)
newpw = "";
if (oldpw == NULL)
oldpw = "";
}
if (newpw)
newLen = PORT_Strlen(newpw);
if (oldpw)
oldLen = PORT_Strlen(oldpw);
/* get a rwsession */
rwsession = PK11_GetRWSession(slot);
if (rwsession == CK_INVALID_SESSION) {
PORT_SetError(SEC_ERROR_BAD_DATA);
return rv;
}
crv = PK11_GETTAB(slot)->C_SetPIN(rwsession,
(unsigned char *)oldpw, oldLen, (unsigned char *)newpw, newLen);
if (crv == CKR_OK) {
rv = SECSuccess;
} else {
PORT_SetError(PK11_MapError(crv));
}
PK11_RestoreROSession(slot, rwsession);
/* update our view of the world */
PK11_InitToken(slot, PR_TRUE);
return rv;
}
static char *
pk11_GetPassword(PK11SlotInfo *slot, PRBool retry, void *wincx)
{
if (PK11_Global.getPass == NULL)
return NULL;
return (*PK11_Global.getPass)(slot, retry, wincx);
}
void
PK11_SetPasswordFunc(PK11PasswordFunc func)
{
PK11_Global.getPass = func;
}
void
PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func)
{
PK11_Global.verifyPass = func;
}
void
PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func)
{
PK11_Global.isLoggedIn = func;
}
/*
* 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, CK_SESSION_HANDLE session,
PRBool loadCerts, void *wincx, PRBool alreadyLocked,
PRBool contextSpecific)
{
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, session, password,
alreadyLocked, contextSpecific);
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;
}
void
PK11_LogoutAll(void)
{
SECMODListLock *lock = SECMOD_GetDefaultModuleListLock();
SECMODModuleList *modList;
SECMODModuleList *mlp = NULL;
int i;
/* NSS is not initialized, there are not tokens to log out */
if (lock == NULL) {
return;
}
SECMOD_GetReadLock(lock);
modList = SECMOD_GetDefaultModuleList();
/* find the number of entries */
for (mlp = modList; mlp != NULL; mlp = mlp->next) {
for (i = 0; i < mlp->module->slotCount; i++) {
PK11_Logout(mlp->module->slots[i]);
}
}
SECMOD_ReleaseReadLock(lock);
}
int
PK11_GetMinimumPwdLength(PK11SlotInfo *slot)
{
return ((int)slot->minPassword);
}
/* Does this slot have a protected pin path? */
PRBool
PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot)
{
return slot->protectedAuthPath;
}
/*
* 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;
}
PRBool
PK11_NeedPWInit()
{
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
PRBool ret = PK11_NeedPWInitForSlot(slot);
PK11_FreeSlot(slot);
return ret;
}
PRBool
pk11_InDelayPeriod(PRIntervalTime lastTime, PRIntervalTime delayTime,
PRIntervalTime *retTime)
{
PRIntervalTime time;
*retTime = time = PR_IntervalNow();
return (PRBool)(lastTime) && ((time - lastTime) < delayTime);
}
/*
* Determine if the token is logged in. We have to actually query the token,
* because it's state can change without intervention from us.
*/
PRBool
PK11_IsLoggedIn(PK11SlotInfo *slot, void *wincx)
{
CK_SESSION_INFO sessionInfo;
int askpw = slot->askpw;
int timeout = slot->timeout;
CK_RV crv;
PRIntervalTime curTime;
static PRIntervalTime login_delay_time = 0;
if (login_delay_time == 0) {
login_delay_time = PR_SecondsToInterval(1);
}
/* If we don't have our own password default values, use the system
* ones */
if ((slot->defaultFlags & PK11_OWN_PW_DEFAULTS) == 0) {
PK11SlotInfo *def_slot = PK11_GetInternalKeySlot();
if (def_slot) {
askpw = def_slot->askpw;
timeout = def_slot->timeout;
PK11_FreeSlot(def_slot);
}
}
if ((wincx != NULL) && (PK11_Global.isLoggedIn != NULL) &&
(*PK11_Global.isLoggedIn)(slot, wincx) == PR_FALSE) {
return PR_FALSE;
}
/* forget the password if we've been inactive too long */
if (askpw == 1) {
PRTime currtime = PR_Now();
PRTime result;
PRTime mult;
LL_I2L(result, timeout);
LL_I2L(mult, 60 * 1000 * 1000);
LL_MUL(result, result, mult);
LL_ADD(result, result, slot->authTime);
if (LL_CMP(result, <, currtime)) {
PK11_EnterSlotMonitor(slot);
PK11_GETTAB(slot)->C_Logout(slot->session);
slot->lastLoginCheck = 0;
PK11_ExitSlotMonitor(slot);
} else {
slot->authTime = currtime;
}
}
PK11_EnterSlotMonitor(slot);
if (pk11_InDelayPeriod(slot->lastLoginCheck, login_delay_time, &curTime)) {
sessionInfo.state = slot->lastState;
crv = CKR_OK;
} else {
crv = PK11_GETTAB(slot)->C_GetSessionInfo(slot->session, &sessionInfo);
if (crv == CKR_OK) {
slot->lastState = sessionInfo.state;
slot->lastLoginCheck = curTime;
}
}
PK11_ExitSlotMonitor(slot);
/* if we can't get session info, something is really wrong */
if (crv != CKR_OK) {
slot->session = CK_INVALID_SESSION;
return PR_FALSE;
}
switch (sessionInfo.state) {
case CKS_RW_PUBLIC_SESSION:
case CKS_RO_PUBLIC_SESSION:
default:
break; /* fail */
case CKS_RW_USER_FUNCTIONS:
case CKS_RW_SO_FUNCTIONS:
case CKS_RO_USER_FUNCTIONS:
return PR_TRUE;
}
return PR_FALSE;
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,141 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* this file maps PKCS11 Errors into SECErrors
* This is an information reducing process, since most errors are reflected
* back to the user (the user doesn't care about invalid flags, or active
* operations). If any of these errors need more detail in the upper layers
* which call PK11 library functions, we can add more SEC_ERROR_XXX functions
* and change there mappings here.
*
* Some PKCS11 errors are mapped to SEC_ERROR_LIBRARY_FAILURE intentionally
* because they indicate that there is a bug in the library (either NSS or
* the token).
*/
#include "pkcs11t.h"
#include "pk11func.h"
#include "secerr.h"
#include "prerror.h"
#ifdef PK11_ERROR_USE_ARRAY
/*
* build a static array of entries...
*/
static struct {
CK_RV pk11_error;
int sec_error;
} pk11_error_map = {
#define MAPERROR(x, y) { x, y },
#else
/* the default is to use a big switch statement */
int
PK11_MapError(CK_RV rv)
{
switch (rv) {
#define MAPERROR(x, y) \
case x: \
return y;
#endif
/* the guts mapping */
/* clang-format off */
MAPERROR(CKR_OK, 0)
MAPERROR(CKR_CANCEL, SEC_ERROR_IO)
MAPERROR(CKR_HOST_MEMORY, SEC_ERROR_NO_MEMORY)
MAPERROR(CKR_SLOT_ID_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_ARGUMENTS_BAD, SEC_ERROR_INVALID_ARGS)
MAPERROR(CKR_ATTRIBUTE_READ_ONLY, SEC_ERROR_READ_ONLY)
MAPERROR(CKR_ATTRIBUTE_SENSITIVE, SEC_ERROR_IO) /* XX SENSITIVE */
MAPERROR(CKR_ATTRIBUTE_TYPE_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_ATTRIBUTE_VALUE_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_BUFFER_TOO_SMALL, SEC_ERROR_OUTPUT_LEN)
MAPERROR(CKR_DATA_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_DATA_LEN_RANGE, SEC_ERROR_INPUT_LEN)
MAPERROR(CKR_DEVICE_ERROR, SEC_ERROR_PKCS11_DEVICE_ERROR)
MAPERROR(CKR_DEVICE_MEMORY, SEC_ERROR_NO_MEMORY)
MAPERROR(CKR_DEVICE_REMOVED, SEC_ERROR_NO_TOKEN)
MAPERROR(CKR_DOMAIN_PARAMS_INVALID, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_ENCRYPTED_DATA_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_ENCRYPTED_DATA_LEN_RANGE, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_FUNCTION_CANCELED, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_FUNCTION_FAILED, SEC_ERROR_PKCS11_FUNCTION_FAILED)
MAPERROR(CKR_FUNCTION_NOT_PARALLEL, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_FUNCTION_NOT_SUPPORTED, PR_NOT_IMPLEMENTED_ERROR)
MAPERROR(CKR_GENERAL_ERROR, SEC_ERROR_PKCS11_GENERAL_ERROR)
MAPERROR(CKR_KEY_HANDLE_INVALID, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_KEY_SIZE_RANGE, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_KEY_TYPE_INCONSISTENT, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_MECHANISM_INVALID, SEC_ERROR_INVALID_ALGORITHM)
MAPERROR(CKR_MECHANISM_PARAM_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_NO_EVENT, SEC_ERROR_NO_EVENT)
MAPERROR(CKR_OBJECT_HANDLE_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_OPERATION_ACTIVE, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_OPERATION_NOT_INITIALIZED, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_PIN_INCORRECT, SEC_ERROR_BAD_PASSWORD)
MAPERROR(CKR_PIN_INVALID, SEC_ERROR_INVALID_PASSWORD)
MAPERROR(CKR_PIN_LEN_RANGE, SEC_ERROR_INVALID_PASSWORD)
MAPERROR(CKR_PIN_EXPIRED, SEC_ERROR_EXPIRED_PASSWORD)
MAPERROR(CKR_PIN_LOCKED, SEC_ERROR_LOCKED_PASSWORD)
MAPERROR(CKR_SESSION_CLOSED, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_SESSION_COUNT, SEC_ERROR_NO_MEMORY) /* XXXX? */
MAPERROR(CKR_SESSION_HANDLE_INVALID, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_SESSION_PARALLEL_NOT_SUPPORTED, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_SESSION_READ_ONLY, SEC_ERROR_READ_ONLY)
MAPERROR(CKR_SIGNATURE_INVALID, SEC_ERROR_BAD_SIGNATURE)
MAPERROR(CKR_SIGNATURE_LEN_RANGE, SEC_ERROR_BAD_SIGNATURE)
MAPERROR(CKR_TEMPLATE_INCOMPLETE, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_TEMPLATE_INCONSISTENT, SEC_ERROR_BAD_DATA)
MAPERROR(CKR_TOKEN_NOT_PRESENT, SEC_ERROR_NO_TOKEN)
MAPERROR(CKR_TOKEN_NOT_RECOGNIZED, SEC_ERROR_IO)
MAPERROR(CKR_TOKEN_WRITE_PROTECTED, SEC_ERROR_READ_ONLY)
MAPERROR(CKR_UNWRAPPING_KEY_HANDLE_INVALID, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_UNWRAPPING_KEY_SIZE_RANGE, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_USER_ALREADY_LOGGED_IN, 0)
MAPERROR(CKR_USER_NOT_LOGGED_IN, SEC_ERROR_TOKEN_NOT_LOGGED_IN)
MAPERROR(CKR_USER_PIN_NOT_INITIALIZED, SEC_ERROR_NO_TOKEN)
MAPERROR(CKR_USER_TYPE_INVALID, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_WRAPPED_KEY_INVALID, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_WRAPPED_KEY_LEN_RANGE, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_WRAPPING_KEY_HANDLE_INVALID, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_WRAPPING_KEY_SIZE_RANGE, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_WRAPPING_KEY_TYPE_INCONSISTENT, SEC_ERROR_INVALID_KEY)
MAPERROR(CKR_VENDOR_DEFINED, SEC_ERROR_LIBRARY_FAILURE)
MAPERROR(CKR_NETSCAPE_CERTDB_FAILED, SEC_ERROR_BAD_DATABASE)
MAPERROR(CKR_NETSCAPE_KEYDB_FAILED, SEC_ERROR_BAD_DATABASE)
MAPERROR(CKR_CANT_LOCK, SEC_ERROR_INCOMPATIBLE_PKCS11)
/* clang-format on */
#ifdef PK11_ERROR_USE_ARRAY
};
int
PK11_MapError(CK_RV rv)
{
int size = sizeof(pk11_error_map) / sizeof(pk11_error_map[0]);
for (i = 0; i < size; i++) {
if (pk11_error_map[i].pk11_error == rv) {
return pk11_error_map[i].sec_error;
}
}
return SEC_ERROR_UNKNOWN_PKCS11_ERROR;
}
#else
/* clang-format off */
default :
break;
/* clang-format on */
}
return SEC_ERROR_UNKNOWN_PKCS11_ERROR;
}
#endif

View file

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PK11FUNC_H_
#define _PK11FUNC_H_
/*
* The original pk11func.h had a mix of public and private functions.
* Continue to provide those for backward compatibility. New code should
* include pk11pub.h instead of pk11func.h.
*/
#include "pk11pub.h"
#include "pk11priv.h"
#endif

View file

@ -0,0 +1,140 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file implements the Symkey wrapper and the PKCS context
* Interfaces.
*/
#include "seccomon.h"
#include "secmod.h"
#include "nssilock.h"
#include "secmodi.h"
#include "secmodti.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "secitem.h"
#include "key.h"
#include "secasn1.h"
#include "sechash.h"
#include "cert.h"
#include "secerr.h"
/*
* find an RSA public key on a card
*/
static CK_OBJECT_HANDLE
pk11_FindRSAPubKey(PK11SlotInfo *slot)
{
CK_KEY_TYPE key_type = CKK_RSA;
CK_OBJECT_CLASS class_type = CKO_PUBLIC_KEY;
CK_ATTRIBUTE theTemplate[2];
int template_count = sizeof(theTemplate) / sizeof(theTemplate[0]);
CK_ATTRIBUTE *attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &class_type, sizeof(class_type));
attrs++;
PK11_SETATTRS(attrs, CKA_KEY_TYPE, &key_type, sizeof(key_type));
attrs++;
template_count = attrs - theTemplate;
PR_ASSERT(template_count <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
return pk11_FindObjectByTemplate(slot, theTemplate, template_count);
}
PK11SymKey *
pk11_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags,
PRBool isPerm, PK11SymKey *symKey)
{
PK11SymKey *newSymKey = NULL;
SECStatus rv;
/* performance improvement can go here --- use a generated key at startup
* to generate a per token wrapping key. If it exists, use it, otherwise
* do a full key exchange. */
/* find a common Key Exchange algorithm */
/* RSA */
if (PK11_DoesMechanism(symKey->slot, CKM_RSA_PKCS) &&
PK11_DoesMechanism(slot, CKM_RSA_PKCS)) {
CK_OBJECT_HANDLE pubKeyHandle = CK_INVALID_HANDLE;
CK_OBJECT_HANDLE privKeyHandle = CK_INVALID_HANDLE;
SECKEYPublicKey *pubKey = NULL;
SECKEYPrivateKey *privKey = NULL;
SECItem wrapData;
unsigned int symKeyLength = PK11_GetKeyLength(symKey);
wrapData.data = NULL;
/* find RSA Public Key on target */
pubKeyHandle = pk11_FindRSAPubKey(slot);
if (pubKeyHandle != CK_INVALID_HANDLE) {
privKeyHandle = PK11_MatchItem(slot, pubKeyHandle, CKO_PRIVATE_KEY);
}
/* if no key exists, generate a key pair */
if (privKeyHandle == CK_INVALID_HANDLE) {
PK11RSAGenParams rsaParams;
if (symKeyLength > 53) /* bytes */ {
/* we'd have to generate an RSA key pair > 512 bits long,
** and that's too costly. Don't even try.
*/
PORT_SetError(SEC_ERROR_CANNOT_MOVE_SENSITIVE_KEY);
goto rsa_failed;
}
rsaParams.keySizeInBits =
(symKeyLength > 21 || symKeyLength == 0) ? 512 : 256;
rsaParams.pe = 0x10001;
privKey = PK11_GenerateKeyPair(slot, CKM_RSA_PKCS_KEY_PAIR_GEN,
&rsaParams, &pubKey, PR_FALSE, PR_TRUE, symKey->cx);
} else {
/* if keys exist, build SECKEY data structures for them */
privKey = PK11_MakePrivKey(slot, nullKey, PR_TRUE, privKeyHandle,
symKey->cx);
if (privKey != NULL) {
pubKey = PK11_ExtractPublicKey(slot, rsaKey, pubKeyHandle);
if (pubKey && pubKey->pkcs11Slot) {
PK11_FreeSlot(pubKey->pkcs11Slot);
pubKey->pkcs11Slot = NULL;
pubKey->pkcs11ID = CK_INVALID_HANDLE;
}
}
}
if (privKey == NULL)
goto rsa_failed;
if (pubKey == NULL)
goto rsa_failed;
wrapData.len = SECKEY_PublicKeyStrength(pubKey);
if (!wrapData.len)
goto rsa_failed;
wrapData.data = PORT_Alloc(wrapData.len);
if (wrapData.data == NULL)
goto rsa_failed;
/* now wrap the keys in and out */
rv = PK11_PubWrapSymKey(CKM_RSA_PKCS, pubKey, symKey, &wrapData);
if (rv == SECSuccess) {
newSymKey = PK11_PubUnwrapSymKeyWithFlagsPerm(privKey,
&wrapData, type, operation,
symKeyLength, flags, isPerm);
/* make sure we wound up where we wanted to be! */
if (newSymKey && newSymKey->slot != slot) {
PK11_FreeSymKey(newSymKey);
newSymKey = NULL;
}
}
rsa_failed:
if (wrapData.data != NULL)
PORT_Free(wrapData.data);
if (privKey != NULL)
SECKEY_DestroyPrivateKey(privKey);
if (pubKey != NULL)
SECKEY_DestroyPublicKey(pubKey);
return newSymKey;
}
PORT_SetError(SEC_ERROR_NO_MODULE);
return NULL;
}

View file

@ -0,0 +1,99 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Locking and queue management primatives
*
*/
#include "seccomon.h"
#include "nssilock.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "nssrwlk.h"
/*
* create a new lock for a Module List
*/
SECMODListLock *
SECMOD_NewListLock()
{
return NSSRWLock_New(10, "moduleListLock");
}
/*
* destroy the lock
*/
void
SECMOD_DestroyListLock(SECMODListLock *lock)
{
NSSRWLock_Destroy(lock);
}
/*
* Lock the List for Read: NOTE: this assumes the reading isn't so common
* the writing will be starved.
*/
void
SECMOD_GetReadLock(SECMODListLock *modLock)
{
NSSRWLock_LockRead(modLock);
}
/*
* Release the Read lock
*/
void
SECMOD_ReleaseReadLock(SECMODListLock *modLock)
{
NSSRWLock_UnlockRead(modLock);
}
/*
* lock the list for Write
*/
void
SECMOD_GetWriteLock(SECMODListLock *modLock)
{
NSSRWLock_LockWrite(modLock);
}
/*
* Release the Write Lock: NOTE, this code is pretty inefficient if you have
* lots of write collisions.
*/
void
SECMOD_ReleaseWriteLock(SECMODListLock *modLock)
{
NSSRWLock_UnlockWrite(modLock);
}
/*
* must Hold the Write lock
*/
void
SECMOD_RemoveList(SECMODModuleList **parent, SECMODModuleList *child)
{
*parent = child->next;
child->next = NULL;
}
/*
* if lock is not specified, it must already be held
*/
void
SECMOD_AddList(SECMODModuleList *parent, SECMODModuleList *child,
SECMODListLock *lock)
{
if (lock) {
SECMOD_GetWriteLock(lock);
}
child->next = parent->next;
parent->next = child;
if (lock) {
SECMOD_ReleaseWriteLock(lock);
}
}

View file

@ -0,0 +1,643 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* The following handles the loading, unloading and management of
* various PCKS #11 modules
*/
#define FORCE_PR_LOG 1
#include "seccomon.h"
#include "pkcs11.h"
#include "secmod.h"
#include "prlink.h"
#include "pk11func.h"
#include "secmodi.h"
#include "secmodti.h"
#include "nssilock.h"
#include "secerr.h"
#include "prenv.h"
#include "utilparst.h"
#define DEBUG_MODULE 1
#ifdef DEBUG_MODULE
static char *modToDBG = NULL;
#include "debug_module.c"
#endif
/* build the PKCS #11 2.01 lock files */
CK_RV PR_CALLBACK
secmodCreateMutext(CK_VOID_PTR_PTR pmutex)
{
*pmutex = (CK_VOID_PTR)PZ_NewLock(nssILockOther);
if (*pmutex)
return CKR_OK;
return CKR_HOST_MEMORY;
}
CK_RV PR_CALLBACK
secmodDestroyMutext(CK_VOID_PTR mutext)
{
PZ_DestroyLock((PZLock *)mutext);
return CKR_OK;
}
CK_RV PR_CALLBACK
secmodLockMutext(CK_VOID_PTR mutext)
{
PZ_Lock((PZLock *)mutext);
return CKR_OK;
}
CK_RV PR_CALLBACK
secmodUnlockMutext(CK_VOID_PTR mutext)
{
PZ_Unlock((PZLock *)mutext);
return CKR_OK;
}
static SECMODModuleID nextModuleID = 1;
static const CK_C_INITIALIZE_ARGS secmodLockFunctions = {
secmodCreateMutext, secmodDestroyMutext, secmodLockMutext,
secmodUnlockMutext, CKF_LIBRARY_CANT_CREATE_OS_THREADS |
CKF_OS_LOCKING_OK,
NULL
};
static const CK_C_INITIALIZE_ARGS secmodNoLockArgs = {
NULL, NULL, NULL, NULL,
CKF_LIBRARY_CANT_CREATE_OS_THREADS, NULL
};
static PRBool loadSingleThreadedModules = PR_TRUE;
static PRBool enforceAlreadyInitializedError = PR_TRUE;
static PRBool finalizeModules = PR_TRUE;
/* set global options for NSS PKCS#11 module loader */
SECStatus
pk11_setGlobalOptions(PRBool noSingleThreadedModules,
PRBool allowAlreadyInitializedModules,
PRBool dontFinalizeModules)
{
if (noSingleThreadedModules) {
loadSingleThreadedModules = PR_FALSE;
} else {
loadSingleThreadedModules = PR_TRUE;
}
if (allowAlreadyInitializedModules) {
enforceAlreadyInitializedError = PR_FALSE;
} else {
enforceAlreadyInitializedError = PR_TRUE;
}
if (dontFinalizeModules) {
finalizeModules = PR_FALSE;
} else {
finalizeModules = PR_TRUE;
}
return SECSuccess;
}
PRBool
pk11_getFinalizeModulesOption(void)
{
return finalizeModules;
}
/*
* Allow specification loading the same module more than once at init time.
* This enables 2 things.
*
* 1) we can load additional databases by manipulating secmod.db/pkcs11.txt.
* 2) we can handle the case where some library has already initialized NSS
* before the main application.
*
* oldModule is the module we have already initialized.
* char *modulespec is the full module spec for the library we want to
* initialize.
*/
static SECStatus
secmod_handleReload(SECMODModule *oldModule, SECMODModule *newModule)
{
PK11SlotInfo *slot;
char *modulespec;
char *newModuleSpec;
char **children;
CK_SLOT_ID *ids;
SECMODConfigList *conflist = NULL;
SECStatus rv = SECFailure;
int count = 0;
/* first look for tokens= key words from the module spec */
modulespec = newModule->libraryParams;
newModuleSpec = secmod_ParseModuleSpecForTokens(PR_TRUE,
newModule->isFIPS, modulespec, &children, &ids);
if (!newModuleSpec) {
return SECFailure;
}
/*
* We are now trying to open a new slot on an already loaded module.
* If that slot represents a cert/key database, we don't want to open
* multiple copies of that same database. Unfortunately we understand
* the softoken flags well enough to be able to do this, so we can only get
* the list of already loaded databases if we are trying to open another
* internal module.
*/
if (oldModule->internal) {
conflist = secmod_GetConfigList(oldModule->isFIPS,
oldModule->libraryParams, &count);
}
/* don't open multiple of the same db */
if (conflist && secmod_MatchConfigList(newModuleSpec, conflist, count)) {
rv = SECSuccess;
goto loser;
}
slot = SECMOD_OpenNewSlot(oldModule, newModuleSpec);
if (slot) {
int newID;
char **thisChild;
CK_SLOT_ID *thisID;
char *oldModuleSpec;
if (secmod_IsInternalKeySlot(newModule)) {
pk11_SetInternalKeySlotIfFirst(slot);
}
newID = slot->slotID;
PK11_FreeSlot(slot);
for (thisChild = children, thisID = ids; thisChild && *thisChild;
thisChild++, thisID++) {
if (conflist &&
secmod_MatchConfigList(*thisChild, conflist, count)) {
*thisID = (CK_SLOT_ID)-1;
continue;
}
slot = SECMOD_OpenNewSlot(oldModule, *thisChild);
if (slot) {
*thisID = slot->slotID;
PK11_FreeSlot(slot);
} else {
*thisID = (CK_SLOT_ID)-1;
}
}
/* update the old module initialization string in case we need to
* shutdown and reinit the whole mess (this is rare, but can happen
* when trying to stop smart card insertion/removal threads)... */
oldModuleSpec = secmod_MkAppendTokensList(oldModule->arena,
oldModule->libraryParams, newModuleSpec, newID,
children, ids);
if (oldModuleSpec) {
oldModule->libraryParams = oldModuleSpec;
}
rv = SECSuccess;
}
loser:
secmod_FreeChildren(children, ids);
PORT_Free(newModuleSpec);
if (conflist) {
secmod_FreeConfigList(conflist, count);
}
return rv;
}
/*
* collect the steps we need to initialize a module in a single function
*/
SECStatus
secmod_ModuleInit(SECMODModule *mod, SECMODModule **reload,
PRBool *alreadyLoaded)
{
CK_C_INITIALIZE_ARGS moduleArgs;
CK_VOID_PTR pInitArgs;
CK_RV crv;
if (reload) {
*reload = NULL;
}
if (!mod || !alreadyLoaded) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
if (mod->libraryParams == NULL) {
if (mod->isThreadSafe) {
pInitArgs = (void *)&secmodLockFunctions;
} else {
pInitArgs = NULL;
}
} else {
if (mod->isThreadSafe) {
moduleArgs = secmodLockFunctions;
} else {
moduleArgs = secmodNoLockArgs;
}
moduleArgs.LibraryParameters = (void *)mod->libraryParams;
pInitArgs = &moduleArgs;
}
crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
if (CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) {
SECMODModule *oldModule = NULL;
/* Library has already been loaded once, if caller expects it, and it
* has additional configuration, try reloading it as well. */
if (reload != NULL && mod->libraryParams) {
oldModule = secmod_FindModuleByFuncPtr(mod->functionList);
}
/* Library has been loaded by NSS. It means it may be capable of
* reloading */
if (oldModule) {
SECStatus rv;
rv = secmod_handleReload(oldModule, mod);
if (rv == SECSuccess) {
/* This module should go away soon, since we've
* simply expanded the slots on the old module.
* When it goes away, it should not Finalize since
* that will close our old module as well. Setting
* the function list to NULL will prevent that close */
mod->functionList = NULL;
*reload = oldModule;
return SECSuccess;
}
SECMOD_DestroyModule(oldModule);
}
/* reload not possible, fall back to old semantics */
if (!enforceAlreadyInitializedError) {
*alreadyLoaded = PR_TRUE;
return SECSuccess;
}
}
if (crv != CKR_OK) {
if (!mod->isThreadSafe ||
crv == CKR_NETSCAPE_CERTDB_FAILED ||
crv == CKR_NETSCAPE_KEYDB_FAILED) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
/* If we had attempted to init a single threaded module "with"
* parameters and it failed, should we retry "without" parameters?
* (currently we don't retry in this scenario) */
if (!loadSingleThreadedModules) {
PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
return SECFailure;
}
/* If we arrive here, the module failed a ThreadSafe init. */
mod->isThreadSafe = PR_FALSE;
if (!mod->libraryParams) {
pInitArgs = NULL;
} else {
moduleArgs = secmodNoLockArgs;
moduleArgs.LibraryParameters = (void *)mod->libraryParams;
pInitArgs = &moduleArgs;
}
crv = PK11_GETTAB(mod)->C_Initialize(pInitArgs);
if ((CKR_CRYPTOKI_ALREADY_INITIALIZED == crv) &&
(!enforceAlreadyInitializedError)) {
*alreadyLoaded = PR_TRUE;
return SECSuccess;
}
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
}
return SECSuccess;
}
/*
* set the hasRootCerts flags in the module so it can be stored back
* into the database.
*/
void
SECMOD_SetRootCerts(PK11SlotInfo *slot, SECMODModule *mod)
{
PK11PreSlotInfo *psi = NULL;
int i;
if (slot->hasRootCerts) {
for (i = 0; i < mod->slotInfoCount; i++) {
if (slot->slotID == mod->slotInfo[i].slotID) {
psi = &mod->slotInfo[i];
break;
}
}
if (psi == NULL) {
/* allocate more slots */
PK11PreSlotInfo *psi_list = (PK11PreSlotInfo *)
PORT_ArenaAlloc(mod->arena,
(mod->slotInfoCount + 1) * sizeof(PK11PreSlotInfo));
/* copy the old ones */
if (mod->slotInfoCount > 0) {
PORT_Memcpy(psi_list, mod->slotInfo,
(mod->slotInfoCount) * sizeof(PK11PreSlotInfo));
}
/* assign psi to the last new slot */
psi = &psi_list[mod->slotInfoCount];
psi->slotID = slot->slotID;
psi->askpw = 0;
psi->timeout = 0;
psi->defaultFlags = 0;
/* increment module count & store new list */
mod->slotInfo = psi_list;
mod->slotInfoCount++;
}
psi->hasRootCerts = 1;
}
}
static const char *my_shlib_name =
SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX;
static const char *softoken_shlib_name =
SHLIB_PREFIX "softokn" SOFTOKEN_SHLIB_VERSION "." SHLIB_SUFFIX;
static const PRCallOnceType pristineCallOnce;
static PRCallOnceType loadSoftokenOnce;
static PRLibrary *softokenLib;
static PRInt32 softokenLoadCount;
#include "prio.h"
#include "prprf.h"
#include <stdio.h>
#include "prsystem.h"
/* This function must be run only once. */
/* determine if hybrid platform, then actually load the DSO. */
static PRStatus
softoken_LoadDSO(void)
{
PRLibrary *handle;
handle = PORT_LoadLibraryFromOrigin(my_shlib_name,
(PRFuncPtr)&softoken_LoadDSO,
softoken_shlib_name);
if (handle) {
softokenLib = handle;
return PR_SUCCESS;
}
return PR_FAILURE;
}
/*
* load a new module into our address space and initialize it.
*/
SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
{
PRLibrary *library = NULL;
CK_C_GetFunctionList entry = NULL;
CK_INFO info;
CK_ULONG slotCount = 0;
SECStatus rv;
PRBool alreadyLoaded = PR_FALSE;
char *disableUnload = NULL;
if (mod->loaded)
return SECSuccess;
/* intenal modules get loaded from their internal list */
if (mod->internal && (mod->dllName == NULL)) {
/*
* Loads softoken as a dynamic library,
* even though the rest of NSS assumes this as the "internal" module.
*/
if (!softokenLib &&
PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO))
return SECFailure;
PR_ATOMIC_INCREMENT(&softokenLoadCount);
if (mod->isFIPS) {
entry = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, "FC_GetFunctionList");
} else {
entry = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, "NSC_GetFunctionList");
}
if (!entry)
return SECFailure;
if (mod->isModuleDB) {
mod->moduleDBFunc = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
}
if (mod->moduleDBOnly) {
mod->loaded = PR_TRUE;
return SECSuccess;
}
} else {
/* Not internal, load the DLL and look up C_GetFunctionList */
if (mod->dllName == NULL) {
return SECFailure;
}
/* load the library. If this succeeds, then we have to remember to
* unload the library if anything goes wrong from here on out...
*/
library = PR_LoadLibrary(mod->dllName);
mod->library = (void *)library;
if (library == NULL) {
return SECFailure;
}
/*
* now we need to get the entry point to find the function pointers
*/
if (!mod->moduleDBOnly) {
entry = (CK_C_GetFunctionList)
PR_FindSymbol(library, "C_GetFunctionList");
}
if (mod->isModuleDB) {
mod->moduleDBFunc = (void *)
PR_FindSymbol(library, "NSS_ReturnModuleSpecData");
}
if (mod->moduleDBFunc == NULL)
mod->isModuleDB = PR_FALSE;
if (entry == NULL) {
if (mod->isModuleDB) {
mod->loaded = PR_TRUE;
mod->moduleDBOnly = PR_TRUE;
return SECSuccess;
}
PR_UnloadLibrary(library);
return SECFailure;
}
}
/*
* We need to get the function list
*/
if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
goto fail;
#ifdef DEBUG_MODULE
if (PR_TRUE) {
modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE");
if (modToDBG && strcmp(mod->commonName, modToDBG) == 0) {
mod->functionList = (void *)nss_InsertDeviceLog(
(CK_FUNCTION_LIST_PTR)mod->functionList);
}
}
#endif
mod->isThreadSafe = PR_TRUE;
/* Now we initialize the module */
rv = secmod_ModuleInit(mod, oldModule, &alreadyLoaded);
if (rv != SECSuccess) {
goto fail;
}
/* module has been reloaded, this module itself is done,
* return to the caller */
if (mod->functionList == NULL) {
mod->loaded = PR_TRUE; /* technically the module is loaded.. */
return SECSuccess;
}
/* check the version number */
if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK)
goto fail2;
if (info.cryptokiVersion.major != 2)
goto fail2;
/* all 2.0 are a priori *not* thread safe */
if (info.cryptokiVersion.minor < 1) {
if (!loadSingleThreadedModules) {
PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
goto fail2;
} else {
mod->isThreadSafe = PR_FALSE;
}
}
mod->cryptokiVersion = info.cryptokiVersion;
/* If we don't have a common name, get it from the PKCS 11 module */
if ((mod->commonName == NULL) || (mod->commonName[0] == 0)) {
mod->commonName = PK11_MakeString(mod->arena, NULL,
(char *)info.libraryDescription, sizeof(info.libraryDescription));
if (mod->commonName == NULL)
goto fail2;
}
/* initialize the Slots */
if (PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, NULL, &slotCount) == CKR_OK) {
CK_SLOT_ID *slotIDs;
int i;
CK_RV crv;
mod->slots = (PK11SlotInfo **)PORT_ArenaAlloc(mod->arena,
sizeof(PK11SlotInfo *) * slotCount);
if (mod->slots == NULL)
goto fail2;
slotIDs = (CK_SLOT_ID *)PORT_Alloc(sizeof(CK_SLOT_ID) * slotCount);
if (slotIDs == NULL) {
goto fail2;
}
crv = PK11_GETTAB(mod)->C_GetSlotList(CK_FALSE, slotIDs, &slotCount);
if (crv != CKR_OK) {
PORT_Free(slotIDs);
goto fail2;
}
/* Initialize each slot */
for (i = 0; i < (int)slotCount; i++) {
mod->slots[i] = PK11_NewSlotInfo(mod);
PK11_InitSlot(mod, slotIDs[i], mod->slots[i]);
/* look down the slot info table */
PK11_LoadSlotList(mod->slots[i], mod->slotInfo, mod->slotInfoCount);
SECMOD_SetRootCerts(mod->slots[i], mod);
/* explicitly mark the internal slot as such if IsInternalKeySlot()
* is set */
if (secmod_IsInternalKeySlot(mod) && (i == (mod->isFIPS ? 0 : 1))) {
pk11_SetInternalKeySlotIfFirst(mod->slots[i]);
}
}
mod->slotCount = slotCount;
mod->slotInfoCount = 0;
PORT_Free(slotIDs);
}
mod->loaded = PR_TRUE;
mod->moduleID = nextModuleID++;
return SECSuccess;
fail2:
if (enforceAlreadyInitializedError || (!alreadyLoaded)) {
PK11_GETTAB(mod)->C_Finalize(NULL);
}
fail:
mod->functionList = NULL;
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (library && !disableUnload) {
PR_UnloadLibrary(library);
}
return SECFailure;
}
SECStatus
SECMOD_UnloadModule(SECMODModule *mod)
{
PRLibrary *library;
char *disableUnload = NULL;
if (!mod->loaded) {
return SECFailure;
}
if (finalizeModules) {
if (mod->functionList && !mod->moduleDBOnly) {
PK11_GETTAB(mod)->C_Finalize(NULL);
}
}
mod->moduleID = 0;
mod->loaded = PR_FALSE;
/* do we want the semantics to allow unloading the internal library?
* if not, we should change this to SECFailure and move it above the
* mod->loaded = PR_FALSE; */
if (mod->internal && (mod->dllName == NULL)) {
if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
if (softokenLib) {
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (!disableUnload) {
#ifdef DEBUG
PRStatus status = PR_UnloadLibrary(softokenLib);
PORT_Assert(PR_SUCCESS == status);
#else
PR_UnloadLibrary(softokenLib);
#endif
}
softokenLib = NULL;
}
loadSoftokenOnce = pristineCallOnce;
}
return SECSuccess;
}
library = (PRLibrary *)mod->library;
/* paranoia */
if (library == NULL) {
return SECFailure;
}
disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
if (!disableUnload) {
PR_UnloadLibrary(library);
}
return SECSuccess;
}
void
nss_DumpModuleLog(void)
{
#ifdef DEBUG_MODULE
if (modToDBG) {
print_final_statistics();
}
#endif
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,791 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file manages Netscape specific PKCS #11 objects (CRLs, Trust objects,
* etc).
*/
#include "secport.h"
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "cert.h"
#include "certi.h"
#include "secitem.h"
#include "sechash.h"
#include "secoid.h"
#include "certdb.h"
#include "secerr.h"
#include "pki3hack.h"
#include "dev3hack.h"
#include "devm.h"
#include "pki.h"
#include "pkim.h"
extern const NSSError NSS_ERROR_NOT_FOUND;
CK_TRUST
pk11_GetTrustField(PK11SlotInfo *slot, PLArenaPool *arena,
CK_OBJECT_HANDLE id, CK_ATTRIBUTE_TYPE type)
{
CK_TRUST rv = 0;
SECItem item;
item.data = NULL;
item.len = 0;
if (SECSuccess == PK11_ReadAttribute(slot, id, type, arena, &item)) {
PORT_Assert(item.len == sizeof(CK_TRUST));
PORT_Memcpy(&rv, item.data, sizeof(CK_TRUST));
/* Damn, is there an endian problem here? */
return rv;
}
return 0;
}
PRBool
pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert, CERTCertTrust *trust)
{
PLArenaPool *arena;
CK_ATTRIBUTE tobjTemplate[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_CERT_SHA1_HASH, NULL, 0 },
};
CK_OBJECT_CLASS tobjc = CKO_NETSCAPE_TRUST;
CK_OBJECT_HANDLE tobjID;
unsigned char sha1_hash[SHA1_LENGTH];
CK_TRUST serverAuth, codeSigning, emailProtection, clientAuth;
PK11_HashBuf(SEC_OID_SHA1, sha1_hash, cert->derCert.data, cert->derCert.len);
PK11_SETATTRS(&tobjTemplate[0], CKA_CLASS, &tobjc, sizeof(tobjc));
PK11_SETATTRS(&tobjTemplate[1], CKA_CERT_SHA1_HASH, sha1_hash,
SHA1_LENGTH);
tobjID = pk11_FindObjectByTemplate(slot, tobjTemplate,
sizeof(tobjTemplate) / sizeof(tobjTemplate[0]));
if (CK_INVALID_HANDLE == tobjID) {
return PR_FALSE;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (NULL == arena)
return PR_FALSE;
/* Unfortunately, it seems that PK11_GetAttributes doesn't deal
* well with nonexistent attributes. I guess we have to check
* the trust info fields one at a time.
*/
/* We could verify CKA_CERT_HASH here */
/* We could verify CKA_EXPIRES here */
/* "Purpose" trust information */
serverAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_SERVER_AUTH);
clientAuth = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CLIENT_AUTH);
codeSigning = pk11_GetTrustField(slot, arena, tobjID, CKA_TRUST_CODE_SIGNING);
emailProtection = pk11_GetTrustField(slot, arena, tobjID,
CKA_TRUST_EMAIL_PROTECTION);
/* Here's where the fun logic happens. We have to map back from the
* key usage, extended key usage, purpose, and possibly other trust values
* into the old trust-flags bits. */
/* First implementation: keep it simple for testing. We can study what other
* mappings would be appropriate and add them later.. fgmr 20000724 */
if (serverAuth == CKT_NSS_TRUSTED) {
trust->sslFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
}
if (serverAuth == CKT_NSS_TRUSTED_DELEGATOR) {
trust->sslFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA |
CERTDB_NS_TRUSTED_CA;
}
if (clientAuth == CKT_NSS_TRUSTED_DELEGATOR) {
trust->sslFlags |= CERTDB_TRUSTED_CLIENT_CA;
}
if (emailProtection == CKT_NSS_TRUSTED) {
trust->emailFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
}
if (emailProtection == CKT_NSS_TRUSTED_DELEGATOR) {
trust->emailFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
}
if (codeSigning == CKT_NSS_TRUSTED) {
trust->objectSigningFlags |= CERTDB_TERMINAL_RECORD | CERTDB_TRUSTED;
}
if (codeSigning == CKT_NSS_TRUSTED_DELEGATOR) {
trust->objectSigningFlags |= CERTDB_VALID_CA | CERTDB_TRUSTED_CA | CERTDB_NS_TRUSTED_CA;
}
/* There's certainly a lot more logic that can go here.. */
PORT_FreeArena(arena, PR_FALSE);
return PR_TRUE;
}
static SECStatus
pk11_CollectCrls(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID, void *arg)
{
SECItem derCrl;
CERTCrlHeadNode *head = (CERTCrlHeadNode *)arg;
CERTCrlNode *new_node = NULL;
CK_ATTRIBUTE fetchCrl[3] = {
{ CKA_VALUE, NULL, 0 },
{ CKA_NETSCAPE_KRL, NULL, 0 },
{ CKA_NETSCAPE_URL, NULL, 0 },
};
const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]);
CK_RV crv;
SECStatus rv = SECFailure;
crv = PK11_GetAttributes(head->arena, slot, crlID, fetchCrl, fetchCrlSize);
if (CKR_OK != crv) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
if (!fetchCrl[1].pValue) {
PORT_SetError(SEC_ERROR_CRL_INVALID);
goto loser;
}
new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena, sizeof(CERTCrlNode));
if (new_node == NULL) {
goto loser;
}
if (*((CK_BBOOL *)fetchCrl[1].pValue))
new_node->type = SEC_KRL_TYPE;
else
new_node->type = SEC_CRL_TYPE;
derCrl.type = siBuffer;
derCrl.data = (unsigned char *)fetchCrl[0].pValue;
derCrl.len = fetchCrl[0].ulValueLen;
new_node->crl = CERT_DecodeDERCrl(head->arena, &derCrl, new_node->type);
if (new_node->crl == NULL) {
goto loser;
}
if (fetchCrl[2].pValue) {
int nnlen = fetchCrl[2].ulValueLen;
new_node->crl->url = (char *)PORT_ArenaAlloc(head->arena, nnlen + 1);
if (!new_node->crl->url) {
goto loser;
}
PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
new_node->crl->url[nnlen] = 0;
} else {
new_node->crl->url = NULL;
}
new_node->next = NULL;
if (head->last) {
head->last->next = new_node;
head->last = new_node;
} else {
head->first = head->last = new_node;
}
rv = SECSuccess;
loser:
return (rv);
}
/*
* Return a list of all the CRLs .
* CRLs are allocated in the list's arena.
*/
SECStatus
PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx)
{
pk11TraverseSlot creater;
CK_ATTRIBUTE theTemplate[2];
CK_ATTRIBUTE *attrs;
CK_OBJECT_CLASS certClass = CKO_NETSCAPE_CRL;
CK_BBOOL isKrl = CK_FALSE;
attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &certClass, sizeof(certClass));
attrs++;
if (type != -1) {
isKrl = (CK_BBOOL)(type == SEC_KRL_TYPE);
PK11_SETATTRS(attrs, CKA_NETSCAPE_KRL, &isKrl, sizeof(isKrl));
attrs++;
}
creater.callback = pk11_CollectCrls;
creater.callbackArg = (void *)nodes;
creater.findTemplate = theTemplate;
creater.templateCount = (attrs - theTemplate);
return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
}
struct crlOptionsStr {
CERTCrlHeadNode *head;
PRInt32 decodeOptions;
};
typedef struct crlOptionsStr crlOptions;
static SECStatus
pk11_RetrieveCrlsCallback(PK11SlotInfo *slot, CK_OBJECT_HANDLE crlID,
void *arg)
{
SECItem *derCrl = NULL;
crlOptions *options = (crlOptions *)arg;
CERTCrlHeadNode *head = options->head;
CERTCrlNode *new_node = NULL;
CK_ATTRIBUTE fetchCrl[3] = {
{ CKA_VALUE, NULL, 0 },
{ CKA_NETSCAPE_KRL, NULL, 0 },
{ CKA_NETSCAPE_URL, NULL, 0 },
};
const int fetchCrlSize = sizeof(fetchCrl) / sizeof(fetchCrl[2]);
CK_RV crv;
SECStatus rv = SECFailure;
PRBool adopted = PR_FALSE; /* whether the CRL adopted the DER memory
successfully */
int i;
crv = PK11_GetAttributes(NULL, slot, crlID, fetchCrl, fetchCrlSize);
if (CKR_OK != crv) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
if (!fetchCrl[1].pValue) {
/* reject KRLs */
PORT_SetError(SEC_ERROR_CRL_INVALID);
goto loser;
}
new_node = (CERTCrlNode *)PORT_ArenaAlloc(head->arena,
sizeof(CERTCrlNode));
if (new_node == NULL) {
goto loser;
}
new_node->type = SEC_CRL_TYPE;
derCrl = SECITEM_AllocItem(NULL, NULL, 0);
if (!derCrl) {
goto loser;
}
derCrl->type = siBuffer;
derCrl->data = (unsigned char *)fetchCrl[0].pValue;
derCrl->len = fetchCrl[0].ulValueLen;
new_node->crl = CERT_DecodeDERCrlWithFlags(NULL, derCrl, new_node->type,
options->decodeOptions);
if (new_node->crl == NULL) {
goto loser;
}
adopted = PR_TRUE; /* now that the CRL has adopted the DER memory,
we won't need to free it upon exit */
if (fetchCrl[2].pValue && fetchCrl[2].ulValueLen) {
/* copy the URL if there is one */
int nnlen = fetchCrl[2].ulValueLen;
new_node->crl->url = (char *)PORT_ArenaAlloc(new_node->crl->arena,
nnlen + 1);
if (!new_node->crl->url) {
goto loser;
}
PORT_Memcpy(new_node->crl->url, fetchCrl[2].pValue, nnlen);
new_node->crl->url[nnlen] = 0;
} else {
new_node->crl->url = NULL;
}
new_node->next = NULL;
if (head->last) {
head->last->next = new_node;
head->last = new_node;
} else {
head->first = head->last = new_node;
}
rv = SECSuccess;
new_node->crl->slot = PK11_ReferenceSlot(slot);
new_node->crl->pkcs11ID = crlID;
loser:
/* free attributes that weren't adopted by the CRL */
for (i = 1; i < fetchCrlSize; i++) {
if (fetchCrl[i].pValue) {
PORT_Free(fetchCrl[i].pValue);
}
}
/* free the DER if the CRL object didn't adopt it */
if (fetchCrl[0].pValue && PR_FALSE == adopted) {
PORT_Free(fetchCrl[0].pValue);
}
if (derCrl && !adopted) {
/* clear the data fields, which we already took care of above */
derCrl->data = NULL;
derCrl->len = 0;
/* free the memory for the SECItem structure itself */
SECITEM_FreeItem(derCrl, PR_TRUE);
}
return (rv);
}
/*
* Return a list of CRLs matching specified issuer and type
* CRLs are not allocated in the list's arena, but rather in their own,
* arena, so that they can be used individually in the CRL cache .
* CRLs are always partially decoded for efficiency.
*/
SECStatus
pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem *issuer,
void *wincx)
{
pk11TraverseSlot creater;
CK_ATTRIBUTE theTemplate[2];
CK_ATTRIBUTE *attrs;
CK_OBJECT_CLASS crlClass = CKO_NETSCAPE_CRL;
crlOptions options;
attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &crlClass, sizeof(crlClass));
attrs++;
options.head = nodes;
/* - do a partial decoding - we don't need to decode the entries while fetching
- don't copy the DER for optimal performance - CRL can be very large
- have the CRL objects adopt the DER, so SEC_DestroyCrl will free it
- keep bad CRL objects. The CRL cache is interested in them, for
security purposes. Bad CRL objects are a sign of something amiss.
*/
options.decodeOptions = CRL_DECODE_SKIP_ENTRIES | CRL_DECODE_DONT_COPY_DER |
CRL_DECODE_ADOPT_HEAP_DER | CRL_DECODE_KEEP_BAD_CRL;
if (issuer) {
PK11_SETATTRS(attrs, CKA_SUBJECT, issuer->data, issuer->len);
attrs++;
}
creater.callback = pk11_RetrieveCrlsCallback;
creater.callbackArg = (void *)&options;
creater.findTemplate = theTemplate;
creater.templateCount = (attrs - theTemplate);
return pk11_TraverseAllSlots(PK11_TraverseSlot, &creater, PR_FALSE, wincx);
}
/*
* return the crl associated with a derSubjectName
*/
SECItem *
PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *crlHandle,
SECItem *name, int type, char **pUrl)
{
NSSCRL **crls, **crlp, *crl = NULL;
NSSDER subject;
SECItem *rvItem;
NSSTrustDomain *td = STAN_GetDefaultTrustDomain();
char *url = NULL;
PORT_SetError(0);
NSSITEM_FROM_SECITEM(&subject, name);
if (*slot) {
nssCryptokiObject **instances;
nssPKIObjectCollection *collection;
nssTokenSearchType tokenOnly = nssTokenSearchType_TokenOnly;
NSSToken *token = PK11Slot_GetNSSToken(*slot);
collection = nssCRLCollection_Create(td, NULL);
if (!collection) {
goto loser;
}
instances = nssToken_FindCRLsBySubject(token, NULL, &subject,
tokenOnly, 0, NULL);
nssPKIObjectCollection_AddInstances(collection, instances, 0);
nss_ZFreeIf(instances);
crls = nssPKIObjectCollection_GetCRLs(collection, NULL, 0, NULL);
nssPKIObjectCollection_Destroy(collection);
} else {
crls = nssTrustDomain_FindCRLsBySubject(td, &subject);
}
if ((!crls) || (*crls == NULL)) {
if (crls) {
nssCRLArray_Destroy(crls);
}
if (NSS_GetError() == NSS_ERROR_NOT_FOUND) {
PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
}
goto loser;
}
for (crlp = crls; *crlp; crlp++) {
if ((!(*crlp)->isKRL && type == SEC_CRL_TYPE) ||
((*crlp)->isKRL && type != SEC_CRL_TYPE)) {
crl = nssCRL_AddRef(*crlp);
break;
}
}
nssCRLArray_Destroy(crls);
if (!crl) {
/* CRL collection was found, but no interesting CRL's were on it.
* Not an error */
PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
goto loser;
}
if (crl->url) {
url = PORT_Strdup(crl->url);
if (!url) {
goto loser;
}
}
rvItem = SECITEM_AllocItem(NULL, NULL, crl->encoding.size);
if (!rvItem) {
goto loser;
}
memcpy(rvItem->data, crl->encoding.data, crl->encoding.size);
*slot = PK11_ReferenceSlot(crl->object.instances[0]->token->pk11slot);
*crlHandle = crl->object.instances[0]->handle;
*pUrl = url;
nssCRL_Destroy(crl);
return rvItem;
loser:
if (url)
PORT_Free(url);
if (crl)
nssCRL_Destroy(crl);
if (PORT_GetError() == 0) {
PORT_SetError(SEC_ERROR_CRL_NOT_FOUND);
}
return NULL;
}
CK_OBJECT_HANDLE
PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl, SECItem *name,
char *url, int type)
{
NSSItem derCRL, derSubject;
NSSToken *token = PK11Slot_GetNSSToken(slot);
nssCryptokiObject *object;
PRBool isKRL = (type == SEC_CRL_TYPE) ? PR_FALSE : PR_TRUE;
CK_OBJECT_HANDLE rvH;
NSSITEM_FROM_SECITEM(&derSubject, name);
NSSITEM_FROM_SECITEM(&derCRL, crl);
object = nssToken_ImportCRL(token, NULL,
&derSubject, &derCRL, isKRL, url, PR_TRUE);
if (object) {
rvH = object->handle;
nssCryptokiObject_Destroy(object);
} else {
rvH = CK_INVALID_HANDLE;
PORT_SetError(SEC_ERROR_CRL_IMPORT_FAILED);
}
return rvH;
}
/*
* delete a crl.
*/
SECStatus
SEC_DeletePermCRL(CERTSignedCrl *crl)
{
PRStatus status;
NSSToken *token;
nssCryptokiObject *object;
PK11SlotInfo *slot = crl->slot;
if (slot == NULL) {
PORT_Assert(slot);
/* shouldn't happen */
PORT_SetError(SEC_ERROR_CRL_INVALID);
return SECFailure;
}
token = PK11Slot_GetNSSToken(slot);
object = nss_ZNEW(NULL, nssCryptokiObject);
if (!object) {
return SECFailure;
}
object->token = nssToken_AddRef(token);
object->handle = crl->pkcs11ID;
object->isTokenObject = PR_TRUE;
status = nssToken_DeleteStoredObject(object);
nssCryptokiObject_Destroy(object);
return (status == PR_SUCCESS) ? SECSuccess : SECFailure;
}
/*
* return the certificate associated with a derCert
*/
SECItem *
PK11_FindSMimeProfile(PK11SlotInfo **slot, char *emailAddr,
SECItem *name, SECItem **profileTime)
{
CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
CK_ATTRIBUTE theTemplate[] = {
{ CKA_SUBJECT, NULL, 0 },
{ CKA_CLASS, NULL, 0 },
{ CKA_NETSCAPE_EMAIL, NULL, 0 },
};
CK_ATTRIBUTE smimeData[] = {
{ CKA_SUBJECT, NULL, 0 },
{ CKA_VALUE, NULL, 0 },
};
/* if you change the array, change the variable below as well */
int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
CK_ATTRIBUTE *attrs = theTemplate;
CK_RV crv;
SECItem *emailProfile = NULL;
if (!emailAddr || !emailAddr[0]) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
PK11_SETATTRS(attrs, CKA_SUBJECT, name->data, name->len);
attrs++;
PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass));
attrs++;
PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL, emailAddr, strlen(emailAddr));
attrs++;
if (*slot) {
smimeh = pk11_FindObjectByTemplate(*slot, theTemplate, tsize);
} else {
PK11SlotList *list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,
PR_FALSE, PR_TRUE, NULL);
PK11SlotListElement *le;
if (!list) {
return NULL;
}
/* loop through all the slots */
for (le = list->head; le; le = le->next) {
smimeh = pk11_FindObjectByTemplate(le->slot, theTemplate, tsize);
if (smimeh != CK_INVALID_HANDLE) {
*slot = PK11_ReferenceSlot(le->slot);
break;
}
}
PK11_FreeSlotList(list);
}
if (smimeh == CK_INVALID_HANDLE) {
PORT_SetError(SEC_ERROR_NO_KRL);
return NULL;
}
if (profileTime) {
PK11_SETATTRS(smimeData, CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0);
}
crv = PK11_GetAttributes(NULL, *slot, smimeh, smimeData, 2);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
if (!profileTime) {
SECItem profileSubject;
profileSubject.data = (unsigned char *)smimeData[0].pValue;
profileSubject.len = smimeData[0].ulValueLen;
if (!SECITEM_ItemsAreEqual(&profileSubject, name)) {
goto loser;
}
}
emailProfile = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
if (emailProfile == NULL) {
goto loser;
}
emailProfile->data = (unsigned char *)smimeData[1].pValue;
emailProfile->len = smimeData[1].ulValueLen;
if (profileTime) {
*profileTime = (SECItem *)PORT_ZAlloc(sizeof(SECItem));
if (*profileTime) {
(*profileTime)->data = (unsigned char *)smimeData[0].pValue;
(*profileTime)->len = smimeData[0].ulValueLen;
}
}
loser:
if (emailProfile == NULL) {
if (smimeData[1].pValue) {
PORT_Free(smimeData[1].pValue);
}
}
if (profileTime == NULL || *profileTime == NULL) {
if (smimeData[0].pValue) {
PORT_Free(smimeData[0].pValue);
}
}
return emailProfile;
}
SECStatus
PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
SECItem *emailProfile, SECItem *profileTime)
{
CK_OBJECT_CLASS smimeClass = CKO_NETSCAPE_SMIME;
CK_BBOOL ck_true = CK_TRUE;
CK_ATTRIBUTE theTemplate[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_TOKEN, NULL, 0 },
{ CKA_SUBJECT, NULL, 0 },
{ CKA_NETSCAPE_EMAIL, NULL, 0 },
{ CKA_NETSCAPE_SMIME_TIMESTAMP, NULL, 0 },
{ CKA_VALUE, NULL, 0 }
};
/* if you change the array, change the variable below as well */
int realSize = 0;
CK_OBJECT_HANDLE smimeh = CK_INVALID_HANDLE;
CK_ATTRIBUTE *attrs = theTemplate;
CK_SESSION_HANDLE rwsession;
PK11SlotInfo *free_slot = NULL;
CK_RV crv;
#ifdef DEBUG
int tsize = sizeof(theTemplate) / sizeof(theTemplate[0]);
#endif
PK11_SETATTRS(attrs, CKA_CLASS, &smimeClass, sizeof(smimeClass));
attrs++;
PK11_SETATTRS(attrs, CKA_TOKEN, &ck_true, sizeof(ck_true));
attrs++;
PK11_SETATTRS(attrs, CKA_SUBJECT, derSubj->data, derSubj->len);
attrs++;
PK11_SETATTRS(attrs, CKA_NETSCAPE_EMAIL,
emailAddr, PORT_Strlen(emailAddr) + 1);
attrs++;
if (profileTime) {
PK11_SETATTRS(attrs, CKA_NETSCAPE_SMIME_TIMESTAMP, profileTime->data,
profileTime->len);
attrs++;
PK11_SETATTRS(attrs, CKA_VALUE, emailProfile->data,
emailProfile->len);
attrs++;
}
realSize = attrs - theTemplate;
PORT_Assert(realSize <= tsize);
if (slot == NULL) {
free_slot = slot = PK11_GetInternalKeySlot();
/* we need to free the key slot in the end!!! */
}
rwsession = PK11_GetRWSession(slot);
if (rwsession == CK_INVALID_SESSION) {
PORT_SetError(SEC_ERROR_READ_ONLY);
if (free_slot) {
PK11_FreeSlot(free_slot);
}
return SECFailure;
}
crv = PK11_GETTAB(slot)->C_CreateObject(rwsession, theTemplate, realSize, &smimeh);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
}
PK11_RestoreROSession(slot, rwsession);
if (free_slot) {
PK11_FreeSlot(free_slot);
}
return SECSuccess;
}
CERTSignedCrl *crl_storeCRL(PK11SlotInfo *slot, char *url,
CERTSignedCrl *newCrl, SECItem *derCrl, int type);
/* import the CRL into the token */
CERTSignedCrl *
PK11_ImportCRL(PK11SlotInfo *slot, SECItem *derCRL, char *url,
int type, void *wincx, PRInt32 importOptions, PLArenaPool *arena,
PRInt32 decodeoptions)
{
CERTSignedCrl *newCrl, *crl;
SECStatus rv;
CERTCertificate *caCert = NULL;
newCrl = crl = NULL;
do {
newCrl = CERT_DecodeDERCrlWithFlags(arena, derCRL, type,
decodeoptions);
if (newCrl == NULL) {
if (type == SEC_CRL_TYPE) {
/* only promote error when the error code is too generic */
if (PORT_GetError() == SEC_ERROR_BAD_DER)
PORT_SetError(SEC_ERROR_CRL_INVALID);
} else {
PORT_SetError(SEC_ERROR_KRL_INVALID);
}
break;
}
if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)) {
CERTCertDBHandle *handle = CERT_GetDefaultCertDB();
PR_ASSERT(handle != NULL);
caCert = CERT_FindCertByName(handle,
&newCrl->crl.derName);
if (caCert == NULL) {
PORT_SetError(SEC_ERROR_UNKNOWN_ISSUER);
break;
}
/* If caCert is a v3 certificate, make sure that it can be used for
crl signing purpose */
rv = CERT_CheckCertUsage(caCert, KU_CRL_SIGN);
if (rv != SECSuccess) {
break;
}
rv = CERT_VerifySignedData(&newCrl->signatureWrap, caCert,
PR_Now(), wincx);
if (rv != SECSuccess) {
if (type == SEC_CRL_TYPE) {
PORT_SetError(SEC_ERROR_CRL_BAD_SIGNATURE);
} else {
PORT_SetError(SEC_ERROR_KRL_BAD_SIGNATURE);
}
break;
}
}
crl = crl_storeCRL(slot, url, newCrl, derCRL, type);
} while (0);
if (crl == NULL) {
SEC_DestroyCrl(newCrl);
}
if (caCert) {
CERT_DestroyCertificate(caCert);
}
return (crl);
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,669 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* This file PKCS #12 fuctions that should really be moved to the
* PKCS #12 directory, however we can't do that in a point release
* because that will break binary compatibility, so we keep them here for now.
*/
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "secitem.h"
#include "key.h"
#include "secoid.h"
#include "secasn1.h"
#include "secerr.h"
#include "prerror.h"
/* These data structures should move to a common .h file shared between the
* wrappers and the pkcs 12 code. */
/*
** RSA Raw Private Key structures
*/
/* member names from PKCS#1, section 7.2 */
struct SECKEYRSAPrivateKeyStr {
PLArenaPool *arena;
SECItem version;
SECItem modulus;
SECItem publicExponent;
SECItem privateExponent;
SECItem prime1;
SECItem prime2;
SECItem exponent1;
SECItem exponent2;
SECItem coefficient;
};
typedef struct SECKEYRSAPrivateKeyStr SECKEYRSAPrivateKey;
/*
** DSA Raw Private Key structures
*/
struct SECKEYDSAPrivateKeyStr {
SECKEYPQGParams params;
SECItem privateValue;
};
typedef struct SECKEYDSAPrivateKeyStr SECKEYDSAPrivateKey;
/*
** Diffie-Hellman Raw Private Key structures
** Structure member names suggested by PKCS#3.
*/
struct SECKEYDHPrivateKeyStr {
PLArenaPool *arena;
SECItem prime;
SECItem base;
SECItem privateValue;
};
typedef struct SECKEYDHPrivateKeyStr SECKEYDHPrivateKey;
/*
** raw private key object
*/
struct SECKEYRawPrivateKeyStr {
PLArenaPool *arena;
KeyType keyType;
union {
SECKEYRSAPrivateKey rsa;
SECKEYDSAPrivateKey dsa;
SECKEYDHPrivateKey dh;
} u;
};
typedef struct SECKEYRawPrivateKeyStr SECKEYRawPrivateKey;
SEC_ASN1_MKSUB(SEC_AnyTemplate)
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
/* ASN1 Templates for new decoder/encoder */
/*
* Attribute value for PKCS8 entries (static?)
*/
const SEC_ASN1Template SECKEY_AttributeTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(SECKEYAttribute) },
{ SEC_ASN1_OBJECT_ID, offsetof(SECKEYAttribute, attrType) },
{ SEC_ASN1_SET_OF | SEC_ASN1_XTRN, offsetof(SECKEYAttribute, attrValue),
SEC_ASN1_SUB(SEC_AnyTemplate) },
{ 0 }
};
const SEC_ASN1Template SECKEY_SetOfAttributeTemplate[] = {
{ SEC_ASN1_SET_OF, 0, SECKEY_AttributeTemplate },
};
const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYPrivateKeyInfo) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYPrivateKeyInfo, version) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(SECKEYPrivateKeyInfo, algorithm),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ SEC_ASN1_OCTET_STRING, offsetof(SECKEYPrivateKeyInfo, privateKey) },
{ SEC_ASN1_OPTIONAL | SEC_ASN1_CONSTRUCTED | SEC_ASN1_CONTEXT_SPECIFIC | 0,
offsetof(SECKEYPrivateKeyInfo, attributes),
SECKEY_SetOfAttributeTemplate },
{ 0 }
};
const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_POINTER, 0, SECKEY_PrivateKeyInfoTemplate }
};
const SEC_ASN1Template SECKEY_RSAPrivateKeyExportTemplate[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SECKEYRawPrivateKey) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.version) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.modulus) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.publicExponent) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.privateExponent) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime1) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.prime2) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent1) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.exponent2) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.rsa.coefficient) },
{ 0 }
};
const SEC_ASN1Template SECKEY_DSAPrivateKeyExportTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dsa.privateValue) },
};
const SEC_ASN1Template SECKEY_DHPrivateKeyExportTemplate[] = {
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.privateValue) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.base) },
{ SEC_ASN1_INTEGER, offsetof(SECKEYRawPrivateKey, u.dh.prime) },
};
const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_SEQUENCE,
0, NULL, sizeof(SECKEYEncryptedPrivateKeyInfo) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN,
offsetof(SECKEYEncryptedPrivateKeyInfo, algorithm),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ SEC_ASN1_OCTET_STRING,
offsetof(SECKEYEncryptedPrivateKeyInfo, encryptedData) },
{ 0 }
};
const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[] = {
{ SEC_ASN1_POINTER, 0, SECKEY_EncryptedPrivateKeyInfoTemplate }
};
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_EncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PrivateKeyInfoTemplate)
SEC_ASN1_CHOOSER_IMPLEMENT(SECKEY_PointerToPrivateKeyInfoTemplate)
/*
* See bugzilla bug 125359
* Since NSS (via PKCS#11) wants to handle big integers as unsigned ints,
* all of the templates above that en/decode into integers must be converted
* from ASN.1's signed integer type. This is done by marking either the
* source or destination (encoding or decoding, respectively) type as
* siUnsignedInteger.
*/
static void
prepare_rsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.rsa.modulus.type = siUnsignedInteger;
key->u.rsa.publicExponent.type = siUnsignedInteger;
key->u.rsa.privateExponent.type = siUnsignedInteger;
key->u.rsa.prime1.type = siUnsignedInteger;
key->u.rsa.prime2.type = siUnsignedInteger;
key->u.rsa.exponent1.type = siUnsignedInteger;
key->u.rsa.exponent2.type = siUnsignedInteger;
key->u.rsa.coefficient.type = siUnsignedInteger;
}
static void
prepare_dsa_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.dsa.privateValue.type = siUnsignedInteger;
key->u.dsa.params.prime.type = siUnsignedInteger;
key->u.dsa.params.subPrime.type = siUnsignedInteger;
key->u.dsa.params.base.type = siUnsignedInteger;
}
static void
prepare_dh_priv_key_export_for_asn1(SECKEYRawPrivateKey *key)
{
key->u.dh.privateValue.type = siUnsignedInteger;
key->u.dh.prime.type = siUnsignedInteger;
key->u.dh.base.type = siUnsignedInteger;
}
SECStatus
PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot, SECItem *derPKI,
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
PRBool isPrivate, unsigned int keyUsage, void *wincx)
{
return PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, derPKI,
nickname, publicValue,
isPerm, isPrivate, keyUsage,
NULL, wincx);
}
SECStatus
PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot, SECItem *derPKI,
SECItem *nickname, SECItem *publicValue,
PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
SECKEYPrivateKey **privk, void *wincx)
{
SECKEYPrivateKeyInfo *pki = NULL;
PLArenaPool *temparena = NULL;
SECStatus rv = SECFailure;
temparena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!temparena)
return rv;
pki = PORT_ArenaZNew(temparena, SECKEYPrivateKeyInfo);
if (!pki) {
PORT_FreeArena(temparena, PR_FALSE);
return rv;
}
pki->arena = temparena;
rv = SEC_ASN1DecodeItem(pki->arena, pki, SECKEY_PrivateKeyInfoTemplate,
derPKI);
if (rv != SECSuccess) {
/* If SEC_ASN1DecodeItem fails, we cannot assume anything about the
* validity of the data in pki. The best we can do is free the arena
* and return. */
PORT_FreeArena(temparena, PR_TRUE);
return rv;
}
if (pki->privateKey.data == NULL) {
/* If SEC_ASN1DecodeItems succeeds but SECKEYPrivateKeyInfo.privateKey
* is a zero-length octet string, free the arena and return a failure
* to avoid trying to zero the corresponding SECItem in
* SECKEY_DestroyPrivateKeyInfo(). */
PORT_FreeArena(temparena, PR_TRUE);
PORT_SetError(SEC_ERROR_BAD_KEY);
return SECFailure;
}
rv = PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
publicValue, isPerm, isPrivate,
keyUsage, privk, wincx);
/* this zeroes the key and frees the arena */
SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE /*freeit*/);
return rv;
}
SECStatus
PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk,
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk,
void *wincx)
{
CK_BBOOL cktrue = CK_TRUE;
CK_BBOOL ckfalse = CK_FALSE;
CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY;
CK_KEY_TYPE keyType = CKK_RSA;
CK_OBJECT_HANDLE objectID;
CK_ATTRIBUTE theTemplate[20];
int templateCount = 0;
SECStatus rv = SECFailure;
CK_ATTRIBUTE *attrs;
CK_ATTRIBUTE *signedattr = NULL;
int signedcount = 0;
CK_ATTRIBUTE *ap;
SECItem *ck_id = NULL;
attrs = theTemplate;
PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass));
attrs++;
PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
attrs++;
PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse,
sizeof(CK_BBOOL));
attrs++;
switch (lpk->keyType) {
case rsaKey:
keyType = CKK_RSA;
PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue
: &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue
: &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
: &ckfalse,
sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN_RECOVER,
(keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue
: &ckfalse,
sizeof(CK_BBOOL));
attrs++;
ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus);
if (ck_id == NULL) {
goto loser;
}
PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
attrs++;
if (nickname) {
PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
attrs++;
}
signedattr = attrs;
PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data,
lpk->u.rsa.modulus.len);
attrs++;
PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT,
lpk->u.rsa.publicExponent.data,
lpk->u.rsa.publicExponent.len);
attrs++;
PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT,
lpk->u.rsa.privateExponent.data,
lpk->u.rsa.privateExponent.len);
attrs++;
PK11_SETATTRS(attrs, CKA_PRIME_1,
lpk->u.rsa.prime1.data,
lpk->u.rsa.prime1.len);
attrs++;
PK11_SETATTRS(attrs, CKA_PRIME_2,
lpk->u.rsa.prime2.data,
lpk->u.rsa.prime2.len);
attrs++;
PK11_SETATTRS(attrs, CKA_EXPONENT_1,
lpk->u.rsa.exponent1.data,
lpk->u.rsa.exponent1.len);
attrs++;
PK11_SETATTRS(attrs, CKA_EXPONENT_2,
lpk->u.rsa.exponent2.data,
lpk->u.rsa.exponent2.len);
attrs++;
PK11_SETATTRS(attrs, CKA_COEFFICIENT,
lpk->u.rsa.coefficient.data,
lpk->u.rsa.coefficient.len);
attrs++;
break;
case dsaKey:
keyType = CKK_DSA;
/* To make our intenal PKCS #11 module work correctly with
* our database, we need to pass in the public key value for
* this dsa key. We have a netscape only CKA_ value to do this.
* Only send it to internal slots */
if (publicValue == NULL) {
goto loser;
}
if (PK11_IsInternal(slot)) {
PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
publicValue->data, publicValue->len);
attrs++;
}
PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL));
attrs++;
PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL));
attrs++;
if (nickname) {
PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
attrs++;
}
ck_id = PK11_MakeIDFromPubKey(publicValue);
if (ck_id == NULL) {
goto loser;
}
PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
attrs++;
signedattr = attrs;
PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data,
lpk->u.dsa.params.prime.len);
attrs++;
PK11_SETATTRS(attrs, CKA_SUBPRIME, lpk->u.dsa.params.subPrime.data,
lpk->u.dsa.params.subPrime.len);
attrs++;
PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data,
lpk->u.dsa.params.base.len);
attrs++;
PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data,
lpk->u.dsa.privateValue.len);
attrs++;
break;
case dhKey:
keyType = CKK_DH;
/* To make our intenal PKCS #11 module work correctly with
* our database, we need to pass in the public key value for
* this dh key. We have a netscape only CKA_ value to do this.
* Only send it to internal slots */
if (PK11_IsInternal(slot)) {
PK11_SETATTRS(attrs, CKA_NETSCAPE_DB,
publicValue->data, publicValue->len);
attrs++;
}
PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL));
attrs++;
if (nickname) {
PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len);
attrs++;
}
ck_id = PK11_MakeIDFromPubKey(publicValue);
if (ck_id == NULL) {
goto loser;
}
PK11_SETATTRS(attrs, CKA_ID, ck_id->data, ck_id->len);
attrs++;
signedattr = attrs;
PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data,
lpk->u.dh.prime.len);
attrs++;
PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data,
lpk->u.dh.base.len);
attrs++;
PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data,
lpk->u.dh.privateValue.len);
attrs++;
break;
/* what about fortezza??? */
default:
PORT_SetError(SEC_ERROR_BAD_KEY);
goto loser;
}
templateCount = attrs - theTemplate;
PORT_Assert(templateCount <= sizeof(theTemplate) / sizeof(CK_ATTRIBUTE));
PORT_Assert(signedattr != NULL);
signedcount = attrs - signedattr;
for (ap = signedattr; signedcount; ap++, signedcount--) {
pk11_SignedToUnsigned(ap);
}
rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION,
theTemplate, templateCount, isPerm, &objectID);
/* create and return a SECKEYPrivateKey */
if (rv == SECSuccess && privk != NULL) {
*privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx);
if (*privk == NULL) {
rv = SECFailure;
}
}
loser:
if (ck_id) {
SECITEM_ZfreeItem(ck_id, PR_TRUE);
}
return rv;
}
SECStatus
PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
SECKEYPrivateKeyInfo *pki, SECItem *nickname, SECItem *publicValue,
PRBool isPerm, PRBool isPrivate, unsigned int keyUsage,
SECKEYPrivateKey **privk, void *wincx)
{
SECStatus rv = SECFailure;
SECKEYRawPrivateKey *lpk = NULL;
const SEC_ASN1Template *keyTemplate, *paramTemplate;
void *paramDest = NULL;
PLArenaPool *arena = NULL;
arena = PORT_NewArena(2048);
if (!arena) {
return SECFailure;
}
/* need to change this to use RSA/DSA keys */
lpk = (SECKEYRawPrivateKey *)PORT_ArenaZAlloc(arena,
sizeof(SECKEYRawPrivateKey));
if (lpk == NULL) {
goto loser;
}
lpk->arena = arena;
switch (SECOID_GetAlgorithmTag(&pki->algorithm)) {
case SEC_OID_PKCS1_RSA_ENCRYPTION:
prepare_rsa_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_RSAPrivateKeyExportTemplate;
paramTemplate = NULL;
paramDest = NULL;
lpk->keyType = rsaKey;
break;
case SEC_OID_ANSIX9_DSA_SIGNATURE:
prepare_dsa_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_DSAPrivateKeyExportTemplate;
paramTemplate = SECKEY_PQGParamsTemplate;
paramDest = &(lpk->u.dsa.params);
lpk->keyType = dsaKey;
break;
case SEC_OID_X942_DIFFIE_HELMAN_KEY:
if (!publicValue) {
goto loser;
}
prepare_dh_priv_key_export_for_asn1(lpk);
keyTemplate = SECKEY_DHPrivateKeyExportTemplate;
paramTemplate = NULL;
paramDest = NULL;
lpk->keyType = dhKey;
break;
default:
keyTemplate = NULL;
paramTemplate = NULL;
paramDest = NULL;
break;
}
if (!keyTemplate) {
goto loser;
}
/* decode the private key and any algorithm parameters */
rv = SEC_ASN1DecodeItem(arena, lpk, keyTemplate, &pki->privateKey);
if (rv != SECSuccess) {
goto loser;
}
if (paramDest && paramTemplate) {
rv = SEC_ASN1DecodeItem(arena, paramDest, paramTemplate,
&(pki->algorithm.parameters));
if (rv != SECSuccess) {
goto loser;
}
}
rv = PK11_ImportAndReturnPrivateKey(slot, lpk, nickname, publicValue, isPerm,
isPrivate, keyUsage, privk, wincx);
loser:
if (arena != NULL) {
PORT_FreeArena(arena, PR_TRUE);
}
return rv;
}
SECStatus
PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot, SECKEYPrivateKeyInfo *pki,
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
PRBool isPrivate, unsigned int keyUsage, void *wincx)
{
return PK11_ImportPrivateKeyInfoAndReturnKey(slot, pki, nickname,
publicValue, isPerm, isPrivate, keyUsage, NULL, wincx);
}
SECItem *
PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx)
{
SECKEYPrivateKeyInfo *pki = PK11_ExportPrivKeyInfo(pk, wincx);
SECItem *derPKI;
if (!pki) {
return NULL;
}
derPKI = SEC_ASN1EncodeItem(NULL, NULL, pki,
SECKEY_PrivateKeyInfoTemplate);
SECKEY_DestroyPrivateKeyInfo(pki, PR_TRUE);
return derPKI;
}
static PRBool
ReadAttribute(SECKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
PLArenaPool *arena, SECItem *output)
{
SECStatus rv = PK11_ReadAttribute(key->pkcs11Slot, key->pkcs11ID, type,
arena, output);
return rv == SECSuccess;
}
/*
* The caller is responsible for freeing the return value by passing it to
* SECKEY_DestroyPrivateKeyInfo(..., PR_TRUE).
*/
SECKEYPrivateKeyInfo *
PK11_ExportPrivKeyInfo(SECKEYPrivateKey *pk, void *wincx)
{
/* PrivateKeyInfo version (always zero) */
const unsigned char pkiVersion = 0;
/* RSAPrivateKey version (always zero) */
const unsigned char rsaVersion = 0;
PLArenaPool *arena = NULL;
SECKEYRawPrivateKey rawKey;
SECKEYPrivateKeyInfo *pki;
SECItem *encoded;
SECStatus rv;
if (pk->keyType != rsaKey) {
PORT_SetError(PR_NOT_IMPLEMENTED_ERROR);
goto loser;
}
arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
if (!arena) {
goto loser;
}
memset(&rawKey, 0, sizeof(rawKey));
rawKey.keyType = pk->keyType;
rawKey.u.rsa.version.type = siUnsignedInteger;
rawKey.u.rsa.version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
if (!rawKey.u.rsa.version.data) {
goto loser;
}
rawKey.u.rsa.version.data[0] = rsaVersion;
rawKey.u.rsa.version.len = 1;
/* Read the component attributes of the private key */
prepare_rsa_priv_key_export_for_asn1(&rawKey);
if (!ReadAttribute(pk, CKA_MODULUS, arena, &rawKey.u.rsa.modulus) ||
!ReadAttribute(pk, CKA_PUBLIC_EXPONENT, arena,
&rawKey.u.rsa.publicExponent) ||
!ReadAttribute(pk, CKA_PRIVATE_EXPONENT, arena,
&rawKey.u.rsa.privateExponent) ||
!ReadAttribute(pk, CKA_PRIME_1, arena, &rawKey.u.rsa.prime1) ||
!ReadAttribute(pk, CKA_PRIME_2, arena, &rawKey.u.rsa.prime2) ||
!ReadAttribute(pk, CKA_EXPONENT_1, arena,
&rawKey.u.rsa.exponent1) ||
!ReadAttribute(pk, CKA_EXPONENT_2, arena,
&rawKey.u.rsa.exponent2) ||
!ReadAttribute(pk, CKA_COEFFICIENT, arena,
&rawKey.u.rsa.coefficient)) {
goto loser;
}
pki = PORT_ArenaZNew(arena, SECKEYPrivateKeyInfo);
if (!pki) {
goto loser;
}
encoded = SEC_ASN1EncodeItem(arena, &pki->privateKey, &rawKey,
SECKEY_RSAPrivateKeyExportTemplate);
if (!encoded) {
goto loser;
}
rv = SECOID_SetAlgorithmID(arena, &pki->algorithm,
SEC_OID_PKCS1_RSA_ENCRYPTION, NULL);
if (rv != SECSuccess) {
goto loser;
}
pki->version.type = siUnsignedInteger;
pki->version.data = (unsigned char *)PORT_ArenaAlloc(arena, 1);
if (!pki->version.data) {
goto loser;
}
pki->version.data[0] = pkiVersion;
pki->version.len = 1;
pki->arena = arena;
return pki;
loser:
if (arena) {
PORT_FreeArena(arena, PR_TRUE);
}
return NULL;
}

View file

@ -0,0 +1,522 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Thse functions are stub functions which will get replaced with calls through
* PKCS #11.
*/
#include "pk11func.h"
#include "secmod.h"
#include "secmodi.h"
#include "secmodti.h"
#include "pkcs11t.h"
#include "pk11pqg.h"
#include "secerr.h"
/* Generate PQGParams and PQGVerify structs.
* Length of P specified by L.
* if L is greater than 1024 then the resulting verify parameters will be
* DSA2.
* Length of Q specified by N. If zero, The PKCS #11 module will
* pick an appropriately sized Q for P. If N is specified and L = 1024, then
* the resulting verify parameters will be DSA2, Otherwise DSA1 parameters
* will be returned.
* Length of SEED in bytes specified in seedBytes.
*
* The underlying PKCS #11 module will check the values for L, N,
* and seedBytes. The rules for softoken are:
*
* If L <= 1024, then L must be between 512 and 1024 in increments of 64 bits.
* If L <= 1024, then N must be 0 or 160.
* If L >= 1024, then L and N must match the following table:
* L=1024 N=0 or 160
* L=2048 N=0 or 224
* L=2048 N=256
* L=3072 N=0 or 256
* if L <= 1024
* seedBbytes must be in the range [20..256].
* if L >= 1024
* seedBbytes must be in the range [20..L/16].
*/
extern SECStatus
PK11_PQG_ParamGenV2(unsigned int L, unsigned int N,
unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy)
{
PK11SlotInfo *slot = NULL;
CK_ATTRIBUTE genTemplate[5];
CK_ATTRIBUTE *attrs = genTemplate;
int count = sizeof(genTemplate) / sizeof(genTemplate[0]);
CK_MECHANISM mechanism;
CK_OBJECT_HANDLE objectID = CK_INVALID_HANDLE;
CK_RV crv;
CK_ATTRIBUTE pTemplate[] = {
{ CKA_PRIME, NULL, 0 },
{ CKA_SUBPRIME, NULL, 0 },
{ CKA_BASE, NULL, 0 },
};
CK_ATTRIBUTE vTemplate[] = {
{ CKA_NETSCAPE_PQG_COUNTER, NULL, 0 },
{ CKA_NETSCAPE_PQG_SEED, NULL, 0 },
{ CKA_NETSCAPE_PQG_H, NULL, 0 },
};
CK_ULONG primeBits = L;
CK_ULONG subPrimeBits = N;
int pTemplateCount = sizeof(pTemplate) / sizeof(pTemplate[0]);
int vTemplateCount = sizeof(vTemplate) / sizeof(vTemplate[0]);
PLArenaPool *parena = NULL;
PLArenaPool *varena = NULL;
PQGParams *params = NULL;
PQGVerify *verify = NULL;
CK_ULONG seedBits = seedBytes * 8;
*pParams = NULL;
*pVfy = NULL;
if (primeBits == (CK_ULONG)-1) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
goto loser;
}
PK11_SETATTRS(attrs, CKA_PRIME_BITS, &primeBits, sizeof(primeBits));
attrs++;
if (subPrimeBits != 0) {
PK11_SETATTRS(attrs, CKA_SUB_PRIME_BITS,
&subPrimeBits, sizeof(subPrimeBits));
attrs++;
}
if (seedBits != 0) {
PK11_SETATTRS(attrs, CKA_NETSCAPE_PQG_SEED_BITS,
&seedBits, sizeof(seedBits));
attrs++;
}
count = attrs - genTemplate;
PR_ASSERT(count <= sizeof(genTemplate) / sizeof(CK_ATTRIBUTE));
slot = PK11_GetInternalSlot();
if (slot == NULL) {
/* set error */
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); /* shouldn't happen */
goto loser;
}
/* make sure the internal slot can handle DSA2 type parameters. */
if (primeBits > 1024) {
CK_MECHANISM_INFO mechanism_info;
if (!slot->isThreadSafe)
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_GetMechanismInfo(slot->slotID,
CKM_DSA_PARAMETER_GEN,
&mechanism_info);
if (!slot->isThreadSafe)
PK11_ExitSlotMonitor(slot);
/* a bug in the old softoken left CKM_DSA_PARAMETER_GEN off of the
* mechanism List. If we get a failure asking for this value, we know
* it can't handle DSA2 */
if ((crv != CKR_OK) || (mechanism_info.ulMaxKeySize < primeBits)) {
PK11_FreeSlot(slot);
slot = PK11_GetBestSlotWithAttributes(CKM_DSA_PARAMETER_GEN, 0,
primeBits, NULL);
if (slot == NULL) {
PORT_SetError(SEC_ERROR_NO_TOKEN); /* can happen */
goto loser;
}
/* ditch seedBits in this case, they are NSS specific and at
* this point we have a token that claims to handle DSA2 */
if (seedBits) {
attrs--;
}
}
}
/* Initialize the Key Gen Mechanism */
mechanism.mechanism = CKM_DSA_PARAMETER_GEN;
mechanism.pParameter = NULL;
mechanism.ulParameterLen = 0;
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_GenerateKey(slot->session,
&mechanism, genTemplate, count, &objectID);
PK11_ExitSlotMonitor(slot);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
parena = PORT_NewArena(60);
if (!parena) {
goto loser;
}
crv = PK11_GetAttributes(parena, slot, objectID, pTemplate, pTemplateCount);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
params = (PQGParams *)PORT_ArenaAlloc(parena, sizeof(PQGParams));
if (params == NULL) {
goto loser;
}
/* fill in Params */
params->arena = parena;
params->prime.type = siUnsignedInteger;
params->prime.data = pTemplate[0].pValue;
params->prime.len = pTemplate[0].ulValueLen;
params->subPrime.type = siUnsignedInteger;
params->subPrime.data = pTemplate[1].pValue;
params->subPrime.len = pTemplate[1].ulValueLen;
params->base.type = siUnsignedInteger;
params->base.data = pTemplate[2].pValue;
params->base.len = pTemplate[2].ulValueLen;
varena = PORT_NewArena(60);
if (!varena) {
goto loser;
}
crv = PK11_GetAttributes(varena, slot, objectID, vTemplate, vTemplateCount);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
goto loser;
}
verify = (PQGVerify *)PORT_ArenaAlloc(varena, sizeof(PQGVerify));
if (verify == NULL) {
goto loser;
}
/* fill in Params */
verify->arena = varena;
verify->counter = (unsigned int)(*(CK_ULONG *)vTemplate[0].pValue);
verify->seed.type = siUnsignedInteger;
verify->seed.data = vTemplate[1].pValue;
verify->seed.len = vTemplate[1].ulValueLen;
verify->h.type = siUnsignedInteger;
verify->h.data = vTemplate[2].pValue;
verify->h.len = vTemplate[2].ulValueLen;
PK11_DestroyObject(slot, objectID);
PK11_FreeSlot(slot);
*pParams = params;
*pVfy = verify;
return SECSuccess;
loser:
if (objectID != CK_INVALID_HANDLE) {
PK11_DestroyObject(slot, objectID);
}
if (parena != NULL) {
PORT_FreeArena(parena, PR_FALSE);
}
if (varena != NULL) {
PORT_FreeArena(varena, PR_FALSE);
}
if (slot) {
PK11_FreeSlot(slot);
}
return SECFailure;
}
/* Generate PQGParams and PQGVerify structs.
* Length of P specified by j. Length of h will match length of P.
* Length of SEED in bytes specified in seedBytes.
* seedBbytes must be in the range [20..255] or an error will result.
*/
extern SECStatus
PK11_PQG_ParamGenSeedLen(unsigned int j, unsigned int seedBytes,
PQGParams **pParams, PQGVerify **pVfy)
{
unsigned int primeBits = PQG_INDEX_TO_PBITS(j);
return PK11_PQG_ParamGenV2(primeBits, 0, seedBytes, pParams, pVfy);
}
/* Generate PQGParams and PQGVerify structs.
* Length of seed and length of h both equal length of P.
* All lengths are specified by "j", according to the table above.
*/
extern SECStatus
PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams, PQGVerify **pVfy)
{
unsigned int primeBits = PQG_INDEX_TO_PBITS(j);
return PK11_PQG_ParamGenV2(primeBits, 0, 0, pParams, pVfy);
}
/* Test PQGParams for validity as DSS PQG values.
* If vfy is non-NULL, test PQGParams to make sure they were generated
* using the specified seed, counter, and h values.
*
* Return value indicates whether Verification operation ran successfully
* to completion, but does not indicate if PQGParams are valid or not.
* If return value is SECSuccess, then *pResult has these meanings:
* SECSuccess: PQGParams are valid.
* SECFailure: PQGParams are invalid.
*/
extern SECStatus
PK11_PQG_VerifyParams(const PQGParams *params, const PQGVerify *vfy,
SECStatus *result)
{
CK_ATTRIBUTE keyTempl[] = {
{ CKA_CLASS, NULL, 0 },
{ CKA_KEY_TYPE, NULL, 0 },
{ CKA_PRIME, NULL, 0 },
{ CKA_SUBPRIME, NULL, 0 },
{ CKA_BASE, NULL, 0 },
{ CKA_TOKEN, NULL, 0 },
{ CKA_NETSCAPE_PQG_COUNTER, NULL, 0 },
{ CKA_NETSCAPE_PQG_SEED, NULL, 0 },
{ CKA_NETSCAPE_PQG_H, NULL, 0 },
};
CK_ATTRIBUTE *attrs;
CK_BBOOL ckfalse = CK_FALSE;
CK_OBJECT_CLASS class = CKO_KG_PARAMETERS;
CK_KEY_TYPE keyType = CKK_DSA;
SECStatus rv = SECSuccess;
PK11SlotInfo *slot;
int keyCount;
CK_OBJECT_HANDLE objectID;
CK_ULONG counter;
CK_RV crv;
attrs = keyTempl;
PK11_SETATTRS(attrs, CKA_CLASS, &class, sizeof(class));
attrs++;
PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType));
attrs++;
PK11_SETATTRS(attrs, CKA_PRIME, params->prime.data,
params->prime.len);
attrs++;
PK11_SETATTRS(attrs, CKA_SUBPRIME, params->subPrime.data,
params->subPrime.len);
attrs++;
if (params->base.len) {
PK11_SETATTRS(attrs, CKA_BASE, params->base.data, params->base.len);
attrs++;
}
PK11_SETATTRS(attrs, CKA_TOKEN, &ckfalse, sizeof(ckfalse));
attrs++;
if (vfy) {
if (vfy->counter != -1) {
counter = vfy->counter;
PK11_SETATTRS(attrs, CKA_NETSCAPE_PQG_COUNTER,
&counter, sizeof(counter));
attrs++;
}
PK11_SETATTRS(attrs, CKA_NETSCAPE_PQG_SEED,
vfy->seed.data, vfy->seed.len);
attrs++;
if (vfy->h.len) {
PK11_SETATTRS(attrs, CKA_NETSCAPE_PQG_H,
vfy->h.data, vfy->h.len);
attrs++;
}
}
keyCount = attrs - keyTempl;
PORT_Assert(keyCount <= sizeof(keyTempl) / sizeof(keyTempl[0]));
slot = PK11_GetInternalSlot();
if (slot == NULL) {
return SECFailure;
}
PK11_EnterSlotMonitor(slot);
crv = PK11_GETTAB(slot)->C_CreateObject(slot->session, keyTempl, keyCount,
&objectID);
PK11_ExitSlotMonitor(slot);
/* throw away the keys, we only wanted the return code */
PK11_DestroyObject(slot, objectID);
PK11_FreeSlot(slot);
*result = SECSuccess;
if (crv == CKR_ATTRIBUTE_VALUE_INVALID) {
*result = SECFailure;
} else if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
rv = SECFailure;
}
return rv;
}
/**************************************************************************
* Free the PQGParams struct and the things it points to. *
**************************************************************************/
extern void
PK11_PQG_DestroyParams(PQGParams *params)
{
if (params == NULL)
return;
if (params->arena != NULL) {
PORT_FreeArena(params->arena, PR_FALSE); /* don't zero it */
} else {
SECITEM_FreeItem(&params->prime, PR_FALSE); /* don't free prime */
SECITEM_FreeItem(&params->subPrime, PR_FALSE); /* don't free subPrime */
SECITEM_FreeItem(&params->base, PR_FALSE); /* don't free base */
PORT_Free(params);
}
}
/**************************************************************************
* Free the PQGVerify struct and the things it points to. *
**************************************************************************/
extern void
PK11_PQG_DestroyVerify(PQGVerify *vfy)
{
if (vfy == NULL)
return;
if (vfy->arena != NULL) {
PORT_FreeArena(vfy->arena, PR_FALSE); /* don't zero it */
} else {
SECITEM_FreeItem(&vfy->seed, PR_FALSE); /* don't free seed */
SECITEM_FreeItem(&vfy->h, PR_FALSE); /* don't free h */
PORT_Free(vfy);
}
}
#define PQG_DEFAULT_CHUNKSIZE 2048 /* bytes */
/**************************************************************************
* Return a pointer to a new PQGParams struct that is constructed from *
* copies of the arguments passed in. *
* Return NULL on failure. *
**************************************************************************/
extern PQGParams *
PK11_PQG_NewParams(const SECItem *prime, const SECItem *subPrime,
const SECItem *base)
{
PLArenaPool *arena;
PQGParams *dest;
SECStatus status;
arena = PORT_NewArena(PQG_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
dest = (PQGParams *)PORT_ArenaZAlloc(arena, sizeof(PQGParams));
if (dest == NULL)
goto loser;
dest->arena = arena;
status = SECITEM_CopyItem(arena, &dest->prime, prime);
if (status != SECSuccess)
goto loser;
status = SECITEM_CopyItem(arena, &dest->subPrime, subPrime);
if (status != SECSuccess)
goto loser;
status = SECITEM_CopyItem(arena, &dest->base, base);
if (status != SECSuccess)
goto loser;
return dest;
loser:
if (arena != NULL)
PORT_FreeArena(arena, PR_FALSE);
return NULL;
}
/**************************************************************************
* Fills in caller's "prime" SECItem with the prime value in params.
* Contents can be freed by calling SECITEM_FreeItem(prime, PR_FALSE);
**************************************************************************/
extern SECStatus
PK11_PQG_GetPrimeFromParams(const PQGParams *params, SECItem *prime)
{
return SECITEM_CopyItem(NULL, prime, &params->prime);
}
/**************************************************************************
* Fills in caller's "subPrime" SECItem with the prime value in params.
* Contents can be freed by calling SECITEM_FreeItem(subPrime, PR_FALSE);
**************************************************************************/
extern SECStatus
PK11_PQG_GetSubPrimeFromParams(const PQGParams *params, SECItem *subPrime)
{
return SECITEM_CopyItem(NULL, subPrime, &params->subPrime);
}
/**************************************************************************
* Fills in caller's "base" SECItem with the base value in params.
* Contents can be freed by calling SECITEM_FreeItem(base, PR_FALSE);
**************************************************************************/
extern SECStatus
PK11_PQG_GetBaseFromParams(const PQGParams *params, SECItem *base)
{
return SECITEM_CopyItem(NULL, base, &params->base);
}
/**************************************************************************
* Return a pointer to a new PQGVerify struct that is constructed from *
* copies of the arguments passed in. *
* Return NULL on failure. *
**************************************************************************/
extern PQGVerify *
PK11_PQG_NewVerify(unsigned int counter, const SECItem *seed,
const SECItem *h)
{
PLArenaPool *arena;
PQGVerify *dest;
SECStatus status;
arena = PORT_NewArena(PQG_DEFAULT_CHUNKSIZE);
if (arena == NULL)
goto loser;
dest = (PQGVerify *)PORT_ArenaZAlloc(arena, sizeof(PQGVerify));
if (dest == NULL)
goto loser;
dest->arena = arena;
dest->counter = counter;
status = SECITEM_CopyItem(arena, &dest->seed, seed);
if (status != SECSuccess)
goto loser;
status = SECITEM_CopyItem(arena, &dest->h, h);
if (status != SECSuccess)
goto loser;
return dest;
loser:
if (arena != NULL)
PORT_FreeArena(arena, PR_FALSE);
return NULL;
}
/**************************************************************************
* Returns "counter" value from the PQGVerify.
**************************************************************************/
extern unsigned int
PK11_PQG_GetCounterFromVerify(const PQGVerify *verify)
{
return verify->counter;
}
/**************************************************************************
* Fills in caller's "seed" SECItem with the seed value in verify.
* Contents can be freed by calling SECITEM_FreeItem(seed, PR_FALSE);
**************************************************************************/
extern SECStatus
PK11_PQG_GetSeedFromVerify(const PQGVerify *verify, SECItem *seed)
{
return SECITEM_CopyItem(NULL, seed, &verify->seed);
}
/**************************************************************************
* Fills in caller's "h" SECItem with the h value in verify.
* Contents can be freed by calling SECITEM_FreeItem(h, PR_FALSE);
**************************************************************************/
extern SECStatus
PK11_PQG_GetHFromVerify(const PQGVerify *verify, SECItem *h)
{
return SECITEM_CopyItem(NULL, h, &verify->h);
}

View file

@ -0,0 +1,135 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* Thse functions are stub functions which will get replaced with calls through
* PKCS #11.
*/
#ifndef _PK11PQG_H_
#define _PK11PQG_H_ 1
#include "blapit.h"
SEC_BEGIN_PROTOS
/* Generate PQGParams and PQGVerify structs.
* Length of seed and length of h both equal length of P.
* All lengths are specified by "j", according to the table above.
*/
extern SECStatus PK11_PQG_ParamGen(unsigned int j, PQGParams **pParams,
PQGVerify **pVfy);
/* Generate PQGParams and PQGVerify structs.
* Length of P specified by j. Length of h will match length of P.
* Length of SEED in bytes specified in seedBytes.
* seedBbytes must be in the range [20..255] or an error will result.
*/
extern SECStatus PK11_PQG_ParamGenSeedLen(unsigned int j,
unsigned int seedBytes, PQGParams **pParams, PQGVerify **pVfy);
/* Generate PQGParams and PQGVerify structs.
* Length of P specified by L.
* if L is greater than 1024 then the resulting verify parameters will be
* DSA2.
* Length of Q specified by N. If zero, The PKCS #11 module will
* pick an appropriately sized Q for L. If N is specified and L = 1024, then
* the resulting verify parameters will be DSA2, Otherwise DSA1 parameters
* will be returned.
* Length of SEED in bytes specified in seedBytes.
*
* The underlying PKCS #11 module will check the values for L, N,
* and seedBytes. The rules for softoken are:
*
* If L <= 1024, then L must be between 512 and 1024 in increments of 64 bits.
* If L <= 1024, then N must be 0 or 160.
* If L >= 1024, then L and N must match the following table:
* L=1024 N=0 or 160
* L=2048 N=0 or 224
* L=2048 N=256
* L=3072 N=0 or 256
* if L <= 1024
* seedBbytes must be in the range [20..256].
* if L >= 1024
* seedBbytes must be in the range [20..L/16].
*/
extern SECStatus
PK11_PQG_ParamGenV2(unsigned int L, unsigned int N, unsigned int seedBytes,
PQGParams **pParams, PQGVerify **pVfy);
/* Test PQGParams for validity as DSS PQG values.
* If vfy is non-NULL, test PQGParams to make sure they were generated
* using the specified seed, counter, and h values.
*
* Return value indicates whether Verification operation ran successfully
* to completion, but does not indicate if PQGParams are valid or not.
* If return value is SECSuccess, then *pResult has these meanings:
* SECSuccess: PQGParams are valid.
* SECFailure: PQGParams are invalid.
*
* Verify the following 12 facts about PQG counter SEED g and h
* These tests are specified in FIPS 186-3 Appendix A.1.1.1, A.1.1.3, and A.2.2
* PQG_VerifyParams in softoken/freebl will automatically choose the
* appropriate test.
*/
extern SECStatus PK11_PQG_VerifyParams(const PQGParams *params,
const PQGVerify *vfy, SECStatus *result);
extern void PK11_PQG_DestroyParams(PQGParams *params);
extern void PK11_PQG_DestroyVerify(PQGVerify *vfy);
/**************************************************************************
* Return a pointer to a new PQGParams struct that is constructed from *
* copies of the arguments passed in. *
* Return NULL on failure. *
**************************************************************************/
extern PQGParams *PK11_PQG_NewParams(const SECItem *prime, const SECItem *subPrime, const SECItem *base);
/**************************************************************************
* Fills in caller's "prime" SECItem with the prime value in params.
* Contents can be freed by calling SECITEM_FreeItem(prime, PR_FALSE);
**************************************************************************/
extern SECStatus PK11_PQG_GetPrimeFromParams(const PQGParams *params,
SECItem *prime);
/**************************************************************************
* Fills in caller's "subPrime" SECItem with the prime value in params.
* Contents can be freed by calling SECITEM_FreeItem(subPrime, PR_FALSE);
**************************************************************************/
extern SECStatus PK11_PQG_GetSubPrimeFromParams(const PQGParams *params,
SECItem *subPrime);
/**************************************************************************
* Fills in caller's "base" SECItem with the base value in params.
* Contents can be freed by calling SECITEM_FreeItem(base, PR_FALSE);
**************************************************************************/
extern SECStatus PK11_PQG_GetBaseFromParams(const PQGParams *params,
SECItem *base);
/**************************************************************************
* Return a pointer to a new PQGVerify struct that is constructed from *
* copies of the arguments passed in. *
* Return NULL on failure. *
**************************************************************************/
extern PQGVerify *PK11_PQG_NewVerify(unsigned int counter,
const SECItem *seed, const SECItem *h);
/**************************************************************************
* Returns "counter" value from the PQGVerify.
**************************************************************************/
extern unsigned int PK11_PQG_GetCounterFromVerify(const PQGVerify *verify);
/**************************************************************************
* Fills in caller's "seed" SECItem with the seed value in verify.
* Contents can be freed by calling SECITEM_FreeItem(seed, PR_FALSE);
**************************************************************************/
extern SECStatus PK11_PQG_GetSeedFromVerify(const PQGVerify *verify,
SECItem *seed);
/**************************************************************************
* Fills in caller's "h" SECItem with the h value in verify.
* Contents can be freed by calling SECITEM_FreeItem(h, PR_FALSE);
**************************************************************************/
extern SECStatus PK11_PQG_GetHFromVerify(const PQGVerify *verify, SECItem *h);
SEC_END_PROTOS
#endif

View file

@ -0,0 +1,187 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PK11PRIV_H_
#define _PK11PRIV_H_
#include "plarena.h"
#include "seccomon.h"
#include "secoidt.h"
#include "secdert.h"
#include "keyt.h"
#include "certt.h"
#include "pkcs11t.h"
#include "secmodt.h"
#include "seccomon.h"
#include "pkcs7t.h"
#include "cmsreclist.h"
/*
* These are the private NSS functions. They are not exported by nss.def, and
* are not callable outside nss3.dll.
*/
SEC_BEGIN_PROTOS
/************************************************************
* Generic Slot Lists Management
************************************************************/
PK11SlotList *PK11_NewSlotList(void);
PK11SlotList *PK11_GetPrivateKeyTokens(CK_MECHANISM_TYPE type,
PRBool needRW, void *wincx);
SECStatus PK11_AddSlotToList(PK11SlotList *list, PK11SlotInfo *slot, PRBool sorted);
SECStatus PK11_DeleteSlotFromList(PK11SlotList *list, PK11SlotListElement *le);
PK11SlotListElement *PK11_FindSlotElement(PK11SlotList *list,
PK11SlotInfo *slot);
PK11SlotInfo *PK11_FindSlotBySerial(char *serial);
int PK11_GetMaxKeyLength(CK_MECHANISM_TYPE type);
/************************************************************
* Generic Slot Management
************************************************************/
CK_OBJECT_HANDLE PK11_CopyKey(PK11SlotInfo *slot, CK_OBJECT_HANDLE srcObject);
SECStatus PK11_ReadAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE type, PLArenaPool *arena, SECItem *result);
CK_ULONG PK11_ReadULongAttribute(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE type);
char *PK11_MakeString(PLArenaPool *arena, char *space, char *staticSring,
int stringLen);
int PK11_MapError(CK_RV error);
CK_SESSION_HANDLE PK11_GetRWSession(PK11SlotInfo *slot);
void PK11_RestoreROSession(PK11SlotInfo *slot, CK_SESSION_HANDLE rwsession);
PRBool PK11_RWSessionHasLock(PK11SlotInfo *slot,
CK_SESSION_HANDLE session_handle);
PK11SlotInfo *PK11_NewSlotInfo(SECMODModule *mod);
void PK11_EnterSlotMonitor(PK11SlotInfo *);
void PK11_ExitSlotMonitor(PK11SlotInfo *);
void PK11_CleanKeyList(PK11SlotInfo *slot);
/************************************************************
* Slot Password Management
************************************************************/
SECStatus PK11_DoPassword(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
PRBool loadCerts, void *wincx, PRBool alreadyLocked,
PRBool contextSpecific);
SECStatus PK11_VerifyPW(PK11SlotInfo *slot, char *pw);
void PK11_HandlePasswordCheck(PK11SlotInfo *slot, void *wincx);
void PK11_SetVerifyPasswordFunc(PK11VerifyPasswordFunc func);
void PK11_SetIsLoggedInFunc(PK11IsLoggedInFunc func);
/************************************************************
* Manage the built-In Slot Lists
************************************************************/
SECStatus PK11_InitSlotLists(void);
void PK11_DestroySlotLists(void);
PK11SlotList *PK11_GetSlotList(CK_MECHANISM_TYPE type);
void PK11_LoadSlotList(PK11SlotInfo *slot, PK11PreSlotInfo *psi, int count);
void PK11_ClearSlotList(PK11SlotInfo *slot);
/******************************************************************
* Slot initialization
******************************************************************/
SECStatus PK11_InitToken(PK11SlotInfo *slot, PRBool loadCerts);
void PK11_InitSlot(SECMODModule *mod, CK_SLOT_ID slotID, PK11SlotInfo *slot);
PRBool PK11_NeedPWInitForSlot(PK11SlotInfo *slot);
SECStatus PK11_ReadSlotCerts(PK11SlotInfo *slot);
void pk11_SetInternalKeySlot(PK11SlotInfo *slot);
PK11SlotInfo *pk11_SwapInternalKeySlot(PK11SlotInfo *slot);
void pk11_SetInternalKeySlotIfFirst(PK11SlotInfo *slot);
/*********************************************************************
* Mechanism Mapping functions
*********************************************************************/
void PK11_AddMechanismEntry(CK_MECHANISM_TYPE type, CK_KEY_TYPE key,
CK_MECHANISM_TYPE keygen, CK_MECHANISM_TYPE pad,
int ivLen, int blocksize);
CK_MECHANISM_TYPE PK11_GetKeyMechanism(CK_KEY_TYPE type);
CK_MECHANISM_TYPE PK11_GetKeyGenWithSize(CK_MECHANISM_TYPE type, int size);
/**********************************************************************
* Symetric, Public, and Private Keys
**********************************************************************/
/* Key Generation specialized for SDR (fixed DES3 key) */
PK11SymKey *PK11_GenDES3TokenKey(PK11SlotInfo *slot, SECItem *keyid, void *cx);
SECKEYPublicKey *PK11_ExtractPublicKey(PK11SlotInfo *slot, KeyType keyType,
CK_OBJECT_HANDLE id);
CK_OBJECT_HANDLE PK11_FindObjectForCert(CERTCertificate *cert,
void *wincx, PK11SlotInfo **pSlot);
PK11SymKey *pk11_CopyToSlot(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey);
/**********************************************************************
* Certs
**********************************************************************/
SECStatus PK11_TraversePrivateKeysInSlot(PK11SlotInfo *slot,
SECStatus (*callback)(SECKEYPrivateKey *, void *), void *arg);
SECKEYPrivateKey *PK11_FindPrivateKeyFromNickname(char *nickname, void *wincx);
CK_OBJECT_HANDLE *PK11_FindObjectsFromNickname(char *nickname,
PK11SlotInfo **slotptr, CK_OBJECT_CLASS objclass, int *returnCount,
void *wincx);
CK_OBJECT_HANDLE PK11_MatchItem(PK11SlotInfo *slot, CK_OBJECT_HANDLE peer,
CK_OBJECT_CLASS o_class);
CK_BBOOL PK11_HasAttributeSet(PK11SlotInfo *slot,
CK_OBJECT_HANDLE id,
CK_ATTRIBUTE_TYPE type,
PRBool haslock);
CK_RV PK11_GetAttributes(PLArenaPool *arena, PK11SlotInfo *slot,
CK_OBJECT_HANDLE obj, CK_ATTRIBUTE *attr, int count);
int PK11_NumberCertsForCertSubject(CERTCertificate *cert);
SECStatus PK11_TraverseCertsForSubject(CERTCertificate *cert,
SECStatus (*callback)(CERTCertificate *, void *), void *arg);
SECStatus PK11_GetKEAMatchedCerts(PK11SlotInfo *slot1,
PK11SlotInfo *slot2, CERTCertificate **cert1, CERTCertificate **cert2);
SECStatus PK11_TraverseCertsInSlot(PK11SlotInfo *slot,
SECStatus (*callback)(CERTCertificate *, void *), void *arg);
SECStatus PK11_LookupCrls(CERTCrlHeadNode *nodes, int type, void *wincx);
/**********************************************************************
* Crypto Contexts
**********************************************************************/
PK11Context *PK11_CreateContextByRawKey(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, PK11Origin origin, CK_ATTRIBUTE_TYPE operation,
SECItem *key, SECItem *param, void *wincx);
PRBool PK11_HashOK(SECOidTag hashAlg);
/**********************************************************************
* Functions which are deprecated....
**********************************************************************/
SECItem *
PK11_FindCrlByName(PK11SlotInfo **slot, CK_OBJECT_HANDLE *handle,
SECItem *derName, int type, char **url);
CK_OBJECT_HANDLE
PK11_PutCrl(PK11SlotInfo *slot, SECItem *crl,
SECItem *name, char *url, int type);
SECItem *
PK11_FindSMimeProfile(PK11SlotInfo **slotp, char *emailAddr, SECItem *derSubj,
SECItem **profileTime);
SECStatus
PK11_SaveSMimeProfile(PK11SlotInfo *slot, char *emailAddr, SECItem *derSubj,
SECItem *emailProfile, SECItem *profileTime);
PRBool PK11_IsPermObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE handle);
char *PK11_GetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id);
SECStatus PK11_SetObjectNickname(PK11SlotInfo *slot, CK_OBJECT_HANDLE id,
const char *nickname);
/* private */
SECStatus pk11_TraverseAllSlots(SECStatus (*callback)(PK11SlotInfo *, void *),
void *cbArg, PRBool forceLogin, void *pwArg);
/* fetch multiple CRLs for a specific issuer */
SECStatus pk11_RetrieveCrls(CERTCrlHeadNode *nodes, SECItem *issuer,
void *wincx);
/* set global options for NSS PKCS#11 module loader */
SECStatus pk11_setGlobalOptions(PRBool noSingleThreadedModules,
PRBool allowAlreadyInitializedModules,
PRBool dontFinalizeModules);
/* return whether NSS is allowed to call C_Finalize */
PRBool pk11_getFinalizeModulesOption(void);
SEC_END_PROTOS
#endif

View file

@ -0,0 +1,879 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PK11PUB_H_
#define _PK11PUB_H_
#include "plarena.h"
#include "seccomon.h"
#include "secoidt.h"
#include "secdert.h"
#include "keyt.h"
#include "certt.h"
#include "pkcs11t.h"
#include "secmodt.h"
#include "seccomon.h"
#include "pkcs7t.h"
#include "cmsreclist.h"
/*
* Exported PK11 wrap functions.
*/
SEC_BEGIN_PROTOS
/************************************************************
* Generic Slot Lists Management
************************************************************/
void PK11_FreeSlotList(PK11SlotList *list);
SECStatus PK11_FreeSlotListElement(PK11SlotList *list, PK11SlotListElement *le);
PK11SlotListElement *PK11_GetFirstSafe(PK11SlotList *list);
PK11SlotListElement *PK11_GetNextSafe(PK11SlotList *list,
PK11SlotListElement *le, PRBool restart);
/************************************************************
* Generic Slot Management
************************************************************/
PK11SlotInfo *PK11_ReferenceSlot(PK11SlotInfo *slot);
void PK11_FreeSlot(PK11SlotInfo *slot);
SECStatus PK11_DestroyObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object);
SECStatus PK11_DestroyTokenObject(PK11SlotInfo *slot, CK_OBJECT_HANDLE object);
PK11SlotInfo *PK11_GetInternalKeySlot(void);
PK11SlotInfo *PK11_GetInternalSlot(void);
SECStatus PK11_Logout(PK11SlotInfo *slot);
void PK11_LogoutAll(void);
/************************************************************
* Slot Password Management
************************************************************/
void PK11_SetSlotPWValues(PK11SlotInfo *slot, int askpw, int timeout);
void PK11_GetSlotPWValues(PK11SlotInfo *slot, int *askpw, int *timeout);
SECStatus PK11_CheckSSOPassword(PK11SlotInfo *slot, char *ssopw);
SECStatus PK11_CheckUserPassword(PK11SlotInfo *slot, const char *pw);
PRBool PK11_IsLoggedIn(PK11SlotInfo *slot, void *wincx);
SECStatus PK11_InitPin(PK11SlotInfo *slot, const char *ssopw,
const char *pk11_userpwd);
SECStatus PK11_ChangePW(PK11SlotInfo *slot, const char *oldpw,
const char *newpw);
void PK11_SetPasswordFunc(PK11PasswordFunc func);
int PK11_GetMinimumPwdLength(PK11SlotInfo *slot);
SECStatus PK11_ResetToken(PK11SlotInfo *slot, char *sso_pwd);
SECStatus PK11_Authenticate(PK11SlotInfo *slot, PRBool loadCerts, void *wincx);
SECStatus PK11_TokenRefresh(PK11SlotInfo *slot);
/******************************************************************
* Slot info functions
******************************************************************/
PK11SlotInfo *PK11_FindSlotByName(const char *name);
/******************************************************************
* PK11_FindSlotsByNames searches for a PK11SlotInfo using one or
* more criteria : dllName, slotName and tokenName . In addition, if
* presentOnly is set , only slots with a token inserted will be
* returned.
******************************************************************/
PK11SlotList *PK11_FindSlotsByNames(const char *dllName,
const char *slotName, const char *tokenName, PRBool presentOnly);
PRBool PK11_IsReadOnly(PK11SlotInfo *slot);
PRBool PK11_IsInternal(PK11SlotInfo *slot);
PRBool PK11_IsInternalKeySlot(PK11SlotInfo *slot);
char *PK11_GetTokenName(PK11SlotInfo *slot);
char *PK11_GetSlotName(PK11SlotInfo *slot);
PRBool PK11_NeedLogin(PK11SlotInfo *slot);
PRBool PK11_IsFriendly(PK11SlotInfo *slot);
PRBool PK11_IsHW(PK11SlotInfo *slot);
PRBool PK11_IsRemovable(PK11SlotInfo *slot);
PRBool PK11_NeedUserInit(PK11SlotInfo *slot);
PRBool PK11_ProtectedAuthenticationPath(PK11SlotInfo *slot);
int PK11_GetSlotSeries(PK11SlotInfo *slot);
int PK11_GetCurrentWrapIndex(PK11SlotInfo *slot);
unsigned long PK11_GetDefaultFlags(PK11SlotInfo *slot);
CK_SLOT_ID PK11_GetSlotID(PK11SlotInfo *slot);
SECMODModuleID PK11_GetModuleID(PK11SlotInfo *slot);
SECStatus PK11_GetSlotInfo(PK11SlotInfo *slot, CK_SLOT_INFO *info);
SECStatus PK11_GetTokenInfo(PK11SlotInfo *slot, CK_TOKEN_INFO *info);
PRBool PK11_IsDisabled(PK11SlotInfo *slot);
PRBool PK11_HasRootCerts(PK11SlotInfo *slot);
PK11DisableReasons PK11_GetDisabledReason(PK11SlotInfo *slot);
/* Prevents the slot from being used, and set disable reason to user-disable */
/* NOTE: Mechanisms that were ON continue to stay ON */
/* Therefore, when the slot is enabled, it will remember */
/* what mechanisms needs to be turned on */
PRBool PK11_UserDisableSlot(PK11SlotInfo *slot);
/* Allow all mechanisms that are ON before UserDisableSlot() */
/* was called to be available again */
PRBool PK11_UserEnableSlot(PK11SlotInfo *slot);
/*
* wait for a specific slot event.
* event is a specific event to wait for. Currently only
* PK11TokenChangeOrRemovalEvent and PK11TokenPresentEvents are defined.
* timeout can be an interval time to wait, PR_INTERVAL_NO_WAIT (meaning only
* poll once), or PR_INTERVAL_NO_TIMEOUT (meaning block until a change).
* pollInterval is a suggested pulling interval value. '0' means use the
* default. Future implementations that don't poll may ignore this value.
* series is the current series for the last slot. This should be the series
* value for the slot the last time you read persistant information from the
* slot. For instance, if you publish a cert from the slot, you should obtain
* the slot series at that time. Then PK11_WaitForTokenEvent can detect a
* a change in the slot between the time you publish and the time
* PK11_WaitForTokenEvent is called, elliminating potential race conditions.
*
* The current status that is returned is:
* PK11TokenNotRemovable - always returned for any non-removable token.
* PK11TokenPresent - returned when the token is present and we are waiting
* on a PK11TokenPresentEvent. Then next event to look for is a
* PK11TokenChangeOrRemovalEvent.
* PK11TokenChanged - returned when the old token has been removed and a new
* token ad been inserted, and we are waiting for a
* PK11TokenChangeOrRemovalEvent. The next event to look for is another
* PK11TokenChangeOrRemovalEvent.
* PK11TokenRemoved - returned when the token is not present and we are
* waiting for a PK11TokenChangeOrRemovalEvent. The next event to look for
* is a PK11TokenPresentEvent.
*/
PK11TokenStatus PK11_WaitForTokenEvent(PK11SlotInfo *slot, PK11TokenEvent event,
PRIntervalTime timeout, PRIntervalTime pollInterval, int series);
PRBool PK11_NeedPWInit(void);
PRBool PK11_TokenExists(CK_MECHANISM_TYPE);
SECStatus PK11_GetModInfo(SECMODModule *mod, CK_INFO *info);
PRBool PK11_IsFIPS(void);
SECMODModule *PK11_GetModule(PK11SlotInfo *slot);
/*********************************************************************
* Slot mapping utility functions.
*********************************************************************/
PRBool PK11_IsPresent(PK11SlotInfo *slot);
PRBool PK11_DoesMechanism(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
PK11SlotList *PK11_GetAllTokens(CK_MECHANISM_TYPE type, PRBool needRW,
PRBool loadCerts, void *wincx);
PK11SlotInfo *PK11_GetBestSlotMultipleWithAttributes(CK_MECHANISM_TYPE *type,
CK_FLAGS *mechFlag, unsigned int *keySize,
unsigned int count, void *wincx);
PK11SlotInfo *PK11_GetBestSlotMultiple(CK_MECHANISM_TYPE *type,
unsigned int count, void *wincx);
PK11SlotInfo *PK11_GetBestSlot(CK_MECHANISM_TYPE type, void *wincx);
PK11SlotInfo *PK11_GetBestSlotWithAttributes(CK_MECHANISM_TYPE type,
CK_FLAGS mechFlag, unsigned int keySize, void *wincx);
CK_MECHANISM_TYPE PK11_GetBestWrapMechanism(PK11SlotInfo *slot);
int PK11_GetBestKeyLength(PK11SlotInfo *slot, CK_MECHANISM_TYPE type);
/*
* Open a new database using the softoken. The caller is responsible for making
* sure the module spec is correct and usable. The caller should ask for one
* new database per call if the caller wants to get meaningful information
* about the new database.
*
* moduleSpec is the same data that you would pass to softoken at
* initialization time under the 'tokens' options. For example, if you were
* to specify tokens=<0x4=[configdir='./mybackup' tokenDescription='Backup']>
* You would specify "configdir='./mybackup' tokenDescription='Backup'" as your
* module spec here. The slot ID will be calculated for you by
* SECMOD_OpenUserDB().
*
* Typical parameters here are configdir, tokenDescription and flags.
*
* a Full list is below:
*
*
* configDir - The location of the databases for this token. If configDir is
* not specified, and noCertDB and noKeyDB is not specified, the load
* will fail.
* certPrefix - Cert prefix for this token.
* keyPrefix - Prefix for the key database for this token. (if not specified,
* certPrefix will be used).
* tokenDescription - The label value for this token returned in the
* CK_TOKEN_INFO structure with an internationalize string (UTF8).
* This value will be truncated at 32 bytes (no NULL, partial UTF8
* characters dropped). You should specify a user friendly name here
* as this is the value the token will be referred to in most
* application UI's. You should make sure tokenDescription is unique.
* slotDescription - The slotDescription value for this token returned
* in the CK_SLOT_INFO structure with an internationalize string
* (UTF8). This value will be truncated at 64 bytes (no NULL, partial
* UTF8 characters dropped). This name will not change after the
* database is closed. It should have some number to make this unique.
* minPWLen - minimum password length for this token.
* flags - comma separated list of flag values, parsed case-insensitive.
* Valid flags are:
* readOnly - Databases should be opened read only.
* noCertDB - Don't try to open a certificate database.
* noKeyDB - Don't try to open a key database.
* forceOpen - Don't fail to initialize the token if the
* databases could not be opened.
* passwordRequired - zero length passwords are not acceptable
* (valid only if there is a keyDB).
* optimizeSpace - allocate smaller hash tables and lock tables.
* When this flag is not specified, Softoken will allocate
* large tables to prevent lock contention.
*/
PK11SlotInfo *SECMOD_OpenUserDB(const char *moduleSpec);
SECStatus SECMOD_CloseUserDB(PK11SlotInfo *slot);
/*
* This is exactly the same as OpenUserDB except it can be called on any
* module that understands softoken style new slot entries. The resulting
* slot can be closed using SECMOD_CloseUserDB above. Value of moduleSpec
* is token specific.
*/
PK11SlotInfo *SECMOD_OpenNewSlot(SECMODModule *mod, const char *moduleSpec);
/*
* merge the permanent objects from on token to another
*/
SECStatus PK11_MergeTokens(PK11SlotInfo *targetSlot, PK11SlotInfo *sourceSlot,
PK11MergeLog *log, void *targetPwArg, void *sourcePwArg);
/*
* create and destroy merge logs needed by PK11_MergeTokens
*/
PK11MergeLog *PK11_CreateMergeLog(void);
void PK11_DestroyMergeLog(PK11MergeLog *log);
/*********************************************************************
* Mechanism Mapping functions
*********************************************************************/
CK_KEY_TYPE PK11_GetKeyType(CK_MECHANISM_TYPE type, unsigned long len);
CK_MECHANISM_TYPE PK11_GetKeyGen(CK_MECHANISM_TYPE type);
int PK11_GetBlockSize(CK_MECHANISM_TYPE type, SECItem *params);
int PK11_GetIVLength(CK_MECHANISM_TYPE type);
SECItem *PK11_ParamFromIV(CK_MECHANISM_TYPE type, SECItem *iv);
unsigned char *PK11_IVFromParam(CK_MECHANISM_TYPE type, SECItem *param, int *len);
SECItem *PK11_BlockData(SECItem *data, unsigned long size);
/* PKCS #11 to DER mapping functions */
SECItem *PK11_ParamFromAlgid(SECAlgorithmID *algid);
SECItem *PK11_GenerateNewParam(CK_MECHANISM_TYPE, PK11SymKey *);
CK_MECHANISM_TYPE PK11_AlgtagToMechanism(SECOidTag algTag);
SECOidTag PK11_MechanismToAlgtag(CK_MECHANISM_TYPE type);
SECOidTag PK11_FortezzaMapSig(SECOidTag algTag);
SECStatus PK11_ParamToAlgid(SECOidTag algtag, SECItem *param,
PLArenaPool *arena, SECAlgorithmID *algid);
SECStatus PK11_SeedRandom(PK11SlotInfo *, unsigned char *data, int len);
SECStatus PK11_GenerateRandomOnSlot(PK11SlotInfo *, unsigned char *data, int len);
SECStatus PK11_RandomUpdate(void *data, size_t bytes);
SECStatus PK11_GenerateRandom(unsigned char *data, int len);
/* warning: cannot work with pkcs 5 v2
* use algorithm ID s instead of pkcs #11 mechanism pointers */
CK_RV PK11_MapPBEMechanismToCryptoMechanism(CK_MECHANISM_PTR pPBEMechanism,
CK_MECHANISM_PTR pCryptoMechanism,
SECItem *pbe_pwd, PRBool bad3DES);
CK_MECHANISM_TYPE PK11_GetPadMechanism(CK_MECHANISM_TYPE);
CK_MECHANISM_TYPE PK11_MapSignKeyType(KeyType keyType);
/**********************************************************************
* Symmetric, Public, and Private Keys
**********************************************************************/
void PK11_FreeSymKey(PK11SymKey *key);
PK11SymKey *PK11_ReferenceSymKey(PK11SymKey *symKey);
PK11SymKey *PK11_ImportSymKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
PK11Origin origin, CK_ATTRIBUTE_TYPE operation, SECItem *key, void *wincx);
PK11SymKey *PK11_ImportSymKeyWithFlags(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, PK11Origin origin, CK_ATTRIBUTE_TYPE operation,
SECItem *key, CK_FLAGS flags, PRBool isPerm, void *wincx);
PK11SymKey *PK11_SymKeyFromHandle(PK11SlotInfo *slot, PK11SymKey *parent,
PK11Origin origin, CK_MECHANISM_TYPE type, CK_OBJECT_HANDLE keyID,
PRBool owner, void *wincx);
PK11SymKey *PK11_GetWrapKey(PK11SlotInfo *slot, int wrap,
CK_MECHANISM_TYPE type, int series, void *wincx);
/*
* This function is not thread-safe. It can only be called when only
* one thread has a reference to wrapKey.
*/
void PK11_SetWrapKey(PK11SlotInfo *slot, int wrap, PK11SymKey *wrapKey);
CK_MECHANISM_TYPE PK11_GetMechanism(PK11SymKey *symKey);
/*
* import a public key into the desired slot
*
* This function takes a public key structure and creates a public key in a
* given slot. If isToken is set, then a persistant public key is created.
*
* Note: it is possible for this function to return a handle for a key which
* is persistant, even if isToken is not set.
*/
CK_OBJECT_HANDLE PK11_ImportPublicKey(PK11SlotInfo *slot,
SECKEYPublicKey *pubKey, PRBool isToken);
PK11SymKey *PK11_KeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
SECItem *param, int keySize, void *wincx);
PK11SymKey *PK11_TokenKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
SECItem *param, int keySize, SECItem *keyid,
PRBool isToken, void *wincx);
PK11SymKey *PK11_TokenKeyGenWithFlags(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, SECItem *param,
int keySize, SECItem *keyid, CK_FLAGS opFlags,
PK11AttrFlags attrFlags, void *wincx);
/* Generates a key using the exact template supplied by the caller. The other
* PK11_[Token]KeyGen mechanisms should be used instead of this one whenever
* they work because they include/exclude the CKA_VALUE_LEN template value
* based on the mechanism type as required by many tokens.
*
* keyGenType should be PK11_GetKeyGenWithSize(type, <key size>) or it should
* be equal to type if PK11_GetKeyGenWithSize cannot be used (e.g. because
* pk11wrap does not know about the mechanisms).
*/
PK11SymKey *PK11_KeyGenWithTemplate(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_MECHANISM_TYPE keyGenType,
SECItem *param, CK_ATTRIBUTE *attrs,
unsigned int attrsCount, void *wincx);
PK11SymKey *PK11_ListFixedKeysInSlot(PK11SlotInfo *slot, char *nickname,
void *wincx);
PK11SymKey *PK11_GetNextSymKey(PK11SymKey *symKey);
CK_KEY_TYPE PK11_GetSymKeyType(PK11SymKey *key);
CK_OBJECT_HANDLE PK11_GetSymKeyHandle(PK11SymKey *symKey);
/*
* PK11_SetSymKeyUserData
* sets generic user data on keys (usually a pointer to a data structure)
* that can later be retrieved by PK11_GetSymKeyUserData().
* symKey - key where data will be set.
* data - data to be set.
* freefunc - function used to free the data.
* Setting user data on symKeys with existing user data already set will cause
* the existing user data to be freed before the new user data is set.
* Freeing user data is done by calling the user specified freefunc.
* If freefunc is NULL, the user data is assumed to be global or static an
* not freed. Passing NULL for user data to PK11_SetSymKeyUserData has the
* effect of freeing any existing user data, and clearing the user data
* pointer. If user data exists when the symKey is finally freed, that
* data will be freed with freefunc.
*
* Applications should only use this function on keys which the application
* has created directly, as there is only one user data value per key.
*/
void PK11_SetSymKeyUserData(PK11SymKey *symKey, void *data,
PK11FreeDataFunc freefunc);
/* PK11_GetSymKeyUserData
* retrieves generic user data which was set on a key by
* PK11_SetSymKeyUserData.
* symKey - key with data to be fetched
*
* If no data exists, or the data has been cleared, PK11_GetSymKeyUserData
* will return NULL. Returned data is still owned and managed by the SymKey,
* the caller should not free the data.
*
*/
void *PK11_GetSymKeyUserData(PK11SymKey *symKey);
SECStatus PK11_PubWrapSymKey(CK_MECHANISM_TYPE type, SECKEYPublicKey *pubKey,
PK11SymKey *symKey, SECItem *wrappedKey);
SECStatus PK11_WrapSymKey(CK_MECHANISM_TYPE type, SECItem *params,
PK11SymKey *wrappingKey, PK11SymKey *symKey, SECItem *wrappedKey);
/* move a key to 'slot' optionally set the key attributes according to either
* operation or the flags and making the key permanent at the same time.
* If the key is moved to the same slot, operation and flags values are
* currently ignored */
PK11SymKey *PK11_MoveSymKey(PK11SlotInfo *slot, CK_ATTRIBUTE_TYPE operation,
CK_FLAGS flags, PRBool perm, PK11SymKey *symKey);
/*
* derive a new key from the base key.
* PK11_Derive returns a key which can do exactly one operation, and is
* ephemeral (session key).
* PK11_DeriveWithFlags is the same as PK11_Derive, except you can use
* CKF_ flags to enable more than one operation.
* PK11_DeriveWithFlagsPerm is the same as PK11_DeriveWithFlags except you can
* (optionally) make the key permanent (token key).
*/
PK11SymKey *PK11_Derive(PK11SymKey *baseKey, CK_MECHANISM_TYPE mechanism,
SECItem *param, CK_MECHANISM_TYPE target,
CK_ATTRIBUTE_TYPE operation, int keySize);
PK11SymKey *PK11_DeriveWithFlags(PK11SymKey *baseKey,
CK_MECHANISM_TYPE derive, SECItem *param, CK_MECHANISM_TYPE target,
CK_ATTRIBUTE_TYPE operation, int keySize, CK_FLAGS flags);
PK11SymKey *PK11_DeriveWithFlagsPerm(PK11SymKey *baseKey,
CK_MECHANISM_TYPE derive,
SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
int keySize, CK_FLAGS flags, PRBool isPerm);
PK11SymKey *
PK11_DeriveWithTemplate(PK11SymKey *baseKey, CK_MECHANISM_TYPE derive,
SECItem *param, CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
int keySize, CK_ATTRIBUTE *userAttr, unsigned int numAttrs,
PRBool isPerm);
PK11SymKey *PK11_PubDerive(SECKEYPrivateKey *privKey,
SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB,
CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
CK_ATTRIBUTE_TYPE operation, int keySize, void *wincx);
PK11SymKey *PK11_PubDeriveWithKDF(SECKEYPrivateKey *privKey,
SECKEYPublicKey *pubKey, PRBool isSender, SECItem *randomA, SECItem *randomB,
CK_MECHANISM_TYPE derive, CK_MECHANISM_TYPE target,
CK_ATTRIBUTE_TYPE operation, int keySize,
CK_ULONG kdf, SECItem *sharedData, void *wincx);
/*
* unwrap a new key with a symetric key.
* PK11_Unwrap returns a key which can do exactly one operation, and is
* ephemeral (session key).
* PK11_UnwrapWithFlags is the same as PK11_Unwrap, except you can use
* CKF_ flags to enable more than one operation.
* PK11_UnwrapWithFlagsPerm is the same as PK11_UnwrapWithFlags except you can
* (optionally) make the key permanent (token key).
*/
PK11SymKey *PK11_UnwrapSymKey(PK11SymKey *key,
CK_MECHANISM_TYPE wraptype, SECItem *param, SECItem *wrapppedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize);
PK11SymKey *PK11_UnwrapSymKeyWithFlags(PK11SymKey *wrappingKey,
CK_MECHANISM_TYPE wrapType, SECItem *param, SECItem *wrappedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize,
CK_FLAGS flags);
PK11SymKey *PK11_UnwrapSymKeyWithFlagsPerm(PK11SymKey *wrappingKey,
CK_MECHANISM_TYPE wrapType,
SECItem *param, SECItem *wrappedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation,
int keySize, CK_FLAGS flags, PRBool isPerm);
/*
* unwrap a new key with a private key.
* PK11_PubUnwrap returns a key which can do exactly one operation, and is
* ephemeral (session key).
* PK11_PubUnwrapWithFlagsPerm is the same as PK11_PubUnwrap except you can
* use * CKF_ flags to enable more than one operation, and optionally make
* the key permanent (token key).
*/
PK11SymKey *PK11_PubUnwrapSymKey(SECKEYPrivateKey *key, SECItem *wrapppedKey,
CK_MECHANISM_TYPE target, CK_ATTRIBUTE_TYPE operation, int keySize);
PK11SymKey *PK11_PubUnwrapSymKeyWithFlagsPerm(SECKEYPrivateKey *wrappingKey,
SECItem *wrappedKey, CK_MECHANISM_TYPE target,
CK_ATTRIBUTE_TYPE operation, int keySize,
CK_FLAGS flags, PRBool isPerm);
PK11SymKey *PK11_FindFixedKey(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
SECItem *keyID, void *wincx);
SECStatus PK11_DeleteTokenPrivateKey(SECKEYPrivateKey *privKey, PRBool force);
SECStatus PK11_DeleteTokenPublicKey(SECKEYPublicKey *pubKey);
SECStatus PK11_DeleteTokenSymKey(PK11SymKey *symKey);
SECStatus PK11_DeleteTokenCertAndKey(CERTCertificate *cert, void *wincx);
SECKEYPrivateKey *PK11_LoadPrivKey(PK11SlotInfo *slot,
SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey,
PRBool token, PRBool sensitive);
char *PK11_GetSymKeyNickname(PK11SymKey *symKey);
char *PK11_GetPrivateKeyNickname(SECKEYPrivateKey *privKey);
char *PK11_GetPublicKeyNickname(SECKEYPublicKey *pubKey);
SECStatus PK11_SetSymKeyNickname(PK11SymKey *symKey, const char *nickname);
SECStatus PK11_SetPrivateKeyNickname(SECKEYPrivateKey *privKey,
const char *nickname);
SECStatus PK11_SetPublicKeyNickname(SECKEYPublicKey *pubKey,
const char *nickname);
/*
* Using __PK11_SetCertificateNickname is *DANGEROUS*.
*
* The API will update the NSS database, but it *will NOT* update the in-memory data.
* As a result, after calling this API, there will be INCONSISTENCY between
* in-memory data and the database.
*
* Use of the API should be limited to short-lived tools, which will exit immediately
* after using this API.
*
* If you ignore this warning, your process is TAINTED and will most likely misbehave.
*/
SECStatus __PK11_SetCertificateNickname(CERTCertificate *cert,
const char *nickname);
/* size to hold key in bytes */
unsigned int PK11_GetKeyLength(PK11SymKey *key);
/* size of actual secret parts of key in bits */
/* algid is because RC4 strength is determined by the effective bits as well
* as the key bits */
unsigned int PK11_GetKeyStrength(PK11SymKey *key, SECAlgorithmID *algid);
SECStatus PK11_ExtractKeyValue(PK11SymKey *symKey);
SECItem *PK11_GetKeyData(PK11SymKey *symKey);
PK11SlotInfo *PK11_GetSlotFromKey(PK11SymKey *symKey);
void *PK11_GetWindow(PK11SymKey *symKey);
/*
* Explicitly set the key usage for the generated private key.
*
* This allows us to specify single use EC and RSA keys whose usage
* can be regulated by the underlying token.
*
* The underlying key usage is set using opFlags. opFlagsMask specifies
* which operations are specified by opFlags. For instance to turn encrypt
* on and signing off, opFlags would be CKF_ENCRYPT|CKF_DECRYPT and
* opFlagsMask would be CKF_ENCRYPT|CKF_DECRYPT|CKF_SIGN|CKF_VERIFY. You
* need to specify both the public and private key flags,
* PK11_GenerateKeyPairWithOpFlags will sort out the correct flag to the
* correct key type. Flags not specified in opFlagMask will be defaulted
* according to mechanism type and token capabilities.
*/
SECKEYPrivateKey *PK11_GenerateKeyPairWithOpFlags(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk,
PK11AttrFlags attrFlags, CK_FLAGS opFlags, CK_FLAGS opFlagsMask,
void *wincx);
/*
* The attrFlags is the logical OR of the PK11_ATTR_XXX bitflags.
* These flags apply to the private key. The PK11_ATTR_TOKEN,
* PK11_ATTR_SESSION, PK11_ATTR_MODIFIABLE, and PK11_ATTR_UNMODIFIABLE
* flags also apply to the public key.
*/
SECKEYPrivateKey *PK11_GenerateKeyPairWithFlags(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk,
PK11AttrFlags attrFlags, void *wincx);
SECKEYPrivateKey *PK11_GenerateKeyPair(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubk,
PRBool isPerm, PRBool isSensitive, void *wincx);
SECKEYPrivateKey *PK11_FindPrivateKeyFromCert(PK11SlotInfo *slot,
CERTCertificate *cert, void *wincx);
SECKEYPrivateKey *PK11_FindKeyByAnyCert(CERTCertificate *cert, void *wincx);
SECKEYPrivateKey *PK11_FindKeyByKeyID(PK11SlotInfo *slot, SECItem *keyID,
void *wincx);
int PK11_GetPrivateModulusLen(SECKEYPrivateKey *key);
SECStatus PK11_Decrypt(PK11SymKey *symkey,
CK_MECHANISM_TYPE mechanism, SECItem *param,
unsigned char *out, unsigned int *outLen,
unsigned int maxLen,
const unsigned char *enc, unsigned int encLen);
SECStatus PK11_Encrypt(PK11SymKey *symKey,
CK_MECHANISM_TYPE mechanism, SECItem *param,
unsigned char *out, unsigned int *outLen,
unsigned int maxLen,
const unsigned char *data, unsigned int dataLen);
/* note: despite the name, this function takes a private key. */
SECStatus PK11_PubDecryptRaw(SECKEYPrivateKey *key,
unsigned char *data, unsigned *outLen,
unsigned int maxLen,
const unsigned char *enc, unsigned encLen);
#define PK11_PrivDecryptRaw PK11_PubDecryptRaw
/* The encrypt function that complements the above decrypt function. */
SECStatus PK11_PubEncryptRaw(SECKEYPublicKey *key,
unsigned char *enc,
const unsigned char *data, unsigned dataLen,
void *wincx);
SECStatus PK11_PrivDecryptPKCS1(SECKEYPrivateKey *key,
unsigned char *data, unsigned *outLen,
unsigned int maxLen,
const unsigned char *enc, unsigned encLen);
/* The encrypt function that complements the above decrypt function. */
SECStatus PK11_PubEncryptPKCS1(SECKEYPublicKey *key,
unsigned char *enc,
const unsigned char *data, unsigned dataLen,
void *wincx);
SECStatus PK11_PrivDecrypt(SECKEYPrivateKey *key,
CK_MECHANISM_TYPE mechanism, SECItem *param,
unsigned char *out, unsigned int *outLen,
unsigned int maxLen,
const unsigned char *enc, unsigned int encLen);
SECStatus PK11_PubEncrypt(SECKEYPublicKey *key,
CK_MECHANISM_TYPE mechanism, SECItem *param,
unsigned char *out, unsigned int *outLen,
unsigned int maxLen,
const unsigned char *data, unsigned int dataLen,
void *wincx);
SECStatus PK11_ImportPrivateKeyInfo(PK11SlotInfo *slot,
SECKEYPrivateKeyInfo *pki, SECItem *nickname,
SECItem *publicValue, PRBool isPerm, PRBool isPrivate,
unsigned int usage, void *wincx);
SECStatus PK11_ImportPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
SECKEYPrivateKeyInfo *pki, SECItem *nickname,
SECItem *publicValue, PRBool isPerm, PRBool isPrivate,
unsigned int usage, SECKEYPrivateKey **privk, void *wincx);
SECStatus PK11_ImportDERPrivateKeyInfo(PK11SlotInfo *slot,
SECItem *derPKI, SECItem *nickname,
SECItem *publicValue, PRBool isPerm, PRBool isPrivate,
unsigned int usage, void *wincx);
SECStatus PK11_ImportDERPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
SECItem *derPKI, SECItem *nickname,
SECItem *publicValue, PRBool isPerm, PRBool isPrivate,
unsigned int usage, SECKEYPrivateKey **privk, void *wincx);
SECStatus PK11_ImportEncryptedPrivateKeyInfo(PK11SlotInfo *slot,
SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
PRBool isPrivate, KeyType type,
unsigned int usage, void *wincx);
SECStatus PK11_ImportEncryptedPrivateKeyInfoAndReturnKey(PK11SlotInfo *slot,
SECKEYEncryptedPrivateKeyInfo *epki, SECItem *pwitem,
SECItem *nickname, SECItem *publicValue, PRBool isPerm,
PRBool isPrivate, KeyType type,
unsigned int usage, SECKEYPrivateKey **privk, void *wincx);
SECItem *PK11_ExportDERPrivateKeyInfo(SECKEYPrivateKey *pk, void *wincx);
SECKEYPrivateKeyInfo *PK11_ExportPrivKeyInfo(
SECKEYPrivateKey *pk, void *wincx);
SECKEYPrivateKeyInfo *PK11_ExportPrivateKeyInfo(
CERTCertificate *cert, void *wincx);
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivKeyInfo(
PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
SECKEYPrivateKey *pk, int iteration, void *wincx);
SECKEYEncryptedPrivateKeyInfo *PK11_ExportEncryptedPrivateKeyInfo(
PK11SlotInfo *slot, SECOidTag algTag, SECItem *pwitem,
CERTCertificate *cert, int iteration, void *wincx);
SECKEYPrivateKey *PK11_FindKeyByDERCert(PK11SlotInfo *slot,
CERTCertificate *cert, void *wincx);
SECKEYPublicKey *PK11_MakeKEAPubKey(unsigned char *data, int length);
SECStatus PK11_DigestKey(PK11Context *context, PK11SymKey *key);
PRBool PK11_VerifyKeyOK(PK11SymKey *key);
SECKEYPrivateKey *PK11_UnwrapPrivKey(PK11SlotInfo *slot,
PK11SymKey *wrappingKey, CK_MECHANISM_TYPE wrapType,
SECItem *param, SECItem *wrappedKey, SECItem *label,
SECItem *publicValue, PRBool token, PRBool sensitive,
CK_KEY_TYPE keyType, CK_ATTRIBUTE_TYPE *usage, int usageCount,
void *wincx);
SECStatus PK11_WrapPrivKey(PK11SlotInfo *slot, PK11SymKey *wrappingKey,
SECKEYPrivateKey *privKey, CK_MECHANISM_TYPE wrapType,
SECItem *param, SECItem *wrappedKey, void *wincx);
/*
* The caller of PK11_DEREncodePublicKey should free the returned SECItem with
* a SECITEM_FreeItem(..., PR_TRUE) call.
*/
SECItem *PK11_DEREncodePublicKey(const SECKEYPublicKey *pubk);
PK11SymKey *PK11_CopySymKeyForSigning(PK11SymKey *originalKey,
CK_MECHANISM_TYPE mech);
SECKEYPrivateKeyList *PK11_ListPrivKeysInSlot(PK11SlotInfo *slot,
char *nickname, void *wincx);
SECKEYPublicKeyList *PK11_ListPublicKeysInSlot(PK11SlotInfo *slot,
char *nickname);
SECKEYPQGParams *PK11_GetPQGParamsFromPrivateKey(SECKEYPrivateKey *privKey);
/* deprecated */
SECKEYPrivateKeyList *PK11_ListPrivateKeysInSlot(PK11SlotInfo *slot);
PK11SymKey *PK11_ConvertSessionSymKeyToTokenSymKey(PK11SymKey *symk,
void *wincx);
SECKEYPrivateKey *PK11_ConvertSessionPrivKeyToTokenPrivKey(
SECKEYPrivateKey *privk, void *wincx);
SECKEYPrivateKey *PK11_CopyTokenPrivKeyToSessionPrivKey(PK11SlotInfo *destSlot,
SECKEYPrivateKey *privKey);
/**********************************************************************
* Certs
**********************************************************************/
SECItem *PK11_MakeIDFromPubKey(SECItem *pubKeyData);
SECStatus PK11_TraverseSlotCerts(
SECStatus (*callback)(CERTCertificate *, SECItem *, void *),
void *arg, void *wincx);
CERTCertificate *PK11_FindCertFromNickname(const char *nickname, void *wincx);
CERTCertList *PK11_FindCertsFromEmailAddress(const char *email, void *wincx);
CERTCertList *PK11_FindCertsFromNickname(const char *nickname, void *wincx);
CERTCertificate *PK11_GetCertFromPrivateKey(SECKEYPrivateKey *privKey);
SECStatus PK11_ImportCert(PK11SlotInfo *slot, CERTCertificate *cert,
CK_OBJECT_HANDLE key, const char *nickname,
PRBool includeTrust);
SECStatus PK11_ImportDERCert(PK11SlotInfo *slot, SECItem *derCert,
CK_OBJECT_HANDLE key, char *nickname, PRBool includeTrust);
PK11SlotInfo *PK11_ImportCertForKey(CERTCertificate *cert,
const char *nickname, void *wincx);
PK11SlotInfo *PK11_ImportDERCertForKey(SECItem *derCert, char *nickname,
void *wincx);
PK11SlotInfo *PK11_KeyForCertExists(CERTCertificate *cert,
CK_OBJECT_HANDLE *keyPtr, void *wincx);
PK11SlotInfo *PK11_KeyForDERCertExists(SECItem *derCert,
CK_OBJECT_HANDLE *keyPtr, void *wincx);
CERTCertificate *PK11_FindCertByIssuerAndSN(PK11SlotInfo **slot,
CERTIssuerAndSN *sn, void *wincx);
CERTCertificate *PK11_FindCertAndKeyByRecipientList(PK11SlotInfo **slot,
SEC_PKCS7RecipientInfo **array, SEC_PKCS7RecipientInfo **rip,
SECKEYPrivateKey **privKey, void *wincx);
int PK11_FindCertAndKeyByRecipientListNew(NSSCMSRecipient **recipientlist,
void *wincx);
SECStatus PK11_TraverseCertsForSubjectInSlot(CERTCertificate *cert,
PK11SlotInfo *slot, SECStatus (*callback)(CERTCertificate *, void *),
void *arg);
CERTCertificate *PK11_FindCertFromDERCert(PK11SlotInfo *slot,
CERTCertificate *cert, void *wincx);
CERTCertificate *PK11_FindCertFromDERCertItem(PK11SlotInfo *slot,
const SECItem *derCert, void *wincx);
SECStatus PK11_ImportCertForKeyToSlot(PK11SlotInfo *slot, CERTCertificate *cert,
char *nickname, PRBool addUsage,
void *wincx);
CERTCertificate *PK11_FindBestKEAMatch(CERTCertificate *serverCert, void *wincx);
PRBool PK11_FortezzaHasKEA(CERTCertificate *cert);
CK_OBJECT_HANDLE PK11_FindCertInSlot(PK11SlotInfo *slot, CERTCertificate *cert,
void *wincx);
SECStatus PK11_TraverseCertsForNicknameInSlot(SECItem *nickname,
PK11SlotInfo *slot, SECStatus (*callback)(CERTCertificate *, void *),
void *arg);
CERTCertList *PK11_ListCerts(PK11CertListType type, void *pwarg);
CERTCertList *PK11_ListCertsInSlot(PK11SlotInfo *slot);
CERTSignedCrl *PK11_ImportCRL(PK11SlotInfo *slot, SECItem *derCRL, char *url,
int type, void *wincx, PRInt32 importOptions, PLArenaPool *arena, PRInt32 decodeOptions);
/**********************************************************************
* Sign/Verify
**********************************************************************/
/*
* Return the length in bytes of a signature generated with the
* private key.
*
* Return 0 or -1 on failure. (XXX Should we fix it to always return
* -1 on failure?)
*/
int PK11_SignatureLen(SECKEYPrivateKey *key);
PK11SlotInfo *PK11_GetSlotFromPrivateKey(SECKEYPrivateKey *key);
SECStatus PK11_Sign(SECKEYPrivateKey *key, SECItem *sig,
const SECItem *hash);
SECStatus PK11_SignWithMechanism(SECKEYPrivateKey *key,
CK_MECHANISM_TYPE mechanism,
const SECItem *param, SECItem *sig,
const SECItem *hash);
SECStatus PK11_SignWithSymKey(PK11SymKey *symKey, CK_MECHANISM_TYPE mechanism,
SECItem *param, SECItem *sig, const SECItem *data);
SECStatus PK11_VerifyRecover(SECKEYPublicKey *key, const SECItem *sig,
SECItem *dsig, void *wincx);
SECStatus PK11_Verify(SECKEYPublicKey *key, const SECItem *sig,
const SECItem *hash, void *wincx);
SECStatus PK11_VerifyWithMechanism(SECKEYPublicKey *key,
CK_MECHANISM_TYPE mechanism,
const SECItem *param, const SECItem *sig,
const SECItem *hash, void *wincx);
/**********************************************************************
* Crypto Contexts
**********************************************************************/
void PK11_DestroyContext(PK11Context *context, PRBool freeit);
PK11Context *PK11_CreateContextBySymKey(CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, PK11SymKey *symKey, SECItem *param);
PK11Context *PK11_CreateDigestContext(SECOidTag hashAlg);
PK11Context *PK11_CloneContext(PK11Context *old);
SECStatus PK11_DigestBegin(PK11Context *cx);
/*
* The output buffer 'out' must be big enough to hold the output of
* the hash algorithm 'hashAlg'.
*/
SECStatus PK11_HashBuf(SECOidTag hashAlg, unsigned char *out,
const unsigned char *in, PRInt32 len);
SECStatus PK11_DigestOp(PK11Context *context, const unsigned char *in,
unsigned len);
SECStatus PK11_CipherOp(PK11Context *context, unsigned char *out, int *outlen,
int maxout, const unsigned char *in, int inlen);
SECStatus PK11_Finalize(PK11Context *context);
SECStatus PK11_DigestFinal(PK11Context *context, unsigned char *data,
unsigned int *outLen, unsigned int length);
#define PK11_CipherFinal PK11_DigestFinal
SECStatus PK11_SaveContext(PK11Context *cx, unsigned char *save,
int *len, int saveLength);
/* Save the context's state, with possible allocation.
* The caller may supply an already allocated buffer in preAllocBuf,
* with length pabLen. If the buffer is large enough for the context's
* state, it will receive the state.
* If the buffer is not large enough (or NULL), then a new buffer will
* be allocated with PORT_Alloc.
* In either case, the state will be returned as a buffer, and the length
* of the state will be given in *stateLen.
*/
unsigned char *
PK11_SaveContextAlloc(PK11Context *cx,
unsigned char *preAllocBuf, unsigned int pabLen,
unsigned int *stateLen);
SECStatus PK11_RestoreContext(PK11Context *cx, unsigned char *save, int len);
SECStatus PK11_GenerateFortezzaIV(PK11SymKey *symKey, unsigned char *iv, int len);
void PK11_SetFortezzaHack(PK11SymKey *symKey);
/**********************************************************************
* PBE functions
**********************************************************************/
/* This function creates PBE parameters from the given inputs. The result
* can be used to create a password integrity key for PKCS#12, by sending
* the return value to PK11_KeyGen along with the appropriate mechanism.
*/
SECItem *
PK11_CreatePBEParams(SECItem *salt, SECItem *pwd, unsigned int iterations);
/* free params created above (can be called after keygen is done */
void PK11_DestroyPBEParams(SECItem *params);
SECAlgorithmID *
PK11_CreatePBEAlgorithmID(SECOidTag algorithm, int iteration, SECItem *salt);
/* use to create PKCS5 V2 algorithms with finder control than that provided
* by PK11_CreatePBEAlgorithmID. */
SECAlgorithmID *
PK11_CreatePBEV2AlgorithmID(SECOidTag pbeAlgTag, SECOidTag cipherAlgTag,
SECOidTag prfAlgTag, int keyLength, int iteration,
SECItem *salt);
PK11SymKey *
PK11_PBEKeyGen(PK11SlotInfo *slot, SECAlgorithmID *algid, SECItem *pwitem,
PRBool faulty3DES, void *wincx);
/* warning: cannot work with PKCS 5 v2 use PK11_PBEKeyGen instead */
PK11SymKey *
PK11_RawPBEKeyGen(PK11SlotInfo *slot, CK_MECHANISM_TYPE type, SECItem *params,
SECItem *pwitem, PRBool faulty3DES, void *wincx);
SECItem *
PK11_GetPBEIV(SECAlgorithmID *algid, SECItem *pwitem);
/*
* Get the Mechanism and parameter of the base encryption or mac scheme from
* a PBE algorithm ID.
* Caller is responsible for freeing the return parameter (param).
*/
CK_MECHANISM_TYPE
PK11_GetPBECryptoMechanism(SECAlgorithmID *algid,
SECItem **param, SECItem *pwd);
/**********************************************************************
* Functions to manage secmod flags
**********************************************************************/
const PK11DefaultArrayEntry *PK11_GetDefaultArray(int *size);
SECStatus PK11_UpdateSlotAttribute(PK11SlotInfo *slot,
const PK11DefaultArrayEntry *entry,
PRBool add);
/**********************************************************************
* Functions to look at PKCS #11 dependent data
**********************************************************************/
PK11GenericObject *PK11_FindGenericObjects(PK11SlotInfo *slot,
CK_OBJECT_CLASS objClass);
PK11GenericObject *PK11_GetNextGenericObject(PK11GenericObject *object);
PK11GenericObject *PK11_GetPrevGenericObject(PK11GenericObject *object);
SECStatus PK11_UnlinkGenericObject(PK11GenericObject *object);
SECStatus PK11_LinkGenericObject(PK11GenericObject *list,
PK11GenericObject *object);
SECStatus PK11_DestroyGenericObjects(PK11GenericObject *object);
SECStatus PK11_DestroyGenericObject(PK11GenericObject *object);
PK11GenericObject *PK11_CreateGenericObject(PK11SlotInfo *slot,
const CK_ATTRIBUTE *pTemplate,
int count, PRBool token);
/*
* PK11_ReadRawAttribute and PK11_WriteRawAttribute are generic
* functions to read and modify the actual PKCS #11 attributes of
* the underlying pkcs #11 object.
*
* object is a pointer to an NSS object that represents the underlying
* PKCS #11 object. It's type must match the type of PK11ObjectType
* as follows:
*
* type object
* PK11_TypeGeneric PK11GenericObject *
* PK11_TypePrivKey SECKEYPrivateKey *
* PK11_TypePubKey SECKEYPublicKey *
* PK11_TypeSymKey PK11SymKey *
*
* All other types are considered invalid. If type does not match the object
* passed, unpredictable results will occur.
*
* PK11_ReadRawAttribute allocates the buffer for returning the attribute
* value. The caller of PK11_ReadRawAttribute should free the data buffer
* pointed to by item using a SECITEM_FreeItem(item, PR_FALSE) or
* PORT_Free(item->data) call.
*/
SECStatus PK11_ReadRawAttribute(PK11ObjectType type, void *object,
CK_ATTRIBUTE_TYPE attr, SECItem *item);
SECStatus PK11_WriteRawAttribute(PK11ObjectType type, void *object,
CK_ATTRIBUTE_TYPE attr, SECItem *item);
/*
* PK11_GetAllSlotsForCert returns all the slots that a given certificate
* exists on, since it's possible for a cert to exist on more than one
* PKCS#11 token.
*/
PK11SlotList *
PK11_GetAllSlotsForCert(CERTCertificate *cert, void *arg);
/**********************************************************************
* New functions which are already deprecated....
**********************************************************************/
SECItem *
PK11_GetLowLevelKeyIDForCert(PK11SlotInfo *slot,
CERTCertificate *cert, void *pwarg);
SECItem *
PK11_GetLowLevelKeyIDForPrivateKey(SECKEYPrivateKey *key);
PRBool SECMOD_HasRootCerts(void);
SEC_END_PROTOS
#endif

View file

@ -0,0 +1,437 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "seccomon.h"
#include "secoid.h"
#include "secasn1.h"
#include "pkcs11.h"
#include "pk11func.h"
#include "pk11sdr.h"
/*
* Data structure and template for encoding the result of an SDR operation
* This is temporary. It should include the algorithm ID of the encryption mechanism
*/
struct SDRResult {
SECItem keyid;
SECAlgorithmID alg;
SECItem data;
};
typedef struct SDRResult SDRResult;
SEC_ASN1_MKSUB(SECOID_AlgorithmIDTemplate)
static SEC_ASN1Template template[] = {
{ SEC_ASN1_SEQUENCE, 0, NULL, sizeof(SDRResult) },
{ SEC_ASN1_OCTET_STRING, offsetof(SDRResult, keyid) },
{ SEC_ASN1_INLINE | SEC_ASN1_XTRN, offsetof(SDRResult, alg),
SEC_ASN1_SUB(SECOID_AlgorithmIDTemplate) },
{ SEC_ASN1_OCTET_STRING, offsetof(SDRResult, data) },
{ 0 }
};
static unsigned char keyID[] = {
0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
};
static SECItem keyIDItem = {
0,
keyID,
sizeof keyID
};
/* local utility function for padding an incoming data block
* to the mechanism block size.
*/
static SECStatus
padBlock(SECItem *data, int blockSize, SECItem *result)
{
SECStatus rv = SECSuccess;
int padLength;
unsigned int i;
result->data = 0;
result->len = 0;
/* This algorithm always adds to the block (to indicate the number
* of pad bytes). So allocate a block large enough.
*/
padLength = blockSize - (data->len % blockSize);
result->len = data->len + padLength;
result->data = (unsigned char *)PORT_Alloc(result->len);
/* Copy the data */
PORT_Memcpy(result->data, data->data, data->len);
/* Add the pad values */
for (i = data->len; i < result->len; i++)
result->data[i] = (unsigned char)padLength;
return rv;
}
static SECStatus
unpadBlock(SECItem *data, int blockSize, SECItem *result)
{
SECStatus rv = SECSuccess;
int padLength;
unsigned int i;
result->data = 0;
result->len = 0;
/* Remove the padding from the end if the input data */
if (data->len == 0 || data->len % blockSize != 0) {
rv = SECFailure;
goto loser;
}
padLength = data->data[data->len - 1];
if (padLength > blockSize) {
rv = SECFailure;
goto loser;
}
/* verify padding */
for (i = data->len - padLength; i < data->len; i++) {
if (data->data[i] != padLength) {
rv = SECFailure;
goto loser;
}
}
result->len = data->len - padLength;
result->data = (unsigned char *)PORT_Alloc(result->len);
if (!result->data) {
rv = SECFailure;
goto loser;
}
PORT_Memcpy(result->data, data->data, result->len);
if (padLength < 2) {
return SECWouldBlock;
}
loser:
return rv;
}
static PRLock *pk11sdrLock = NULL;
void
pk11sdr_Init(void)
{
pk11sdrLock = PR_NewLock();
}
void
pk11sdr_Shutdown(void)
{
if (pk11sdrLock) {
PR_DestroyLock(pk11sdrLock);
pk11sdrLock = NULL;
}
}
/*
* PK11SDR_Encrypt
* Encrypt a block of data using the symmetric key identified. The result
* is an ASN.1 (DER) encoded block of keyid, params and data.
*/
SECStatus
PK11SDR_Encrypt(SECItem *keyid, SECItem *data, SECItem *result, void *cx)
{
SECStatus rv = SECSuccess;
PK11SlotInfo *slot = 0;
PK11SymKey *key = 0;
SECItem *params = 0;
PK11Context *ctx = 0;
CK_MECHANISM_TYPE type;
SDRResult sdrResult;
SECItem paddedData;
SECItem *pKeyID;
PLArenaPool *arena = 0;
/* Initialize */
paddedData.len = 0;
paddedData.data = 0;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (!arena) {
rv = SECFailure;
goto loser;
}
/* 1. Locate the requested keyid, or the default key (which has a keyid)
* 2. Create an encryption context
* 3. Encrypt
* 4. Encode the results (using ASN.1)
*/
slot = PK11_GetInternalKeySlot();
if (!slot) {
rv = SECFailure;
goto loser;
}
/* Use triple-DES */
type = CKM_DES3_CBC;
/*
* Login to the internal token before we look for the key, otherwise we
* won't find it.
*/
rv = PK11_Authenticate(slot, PR_TRUE, cx);
if (rv != SECSuccess)
goto loser;
/* Find the key to use */
pKeyID = keyid;
if (pKeyID->len == 0) {
pKeyID = &keyIDItem; /* Use default value */
/* put in a course lock to prevent a race between not finding the
* key and creating one.
*/
if (pk11sdrLock)
PR_Lock(pk11sdrLock);
/* Try to find the key */
key = PK11_FindFixedKey(slot, type, pKeyID, cx);
/* If the default key doesn't exist yet, try to create it */
if (!key)
key = PK11_GenDES3TokenKey(slot, pKeyID, cx);
if (pk11sdrLock)
PR_Unlock(pk11sdrLock);
} else {
key = PK11_FindFixedKey(slot, type, pKeyID, cx);
}
if (!key) {
rv = SECFailure;
goto loser;
}
params = PK11_GenerateNewParam(type, key);
if (!params) {
rv = SECFailure;
goto loser;
}
ctx = PK11_CreateContextBySymKey(type, CKA_ENCRYPT, key, params);
if (!ctx) {
rv = SECFailure;
goto loser;
}
rv = padBlock(data, PK11_GetBlockSize(type, 0), &paddedData);
if (rv != SECSuccess)
goto loser;
sdrResult.data.len = paddedData.len;
sdrResult.data.data = (unsigned char *)PORT_ArenaAlloc(arena, sdrResult.data.len);
rv = PK11_CipherOp(ctx, sdrResult.data.data, (int *)&sdrResult.data.len, sdrResult.data.len,
paddedData.data, paddedData.len);
if (rv != SECSuccess)
goto loser;
PK11_Finalize(ctx);
sdrResult.keyid = *pKeyID;
rv = PK11_ParamToAlgid(SEC_OID_DES_EDE3_CBC, params, arena, &sdrResult.alg);
if (rv != SECSuccess)
goto loser;
if (!SEC_ASN1EncodeItem(0, result, &sdrResult, template)) {
rv = SECFailure;
goto loser;
}
loser:
SECITEM_ZfreeItem(&paddedData, PR_FALSE);
if (arena)
PORT_FreeArena(arena, PR_TRUE);
if (ctx)
PK11_DestroyContext(ctx, PR_TRUE);
if (params)
SECITEM_ZfreeItem(params, PR_TRUE);
if (key)
PK11_FreeSymKey(key);
if (slot)
PK11_FreeSlot(slot);
return rv;
}
/* decrypt a block */
static SECStatus
pk11Decrypt(PK11SlotInfo *slot, PLArenaPool *arena,
CK_MECHANISM_TYPE type, PK11SymKey *key,
SECItem *params, SECItem *in, SECItem *result)
{
PK11Context *ctx = 0;
SECItem paddedResult;
SECStatus rv;
paddedResult.len = 0;
paddedResult.data = 0;
ctx = PK11_CreateContextBySymKey(type, CKA_DECRYPT, key, params);
if (!ctx) {
rv = SECFailure;
goto loser;
}
paddedResult.len = in->len;
paddedResult.data = PORT_ArenaAlloc(arena, paddedResult.len);
rv = PK11_CipherOp(ctx, paddedResult.data,
(int *)&paddedResult.len, paddedResult.len,
in->data, in->len);
if (rv != SECSuccess)
goto loser;
PK11_Finalize(ctx);
/* Remove the padding */
rv = unpadBlock(&paddedResult, PK11_GetBlockSize(type, 0), result);
if (rv)
goto loser;
loser:
if (ctx)
PK11_DestroyContext(ctx, PR_TRUE);
return rv;
}
/*
* PK11SDR_Decrypt
* Decrypt a block of data produced by PK11SDR_Encrypt. The key used is identified
* by the keyid field within the input.
*/
SECStatus
PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx)
{
SECStatus rv = SECSuccess;
PK11SlotInfo *slot = 0;
PK11SymKey *key = 0;
CK_MECHANISM_TYPE type;
SDRResult sdrResult;
SECItem *params = 0;
SECItem possibleResult = { 0, NULL, 0 };
PLArenaPool *arena = 0;
arena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE);
if (!arena) {
rv = SECFailure;
goto loser;
}
/* Decode the incoming data */
memset(&sdrResult, 0, sizeof sdrResult);
rv = SEC_QuickDERDecodeItem(arena, &sdrResult, template, data);
if (rv != SECSuccess)
goto loser; /* Invalid format */
/* Find the slot and key for the given keyid */
slot = PK11_GetInternalKeySlot();
if (!slot) {
rv = SECFailure;
goto loser;
}
rv = PK11_Authenticate(slot, PR_TRUE, cx);
if (rv != SECSuccess)
goto loser;
/* Get the parameter values from the data */
params = PK11_ParamFromAlgid(&sdrResult.alg);
if (!params) {
rv = SECFailure;
goto loser;
}
/* Use triple-DES (Should look up the algorithm) */
type = CKM_DES3_CBC;
key = PK11_FindFixedKey(slot, type, &sdrResult.keyid, cx);
if (!key) {
rv = SECFailure;
} else {
rv = pk11Decrypt(slot, arena, type, key, params,
&sdrResult.data, result);
}
/*
* if the pad value was too small (1 or 2), then it's statistically
* 'likely' that (1 in 256) that we may not have the correct key.
* Check the other keys for a better match. If we find none, use
* this result.
*/
if (rv == SECWouldBlock) {
possibleResult = *result;
}
/*
* handle the case where your key indicies may have been broken
*/
if (rv != SECSuccess) {
PK11SymKey *keyList = PK11_ListFixedKeysInSlot(slot, NULL, cx);
PK11SymKey *testKey = NULL;
PK11SymKey *nextKey = NULL;
for (testKey = keyList; testKey;
testKey = PK11_GetNextSymKey(testKey)) {
rv = pk11Decrypt(slot, arena, type, testKey, params,
&sdrResult.data, result);
if (rv == SECSuccess) {
break;
}
/* found a close match. If it's our first remember it */
if (rv == SECWouldBlock) {
if (possibleResult.data) {
/* this is unlikely but possible. If we hit this condition,
* we have no way of knowing which possibility to prefer.
* in this case we just match the key the application
* thought was the right one */
SECITEM_ZfreeItem(result, PR_FALSE);
} else {
possibleResult = *result;
}
}
}
/* free the list */
for (testKey = keyList; testKey; testKey = nextKey) {
nextKey = PK11_GetNextSymKey(testKey);
PK11_FreeSymKey(testKey);
}
}
/* we didn't find a better key, use the one with a small pad value */
if ((rv != SECSuccess) && (possibleResult.data)) {
*result = possibleResult;
possibleResult.data = NULL;
rv = SECSuccess;
}
loser:
if (arena)
PORT_FreeArena(arena, PR_TRUE);
if (key)
PK11_FreeSymKey(key);
if (params)
SECITEM_ZfreeItem(params, PR_TRUE);
if (slot)
PK11_FreeSlot(slot);
if (possibleResult.data)
SECITEM_ZfreeItem(&possibleResult, PR_FALSE);
return rv;
}

View file

@ -0,0 +1,28 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _PK11SDR_H_
#define _PK11SDR_H_
#include "seccomon.h"
SEC_BEGIN_PROTOS
/*
* PK11SDR_Encrypt - encrypt data using the specified key id or SDR default
* result should be freed with SECItem_ZfreeItem
*/
SECStatus
PK11SDR_Encrypt(SECItem *keyid, SECItem *data, SECItem *result, void *cx);
/*
* PK11SDR_Decrypt - decrypt data previously encrypted with PK11SDR_Encrypt
* result should be freed with SECItem_ZfreeItem
*/
SECStatus
PK11SDR_Decrypt(SECItem *data, SECItem *result, void *cx);
SEC_END_PROTOS
#endif

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,51 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'includes': [
'../../coreconf/config.gypi'
],
'targets': [
{
'target_name': 'pk11wrap',
'type': 'static_library',
'sources': [
'dev3hack.c',
'pk11akey.c',
'pk11auth.c',
'pk11cert.c',
'pk11cxt.c',
'pk11err.c',
'pk11kea.c',
'pk11list.c',
'pk11load.c',
'pk11mech.c',
'pk11merge.c',
'pk11nobj.c',
'pk11obj.c',
'pk11pars.c',
'pk11pbe.c',
'pk11pk12.c',
'pk11pqg.c',
'pk11sdr.c',
'pk11skey.c',
'pk11slot.c',
'pk11util.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
]
}
],
'target_defaults': {
'defines': [
'SHLIB_SUFFIX=\"<(dll_suffix)\"',
'SHLIB_PREFIX=\"<(dll_prefix)\"',
'SHLIB_VERSION=\"3\"',
'SOFTOKEN_SHLIB_VERSION=\"3\"'
]
},
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,167 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SECMOD_H_
#define _SECMOD_H_
#include "seccomon.h"
#include "secmodt.h"
#include "prinrval.h"
/* These mechanisms flags are visible to all other libraries. */
/* They must be converted to internal SECMOD_*_FLAG */
/* if used inside the functions of the security library */
#define PUBLIC_MECH_RSA_FLAG 0x00000001ul
#define PUBLIC_MECH_DSA_FLAG 0x00000002ul
#define PUBLIC_MECH_RC2_FLAG 0x00000004ul
#define PUBLIC_MECH_RC4_FLAG 0x00000008ul
#define PUBLIC_MECH_DES_FLAG 0x00000010ul
#define PUBLIC_MECH_DH_FLAG 0x00000020ul
#define PUBLIC_MECH_FORTEZZA_FLAG 0x00000040ul
#define PUBLIC_MECH_RC5_FLAG 0x00000080ul
#define PUBLIC_MECH_SHA1_FLAG 0x00000100ul
#define PUBLIC_MECH_MD5_FLAG 0x00000200ul
#define PUBLIC_MECH_MD2_FLAG 0x00000400ul
#define PUBLIC_MECH_SSL_FLAG 0x00000800ul
#define PUBLIC_MECH_TLS_FLAG 0x00001000ul
#define PUBLIC_MECH_AES_FLAG 0x00002000ul
#define PUBLIC_MECH_SHA256_FLAG 0x00004000ul
#define PUBLIC_MECH_SHA512_FLAG 0x00008000ul
#define PUBLIC_MECH_CAMELLIA_FLAG 0x00010000ul
#define PUBLIC_MECH_SEED_FLAG 0x00020000ul
#define PUBLIC_MECH_ECC_FLAG 0x00040000ul
#define PUBLIC_MECH_RANDOM_FLAG 0x08000000ul
#define PUBLIC_MECH_FRIENDLY_FLAG 0x10000000ul
#define PUBLIC_OWN_PW_DEFAULTS 0X20000000ul
#define PUBLIC_DISABLE_FLAG 0x40000000ul
/* warning: reserved means reserved */
#define PUBLIC_MECH_RESERVED_FLAGS 0x87FF0000ul
/* These cipher flags are visible to all other libraries, */
/* But they must be converted before used in functions */
/* withing the security module */
#define PUBLIC_CIPHER_FORTEZZA_FLAG 0x00000001ul
/* warning: reserved means reserved */
#define PUBLIC_CIPHER_RESERVED_FLAGS 0xFFFFFFFEul
SEC_BEGIN_PROTOS
/*
* the following functions are going to be deprecated in NSS 4.0 in
* favor of the new stan functions.
*/
/* Initialization */
extern SECMODModule *SECMOD_LoadModule(char *moduleSpec, SECMODModule *parent,
PRBool recurse);
extern SECMODModule *SECMOD_LoadUserModule(char *moduleSpec, SECMODModule *parent,
PRBool recurse);
SECStatus SECMOD_UnloadUserModule(SECMODModule *mod);
SECMODModule *SECMOD_CreateModule(const char *lib, const char *name,
const char *param, const char *nss);
SECMODModule *SECMOD_CreateModuleEx(const char *lib, const char *name,
const char *param, const char *nss,
const char *config);
/*
* After a fork(), PKCS #11 says we need to call C_Initialize again in
* the child before we can use the module. This function causes this
* reinitialization.
* NOTE: Any outstanding handles will become invalid, which means your
* keys and contexts will fail, but new ones can be created.
*
* Setting 'force' to true means to do the reinitialization even if the
* PKCS #11 module does not seem to need it. This allows software modules
* which ignore fork to preserve their keys across the fork().
*/
SECStatus SECMOD_RestartModules(PRBool force);
/* Module Management */
char **SECMOD_GetModuleSpecList(SECMODModule *module);
SECStatus SECMOD_FreeModuleSpecList(SECMODModule *module, char **moduleSpecList);
/* protoypes */
/* Get a list of active PKCS #11 modules */
extern SECMODModuleList *SECMOD_GetDefaultModuleList(void);
/* Get a list of defined but not loaded PKCS #11 modules */
extern SECMODModuleList *SECMOD_GetDeadModuleList(void);
/* Get a list of Modules which define PKCS #11 modules to load */
extern SECMODModuleList *SECMOD_GetDBModuleList(void);
/* lock to protect all three module lists above */
extern SECMODListLock *SECMOD_GetDefaultModuleListLock(void);
extern SECStatus SECMOD_UpdateModule(SECMODModule *module);
/* lock management */
extern void SECMOD_GetReadLock(SECMODListLock *);
extern void SECMOD_ReleaseReadLock(SECMODListLock *);
/* Operate on modules by name */
extern SECMODModule *SECMOD_FindModule(const char *name);
extern SECStatus SECMOD_DeleteModule(const char *name, int *type);
extern SECStatus SECMOD_DeleteModuleEx(const char *name,
SECMODModule *mod,
int *type,
PRBool permdb);
extern SECStatus SECMOD_DeleteInternalModule(const char *name);
extern PRBool SECMOD_CanDeleteInternalModule(void);
extern SECStatus SECMOD_AddNewModule(const char *moduleName,
const char *dllPath,
unsigned long defaultMechanismFlags,
unsigned long cipherEnableFlags);
extern SECStatus SECMOD_AddNewModuleEx(const char *moduleName,
const char *dllPath,
unsigned long defaultMechanismFlags,
unsigned long cipherEnableFlags,
char *modparms,
char *nssparms);
/* database/memory management */
extern SECMODModule *SECMOD_GetInternalModule(void);
extern SECMODModule *SECMOD_ReferenceModule(SECMODModule *module);
extern void SECMOD_DestroyModule(SECMODModule *module);
extern PK11SlotInfo *SECMOD_LookupSlot(SECMODModuleID module,
unsigned long slotID);
extern PK11SlotInfo *SECMOD_FindSlot(SECMODModule *module, const char *name);
/* Funtion reports true if at least one of the modules */
/* of modType has been installed */
PRBool SECMOD_IsModulePresent(unsigned long int pubCipherEnableFlags);
/* accessors */
PRBool SECMOD_GetSkipFirstFlag(SECMODModule *mod);
PRBool SECMOD_GetDefaultModDBFlag(SECMODModule *mod);
/* Functions used to convert between internal & public representation
* of Mechanism Flags and Cipher Enable Flags */
extern unsigned long SECMOD_PubMechFlagstoInternal(unsigned long publicFlags);
extern unsigned long SECMOD_InternaltoPubMechFlags(unsigned long internalFlags);
extern unsigned long SECMOD_PubCipherFlagstoInternal(unsigned long publicFlags);
PRBool SECMOD_HasRemovableSlots(SECMODModule *mod);
PK11SlotInfo *SECMOD_WaitForAnyTokenEvent(SECMODModule *mod,
unsigned long flags, PRIntervalTime latency);
/*
* Warning: the SECMOD_CancelWait function is highly destructive, potentially
* finalizing the module 'mod' (causing inprogress operations to fail,
* and session key material to disappear). It should only be called when
* shutting down the module.
*/
SECStatus SECMOD_CancelWait(SECMODModule *mod);
/*
* check to see if the module has added new slots. PKCS 11 v2.20 allows for
* modules to add new slots, but never remove them. Slots not be added between
* a call to C_GetSlotLlist(Flag, NULL, &count) and the corresponding
* C_GetSlotList(flag, &data, &count) so that the array doesn't accidently
* grow on the caller. It is permissible for the slots to increase between
* corresponding calls with NULL to get the size.
*/
SECStatus SECMOD_UpdateSlotList(SECMODModule *mod);
SEC_END_PROTOS
#endif

View file

@ -0,0 +1,170 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Internal header file included only by files in pkcs11 dir, or in
* pkcs11 specific client and server files.
*/
#ifndef _SECMODI_H_
#define _SECMODI_H_ 1
#include "pkcs11.h"
#include "nssilock.h"
#include "secoidt.h"
#include "secdert.h"
#include "certt.h"
#include "secmodt.h"
#include "keyt.h"
SEC_BEGIN_PROTOS
/* proto-types */
extern SECStatus SECMOD_DeletePermDB(SECMODModule *module);
extern SECStatus SECMOD_AddPermDB(SECMODModule *module);
extern SECStatus SECMOD_Shutdown(void);
void nss_DumpModuleLog(void);
extern int secmod_PrivateModuleCount;
extern void SECMOD_Init(void);
SECStatus secmod_ModuleInit(SECMODModule *mod, SECMODModule **oldModule,
PRBool *alreadyLoaded);
/* list managment */
extern SECStatus SECMOD_AddModuleToList(SECMODModule *newModule);
extern SECStatus SECMOD_AddModuleToDBOnlyList(SECMODModule *newModule);
extern SECStatus SECMOD_AddModuleToUnloadList(SECMODModule *newModule);
extern void SECMOD_RemoveList(SECMODModuleList **, SECMODModuleList *);
extern void SECMOD_AddList(SECMODModuleList *, SECMODModuleList *, SECMODListLock *);
extern SECMODListLock *SECMOD_NewListLock(void);
extern void SECMOD_DestroyListLock(SECMODListLock *);
extern void SECMOD_GetWriteLock(SECMODListLock *);
extern void SECMOD_ReleaseWriteLock(SECMODListLock *);
/* Operate on modules by name */
extern SECMODModule *SECMOD_FindModuleByID(SECMODModuleID);
extern SECMODModule *secmod_FindModuleByFuncPtr(void *funcPtr);
/* database/memory management */
extern SECMODModuleList *SECMOD_NewModuleListElement(void);
extern SECMODModuleList *SECMOD_DestroyModuleListElement(SECMODModuleList *);
extern void SECMOD_DestroyModuleList(SECMODModuleList *);
extern SECStatus SECMOD_AddModule(SECMODModule *newModule);
extern unsigned long SECMOD_InternaltoPubCipherFlags(unsigned long internalFlags);
/* Library functions */
SECStatus secmod_LoadPKCS11Module(SECMODModule *, SECMODModule **oldModule);
SECStatus SECMOD_UnloadModule(SECMODModule *);
void SECMOD_SetInternalModule(SECMODModule *);
PRBool secmod_IsInternalKeySlot(SECMODModule *);
void secmod_SetInternalKeySlotFlag(SECMODModule *mod, PRBool val);
/* tools for checking if we are loading the same database twice */
typedef struct SECMODConfigListStr SECMODConfigList;
/* collect all the databases in a given spec */
SECMODConfigList *secmod_GetConfigList(PRBool isFIPS, char *spec, int *count);
/* see is a spec matches a database on the list */
PRBool secmod_MatchConfigList(const char *spec,
SECMODConfigList *conflist, int count);
/* returns the slot id from a module and modulespec */
CK_SLOT_ID secmod_GetSlotIDFromModuleSpec(const char *moduleSpec, SECMODModule *module);
/* free our list of databases */
void secmod_FreeConfigList(SECMODConfigList *conflist, int count);
/* parsing parameters */
/* returned char * must be freed by caller with PORT_Free */
/* children and ids are null terminated arrays which must be freed with
* secmod_FreeChildren */
char *secmod_ParseModuleSpecForTokens(PRBool convert,
PRBool isFIPS,
const char *moduleSpec,
char ***children,
CK_SLOT_ID **ids);
void secmod_FreeChildren(char **children, CK_SLOT_ID *ids);
char *secmod_MkAppendTokensList(PLArenaPool *arena, char *origModuleSpec,
char *newModuleSpec, CK_SLOT_ID newID,
char **children, CK_SLOT_ID *ids);
void SECMOD_SlotDestroyModule(SECMODModule *module, PRBool fromSlot);
CK_RV pk11_notify(CK_SESSION_HANDLE session, CK_NOTIFICATION event,
CK_VOID_PTR pdata);
void pk11_SignedToUnsigned(CK_ATTRIBUTE *attrib);
CK_OBJECT_HANDLE pk11_FindObjectByTemplate(PK11SlotInfo *slot,
CK_ATTRIBUTE *inTemplate, int tsize);
CK_OBJECT_HANDLE *pk11_FindObjectsByTemplate(PK11SlotInfo *slot,
CK_ATTRIBUTE *inTemplate, int tsize, int *objCount);
#define PK11_GETTAB(x) ((CK_FUNCTION_LIST_PTR)((x)->functionList))
#define PK11_SETATTRS(x, id, v, l) \
(x)->type = (id); \
(x)->pValue = (v); \
(x)->ulValueLen = (l);
SECStatus PK11_CreateNewObject(PK11SlotInfo *slot, CK_SESSION_HANDLE session,
const CK_ATTRIBUTE *theTemplate, int count,
PRBool token, CK_OBJECT_HANDLE *objectID);
SECStatus pbe_PK11AlgidToParam(SECAlgorithmID *algid, SECItem *mech);
SECStatus PBE_PK11ParamToAlgid(SECOidTag algTag, SECItem *param,
PLArenaPool *arena, SECAlgorithmID *algId);
PK11SymKey *pk11_TokenKeyGenWithFlagsAndKeyType(PK11SlotInfo *slot,
CK_MECHANISM_TYPE type, SECItem *param, CK_KEY_TYPE keyType,
int keySize, SECItem *keyId, CK_FLAGS opFlags,
PK11AttrFlags attrFlags, void *wincx);
CK_MECHANISM_TYPE pk11_GetPBECryptoMechanism(SECAlgorithmID *algid,
SECItem **param, SECItem *pwd, PRBool faulty3DES);
extern void pk11sdr_Init(void);
extern void pk11sdr_Shutdown(void);
/*
* Private to pk11wrap.
*/
PRBool pk11_LoginStillRequired(PK11SlotInfo *slot, void *wincx);
CK_SESSION_HANDLE pk11_GetNewSession(PK11SlotInfo *slot, PRBool *owner);
void pk11_CloseSession(PK11SlotInfo *slot, CK_SESSION_HANDLE sess, PRBool own);
PK11SymKey *pk11_ForceSlot(PK11SymKey *symKey, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation);
/* Convert key operation flags to PKCS #11 attributes. */
unsigned int pk11_OpFlagsToAttributes(CK_FLAGS flags,
CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue);
/* Check for bad (conflicting) attribute flags */
PRBool pk11_BadAttrFlags(PK11AttrFlags attrFlags);
/* Convert key attribute flags to PKCS #11 attributes. */
unsigned int pk11_AttrFlagsToAttributes(PK11AttrFlags attrFlags,
CK_ATTRIBUTE *attrs, CK_BBOOL *ckTrue, CK_BBOOL *ckFalse);
PRBool pk11_FindAttrInTemplate(CK_ATTRIBUTE *attr, unsigned int numAttrs,
CK_ATTRIBUTE_TYPE target);
CK_MECHANISM_TYPE pk11_mapWrapKeyType(KeyType keyType);
PK11SymKey *pk11_KeyExchange(PK11SlotInfo *slot, CK_MECHANISM_TYPE type,
CK_ATTRIBUTE_TYPE operation, CK_FLAGS flags, PRBool isPerm,
PK11SymKey *symKey);
PRBool pk11_HandleTrustObject(PK11SlotInfo *slot, CERTCertificate *cert,
CERTCertTrust *trust);
CK_OBJECT_HANDLE pk11_FindPubKeyByAnyCert(CERTCertificate *cert,
PK11SlotInfo **slot, void *wincx);
SECStatus pk11_AuthenticateUnfriendly(PK11SlotInfo *slot, PRBool loadCerts,
void *wincx);
int PK11_NumberObjectsFor(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
int templateCount);
SECItem *pk11_GetLowLevelKeyFromHandle(PK11SlotInfo *slot,
CK_OBJECT_HANDLE handle);
SECStatus PK11_TraverseSlot(PK11SlotInfo *slot, void *arg);
CK_OBJECT_HANDLE pk11_FindPrivateKeyFromCertID(PK11SlotInfo *slot,
SECItem *keyID);
SECKEYPrivateKey *PK11_MakePrivKey(PK11SlotInfo *slot, KeyType keyType,
PRBool isTemp, CK_OBJECT_HANDLE privID, void *wincx);
CERTCertificate *PK11_MakeCertFromHandle(PK11SlotInfo *slot,
CK_OBJECT_HANDLE certID, CK_ATTRIBUTE *privateLabel);
SECItem *pk11_GenerateNewParamWithKeyLen(CK_MECHANISM_TYPE type, int keyLen);
SECItem *pk11_ParamFromIVWithLen(CK_MECHANISM_TYPE type,
SECItem *iv, int keyLen);
SEC_END_PROTOS
#endif

View file

@ -0,0 +1,444 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SECMODT_H_
#define _SECMODT_H_ 1
#include "nssrwlkt.h"
#include "nssilckt.h"
#include "secoid.h"
#include "secasn1.h"
#include "pkcs11t.h"
#include "utilmodt.h"
SEC_BEGIN_PROTOS
/* find a better home for these... */
extern const SEC_ASN1Template SECKEY_PointerToEncryptedPrivateKeyInfoTemplate[];
SEC_ASN1_CHOOSER_DECLARE(SECKEY_PointerToEncryptedPrivateKeyInfoTemplate)
extern const SEC_ASN1Template SECKEY_EncryptedPrivateKeyInfoTemplate[];
SEC_ASN1_CHOOSER_DECLARE(SECKEY_EncryptedPrivateKeyInfoTemplate)
extern const SEC_ASN1Template SECKEY_PrivateKeyInfoTemplate[];
SEC_ASN1_CHOOSER_DECLARE(SECKEY_PrivateKeyInfoTemplate)
extern const SEC_ASN1Template SECKEY_PointerToPrivateKeyInfoTemplate[];
SEC_ASN1_CHOOSER_DECLARE(SECKEY_PointerToPrivateKeyInfoTemplate)
SEC_END_PROTOS
/* PKCS11 needs to be included */
typedef struct SECMODModuleStr SECMODModule;
typedef struct SECMODModuleListStr SECMODModuleList;
typedef NSSRWLock SECMODListLock;
typedef struct PK11SlotInfoStr PK11SlotInfo; /* defined in secmodti.h */
typedef struct NSSUTILPreSlotInfoStr PK11PreSlotInfo; /* defined in secmodti.h */
typedef struct PK11SymKeyStr PK11SymKey; /* defined in secmodti.h */
typedef struct PK11ContextStr PK11Context; /* defined in secmodti.h */
typedef struct PK11SlotListStr PK11SlotList;
typedef struct PK11SlotListElementStr PK11SlotListElement;
typedef struct PK11RSAGenParamsStr PK11RSAGenParams;
typedef unsigned long SECMODModuleID;
typedef struct PK11DefaultArrayEntryStr PK11DefaultArrayEntry;
typedef struct PK11GenericObjectStr PK11GenericObject;
typedef void (*PK11FreeDataFunc)(void *);
struct SECMODModuleStr {
PLArenaPool *arena;
PRBool internal; /* true of internally linked modules, false
* for the loaded modules */
PRBool loaded; /* Set to true if module has been loaded */
PRBool isFIPS; /* Set to true if module is finst internal */
char *dllName; /* name of the shared library which implements
* this module */
char *commonName; /* name of the module to display to the user */
void *library; /* pointer to the library. opaque. used only by
* pk11load.c */
void *functionList; /* The PKCS #11 function table */
PZLock *refLock; /* only used pk11db.c */
int refCount; /* Module reference count */
PK11SlotInfo **slots; /* array of slot points attached to this mod*/
int slotCount; /* count of slot in above array */
PK11PreSlotInfo *slotInfo; /* special info about slots default settings */
int slotInfoCount; /* count */
SECMODModuleID moduleID; /* ID so we can find this module again */
PRBool isThreadSafe;
unsigned long ssl[2]; /* SSL cipher enable flags */
char *libraryParams; /* Module specific parameters */
void *moduleDBFunc; /* function to return module configuration data*/
SECMODModule *parent; /* module that loaded us */
PRBool isCritical; /* This module must load successfully */
PRBool isModuleDB; /* this module has lists of PKCS #11 modules */
PRBool moduleDBOnly; /* this module only has lists of PKCS #11 modules */
int trustOrder; /* order for this module's certificate trust rollup */
int cipherOrder; /* order for cipher operations */
unsigned long evControlMask; /* control the running and shutdown of slot
* events (SECMOD_WaitForAnyTokenEvent) */
CK_VERSION cryptokiVersion; /* version of this library */
};
/* evControlMask flags */
/*
* These bits tell the current state of a SECMOD_WaitForAnyTokenEvent.
*
* SECMOD_WAIT_PKCS11_EVENT - we're waiting in the PKCS #11 module in
* C_WaitForSlotEvent().
* SECMOD_WAIT_SIMULATED_EVENT - we're waiting in the NSS simulation code
* which polls for token insertion and removal events.
* SECMOD_END_WAIT - SECMOD_CancelWait has been called while the module is
* waiting in SECMOD_WaitForAnyTokenEvent. SECMOD_WaitForAnyTokenEvent
* should return immediately to it's caller.
*/
#define SECMOD_END_WAIT 0x01
#define SECMOD_WAIT_SIMULATED_EVENT 0x02
#define SECMOD_WAIT_PKCS11_EVENT 0x04
struct SECMODModuleListStr {
SECMODModuleList *next;
SECMODModule *module;
};
struct PK11SlotListStr {
PK11SlotListElement *head;
PK11SlotListElement *tail;
PZLock *lock;
};
struct PK11SlotListElementStr {
PK11SlotListElement *next;
PK11SlotListElement *prev;
PK11SlotInfo *slot;
int refCount;
};
struct PK11RSAGenParamsStr {
int keySizeInBits;
unsigned long pe;
};
typedef enum {
PK11CertListUnique = 0, /* get one instance of all certs */
PK11CertListUser = 1, /* get all instances of user certs */
PK11CertListRootUnique = 2, /* get one instance of CA certs without a private key.
* deprecated. Use PK11CertListCAUnique
*/
PK11CertListCA = 3, /* get all instances of CA certs */
PK11CertListCAUnique = 4, /* get one instance of CA certs */
PK11CertListUserUnique = 5, /* get one instance of user certs */
PK11CertListAll = 6 /* get all instances of all certs */
} PK11CertListType;
/*
* Entry into the array which lists all the legal bits for the default flags
* in the slot, their definition, and the PKCS #11 mechanism they represent.
* Always statically allocated.
*/
struct PK11DefaultArrayEntryStr {
const char *name;
unsigned long flag;
unsigned long mechanism; /* this is a long so we don't include the
* whole pkcs 11 world to use this header */
};
/*
* PK11AttrFlags
*
* A 32-bit bitmask of PK11_ATTR_XXX flags
*/
typedef PRUint32 PK11AttrFlags;
/*
* PK11_ATTR_XXX
*
* The following PK11_ATTR_XXX bitflags are used to specify
* PKCS #11 object attributes that have Boolean values. Some NSS
* functions have a "PK11AttrFlags attrFlags" parameter whose value
* is the logical OR of these bitflags. NSS use these bitflags on
* private keys or secret keys. Some of these bitflags also apply
* to the public keys associated with the private keys.
*
* For each PKCS #11 object attribute, we need two bitflags to
* specify not only "true" and "false" but also "default". For
* example, PK11_ATTR_PRIVATE and PK11_ATTR_PUBLIC control the
* CKA_PRIVATE attribute. If PK11_ATTR_PRIVATE is set, we add
* { CKA_PRIVATE, &cktrue, sizeof(CK_BBOOL) }
* to the template. If PK11_ATTR_PUBLIC is set, we add
* { CKA_PRIVATE, &ckfalse, sizeof(CK_BBOOL) }
* to the template. If neither flag is set, we don't add any
* CKA_PRIVATE entry to the template.
*/
/*
* Attributes for PKCS #11 storage objects, which include not only
* keys but also certificates and domain parameters.
*/
/*
* PK11_ATTR_TOKEN
* PK11_ATTR_SESSION
*
* These two flags determine whether the object is a token or
* session object.
*
* These two flags are related and cannot both be set.
* If the PK11_ATTR_TOKEN flag is set, the object is a token
* object. If the PK11_ATTR_SESSION flag is set, the object is
* a session object. If neither flag is set, the object is *by
* default* a session object.
*
* These two flags specify the value of the PKCS #11 CKA_TOKEN
* attribute.
*/
#define PK11_ATTR_TOKEN 0x00000001L
#define PK11_ATTR_SESSION 0x00000002L
/*
* PK11_ATTR_PRIVATE
* PK11_ATTR_PUBLIC
*
* These two flags determine whether the object is a private or
* public object. A user may not access a private object until the
* user has authenticated to the token.
*
* These two flags are related and cannot both be set.
* If the PK11_ATTR_PRIVATE flag is set, the object is a private
* object. If the PK11_ATTR_PUBLIC flag is set, the object is a
* public object. If neither flag is set, it is token-specific
* whether the object is private or public.
*
* These two flags specify the value of the PKCS #11 CKA_PRIVATE
* attribute. NSS only uses this attribute on private and secret
* keys, so public keys created by NSS get the token-specific
* default value of the CKA_PRIVATE attribute.
*/
#define PK11_ATTR_PRIVATE 0x00000004L
#define PK11_ATTR_PUBLIC 0x00000008L
/*
* PK11_ATTR_MODIFIABLE
* PK11_ATTR_UNMODIFIABLE
*
* These two flags determine whether the object is modifiable or
* read-only.
*
* These two flags are related and cannot both be set.
* If the PK11_ATTR_MODIFIABLE flag is set, the object can be
* modified. If the PK11_ATTR_UNMODIFIABLE flag is set, the object
* is read-only. If neither flag is set, the object is *by default*
* modifiable.
*
* These two flags specify the value of the PKCS #11 CKA_MODIFIABLE
* attribute.
*/
#define PK11_ATTR_MODIFIABLE 0x00000010L
#define PK11_ATTR_UNMODIFIABLE 0x00000020L
/* Attributes for PKCS #11 key objects. */
/*
* PK11_ATTR_SENSITIVE
* PK11_ATTR_INSENSITIVE
*
* These two flags are related and cannot both be set.
* If the PK11_ATTR_SENSITIVE flag is set, the key is sensitive.
* If the PK11_ATTR_INSENSITIVE flag is set, the key is not
* sensitive. If neither flag is set, it is token-specific whether
* the key is sensitive or not.
*
* If a key is sensitive, certain attributes of the key cannot be
* revealed in plaintext outside the token.
*
* This flag specifies the value of the PKCS #11 CKA_SENSITIVE
* attribute. Although the default value of the CKA_SENSITIVE
* attribute for secret keys is CK_FALSE per PKCS #11, some FIPS
* tokens set the default value to CK_TRUE because only CK_TRUE
* is allowed. So in practice the default value of this attribute
* is token-specific, hence the need for two bitflags.
*/
#define PK11_ATTR_SENSITIVE 0x00000040L
#define PK11_ATTR_INSENSITIVE 0x00000080L
/*
* PK11_ATTR_EXTRACTABLE
* PK11_ATTR_UNEXTRACTABLE
*
* These two flags are related and cannot both be set.
* If the PK11_ATTR_EXTRACTABLE flag is set, the key is extractable
* and can be wrapped. If the PK11_ATTR_UNEXTRACTABLE flag is set,
* the key is not extractable, and certain attributes of the key
* cannot be revealed in plaintext outside the token (just like a
* sensitive key). If neither flag is set, it is token-specific
* whether the key is extractable or not.
*
* These two flags specify the value of the PKCS #11 CKA_EXTRACTABLE
* attribute.
*/
#define PK11_ATTR_EXTRACTABLE 0x00000100L
#define PK11_ATTR_UNEXTRACTABLE 0x00000200L
/* Cryptographic module types */
#define SECMOD_EXTERNAL 0 /* external module */
#define SECMOD_INTERNAL 1 /* internal default module */
#define SECMOD_FIPS 2 /* internal fips module */
/* default module configuration strings */
#define SECMOD_SLOT_FLAGS "slotFlags=[RSA,DSA,DH,RC2,RC4,DES,RANDOM,SHA1,MD5,MD2,SSL,TLS,AES,Camellia,SEED,SHA256,SHA512]"
#define SECMOD_MAKE_NSS_FLAGS(fips, slot) \
"Flags=internal,critical" fips " slotparams=(" #slot "={" SECMOD_SLOT_FLAGS "})"
#define SECMOD_INT_NAME "NSS Internal PKCS #11 Module"
#define SECMOD_INT_FLAGS SECMOD_MAKE_NSS_FLAGS("", 1)
#define SECMOD_FIPS_NAME "NSS Internal FIPS PKCS #11 Module"
#define SECMOD_FIPS_FLAGS SECMOD_MAKE_NSS_FLAGS(",fips", 3)
/*
* What is the origin of a given Key. Normally this doesn't matter, but
* the fortezza code needs to know if it needs to invoke the SSL3 fortezza
* hack.
*/
typedef enum {
PK11_OriginNULL = 0, /* There is not key, it's a null SymKey */
PK11_OriginDerive = 1, /* Key was derived from some other key */
PK11_OriginGenerated = 2, /* Key was generated (also PBE keys) */
PK11_OriginFortezzaHack = 3, /* Key was marked for fortezza hack */
PK11_OriginUnwrap = 4 /* Key was unwrapped or decrypted */
} PK11Origin;
/* PKCS #11 disable reasons */
typedef enum {
PK11_DIS_NONE = 0,
PK11_DIS_USER_SELECTED = 1,
PK11_DIS_COULD_NOT_INIT_TOKEN = 2,
PK11_DIS_TOKEN_VERIFY_FAILED = 3,
PK11_DIS_TOKEN_NOT_PRESENT = 4
} PK11DisableReasons;
/* types of PKCS #11 objects
* used to identify which NSS data structure is
* passed to the PK11_Raw* functions. Types map as follows:
* PK11_TypeGeneric PK11GenericObject *
* PK11_TypePrivKey SECKEYPrivateKey *
* PK11_TypePubKey SECKEYPublicKey *
* PK11_TypeSymKey PK11SymKey *
* PK11_TypeCert CERTCertificate * (currently not used).
*/
typedef enum {
PK11_TypeGeneric = 0,
PK11_TypePrivKey = 1,
PK11_TypePubKey = 2,
PK11_TypeCert = 3,
PK11_TypeSymKey = 4
} PK11ObjectType;
/* function pointer type for password callback function.
* This type is passed in to PK11_SetPasswordFunc()
*/
typedef char *(PR_CALLBACK *PK11PasswordFunc)(PK11SlotInfo *slot, PRBool retry, void *arg);
typedef PRBool(PR_CALLBACK *PK11VerifyPasswordFunc)(PK11SlotInfo *slot, void *arg);
typedef PRBool(PR_CALLBACK *PK11IsLoggedInFunc)(PK11SlotInfo *slot, void *arg);
/*
* Special strings the password callback function can return only if
* the slot is an protected auth path slot.
*/
#define PK11_PW_RETRY "RETRY" /* an failed attempt to authenticate \
* has already been made, just retry \
* the operation */
#define PK11_PW_AUTHENTICATED "AUTH" /* a successful attempt to authenticate \
* has completed. Continue without \
* another call to C_Login */
/* All other non-null values mean that that NSS could call C_Login to force
* the authentication. The following define is to aid applications in
* documenting that is what it's trying to do */
#define PK11_PW_TRY "TRY" /* Default: a prompt has been presented \
* to the user, initiate a C_Login \
* to authenticate the token */
/*
* PKCS #11 key structures
*/
/*
** Attributes
*/
struct SECKEYAttributeStr {
SECItem attrType;
SECItem **attrValue;
};
typedef struct SECKEYAttributeStr SECKEYAttribute;
/*
** A PKCS#8 private key info object
*/
struct SECKEYPrivateKeyInfoStr {
PLArenaPool *arena;
SECItem version;
SECAlgorithmID algorithm;
SECItem privateKey;
SECKEYAttribute **attributes;
};
typedef struct SECKEYPrivateKeyInfoStr SECKEYPrivateKeyInfo;
/*
** A PKCS#8 private key info object
*/
struct SECKEYEncryptedPrivateKeyInfoStr {
PLArenaPool *arena;
SECAlgorithmID algorithm;
SECItem encryptedData;
};
typedef struct SECKEYEncryptedPrivateKeyInfoStr SECKEYEncryptedPrivateKeyInfo;
/*
* token removal detection
*/
typedef enum {
PK11TokenNotRemovable = 0,
PK11TokenPresent = 1,
PK11TokenChanged = 2,
PK11TokenRemoved = 3
} PK11TokenStatus;
typedef enum {
PK11TokenRemovedOrChangedEvent = 0,
PK11TokenPresentEvent = 1
} PK11TokenEvent;
/*
* CRL Import Flags
*/
#define CRL_IMPORT_DEFAULT_OPTIONS 0x00000000
#define CRL_IMPORT_BYPASS_CHECKS 0x00000001
/*
* Merge Error Log
*/
typedef struct PK11MergeLogStr PK11MergeLog;
typedef struct PK11MergeLogNodeStr PK11MergeLogNode;
/* These need to be global, leave some open fields so we can 'expand'
* these without breaking binary compatibility */
struct PK11MergeLogNodeStr {
PK11MergeLogNode *next; /* next entry in the list */
PK11MergeLogNode *prev; /* last entry in the list */
PK11GenericObject *object; /* object that failed */
int error; /* what the error was */
CK_RV reserved1;
unsigned long reserved2; /* future flags */
unsigned long reserved3; /* future scalar */
void *reserved4; /* future pointer */
void *reserved5; /* future expansion pointer */
};
struct PK11MergeLogStr {
PK11MergeLogNode *head;
PK11MergeLogNode *tail;
PLArenaPool *arena;
int version;
unsigned long reserved1;
unsigned long reserved2;
unsigned long reserved3;
void *reserverd4;
void *reserverd5;
};
#endif /*_SECMODT_H_ */

View file

@ -0,0 +1,183 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Internal header file included only by files in pkcs11 dir, or in
* pkcs11 specific client and server files.
*/
#ifndef _SECMODTI_H_
#define _SECMODTI_H_ 1
#include "prmon.h"
#include "prtypes.h"
#include "nssilckt.h"
#include "secmodt.h"
#include "pkcs11t.h"
#include "nssdevt.h"
/* internal data structures */
/* Traverse slots callback */
typedef struct pk11TraverseSlotStr {
SECStatus (*callback)(PK11SlotInfo *, CK_OBJECT_HANDLE, void *);
void *callbackArg;
CK_ATTRIBUTE *findTemplate;
int templateCount;
} pk11TraverseSlot;
/* represent a pkcs#11 slot reference counted. */
struct PK11SlotInfoStr {
/* the PKCS11 function list for this slot */
void *functionList;
SECMODModule *module; /* our parent module */
/* Boolean to indicate the current state of this slot */
PRBool needTest; /* Has this slot been tested for Export complience */
PRBool isPerm; /* is this slot a permanment device */
PRBool isHW; /* is this slot a hardware device */
PRBool isInternal; /* is this slot one of our internal PKCS #11 devices */
PRBool disabled; /* is this slot disabled... */
PK11DisableReasons reason; /* Why this slot is disabled */
PRBool readOnly; /* is the token in this slot read-only */
PRBool needLogin; /* does the token of the type that needs
* authentication (still true even if token is logged
* in) */
PRBool hasRandom; /* can this token generated random numbers */
PRBool defRWSession; /* is the default session RW (we open our default
* session rw if the token can only handle one session
* at a time. */
PRBool isThreadSafe; /* copied from the module */
/* The actual flags (many of which are distilled into the above PRBools) */
CK_FLAGS flags; /* flags from PKCS #11 token Info */
/* a default session handle to do quick and dirty functions */
CK_SESSION_HANDLE session;
PZLock *sessionLock; /* lock for this session */
/* our ID */
CK_SLOT_ID slotID;
/* persistant flags saved from startup to startup */
unsigned long defaultFlags;
/* keep track of who is using us so we don't accidently get freed while
* still in use */
PRInt32 refCount; /* to be in/decremented by atomic calls ONLY! */
PZLock *freeListLock;
PK11SymKey *freeSymKeysWithSessionHead;
PK11SymKey *freeSymKeysHead;
int keyCount;
int maxKeyCount;
/* Password control functions for this slot. many of these are only
* active if the appropriate flag is on in defaultFlags */
int askpw; /* what our password options are */
int timeout; /* If we're ask_timeout, what is our timeout time is
* seconds */
int authTransact; /* allow multiple authentications off one password if
* they are all part of the same transaction */
PRTime authTime; /* when were we last authenticated */
int minPassword; /* smallest legal password */
int maxPassword; /* largest legal password */
PRUint16 series; /* break up the slot info into various groups of
* inserted tokens so that keys and certs can be
* invalidated */
PRUint16 flagSeries; /* record the last series for the last event
* returned for this slot */
PRBool flagState; /* record the state of the last event returned for this
* slot. */
PRUint16 wrapKey; /* current wrapping key for SSL master secrets */
CK_MECHANISM_TYPE wrapMechanism;
/* current wrapping mechanism for current wrapKey */
CK_OBJECT_HANDLE refKeys[1]; /* array of existing wrapping keys for */
CK_MECHANISM_TYPE *mechanismList; /* list of mechanism supported by this
* token */
int mechanismCount;
/* cache the certificates stored on the token of this slot */
CERTCertificate **cert_array;
int array_size;
int cert_count;
char serial[16];
/* since these are odd sizes, keep them last. They are odd sizes to
* allow them to become null terminated strings */
char slot_name[65];
char token_name[33];
PRBool hasRootCerts;
PRBool hasRootTrust;
PRBool hasRSAInfo;
CK_FLAGS RSAInfoFlags;
PRBool protectedAuthPath;
PRBool isActiveCard;
PRIntervalTime lastLoginCheck;
unsigned int lastState;
/* for Stan */
NSSToken *nssToken;
/* fast mechanism lookup */
char mechanismBits[256];
};
/* Symetric Key structure. Reference Counted */
struct PK11SymKeyStr {
CK_MECHANISM_TYPE type; /* type of operation this key was created for*/
CK_OBJECT_HANDLE objectID; /* object id of this key in the slot */
PK11SlotInfo *slot; /* Slot this key is loaded into */
void *cx; /* window context in case we need to loggin */
PK11SymKey *next;
PRBool owner;
SECItem data; /* raw key data if available */
CK_SESSION_HANDLE session;
PRBool sessionOwner;
PRInt32 refCount; /* number of references to this key */
int size; /* key size in bytes */
PK11Origin origin; /* where this key came from
* (see def in secmodt.h) */
PK11SymKey *parent; /* potential owner key of the session */
PRUint16 series; /* break up the slot info into various groups
* of inserted tokens so that keys and certs
* can be invalidated */
void *userData; /* random data the application can attach to
* this key */
PK11FreeDataFunc freeFunc; /* function to free the user data */
};
/*
* hold a hash, encryption or signing context for multi-part operations.
* hold enough information so that multiple contexts can be interleaved
* if necessary. ... Not RefCounted.
*/
struct PK11ContextStr {
CK_ATTRIBUTE_TYPE operation; /* type of operation this context is doing
* (CKA_ENCRYPT, CKA_SIGN, CKA_HASH, etc. */
PK11SymKey *key; /* symetric key used in this context */
PK11SlotInfo *slot; /* slot this context is operationing on */
CK_SESSION_HANDLE session; /* session this context is using */
PZLock *sessionLock; /* lock before accessing a PKCS #11
* session */
PRBool ownSession; /* do we own the session? */
void *cx; /* window context in case we need to loggin*/
void *savedData; /* save data when we are multiplexing on a
* single context */
unsigned long savedLength; /* length of the saved context */
SECItem *param; /* mechanism parameters used to build this
context */
PRBool init; /* has this contexted been initialized */
CK_MECHANISM_TYPE type; /* what is the PKCS #11 this context is
* representing (usually what algorithm is
* being used (CKM_RSA_PKCS, CKM_DES,
* CKM_SHA, etc.*/
PRBool fortezzaHack; /* Fortezza SSL has some special
* non-standard semantics*/
};
/*
* structure to hold a pointer to a unique PKCS #11 object
* (pointer to the slot and the object id).
*/
struct PK11GenericObjectStr {
PK11GenericObject *prev;
PK11GenericObject *next;
PK11SlotInfo *slot;
CK_OBJECT_HANDLE objectID;
};
#define MAX_TEMPL_ATTRS 16 /* maximum attributes in template */
/* This mask includes all CK_FLAGs with an equivalent CKA_ attribute. */
#define CKF_KEY_OPERATION_FLAGS 0x000e7b00UL
#endif /* _SECMODTI_H_ */

View file

@ -0,0 +1,61 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _SECPKCS5_H_
#define _SECPKCS5_H_
#include "seccomon.h"
#include "secmodt.h"
/* used for V2 PKCS 12 Draft Spec */
typedef enum {
pbeBitGenIDNull = 0,
pbeBitGenCipherKey = 0x01,
pbeBitGenCipherIV = 0x02,
pbeBitGenIntegrityKey = 0x03
} PBEBitGenID;
typedef struct PBEBitGenContextStr PBEBitGenContext;
SEC_BEGIN_PROTOS
/* private */
SECAlgorithmID *
sec_pkcs5CreateAlgorithmID(SECOidTag algorithm, SECOidTag cipherAlgorithm,
SECOidTag prfAlg, SECOidTag *pPbeAlgorithm,
int keyLengh, SECItem *salt, int iteration);
/* Get the initialization vector. The password is passed in, hashing
* is performed, and the initialization vector is returned.
* algid is a pointer to a PBE algorithm ID
* pwitem is the password
* If an error occurs or the algorithm id is not a PBE algrithm,
* NULL is returned. Otherwise, the iv is returned in a secitem.
*/
SECItem *
SEC_PKCS5GetIV(SECAlgorithmID *algid, SECItem *pwitem, PRBool faulty3DES);
SECOidTag SEC_PKCS5GetCryptoAlgorithm(SECAlgorithmID *algid);
PRBool SEC_PKCS5IsAlgorithmPBEAlg(SECAlgorithmID *algid);
PRBool SEC_PKCS5IsAlgorithmPBEAlgTag(SECOidTag algTag);
SECOidTag SEC_PKCS5GetPBEAlgorithm(SECOidTag algTag, int keyLen);
int SEC_PKCS5GetKeyLength(SECAlgorithmID *algid);
/**********************************************************************
* Deprecated PBE functions. Use the PBE functions in pk11func.h
* instead.
**********************************************************************/
PBEBitGenContext *
PBE_CreateContext(SECOidTag hashAlgorithm, PBEBitGenID bitGenPurpose,
SECItem *pwitem, SECItem *salt, unsigned int bitsNeeded,
unsigned int iterations);
void
PBE_DestroyContext(PBEBitGenContext *context);
SECItem *
PBE_GenerateBits(PBEBitGenContext *context);
SEC_END_PROTOS
#endif /* _SECPKS5_H_ */