summaryrefslogtreecommitdiffstats
path: root/security/nss/lib/pk11wrap/pk11obj.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/pk11wrap/pk11obj.c')
-rw-r--r--security/nss/lib/pk11wrap/pk11obj.c132
1 files changed, 118 insertions, 14 deletions
diff --git a/security/nss/lib/pk11wrap/pk11obj.c b/security/nss/lib/pk11wrap/pk11obj.c
index 937ac654a..bc9e93454 100644
--- a/security/nss/lib/pk11wrap/pk11obj.c
+++ b/security/nss/lib/pk11wrap/pk11obj.c
@@ -4,6 +4,8 @@
/*
* This file manages object type indepentent functions.
*/
+#include <limits.h>
+
#include "seccomon.h"
#include "secmod.h"
#include "secmodi.h"
@@ -933,11 +935,11 @@ PK11_Decrypt(PK11SymKey *symKey,
if (haslock)
PK11_ExitSlotMonitor(slot);
pk11_CloseSession(slot, session, owner);
- *outLen = len;
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
+ *outLen = len;
return SECSuccess;
}
@@ -979,11 +981,11 @@ PK11_Encrypt(PK11SymKey *symKey,
if (haslock)
PK11_ExitSlotMonitor(slot);
pk11_CloseSession(slot, session, owner);
- *outLen = len;
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
return SECFailure;
}
+ *outLen = len;
return SECSuccess;
}
@@ -1665,10 +1667,10 @@ pk11_CreateGenericObjectHelper(PK11SlotInfo *slot,
/* This is the classic interface. Applications would call this function to
* create new object that would not be destroyed later. This lead to resource
* leaks (and thus memory leaks in the PKCS #11 module). To solve this we have
- * a new interface that automatically marks objects created on the fly to be
- * destroyed later.
+ * a new interface that automatically marks objects created on the fly to be
+ * destroyed later.
* The old interface is preserved because applications like Mozilla purposefully
- * leak the reference to be found later with PK11_FindGenericObjects. New
+ * leak the reference to be found later with PK11_FindGenericObjects. New
* applications should use the new interface PK11_CreateManagedGenericObject */
PK11GenericObject *
PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
@@ -1678,8 +1680,8 @@ PK11_CreateGenericObject(PK11SlotInfo *slot, const CK_ATTRIBUTE *pTemplate,
PR_FALSE);
}
-/* Use this interface. It will automatically destroy any temporary objects
- * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
+/* Use this interface. It will automatically destroy any temporary objects
+ * (token = PR_FALSE) when the PK11GenericObject is freed. Permanent objects still
* need to be destroyed by hand with PK11_DestroyTokenObject.
*/
PK11GenericObject *
@@ -1828,15 +1830,24 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
{
CK_OBJECT_HANDLE *objID = NULL;
CK_ULONG returned_count = 0;
+ PRBool owner = PR_TRUE;
+ CK_SESSION_HANDLE session;
+ PRBool haslock = PR_FALSE;
CK_RV crv = CKR_SESSION_HANDLE_INVALID;
- PK11_EnterSlotMonitor(slot);
- if (slot->session != CK_INVALID_SESSION) {
- crv = PK11_GETTAB(slot)->C_FindObjectsInit(slot->session,
+ session = pk11_GetNewSession(slot, &owner);
+ haslock = (!owner || !(slot->isThreadSafe));
+ if (haslock) {
+ PK11_EnterSlotMonitor(slot);
+ }
+ if (session != CK_INVALID_SESSION) {
+ crv = PK11_GETTAB(slot)->C_FindObjectsInit(session,
findTemplate, templCount);
}
if (crv != CKR_OK) {
- PK11_ExitSlotMonitor(slot);
+ if (haslock)
+ PK11_ExitSlotMonitor(slot);
+ pk11_CloseSession(slot, session, owner);
PORT_SetError(PK11_MapError(crv));
*object_count = -1;
return NULL;
@@ -1861,7 +1872,7 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
PORT_Free(oldObjID);
break;
}
- crv = PK11_GETTAB(slot)->C_FindObjects(slot->session,
+ crv = PK11_GETTAB(slot)->C_FindObjects(session,
&objID[*object_count], PK11_SEARCH_CHUNKSIZE, &returned_count);
if (crv != CKR_OK) {
PORT_SetError(PK11_MapError(crv));
@@ -1872,8 +1883,11 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
*object_count += returned_count;
} while (returned_count == PK11_SEARCH_CHUNKSIZE);
- PK11_GETTAB(slot)->C_FindObjectsFinal(slot->session);
- PK11_ExitSlotMonitor(slot);
+ PK11_GETTAB(slot)->C_FindObjectsFinal(session);
+ if (haslock) {
+ PK11_ExitSlotMonitor(slot);
+ }
+ pk11_CloseSession(slot, session, owner);
if (objID && (*object_count == 0)) {
PORT_Free(objID);
@@ -1883,6 +1897,96 @@ pk11_FindObjectsByTemplate(PK11SlotInfo *slot, CK_ATTRIBUTE *findTemplate,
*object_count = -1;
return objID;
}
+
+SECStatus
+PK11_FindRawCertsWithSubject(PK11SlotInfo *slot, SECItem *derSubject,
+ CERTCertificateList **results)
+{
+ if (!slot || !derSubject || !results) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+ *results = NULL;
+
+ // derSubject->data may be null. If so, derSubject->len must be 0.
+ if (!derSubject->data && derSubject->len != 0) {
+ PORT_SetError(SEC_ERROR_INVALID_ARGS);
+ return SECFailure;
+ }
+
+ CK_CERTIFICATE_TYPE ckc_x_509 = CKC_X_509;
+ CK_OBJECT_CLASS cko_certificate = CKO_CERTIFICATE;
+ CK_ATTRIBUTE subjectTemplate[] = {
+ { CKA_CERTIFICATE_TYPE, &ckc_x_509, sizeof(ckc_x_509) },
+ { CKA_CLASS, &cko_certificate, sizeof(cko_certificate) },
+ { CKA_SUBJECT, derSubject->data, derSubject->len },
+ };
+ int templateCount = sizeof(subjectTemplate) / sizeof(subjectTemplate[0]);
+ int handleCount = 0;
+ CK_OBJECT_HANDLE *handles =
+ pk11_FindObjectsByTemplate(slot, subjectTemplate, templateCount,
+ &handleCount);
+ if (!handles) {
+ // pk11_FindObjectsByTemplate indicates there was an error by setting
+ // handleCount to -1 (and it has set an error with PORT_SetError).
+ if (handleCount == -1) {
+ return SECFailure;
+ }
+ return SECSuccess;
+ }
+ PORT_Assert(handleCount > 0);
+ if (handleCount <= 0) {
+ PORT_Free(handles);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ if (handleCount > INT_MAX / sizeof(SECItem)) {
+ PORT_Free(handles);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ PLArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+ if (!arena) {
+ PORT_Free(handles);
+ return SECFailure;
+ }
+ CERTCertificateList *rawCertificates =
+ PORT_ArenaNew(arena, CERTCertificateList);
+ if (!rawCertificates) {
+ PORT_Free(handles);
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ rawCertificates->arena = arena;
+ rawCertificates->certs = PORT_ArenaNewArray(arena, SECItem, handleCount);
+ if (!rawCertificates->certs) {
+ PORT_Free(handles);
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ rawCertificates->len = handleCount;
+ int handleIndex;
+ for (handleIndex = 0; handleIndex < handleCount; handleIndex++) {
+ SECStatus rv =
+ PK11_ReadAttribute(slot, handles[handleIndex], CKA_VALUE, arena,
+ &rawCertificates->certs[handleIndex]);
+ if (rv != SECSuccess) {
+ PORT_Free(handles);
+ PORT_FreeArena(arena, PR_FALSE);
+ return SECFailure;
+ }
+ if (!rawCertificates->certs[handleIndex].data) {
+ PORT_Free(handles);
+ PORT_FreeArena(arena, PR_FALSE);
+ PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
+ return SECFailure;
+ }
+ }
+ PORT_Free(handles);
+ *results = rawCertificates;
+ return SECSuccess;
+}
+
/*
* given a PKCS #11 object, match it's peer based on the KeyID. searchID
* is typically a privateKey or a certificate while the peer is the opposite