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,24 @@
#
# 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 manifest.mn
include $(CORE_DEPTH)/coreconf/config.mk
include config.mk
include $(CORE_DEPTH)/coreconf/rules.mk
# On AIX 4.3, IBM xlC_r compiler (version 3.6.6) cannot compile
# ckhelper.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)/ckhelper.o: ckhelper.c
@$(MAKE_OBJDIR)
$(CC) -o $@ -c -O2 $(CFLAGS) $<
endif
endif
endif
export:: private_export

View file

@ -0,0 +1,592 @@
/* 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 "pkcs11.h"
#ifndef DEVM_H
#include "devm.h"
#endif /* DEVM_H */
#ifndef CKHELPER_H
#include "ckhelper.h"
#endif /* CKHELPER_H */
extern const NSSError NSS_ERROR_DEVICE_ERROR;
static const CK_BBOOL s_true = CK_TRUE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_true = { (CK_VOID_PTR)&s_true, sizeof(s_true) };
static const CK_BBOOL s_false = CK_FALSE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_false = { (CK_VOID_PTR)&s_false, sizeof(s_false) };
static const CK_OBJECT_CLASS s_class_cert = CKO_CERTIFICATE;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_cert = { (CK_VOID_PTR)&s_class_cert, sizeof(s_class_cert) };
static const CK_OBJECT_CLASS s_class_pubkey = CKO_PUBLIC_KEY;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_pubkey = { (CK_VOID_PTR)&s_class_pubkey, sizeof(s_class_pubkey) };
static const CK_OBJECT_CLASS s_class_privkey = CKO_PRIVATE_KEY;
NSS_IMPLEMENT_DATA const NSSItem
g_ck_class_privkey = { (CK_VOID_PTR)&s_class_privkey, sizeof(s_class_privkey) };
static PRBool
is_string_attribute(
CK_ATTRIBUTE_TYPE aType)
{
PRBool isString;
switch (aType) {
case CKA_LABEL:
case CKA_NSS_EMAIL:
isString = PR_TRUE;
break;
default:
isString = PR_FALSE;
break;
}
return isString;
}
NSS_IMPLEMENT PRStatus
nssCKObject_GetAttributes(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot)
{
nssArenaMark *mark = NULL;
CK_SESSION_HANDLE hSession;
CK_ULONG i = 0;
CK_RV ckrv;
PRStatus nssrv;
PRBool alloced = PR_FALSE;
void *epv = nssSlot_GetCryptokiEPV(slot);
hSession = session->handle;
if (arenaOpt) {
mark = nssArena_Mark(arenaOpt);
if (!mark) {
goto loser;
}
}
nssSession_EnterMonitor(session);
/* XXX kinda hacky, if the storage size is already in the first template
* item, then skip the alloc portion
*/
if (obj_template[0].ulValueLen == 0) {
/* Get the storage size needed for each attribute */
ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
object, obj_template, count);
if (ckrv != CKR_OK &&
ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
ckrv != CKR_ATTRIBUTE_SENSITIVE) {
nssSession_ExitMonitor(session);
nss_SetError(NSS_ERROR_DEVICE_ERROR);
goto loser;
}
/* Allocate memory for each attribute. */
for (i = 0; i < count; i++) {
CK_ULONG ulValueLen = obj_template[i].ulValueLen;
if (ulValueLen == 0 || ulValueLen == (CK_ULONG)-1) {
obj_template[i].pValue = NULL;
obj_template[i].ulValueLen = 0;
continue;
}
if (is_string_attribute(obj_template[i].type)) {
ulValueLen++;
}
obj_template[i].pValue = nss_ZAlloc(arenaOpt, ulValueLen);
if (!obj_template[i].pValue) {
nssSession_ExitMonitor(session);
goto loser;
}
}
alloced = PR_TRUE;
}
/* Obtain the actual attribute values. */
ckrv = CKAPI(epv)->C_GetAttributeValue(hSession,
object, obj_template, count);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK &&
ckrv != CKR_ATTRIBUTE_TYPE_INVALID &&
ckrv != CKR_ATTRIBUTE_SENSITIVE) {
nss_SetError(NSS_ERROR_DEVICE_ERROR);
goto loser;
}
if (alloced && arenaOpt) {
nssrv = nssArena_Unmark(arenaOpt, mark);
if (nssrv != PR_SUCCESS) {
goto loser;
}
}
if (count > 1 && ((ckrv == CKR_ATTRIBUTE_TYPE_INVALID) ||
(ckrv == CKR_ATTRIBUTE_SENSITIVE))) {
/* old tokens would keep the length of '0' and not deal with any
* of the attributes we passed. For those tokens read them one at
* a time */
for (i = 0; i < count; i++) {
if ((obj_template[i].ulValueLen == 0) ||
(obj_template[i].ulValueLen == -1)) {
obj_template[i].ulValueLen = 0;
(void)nssCKObject_GetAttributes(object, &obj_template[i], 1,
arenaOpt, session, slot);
}
}
}
return PR_SUCCESS;
loser:
if (alloced) {
if (arenaOpt) {
/* release all arena memory allocated before the failure. */
(void)nssArena_Release(arenaOpt, mark);
} else {
CK_ULONG j;
/* free each heap object that was allocated before the failure. */
for (j = 0; j < i; j++) {
nss_ZFreeIf(obj_template[j].pValue);
}
}
}
return PR_FAILURE;
}
NSS_IMPLEMENT PRStatus
nssCKObject_GetAttributeItem(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_TYPE attribute,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot,
NSSItem *rvItem)
{
CK_ATTRIBUTE attr = { 0, NULL, 0 };
PRStatus nssrv;
attr.type = attribute;
nssrv = nssCKObject_GetAttributes(object, &attr, 1,
arenaOpt, session, slot);
if (nssrv != PR_SUCCESS) {
return nssrv;
}
rvItem->data = (void *)attr.pValue;
rvItem->size = (PRUint32)attr.ulValueLen;
return PR_SUCCESS;
}
NSS_IMPLEMENT PRBool
nssCKObject_IsAttributeTrue(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_TYPE attribute,
nssSession *session,
NSSSlot *slot,
PRStatus *rvStatus)
{
CK_BBOOL bool;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE atemplate = { 0, NULL, 0 };
CK_RV ckrv;
void *epv = nssSlot_GetCryptokiEPV(slot);
attr = &atemplate;
NSS_CK_SET_ATTRIBUTE_VAR(attr, attribute, bool);
nssSession_EnterMonitor(session);
ckrv = CKAPI(epv)->C_GetAttributeValue(session->handle, object,
&atemplate, 1);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
*rvStatus = PR_FAILURE;
return PR_FALSE;
}
*rvStatus = PR_SUCCESS;
return (PRBool)(bool == CK_TRUE);
}
NSS_IMPLEMENT PRStatus
nssCKObject_SetAttributes(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
nssSession *session,
NSSSlot *slot)
{
CK_RV ckrv;
void *epv = nssSlot_GetCryptokiEPV(slot);
nssSession_EnterMonitor(session);
ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle, object,
obj_template, count);
nssSession_ExitMonitor(session);
if (ckrv == CKR_OK) {
return PR_SUCCESS;
} else {
return PR_FAILURE;
}
}
NSS_IMPLEMENT PRBool
nssCKObject_IsTokenObjectTemplate(
CK_ATTRIBUTE_PTR objectTemplate,
CK_ULONG otsize)
{
CK_ULONG ul;
for (ul = 0; ul < otsize; ul++) {
if (objectTemplate[ul].type == CKA_TOKEN) {
return (*((CK_BBOOL *)objectTemplate[ul].pValue) == CK_TRUE);
}
}
return PR_FALSE;
}
static NSSCertificateType
nss_cert_type_from_ck_attrib(CK_ATTRIBUTE_PTR attrib)
{
CK_CERTIFICATE_TYPE ckCertType;
if (!attrib->pValue) {
/* default to PKIX */
return NSSCertificateType_PKIX;
}
ckCertType = *((CK_ULONG *)attrib->pValue);
switch (ckCertType) {
case CKC_X_509:
return NSSCertificateType_PKIX;
default:
break;
}
return NSSCertificateType_Unknown;
}
/* incoming pointers must be valid */
NSS_IMPLEMENT PRStatus
nssCryptokiCertificate_GetAttributes(
nssCryptokiObject *certObject,
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSCertificateType *certTypeOpt,
NSSItem *idOpt,
NSSDER *encodingOpt,
NSSDER *issuerOpt,
NSSDER *serialOpt,
NSSDER *subjectOpt)
{
PRStatus status;
PRUint32 i;
nssSession *session;
NSSSlot *slot;
CK_ULONG template_size;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE cert_template[6];
/* Set up a template of all options chosen by caller */
NSS_CK_TEMPLATE_START(cert_template, attr, template_size);
if (certTypeOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CERTIFICATE_TYPE);
}
if (idOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ID);
}
if (encodingOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
}
if (issuerOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_ISSUER);
}
if (serialOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SERIAL_NUMBER);
}
if (subjectOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
}
NSS_CK_TEMPLATE_FINISH(cert_template, attr, template_size);
if (template_size == 0) {
/* caller didn't want anything */
return PR_SUCCESS;
}
status = nssToken_GetCachedObjectAttributes(certObject->token, arenaOpt,
certObject, CKO_CERTIFICATE,
cert_template, template_size);
if (status != PR_SUCCESS) {
session = sessionOpt ? sessionOpt
: nssToken_GetDefaultSession(certObject->token);
if (!session) {
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
return PR_FAILURE;
}
slot = nssToken_GetSlot(certObject->token);
status = nssCKObject_GetAttributes(certObject->handle,
cert_template, template_size,
arenaOpt, session, slot);
nssSlot_Destroy(slot);
if (status != PR_SUCCESS) {
return status;
}
}
i = 0;
if (certTypeOpt) {
*certTypeOpt = nss_cert_type_from_ck_attrib(&cert_template[i]);
i++;
}
if (idOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], idOpt);
i++;
}
if (encodingOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], encodingOpt);
i++;
}
if (issuerOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], issuerOpt);
i++;
}
if (serialOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], serialOpt);
i++;
}
if (subjectOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&cert_template[i], subjectOpt);
i++;
}
return PR_SUCCESS;
}
static nssTrustLevel
get_nss_trust(
CK_TRUST ckt)
{
nssTrustLevel t;
switch (ckt) {
case CKT_NSS_NOT_TRUSTED:
t = nssTrustLevel_NotTrusted;
break;
case CKT_NSS_TRUSTED_DELEGATOR:
t = nssTrustLevel_TrustedDelegator;
break;
case CKT_NSS_VALID_DELEGATOR:
t = nssTrustLevel_ValidDelegator;
break;
case CKT_NSS_TRUSTED:
t = nssTrustLevel_Trusted;
break;
case CKT_NSS_MUST_VERIFY_TRUST:
t = nssTrustLevel_MustVerify;
break;
case CKT_NSS_TRUST_UNKNOWN:
default:
t = nssTrustLevel_Unknown;
break;
}
return t;
}
NSS_IMPLEMENT PRStatus
nssCryptokiTrust_GetAttributes(
nssCryptokiObject *trustObject,
nssSession *sessionOpt,
NSSItem *sha1_hash,
nssTrustLevel *serverAuth,
nssTrustLevel *clientAuth,
nssTrustLevel *codeSigning,
nssTrustLevel *emailProtection,
PRBool *stepUpApproved)
{
PRStatus status;
NSSSlot *slot;
nssSession *session;
CK_BBOOL isToken = PR_FALSE;
CK_BBOOL stepUp = PR_FALSE;
CK_TRUST saTrust = CKT_NSS_TRUST_UNKNOWN;
CK_TRUST caTrust = CKT_NSS_TRUST_UNKNOWN;
CK_TRUST epTrust = CKT_NSS_TRUST_UNKNOWN;
CK_TRUST csTrust = CKT_NSS_TRUST_UNKNOWN;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE trust_template[7];
CK_ATTRIBUTE_PTR sha1_hash_attr;
CK_ULONG trust_size;
/* Use the trust object to find the trust settings */
NSS_CK_TEMPLATE_START(trust_template, attr, trust_size);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TOKEN, isToken);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_SERVER_AUTH, saTrust);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CLIENT_AUTH, caTrust);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_EMAIL_PROTECTION, epTrust);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_CODE_SIGNING, csTrust);
NSS_CK_SET_ATTRIBUTE_VAR(attr, CKA_TRUST_STEP_UP_APPROVED, stepUp);
sha1_hash_attr = attr;
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_CERT_SHA1_HASH, sha1_hash);
NSS_CK_TEMPLATE_FINISH(trust_template, attr, trust_size);
status = nssToken_GetCachedObjectAttributes(trustObject->token, NULL,
trustObject,
CKO_NSS_TRUST,
trust_template, trust_size);
if (status != PR_SUCCESS) {
session = sessionOpt ? sessionOpt
: nssToken_GetDefaultSession(trustObject->token);
if (!session) {
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
return PR_FAILURE;
}
slot = nssToken_GetSlot(trustObject->token);
status = nssCKObject_GetAttributes(trustObject->handle,
trust_template, trust_size,
NULL, session, slot);
nssSlot_Destroy(slot);
if (status != PR_SUCCESS) {
return status;
}
}
if (sha1_hash_attr->ulValueLen == -1) {
/* The trust object does not have the CKA_CERT_SHA1_HASH attribute. */
sha1_hash_attr->ulValueLen = 0;
}
sha1_hash->size = sha1_hash_attr->ulValueLen;
*serverAuth = get_nss_trust(saTrust);
*clientAuth = get_nss_trust(caTrust);
*emailProtection = get_nss_trust(epTrust);
*codeSigning = get_nss_trust(csTrust);
*stepUpApproved = stepUp;
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssCryptokiCRL_GetAttributes(
nssCryptokiObject *crlObject,
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSItem *encodingOpt,
NSSItem *subjectOpt,
CK_ULONG *crl_class,
NSSUTF8 **urlOpt,
PRBool *isKRLOpt)
{
PRStatus status;
NSSSlot *slot;
nssSession *session;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE crl_template[7];
CK_ULONG crl_size;
PRUint32 i;
NSS_CK_TEMPLATE_START(crl_template, attr, crl_size);
if (crl_class) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_CLASS);
}
if (encodingOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_VALUE);
}
if (urlOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_URL);
}
if (isKRLOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_NSS_KRL);
}
if (subjectOpt) {
NSS_CK_SET_ATTRIBUTE_NULL(attr, CKA_SUBJECT);
}
NSS_CK_TEMPLATE_FINISH(crl_template, attr, crl_size);
status = nssToken_GetCachedObjectAttributes(crlObject->token, NULL,
crlObject,
CKO_NSS_CRL,
crl_template, crl_size);
if (status != PR_SUCCESS) {
session = sessionOpt ? sessionOpt
: nssToken_GetDefaultSession(crlObject->token);
if (session == NULL) {
nss_SetError(NSS_ERROR_INVALID_ARGUMENT);
return PR_FAILURE;
}
slot = nssToken_GetSlot(crlObject->token);
status = nssCKObject_GetAttributes(crlObject->handle,
crl_template, crl_size,
arenaOpt, session, slot);
nssSlot_Destroy(slot);
if (status != PR_SUCCESS) {
return status;
}
}
i = 0;
if (crl_class) {
NSS_CK_ATTRIBUTE_TO_ULONG(&crl_template[i], *crl_class);
i++;
}
if (encodingOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], encodingOpt);
i++;
}
if (urlOpt) {
NSS_CK_ATTRIBUTE_TO_UTF8(&crl_template[i], *urlOpt);
i++;
}
if (isKRLOpt) {
NSS_CK_ATTRIBUTE_TO_BOOL(&crl_template[i], *isKRLOpt);
i++;
}
if (subjectOpt) {
NSS_CK_ATTRIBUTE_TO_ITEM(&crl_template[i], subjectOpt);
i++;
}
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssCryptokiPrivateKey_SetCertificate(
nssCryptokiObject *keyObject,
nssSession *sessionOpt,
const NSSUTF8 *nickname,
NSSItem *id,
NSSDER *subject)
{
CK_RV ckrv;
CK_ATTRIBUTE_PTR attr;
CK_ATTRIBUTE key_template[3];
CK_ULONG key_size;
void *epv = nssToken_GetCryptokiEPV(keyObject->token);
nssSession *session;
NSSToken *token = keyObject->token;
nssSession *defaultSession = nssToken_GetDefaultSession(token);
PRBool createdSession = PR_FALSE;
NSS_CK_TEMPLATE_START(key_template, attr, key_size);
NSS_CK_SET_ATTRIBUTE_UTF8(attr, CKA_LABEL, nickname);
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_ID, id);
NSS_CK_SET_ATTRIBUTE_ITEM(attr, CKA_SUBJECT, subject);
NSS_CK_TEMPLATE_FINISH(key_template, attr, key_size);
if (sessionOpt) {
if (!nssSession_IsReadWrite(sessionOpt)) {
return PR_FAILURE;
}
session = sessionOpt;
} else if (defaultSession && nssSession_IsReadWrite(defaultSession)) {
session = defaultSession;
} else {
NSSSlot *slot = nssToken_GetSlot(token);
session = nssSlot_CreateSession(token->slot, NULL, PR_TRUE);
nssSlot_Destroy(slot);
if (!session) {
return PR_FAILURE;
}
createdSession = PR_TRUE;
}
ckrv = CKAPI(epv)->C_SetAttributeValue(session->handle,
keyObject->handle,
key_template,
key_size);
if (createdSession) {
nssSession_Destroy(session);
}
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}

