security/nss/lib/ckfw/session.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/ckfw/session.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2460 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * session.c
    1.10 + *
    1.11 + * This file implements the NSSCKFWSession type and methods.
    1.12 + */
    1.13 +
    1.14 +#ifndef CK_T
    1.15 +#include "ck.h"
    1.16 +#endif /* CK_T */
    1.17 +
    1.18 +/*
    1.19 + * NSSCKFWSession
    1.20 + *
    1.21 + *  -- create/destroy --
    1.22 + *  nssCKFWSession_Create
    1.23 + *  nssCKFWSession_Destroy
    1.24 + *
    1.25 + *  -- public accessors --
    1.26 + *  NSSCKFWSession_GetMDSession
    1.27 + *  NSSCKFWSession_GetArena
    1.28 + *  NSSCKFWSession_CallNotification
    1.29 + *  NSSCKFWSession_IsRWSession
    1.30 + *  NSSCKFWSession_IsSO
    1.31 + *
    1.32 + *  -- implement public accessors --
    1.33 + *  nssCKFWSession_GetMDSession
    1.34 + *  nssCKFWSession_GetArena
    1.35 + *  nssCKFWSession_CallNotification
    1.36 + *  nssCKFWSession_IsRWSession
    1.37 + *  nssCKFWSession_IsSO
    1.38 + *
    1.39 + *  -- private accessors --
    1.40 + *  nssCKFWSession_GetSlot
    1.41 + *  nssCKFWSession_GetSessionState
    1.42 + *  nssCKFWSession_SetFWFindObjects
    1.43 + *  nssCKFWSession_GetFWFindObjects
    1.44 + *  nssCKFWSession_SetMDSession
    1.45 + *  nssCKFWSession_SetHandle
    1.46 + *  nssCKFWSession_GetHandle
    1.47 + *  nssCKFWSession_RegisterSessionObject
    1.48 + *  nssCKFWSession_DeegisterSessionObject
    1.49 + *
    1.50 + *  -- module fronts --
    1.51 + *  nssCKFWSession_GetDeviceError
    1.52 + *  nssCKFWSession_Login
    1.53 + *  nssCKFWSession_Logout
    1.54 + *  nssCKFWSession_InitPIN
    1.55 + *  nssCKFWSession_SetPIN
    1.56 + *  nssCKFWSession_GetOperationStateLen
    1.57 + *  nssCKFWSession_GetOperationState
    1.58 + *  nssCKFWSession_SetOperationState
    1.59 + *  nssCKFWSession_CreateObject
    1.60 + *  nssCKFWSession_CopyObject
    1.61 + *  nssCKFWSession_FindObjectsInit
    1.62 + *  nssCKFWSession_SeedRandom
    1.63 + *  nssCKFWSession_GetRandom
    1.64 + */
    1.65 +
    1.66 +struct NSSCKFWSessionStr {
    1.67 +  NSSArena *arena;
    1.68 +  NSSCKMDSession *mdSession;
    1.69 +  NSSCKFWToken *fwToken;
    1.70 +  NSSCKMDToken *mdToken;
    1.71 +  NSSCKFWInstance *fwInstance;
    1.72 +  NSSCKMDInstance *mdInstance;
    1.73 +  CK_VOID_PTR pApplication;
    1.74 +  CK_NOTIFY Notify;
    1.75 +
    1.76 +  /*
    1.77 +   * Everything above is set at creation time, and then not modified.
    1.78 +   * The items below are atomic.  No locking required.  If we fear
    1.79 +   * about pointer-copies being nonatomic, we'll lock fwFindObjects.
    1.80 +   */
    1.81 +
    1.82 +  CK_BBOOL rw;
    1.83 +  NSSCKFWFindObjects *fwFindObjects;
    1.84 +  NSSCKFWCryptoOperation *fwOperationArray[NSSCKFWCryptoOperationState_Max];
    1.85 +  nssCKFWHash *sessionObjectHash;
    1.86 +  CK_SESSION_HANDLE hSession;
    1.87 +};
    1.88 +
    1.89 +#ifdef DEBUG
    1.90 +/*
    1.91 + * But first, the pointer-tracking stuff.
    1.92 + *
    1.93 + * NOTE: the pointer-tracking support in NSS/base currently relies
    1.94 + * upon NSPR's CallOnce support.  That, however, relies upon NSPR's
    1.95 + * locking, which is tied into the runtime.  We need a pointer-tracker
    1.96 + * implementation that uses the locks supplied through C_Initialize.
    1.97 + * That support, however, can be filled in later.  So for now, I'll
    1.98 + * just do this routines as no-ops.
    1.99 + */
   1.100 +
   1.101 +static CK_RV
   1.102 +session_add_pointer
   1.103 +(
   1.104 +  const NSSCKFWSession *fwSession
   1.105 +)
   1.106 +{
   1.107 +  return CKR_OK;
   1.108 +}
   1.109 +
   1.110 +static CK_RV
   1.111 +session_remove_pointer
   1.112 +(
   1.113 +  const NSSCKFWSession *fwSession
   1.114 +)
   1.115 +{
   1.116 +  return CKR_OK;
   1.117 +}
   1.118 +
   1.119 +NSS_IMPLEMENT CK_RV
   1.120 +nssCKFWSession_verifyPointer
   1.121 +(
   1.122 +  const NSSCKFWSession *fwSession
   1.123 +)
   1.124 +{
   1.125 +  return CKR_OK;
   1.126 +}
   1.127 +
   1.128 +#endif /* DEBUG */
   1.129 +
   1.130 +/*
   1.131 + * nssCKFWSession_Create
   1.132 + *
   1.133 + */
   1.134 +NSS_IMPLEMENT NSSCKFWSession *
   1.135 +nssCKFWSession_Create
   1.136 +(
   1.137 +  NSSCKFWToken *fwToken,
   1.138 +  CK_BBOOL rw,
   1.139 +  CK_VOID_PTR pApplication,
   1.140 +  CK_NOTIFY Notify,
   1.141 +  CK_RV *pError
   1.142 +)
   1.143 +{
   1.144 +  NSSArena *arena = (NSSArena *)NULL;
   1.145 +  NSSCKFWSession *fwSession;
   1.146 +  NSSCKFWSlot *fwSlot;
   1.147 +
   1.148 +#ifdef NSSDEBUG
   1.149 +  if (!pError) {
   1.150 +    return (NSSCKFWSession *)NULL;
   1.151 +  }
   1.152 +
   1.153 +  *pError = nssCKFWToken_verifyPointer(fwToken);
   1.154 +  if( CKR_OK != *pError ) {
   1.155 +    return (NSSCKFWSession *)NULL;
   1.156 +  }
   1.157 +#endif /* NSSDEBUG */
   1.158 +
   1.159 +  arena = NSSArena_Create();
   1.160 +  if (!arena) {
   1.161 +    *pError = CKR_HOST_MEMORY;
   1.162 +    return (NSSCKFWSession *)NULL;
   1.163 +  }
   1.164 +
   1.165 +  fwSession = nss_ZNEW(arena, NSSCKFWSession);
   1.166 +  if (!fwSession) {
   1.167 +    *pError = CKR_HOST_MEMORY;
   1.168 +    goto loser;
   1.169 +  }
   1.170 +
   1.171 +  fwSession->arena = arena;
   1.172 +  fwSession->mdSession = (NSSCKMDSession *)NULL; /* set later */
   1.173 +  fwSession->fwToken = fwToken;
   1.174 +  fwSession->mdToken = nssCKFWToken_GetMDToken(fwToken);
   1.175 +
   1.176 +  fwSlot = nssCKFWToken_GetFWSlot(fwToken);
   1.177 +  fwSession->fwInstance = nssCKFWSlot_GetFWInstance(fwSlot);
   1.178 +  fwSession->mdInstance = nssCKFWSlot_GetMDInstance(fwSlot);
   1.179 +
   1.180 +  fwSession->rw = rw;
   1.181 +  fwSession->pApplication = pApplication;
   1.182 +  fwSession->Notify = Notify;
   1.183 +
   1.184 +  fwSession->fwFindObjects = (NSSCKFWFindObjects *)NULL;
   1.185 +
   1.186 +  fwSession->sessionObjectHash = nssCKFWHash_Create(fwSession->fwInstance, arena, pError);
   1.187 +  if (!fwSession->sessionObjectHash) {
   1.188 +    if( CKR_OK == *pError ) {
   1.189 +      *pError = CKR_GENERAL_ERROR;
   1.190 +    }
   1.191 +    goto loser;
   1.192 +  }
   1.193 +
   1.194 +#ifdef DEBUG
   1.195 +  *pError = session_add_pointer(fwSession);
   1.196 +  if( CKR_OK != *pError ) {
   1.197 +    goto loser;
   1.198 +  }
   1.199 +#endif /* DEBUG */
   1.200 +
   1.201 +  return fwSession;
   1.202 +
   1.203 + loser:
   1.204 +  if (arena) {
   1.205 +    if (fwSession &&   fwSession->sessionObjectHash) {
   1.206 +      (void)nssCKFWHash_Destroy(fwSession->sessionObjectHash);
   1.207 +    }
   1.208 +    NSSArena_Destroy(arena);
   1.209 +  }
   1.210 +
   1.211 +  return (NSSCKFWSession *)NULL;
   1.212 +}
   1.213 +
   1.214 +static void
   1.215 +nss_ckfw_session_object_destroy_iterator
   1.216 +(
   1.217 +  const void *key,
   1.218 +  void *value,
   1.219 +  void *closure
   1.220 +)
   1.221 +{
   1.222 +  NSSCKFWObject *fwObject = (NSSCKFWObject *)value;
   1.223 +  nssCKFWObject_Finalize(fwObject, PR_TRUE);
   1.224 +}
   1.225 +
   1.226 +/*
   1.227 + * nssCKFWSession_Destroy
   1.228 + *
   1.229 + */
   1.230 +NSS_IMPLEMENT CK_RV
   1.231 +nssCKFWSession_Destroy
   1.232 +(
   1.233 +  NSSCKFWSession *fwSession,
   1.234 +  CK_BBOOL removeFromTokenHash
   1.235 +)
   1.236 +{
   1.237 +  CK_RV error = CKR_OK;
   1.238 +  nssCKFWHash *sessionObjectHash;
   1.239 +  NSSCKFWCryptoOperationState i;
   1.240 +
   1.241 +#ifdef NSSDEBUG
   1.242 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.243 +  if( CKR_OK != error ) {
   1.244 +    return error;
   1.245 +  }
   1.246 +#endif /* NSSDEBUG */
   1.247 +
   1.248 +  if( removeFromTokenHash ) {
   1.249 +    error = nssCKFWToken_RemoveSession(fwSession->fwToken, fwSession);
   1.250 +  }
   1.251 +
   1.252 +  /*
   1.253 +   * Invalidate session objects
   1.254 +   */
   1.255 +
   1.256 +  sessionObjectHash = fwSession->sessionObjectHash;
   1.257 +  fwSession->sessionObjectHash = (nssCKFWHash *)NULL;
   1.258 +
   1.259 +  nssCKFWHash_Iterate(sessionObjectHash, 
   1.260 +                      nss_ckfw_session_object_destroy_iterator, 
   1.261 +                      (void *)NULL);
   1.262 +
   1.263 +  for (i=0; i < NSSCKFWCryptoOperationState_Max; i++) {
   1.264 +    if (fwSession->fwOperationArray[i]) {
   1.265 +      nssCKFWCryptoOperation_Destroy(fwSession->fwOperationArray[i]);
   1.266 +    }
   1.267 +  }
   1.268 +
   1.269 +#ifdef DEBUG
   1.270 +  (void)session_remove_pointer(fwSession);
   1.271 +#endif /* DEBUG */
   1.272 +  (void)nssCKFWHash_Destroy(sessionObjectHash);
   1.273 +  NSSArena_Destroy(fwSession->arena);
   1.274 +
   1.275 +  return error;
   1.276 +}
   1.277 +
   1.278 +/*
   1.279 + * nssCKFWSession_GetMDSession
   1.280 + *
   1.281 + */
   1.282 +NSS_IMPLEMENT NSSCKMDSession *
   1.283 +nssCKFWSession_GetMDSession
   1.284 +(
   1.285 +  NSSCKFWSession *fwSession
   1.286 +)
   1.287 +{
   1.288 +#ifdef NSSDEBUG
   1.289 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.290 +    return (NSSCKMDSession *)NULL;
   1.291 +  }
   1.292 +#endif /* NSSDEBUG */
   1.293 +
   1.294 +  return fwSession->mdSession;
   1.295 +}
   1.296 +
   1.297 +/*
   1.298 + * nssCKFWSession_GetArena
   1.299 + *
   1.300 + */
   1.301 +NSS_IMPLEMENT NSSArena *
   1.302 +nssCKFWSession_GetArena
   1.303 +(
   1.304 +  NSSCKFWSession *fwSession,
   1.305 +  CK_RV *pError
   1.306 +)
   1.307 +{
   1.308 +#ifdef NSSDEBUG
   1.309 +  if (!pError) {
   1.310 +    return (NSSArena *)NULL;
   1.311 +  }
   1.312 +
   1.313 +  *pError = nssCKFWSession_verifyPointer(fwSession);
   1.314 +  if( CKR_OK != *pError ) {
   1.315 +    return (NSSArena *)NULL;
   1.316 +  }
   1.317 +#endif /* NSSDEBUG */
   1.318 +
   1.319 +  return fwSession->arena;
   1.320 +}
   1.321 +
   1.322 +/*
   1.323 + * nssCKFWSession_CallNotification
   1.324 + *
   1.325 + */
   1.326 +NSS_IMPLEMENT CK_RV
   1.327 +nssCKFWSession_CallNotification
   1.328 +(
   1.329 +  NSSCKFWSession *fwSession,
   1.330 +  CK_NOTIFICATION event
   1.331 +)
   1.332 +{
   1.333 +  CK_RV error = CKR_OK;
   1.334 +  CK_SESSION_HANDLE handle;
   1.335 +
   1.336 +#ifdef NSSDEBUG
   1.337 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.338 +  if( CKR_OK != error ) {
   1.339 +    return error;
   1.340 +  }
   1.341 +#endif /* NSSDEBUG */
   1.342 +
   1.343 +  if( (CK_NOTIFY)NULL == fwSession->Notify ) {
   1.344 +    return CKR_OK;
   1.345 +  }
   1.346 +
   1.347 +  handle = nssCKFWInstance_FindSessionHandle(fwSession->fwInstance, fwSession);
   1.348 +  if( (CK_SESSION_HANDLE)0 == handle ) {
   1.349 +    return CKR_GENERAL_ERROR;
   1.350 +  }
   1.351 +
   1.352 +  error = fwSession->Notify(handle, event, fwSession->pApplication);
   1.353 +
   1.354 +  return error;
   1.355 +}
   1.356 +
   1.357 +/*
   1.358 + * nssCKFWSession_IsRWSession
   1.359 + *
   1.360 + */
   1.361 +NSS_IMPLEMENT CK_BBOOL
   1.362 +nssCKFWSession_IsRWSession
   1.363 +(
   1.364 +  NSSCKFWSession *fwSession
   1.365 +)
   1.366 +{
   1.367 +#ifdef NSSDEBUG
   1.368 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.369 +    return CK_FALSE;
   1.370 +  }
   1.371 +#endif /* NSSDEBUG */
   1.372 +
   1.373 +  return fwSession->rw;
   1.374 +}
   1.375 +
   1.376 +/*
   1.377 + * nssCKFWSession_IsSO
   1.378 + *
   1.379 + */
   1.380 +NSS_IMPLEMENT CK_BBOOL
   1.381 +nssCKFWSession_IsSO
   1.382 +(
   1.383 +  NSSCKFWSession *fwSession
   1.384 +)
   1.385 +{
   1.386 +  CK_STATE state;
   1.387 +
   1.388 +#ifdef NSSDEBUG
   1.389 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.390 +    return CK_FALSE;
   1.391 +  }
   1.392 +#endif /* NSSDEBUG */
   1.393 +
   1.394 +  state = nssCKFWToken_GetSessionState(fwSession->fwToken);
   1.395 +  switch( state ) {
   1.396 +  case CKS_RO_PUBLIC_SESSION:
   1.397 +  case CKS_RO_USER_FUNCTIONS:
   1.398 +  case CKS_RW_PUBLIC_SESSION:
   1.399 +  case CKS_RW_USER_FUNCTIONS:
   1.400 +    return CK_FALSE;
   1.401 +  case CKS_RW_SO_FUNCTIONS:
   1.402 +    return CK_TRUE;
   1.403 +  default:
   1.404 +    return CK_FALSE;
   1.405 +  }
   1.406 +}
   1.407 +
   1.408 +/*
   1.409 + * nssCKFWSession_GetFWSlot
   1.410 + *
   1.411 + */
   1.412 +NSS_IMPLEMENT NSSCKFWSlot *
   1.413 +nssCKFWSession_GetFWSlot
   1.414 +(
   1.415 +  NSSCKFWSession *fwSession
   1.416 +)
   1.417 +{
   1.418 +#ifdef NSSDEBUG
   1.419 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.420 +    return (NSSCKFWSlot *)NULL;
   1.421 +  }
   1.422 +#endif /* NSSDEBUG */
   1.423 +
   1.424 +  return nssCKFWToken_GetFWSlot(fwSession->fwToken);
   1.425 +}
   1.426 +
   1.427 +/*
   1.428 + * nssCFKWSession_GetSessionState
   1.429 + *
   1.430 + */
   1.431 +NSS_IMPLEMENT CK_STATE
   1.432 +nssCKFWSession_GetSessionState
   1.433 +(
   1.434 +  NSSCKFWSession *fwSession
   1.435 +)
   1.436 +{
   1.437 +#ifdef NSSDEBUG
   1.438 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.439 +    return CKS_RO_PUBLIC_SESSION; /* whatever */
   1.440 +  }
   1.441 +#endif /* NSSDEBUG */
   1.442 +
   1.443 +  return nssCKFWToken_GetSessionState(fwSession->fwToken);
   1.444 +}
   1.445 +
   1.446 +/*
   1.447 + * nssCKFWSession_SetFWFindObjects
   1.448 + *
   1.449 + */
   1.450 +NSS_IMPLEMENT CK_RV
   1.451 +nssCKFWSession_SetFWFindObjects
   1.452 +(
   1.453 +  NSSCKFWSession *fwSession,
   1.454 +  NSSCKFWFindObjects *fwFindObjects
   1.455 +)
   1.456 +{
   1.457 +#ifdef NSSDEBUG
   1.458 +  CK_RV error = CKR_OK;
   1.459 +#endif /* NSSDEBUG */
   1.460 +
   1.461 +#ifdef NSSDEBUG
   1.462 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.463 +  if( CKR_OK != error ) {
   1.464 +    return error;
   1.465 +  }
   1.466 +
   1.467 +  /* fwFindObjects may be null */
   1.468 +#endif /* NSSDEBUG */
   1.469 +
   1.470 +  if ((fwSession->fwFindObjects) &&
   1.471 +      (fwFindObjects)) {
   1.472 +    return CKR_OPERATION_ACTIVE;
   1.473 +  }
   1.474 +
   1.475 +  fwSession->fwFindObjects = fwFindObjects;
   1.476 +
   1.477 +  return CKR_OK;
   1.478 +}
   1.479 +
   1.480 +/*
   1.481 + * nssCKFWSession_GetFWFindObjects
   1.482 + *
   1.483 + */
   1.484 +NSS_IMPLEMENT NSSCKFWFindObjects *
   1.485 +nssCKFWSession_GetFWFindObjects
   1.486 +(
   1.487 +  NSSCKFWSession *fwSession,
   1.488 +  CK_RV *pError
   1.489 +)
   1.490 +{
   1.491 +#ifdef NSSDEBUG
   1.492 +  if (!pError) {
   1.493 +    return (NSSCKFWFindObjects *)NULL;
   1.494 +  }
   1.495 +
   1.496 +  *pError = nssCKFWSession_verifyPointer(fwSession);
   1.497 +  if( CKR_OK != *pError ) {
   1.498 +    return (NSSCKFWFindObjects *)NULL;
   1.499 +  }
   1.500 +#endif /* NSSDEBUG */
   1.501 +
   1.502 +  if (!fwSession->fwFindObjects) {
   1.503 +    *pError = CKR_OPERATION_NOT_INITIALIZED;
   1.504 +    return (NSSCKFWFindObjects *)NULL;
   1.505 +  }
   1.506 +
   1.507 +  return fwSession->fwFindObjects;
   1.508 +}
   1.509 +
   1.510 +/*
   1.511 + * nssCKFWSession_SetMDSession
   1.512 + *
   1.513 + */
   1.514 +NSS_IMPLEMENT CK_RV
   1.515 +nssCKFWSession_SetMDSession
   1.516 +(
   1.517 +  NSSCKFWSession *fwSession,
   1.518 +  NSSCKMDSession *mdSession
   1.519 +)
   1.520 +{
   1.521 +#ifdef NSSDEBUG
   1.522 +  CK_RV error = CKR_OK;
   1.523 +#endif /* NSSDEBUG */
   1.524 +
   1.525 +#ifdef NSSDEBUG
   1.526 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.527 +  if( CKR_OK != error ) {
   1.528 +    return error;
   1.529 +  }
   1.530 +
   1.531 +  if (!mdSession) {
   1.532 +    return CKR_ARGUMENTS_BAD;
   1.533 +  }
   1.534 +#endif /* NSSDEBUG */
   1.535 +
   1.536 +  if (fwSession->mdSession) {
   1.537 +    return CKR_GENERAL_ERROR;
   1.538 +  }
   1.539 +
   1.540 +  fwSession->mdSession = mdSession;
   1.541 +
   1.542 +  return CKR_OK;
   1.543 +}
   1.544 +
   1.545 +/*
   1.546 + * nssCKFWSession_SetHandle
   1.547 + *
   1.548 + */
   1.549 +NSS_IMPLEMENT CK_RV
   1.550 +nssCKFWSession_SetHandle
   1.551 +(
   1.552 +  NSSCKFWSession *fwSession,
   1.553 +  CK_SESSION_HANDLE hSession
   1.554 +)
   1.555 +{
   1.556 +#ifdef NSSDEBUG
   1.557 +  CK_RV error = CKR_OK;
   1.558 +#endif /* NSSDEBUG */
   1.559 +
   1.560 +#ifdef NSSDEBUG
   1.561 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.562 +  if( CKR_OK != error ) {
   1.563 +    return error;
   1.564 +  }
   1.565 +#endif /* NSSDEBUG */
   1.566 +
   1.567 +  if( (CK_SESSION_HANDLE)0 != fwSession->hSession ) {
   1.568 +    return CKR_GENERAL_ERROR;
   1.569 +  }
   1.570 +
   1.571 +  fwSession->hSession = hSession;
   1.572 +
   1.573 +  return CKR_OK;
   1.574 +}
   1.575 +
   1.576 +/*
   1.577 + * nssCKFWSession_GetHandle
   1.578 + *
   1.579 + */
   1.580 +NSS_IMPLEMENT CK_SESSION_HANDLE
   1.581 +nssCKFWSession_GetHandle
   1.582 +(
   1.583 +  NSSCKFWSession *fwSession
   1.584 +)
   1.585 +{
   1.586 +#ifdef NSSDEBUG
   1.587 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.588 +    return NULL;
   1.589 +  }
   1.590 +#endif /* NSSDEBUG */
   1.591 +
   1.592 +  return fwSession->hSession;
   1.593 +}
   1.594 +
   1.595 +/*
   1.596 + * nssCKFWSession_RegisterSessionObject
   1.597 + *
   1.598 + */
   1.599 +NSS_IMPLEMENT CK_RV
   1.600 +nssCKFWSession_RegisterSessionObject
   1.601 +(
   1.602 +  NSSCKFWSession *fwSession,
   1.603 +  NSSCKFWObject *fwObject
   1.604 +)
   1.605 +{
   1.606 +  CK_RV rv = CKR_OK;
   1.607 +
   1.608 +#ifdef NSSDEBUG
   1.609 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.610 +    return CKR_GENERAL_ERROR;
   1.611 +  }
   1.612 +#endif /* NSSDEBUG */
   1.613 +
   1.614 +  if (fwSession->sessionObjectHash) {
   1.615 +    rv = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
   1.616 +  }
   1.617 +
   1.618 +  return rv;
   1.619 +}
   1.620 +
   1.621 +/*
   1.622 + * nssCKFWSession_DeregisterSessionObject
   1.623 + *
   1.624 + */
   1.625 +NSS_IMPLEMENT CK_RV
   1.626 +nssCKFWSession_DeregisterSessionObject
   1.627 +(
   1.628 +  NSSCKFWSession *fwSession,
   1.629 +  NSSCKFWObject *fwObject
   1.630 +)
   1.631 +{
   1.632 +#ifdef NSSDEBUG
   1.633 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.634 +    return CKR_GENERAL_ERROR;
   1.635 +  }
   1.636 +#endif /* NSSDEBUG */
   1.637 +
   1.638 +  if (fwSession->sessionObjectHash) {
   1.639 +    nssCKFWHash_Remove(fwSession->sessionObjectHash, fwObject);
   1.640 +  }
   1.641 +
   1.642 +  return CKR_OK;
   1.643 +}
   1.644 +
   1.645 +/*
   1.646 + * nssCKFWSession_GetDeviceError
   1.647 + *
   1.648 + */
   1.649 +NSS_IMPLEMENT CK_ULONG
   1.650 +nssCKFWSession_GetDeviceError
   1.651 +(
   1.652 +  NSSCKFWSession *fwSession
   1.653 +)
   1.654 +{
   1.655 +#ifdef NSSDEBUG
   1.656 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
   1.657 +    return (CK_ULONG)0;
   1.658 +  }
   1.659 +
   1.660 +  if (!fwSession->mdSession) {
   1.661 +    return (CK_ULONG)0;
   1.662 +  }
   1.663 +#endif /* NSSDEBUG */
   1.664 +
   1.665 +  if (!fwSession->mdSession->GetDeviceError) {
   1.666 +    return (CK_ULONG)0;
   1.667 +  }
   1.668 +
   1.669 +  return fwSession->mdSession->GetDeviceError(fwSession->mdSession, 
   1.670 +    fwSession, fwSession->mdToken, fwSession->fwToken, 
   1.671 +    fwSession->mdInstance, fwSession->fwInstance);
   1.672 +}
   1.673 +
   1.674 +/*
   1.675 + * nssCKFWSession_Login
   1.676 + *
   1.677 + */
   1.678 +NSS_IMPLEMENT CK_RV
   1.679 +nssCKFWSession_Login
   1.680 +(
   1.681 +  NSSCKFWSession *fwSession,
   1.682 +  CK_USER_TYPE userType,
   1.683 +  NSSItem *pin
   1.684 +)
   1.685 +{
   1.686 +  CK_RV error = CKR_OK;
   1.687 +  CK_STATE oldState;
   1.688 +  CK_STATE newState;
   1.689 +
   1.690 +#ifdef NSSDEBUG
   1.691 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.692 +  if( CKR_OK != error ) {
   1.693 +    return error;
   1.694 +  }
   1.695 +
   1.696 +  switch( userType ) {
   1.697 +  case CKU_SO:
   1.698 +  case CKU_USER:
   1.699 +    break;
   1.700 +  default:
   1.701 +    return CKR_USER_TYPE_INVALID;
   1.702 +  }
   1.703 +
   1.704 +  if (!pin) {
   1.705 +    if( CK_TRUE != nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken) ) {
   1.706 +      return CKR_ARGUMENTS_BAD;
   1.707 +    }
   1.708 +  }
   1.709 +
   1.710 +  if (!fwSession->mdSession) {
   1.711 +    return CKR_GENERAL_ERROR;
   1.712 +  }
   1.713 +#endif /* NSSDEBUG */
   1.714 +
   1.715 +  oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
   1.716 +
   1.717 +  /*
   1.718 +   * It's not clear what happens when you're already logged in.
   1.719 +   * I'll just fail; but if we decide to change, the logic is
   1.720 +   * all right here.
   1.721 +   */
   1.722 +
   1.723 +  if( CKU_SO == userType ) {
   1.724 +    switch( oldState ) {
   1.725 +    case CKS_RO_PUBLIC_SESSION:      
   1.726 +      /*
   1.727 +       * There's no such thing as a read-only security officer
   1.728 +       * session, so fail.  The error should be CKR_SESSION_READ_ONLY,
   1.729 +       * except that C_Login isn't defined to return that.  So we'll
   1.730 +       * do CKR_SESSION_READ_ONLY_EXISTS, which is what is documented.
   1.731 +       */
   1.732 +      return CKR_SESSION_READ_ONLY_EXISTS;
   1.733 +    case CKS_RO_USER_FUNCTIONS:
   1.734 +      return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   1.735 +    case CKS_RW_PUBLIC_SESSION:
   1.736 +      newState = CKS_RW_SO_FUNCTIONS;
   1.737 +      break;
   1.738 +    case CKS_RW_USER_FUNCTIONS:
   1.739 +      return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   1.740 +    case CKS_RW_SO_FUNCTIONS:
   1.741 +      return CKR_USER_ALREADY_LOGGED_IN;
   1.742 +    default:
   1.743 +      return CKR_GENERAL_ERROR;
   1.744 +    }
   1.745 +  } else /* CKU_USER == userType */ {
   1.746 +    switch( oldState ) {
   1.747 +    case CKS_RO_PUBLIC_SESSION:      
   1.748 +      newState = CKS_RO_USER_FUNCTIONS;
   1.749 +      break;
   1.750 +    case CKS_RO_USER_FUNCTIONS:
   1.751 +      return CKR_USER_ALREADY_LOGGED_IN;
   1.752 +    case CKS_RW_PUBLIC_SESSION:
   1.753 +      newState = CKS_RW_USER_FUNCTIONS;
   1.754 +      break;
   1.755 +    case CKS_RW_USER_FUNCTIONS:
   1.756 +      return CKR_USER_ALREADY_LOGGED_IN;
   1.757 +    case CKS_RW_SO_FUNCTIONS:
   1.758 +      return CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
   1.759 +    default:
   1.760 +      return CKR_GENERAL_ERROR;
   1.761 +    }
   1.762 +  }
   1.763 +
   1.764 +  /*
   1.765 +   * So now we're in one of three cases:
   1.766 +   *
   1.767 +   * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_SO_FUNCTIONS;
   1.768 +   * Old == CKS_RW_PUBLIC_SESSION, New == CKS_RW_USER_FUNCTIONS;
   1.769 +   * Old == CKS_RO_PUBLIC_SESSION, New == CKS_RO_USER_FUNCTIONS;
   1.770 +   */
   1.771 +
   1.772 +  if (!fwSession->mdSession->Login) {
   1.773 +    /*
   1.774 +     * The Module doesn't want to be informed (or check the pin)
   1.775 +     * it'll just rely on the Framework as needed.
   1.776 +     */
   1.777 +    ;
   1.778 +  } else {
   1.779 +    error = fwSession->mdSession->Login(fwSession->mdSession, fwSession,
   1.780 +      fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   1.781 +      fwSession->fwInstance, userType, pin, oldState, newState);
   1.782 +    if( CKR_OK != error ) {
   1.783 +      return error;
   1.784 +    }
   1.785 +  }
   1.786 +
   1.787 +  (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
   1.788 +  return CKR_OK;
   1.789 +}
   1.790 +
   1.791 +/*
   1.792 + * nssCKFWSession_Logout
   1.793 + *
   1.794 + */
   1.795 +NSS_IMPLEMENT CK_RV
   1.796 +nssCKFWSession_Logout
   1.797 +(
   1.798 +  NSSCKFWSession *fwSession
   1.799 +)
   1.800 +{
   1.801 +  CK_RV error = CKR_OK;
   1.802 +  CK_STATE oldState;
   1.803 +  CK_STATE newState;
   1.804 +
   1.805 +#ifdef NSSDEBUG
   1.806 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.807 +  if( CKR_OK != error ) {
   1.808 +    return error;
   1.809 +  }
   1.810 +
   1.811 +  if (!fwSession->mdSession) {
   1.812 +    return CKR_GENERAL_ERROR;
   1.813 +  }
   1.814 +#endif /* NSSDEBUG */
   1.815 +
   1.816 +  oldState = nssCKFWToken_GetSessionState(fwSession->fwToken);
   1.817 +
   1.818 +  switch( oldState ) {
   1.819 +  case CKS_RO_PUBLIC_SESSION:
   1.820 +    return CKR_USER_NOT_LOGGED_IN;
   1.821 +  case CKS_RO_USER_FUNCTIONS:
   1.822 +    newState = CKS_RO_PUBLIC_SESSION;
   1.823 +    break;
   1.824 +  case CKS_RW_PUBLIC_SESSION:
   1.825 +    return CKR_USER_NOT_LOGGED_IN;
   1.826 +  case CKS_RW_USER_FUNCTIONS:
   1.827 +    newState = CKS_RW_PUBLIC_SESSION;
   1.828 +    break;
   1.829 +  case CKS_RW_SO_FUNCTIONS:
   1.830 +    newState = CKS_RW_PUBLIC_SESSION;
   1.831 +    break;
   1.832 +  default:
   1.833 +    return CKR_GENERAL_ERROR;
   1.834 +  }
   1.835 +
   1.836 +  /*
   1.837 +   * So now we're in one of three cases:
   1.838 +   *
   1.839 +   * Old == CKS_RW_SO_FUNCTIONS,   New == CKS_RW_PUBLIC_SESSION;
   1.840 +   * Old == CKS_RW_USER_FUNCTIONS, New == CKS_RW_PUBLIC_SESSION;
   1.841 +   * Old == CKS_RO_USER_FUNCTIONS, New == CKS_RO_PUBLIC_SESSION;
   1.842 +   */
   1.843 +
   1.844 +  if (!fwSession->mdSession->Logout) {
   1.845 +    /*
   1.846 +     * The Module doesn't want to be informed.  Okay.
   1.847 +     */
   1.848 +    ;
   1.849 +  } else {
   1.850 +    error = fwSession->mdSession->Logout(fwSession->mdSession, fwSession,
   1.851 +      fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   1.852 +      fwSession->fwInstance, oldState, newState);
   1.853 +    if( CKR_OK != error ) {
   1.854 +      /*
   1.855 +       * Now what?!  A failure really should end up with the Framework
   1.856 +       * considering it logged out, right?
   1.857 +       */
   1.858 +      ;
   1.859 +    }
   1.860 +  }
   1.861 +
   1.862 +  (void)nssCKFWToken_SetSessionState(fwSession->fwToken, newState);
   1.863 +  return error;
   1.864 +}
   1.865 +
   1.866 +/*
   1.867 + * nssCKFWSession_InitPIN
   1.868 + *
   1.869 + */
   1.870 +NSS_IMPLEMENT CK_RV
   1.871 +nssCKFWSession_InitPIN
   1.872 +(
   1.873 +  NSSCKFWSession *fwSession,
   1.874 +  NSSItem *pin
   1.875 +)
   1.876 +{
   1.877 +  CK_RV error = CKR_OK;
   1.878 +  CK_STATE state;
   1.879 +
   1.880 +#ifdef NSSDEBUG
   1.881 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.882 +  if( CKR_OK != error ) {
   1.883 +    return error;
   1.884 +  }
   1.885 +
   1.886 +  if (!fwSession->mdSession) {
   1.887 +    return CKR_GENERAL_ERROR;
   1.888 +  }
   1.889 +#endif /* NSSDEBUG */
   1.890 +
   1.891 +  state = nssCKFWToken_GetSessionState(fwSession->fwToken);
   1.892 +  if( CKS_RW_SO_FUNCTIONS != state ) {
   1.893 +    return CKR_USER_NOT_LOGGED_IN;
   1.894 +  }
   1.895 +
   1.896 +  if (!pin) {
   1.897 +    CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   1.898 +    if( CK_TRUE != has ) {
   1.899 +      return CKR_ARGUMENTS_BAD;
   1.900 +    }
   1.901 +  }
   1.902 +
   1.903 +  if (!fwSession->mdSession->InitPIN) {
   1.904 +    return CKR_TOKEN_WRITE_PROTECTED;
   1.905 +  }
   1.906 +
   1.907 +  error = fwSession->mdSession->InitPIN(fwSession->mdSession, fwSession,
   1.908 +    fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   1.909 +    fwSession->fwInstance, pin);
   1.910 +
   1.911 +  return error;
   1.912 +}
   1.913 +
   1.914 +/*
   1.915 + * nssCKFWSession_SetPIN
   1.916 + *
   1.917 + */
   1.918 +NSS_IMPLEMENT CK_RV
   1.919 +nssCKFWSession_SetPIN
   1.920 +(
   1.921 +  NSSCKFWSession *fwSession,
   1.922 +  NSSItem *newPin,
   1.923 +  NSSItem *oldPin
   1.924 +)
   1.925 +{
   1.926 +  CK_RV error = CKR_OK;
   1.927 +
   1.928 +#ifdef NSSDEBUG
   1.929 +  error = nssCKFWSession_verifyPointer(fwSession);
   1.930 +  if( CKR_OK != error ) {
   1.931 +    return error;
   1.932 +  }
   1.933 +
   1.934 +  if (!fwSession->mdSession) {
   1.935 +    return CKR_GENERAL_ERROR;
   1.936 +  }
   1.937 +#endif /* NSSDEBUG */
   1.938 +
   1.939 +  if (!newPin) {
   1.940 +    CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   1.941 +    if( CK_TRUE != has ) {
   1.942 +      return CKR_ARGUMENTS_BAD;
   1.943 +    }
   1.944 +  }
   1.945 +
   1.946 +  if (!oldPin) {
   1.947 +    CK_BBOOL has = nssCKFWToken_GetHasProtectedAuthenticationPath(fwSession->fwToken);
   1.948 +    if( CK_TRUE != has ) {
   1.949 +      return CKR_ARGUMENTS_BAD;
   1.950 +    }
   1.951 +  }
   1.952 +
   1.953 +  if (!fwSession->mdSession->SetPIN) {
   1.954 +    return CKR_TOKEN_WRITE_PROTECTED;
   1.955 +  }
   1.956 +
   1.957 +  error = fwSession->mdSession->SetPIN(fwSession->mdSession, fwSession,
   1.958 +    fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
   1.959 +    fwSession->fwInstance, newPin, oldPin);
   1.960 +
   1.961 +  return error;
   1.962 +}
   1.963 +
   1.964 +/*
   1.965 + * nssCKFWSession_GetOperationStateLen
   1.966 + *
   1.967 + */
   1.968 +NSS_IMPLEMENT CK_ULONG
   1.969 +nssCKFWSession_GetOperationStateLen
   1.970 +(
   1.971 +  NSSCKFWSession *fwSession,
   1.972 +  CK_RV *pError
   1.973 +)
   1.974 +{
   1.975 +  CK_ULONG mdAmt;
   1.976 +  CK_ULONG fwAmt;
   1.977 +
   1.978 +#ifdef NSSDEBUG
   1.979 +  if (!pError) {
   1.980 +    return (CK_ULONG)0;
   1.981 +  }
   1.982 +
   1.983 +  *pError = nssCKFWSession_verifyPointer(fwSession);
   1.984 +  if( CKR_OK != *pError ) {
   1.985 +    return (CK_ULONG)0;
   1.986 +  }
   1.987 +
   1.988 +  if (!fwSession->mdSession) {
   1.989 +    *pError = CKR_GENERAL_ERROR;
   1.990 +    return (CK_ULONG)0;
   1.991 +  }
   1.992 +#endif /* NSSDEBUG */
   1.993 +
   1.994 +  if (!fwSession->mdSession->GetOperationStateLen) {
   1.995 +    *pError = CKR_STATE_UNSAVEABLE;
   1.996 +    return (CK_ULONG)0;
   1.997 +  }
   1.998 +
   1.999 +  /*
  1.1000 +   * We could check that the session is actually in some state..
  1.1001 +   */
  1.1002 +
  1.1003 +  mdAmt = fwSession->mdSession->GetOperationStateLen(fwSession->mdSession,
  1.1004 +    fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1.1005 +    fwSession->fwInstance, pError);
  1.1006 +
  1.1007 +  if( ((CK_ULONG)0 == mdAmt) && (CKR_OK != *pError) ) {
  1.1008 +    return (CK_ULONG)0;
  1.1009 +  }
  1.1010 +
  1.1011 +  /*
  1.1012 +   * Add a bit of sanity-checking
  1.1013 +   */
  1.1014 +  fwAmt = mdAmt + 2*sizeof(CK_ULONG);
  1.1015 +
  1.1016 +  return fwAmt;
  1.1017 +}
  1.1018 +
  1.1019 +/*
  1.1020 + * nssCKFWSession_GetOperationState
  1.1021 + *
  1.1022 + */
  1.1023 +NSS_IMPLEMENT CK_RV
  1.1024 +nssCKFWSession_GetOperationState
  1.1025 +(
  1.1026 +  NSSCKFWSession *fwSession,
  1.1027 +  NSSItem *buffer
  1.1028 +)
  1.1029 +{
  1.1030 +  CK_RV error = CKR_OK;
  1.1031 +  CK_ULONG fwAmt;
  1.1032 +  CK_ULONG *ulBuffer;
  1.1033 +  NSSItem i2;
  1.1034 +  CK_ULONG n, i;
  1.1035 +
  1.1036 +#ifdef NSSDEBUG
  1.1037 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1038 +  if( CKR_OK != error ) {
  1.1039 +    return error;
  1.1040 +  }
  1.1041 +
  1.1042 +  if (!buffer) {
  1.1043 +    return CKR_ARGUMENTS_BAD;
  1.1044 +  }
  1.1045 +
  1.1046 +  if (!buffer->data) {
  1.1047 +    return CKR_ARGUMENTS_BAD;
  1.1048 +  }
  1.1049 +
  1.1050 +  if (!fwSession->mdSession) {
  1.1051 +    return CKR_GENERAL_ERROR;
  1.1052 +  }
  1.1053 +#endif /* NSSDEBUG */
  1.1054 +
  1.1055 +  if (!fwSession->mdSession->GetOperationState) {
  1.1056 +    return CKR_STATE_UNSAVEABLE;
  1.1057 +  }
  1.1058 +
  1.1059 +  /*
  1.1060 +   * Sanity-check the caller's buffer.
  1.1061 +   */
  1.1062 +
  1.1063 +  error = CKR_OK;
  1.1064 +  fwAmt = nssCKFWSession_GetOperationStateLen(fwSession, &error);
  1.1065 +  if( ((CK_ULONG)0 == fwAmt) && (CKR_OK != error) ) {
  1.1066 +    return error;
  1.1067 +  }
  1.1068 +
  1.1069 +  if( buffer->size < fwAmt ) {
  1.1070 +    return CKR_BUFFER_TOO_SMALL;
  1.1071 +  }
  1.1072 +
  1.1073 +  ulBuffer = (CK_ULONG *)buffer->data;
  1.1074 +
  1.1075 +  i2.size = buffer->size - 2*sizeof(CK_ULONG);
  1.1076 +  i2.data = (void *)&ulBuffer[2];
  1.1077 +
  1.1078 +  error = fwSession->mdSession->GetOperationState(fwSession->mdSession,
  1.1079 +    fwSession, fwSession->mdToken, fwSession->fwToken, 
  1.1080 +    fwSession->mdInstance, fwSession->fwInstance, &i2);
  1.1081 +
  1.1082 +  if( CKR_OK != error ) {
  1.1083 +    return error;
  1.1084 +  }
  1.1085 +
  1.1086 +  /*
  1.1087 +   * Add a little integrety/identity check.  
  1.1088 +   * NOTE: right now, it's pretty stupid.  
  1.1089 +   * A CRC or something would be better.
  1.1090 +   */
  1.1091 +
  1.1092 +  ulBuffer[0] = 0x434b4657; /* CKFW */
  1.1093 +  ulBuffer[1] = 0;
  1.1094 +  n = i2.size/sizeof(CK_ULONG);
  1.1095 +  for( i = 0; i < n; i++ ) {
  1.1096 +    ulBuffer[1] ^= ulBuffer[2+i];
  1.1097 +  }
  1.1098 +
  1.1099 +  return CKR_OK;
  1.1100 +}
  1.1101 +
  1.1102 +/*
  1.1103 + * nssCKFWSession_SetOperationState
  1.1104 + *
  1.1105 + */
  1.1106 +NSS_IMPLEMENT CK_RV
  1.1107 +nssCKFWSession_SetOperationState
  1.1108 +(
  1.1109 +  NSSCKFWSession *fwSession,
  1.1110 +  NSSItem *state,
  1.1111 +  NSSCKFWObject *encryptionKey,
  1.1112 +  NSSCKFWObject *authenticationKey
  1.1113 +)
  1.1114 +{
  1.1115 +  CK_RV error = CKR_OK;
  1.1116 +  CK_ULONG *ulBuffer;
  1.1117 +  CK_ULONG n, i;
  1.1118 +  CK_ULONG x;
  1.1119 +  NSSItem s;
  1.1120 +  NSSCKMDObject *mdek;
  1.1121 +  NSSCKMDObject *mdak;
  1.1122 +
  1.1123 +#ifdef NSSDEBUG
  1.1124 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1125 +  if( CKR_OK != error ) {
  1.1126 +    return error;
  1.1127 +  }
  1.1128 +
  1.1129 +  if (!state) {
  1.1130 +    return CKR_ARGUMENTS_BAD;
  1.1131 +  }
  1.1132 +
  1.1133 +  if (!state->data) {
  1.1134 +    return CKR_ARGUMENTS_BAD;
  1.1135 +  }
  1.1136 +
  1.1137 +  if (encryptionKey) {
  1.1138 +    error = nssCKFWObject_verifyPointer(encryptionKey);
  1.1139 +    if( CKR_OK != error ) {
  1.1140 +      return error;
  1.1141 +    }
  1.1142 +  }
  1.1143 +
  1.1144 +  if (authenticationKey) {
  1.1145 +    error = nssCKFWObject_verifyPointer(authenticationKey);
  1.1146 +    if( CKR_OK != error ) {
  1.1147 +      return error;
  1.1148 +    }
  1.1149 +  }
  1.1150 +
  1.1151 +  if (!fwSession->mdSession) {
  1.1152 +    return CKR_GENERAL_ERROR;
  1.1153 +  }
  1.1154 +#endif /* NSSDEBUG */
  1.1155 +
  1.1156 +  ulBuffer = (CK_ULONG *)state->data;
  1.1157 +  if( 0x43b4657 != ulBuffer[0] ) {
  1.1158 +    return CKR_SAVED_STATE_INVALID;
  1.1159 +  }
  1.1160 +  n = (state->size / sizeof(CK_ULONG)) - 2;
  1.1161 +  x = (CK_ULONG)0;
  1.1162 +  for( i = 0; i < n; i++ ) {
  1.1163 +    x ^= ulBuffer[2+i];
  1.1164 +  }
  1.1165 +
  1.1166 +  if( x != ulBuffer[1] ) {
  1.1167 +    return CKR_SAVED_STATE_INVALID;
  1.1168 +  }
  1.1169 +
  1.1170 +  if (!fwSession->mdSession->SetOperationState) {
  1.1171 +    return CKR_GENERAL_ERROR;
  1.1172 +  }
  1.1173 +
  1.1174 +  s.size = state->size - 2*sizeof(CK_ULONG);
  1.1175 +  s.data = (void *)&ulBuffer[2];
  1.1176 +
  1.1177 +  if (encryptionKey) {
  1.1178 +    mdek = nssCKFWObject_GetMDObject(encryptionKey);
  1.1179 +  } else {
  1.1180 +    mdek = (NSSCKMDObject *)NULL;
  1.1181 +  }
  1.1182 +
  1.1183 +  if (authenticationKey) {
  1.1184 +    mdak = nssCKFWObject_GetMDObject(authenticationKey);
  1.1185 +  } else {
  1.1186 +    mdak = (NSSCKMDObject *)NULL;
  1.1187 +  }
  1.1188 +
  1.1189 +  error = fwSession->mdSession->SetOperationState(fwSession->mdSession, 
  1.1190 +    fwSession, fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1.1191 +    fwSession->fwInstance, &s, mdek, encryptionKey, mdak, authenticationKey);
  1.1192 +
  1.1193 +  if( CKR_OK != error ) {
  1.1194 +    return error;
  1.1195 +  }
  1.1196 +
  1.1197 +  /*
  1.1198 +   * Here'd we restore any session data
  1.1199 +   */
  1.1200 +  
  1.1201 +  return CKR_OK;
  1.1202 +}
  1.1203 +
  1.1204 +static CK_BBOOL
  1.1205 +nss_attributes_form_token_object
  1.1206 +(
  1.1207 +  CK_ATTRIBUTE_PTR pTemplate,
  1.1208 +  CK_ULONG ulAttributeCount
  1.1209 +)
  1.1210 +{
  1.1211 +  CK_ULONG i;
  1.1212 +  CK_BBOOL rv;
  1.1213 +
  1.1214 +  for( i = 0; i < ulAttributeCount; i++ ) {
  1.1215 +    if( CKA_TOKEN == pTemplate[i].type ) {
  1.1216 +      /* If we sanity-check, we can remove this sizeof check */
  1.1217 +      if( sizeof(CK_BBOOL) == pTemplate[i].ulValueLen ) {
  1.1218 +        (void)nsslibc_memcpy(&rv, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1.1219 +        return rv;
  1.1220 +      } else {
  1.1221 +        return CK_FALSE;
  1.1222 +      }
  1.1223 +    }
  1.1224 +  }
  1.1225 +
  1.1226 +  return CK_FALSE;
  1.1227 +}
  1.1228 +
  1.1229 +/*
  1.1230 + * nssCKFWSession_CreateObject
  1.1231 + *
  1.1232 + */
  1.1233 +NSS_IMPLEMENT NSSCKFWObject *
  1.1234 +nssCKFWSession_CreateObject
  1.1235 +(
  1.1236 +  NSSCKFWSession *fwSession,
  1.1237 +  CK_ATTRIBUTE_PTR pTemplate,
  1.1238 +  CK_ULONG ulAttributeCount,
  1.1239 +  CK_RV *pError
  1.1240 +)
  1.1241 +{
  1.1242 +  NSSArena *arena;
  1.1243 +  NSSCKMDObject *mdObject;
  1.1244 +  NSSCKFWObject *fwObject;
  1.1245 +  CK_BBOOL isTokenObject;
  1.1246 +
  1.1247 +#ifdef NSSDEBUG
  1.1248 +  if (!pError) {
  1.1249 +    return (NSSCKFWObject *)NULL;
  1.1250 +  }
  1.1251 +
  1.1252 +  *pError = nssCKFWSession_verifyPointer(fwSession);
  1.1253 +  if( CKR_OK != pError ) {
  1.1254 +    return (NSSCKFWObject *)NULL;
  1.1255 +  }
  1.1256 +
  1.1257 +  if( (CK_ATTRIBUTE_PTR)NULL == pTemplate ) {
  1.1258 +    *pError = CKR_ARGUMENTS_BAD;
  1.1259 +    return (NSSCKFWObject *)NULL;
  1.1260 +  }
  1.1261 +
  1.1262 +  if (!fwSession->mdSession) {
  1.1263 +    *pError = CKR_GENERAL_ERROR;
  1.1264 +    return (NSSCKFWObject *)NULL;
  1.1265 +  }
  1.1266 +#endif /* NSSDEBUG */
  1.1267 +
  1.1268 +  /*
  1.1269 +   * Here would be an excellent place to sanity-check the object.
  1.1270 +   */
  1.1271 +
  1.1272 +  isTokenObject = nss_attributes_form_token_object(pTemplate, ulAttributeCount);
  1.1273 +  if( CK_TRUE == isTokenObject ) {
  1.1274 +    /* === TOKEN OBJECT === */
  1.1275 +
  1.1276 +    if (!fwSession->mdSession->CreateObject) {
  1.1277 +      *pError = CKR_TOKEN_WRITE_PROTECTED;
  1.1278 +      return (NSSCKFWObject *)NULL;
  1.1279 +    }
  1.1280 +
  1.1281 +    arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1.1282 +    if (!arena) {
  1.1283 +      if( CKR_OK == *pError ) {
  1.1284 +        *pError = CKR_GENERAL_ERROR;
  1.1285 +      }
  1.1286 +      return (NSSCKFWObject *)NULL;
  1.1287 +    }
  1.1288 +
  1.1289 +    goto callmdcreateobject;
  1.1290 +  } else {
  1.1291 +    /* === SESSION OBJECT === */
  1.1292 +
  1.1293 +    arena = nssCKFWSession_GetArena(fwSession, pError);
  1.1294 +    if (!arena) {
  1.1295 +      if( CKR_OK == *pError ) {
  1.1296 +        *pError = CKR_GENERAL_ERROR;
  1.1297 +      }
  1.1298 +      return (NSSCKFWObject *)NULL;
  1.1299 +    }
  1.1300 +
  1.1301 +    if( CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1.1302 +                     fwSession->fwInstance) ) {
  1.1303 +      /* --- module handles the session object -- */
  1.1304 +
  1.1305 +      if (!fwSession->mdSession->CreateObject) {
  1.1306 +        *pError = CKR_GENERAL_ERROR;
  1.1307 +        return (NSSCKFWObject *)NULL;
  1.1308 +      }
  1.1309 +      
  1.1310 +      goto callmdcreateobject;
  1.1311 +    } else {
  1.1312 +      /* --- framework handles the session object -- */
  1.1313 +      mdObject = nssCKMDSessionObject_Create(fwSession->fwToken, 
  1.1314 +        arena, pTemplate, ulAttributeCount, pError);
  1.1315 +      goto gotmdobject;
  1.1316 +    }
  1.1317 +  }
  1.1318 +
  1.1319 + callmdcreateobject:
  1.1320 +  mdObject = fwSession->mdSession->CreateObject(fwSession->mdSession,
  1.1321 +    fwSession, fwSession->mdToken, fwSession->fwToken,
  1.1322 +    fwSession->mdInstance, fwSession->fwInstance, arena, pTemplate,
  1.1323 +    ulAttributeCount, pError);
  1.1324 +
  1.1325 + gotmdobject:
  1.1326 +  if (!mdObject) {
  1.1327 +    if( CKR_OK == *pError ) {
  1.1328 +      *pError = CKR_GENERAL_ERROR;
  1.1329 +    }
  1.1330 +    return (NSSCKFWObject *)NULL;
  1.1331 +  }
  1.1332 +
  1.1333 +  fwObject = nssCKFWObject_Create(arena, mdObject, 
  1.1334 +    isTokenObject ? NULL : fwSession, 
  1.1335 +    fwSession->fwToken, fwSession->fwInstance, pError);
  1.1336 +  if (!fwObject) {
  1.1337 +    if( CKR_OK == *pError ) {
  1.1338 +      *pError = CKR_GENERAL_ERROR;
  1.1339 +    }
  1.1340 +    
  1.1341 +    if (mdObject->Destroy) {
  1.1342 +      (void)mdObject->Destroy(mdObject, (NSSCKFWObject *)NULL,
  1.1343 +        fwSession->mdSession, fwSession, fwSession->mdToken,
  1.1344 +        fwSession->fwToken, fwSession->mdInstance, fwSession->fwInstance);
  1.1345 +    }
  1.1346 +    
  1.1347 +    return (NSSCKFWObject *)NULL;
  1.1348 +  }
  1.1349 +
  1.1350 +  if( CK_FALSE == isTokenObject ) {
  1.1351 +    if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, fwObject) ) {
  1.1352 +      *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, fwObject, fwObject);
  1.1353 +      if( CKR_OK != *pError ) {
  1.1354 +        nssCKFWObject_Finalize(fwObject, PR_TRUE);
  1.1355 +        return (NSSCKFWObject *)NULL;
  1.1356 +      }
  1.1357 +    }
  1.1358 +  }
  1.1359 +  
  1.1360 +  return fwObject;
  1.1361 +}
  1.1362 +
  1.1363 +/*
  1.1364 + * nssCKFWSession_CopyObject
  1.1365 + *
  1.1366 + */
  1.1367 +NSS_IMPLEMENT NSSCKFWObject *
  1.1368 +nssCKFWSession_CopyObject
  1.1369 +(
  1.1370 +  NSSCKFWSession *fwSession,
  1.1371 +  NSSCKFWObject *fwObject,
  1.1372 +  CK_ATTRIBUTE_PTR pTemplate,
  1.1373 +  CK_ULONG ulAttributeCount,
  1.1374 +  CK_RV *pError
  1.1375 +)
  1.1376 +{
  1.1377 +  CK_BBOOL oldIsToken;
  1.1378 +  CK_BBOOL newIsToken;
  1.1379 +  CK_ULONG i;
  1.1380 +  NSSCKFWObject *rv;
  1.1381 +
  1.1382 +#ifdef NSSDEBUG
  1.1383 +  if (!pError) {
  1.1384 +    return (NSSCKFWObject *)NULL;
  1.1385 +  }
  1.1386 +
  1.1387 +  *pError = nssCKFWSession_verifyPointer(fwSession);
  1.1388 +  if( CKR_OK != *pError ) {
  1.1389 +    return (NSSCKFWObject *)NULL;
  1.1390 +  }
  1.1391 +
  1.1392 +  *pError = nssCKFWObject_verifyPointer(fwObject);
  1.1393 +  if( CKR_OK != *pError ) {
  1.1394 +    return (NSSCKFWObject *)NULL;
  1.1395 +  }
  1.1396 +
  1.1397 +  if (!fwSession->mdSession) {
  1.1398 +    *pError = CKR_GENERAL_ERROR;
  1.1399 +    return (NSSCKFWObject *)NULL;
  1.1400 +  }
  1.1401 +#endif /* NSSDEBUG */
  1.1402 +
  1.1403 +  /*
  1.1404 +   * Sanity-check object
  1.1405 +   */
  1.1406 +
  1.1407 +  if (!fwObject) {
  1.1408 +    *pError = CKR_ARGUMENTS_BAD;
  1.1409 +    return (NSSCKFWObject *)NULL;
  1.1410 +  }
  1.1411 +
  1.1412 +  oldIsToken = nssCKFWObject_IsTokenObject(fwObject);
  1.1413 +
  1.1414 +  newIsToken = oldIsToken;
  1.1415 +  for( i = 0; i < ulAttributeCount; i++ ) {
  1.1416 +    if( CKA_TOKEN == pTemplate[i].type ) {
  1.1417 +      /* Since we sanity-checked the object, we know this is the right size. */
  1.1418 +      (void)nsslibc_memcpy(&newIsToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1.1419 +      break;
  1.1420 +    }
  1.1421 +  }
  1.1422 +
  1.1423 +  /*
  1.1424 +   * If the Module handles its session objects, or if both the new
  1.1425 +   * and old object are token objects, use CopyObject if it exists.
  1.1426 +   */
  1.1427 +
  1.1428 +  if ((fwSession->mdSession->CopyObject) &&
  1.1429 +      (((CK_TRUE == oldIsToken) && (CK_TRUE == newIsToken)) ||
  1.1430 +       (CK_TRUE == nssCKFWInstance_GetModuleHandlesSessionObjects(
  1.1431 +                     fwSession->fwInstance))) ) {
  1.1432 +    /* use copy object */
  1.1433 +    NSSArena *arena;
  1.1434 +    NSSCKMDObject *mdOldObject;
  1.1435 +    NSSCKMDObject *mdObject;
  1.1436 +
  1.1437 +    mdOldObject = nssCKFWObject_GetMDObject(fwObject);
  1.1438 +
  1.1439 +    if( CK_TRUE == newIsToken ) {
  1.1440 +      arena = nssCKFWToken_GetArena(fwSession->fwToken, pError);
  1.1441 +    } else {
  1.1442 +      arena = nssCKFWSession_GetArena(fwSession, pError);
  1.1443 +    }
  1.1444 +    if (!arena) {
  1.1445 +      if( CKR_OK == *pError ) {
  1.1446 +        *pError = CKR_GENERAL_ERROR;
  1.1447 +      }
  1.1448 +      return (NSSCKFWObject *)NULL;
  1.1449 +    }
  1.1450 +
  1.1451 +    mdObject = fwSession->mdSession->CopyObject(fwSession->mdSession,
  1.1452 +      fwSession, fwSession->mdToken, fwSession->fwToken,
  1.1453 +      fwSession->mdInstance, fwSession->fwInstance, mdOldObject,
  1.1454 +      fwObject, arena, pTemplate, ulAttributeCount, pError);
  1.1455 +    if (!mdObject) {
  1.1456 +      if( CKR_OK == *pError ) {
  1.1457 +        *pError = CKR_GENERAL_ERROR;
  1.1458 +      }
  1.1459 +      return (NSSCKFWObject *)NULL;
  1.1460 +    }
  1.1461 +
  1.1462 +    rv = nssCKFWObject_Create(arena, mdObject, 
  1.1463 +      newIsToken ? NULL : fwSession,
  1.1464 +      fwSession->fwToken, fwSession->fwInstance, pError);
  1.1465 +
  1.1466 +    if( CK_FALSE == newIsToken ) {
  1.1467 +      if( CK_FALSE == nssCKFWHash_Exists(fwSession->sessionObjectHash, rv) ) {
  1.1468 +        *pError = nssCKFWHash_Add(fwSession->sessionObjectHash, rv, rv);
  1.1469 +        if( CKR_OK != *pError ) {
  1.1470 +          nssCKFWObject_Finalize(rv, PR_TRUE);
  1.1471 +          return (NSSCKFWObject *)NULL;
  1.1472 +        }
  1.1473 +      }
  1.1474 +    }
  1.1475 +
  1.1476 +    return rv;
  1.1477 +  } else {
  1.1478 +    /* use create object */
  1.1479 +    NSSArena *tmpArena;
  1.1480 +    CK_ATTRIBUTE_PTR newTemplate;
  1.1481 +    CK_ULONG i, j, n, newLength, k;
  1.1482 +    CK_ATTRIBUTE_TYPE_PTR oldTypes;
  1.1483 +    NSSCKFWObject *rv;
  1.1484 +    
  1.1485 +    n = nssCKFWObject_GetAttributeCount(fwObject, pError);
  1.1486 +    if( (0 == n) && (CKR_OK != *pError) ) {
  1.1487 +      return (NSSCKFWObject *)NULL;
  1.1488 +    }
  1.1489 +
  1.1490 +    tmpArena = NSSArena_Create();
  1.1491 +    if (!tmpArena) {
  1.1492 +      *pError = CKR_HOST_MEMORY;
  1.1493 +      return (NSSCKFWObject *)NULL;
  1.1494 +    }
  1.1495 +
  1.1496 +    oldTypes = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE_TYPE, n);
  1.1497 +    if( (CK_ATTRIBUTE_TYPE_PTR)NULL == oldTypes ) {
  1.1498 +      NSSArena_Destroy(tmpArena);
  1.1499 +      *pError = CKR_HOST_MEMORY;
  1.1500 +      return (NSSCKFWObject *)NULL;
  1.1501 +    }
  1.1502 +
  1.1503 +    *pError = nssCKFWObject_GetAttributeTypes(fwObject, oldTypes, n);
  1.1504 +    if( CKR_OK != *pError ) {
  1.1505 +      NSSArena_Destroy(tmpArena);
  1.1506 +      return (NSSCKFWObject *)NULL;
  1.1507 +    }
  1.1508 +
  1.1509 +    newLength = n;
  1.1510 +    for( i = 0; i < ulAttributeCount; i++ ) {
  1.1511 +      for( j = 0; j < n; j++ ) {
  1.1512 +        if( oldTypes[j] == pTemplate[i].type ) {
  1.1513 +          if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1.1514 +            /* Removing the attribute */
  1.1515 +            newLength--;
  1.1516 +          }
  1.1517 +          break;
  1.1518 +        }
  1.1519 +      }
  1.1520 +      if( j == n ) {
  1.1521 +        /* Not found */
  1.1522 +        newLength++;
  1.1523 +      }
  1.1524 +    }
  1.1525 +
  1.1526 +    newTemplate = nss_ZNEWARRAY(tmpArena, CK_ATTRIBUTE, newLength);
  1.1527 +    if( (CK_ATTRIBUTE_PTR)NULL == newTemplate ) {
  1.1528 +      NSSArena_Destroy(tmpArena);
  1.1529 +      *pError = CKR_HOST_MEMORY;
  1.1530 +      return (NSSCKFWObject *)NULL;
  1.1531 +    }
  1.1532 +
  1.1533 +    k = 0;
  1.1534 +    for( j = 0; j < n; j++ ) {
  1.1535 +      for( i = 0; i < ulAttributeCount; i++ ) {
  1.1536 +        if( oldTypes[j] == pTemplate[i].type ) {
  1.1537 +          if( (CK_VOID_PTR)NULL == pTemplate[i].pValue ) {
  1.1538 +            /* This attribute is being deleted */
  1.1539 +            ;
  1.1540 +          } else {
  1.1541 +            /* This attribute is being replaced */
  1.1542 +            newTemplate[k].type = pTemplate[i].type;
  1.1543 +            newTemplate[k].pValue = pTemplate[i].pValue;
  1.1544 +            newTemplate[k].ulValueLen = pTemplate[i].ulValueLen;
  1.1545 +            k++;
  1.1546 +          }
  1.1547 +          break;
  1.1548 +        }
  1.1549 +      }
  1.1550 +      if( i == ulAttributeCount ) {
  1.1551 +        /* This attribute is being copied over from the old object */
  1.1552 +        NSSItem item, *it;
  1.1553 +        item.size = 0;
  1.1554 +        item.data = (void *)NULL;
  1.1555 +        it = nssCKFWObject_GetAttribute(fwObject, oldTypes[j],
  1.1556 +          &item, tmpArena, pError);
  1.1557 +        if (!it) {
  1.1558 +          if( CKR_OK == *pError ) {
  1.1559 +            *pError = CKR_GENERAL_ERROR;
  1.1560 +          }
  1.1561 +          NSSArena_Destroy(tmpArena);
  1.1562 +          return (NSSCKFWObject *)NULL;
  1.1563 +        }
  1.1564 +        newTemplate[k].type = oldTypes[j];
  1.1565 +        newTemplate[k].pValue = it->data;
  1.1566 +        newTemplate[k].ulValueLen = it->size;
  1.1567 +        k++;
  1.1568 +      }
  1.1569 +    }
  1.1570 +    /* assert that k == newLength */
  1.1571 +
  1.1572 +    rv = nssCKFWSession_CreateObject(fwSession, newTemplate, newLength, pError);
  1.1573 +    if (!rv) {
  1.1574 +      if( CKR_OK == *pError ) {
  1.1575 +        *pError = CKR_GENERAL_ERROR;
  1.1576 +      }
  1.1577 +      NSSArena_Destroy(tmpArena);
  1.1578 +      return (NSSCKFWObject *)NULL;
  1.1579 +    }
  1.1580 +
  1.1581 +    NSSArena_Destroy(tmpArena);
  1.1582 +    return rv;
  1.1583 +  }
  1.1584 +}
  1.1585 +
  1.1586 +/*
  1.1587 + * nssCKFWSession_FindObjectsInit
  1.1588 + *
  1.1589 + */
  1.1590 +NSS_IMPLEMENT NSSCKFWFindObjects *
  1.1591 +nssCKFWSession_FindObjectsInit
  1.1592 +(
  1.1593 +  NSSCKFWSession *fwSession,
  1.1594 +  CK_ATTRIBUTE_PTR pTemplate,
  1.1595 +  CK_ULONG ulAttributeCount,
  1.1596 +  CK_RV *pError
  1.1597 +)
  1.1598 +{
  1.1599 +  NSSCKMDFindObjects *mdfo1 = (NSSCKMDFindObjects *)NULL;
  1.1600 +  NSSCKMDFindObjects *mdfo2 = (NSSCKMDFindObjects *)NULL;
  1.1601 +
  1.1602 +#ifdef NSSDEBUG
  1.1603 +  if (!pError) {
  1.1604 +    return (NSSCKFWFindObjects *)NULL;
  1.1605 +  }
  1.1606 +
  1.1607 +  *pError = nssCKFWSession_verifyPointer(fwSession);
  1.1608 +  if( CKR_OK != *pError ) {
  1.1609 +    return (NSSCKFWFindObjects *)NULL;
  1.1610 +  }
  1.1611 +
  1.1612 +  if( ((CK_ATTRIBUTE_PTR)NULL == pTemplate) && (ulAttributeCount != 0) ) {
  1.1613 +    *pError = CKR_ARGUMENTS_BAD;
  1.1614 +    return (NSSCKFWFindObjects *)NULL;
  1.1615 +  }
  1.1616 +
  1.1617 +  if (!fwSession->mdSession) {
  1.1618 +    *pError = CKR_GENERAL_ERROR;
  1.1619 +    return (NSSCKFWFindObjects *)NULL;
  1.1620 +  }
  1.1621 +#endif /* NSSDEBUG */
  1.1622 +
  1.1623 +  if( CK_TRUE != nssCKFWInstance_GetModuleHandlesSessionObjects(
  1.1624 +                   fwSession->fwInstance) ) {
  1.1625 +    CK_ULONG i;
  1.1626 +
  1.1627 +    /*
  1.1628 +     * Does the search criteria restrict us to token or session
  1.1629 +     * objects?
  1.1630 +     */
  1.1631 +
  1.1632 +    for( i = 0; i < ulAttributeCount; i++ ) {
  1.1633 +      if( CKA_TOKEN == pTemplate[i].type ) {
  1.1634 +        /* Yes, it does. */
  1.1635 +        CK_BBOOL isToken;
  1.1636 +        if( sizeof(CK_BBOOL) != pTemplate[i].ulValueLen ) {
  1.1637 +          *pError = CKR_ATTRIBUTE_VALUE_INVALID;
  1.1638 +          return (NSSCKFWFindObjects *)NULL;
  1.1639 +        }
  1.1640 +        (void)nsslibc_memcpy(&isToken, pTemplate[i].pValue, sizeof(CK_BBOOL));
  1.1641 +
  1.1642 +        if( CK_TRUE == isToken ) {
  1.1643 +          /* Pass it on to the module's search routine */
  1.1644 +          if (!fwSession->mdSession->FindObjectsInit) {
  1.1645 +            goto wrap;
  1.1646 +          }
  1.1647 +
  1.1648 +          mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1.1649 +                    fwSession, fwSession->mdToken, fwSession->fwToken,
  1.1650 +                    fwSession->mdInstance, fwSession->fwInstance, 
  1.1651 +                    pTemplate, ulAttributeCount, pError);
  1.1652 +        } else {
  1.1653 +          /* Do the search ourselves */
  1.1654 +          mdfo1 = nssCKMDFindSessionObjects_Create(fwSession->fwToken, 
  1.1655 +                    pTemplate, ulAttributeCount, pError);
  1.1656 +        }
  1.1657 +
  1.1658 +        if (!mdfo1) {
  1.1659 +          if( CKR_OK == *pError ) {
  1.1660 +            *pError = CKR_GENERAL_ERROR;
  1.1661 +          }
  1.1662 +          return (NSSCKFWFindObjects *)NULL;
  1.1663 +        }
  1.1664 +        
  1.1665 +        goto wrap;
  1.1666 +      }
  1.1667 +    }
  1.1668 +
  1.1669 +    if( i == ulAttributeCount ) {
  1.1670 +      /* No, it doesn't.  Do a hybrid search. */
  1.1671 +      mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1.1672 +                fwSession, fwSession->mdToken, fwSession->fwToken,
  1.1673 +                fwSession->mdInstance, fwSession->fwInstance, 
  1.1674 +                pTemplate, ulAttributeCount, pError);
  1.1675 +
  1.1676 +      if (!mdfo1) {
  1.1677 +        if( CKR_OK == *pError ) {
  1.1678 +          *pError = CKR_GENERAL_ERROR;
  1.1679 +        }
  1.1680 +        return (NSSCKFWFindObjects *)NULL;
  1.1681 +      }
  1.1682 +
  1.1683 +      mdfo2 = nssCKMDFindSessionObjects_Create(fwSession->fwToken,
  1.1684 +                pTemplate, ulAttributeCount, pError);
  1.1685 +      if (!mdfo2) {
  1.1686 +        if( CKR_OK == *pError ) {
  1.1687 +          *pError = CKR_GENERAL_ERROR;
  1.1688 +        }
  1.1689 +        if (mdfo1->Final) {
  1.1690 +          mdfo1->Final(mdfo1, (NSSCKFWFindObjects *)NULL, fwSession->mdSession,
  1.1691 +            fwSession, fwSession->mdToken, fwSession->fwToken, 
  1.1692 +            fwSession->mdInstance, fwSession->fwInstance);
  1.1693 +        }
  1.1694 +        return (NSSCKFWFindObjects *)NULL;
  1.1695 +      }
  1.1696 +
  1.1697 +      goto wrap;
  1.1698 +    }
  1.1699 +    /*NOTREACHED*/
  1.1700 +  } else {
  1.1701 +    /* Module handles all its own objects.  Pass on to module's search */
  1.1702 +    mdfo1 = fwSession->mdSession->FindObjectsInit(fwSession->mdSession,
  1.1703 +              fwSession, fwSession->mdToken, fwSession->fwToken,
  1.1704 +              fwSession->mdInstance, fwSession->fwInstance, 
  1.1705 +              pTemplate, ulAttributeCount, pError);
  1.1706 +
  1.1707 +    if (!mdfo1) {
  1.1708 +      if( CKR_OK == *pError ) {
  1.1709 +        *pError = CKR_GENERAL_ERROR;
  1.1710 +      }
  1.1711 +      return (NSSCKFWFindObjects *)NULL;
  1.1712 +    }
  1.1713 +
  1.1714 +    goto wrap;
  1.1715 +  }
  1.1716 +
  1.1717 + wrap:
  1.1718 +  return nssCKFWFindObjects_Create(fwSession, fwSession->fwToken,
  1.1719 +           fwSession->fwInstance, mdfo1, mdfo2, pError);
  1.1720 +}
  1.1721 +
  1.1722 +/*
  1.1723 + * nssCKFWSession_SeedRandom
  1.1724 + *
  1.1725 + */
  1.1726 +NSS_IMPLEMENT CK_RV
  1.1727 +nssCKFWSession_SeedRandom
  1.1728 +(
  1.1729 +  NSSCKFWSession *fwSession,
  1.1730 +  NSSItem *seed
  1.1731 +)
  1.1732 +{
  1.1733 +  CK_RV error = CKR_OK;
  1.1734 +
  1.1735 +#ifdef NSSDEBUG
  1.1736 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1737 +  if( CKR_OK != error ) {
  1.1738 +    return error;
  1.1739 +  }
  1.1740 +
  1.1741 +  if (!seed) {
  1.1742 +    return CKR_ARGUMENTS_BAD;
  1.1743 +  }
  1.1744 +
  1.1745 +  if (!seed->data) {
  1.1746 +    return CKR_ARGUMENTS_BAD;
  1.1747 +  }
  1.1748 +
  1.1749 +  if( 0 == seed->size ) {
  1.1750 +    return CKR_ARGUMENTS_BAD;
  1.1751 +  }
  1.1752 +
  1.1753 +  if (!fwSession->mdSession) {
  1.1754 +    return CKR_GENERAL_ERROR;
  1.1755 +  }
  1.1756 +#endif /* NSSDEBUG */
  1.1757 +
  1.1758 +  if (!fwSession->mdSession->SeedRandom) {
  1.1759 +    return CKR_RANDOM_SEED_NOT_SUPPORTED;
  1.1760 +  }
  1.1761 +
  1.1762 +  error = fwSession->mdSession->SeedRandom(fwSession->mdSession, fwSession,
  1.1763 +    fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1.1764 +    fwSession->fwInstance, seed);
  1.1765 +
  1.1766 +  return error;
  1.1767 +}
  1.1768 +
  1.1769 +/*
  1.1770 + * nssCKFWSession_GetRandom
  1.1771 + *
  1.1772 + */
  1.1773 +NSS_IMPLEMENT CK_RV
  1.1774 +nssCKFWSession_GetRandom
  1.1775 +(
  1.1776 +  NSSCKFWSession *fwSession,
  1.1777 +  NSSItem *buffer
  1.1778 +)
  1.1779 +{
  1.1780 +  CK_RV error = CKR_OK;
  1.1781 +
  1.1782 +#ifdef NSSDEBUG
  1.1783 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1784 +  if( CKR_OK != error ) {
  1.1785 +    return error;
  1.1786 +  }
  1.1787 +
  1.1788 +  if (!buffer) {
  1.1789 +    return CKR_ARGUMENTS_BAD;
  1.1790 +  }
  1.1791 +
  1.1792 +  if (!buffer->data) {
  1.1793 +    return CKR_ARGUMENTS_BAD;
  1.1794 +  }
  1.1795 +
  1.1796 +  if (!fwSession->mdSession) {
  1.1797 +    return CKR_GENERAL_ERROR;
  1.1798 +  }
  1.1799 +#endif /* NSSDEBUG */
  1.1800 +
  1.1801 +  if (!fwSession->mdSession->GetRandom) {
  1.1802 +    if( CK_TRUE == nssCKFWToken_GetHasRNG(fwSession->fwToken) ) {
  1.1803 +      return CKR_GENERAL_ERROR;
  1.1804 +    } else {
  1.1805 +      return CKR_RANDOM_NO_RNG;
  1.1806 +    }
  1.1807 +  }
  1.1808 +
  1.1809 +  if( 0 == buffer->size ) {
  1.1810 +    return CKR_OK;
  1.1811 +  }
  1.1812 +
  1.1813 +  error = fwSession->mdSession->GetRandom(fwSession->mdSession, fwSession,
  1.1814 +    fwSession->mdToken, fwSession->fwToken, fwSession->mdInstance,
  1.1815 +    fwSession->fwInstance, buffer);
  1.1816 +
  1.1817 +  return error;
  1.1818 +}
  1.1819 +
  1.1820 +
  1.1821 +/*
  1.1822 + * nssCKFWSession_SetCurrentCryptoOperation
  1.1823 + */
  1.1824 +NSS_IMPLEMENT void
  1.1825 +nssCKFWSession_SetCurrentCryptoOperation
  1.1826 +(
  1.1827 +  NSSCKFWSession *fwSession,
  1.1828 +  NSSCKFWCryptoOperation * fwOperation,
  1.1829 +  NSSCKFWCryptoOperationState state
  1.1830 +)
  1.1831 +{
  1.1832 +#ifdef NSSDEBUG
  1.1833 +  CK_RV error = CKR_OK;
  1.1834 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1835 +  if( CKR_OK != error ) {
  1.1836 +    return;
  1.1837 +  }
  1.1838 +
  1.1839 +  if ( state >= NSSCKFWCryptoOperationState_Max) {
  1.1840 +    return;
  1.1841 +  }
  1.1842 +
  1.1843 +  if (!fwSession->mdSession) {
  1.1844 +    return;
  1.1845 +  }
  1.1846 +#endif /* NSSDEBUG */
  1.1847 +  fwSession->fwOperationArray[state] = fwOperation;
  1.1848 +  return;
  1.1849 +}
  1.1850 +
  1.1851 +/*
  1.1852 + * nssCKFWSession_GetCurrentCryptoOperation
  1.1853 + */
  1.1854 +NSS_IMPLEMENT NSSCKFWCryptoOperation *
  1.1855 +nssCKFWSession_GetCurrentCryptoOperation
  1.1856 +(
  1.1857 +  NSSCKFWSession *fwSession,
  1.1858 +  NSSCKFWCryptoOperationState state
  1.1859 +)
  1.1860 +{
  1.1861 +#ifdef NSSDEBUG
  1.1862 +  CK_RV error = CKR_OK;
  1.1863 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1864 +  if( CKR_OK != error ) {
  1.1865 +    return (NSSCKFWCryptoOperation *)NULL;
  1.1866 +  }
  1.1867 +
  1.1868 +  if ( state >= NSSCKFWCryptoOperationState_Max) {
  1.1869 +    return (NSSCKFWCryptoOperation *)NULL;
  1.1870 +  }
  1.1871 +
  1.1872 +  if (!fwSession->mdSession) {
  1.1873 +    return (NSSCKFWCryptoOperation *)NULL;
  1.1874 +  }
  1.1875 +#endif /* NSSDEBUG */
  1.1876 +  return fwSession->fwOperationArray[state];
  1.1877 +}
  1.1878 +
  1.1879 +/*
  1.1880 + * nssCKFWSession_Final
  1.1881 + */
  1.1882 +NSS_IMPLEMENT CK_RV
  1.1883 +nssCKFWSession_Final
  1.1884 +(
  1.1885 +  NSSCKFWSession *fwSession,
  1.1886 +  NSSCKFWCryptoOperationType type,
  1.1887 +  NSSCKFWCryptoOperationState state,
  1.1888 +  CK_BYTE_PTR  outBuf,
  1.1889 +  CK_ULONG_PTR outBufLen
  1.1890 +)
  1.1891 +{
  1.1892 +  NSSCKFWCryptoOperation *fwOperation;
  1.1893 +  NSSItem outputBuffer;
  1.1894 +  CK_RV error = CKR_OK;
  1.1895 +
  1.1896 +#ifdef NSSDEBUG
  1.1897 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1898 +  if( CKR_OK != error ) {
  1.1899 +    return error;
  1.1900 +  }
  1.1901 +
  1.1902 +  if (!fwSession->mdSession) {
  1.1903 +    return CKR_GENERAL_ERROR;
  1.1904 +  }
  1.1905 +#endif /* NSSDEBUG */
  1.1906 +
  1.1907 +  /* make sure we have a valid operation initialized */
  1.1908 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1.1909 +  if (!fwOperation) {
  1.1910 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.1911 +  }
  1.1912 +
  1.1913 +  /* make sure it's the correct type */
  1.1914 +  if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.1915 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.1916 +  }
  1.1917 +
  1.1918 +  /* handle buffer issues, note for Verify, the type is an input buffer. */
  1.1919 +  if (NSSCKFWCryptoOperationType_Verify == type) {
  1.1920 +    if ((CK_BYTE_PTR)NULL == outBuf) {
  1.1921 +      error = CKR_ARGUMENTS_BAD;
  1.1922 +      goto done;
  1.1923 +    }
  1.1924 +  } else {
  1.1925 +    CK_ULONG len = nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
  1.1926 +    CK_ULONG maxBufLen = *outBufLen;
  1.1927 +
  1.1928 +    if (CKR_OK != error) {
  1.1929 +       goto done;
  1.1930 +    }
  1.1931 +    *outBufLen = len;
  1.1932 +    if ((CK_BYTE_PTR)NULL == outBuf) {
  1.1933 +      return CKR_OK;
  1.1934 +    }
  1.1935 +
  1.1936 +    if (len > maxBufLen) {
  1.1937 +      return CKR_BUFFER_TOO_SMALL;
  1.1938 +    }
  1.1939 +  }
  1.1940 +  outputBuffer.data = outBuf;
  1.1941 +  outputBuffer.size = *outBufLen;
  1.1942 +
  1.1943 +  error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
  1.1944 +done:
  1.1945 +  if (CKR_BUFFER_TOO_SMALL == error) {
  1.1946 +    return error;
  1.1947 +  }
  1.1948 +  /* clean up our state */
  1.1949 +  nssCKFWCryptoOperation_Destroy(fwOperation);
  1.1950 +  nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
  1.1951 +  return error;
  1.1952 +}
  1.1953 +
  1.1954 +/*
  1.1955 + * nssCKFWSession_Update
  1.1956 + */
  1.1957 +NSS_IMPLEMENT CK_RV
  1.1958 +nssCKFWSession_Update
  1.1959 +(
  1.1960 +  NSSCKFWSession *fwSession,
  1.1961 +  NSSCKFWCryptoOperationType type,
  1.1962 +  NSSCKFWCryptoOperationState state,
  1.1963 +  CK_BYTE_PTR  inBuf,
  1.1964 +  CK_ULONG     inBufLen,
  1.1965 +  CK_BYTE_PTR  outBuf,
  1.1966 +  CK_ULONG_PTR outBufLen
  1.1967 +)
  1.1968 +{
  1.1969 +  NSSCKFWCryptoOperation *fwOperation;
  1.1970 +  NSSItem inputBuffer;
  1.1971 +  NSSItem outputBuffer;
  1.1972 +  CK_ULONG len;
  1.1973 +  CK_ULONG maxBufLen;
  1.1974 +  CK_RV error = CKR_OK;
  1.1975 +
  1.1976 +#ifdef NSSDEBUG
  1.1977 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.1978 +  if( CKR_OK != error ) {
  1.1979 +    return error;
  1.1980 +  }
  1.1981 +
  1.1982 +  if (!fwSession->mdSession) {
  1.1983 +    return CKR_GENERAL_ERROR;
  1.1984 +  }
  1.1985 +#endif /* NSSDEBUG */
  1.1986 +
  1.1987 +  /* make sure we have a valid operation initialized */
  1.1988 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1.1989 +  if (!fwOperation) {
  1.1990 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.1991 +  }
  1.1992 +
  1.1993 +  /* make sure it's the correct type */
  1.1994 +  if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.1995 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.1996 +  }
  1.1997 +
  1.1998 +  inputBuffer.data = inBuf;
  1.1999 +  inputBuffer.size = inBufLen;
  1.2000 +
  1.2001 +  /* handle buffer issues, note for Verify, the type is an input buffer. */
  1.2002 +  len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, &inputBuffer, 
  1.2003 +                                                  &error);
  1.2004 +  if (CKR_OK != error) {
  1.2005 +    return error;
  1.2006 +  }
  1.2007 +  maxBufLen = *outBufLen;
  1.2008 +
  1.2009 +  *outBufLen = len;
  1.2010 +  if ((CK_BYTE_PTR)NULL == outBuf) {
  1.2011 +    return CKR_OK;
  1.2012 +  }
  1.2013 +
  1.2014 +  if (len > maxBufLen) {
  1.2015 +    return CKR_BUFFER_TOO_SMALL;
  1.2016 +  }
  1.2017 +  outputBuffer.data = outBuf;
  1.2018 +  outputBuffer.size = *outBufLen;
  1.2019 +
  1.2020 +  return nssCKFWCryptoOperation_Update(fwOperation,
  1.2021 +                                       &inputBuffer, &outputBuffer);
  1.2022 +}
  1.2023 +
  1.2024 +/*
  1.2025 + * nssCKFWSession_DigestUpdate
  1.2026 + */
  1.2027 +NSS_IMPLEMENT CK_RV
  1.2028 +nssCKFWSession_DigestUpdate
  1.2029 +(
  1.2030 +  NSSCKFWSession *fwSession,
  1.2031 +  NSSCKFWCryptoOperationType type,
  1.2032 +  NSSCKFWCryptoOperationState state,
  1.2033 +  CK_BYTE_PTR  inBuf,
  1.2034 +  CK_ULONG     inBufLen
  1.2035 +)
  1.2036 +{
  1.2037 +  NSSCKFWCryptoOperation *fwOperation;
  1.2038 +  NSSItem inputBuffer;
  1.2039 +  CK_RV error = CKR_OK;
  1.2040 +
  1.2041 +#ifdef NSSDEBUG
  1.2042 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2043 +  if( CKR_OK != error ) {
  1.2044 +    return error;
  1.2045 +  }
  1.2046 +
  1.2047 +  if (!fwSession->mdSession) {
  1.2048 +    return CKR_GENERAL_ERROR;
  1.2049 +  }
  1.2050 +#endif /* NSSDEBUG */
  1.2051 +
  1.2052 +  /* make sure we have a valid operation initialized */
  1.2053 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1.2054 +  if (!fwOperation) {
  1.2055 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2056 +  }
  1.2057 +
  1.2058 +  /* make sure it's the correct type */
  1.2059 +  if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.2060 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2061 +  }
  1.2062 +
  1.2063 +  inputBuffer.data = inBuf;
  1.2064 +  inputBuffer.size = inBufLen;
  1.2065 +
  1.2066 +
  1.2067 +  error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
  1.2068 +  return error;
  1.2069 +}
  1.2070 +
  1.2071 +/*
  1.2072 + * nssCKFWSession_DigestUpdate
  1.2073 + */
  1.2074 +NSS_IMPLEMENT CK_RV
  1.2075 +nssCKFWSession_DigestKey
  1.2076 +(
  1.2077 +  NSSCKFWSession *fwSession,
  1.2078 +  NSSCKFWObject *fwKey
  1.2079 +)
  1.2080 +{
  1.2081 +  NSSCKFWCryptoOperation *fwOperation;
  1.2082 +  NSSItem *inputBuffer;
  1.2083 +  CK_RV error = CKR_OK;
  1.2084 +
  1.2085 +#ifdef NSSDEBUG
  1.2086 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2087 +  if( CKR_OK != error ) {
  1.2088 +    return error;
  1.2089 +  }
  1.2090 +
  1.2091 +  if (!fwSession->mdSession) {
  1.2092 +    return CKR_GENERAL_ERROR;
  1.2093 +  }
  1.2094 +#endif /* NSSDEBUG */
  1.2095 +
  1.2096 +  /* make sure we have a valid operation initialized */
  1.2097 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  1.2098 +                                 NSSCKFWCryptoOperationState_Digest);
  1.2099 +  if (!fwOperation) {
  1.2100 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2101 +  }
  1.2102 +
  1.2103 +  /* make sure it's the correct type */
  1.2104 +  if (NSSCKFWCryptoOperationType_Digest != 
  1.2105 +      nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.2106 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2107 +  }
  1.2108 +
  1.2109 +  error = nssCKFWCryptoOperation_DigestKey(fwOperation, fwKey);
  1.2110 +  if (CKR_FUNCTION_FAILED != error) {
  1.2111 +    return error;
  1.2112 +  }
  1.2113 +
  1.2114 +  /* no machine depended way for this to happen, do it by hand */
  1.2115 +  inputBuffer=nssCKFWObject_GetAttribute(fwKey, CKA_VALUE, NULL, NULL, &error);
  1.2116 +  if (!inputBuffer) {
  1.2117 +    /* couldn't get the value, just fail then */
  1.2118 +    return error;
  1.2119 +  }
  1.2120 +  error = nssCKFWCryptoOperation_DigestUpdate(fwOperation, inputBuffer);
  1.2121 +  nssItem_Destroy(inputBuffer);
  1.2122 +  return error;
  1.2123 +}
  1.2124 +
  1.2125 +/*
  1.2126 + * nssCKFWSession_UpdateFinal
  1.2127 + */
  1.2128 +NSS_IMPLEMENT CK_RV
  1.2129 +nssCKFWSession_UpdateFinal
  1.2130 +(
  1.2131 +  NSSCKFWSession *fwSession,
  1.2132 +  NSSCKFWCryptoOperationType type,
  1.2133 +  NSSCKFWCryptoOperationState state,
  1.2134 +  CK_BYTE_PTR  inBuf,
  1.2135 +  CK_ULONG     inBufLen,
  1.2136 +  CK_BYTE_PTR  outBuf,
  1.2137 +  CK_ULONG_PTR outBufLen
  1.2138 +)
  1.2139 +{
  1.2140 +  NSSCKFWCryptoOperation *fwOperation;
  1.2141 +  NSSItem inputBuffer;
  1.2142 +  NSSItem outputBuffer;
  1.2143 +  PRBool isEncryptDecrypt;
  1.2144 +  CK_RV error = CKR_OK;
  1.2145 +
  1.2146 +#ifdef NSSDEBUG
  1.2147 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2148 +  if( CKR_OK != error ) {
  1.2149 +    return error;
  1.2150 +  }
  1.2151 +
  1.2152 +  if (!fwSession->mdSession) {
  1.2153 +    return CKR_GENERAL_ERROR;
  1.2154 +  }
  1.2155 +#endif /* NSSDEBUG */
  1.2156 +
  1.2157 +  /* make sure we have a valid operation initialized */
  1.2158 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1.2159 +  if (!fwOperation) {
  1.2160 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2161 +  }
  1.2162 +
  1.2163 +  /* make sure it's the correct type */
  1.2164 +  if (type != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.2165 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2166 +  }
  1.2167 +
  1.2168 +  inputBuffer.data = inBuf;
  1.2169 +  inputBuffer.size = inBufLen;
  1.2170 +  isEncryptDecrypt = (PRBool) ((NSSCKFWCryptoOperationType_Encrypt == type) || 
  1.2171 +                               (NSSCKFWCryptoOperationType_Decrypt == type)) ;
  1.2172 +
  1.2173 +  /* handle buffer issues, note for Verify, the type is an input buffer. */
  1.2174 +  if (NSSCKFWCryptoOperationType_Verify == type) {
  1.2175 +    if ((CK_BYTE_PTR)NULL == outBuf) {
  1.2176 +      error = CKR_ARGUMENTS_BAD;
  1.2177 +      goto done;
  1.2178 +    }
  1.2179 +  } else {
  1.2180 +    CK_ULONG maxBufLen = *outBufLen;
  1.2181 +    CK_ULONG len;
  1.2182 +
  1.2183 +    len = (isEncryptDecrypt) ?
  1.2184 +      nssCKFWCryptoOperation_GetOperationLength(fwOperation, 
  1.2185 +                                                &inputBuffer, &error) :
  1.2186 +      nssCKFWCryptoOperation_GetFinalLength(fwOperation, &error);
  1.2187 +
  1.2188 +    if (CKR_OK != error) {
  1.2189 +      goto done;
  1.2190 +    }
  1.2191 +
  1.2192 +    *outBufLen = len;
  1.2193 +    if ((CK_BYTE_PTR)NULL == outBuf) {
  1.2194 +      return CKR_OK;
  1.2195 +    }
  1.2196 +
  1.2197 +    if (len > maxBufLen) {
  1.2198 +      return CKR_BUFFER_TOO_SMALL;
  1.2199 +    }
  1.2200 +  }
  1.2201 +  outputBuffer.data = outBuf;
  1.2202 +  outputBuffer.size = *outBufLen;
  1.2203 +
  1.2204 +  error = nssCKFWCryptoOperation_UpdateFinal(fwOperation, 
  1.2205 +                                             &inputBuffer, &outputBuffer);
  1.2206 +
  1.2207 +  /* UpdateFinal isn't support, manually use Update and Final */
  1.2208 +  if (CKR_FUNCTION_FAILED == error) {
  1.2209 +    error = isEncryptDecrypt ? 
  1.2210 +      nssCKFWCryptoOperation_Update(fwOperation, &inputBuffer, &outputBuffer) :
  1.2211 +      nssCKFWCryptoOperation_DigestUpdate(fwOperation, &inputBuffer);
  1.2212 +
  1.2213 +    if (CKR_OK == error) {
  1.2214 +      error = nssCKFWCryptoOperation_Final(fwOperation, &outputBuffer);
  1.2215 +    }
  1.2216 +  }
  1.2217 +
  1.2218 +
  1.2219 +done:
  1.2220 +  if (CKR_BUFFER_TOO_SMALL == error) {
  1.2221 +    /* if we return CKR_BUFFER_TOO_SMALL, we the caller is not expecting.
  1.2222 +     * the crypto state to be freed */
  1.2223 +    return error;
  1.2224 +  }
  1.2225 +
  1.2226 +  /* clean up our state */
  1.2227 +  nssCKFWCryptoOperation_Destroy(fwOperation);
  1.2228 +  nssCKFWSession_SetCurrentCryptoOperation(fwSession, NULL, state);
  1.2229 +  return error;
  1.2230 +}
  1.2231 +
  1.2232 +NSS_IMPLEMENT CK_RV
  1.2233 +nssCKFWSession_UpdateCombo
  1.2234 +(
  1.2235 +  NSSCKFWSession *fwSession,
  1.2236 +  NSSCKFWCryptoOperationType encryptType,
  1.2237 +  NSSCKFWCryptoOperationType digestType,
  1.2238 +  NSSCKFWCryptoOperationState digestState,
  1.2239 +  CK_BYTE_PTR  inBuf,
  1.2240 +  CK_ULONG     inBufLen,
  1.2241 +  CK_BYTE_PTR  outBuf,
  1.2242 +  CK_ULONG_PTR outBufLen
  1.2243 +)
  1.2244 +{
  1.2245 +  NSSCKFWCryptoOperation *fwOperation;
  1.2246 +  NSSCKFWCryptoOperation *fwPeerOperation;
  1.2247 +  NSSItem inputBuffer;
  1.2248 +  NSSItem outputBuffer;
  1.2249 +  CK_ULONG maxBufLen = *outBufLen;
  1.2250 +  CK_ULONG len;
  1.2251 +  CK_RV error = CKR_OK;
  1.2252 +
  1.2253 +#ifdef NSSDEBUG
  1.2254 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2255 +  if( CKR_OK != error ) {
  1.2256 +    return error;
  1.2257 +  }
  1.2258 +
  1.2259 +  if (!fwSession->mdSession) {
  1.2260 +    return CKR_GENERAL_ERROR;
  1.2261 +  }
  1.2262 +#endif /* NSSDEBUG */
  1.2263 +
  1.2264 +  /* make sure we have a valid operation initialized */
  1.2265 +  fwOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  1.2266 +                NSSCKFWCryptoOperationState_EncryptDecrypt);
  1.2267 +  if (!fwOperation) {
  1.2268 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2269 +  }
  1.2270 +
  1.2271 +  /* make sure it's the correct type */
  1.2272 +  if (encryptType != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.2273 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2274 +  }
  1.2275 +  /* make sure we have a valid operation initialized */
  1.2276 +  fwPeerOperation = nssCKFWSession_GetCurrentCryptoOperation(fwSession, 
  1.2277 +                  digestState);
  1.2278 +  if (!fwPeerOperation) {
  1.2279 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2280 +  }
  1.2281 +
  1.2282 +  /* make sure it's the correct type */
  1.2283 +  if (digestType != nssCKFWCryptoOperation_GetType(fwOperation)) {
  1.2284 +    return CKR_OPERATION_NOT_INITIALIZED;
  1.2285 +  }
  1.2286 +
  1.2287 +  inputBuffer.data = inBuf;
  1.2288 +  inputBuffer.size = inBufLen;
  1.2289 +  len = nssCKFWCryptoOperation_GetOperationLength(fwOperation, 
  1.2290 +                                                &inputBuffer, &error);
  1.2291 +  if (CKR_OK != error) {
  1.2292 +    return error;
  1.2293 +  }
  1.2294 +
  1.2295 +  *outBufLen = len;
  1.2296 +  if ((CK_BYTE_PTR)NULL == outBuf) {
  1.2297 +    return CKR_OK;
  1.2298 +  }
  1.2299 +
  1.2300 +  if (len > maxBufLen) {
  1.2301 +    return CKR_BUFFER_TOO_SMALL;
  1.2302 +  }
  1.2303 +
  1.2304 +  outputBuffer.data = outBuf;
  1.2305 +  outputBuffer.size = *outBufLen;
  1.2306 +
  1.2307 +  error = nssCKFWCryptoOperation_UpdateCombo(fwOperation, fwPeerOperation,
  1.2308 +                                             &inputBuffer, &outputBuffer);
  1.2309 +  if (CKR_FUNCTION_FAILED == error) {
  1.2310 +    PRBool isEncrypt = 
  1.2311 +           (PRBool) (NSSCKFWCryptoOperationType_Encrypt == encryptType);
  1.2312 +
  1.2313 +    if (isEncrypt) {
  1.2314 +      error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation, 
  1.2315 +                                                  &inputBuffer);
  1.2316 +      if (CKR_OK != error) {
  1.2317 +        return error;
  1.2318 +      }
  1.2319 +    }
  1.2320 +    error = nssCKFWCryptoOperation_Update(fwOperation, 
  1.2321 +                                          &inputBuffer, &outputBuffer);
  1.2322 +    if (CKR_OK != error) {
  1.2323 +      return error;
  1.2324 +    }
  1.2325 +    if (!isEncrypt) {
  1.2326 +      error = nssCKFWCryptoOperation_DigestUpdate(fwPeerOperation,
  1.2327 +                                                  &outputBuffer);
  1.2328 +    }
  1.2329 +  }
  1.2330 +  return error;
  1.2331 +}
  1.2332 +
  1.2333 +
  1.2334 +/*
  1.2335 + * NSSCKFWSession_GetMDSession
  1.2336 + *
  1.2337 + */
  1.2338 +
  1.2339 +NSS_IMPLEMENT NSSCKMDSession *
  1.2340 +NSSCKFWSession_GetMDSession
  1.2341 +(
  1.2342 +  NSSCKFWSession *fwSession
  1.2343 +)
  1.2344 +{
  1.2345 +#ifdef DEBUG
  1.2346 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1.2347 +    return (NSSCKMDSession *)NULL;
  1.2348 +  }
  1.2349 +#endif /* DEBUG */
  1.2350 +
  1.2351 +  return nssCKFWSession_GetMDSession(fwSession);
  1.2352 +}
  1.2353 +
  1.2354 +/*
  1.2355 + * NSSCKFWSession_GetArena
  1.2356 + *
  1.2357 + */
  1.2358 +
  1.2359 +NSS_IMPLEMENT NSSArena *
  1.2360 +NSSCKFWSession_GetArena
  1.2361 +(
  1.2362 +  NSSCKFWSession *fwSession,
  1.2363 +  CK_RV *pError
  1.2364 +)
  1.2365 +{
  1.2366 +#ifdef DEBUG
  1.2367 +  if (!pError) {
  1.2368 +    return (NSSArena *)NULL;
  1.2369 +  }
  1.2370 +
  1.2371 +  *pError = nssCKFWSession_verifyPointer(fwSession);
  1.2372 +  if( CKR_OK != *pError ) {
  1.2373 +    return (NSSArena *)NULL;
  1.2374 +  }
  1.2375 +#endif /* DEBUG */
  1.2376 +
  1.2377 +  return nssCKFWSession_GetArena(fwSession, pError);
  1.2378 +}
  1.2379 +
  1.2380 +/*
  1.2381 + * NSSCKFWSession_CallNotification
  1.2382 + *
  1.2383 + */
  1.2384 +
  1.2385 +NSS_IMPLEMENT CK_RV
  1.2386 +NSSCKFWSession_CallNotification
  1.2387 +(
  1.2388 +  NSSCKFWSession *fwSession,
  1.2389 +  CK_NOTIFICATION event
  1.2390 +)
  1.2391 +{
  1.2392 +#ifdef DEBUG
  1.2393 +  CK_RV error = CKR_OK;
  1.2394 +
  1.2395 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2396 +  if( CKR_OK != error ) {
  1.2397 +    return error;
  1.2398 +  }
  1.2399 +#endif /* DEBUG */
  1.2400 +
  1.2401 +  return nssCKFWSession_CallNotification(fwSession, event);
  1.2402 +}
  1.2403 +
  1.2404 +/*
  1.2405 + * NSSCKFWSession_IsRWSession
  1.2406 + *
  1.2407 + */
  1.2408 +
  1.2409 +NSS_IMPLEMENT CK_BBOOL
  1.2410 +NSSCKFWSession_IsRWSession
  1.2411 +(
  1.2412 +  NSSCKFWSession *fwSession
  1.2413 +)
  1.2414 +{
  1.2415 +#ifdef DEBUG
  1.2416 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1.2417 +    return CK_FALSE;
  1.2418 +  }
  1.2419 +#endif /* DEBUG */
  1.2420 +
  1.2421 +  return nssCKFWSession_IsRWSession(fwSession);
  1.2422 +}
  1.2423 +
  1.2424 +/*
  1.2425 + * NSSCKFWSession_IsSO
  1.2426 + *
  1.2427 + */
  1.2428 +
  1.2429 +NSS_IMPLEMENT CK_BBOOL
  1.2430 +NSSCKFWSession_IsSO
  1.2431 +(
  1.2432 +  NSSCKFWSession *fwSession
  1.2433 +)
  1.2434 +{
  1.2435 +#ifdef DEBUG
  1.2436 +  if( CKR_OK != nssCKFWSession_verifyPointer(fwSession) ) {
  1.2437 +    return CK_FALSE;
  1.2438 +  }
  1.2439 +#endif /* DEBUG */
  1.2440 +
  1.2441 +  return nssCKFWSession_IsSO(fwSession);
  1.2442 +}
  1.2443 +
  1.2444 +NSS_IMPLEMENT NSSCKFWCryptoOperation *
  1.2445 +NSSCKFWSession_GetCurrentCryptoOperation
  1.2446 +(
  1.2447 +  NSSCKFWSession *fwSession,
  1.2448 +  NSSCKFWCryptoOperationState state
  1.2449 +)
  1.2450 +{
  1.2451 +#ifdef DEBUG
  1.2452 +  CK_RV error = CKR_OK;
  1.2453 +  error = nssCKFWSession_verifyPointer(fwSession);
  1.2454 +  if( CKR_OK != error ) {
  1.2455 +    return (NSSCKFWCryptoOperation *)NULL;
  1.2456 +  }
  1.2457 +
  1.2458 +  if ( state >= NSSCKFWCryptoOperationState_Max) {
  1.2459 +    return (NSSCKFWCryptoOperation *)NULL;
  1.2460 +  }
  1.2461 +#endif /* DEBUG */
  1.2462 +  return nssCKFWSession_GetCurrentCryptoOperation(fwSession, state);
  1.2463 +}

mercurial