2001-09-14 02:06:10 +04:00
|
|
|
/*
|
|
|
|
* The contents of this file are subject to the Mozilla Public
|
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
|
|
|
* the License at http://www.mozilla.org/MPL/
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed on an "AS
|
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code is the Netscape security libraries.
|
|
|
|
*
|
|
|
|
* The Initial Developer of the Original Code is Netscape
|
|
|
|
* Communications Corporation. Portions created by Netscape are
|
|
|
|
* Copyright (C) 1994-2000 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
|
|
|
* Contributor(s):
|
|
|
|
*
|
|
|
|
* Alternatively, the contents of this file may be used under the
|
|
|
|
* terms of the GNU General Public License Version 2 or later (the
|
|
|
|
* "GPL"), in which case the provisions of the GPL are applicable
|
|
|
|
* instead of those above. If you wish to allow use of your
|
|
|
|
* version of this file only under the terms of the GPL and not to
|
|
|
|
* allow others to use your version of this file under the MPL,
|
|
|
|
* indicate your decision by deleting the provisions above and
|
|
|
|
* replace them with the notice and other provisions required by
|
|
|
|
* the GPL. If you do not delete the provisions above, a recipient
|
|
|
|
* may use your version of this file under either the MPL or the
|
|
|
|
* GPL.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifdef DEBUG
|
2001-11-28 19:23:51 +03:00
|
|
|
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.3 $ $Date: 2001/11/28 16:23:39 $ $Name: $";
|
2001-09-14 02:06:10 +04:00
|
|
|
#endif /* DEBUG */
|
|
|
|
|
|
|
|
#ifndef DEV_H
|
|
|
|
#include "dev.h"
|
|
|
|
#endif /* DEV_H */
|
|
|
|
|
|
|
|
#ifndef DEVM_H
|
|
|
|
#include "devm.h"
|
|
|
|
#endif /* DEVM_H */
|
|
|
|
|
|
|
|
#ifndef NSSCKEPV_H
|
|
|
|
#include "nssckepv.h"
|
|
|
|
#endif /* NSSCKEPV_H */
|
|
|
|
|
|
|
|
#ifndef CKHELPER_H
|
|
|
|
#include "ckhelper.h"
|
|
|
|
#endif /* CKHELPER_H */
|
|
|
|
|
|
|
|
#ifndef BASE_H
|
|
|
|
#include "base.h"
|
|
|
|
#endif /* BASE_H */
|
|
|
|
|
|
|
|
/* maybe this should really inherit completely from the module... I dunno,
|
|
|
|
* any uses of slots where independence is needed?
|
|
|
|
*/
|
|
|
|
NSS_IMPLEMENT NSSToken *
|
2001-09-20 01:47:23 +04:00
|
|
|
nssToken_Create
|
2001-09-14 02:06:10 +04:00
|
|
|
(
|
|
|
|
NSSArena *arenaOpt,
|
|
|
|
CK_SLOT_ID slotID,
|
|
|
|
NSSSlot *parent
|
|
|
|
)
|
|
|
|
{
|
|
|
|
NSSArena *arena;
|
|
|
|
nssArenaMark *mark;
|
|
|
|
NSSToken *rvToken;
|
2001-09-19 00:54:28 +04:00
|
|
|
nssSession *session;
|
2001-09-14 02:06:10 +04:00
|
|
|
NSSUTF8 *tokenName = NULL;
|
|
|
|
PRUint32 length;
|
|
|
|
PRBool newArena;
|
2001-10-09 00:19:30 +04:00
|
|
|
PRBool readWrite;
|
2001-09-14 02:06:10 +04:00
|
|
|
PRStatus nssrv;
|
|
|
|
CK_TOKEN_INFO tokenInfo;
|
|
|
|
CK_RV ckrv;
|
|
|
|
if (arenaOpt) {
|
|
|
|
arena = arenaOpt;
|
|
|
|
mark = nssArena_Mark(arena);
|
|
|
|
if (!mark) {
|
2001-10-09 00:19:30 +04:00
|
|
|
return (NSSToken *)NULL;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
|
|
|
newArena = PR_FALSE;
|
|
|
|
} else {
|
|
|
|
arena = NSSArena_Create();
|
|
|
|
if(!arena) {
|
|
|
|
return (NSSToken *)NULL;
|
|
|
|
}
|
|
|
|
newArena = PR_TRUE;
|
|
|
|
}
|
|
|
|
rvToken = nss_ZNEW(arena, NSSToken);
|
|
|
|
if (!rvToken) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
/* Get token information */
|
|
|
|
ckrv = CKAPI(parent)->C_GetTokenInfo(slotID, &tokenInfo);
|
|
|
|
if (ckrv != CKR_OK) {
|
|
|
|
/* set an error here, eh? */
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
/* Grab the slot description from the PKCS#11 fixed-length buffer */
|
|
|
|
length = nssPKCS11StringLength(tokenInfo.label, sizeof(tokenInfo.label));
|
|
|
|
if (length > 0) {
|
|
|
|
tokenName = nssUTF8_Create(arena, nssStringType_UTF8String,
|
|
|
|
(void *)tokenInfo.label, length);
|
|
|
|
if (!tokenName) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
}
|
2001-09-19 00:54:28 +04:00
|
|
|
/* Open a default session handle for the token. */
|
2001-10-09 00:19:30 +04:00
|
|
|
if (tokenInfo.ulMaxSessionCount == 1) {
|
|
|
|
/* if the token can only handle one session, it must be RW. */
|
|
|
|
readWrite = PR_TRUE;
|
|
|
|
} else {
|
|
|
|
readWrite = PR_FALSE;
|
|
|
|
}
|
|
|
|
session = nssSlot_CreateSession(parent, arena, readWrite);
|
2001-09-19 00:54:28 +04:00
|
|
|
if (session == NULL) {
|
2001-09-14 02:06:10 +04:00
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
/* TODO: seed the RNG here */
|
|
|
|
if (!arenaOpt) {
|
|
|
|
/* Avoid confusion now - only set the token's arena to a non-NULL value
|
|
|
|
* if a new arena is created. Otherwise, depend on the caller (having
|
|
|
|
* passed arenaOpt) to free the arena.
|
|
|
|
*/
|
|
|
|
rvToken->arena = arena;
|
|
|
|
}
|
2001-09-21 00:38:08 +04:00
|
|
|
rvToken->refCount = 1;
|
2001-09-14 02:06:10 +04:00
|
|
|
rvToken->slot = parent;
|
|
|
|
rvToken->name = tokenName;
|
|
|
|
rvToken->ckFlags = tokenInfo.flags;
|
2001-09-19 00:54:28 +04:00
|
|
|
rvToken->defaultSession = session;
|
2001-09-14 02:06:10 +04:00
|
|
|
nssrv = nssArena_Unmark(arena, mark);
|
|
|
|
if (nssrv != PR_SUCCESS) {
|
|
|
|
goto loser;
|
|
|
|
}
|
|
|
|
return rvToken;
|
|
|
|
loser:
|
2001-09-19 00:54:28 +04:00
|
|
|
if (session) {
|
|
|
|
nssSession_Destroy(session);
|
|
|
|
}
|
2001-09-14 02:06:10 +04:00
|
|
|
if (newArena) {
|
|
|
|
nssArena_Destroy(arena);
|
|
|
|
} else {
|
|
|
|
if (mark) {
|
|
|
|
nssArena_Release(arena, mark);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return (NSSToken *)NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
NSS_IMPLEMENT PRStatus
|
2001-09-20 01:47:23 +04:00
|
|
|
nssToken_Destroy
|
2001-09-14 02:06:10 +04:00
|
|
|
(
|
|
|
|
NSSToken *tok
|
|
|
|
)
|
|
|
|
{
|
|
|
|
if (--tok->refCount == 0) {
|
2001-10-11 20:33:38 +04:00
|
|
|
#ifndef NSS_3_4_CODE
|
|
|
|
/* don't do this in 3.4 -- let PK11SlotInfo handle it */
|
2001-09-19 00:54:28 +04:00
|
|
|
if (tok->defaultSession) {
|
|
|
|
nssSession_Destroy(tok->defaultSession);
|
|
|
|
}
|
2001-10-11 20:33:38 +04:00
|
|
|
#endif
|
|
|
|
if (tok->arena) {
|
|
|
|
return NSSArena_Destroy(tok->arena);
|
|
|
|
} else {
|
|
|
|
nss_ZFreeIf(tok);
|
|
|
|
}
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
|
|
|
return PR_SUCCESS;
|
|
|
|
}
|
|
|
|
|
2001-10-09 00:19:30 +04:00
|
|
|
NSS_IMPLEMENT NSSToken *
|
|
|
|
nssToken_AddRef
|
|
|
|
(
|
|
|
|
NSSToken *tok
|
|
|
|
)
|
|
|
|
{
|
|
|
|
++tok->refCount;
|
|
|
|
return tok;
|
|
|
|
}
|
|
|
|
|
2001-10-17 18:39:11 +04:00
|
|
|
NSS_IMPLEMENT NSSUTF8 *
|
|
|
|
nssToken_GetName
|
|
|
|
(
|
|
|
|
NSSToken *tok
|
|
|
|
)
|
|
|
|
{
|
|
|
|
return tok->name;
|
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
NSS_IMPLEMENT NSSItem *
|
|
|
|
nssToken_Digest
|
2001-10-09 00:19:30 +04:00
|
|
|
(
|
|
|
|
NSSToken *tok,
|
|
|
|
nssSession *sessionOpt,
|
2001-11-28 19:23:51 +03:00
|
|
|
NSSAlgorithmAndParameters *ap,
|
|
|
|
NSSItem *data,
|
|
|
|
NSSItem *rvOpt,
|
|
|
|
NSSArena *arenaOpt
|
2001-10-09 00:19:30 +04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
CK_RV ckrv;
|
2001-11-28 19:23:51 +03:00
|
|
|
CK_ULONG digestLen;
|
|
|
|
CK_BYTE_PTR digest;
|
|
|
|
NSSItem *rvItem = NULL;
|
|
|
|
nssSession *session;
|
|
|
|
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
|
|
|
|
nssSession_EnterMonitor(session);
|
|
|
|
ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism);
|
|
|
|
if (ckrv != CKR_OK) {
|
|
|
|
nssSession_ExitMonitor(session);
|
|
|
|
return NULL;
|
2001-11-07 19:15:29 +03:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
#if 0
|
|
|
|
/* XXX the standard says this should work, but it doesn't */
|
|
|
|
ckrv = CKAPI(tok)->C_Digest(session->handle, NULL, 0, NULL, &digestLen);
|
|
|
|
if (ckrv != CKR_OK) {
|
|
|
|
nssSession_ExitMonitor(session);
|
|
|
|
return NULL;
|
2001-11-08 03:15:51 +03:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
#endif
|
|
|
|
digestLen = 0; /* XXX for now */
|
|
|
|
digest = NULL;
|
|
|
|
if (rvOpt) {
|
|
|
|
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
|
|
|
|
nssSession_ExitMonitor(session);
|
|
|
|
/* the error should be bad args */
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
if (rvOpt->data) {
|
|
|
|
digest = rvOpt->data;
|
|
|
|
}
|
|
|
|
digestLen = rvOpt->size;
|
|
|
|
}
|
|
|
|
if (!digest) {
|
|
|
|
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
|
|
|
|
if (!digest) {
|
|
|
|
nssSession_ExitMonitor(session);
|
|
|
|
return NULL;
|
|
|
|
}
|
2001-11-07 19:15:29 +03:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
ckrv = CKAPI(tok)->C_Digest(session->handle,
|
|
|
|
(CK_BYTE_PTR)data->data,
|
|
|
|
(CK_ULONG)data->size,
|
|
|
|
(CK_BYTE_PTR)digest,
|
|
|
|
&digestLen);
|
|
|
|
nssSession_ExitMonitor(session);
|
2001-10-09 00:19:30 +04:00
|
|
|
if (ckrv != CKR_OK) {
|
2001-11-28 19:23:51 +03:00
|
|
|
nss_ZFreeIf(digest);
|
|
|
|
return NULL;
|
2001-10-09 00:19:30 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
if (!rvOpt) {
|
|
|
|
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
|
|
|
|
}
|
|
|
|
return rvItem;
|
2001-10-09 00:19:30 +04:00
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
NSS_IMPLEMENT PRStatus
|
|
|
|
nssToken_BeginDigest
|
2001-10-09 00:19:30 +04:00
|
|
|
(
|
|
|
|
NSSToken *tok,
|
|
|
|
nssSession *sessionOpt,
|
2001-11-28 19:23:51 +03:00
|
|
|
NSSAlgorithmAndParameters *ap
|
2001-10-09 00:19:30 +04:00
|
|
|
)
|
|
|
|
{
|
|
|
|
CK_RV ckrv;
|
2001-11-28 19:23:51 +03:00
|
|
|
nssSession *session;
|
|
|
|
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
|
2001-10-09 00:19:30 +04:00
|
|
|
nssSession_EnterMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism);
|
2001-10-09 00:19:30 +04:00
|
|
|
nssSession_ExitMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
|
2001-10-09 00:19:30 +04:00
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
NSS_IMPLEMENT PRStatus
|
|
|
|
nssToken_ContinueDigest
|
2001-10-11 20:33:38 +04:00
|
|
|
(
|
|
|
|
NSSToken *tok,
|
|
|
|
nssSession *sessionOpt,
|
2001-11-28 19:23:51 +03:00
|
|
|
NSSItem *item
|
2001-10-11 20:33:38 +04:00
|
|
|
)
|
2001-09-19 00:54:28 +04:00
|
|
|
{
|
2001-10-11 20:33:38 +04:00
|
|
|
CK_RV ckrv;
|
|
|
|
nssSession *session;
|
|
|
|
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
|
|
|
|
nssSession_EnterMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
ckrv = CKAPI(tok)->C_DigestUpdate(session->handle,
|
|
|
|
(CK_BYTE_PTR)item->data,
|
|
|
|
(CK_ULONG)item->size);
|
2001-10-11 20:33:38 +04:00
|
|
|
nssSession_ExitMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
|
2001-09-19 00:54:28 +04:00
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
NSS_IMPLEMENT NSSItem *
|
|
|
|
nssToken_FinishDigest
|
2001-09-14 02:06:10 +04:00
|
|
|
(
|
|
|
|
NSSToken *tok,
|
2001-11-28 19:23:51 +03:00
|
|
|
nssSession *sessionOpt,
|
|
|
|
NSSItem *rvOpt,
|
|
|
|
NSSArena *arenaOpt
|
2001-09-14 02:06:10 +04:00
|
|
|
)
|
|
|
|
{
|
2001-09-19 00:54:28 +04:00
|
|
|
CK_RV ckrv;
|
2001-11-28 19:23:51 +03:00
|
|
|
CK_ULONG digestLen;
|
|
|
|
CK_BYTE_PTR digest;
|
|
|
|
NSSItem *rvItem = NULL;
|
|
|
|
nssSession *session;
|
|
|
|
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
|
2001-10-11 20:33:38 +04:00
|
|
|
nssSession_EnterMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
ckrv = CKAPI(tok)->C_DigestFinal(session->handle, NULL, &digestLen);
|
|
|
|
if (ckrv != CKR_OK || digestLen == 0) {
|
2001-10-11 20:33:38 +04:00
|
|
|
nssSession_ExitMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
return NULL;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
digest = NULL;
|
|
|
|
if (rvOpt) {
|
|
|
|
if (rvOpt->size > 0 && rvOpt->size < digestLen) {
|
2001-10-11 20:33:38 +04:00
|
|
|
nssSession_ExitMonitor(session);
|
2001-11-28 19:23:51 +03:00
|
|
|
/* the error should be bad args */
|
|
|
|
return NULL;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
if (rvOpt->data) {
|
|
|
|
digest = rvOpt->data;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
digestLen = rvOpt->size;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
if (!digest) {
|
|
|
|
digest = (CK_BYTE_PTR)nss_ZAlloc(arenaOpt, digestLen);
|
|
|
|
if (!digest) {
|
|
|
|
nssSession_ExitMonitor(session);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ckrv = CKAPI(tok)->C_DigestFinal(session->handle, digest, &digestLen);
|
2001-10-11 20:33:38 +04:00
|
|
|
nssSession_ExitMonitor(session);
|
2001-09-14 02:06:10 +04:00
|
|
|
if (ckrv != CKR_OK) {
|
2001-11-28 19:23:51 +03:00
|
|
|
nss_ZFreeIf(digest);
|
|
|
|
return NULL;
|
2001-10-11 20:33:38 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
if (!rvOpt) {
|
|
|
|
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
|
2001-10-11 20:33:38 +04:00
|
|
|
}
|
2001-11-28 19:23:51 +03:00
|
|
|
return rvItem;
|
2001-09-14 02:06:10 +04:00
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
/* XXX of course this doesn't belong here */
|
|
|
|
NSS_IMPLEMENT NSSAlgorithmAndParameters *
|
|
|
|
NSSAlgorithmAndParameters_CreateSHA1Digest
|
2001-09-19 00:54:28 +04:00
|
|
|
(
|
2001-11-28 19:23:51 +03:00
|
|
|
NSSArena *arenaOpt
|
2001-09-19 00:54:28 +04:00
|
|
|
)
|
|
|
|
{
|
2001-11-28 19:23:51 +03:00
|
|
|
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;
|
2001-09-19 00:54:28 +04:00
|
|
|
}
|
|
|
|
|
2001-11-28 19:23:51 +03:00
|
|
|
NSS_IMPLEMENT NSSAlgorithmAndParameters *
|
|
|
|
NSSAlgorithmAndParameters_CreateMD5Digest
|
2001-10-09 00:19:30 +04:00
|
|
|
(
|
2001-11-28 19:23:51 +03:00
|
|
|
NSSArena *arenaOpt
|
2001-10-09 00:19:30 +04:00
|
|
|
)
|
|
|
|
{
|
2001-11-28 19:23:51 +03:00
|
|
|
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;
|
2001-10-09 00:19:30 +04:00
|
|
|
}
|
|
|
|
|