View file

@ -0,0 +1,148 @@
/* 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/. */
/*
* ckhelper.h
*
* This file contains some helper utilities for interaction with cryptoki.
*/
#ifndef CKHELPER_H
#define CKHELPER_H
PR_BEGIN_EXTERN_C
/* Some globals to keep from constantly redeclaring common cryptoki
* attribute types on the stack.
*/
/* Boolean values */
NSS_EXTERN_DATA const NSSItem g_ck_true;
NSS_EXTERN_DATA const NSSItem g_ck_false;
/* Object classes */
NSS_EXTERN_DATA const NSSItem g_ck_class_cert;
NSS_EXTERN_DATA const NSSItem g_ck_class_pubkey;
NSS_EXTERN_DATA const NSSItem g_ck_class_privkey;
#define NSS_CK_TEMPLATE_START(_template, attr, size) \
attr = _template; \
size = 0;
#define NSS_CK_SET_ATTRIBUTE_ITEM(pattr, kind, item) \
(pattr)->type = kind; \
(pattr)->pValue = (CK_VOID_PTR)(item)->data; \
(pattr)->ulValueLen = (CK_ULONG)(item)->size; \
(pattr)++;
#define NSS_CK_SET_ATTRIBUTE_UTF8(pattr, kind, utf8) \
(pattr)->type = kind; \
(pattr)->pValue = (CK_VOID_PTR)utf8; \
(pattr)->ulValueLen = (CK_ULONG)nssUTF8_Size(utf8, NULL); \
if ((pattr)->ulValueLen) \
((pattr)->ulValueLen)--; \
(pattr)++;
#define NSS_CK_SET_ATTRIBUTE_VAR(pattr, kind, var) \
(pattr)->type = kind; \
(pattr)->pValue = (CK_VOID_PTR)&var; \
(pattr)->ulValueLen = (CK_ULONG)sizeof(var); \
(pattr)++;
#define NSS_CK_SET_ATTRIBUTE_NULL(pattr, kind) \
(pattr)->type = kind; \
(pattr)->pValue = (CK_VOID_PTR)NULL; \
(pattr)->ulValueLen = 0; \
(pattr)++;
#define NSS_CK_TEMPLATE_FINISH(_template, attr, size) \
size = (attr) - (_template); \
PR_ASSERT(size <= sizeof(_template) / sizeof(_template[0]));
/* NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item)
*
* Convert a CK_ATTRIBUTE to an NSSItem.
*/
#define NSS_CK_ATTRIBUTE_TO_ITEM(attrib, item) \
if ((CK_LONG)(attrib)->ulValueLen > 0) { \
(item)->data = (void *)(attrib)->pValue; \
(item)->size = (PRUint32)(attrib)->ulValueLen; \
} else { \
(item)->data = 0; \
(item)->size = 0; \
}
#define NSS_CK_ATTRIBUTE_TO_BOOL(attrib, boolvar) \
if ((attrib)->ulValueLen > 0) { \
if (*((CK_BBOOL *)(attrib)->pValue) == CK_TRUE) { \
boolvar = PR_TRUE; \
} else { \
boolvar = PR_FALSE; \
} \
}
#define NSS_CK_ATTRIBUTE_TO_ULONG(attrib, ulongvar) \
if ((attrib)->ulValueLen > 0) { \
ulongvar = *((CK_ULONG *)(attrib)->pValue); \
}
/* NSS_CK_ATTRIBUTE_TO_UTF8(attrib, str)
*
* Convert a CK_ATTRIBUTE to a string.
*/
#define NSS_CK_ATTRIBUTE_TO_UTF8(attrib, str) \
str = (NSSUTF8 *)((attrib)->pValue);
/* NSS_CK_ITEM_TO_ATTRIBUTE(item, attrib)
*
* Convert an NSSItem to a CK_ATTRIBUTE.
*/
#define NSS_CK_ITEM_TO_ATTRIBUTE(item, attrib) \
(attrib)->pValue = (CK_VOID_PTR)(item)->data; \
(attrib)->ulValueLen = (CK_ULONG)(item)->size;
/* Get an array of attributes from an object. */
NSS_EXTERN PRStatus
nssCKObject_GetAttributes(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot);
/* Get a single attribute as an item. */
NSS_EXTERN PRStatus
nssCKObject_GetAttributeItem(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_TYPE attribute,
NSSArena *arenaOpt,
nssSession *session,
NSSSlot *slot,
NSSItem *rvItem);
NSS_EXTERN PRBool
nssCKObject_IsAttributeTrue(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_TYPE attribute,
nssSession *session,
NSSSlot *slot,
PRStatus *rvStatus);
NSS_EXTERN PRStatus
nssCKObject_SetAttributes(
CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_PTR obj_template,
CK_ULONG count,
nssSession *session,
NSSSlot *slot);
NSS_EXTERN PRBool
nssCKObject_IsTokenObjectTemplate(
CK_ATTRIBUTE_PTR objectTemplate,
CK_ULONG otsize);
PR_END_EXTERN_C
#endif /* CKHELPER_H */

