Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1603628 Update NSS to handle PKCS #11 v3.0 r=ueno r=mt
Update to PKCS #11 v3.0 part 2.

Create the functions and switch to the C_Interface() function to fetch the PKCS #11 function table. Also PKCS #11 v3.0 uses a new fork safe interface. NSS can already handle the case if the PKCS #11 module happens to be fork safe (when asked by the application to refresh the tokens in the child process, NSS can detect that such a refresh is not necessary and continue. Softoken could also be put in fork_safe mode with an environment variable. With this patch it's the default, and NSS asks for the fork safe API by default. Technically softoken should implement the old non-fork safe interface when PKCS #11 v2.0 is called, but NSS no longer needs it, and doing so would double the number of PKCS #11 interfaces are needed. You can still compile with fork unsafe semantics, and the PKCS #11 V3.0 module will do the right thing and not include the fork safe flag. Firefox does not fork(), so for firefox this is simply code that is no longer compilied.

We now use C_GetInterface, which allows us to specify what kind of interface we want (PKCS #11 v3.0, PKCS #11 v2.0, fork safe, etc.). Vendor specific functions can now be accessed through the C_GetInterface. If the C_GetInterface function does not exists, we fall bak to the old C_GetFunctionList.

There are 24 new functions in PKCS #11 v3.0:
C_GetInterfaceList - return a table of all the supported interfaces
C_GetInterface - return a specific interface. You can specify interface name, version and flags separately. You can leave off any of these and you will get what the token thinks is the best match of the interfaces that meet the criteria. We do this in softoken by the order of the interface list.
C_SessionCancel - Cancel one or more multipart operation
C_LoginUser - Supply a user name to C_Login(). This function has no meaning for softoken, so it just returns CKR_OPERATION_NOT_INITIALIZED under the theory that if we in the future want to support usernames, the NSS db would need special initialization to make that happen.
C_Message* and C_*Message*  (20 functions in all) are the new AEAD interface (they are written generally so that it can be used for things other than AEAD). In this patch they are unimplemented (see the next patch).

This patch adds regular (NSC_) and FIPS (FC_) versions of these functions.
Also when creating the PKCS #11 v2.0 interface, we had to create a 2.0 specific version of C_GetInfo so that it can return a 2.40 in the CK_VERSION field rather than 3.00. We do this with #defines since all the function tables are generated automagically with pkcs11f.h.

Differential Revision: https://phabricator.services.mozilla.com/D67240
  • Loading branch information
rjrelyea committed Mar 18, 2020
1 parent ccfefef commit a95d4e2
Show file tree
Hide file tree
Showing 20 changed files with 870 additions and 54 deletions.
13 changes: 13 additions & 0 deletions automation/abi-check/expected-report-libnss3.so.txt
@@ -0,0 +1,13 @@

1 function with some indirect sub-type change:

[C]'function SECStatus PK11_GetModInfo(SECMODModule*, CK_INFO*)' at pk11util.c:613:1 has some indirect sub-type changes:
parameter 1 of type 'SECMODModule*' has sub-type changes:
in pointed to type 'typedef SECMODModule' at secmodt.h:29:1:
underlying type 'struct SECMODModuleStr' at secmodt.h:44:1 changed:
type size changed from 1600 to 1664 (in bits)
1 data member insertion:
'CK_FLAGS SECMODModuleStr::flags', at offset 1600 (in bits) at secmodt.h:76:1
no data member change (1 filtered);


10 changes: 10 additions & 0 deletions automation/abi-check/expected-report-libsoftokn3.so.txt
@@ -0,0 +1,10 @@

6 Added functions:

'function CK_RV C_GetInterface(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS)' {C_GetInterface@@NSS_3.52}
'function CK_RV C_GetInterfaceList(CK_INTERFACE_PTR, CK_ULONG_PTR)' {C_GetInterfaceList@@NSS_3.52}
'function CK_RV FC_GetInterface(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS)' {FC_GetInterface@@NSS_3.52}
'function CK_RV FC_GetInterfaceList(CK_INTERFACE_PTR, CK_ULONG_PTR)' {FC_GetInterfaceList@@NSS_3.52}
'function CK_RV NSC_GetInterface(CK_UTF8CHAR_PTR, CK_VERSION_PTR, CK_INTERFACE_PTR_PTR, CK_FLAGS)' {NSC_GetInterface@@NSS_3.52}
'function CK_RV NSC_GetInterfaceList(CK_INTERFACE_PTR, CK_ULONG_PTR)' {NSC_GetInterfaceList@@NSS_3.52}

2 changes: 1 addition & 1 deletion cmd/pk11mode/pk11mode.c
Expand Up @@ -16,7 +16,7 @@
#include <string.h>
#include <stdarg.h>

#if defined(XP_UNIX) && !defined(NO_FORK_CHECK)
#if defined(XP_UNIX) && defined(DO_FORK_CHECK)
#include <unistd.h>
#include <sys/wait.h>
#else
Expand Down
65 changes: 49 additions & 16 deletions lib/pk11wrap/pk11load.c
Expand Up @@ -380,7 +380,9 @@ softoken_LoadDSO(void)
return PR_FAILURE;
}
#else
CK_RV NSC_GetFunctionList(CK_FUNCTION_LIST_PTR *pFunctionList);
CK_RV NSC_GetInterface(CK_UTF8CHAR_PTR pInterfaceName,
CK_VERSION_PTR pVersion,
CK_INTERFACE_PTR_PTR *ppInterface, CK_FLAGS flags);
char **NSC_ModuleDBFunc(unsigned long function, char *parameters, void *args);
#endif

