gecko-dev/security/nss/lib/dev/devtoken.c

385 строки
9.4 KiB
C
Исходник Обычный вид История

/*
* 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
static const char CVS_ID[] = "@(#) $RCSfile: devtoken.c,v $ $Revision: 1.3 $ $Date: 2001/11/28 16:23:39 $ $Name: $";
#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 *
nssToken_Create
(
NSSArena *arenaOpt,
CK_SLOT_ID slotID,
NSSSlot *parent
)
{
NSSArena *arena;
nssArenaMark *mark;
NSSToken *rvToken;
nssSession *session;
NSSUTF8 *tokenName = NULL;
PRUint32 length;
PRBool newArena;
PRBool readWrite;
PRStatus nssrv;
CK_TOKEN_INFO tokenInfo;
CK_RV ckrv;
if (arenaOpt) {
arena = arenaOpt;
mark = nssArena_Mark(arena);
if (!mark) {
return (NSSToken *)NULL;
}
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;
}
}
/* Open a default session handle for the token. */
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);
if (session == NULL) {
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;
}
rvToken->refCount = 1;
rvToken->slot = parent;
rvToken->name = tokenName;
rvToken->ckFlags = tokenInfo.flags;
rvToken->defaultSession = session;
nssrv = nssArena_Unmark(arena, mark);
if (nssrv != PR_SUCCESS) {
goto loser;
}
return rvToken;
loser:
if (session) {
nssSession_Destroy(session);
}
if (newArena) {
nssArena_Destroy(arena);
} else {
if (mark) {
nssArena_Release(arena, mark);
}
}
return (NSSToken *)NULL;
}
NSS_IMPLEMENT PRStatus
nssToken_Destroy
(
NSSToken *tok
)
{
if (--tok->refCount == 0) {
#ifndef NSS_3_4_CODE
/* don't do this in 3.4 -- let PK11SlotInfo handle it */
if (tok->defaultSession) {
nssSession_Destroy(tok->defaultSession);
}
#endif
if (tok->arena) {
return NSSArena_Destroy(tok->arena);
} else {
nss_ZFreeIf(tok);
}
}
return PR_SUCCESS;
}
NSS_IMPLEMENT NSSToken *
nssToken_AddRef
(
NSSToken *tok
)
{
++tok->refCount;
return tok;
}
NSS_IMPLEMENT NSSUTF8 *
nssToken_GetName
(
NSSToken *tok
)
{
return tok->name;
}
NSS_IMPLEMENT NSSItem *
nssToken_Digest
(
NSSToken *tok,
nssSession *sessionOpt,
NSSAlgorithmAndParameters *ap,
NSSItem *data,
NSSItem *rvOpt,
NSSArena *arenaOpt
)
{
CK_RV ckrv;
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;
}
#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;
}
#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;
}
}
ckrv = CKAPI(tok)->C_Digest(session->handle,
(CK_BYTE_PTR)data->data,
(CK_ULONG)data->size,
(CK_BYTE_PTR)digest,
&digestLen);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
nss_ZFreeIf(digest);
return NULL;
}
if (!rvOpt) {
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
}
return rvItem;
}
NSS_IMPLEMENT PRStatus
nssToken_BeginDigest
(
NSSToken *tok,
nssSession *sessionOpt,
NSSAlgorithmAndParameters *ap
)
{
CK_RV ckrv;
nssSession *session;
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
ckrv = CKAPI(tok)->C_DigestInit(session->handle, &ap->mechanism);
nssSession_ExitMonitor(session);
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
NSS_IMPLEMENT PRStatus
nssToken_ContinueDigest
(
NSSToken *tok,
nssSession *sessionOpt,
NSSItem *item
)
{
CK_RV ckrv;
nssSession *session;
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
ckrv = CKAPI(tok)->C_DigestUpdate(session->handle,
(CK_BYTE_PTR)item->data,
(CK_ULONG)item->size);
nssSession_ExitMonitor(session);
return (ckrv == CKR_OK) ? PR_SUCCESS : PR_FAILURE;
}
NSS_IMPLEMENT NSSItem *
nssToken_FinishDigest
(
NSSToken *tok,
nssSession *sessionOpt,
NSSItem *rvOpt,
NSSArena *arenaOpt
)
{
CK_RV ckrv;
CK_ULONG digestLen;
CK_BYTE_PTR digest;
NSSItem *rvItem = NULL;
nssSession *session;
session = (sessionOpt) ? sessionOpt : tok->defaultSession;
nssSession_EnterMonitor(session);
ckrv = CKAPI(tok)->C_DigestFinal(session->handle, NULL, &digestLen);
if (ckrv != CKR_OK || digestLen == 0) {
nssSession_ExitMonitor(session);
return NULL;
}
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;
}
}
ckrv = CKAPI(tok)->C_DigestFinal(session->handle, digest, &digestLen);
nssSession_ExitMonitor(session);
if (ckrv != CKR_OK) {
nss_ZFreeIf(digest);
return NULL;
}
if (!rvOpt) {
rvItem = nssItem_Create(arenaOpt, NULL, digestLen, (void *)digest);
}
return rvItem;
}
/* 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;
}