View file

@ -0,0 +1,19 @@
#
# 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/.
ifdef BUILD_IDG
DEFINES += -DNSSDEBUG
endif
#
# Override TARGETS variable so that only static libraries
# are specifed as dependencies within rules.mk.
#
TARGETS = $(LIBRARY)
SHARED_LIBRARY =
IMPORT_LIBRARY =
PROGRAM =

View file

@ -0,0 +1,26 @@
# 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': 'nssdev',
'type': 'static_library',
'sources': [
'ckhelper.c',
'devslot.c',
'devtoken.c',
'devutil.c'
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports'
]
}
],
'variables': {
'module': 'nss'
}
}

747
security/nss/lib/dev/dev.h Normal file
View file

@ -0,0 +1,747 @@
/* 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 DEV_H
#define DEV_H
/*
* dev.h
*
* Low-level methods for interaction with cryptoki devices
*/
#ifndef NSSDEV_H
#include "nssdev.h"
#endif /* NSSDEV_H */
#ifndef DEVT_H
#include "devt.h"
#endif /* DEVT_H */
PR_BEGIN_EXTERN_C
/* the global module list
*
* These functions are for managing the global set of modules. Trust Domains,
* etc., will draw from this set. These functions are completely internal
* and only invoked when there are changes to the global module state
* (load or unload).
*
* nss_InitializeGlobalModuleList
* nss_DestroyGlobalModuleList
* nss_GetLoadedModules
*
* nssGlobalModuleList_Add
* nssGlobalModuleList_Remove
* nssGlobalModuleList_FindModuleByName
* nssGlobalModuleList_FindSlotByName
* nssGlobalModuleList_FindTokenByName
*/
NSS_EXTERN PRStatus
nss_InitializeGlobalModuleList(
void);
NSS_EXTERN PRStatus
nss_DestroyGlobalModuleList(
void);
NSS_EXTERN NSSModule **
nss_GetLoadedModules(
void);
NSS_EXTERN PRStatus
nssGlobalModuleList_Add(
NSSModule *module);
NSS_EXTERN PRStatus
nssGlobalModuleList_Remove(
NSSModule *module);
NSS_EXTERN NSSModule *
nssGlobalModuleList_FindModuleByName(
NSSUTF8 *moduleName);
NSS_EXTERN NSSSlot *
nssGlobalModuleList_FindSlotByName(
NSSUTF8 *slotName);
NSS_EXTERN NSSToken *
nssGlobalModuleList_FindTokenByName(
NSSUTF8 *tokenName);
NSS_EXTERN NSSToken *
nss_GetDefaultCryptoToken(
void);
NSS_EXTERN NSSToken *
nss_GetDefaultDatabaseToken(
void);
/*
* |-----------|<---> NSSSlot <--> NSSToken
* | NSSModule |<---> NSSSlot <--> NSSToken
* |-----------|<---> NSSSlot <--> NSSToken
*/
/* NSSModule
*
* nssModule_Create
* nssModule_CreateFromSpec
* nssModule_AddRef
* nssModule_GetName
* nssModule_GetSlots
* nssModule_FindSlotByName
* nssModule_FindTokenByName
* nssModule_GetCertOrder
*/
NSS_EXTERN NSSModule *
nssModule_Create(
NSSUTF8 *moduleOpt,
NSSUTF8 *uriOpt,
NSSUTF8 *opaqueOpt,
void *reserved);
/* This is to use the new loading mechanism. */
NSS_EXTERN NSSModule *
nssModule_CreateFromSpec(
NSSUTF8 *moduleSpec,
NSSModule *parent,
PRBool loadSubModules);
NSS_EXTERN PRStatus
nssModule_Destroy(
NSSModule *mod);
NSS_EXTERN NSSModule *
nssModule_AddRef(
NSSModule *mod);
NSS_EXTERN NSSUTF8 *
nssModule_GetName(
NSSModule *mod);
NSS_EXTERN NSSSlot **
nssModule_GetSlots(
NSSModule *mod);
NSS_EXTERN NSSSlot *
nssModule_FindSlotByName(
NSSModule *mod,
NSSUTF8 *slotName);
NSS_EXTERN NSSToken *
nssModule_FindTokenByName(
NSSModule *mod,
NSSUTF8 *tokenName);
NSS_EXTERN PRInt32
nssModule_GetCertOrder(
NSSModule *module);
/* NSSSlot
*
* nssSlot_Destroy
* nssSlot_AddRef
* nssSlot_GetName
* nssSlot_GetTokenName
* nssSlot_IsTokenPresent
* nssSlot_IsPermanent
* nssSlot_IsFriendly
* nssSlot_IsHardware
* nssSlot_Refresh
* nssSlot_GetModule
* nssSlot_GetToken
* nssSlot_Login
* nssSlot_Logout
* nssSlot_SetPassword
* nssSlot_CreateSession
*/
NSS_EXTERN PRStatus
nssSlot_Destroy(
NSSSlot *slot);
NSS_EXTERN NSSSlot *
nssSlot_AddRef(
NSSSlot *slot);
NSS_EXTERN void
nssSlot_ResetDelay(
NSSSlot *slot);
NSS_EXTERN NSSUTF8 *
nssSlot_GetName(
NSSSlot *slot);
NSS_EXTERN NSSUTF8 *
nssSlot_GetTokenName(
NSSSlot *slot);
NSS_EXTERN NSSModule *
nssSlot_GetModule(
NSSSlot *slot);
NSS_EXTERN NSSToken *
nssSlot_GetToken(
NSSSlot *slot);
NSS_EXTERN PRBool
nssSlot_IsTokenPresent(
NSSSlot *slot);
NSS_EXTERN PRBool
nssSlot_IsPermanent(
NSSSlot *slot);
NSS_EXTERN PRBool
nssSlot_IsFriendly(
NSSSlot *slot);
NSS_EXTERN PRBool
nssSlot_IsHardware(
NSSSlot *slot);
NSS_EXTERN PRBool
nssSlot_IsLoggedIn(
NSSSlot *slot);
NSS_EXTERN PRStatus
nssSlot_Refresh(
NSSSlot *slot);
NSS_EXTERN PRStatus
nssSlot_Login(
NSSSlot *slot,
NSSCallback *pwcb);
extern const NSSError NSS_ERROR_INVALID_PASSWORD;
extern const NSSError NSS_ERROR_USER_CANCELED;
NSS_EXTERN PRStatus
nssSlot_Logout(
NSSSlot *slot,
nssSession *sessionOpt);
NSS_EXTERN void
nssSlot_EnterMonitor(
NSSSlot *slot);
NSS_EXTERN void
nssSlot_ExitMonitor(
NSSSlot *slot);
#define NSSSLOT_ASK_PASSWORD_FIRST_TIME -1
#define NSSSLOT_ASK_PASSWORD_EVERY_TIME 0
NSS_EXTERN void
nssSlot_SetPasswordDefaults(
NSSSlot *slot,
PRInt32 askPasswordTimeout);
NSS_EXTERN PRStatus
nssSlot_SetPassword(
NSSSlot *slot,
NSSUTF8 *oldPasswordOpt,
NSSUTF8 *newPassword);
extern const NSSError NSS_ERROR_INVALID_PASSWORD;
extern const NSSError NSS_ERROR_USER_CANCELED;
/*
* nssSlot_IsLoggedIn
*/
NSS_EXTERN nssSession *
nssSlot_CreateSession(
NSSSlot *slot,
NSSArena *arenaOpt,
PRBool readWrite /* so far, this is the only flag used */
);
/* NSSToken
*
* nssToken_Destroy
* nssToken_AddRef
* nssToken_GetName
* nssToken_GetModule
* nssToken_GetSlot
* nssToken_NeedsPINInitialization
* nssToken_ImportCertificate
* nssToken_ImportTrust
* nssToken_ImportCRL
* nssToken_GenerateKeyPair
* nssToken_GenerateSymmetricKey
* nssToken_DeleteStoredObject
* nssToken_FindObjects
* nssToken_FindCertificatesBySubject
* nssToken_FindCertificatesByNickname
* nssToken_FindCertificatesByEmail
* nssToken_FindCertificateByIssuerAndSerialNumber
* nssToken_FindCertificateByEncodedCertificate
* nssToken_FindTrustForCertificate
* nssToken_FindCRLsBySubject
* nssToken_FindPrivateKeys
* nssToken_FindPrivateKeyByID
* nssToken_Digest
* nssToken_BeginDigest
* nssToken_ContinueDigest
* nssToken_FinishDigest
*/
NSS_EXTERN PRStatus
nssToken_Destroy(
NSSToken *tok);
NSS_EXTERN NSSToken *
nssToken_AddRef(
NSSToken *tok);
NSS_EXTERN NSSUTF8 *
nssToken_GetName(
NSSToken *tok);
NSS_EXTERN NSSModule *
nssToken_GetModule(
NSSToken *token);
NSS_EXTERN NSSSlot *
nssToken_GetSlot(
NSSToken *tok);
NSS_EXTERN PRBool
nssToken_NeedsPINInitialization(
NSSToken *token);
NSS_EXTERN nssCryptokiObject *
nssToken_ImportCertificate(
NSSToken *tok,
nssSession *sessionOpt,
NSSCertificateType certType,
NSSItem *id,
const NSSUTF8 *nickname,
NSSDER *encoding,
NSSDER *issuer,
NSSDER *subject,
NSSDER *serial,
NSSASCII7 *emailAddr,
PRBool asTokenObject);
NSS_EXTERN nssCryptokiObject *
nssToken_ImportTrust(
NSSToken *tok,
nssSession *sessionOpt,
NSSDER *certEncoding,
NSSDER *certIssuer,
NSSDER *certSerial,
nssTrustLevel serverAuth,
nssTrustLevel clientAuth,
nssTrustLevel codeSigning,
nssTrustLevel emailProtection,
PRBool stepUpApproved,
PRBool asTokenObject);
NSS_EXTERN nssCryptokiObject *
nssToken_ImportCRL(
NSSToken *token,
nssSession *sessionOpt,
NSSDER *subject,
NSSDER *encoding,
PRBool isKRL,
NSSUTF8 *url,
PRBool asTokenObject);
/* Permanently remove an object from the token. */
NSS_EXTERN PRStatus
nssToken_DeleteStoredObject(
nssCryptokiObject *instance);
NSS_EXTERN nssCryptokiObject **
nssToken_FindObjects(
NSSToken *token,
nssSession *sessionOpt,
CK_OBJECT_CLASS objclass,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject **
nssToken_FindCertificatesBySubject(
NSSToken *token,
nssSession *sessionOpt,
NSSDER *subject,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject **
nssToken_FindCertificatesByNickname(
NSSToken *token,
nssSession *sessionOpt,
const NSSUTF8 *name,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject **
nssToken_FindCertificatesByEmail(
NSSToken *token,
nssSession *sessionOpt,
NSSASCII7 *email,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject **
nssToken_FindCertificatesByID(
NSSToken *token,
nssSession *sessionOpt,
NSSItem *id,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject *
nssToken_FindCertificateByIssuerAndSerialNumber(
NSSToken *token,
nssSession *sessionOpt,
NSSDER *issuer,
NSSDER *serial,
nssTokenSearchType searchType,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject *
nssToken_FindCertificateByEncodedCertificate(
NSSToken *token,
nssSession *sessionOpt,
NSSBER *encodedCertificate,
nssTokenSearchType searchType,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject *
nssToken_FindTrustForCertificate(
NSSToken *token,
nssSession *sessionOpt,
NSSDER *certEncoding,
NSSDER *certIssuer,
NSSDER *certSerial,
nssTokenSearchType searchType);
NSS_EXTERN nssCryptokiObject **
nssToken_FindCRLsBySubject(
NSSToken *token,
nssSession *sessionOpt,
NSSDER *subject,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject **
nssToken_FindPrivateKeys(
NSSToken *token,
nssSession *sessionOpt,
nssTokenSearchType searchType,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN nssCryptokiObject *
nssToken_FindPrivateKeyByID(
NSSToken *token,
nssSession *sessionOpt,
NSSItem *keyID);
NSS_EXTERN nssCryptokiObject *
nssToken_FindPublicKeyByID(
NSSToken *token,
nssSession *sessionOpt,
NSSItem *keyID);
NSS_EXTERN NSSItem *
nssToken_Digest(
NSSToken *tok,
nssSession *sessionOpt,
NSSAlgorithmAndParameters *ap,
NSSItem *data,
NSSItem *rvOpt,
NSSArena *arenaOpt);
NSS_EXTERN PRStatus
nssToken_BeginDigest(
NSSToken *tok,
nssSession *sessionOpt,
NSSAlgorithmAndParameters *ap);
NSS_EXTERN PRStatus
nssToken_ContinueDigest(
NSSToken *tok,
nssSession *sessionOpt,
NSSItem *item);
NSS_EXTERN NSSItem *
nssToken_FinishDigest(
NSSToken *tok,
nssSession *sessionOpt,
NSSItem *rvOpt,
NSSArena *arenaOpt);
/* nssSession
*
* nssSession_Destroy
* nssSession_EnterMonitor
* nssSession_ExitMonitor
* nssSession_IsReadWrite
*/
NSS_EXTERN PRStatus
nssSession_Destroy(
nssSession *s);
/* would like to inline */
NSS_EXTERN PRStatus
nssSession_EnterMonitor(
nssSession *s);
/* would like to inline */
NSS_EXTERN PRStatus
nssSession_ExitMonitor(
nssSession *s);
/* would like to inline */
NSS_EXTERN PRBool
nssSession_IsReadWrite(
nssSession *s);
/* nssCryptokiObject
*
* An object living on a cryptoki token.
* Not really proper to mix up the object types just because
* nssCryptokiObject itself is generic, but doing so anyway.
*
* nssCryptokiObject_Destroy
* nssCryptokiObject_Equal
* nssCryptokiObject_Clone
* nssCryptokiCertificate_GetAttributes
* nssCryptokiPrivateKey_GetAttributes
* nssCryptokiPublicKey_GetAttributes
* nssCryptokiTrust_GetAttributes
* nssCryptokiCRL_GetAttributes
*/
NSS_EXTERN void
nssCryptokiObject_Destroy(
nssCryptokiObject *object);
NSS_EXTERN PRBool
nssCryptokiObject_Equal(
nssCryptokiObject *object1,
nssCryptokiObject *object2);
NSS_EXTERN nssCryptokiObject *
nssCryptokiObject_Clone(
nssCryptokiObject *object);
NSS_EXTERN PRStatus
nssCryptokiCertificate_GetAttributes(
nssCryptokiObject *object,
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSCertificateType *certTypeOpt,
NSSItem *idOpt,
NSSDER *encodingOpt,
NSSDER *issuerOpt,
NSSDER *serialOpt,
NSSDER *subjectOpt);
NSS_EXTERN PRStatus
nssCryptokiTrust_GetAttributes(
nssCryptokiObject *trustObject,
nssSession *sessionOpt,
NSSItem *sha1_hash,
nssTrustLevel *serverAuth,
nssTrustLevel *clientAuth,
nssTrustLevel *codeSigning,
nssTrustLevel *emailProtection,
PRBool *stepUpApproved);
NSS_EXTERN PRStatus
nssCryptokiCRL_GetAttributes(
nssCryptokiObject *crlObject,
nssSession *sessionOpt,
NSSArena *arenaOpt,
NSSItem *encodingOpt,
NSSItem *subjectOpt,
CK_ULONG *crl_class,
NSSUTF8 **urlOpt,
PRBool *isKRLOpt);
/* I'm including this to handle import of certificates in NSS 3.5. This
* function will set the cert-related attributes of a key, in order to
* associate it with a cert. Does it stay like this for 4.0?
*/
NSS_EXTERN PRStatus
nssCryptokiPrivateKey_SetCertificate(
nssCryptokiObject *keyObject,
nssSession *sessionOpt,
const NSSUTF8 *nickname,
NSSItem *id,
NSSDER *subject);
NSS_EXTERN void
nssModuleArray_Destroy(
NSSModule **modules);
/* nssSlotArray
*
* nssSlotArray_Destroy
*/
NSS_EXTERN void
nssSlotArray_Destroy(
NSSSlot **slots);
/* nssTokenArray
*
* nssTokenArray_Destroy
*/
NSS_EXTERN void
nssTokenArray_Destroy(
NSSToken **tokens);
/* nssCryptokiObjectArray
*
* nssCryptokiObjectArray_Destroy
*/
NSS_EXTERN void
nssCryptokiObjectArray_Destroy(
nssCryptokiObject **object);
/* nssSlotList
*
* An ordered list of slots. The order can be anything, it is set in the
* Add methods. Perhaps it should be CreateInCertOrder, ...?
*
* nssSlotList_Create
* nssSlotList_Destroy
* nssSlotList_Add
* nssSlotList_AddModuleSlots
* nssSlotList_GetSlots
* nssSlotList_FindSlotByName
* nssSlotList_FindTokenByName
* nssSlotList_GetBestSlot
* nssSlotList_GetBestSlotForAlgorithmAndParameters
* nssSlotList_GetBestSlotForAlgorithmsAndParameters
*/
/* nssSlotList_Create
*/
NSS_EXTERN nssSlotList *
nssSlotList_Create(
NSSArena *arenaOpt);
/* nssSlotList_Destroy
*/
NSS_EXTERN void
nssSlotList_Destroy(
nssSlotList *slotList);
/* nssSlotList_Add
*
* Add the given slot in the given order.
*/
NSS_EXTERN PRStatus
nssSlotList_Add(
nssSlotList *slotList,
NSSSlot *slot,
PRUint32 order);
/* nssSlotList_AddModuleSlots
*
* Add all slots in the module, in the given order (the slots will have
* equal weight).
*/
NSS_EXTERN PRStatus
nssSlotList_AddModuleSlots(
nssSlotList *slotList,
NSSModule *module,
PRUint32 order);
/* nssSlotList_GetSlots
*/
NSS_EXTERN NSSSlot **
nssSlotList_GetSlots(
nssSlotList *slotList);
/* nssSlotList_FindSlotByName
*/
NSS_EXTERN NSSSlot *
nssSlotList_FindSlotByName(
nssSlotList *slotList,
NSSUTF8 *slotName);
/* nssSlotList_FindTokenByName
*/
NSS_EXTERN NSSToken *
nssSlotList_FindTokenByName(
nssSlotList *slotList,
NSSUTF8 *tokenName);
/* nssSlotList_GetBestSlot
*
* The best slot is the highest ranking in order, i.e., the first in the
* list.
*/
NSS_EXTERN NSSSlot *
nssSlotList_GetBestSlot(
nssSlotList *slotList);
/* nssSlotList_GetBestSlotForAlgorithmAndParameters
*
* Highest-ranking slot than can handle algorithm/parameters.
*/
NSS_EXTERN NSSSlot *
nssSlotList_GetBestSlotForAlgorithmAndParameters(
nssSlotList *slotList,
NSSAlgorithmAndParameters *ap);
/* nssSlotList_GetBestSlotForAlgorithmsAndParameters
*
* Highest-ranking slot than can handle all algorithms/parameters.
*/
NSS_EXTERN NSSSlot *
nssSlotList_GetBestSlotForAlgorithmsAndParameters(
nssSlotList *slotList,
NSSAlgorithmAndParameters **ap);
NSS_EXTERN PRBool
nssToken_IsPresent(
NSSToken *token);
NSS_EXTERN nssSession *
nssToken_GetDefaultSession(
NSSToken *token);
NSS_EXTERN PRStatus
nssToken_GetTrustOrder(
NSSToken *tok);
NSS_EXTERN PRStatus
nssToken_NotifyCertsNotVisible(
NSSToken *tok);
NSS_EXTERN PRStatus
nssToken_TraverseCertificates(
NSSToken *token,
nssSession *sessionOpt,
nssTokenSearchType searchType,
PRStatus (*callback)(nssCryptokiObject *instance, void *arg),
void *arg);
NSS_EXTERN PRBool
nssToken_IsPrivateKeyAvailable(
NSSToken *token,
NSSCertificate *c,
nssCryptokiObject *instance);
PR_END_EXTERN_C
#endif /* DEV_H */

157
security/nss/lib/dev/devm.h Normal file
View file

@ -0,0 +1,157 @@
/* 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 DEVM_H
#define DEVM_H
#ifndef BASE_H
#include "base.h"
#endif /* BASE_H */
#ifndef DEV_H
#include "dev.h"
#endif /* DEV_H */
#ifndef DEVTM_H
#include "devtm.h"
#endif /* DEVTM_H */
PR_BEGIN_EXTERN_C
/* Shortcut to cryptoki API functions. */
#define CKAPI(epv) \
((CK_FUNCTION_LIST_PTR)(epv))
NSS_EXTERN void
nssDevice_AddRef(
struct nssDeviceBaseStr *device);
NSS_EXTERN PRBool
nssDevice_Destroy(
struct nssDeviceBaseStr *device);
NSS_EXTERN PRBool
nssModule_IsThreadSafe(
NSSModule *module);
NSS_EXTERN PRBool
nssModule_IsInternal(
NSSModule *mod);
NSS_EXTERN PRBool
nssModule_IsModuleDBOnly(
NSSModule *mod);
NSS_EXTERN void *
nssModule_GetCryptokiEPV(
NSSModule *mod);
NSS_EXTERN NSSSlot *
nssSlot_Create(
CK_SLOT_ID slotId,
NSSModule *parent);
NSS_EXTERN void *
nssSlot_GetCryptokiEPV(
NSSSlot *slot);
NSS_EXTERN NSSToken *
nssToken_Create(
CK_SLOT_ID slotID,
NSSSlot *peer);
NSS_EXTERN void *
nssToken_GetCryptokiEPV(
NSSToken *token);
NSS_EXTERN nssSession *
nssToken_GetDefaultSession(
NSSToken *token);
NSS_EXTERN PRBool
nssToken_IsLoginRequired(
NSSToken *token);
NSS_EXTERN void
nssToken_Remove(
NSSToken *token);
NSS_EXTERN nssCryptokiObject *
nssCryptokiObject_Create(
NSSToken *t,
nssSession *session,
CK_OBJECT_HANDLE h);
NSS_EXTERN nssTokenObjectCache *
nssTokenObjectCache_Create(
NSSToken *token,
PRBool cacheCerts,
PRBool cacheTrust,
PRBool cacheCRLs);
NSS_EXTERN void
nssTokenObjectCache_Destroy(
nssTokenObjectCache *cache);
NSS_EXTERN void
nssTokenObjectCache_Clear(
nssTokenObjectCache *cache);
NSS_EXTERN PRBool
nssTokenObjectCache_HaveObjectClass(
nssTokenObjectCache *cache,
CK_OBJECT_CLASS objclass);
NSS_EXTERN nssCryptokiObject **
nssTokenObjectCache_FindObjectsByTemplate(
nssTokenObjectCache *cache,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR otemplate,
CK_ULONG otlen,
PRUint32 maximumOpt,
PRStatus *statusOpt);
NSS_EXTERN PRStatus
nssTokenObjectCache_GetObjectAttributes(
nssTokenObjectCache *cache,
NSSArena *arenaOpt,
nssCryptokiObject *object,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR atemplate,
CK_ULONG atlen);
NSS_EXTERN PRStatus
nssTokenObjectCache_ImportObject(
nssTokenObjectCache *cache,
nssCryptokiObject *object,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR ot,
CK_ULONG otlen);
NSS_EXTERN void
nssTokenObjectCache_RemoveObject(
nssTokenObjectCache *cache,
nssCryptokiObject *object);
/* XXX allows peek back into token */
NSS_EXTERN PRStatus
nssToken_GetCachedObjectAttributes(
NSSToken *token,
NSSArena *arenaOpt,
nssCryptokiObject *object,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR atemplate,
CK_ULONG atlen);
/* PKCS#11 stores strings in a fixed-length buffer padded with spaces. This
* function gets the length of the actual string.
*/
NSS_EXTERN PRUint32
nssPKCS11String_Length(
CK_CHAR *pkcs11str,
PRUint32 bufLen);
PR_END_EXTERN_C
#endif /* DEV_H */

View file

@ -0,0 +1,247 @@
/* 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 "pkcs11.h"
#ifndef DEVM_H
#include "devm.h"
#endif /* DEVM_H */
#ifndef CKHELPER_H
#include "ckhelper.h"
#endif /* CKHELPER_H */
#include "pk11pub.h"
/* measured in seconds */
#define NSSSLOT_TOKEN_DELAY_TIME 1
/* this should track global and per-transaction login information */
#define NSSSLOT_IS_FRIENDLY(slot) \
(slot->base.flags & NSSSLOT_FLAGS_FRIENDLY)
/* measured as interval */
static PRIntervalTime s_token_delay_time = 0;
NSS_IMPLEMENT PRStatus
nssSlot_Destroy(
NSSSlot *slot)
{
if (slot) {
if (PR_ATOMIC_DECREMENT(&slot->base.refCount) == 0) {
PZ_DestroyLock(slot->base.lock);
return nssArena_Destroy(slot->base.arena);
}
}
return PR_SUCCESS;
}
void
nssSlot_EnterMonitor(NSSSlot *slot)
{
if (slot->lock) {
PZ_Lock(slot->lock);
}
}
void
nssSlot_ExitMonitor(NSSSlot *slot)
{
if (slot->lock) {
PZ_Unlock(slot->lock);
}
}
NSS_IMPLEMENT void
NSSSlot_Destroy(
NSSSlot *slot)
{
(void)nssSlot_Destroy(slot);
}
NSS_IMPLEMENT NSSSlot *
nssSlot_AddRef(
NSSSlot *slot)
{
PR_ATOMIC_INCREMENT(&slot->base.refCount);
return slot;
}
NSS_IMPLEMENT NSSUTF8 *
nssSlot_GetName(
NSSSlot *slot)
{
return slot->base.name;
}
NSS_IMPLEMENT NSSUTF8 *
nssSlot_GetTokenName(
NSSSlot *slot)
{
return nssToken_GetName(slot->token);
}
NSS_IMPLEMENT void
nssSlot_ResetDelay(
NSSSlot *slot)
{
slot->lastTokenPing = 0;
}
static PRBool
within_token_delay_period(NSSSlot *slot)
{
PRIntervalTime time, lastTime;
/* Set the delay time for checking the token presence */
if (s_token_delay_time == 0) {
s_token_delay_time = PR_SecondsToInterval(NSSSLOT_TOKEN_DELAY_TIME);
}
time = PR_IntervalNow();
lastTime = slot->lastTokenPing;
if ((lastTime) && ((time - lastTime) < s_token_delay_time)) {
return PR_TRUE;
}
slot->lastTokenPing = time;
return PR_FALSE;
}
NSS_IMPLEMENT PRBool
nssSlot_IsTokenPresent(
NSSSlot *slot)
{
CK_RV ckrv;
PRStatus nssrv;
/* XXX */
nssSession *session;
CK_SLOT_INFO slotInfo;
void *epv;
/* permanent slots are always present unless they're disabled */
if (nssSlot_IsPermanent(slot)) {
return !PK11_IsDisabled(slot->pk11slot);
}
/* avoid repeated calls to check token status within set interval */
if (within_token_delay_period(slot)) {
return ((slot->ckFlags & CKF_TOKEN_PRESENT) != 0);
}
/* First obtain the slot info */
epv = slot->epv;
if (!epv) {
return PR_FALSE;
}
nssSlot_EnterMonitor(slot);
ckrv = CKAPI(epv)->C_GetSlotInfo(slot->slotID, &slotInfo);
nssSlot_ExitMonitor(slot);
if (ckrv != CKR_OK) {
slot->token->base.name[0] = 0; /* XXX */
return PR_FALSE;
}
slot->ckFlags = slotInfo.flags;
/* check for the presence of the token */
if ((slot->ckFlags & CKF_TOKEN_PRESENT) == 0) {
if (!slot->token) {
/* token was never present */
return PR_FALSE;
}
session = nssToken_GetDefaultSession(slot->token);
if (session) {
nssSession_EnterMonitor(session);
/* token is not present */
if (session->handle != CK_INVALID_SESSION) {
/* session is valid, close and invalidate it */
CKAPI(epv)
->C_CloseSession(session->handle);
session->handle = CK_INVALID_SESSION;
}
nssSession_ExitMonitor(session);
}
if (slot->token->base.name[0] != 0) {
/* notify the high-level cache that the token is removed */
slot->token->base.name[0] = 0; /* XXX */
nssToken_NotifyCertsNotVisible(slot->token);
}
slot->token->base.name[0] = 0; /* XXX */
/* clear the token cache */
nssToken_Remove(slot->token);
return PR_FALSE;
}
/* token is present, use the session info to determine if the card
* has been removed and reinserted.
*/
session = nssToken_GetDefaultSession(slot->token);
if (session) {
PRBool isPresent = PR_FALSE;
nssSession_EnterMonitor(session);
if (session->handle != CK_INVALID_SESSION) {
CK_SESSION_INFO sessionInfo;
ckrv = CKAPI(epv)->C_GetSessionInfo(session->handle, &sessionInfo);
if (ckrv != CKR_OK) {
/* session is screwy, close and invalidate it */
CKAPI(epv)
->C_CloseSession(session->handle);
session->handle = CK_INVALID_SESSION;
}
}
isPresent = session->handle != CK_INVALID_SESSION;
nssSession_ExitMonitor(session);
/* token not removed, finished */
if (isPresent)
return PR_TRUE;
}
/* the token has been removed, and reinserted, or the slot contains
* a token it doesn't recognize. invalidate all the old
* information we had on this token, if we can't refresh, clear
* the present flag */
nssToken_NotifyCertsNotVisible(slot->token);
nssToken_Remove(slot->token);
/* token has been removed, need to refresh with new session */
nssrv = nssSlot_Refresh(slot);
if (nssrv != PR_SUCCESS) {
slot->token->base.name[0] = 0; /* XXX */
slot->ckFlags &= ~CKF_TOKEN_PRESENT;
return PR_FALSE;
}
return PR_TRUE;
}
NSS_IMPLEMENT void *
nssSlot_GetCryptokiEPV(
NSSSlot *slot)
{
return slot->epv;
}
NSS_IMPLEMENT NSSToken *
nssSlot_GetToken(
NSSSlot *slot)
{
if (nssSlot_IsTokenPresent(slot)) {
return nssToken_AddRef(slot->token);
}
return (NSSToken *)NULL;
}
NSS_IMPLEMENT PRStatus
nssSession_EnterMonitor(
nssSession *s)
{
if (s->lock)
PZ_Lock(s->lock);
return PR_SUCCESS;
}
NSS_IMPLEMENT PRStatus
nssSession_ExitMonitor(
nssSession *s)
{
return (s->lock) ? PZ_Unlock(s->lock) : PR_SUCCESS;
}
NSS_EXTERN PRBool
nssSession_IsReadWrite(
nssSession *s)
{
return s->isRW;
}

147
security/nss/lib/dev/devt.h Normal file
View file

@ -0,0 +1,147 @@
/* 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 DEVT_H
#define DEVT_H
/*
* devt.h
*
* This file contains definitions for the low-level cryptoki devices.
*/
#ifndef NSSBASET_H
#include "nssbaset.h"
#endif /* NSSBASET_H */
#ifndef NSSPKIT_H
#include "nsspkit.h"
#endif /* NSSPKIT_H */
#ifndef NSSDEVT_H
#include "nssdevt.h"
#endif /* NSSDEVT_H */
#ifndef BASET_H
#include "baset.h"
#endif /* BASET_H */
#include "secmodt.h"
PR_BEGIN_EXTERN_C
typedef struct nssSessionStr nssSession;
/* XXX until NSSTokenStr is moved */
struct nssDeviceBaseStr {
NSSArena *arena;
PZLock *lock;
PRInt32 refCount;
NSSUTF8 *name;
PRUint32 flags;
};
typedef struct nssTokenObjectCacheStr nssTokenObjectCache;
/* XXX until devobject.c goes away */
struct NSSTokenStr {
struct nssDeviceBaseStr base;
NSSSlot *slot; /* Parent (or peer, if you will) */
CK_FLAGS ckFlags; /* from CK_TOKEN_INFO.flags */
PRUint32 flags;
void *epv;
nssSession *defaultSession;
NSSTrustDomain *trustDomain;
PRIntervalTime lastTime;
nssTokenObjectCache *cache;
PK11SlotInfo *pk11slot;
};
typedef enum {
nssSlotAskPasswordTimes_FirstTime = 0,
nssSlotAskPasswordTimes_EveryTime = 1,
nssSlotAskPasswordTimes_Timeout = 2
} nssSlotAskPasswordTimes;
struct nssSlotAuthInfoStr {
PRTime lastLogin;
nssSlotAskPasswordTimes askTimes;
PRIntervalTime askPasswordTimeout;
};
struct NSSSlotStr {
struct nssDeviceBaseStr base;
NSSModule *module; /* Parent */
NSSToken *token; /* Peer */
CK_SLOT_ID slotID;
CK_FLAGS ckFlags; /* from CK_SLOT_INFO.flags */
struct nssSlotAuthInfoStr authInfo;
PRIntervalTime lastTokenPing;
PZLock *lock;
void *epv;
PK11SlotInfo *pk11slot;
};
struct nssSessionStr {
PZLock *lock;
CK_SESSION_HANDLE handle;
NSSSlot *slot;
PRBool isRW;
PRBool ownLock;
};
typedef enum {
NSSCertificateType_Unknown = 0,
NSSCertificateType_PKIX = 1
} NSSCertificateType;
typedef enum {
nssTrustLevel_Unknown = 0,
nssTrustLevel_NotTrusted = 1,
nssTrustLevel_Trusted = 2,
nssTrustLevel_TrustedDelegator = 3,
nssTrustLevel_MustVerify = 4,
nssTrustLevel_ValidDelegator = 5
} nssTrustLevel;
typedef struct nssCryptokiInstanceStr nssCryptokiInstance;
struct nssCryptokiInstanceStr {
CK_OBJECT_HANDLE handle;
NSSToken *token;
PRBool isTokenObject;
NSSUTF8 *label;
};
typedef struct nssCryptokiInstanceStr nssCryptokiObject;
typedef struct nssTokenCertSearchStr nssTokenCertSearch;
typedef enum {
nssTokenSearchType_AllObjects = 0,
nssTokenSearchType_SessionOnly = 1,
nssTokenSearchType_TokenOnly = 2,
nssTokenSearchType_TokenForced = 3
} nssTokenSearchType;
struct nssTokenCertSearchStr {
nssTokenSearchType searchType;
PRStatus (*callback)(NSSCertificate *c, void *arg);
void *cbarg;
nssList *cached;
/* TODO: add a cache query callback if the list would be large
* (traversal)
*/
};
struct nssSlotListStr;
typedef struct nssSlotListStr nssSlotList;
struct NSSAlgorithmAndParametersStr {
CK_MECHANISM mechanism;
};
PR_END_EXTERN_C
#endif /* DEVT_H */

View file

@ -0,0 +1,25 @@
/* 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 DEVTM_H
#define DEVTM_H
/*
* devtm.h
*
* This file contains module-private definitions for the low-level
* cryptoki devices.
*/
#ifndef DEVT_H
#include "devt.h"
#endif /* DEVT_H */
PR_BEGIN_EXTERN_C
#define MAX_LOCAL_CACHE_OBJECTS 10
PR_END_EXTERN_C
#endif /* DEVTM_H */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,998 @@
/* 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 DEVM_H
#include "devm.h"
#endif /* DEVM_H */
#ifndef CKHELPER_H
#include "ckhelper.h"
#endif /* CKHELPER_H */
NSS_IMPLEMENT nssCryptokiObject *
nssCryptokiObject_Create(
NSSToken *t,
nssSession *session,
CK_OBJECT_HANDLE h)
{
PRStatus status;
NSSSlot *slot;
nssCryptokiObject *object;
CK_BBOOL *isTokenObject;
CK_ATTRIBUTE cert_template[] = {
{ CKA_TOKEN, NULL, 0 },
{ CKA_LABEL, NULL, 0 }
};
slot = nssToken_GetSlot(t);
status = nssCKObject_GetAttributes(h, cert_template, 2,
NULL, session, slot);
nssSlot_Destroy(slot);
if (status != PR_SUCCESS) {
/* a failure here indicates a device error */
return (nssCryptokiObject *)NULL;
}
object = nss_ZNEW(NULL, nssCryptokiObject);
if (!object) {
return (nssCryptokiObject *)NULL;
}
object->handle = h;
object->token = nssToken_AddRef(t);
isTokenObject = (CK_BBOOL *)cert_template[0].pValue;
object->isTokenObject = *isTokenObject;
nss_ZFreeIf(isTokenObject);
NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label);
return object;
}
NSS_IMPLEMENT void
nssCryptokiObject_Destroy(
nssCryptokiObject *object)
{
if (object) {
nssToken_Destroy(object->token);
nss_ZFreeIf(object->label);
nss_ZFreeIf(object);
}
}
NSS_IMPLEMENT nssCryptokiObject *
nssCryptokiObject_Clone(
nssCryptokiObject *object)
{
nssCryptokiObject *rvObject;
rvObject = nss_ZNEW(NULL, nssCryptokiObject);
if (rvObject) {
rvObject->handle = object->handle;
rvObject->token = nssToken_AddRef(object->token);
rvObject->isTokenObject = object->isTokenObject;
if (object->label) {
rvObject->label = nssUTF8_Duplicate(object->label, NULL);
}
}
return rvObject;
}
NSS_EXTERN PRBool
nssCryptokiObject_Equal(
nssCryptokiObject *o1,
nssCryptokiObject *o2)
{
return (o1->token == o2->token && o1->handle == o2->handle);
}
NSS_IMPLEMENT PRUint32
nssPKCS11String_Length(CK_CHAR *pkcs11Str, PRUint32 bufLen)
{
PRInt32 i;
for (i = bufLen - 1; i >= 0;) {
if (pkcs11Str[i] != ' ' && pkcs11Str[i] != '\0')
break;
--i;
}
return (PRUint32)(i + 1);
}
/*
* Slot arrays
*/
NSS_IMPLEMENT NSSSlot **
nssSlotArray_Clone(
NSSSlot **slots)
{
NSSSlot **rvSlots = NULL;
NSSSlot **sp = slots;
PRUint32 count = 0;
while (sp && *sp)
count++;
if (count > 0) {
rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
if (rvSlots) {
for (sp = slots, count = 0; *sp; sp++) {
rvSlots[count++] = nssSlot_AddRef(*sp);
}
}
}
return rvSlots;
}
NSS_IMPLEMENT void
nssSlotArray_Destroy(
NSSSlot **slots)
{
if (slots) {
NSSSlot **slotp;
for (slotp = slots; *slotp; slotp++) {
nssSlot_Destroy(*slotp);
}
nss_ZFreeIf(slots);
}
}
NSS_IMPLEMENT void
NSSSlotArray_Destroy(
NSSSlot **slots)
{
nssSlotArray_Destroy(slots);
}
NSS_IMPLEMENT void
nssTokenArray_Destroy(
NSSToken **tokens)
{
if (tokens) {
NSSToken **tokenp;
for (tokenp = tokens; *tokenp; tokenp++) {
nssToken_Destroy(*tokenp);
}
nss_ZFreeIf(tokens);
}
}
NSS_IMPLEMENT void
NSSTokenArray_Destroy(
NSSToken **tokens)
{
nssTokenArray_Destroy(tokens);
}
NSS_IMPLEMENT void
nssCryptokiObjectArray_Destroy(
nssCryptokiObject **objects)
{
if (objects) {
nssCryptokiObject **op;
for (op = objects; *op; op++) {
nssCryptokiObject_Destroy(*op);
}
nss_ZFreeIf(objects);
}
}
/* object cache for token */
typedef struct
{
NSSArena *arena;
nssCryptokiObject *object;
CK_ATTRIBUTE_PTR attributes;
CK_ULONG numAttributes;
} nssCryptokiObjectAndAttributes;
enum {
cachedCerts = 0,
cachedTrust = 1,
cachedCRLs = 2
} cachedObjectType;
struct nssTokenObjectCacheStr {
NSSToken *token;
PZLock *lock;
PRBool loggedIn;
PRBool doObjectType[3];
PRBool searchedObjectType[3];
nssCryptokiObjectAndAttributes **objects[3];
};
NSS_IMPLEMENT nssTokenObjectCache *
nssTokenObjectCache_Create(
NSSToken *token,
PRBool cacheCerts,
PRBool cacheTrust,
PRBool cacheCRLs)
{
nssTokenObjectCache *rvCache;
rvCache = nss_ZNEW(NULL, nssTokenObjectCache);
if (!rvCache) {
goto loser;
}
rvCache->lock = PZ_NewLock(nssILockOther); /* XXX */
if (!rvCache->lock) {
goto loser;
}
rvCache->doObjectType[cachedCerts] = cacheCerts;
rvCache->doObjectType[cachedTrust] = cacheTrust;
rvCache->doObjectType[cachedCRLs] = cacheCRLs;
rvCache->token = token; /* cache goes away with token */
return rvCache;
loser:
nssTokenObjectCache_Destroy(rvCache);
return (nssTokenObjectCache *)NULL;
}
static void
clear_cache(
nssTokenObjectCache *cache)
{
nssCryptokiObjectAndAttributes **oa;
PRUint32 objectType;
for (objectType = cachedCerts; objectType <= cachedCRLs; objectType++) {
cache->searchedObjectType[objectType] = PR_FALSE;
if (!cache->objects[objectType]) {
continue;
}
for (oa = cache->objects[objectType]; *oa; oa++) {
/* prevent the token from being destroyed */
(*oa)->object->token = NULL;
nssCryptokiObject_Destroy((*oa)->object);
nssArena_Destroy((*oa)->arena);
}
nss_ZFreeIf(cache->objects[objectType]);
cache->objects[objectType] = NULL;
}
}
NSS_IMPLEMENT void
nssTokenObjectCache_Clear(
nssTokenObjectCache *cache)
{
if (cache) {
PZ_Lock(cache->lock);
clear_cache(cache);
PZ_Unlock(cache->lock);
}
}
NSS_IMPLEMENT void
nssTokenObjectCache_Destroy(
nssTokenObjectCache *cache)
{
if (cache) {
clear_cache(cache);
if (cache->lock) {
PZ_DestroyLock(cache->lock);
}
nss_ZFreeIf(cache);
}
}
NSS_IMPLEMENT PRBool
nssTokenObjectCache_HaveObjectClass(
nssTokenObjectCache *cache,
CK_OBJECT_CLASS objclass)
{
PRBool haveIt;
PZ_Lock(cache->lock);
switch (objclass) {
case CKO_CERTIFICATE:
haveIt = cache->doObjectType[cachedCerts];
break;
case CKO_NETSCAPE_TRUST:
haveIt = cache->doObjectType[cachedTrust];
break;
case CKO_NETSCAPE_CRL:
haveIt = cache->doObjectType[cachedCRLs];
break;
default:
haveIt = PR_FALSE;
}
PZ_Unlock(cache->lock);
return haveIt;
}
static nssCryptokiObjectAndAttributes **
create_object_array(
nssCryptokiObject **objects,
PRBool *doObjects,
PRUint32 *numObjects,
PRStatus *status)
{
nssCryptokiObjectAndAttributes **rvOandA = NULL;
*numObjects = 0;
/* There are no objects for this type */
if (!objects || !*objects) {
*status = PR_SUCCESS;
return rvOandA;
}
while (*objects++)
(*numObjects)++;
if (*numObjects >= MAX_LOCAL_CACHE_OBJECTS) {
/* Hit the maximum allowed, so don't use a cache (there are
* too many objects to make caching worthwhile, presumably, if
* the token can handle that many objects, it can handle searching.
*/
*doObjects = PR_FALSE;
*status = PR_FAILURE;
*numObjects = 0;
} else {
rvOandA = nss_ZNEWARRAY(NULL,
nssCryptokiObjectAndAttributes *,
*numObjects + 1);
*status = rvOandA ? PR_SUCCESS : PR_FAILURE;
}
return rvOandA;
}
static nssCryptokiObjectAndAttributes *
create_object(
nssCryptokiObject *object,
const CK_ATTRIBUTE_TYPE *types,
PRUint32 numTypes,
PRStatus *status)
{
PRUint32 j;
NSSArena *arena = NULL;
NSSSlot *slot = NULL;
nssSession *session = NULL;
nssCryptokiObjectAndAttributes *rvCachedObject = NULL;
slot = nssToken_GetSlot(object->token);
if (!slot) {
nss_SetError(NSS_ERROR_INVALID_POINTER);
goto loser;
}
session = nssToken_GetDefaultSession(object->token);
if (!session) {
nss_SetError(NSS_ERROR_INVALID_POINTER);
goto loser;
}
arena = nssArena_Create();
if (!arena) {
goto loser;
}
rvCachedObject = nss_ZNEW(arena, nssCryptokiObjectAndAttributes);
if (!rvCachedObject) {
goto loser;
}
rvCachedObject->arena = arena;
/* The cache is tied to the token, and therefore the objects
* in it should not hold references to the token.
*/
nssToken_Destroy(object->token);
rvCachedObject->object = object;
rvCachedObject->attributes = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, numTypes);
if (!rvCachedObject->attributes) {
goto loser;
}
for (j = 0; j < numTypes; j++) {
rvCachedObject->attributes[j].type = types[j];
}
*status = nssCKObject_GetAttributes(object->handle,
rvCachedObject->attributes,
numTypes,
arena,
session,
slot);
if (*status != PR_SUCCESS) {
goto loser;
}
rvCachedObject->numAttributes = numTypes;
*status = PR_SUCCESS;
nssSlot_Destroy(slot);
return rvCachedObject;
loser:
*status = PR_FAILURE;
if (slot) {
nssSlot_Destroy(slot);
}
if (arena)
nssArena_Destroy(arena);
return (nssCryptokiObjectAndAttributes *)NULL;
}
/*
*
* State diagram for cache:
*
* token !present token removed
* +-------------------------+<----------------------+
* | ^ |
* v | |
* +----------+ slot friendly | token present +----------+
* | cache | -----------------> % ---------------> | cache |
* | unloaded | | loaded |
* +----------+ +----------+
* ^ | ^ |
* | | slot !friendly slot logged in | |
* | +-----------------------> % ----------------------+ |
* | | |
* | slot logged out v slot !friendly |
* +-----------------------------+<--------------------------+
*
*/
/* This function must not be called with cache->lock locked. */
static PRBool
token_is_present(
nssTokenObjectCache *cache)
{
NSSSlot *slot = nssToken_GetSlot(cache->token);
PRBool tokenPresent = nssSlot_IsTokenPresent(slot);
nssSlot_Destroy(slot);
return tokenPresent;
}
static PRBool
search_for_objects(
nssTokenObjectCache *cache)
{
PRBool doSearch = PR_FALSE;
NSSSlot *slot = nssToken_GetSlot(cache->token);
/* Handle non-friendly slots (slots which require login for objects) */
if (!nssSlot_IsFriendly(slot)) {
if (nssSlot_IsLoggedIn(slot)) {
/* Either no state change, or went from !logged in -> logged in */
cache->loggedIn = PR_TRUE;
doSearch = PR_TRUE;
} else {
if (cache->loggedIn) {
/* went from logged in -> !logged in, destroy cached objects */
clear_cache(cache);
cache->loggedIn = PR_FALSE;
} /* else no state change, still not logged in, so exit */
}
} else {
/* slot is friendly, thus always available for search */
doSearch = PR_TRUE;
}
nssSlot_Destroy(slot);
return doSearch;
}
static nssCryptokiObjectAndAttributes *
create_cert(
nssCryptokiObject *object,
PRStatus *status)
{
static const CK_ATTRIBUTE_TYPE certAttr[] = {
CKA_CLASS,
CKA_TOKEN,
CKA_LABEL,
CKA_CERTIFICATE_TYPE,
CKA_ID,
CKA_VALUE,
CKA_ISSUER,
CKA_SERIAL_NUMBER,
CKA_SUBJECT,
CKA_NETSCAPE_EMAIL
};
static const PRUint32 numCertAttr = sizeof(certAttr) / sizeof(certAttr[0]);
return create_object(object, certAttr, numCertAttr, status);
}
static nssCryptokiObjectAndAttributes *
create_trust(
nssCryptokiObject *object,
PRStatus *status)
{
static const CK_ATTRIBUTE_TYPE trustAttr[] = {
CKA_CLASS,
CKA_TOKEN,
CKA_LABEL,
CKA_CERT_SHA1_HASH,
CKA_CERT_MD5_HASH,
CKA_ISSUER,
CKA_SUBJECT,
CKA_TRUST_SERVER_AUTH,
CKA_TRUST_CLIENT_AUTH,
CKA_TRUST_EMAIL_PROTECTION,
CKA_TRUST_CODE_SIGNING
};
static const PRUint32 numTrustAttr = sizeof(trustAttr) / sizeof(trustAttr[0]);
return create_object(object, trustAttr, numTrustAttr, status);
}
static nssCryptokiObjectAndAttributes *
create_crl(
nssCryptokiObject *object,
PRStatus *status)
{
static const CK_ATTRIBUTE_TYPE crlAttr[] = {
CKA_CLASS,
CKA_TOKEN,
CKA_LABEL,
CKA_VALUE,
CKA_SUBJECT,
CKA_NETSCAPE_KRL,
CKA_NETSCAPE_URL
};
static const PRUint32 numCRLAttr = sizeof(crlAttr) / sizeof(crlAttr[0]);
return create_object(object, crlAttr, numCRLAttr, status);
}
/* Dispatch to the create function for the object type */
static nssCryptokiObjectAndAttributes *
create_object_of_type(
nssCryptokiObject *object,
PRUint32 objectType,
PRStatus *status)
{
if (objectType == cachedCerts) {
return create_cert(object, status);
}
if (objectType == cachedTrust) {
return create_trust(object, status);
}
if (objectType == cachedCRLs) {
return create_crl(object, status);
}
return (nssCryptokiObjectAndAttributes *)NULL;
}
static PRStatus
get_token_objects_for_cache(
nssTokenObjectCache *cache,
PRUint32 objectType,
CK_OBJECT_CLASS objclass)
{
PRStatus status;
nssCryptokiObject **objects;
PRBool *doIt = &cache->doObjectType[objectType];
PRUint32 i, numObjects;
if (!search_for_objects(cache) ||
cache->searchedObjectType[objectType] ||
!cache->doObjectType[objectType]) {
/* Either there was a state change that prevents a search
* (token logged out), or the search was already done,
* or objects of this type are not being cached.
*/
return PR_SUCCESS;
}
objects = nssToken_FindObjects(cache->token, NULL, objclass,
nssTokenSearchType_TokenForced,
MAX_LOCAL_CACHE_OBJECTS, &status);
if (status != PR_SUCCESS) {
return status;
}
cache->objects[objectType] = create_object_array(objects,
doIt,
&numObjects,
&status);
if (status != PR_SUCCESS) {
nss_ZFreeIf(objects);
return status;
}
for (i = 0; i < numObjects; i++) {
cache->objects[objectType][i] = create_object_of_type(objects[i],
objectType,
&status);
if (status != PR_SUCCESS) {
break;
}
}
if (status == PR_SUCCESS) {
nss_ZFreeIf(objects);
} else {
PRUint32 j;
for (j = 0; j < i; j++) {
/* sigh */
nssToken_AddRef(cache->objects[objectType][j]->object->token);
nssArena_Destroy(cache->objects[objectType][j]->arena);
}
nss_ZFreeIf(cache->objects[objectType]);
cache->objects[objectType] = NULL;
nssCryptokiObjectArray_Destroy(objects);
}
cache->searchedObjectType[objectType] = PR_TRUE;
return status;
}
static CK_ATTRIBUTE_PTR
find_attribute_in_object(
nssCryptokiObjectAndAttributes *obj,
CK_ATTRIBUTE_TYPE attrType)
{
PRUint32 j;
for (j = 0; j < obj->numAttributes; j++) {
if (attrType == obj->attributes[j].type) {
return &obj->attributes[j];
}
}
return (CK_ATTRIBUTE_PTR)NULL;
}
/* Find all objects in the array that match the supplied template */
static nssCryptokiObject **
find_objects_in_array(
nssCryptokiObjectAndAttributes **objArray,
CK_ATTRIBUTE_PTR ot,
CK_ULONG otlen,
PRUint32 maximumOpt)
{
PRIntn oi = 0;
PRUint32 i;
NSSArena *arena;
PRUint32 size = 8;
PRUint32 numMatches = 0;
nssCryptokiObject **objects = NULL;
nssCryptokiObjectAndAttributes **matches = NULL;
CK_ATTRIBUTE_PTR attr;
if (!objArray) {
return (nssCryptokiObject **)NULL;
}
arena = nssArena_Create();
if (!arena) {
return (nssCryptokiObject **)NULL;
}
matches = nss_ZNEWARRAY(arena, nssCryptokiObjectAndAttributes *, size);
if (!matches) {
goto loser;
}
if (maximumOpt == 0)
maximumOpt = ~0;
/* loop over the cached objects */
for (; *objArray && numMatches < maximumOpt; objArray++) {
nssCryptokiObjectAndAttributes *obj = *objArray;
/* loop over the test template */
for (i = 0; i < otlen; i++) {
/* see if the object has the attribute */
attr = find_attribute_in_object(obj, ot[i].type);
if (!attr) {
/* nope, match failed */
break;
}
/* compare the attribute against the test value */
if (ot[i].ulValueLen != attr->ulValueLen ||
!nsslibc_memequal(ot[i].pValue,
attr->pValue,
attr->ulValueLen, NULL)) {
/* nope, match failed */
break;
}
}
if (i == otlen) {
/* all of the attributes in the test template were found
* in the object's template, and they all matched
*/
matches[numMatches++] = obj;
if (numMatches == size) {
size *= 2;
matches = nss_ZREALLOCARRAY(matches,
nssCryptokiObjectAndAttributes *,
size);
if (!matches) {
goto loser;
}
}
}
}
if (numMatches > 0) {
objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numMatches + 1);
if (!objects) {
goto loser;
}
for (oi = 0; oi < (PRIntn)numMatches; oi++) {
objects[oi] = nssCryptokiObject_Clone(matches[oi]->object);
if (!objects[oi]) {
goto loser;
}
}
}
nssArena_Destroy(arena);
return objects;
loser:
nssCryptokiObjectArray_Destroy(objects);
nssArena_Destroy(arena);
return (nssCryptokiObject **)NULL;
}
NSS_IMPLEMENT nssCryptokiObject **
nssTokenObjectCache_FindObjectsByTemplate(
nssTokenObjectCache *cache,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR otemplate,
CK_ULONG otlen,
PRUint32 maximumOpt,
PRStatus *statusOpt)
{
PRStatus status = PR_FAILURE;
nssCryptokiObject **rvObjects = NULL;
PRUint32 objectType;
if (!token_is_present(cache)) {
status = PR_SUCCESS;
goto finish;
}
switch (objclass) {
case CKO_CERTIFICATE:
objectType = cachedCerts;
break;
case CKO_NETSCAPE_TRUST:
objectType = cachedTrust;
break;
case CKO_NETSCAPE_CRL:
objectType = cachedCRLs;
break;
default:
goto finish;
}
PZ_Lock(cache->lock);
if (cache->doObjectType[objectType]) {
status = get_token_objects_for_cache(cache, objectType, objclass);
if (status == PR_SUCCESS) {
rvObjects = find_objects_in_array(cache->objects[objectType],
otemplate, otlen, maximumOpt);
}
}
PZ_Unlock(cache->lock);
finish:
if (statusOpt) {
*statusOpt = status;
}
return rvObjects;
}
static PRBool
cache_available_for_object_type(
nssTokenObjectCache *cache,
PRUint32 objectType)
{
if (!cache->doObjectType[objectType]) {
/* not caching this object kind */
return PR_FALSE;
}
if (!cache->searchedObjectType[objectType]) {
/* objects are not cached yet */
return PR_FALSE;
}
if (!search_for_objects(cache)) {
/* not logged in */
return PR_FALSE;
}
return PR_TRUE;
}
NSS_IMPLEMENT PRStatus
nssTokenObjectCache_GetObjectAttributes(
nssTokenObjectCache *cache,
NSSArena *arenaOpt,
nssCryptokiObject *object,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR atemplate,
CK_ULONG atlen)
{
PRUint32 i, j;
NSSArena *arena = NULL;
nssArenaMark *mark = NULL;
nssCryptokiObjectAndAttributes *cachedOA = NULL;
nssCryptokiObjectAndAttributes **oa = NULL;
PRUint32 objectType;
if (!token_is_present(cache)) {
return PR_FAILURE;
}
PZ_Lock(cache->lock);
switch (objclass) {
case CKO_CERTIFICATE:
objectType = cachedCerts;
break;
case CKO_NETSCAPE_TRUST:
objectType = cachedTrust;
break;
case CKO_NETSCAPE_CRL:
objectType = cachedCRLs;
break;
default:
goto loser;
}
if (!cache_available_for_object_type(cache, objectType)) {
goto loser;
}
oa = cache->objects[objectType];
if (!oa) {
goto loser;
}
for (; *oa; oa++) {
if (nssCryptokiObject_Equal((*oa)->object, object)) {
cachedOA = *oa;
break;
}
}
if (!cachedOA) {
goto loser; /* don't have this object */
}
if (arenaOpt) {
arena = arenaOpt;
mark = nssArena_Mark(arena);
}
for (i = 0; i < atlen; i++) {
for (j = 0; j < cachedOA->numAttributes; j++) {
if (atemplate[i].type == cachedOA->attributes[j].type) {
CK_ATTRIBUTE_PTR attr = &cachedOA->attributes[j];
if (cachedOA->attributes[j].ulValueLen == 0 ||
cachedOA->attributes[j].ulValueLen == (CK_ULONG)-1) {
break; /* invalid attribute */
}
if (atemplate[i].ulValueLen > 0) {
if (atemplate[i].pValue == NULL ||
atemplate[i].ulValueLen < attr->ulValueLen) {
goto loser;
}
} else {
atemplate[i].pValue = nss_ZAlloc(arena, attr->ulValueLen);
if (!atemplate[i].pValue) {
goto loser;
}
}
nsslibc_memcpy(atemplate[i].pValue,
attr->pValue, attr->ulValueLen);
atemplate[i].ulValueLen = attr->ulValueLen;
break;
}
}
if (j == cachedOA->numAttributes) {
atemplate[i].ulValueLen = (CK_ULONG)-1;
}
}
PZ_Unlock(cache->lock);
if (mark) {
nssArena_Unmark(arena, mark);
}
return PR_SUCCESS;
loser:
PZ_Unlock(cache->lock);
if (mark) {
nssArena_Release(arena, mark);
}
return PR_FAILURE;
}
NSS_IMPLEMENT PRStatus
nssTokenObjectCache_ImportObject(
nssTokenObjectCache *cache,
nssCryptokiObject *object,
CK_OBJECT_CLASS objclass,
CK_ATTRIBUTE_PTR ot,
CK_ULONG otlen)
{
PRStatus status = PR_SUCCESS;
PRUint32 count;
nssCryptokiObjectAndAttributes **oa, ***otype;
PRUint32 objectType;
PRBool haveIt = PR_FALSE;
if (!token_is_present(cache)) {
return PR_SUCCESS; /* cache not active, ignored */
}
PZ_Lock(cache->lock);
switch (objclass) {
case CKO_CERTIFICATE:
objectType = cachedCerts;
break;
case CKO_NETSCAPE_TRUST:
objectType = cachedTrust;
break;
case CKO_NETSCAPE_CRL:
objectType = cachedCRLs;
break;
default:
PZ_Unlock(cache->lock);
return PR_SUCCESS; /* don't need to import it here */
}
if (!cache_available_for_object_type(cache, objectType)) {
PZ_Unlock(cache->lock);
return PR_SUCCESS; /* cache not active, ignored */
}
count = 0;
otype = &cache->objects[objectType]; /* index into array of types */
oa = *otype; /* the array of objects for this type */
while (oa && *oa) {
if (nssCryptokiObject_Equal((*oa)->object, object)) {
haveIt = PR_TRUE;
break;
}
count++;
oa++;
}
if (haveIt) {
/* Destroy the old entry */
(*oa)->object->token = NULL;
nssCryptokiObject_Destroy((*oa)->object);
nssArena_Destroy((*oa)->arena);
} else {
/* Create space for a new entry */
if (count > 0) {
*otype = nss_ZREALLOCARRAY(*otype,
nssCryptokiObjectAndAttributes *,
count + 2);
} else {
*otype = nss_ZNEWARRAY(NULL, nssCryptokiObjectAndAttributes *, 2);
}
}
if (*otype) {
nssCryptokiObject *copyObject = nssCryptokiObject_Clone(object);
(*otype)[count] = create_object_of_type(copyObject, objectType,
&status);
} else {
status = PR_FAILURE;
}
PZ_Unlock(cache->lock);
return status;
}
NSS_IMPLEMENT void
nssTokenObjectCache_RemoveObject(
nssTokenObjectCache *cache,
nssCryptokiObject *object)
{
PRUint32 oType;
nssCryptokiObjectAndAttributes **oa, **swp = NULL;
if (!token_is_present(cache)) {
return;
}
PZ_Lock(cache->lock);
for (oType = 0; oType < 3; oType++) {
if (!cache_available_for_object_type(cache, oType) ||
!cache->objects[oType]) {
continue;
}
for (oa = cache->objects[oType]; *oa; oa++) {
if (nssCryptokiObject_Equal((*oa)->object, object)) {
swp = oa; /* the entry to remove */
while (oa[1])
oa++; /* go to the tail */
(*swp)->object->token = NULL;
nssCryptokiObject_Destroy((*swp)->object);
nssArena_Destroy((*swp)->arena); /* destroy it */
*swp = *oa; /* swap the last with the removed */
*oa = NULL; /* null-terminate the array */
break;
}
}
if (swp) {
break;
}
}
if ((oType < 3) &&
cache->objects[oType] && cache->objects[oType][0] == NULL) {
nss_ZFreeIf(cache->objects[oType]); /* no entries remaining */
cache->objects[oType] = NULL;
}
PZ_Unlock(cache->lock);
}
/* These two hash algorithms are presently sufficient.
** They are used for fingerprints of certs which are stored as the
** CKA_CERT_SHA1_HASH and CKA_CERT_MD5_HASH attributes.
** We don't need to add SHAxxx to these now.
*/
/* XXX of course this doesn't belong here */
NSS_IMPLEMENT NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateSHA1Digest(
NSSArena *arenaOpt)
{
NSSAlgorithmAndParameters *rvAP = NULL;
rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters);
if (rvAP) {
rvAP->mechanism.mechanism = CKM_SHA_1;
rvAP->mechanism.pParameter = NULL;
rvAP->mechanism.ulParameterLen = 0;
}
return rvAP;
}
NSS_IMPLEMENT NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateMD5Digest(
NSSArena *arenaOpt)
{
NSSAlgorithmAndParameters *rvAP = NULL;
rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters);
if (rvAP) {
rvAP->mechanism.mechanism = CKM_MD5;
rvAP->mechanism.pParameter = NULL;
rvAP->mechanism.ulParameterLen = 0;
}
return rvAP;
}

View file

@ -0,0 +1,31 @@
# 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_dev_exports',
'type': 'none',
'copies': [
{
'files': [
'ckhelper.h',
'dev.h',
'devm.h',
'devt.h',
'devtm.h',
'nssdev.h',
'nssdevt.h'
],
'destination': '<(nss_private_dist_dir)/<(module)'
}
]
}
],
'variables': {
'module': 'nss'
}
}

View file

@ -0,0 +1,35 @@
#
# 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 = ../..
PRIVATE_EXPORTS = \
ckhelper.h \
devm.h \
devtm.h \
devt.h \
dev.h \
nssdevt.h \
nssdev.h \
$(NULL)
EXPORTS = \
$(NULL)
MODULE = nss
CSRCS = \
devslot.c \
devtoken.c \
devutil.c \
ckhelper.c \
$(NULL)
REQUIRES = nspr
LIBRARY_NAME = nssdev
# This part of the code, including all sub-dirs, can be optimized for size
export ALLOW_OPT_CODE_SIZE = 1

View file

@ -0,0 +1,36 @@
/* 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 NSSDEV_H
#define NSSDEV_H
/*
* nssdev.h
*
* High-level methods for interaction with cryptoki devices
*/
#ifndef NSSDEVT_H
#include "nssdevt.h"
#endif /* NSSDEVT_H */
PR_BEGIN_EXTERN_C
/* NSSAlgorithmAndParameters
*
* NSSAlgorithmAndParameters_CreateSHA1Digest
* NSSAlgorithmAndParameters_CreateMD5Digest
*/
NSS_EXTERN NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateSHA1Digest(
NSSArena *arenaOpt);
NSS_EXTERN NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateMD5Digest(
NSSArena *arenaOpt);
PR_END_EXTERN_C
#endif /* DEV_H */

View file

@ -0,0 +1,36 @@
/* 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 NSSDEVT_H
#define NSSDEVT_H
/*
* nssdevt.h
*
* This file contains definitions for the low-level cryptoki devices.
*/
#ifndef NSSBASET_H
#include "nssbaset.h"
#endif /* NSSBASET_H */
#ifndef NSSPKIT_H
#include "nsspkit.h"
#endif /* NSSPKIT_H */
PR_BEGIN_EXTERN_C
/*
* NSSModule and NSSSlot -- placeholders for the PKCS#11 types
*/
typedef struct NSSModuleStr NSSModule;
typedef struct NSSSlotStr NSSSlot;
typedef struct NSSTokenStr NSSToken;
PR_END_EXTERN_C
#endif /* NSSDEVT_H */