Expand All @@ -391,20 +393,26 @@ SECStatus
secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
{
PRLibrary *library = NULL;
CK_C_GetFunctionList entry = NULL;
CK_C_GetInterface ientry = NULL;
CK_C_GetFunctionList fentry = NULL;
CK_INFO info;
CK_ULONG slotCount = 0;
SECStatus rv;
PRBool alreadyLoaded = PR_FALSE;
char *disableUnload = NULL;
#ifndef NSS_STATIC_SOFTOKEN
const char *nss_interface;
const char *nss_function;
#endif
CK_INTERFACE_PTR interface;

if (mod->loaded)
return SECSuccess;

/* internal modules get loaded from their internal list */
if (mod->internal && (mod->dllName == NULL)) {
#ifdef NSS_STATIC_SOFTOKEN
entry = (CK_C_GetFunctionList)NSC_GetFunctionList;
ientry = (CK_C_GetInterface)NSC_GetInterface;
#else
/*
* Loads softoken as a dynamic library,
Expand All @@ -417,15 +425,22 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
PR_ATOMIC_INCREMENT(&softokenLoadCount);

if (mod->isFIPS) {
entry = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, "FC_GetFunctionList");
nss_interface = "FC_GetInterface";
nss_function = "FC_GetFunctionList";
} else {
entry = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, "NSC_GetFunctionList");
nss_interface = "NSC_GetInterface";
nss_function = "NSC_GetFunctionList";
}

if (!entry)
return SECFailure;
ientry = (CK_C_GetInterface)
PR_FindSymbol(softokenLib, nss_interface);
if (!ientry) {
fentry = (CK_C_GetFunctionList)
PR_FindSymbol(softokenLib, nss_function);
if (!fentry) {
return SECFailure;
}
}
#endif

if (mod->isModuleDB) {
Expand Down Expand Up @@ -461,16 +476,20 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
* 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");
ientry = (CK_C_GetInterface)
PR_FindSymbol(library, "C_GetInterface");
if (!ientry) {
fentry = (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 ((ientry == NULL) && (fentry == NULL)) {
if (mod->isModuleDB) {
mod->loaded = PR_TRUE;
mod->moduleDBOnly = PR_TRUE;
Expand All @@ -484,8 +503,22 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
/*
* We need to get the function list
*/
if ((*entry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
goto fail;
if (ientry) {
/* we first try to get a FORK_SAFE interface */
if ((*ientry)((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface,
CKF_INTERFACE_FORK_SAFE) != CKR_OK) {
/* one is not appearantly available, get a non-fork safe version */
if ((*ientry)((CK_UTF8CHAR_PTR) "PKCS 11", NULL, &interface, 0) != CKR_OK) {
goto fail;
}
}
mod->functionList = interface->pFunctionList;
mod->flags = interface->flags;
} else {
if ((*fentry)((CK_FUNCTION_LIST_PTR *)&mod->functionList) != CKR_OK)
goto fail;
mod->flags = 0;
}

#ifdef DEBUG_MODULE
modToDBG = PR_GetEnvSecure("NSS_DEBUG_PKCS11_MODULE");
Expand Down Expand Up @@ -513,10 +546,10 @@ secmod_LoadPKCS11Module(SECMODModule *mod, SECMODModule **oldModule)
/* check the version number */
if (PK11_GETTAB(mod)->C_GetInfo(&info) != CKR_OK)
goto fail2;
if (info.cryptokiVersion.major != 2)
if (info.cryptokiVersion.major < 2)
goto fail2;
/* all 2.0 are a priori *not* thread safe */
if (info.cryptokiVersion.minor < 1) {
if ((info.cryptokiVersion.major == 2) && (info.cryptokiVersion.minor < 1)) {
if (!loadSingleThreadedModules) {
PORT_SetError(SEC_ERROR_INCOMPATIBLE_PKCS11);
goto fail2;
Expand Down
2 changes: 1 addition & 1 deletion lib/pk11wrap/secmodi.h
Expand Up @@ -94,7 +94,7 @@ CK_OBJECT_HANDLE pk11_FindObjectByTemplate(PK11SlotInfo *slot,
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_GETTAB(x) ((CK_FUNCTION_LIST_3_0_PTR)((x)->functionList))
#define PK11_SETATTRS(x, id, v, l) \
(x)->type = (id); \
(x)->pValue = (v); \
Expand Down
1 change: 1 addition & 0 deletions lib/pk11wrap/secmodt.h
Expand Up @@ -73,6 +73,7 @@ struct SECMODModuleStr {
unsigned long evControlMask; /* control the running and shutdown of slot
* events (SECMOD_WaitForAnyTokenEvent) */
CK_VERSION cryptokiVersion; /* version of this library */
CK_FLAGS flags; /* pkcs11 v3 flags */
};

/* evControlMask flags */
Expand Down

0 comments on commit a95d4e2

Please sign in to comment.