security/nss/lib/softoken/legacydb/lgattr.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/softoken/legacydb/lgattr.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1790 @@
     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 + * Internal PKCS #11 functions. Should only be called by pkcs11.c
     1.9 + */
    1.10 +#include "pkcs11.h"
    1.11 +#include "lgdb.h"
    1.12 +
    1.13 +#include "pcertt.h"
    1.14 +#include "lowkeyi.h"
    1.15 +#include "pcert.h"
    1.16 +#include "blapi.h"
    1.17 +#include "secerr.h"
    1.18 +#include "secasn1.h"
    1.19 +
    1.20 +/*
    1.21 + * Cache the object we are working on during Set's and Get's
    1.22 + */
    1.23 +typedef struct LGObjectCacheStr {
    1.24 +    CK_OBJECT_CLASS  objclass;
    1.25 +    CK_OBJECT_HANDLE handle;
    1.26 +    SDB              *sdb;
    1.27 +    void             *objectInfo;
    1.28 +    LGFreeFunc       infoFree;
    1.29 +    SECItem          dbKey;
    1.30 +} LGObjectCache;
    1.31 +
    1.32 +static const CK_OBJECT_HANDLE lg_classArray[] = {
    1.33 +    0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
    1.34 +    CKO_NSS_TRUST, CKO_NSS_CRL, CKO_NSS_SMIME,
    1.35 +     CKO_CERTIFICATE };
    1.36 +
    1.37 +#define handleToClass(handle) \
    1.38 +    lg_classArray[((handle & LG_TOKEN_TYPE_MASK))>>LG_TOKEN_TYPE_SHIFT]
    1.39 +
    1.40 +
    1.41 +static void lg_DestroyObjectCache(LGObjectCache *obj);
    1.42 +
    1.43 +static LGObjectCache *
    1.44 +lg_NewObjectCache(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE handle)
    1.45 +{
    1.46 +    LGObjectCache *obj = NULL;
    1.47 +    SECStatus rv;
    1.48 +
    1.49 +    obj = PORT_New(LGObjectCache);
    1.50 +    if (obj == NULL) {
    1.51 +	return NULL;
    1.52 +    }
    1.53 +
    1.54 +    obj->objclass = handleToClass(handle);
    1.55 +    obj->handle = handle;
    1.56 +    obj->sdb = sdb;
    1.57 +    obj->objectInfo = NULL;
    1.58 +    obj->infoFree = NULL;
    1.59 +    obj->dbKey.data = NULL;
    1.60 +    obj->dbKey.len = 0;
    1.61 +    lg_DBLock(sdb);
    1.62 +    if (dbKey == NULL) {
    1.63 +	dbKey = lg_lookupTokenKeyByHandle(sdb,handle);
    1.64 +    }
    1.65 +    if (dbKey == NULL) {
    1.66 +	lg_DBUnlock(sdb);
    1.67 +	goto loser;
    1.68 +    }
    1.69 +    rv = SECITEM_CopyItem(NULL,&obj->dbKey,dbKey);
    1.70 +    lg_DBUnlock(sdb);
    1.71 +    if (rv != SECSuccess) {
    1.72 +	goto loser;
    1.73 +    }
    1.74 +
    1.75 +    return obj;
    1.76 +loser:
    1.77 +    if (obj) {
    1.78 +	(void) lg_DestroyObjectCache(obj);
    1.79 +    }
    1.80 +    return NULL;
    1.81 +
    1.82 +}
    1.83 +
    1.84 +/*
    1.85 + * free all the data associated with an object. Object reference count must
    1.86 + * be 'zero'.
    1.87 + */
    1.88 +static void
    1.89 +lg_DestroyObjectCache(LGObjectCache *obj)
    1.90 +{
    1.91 +    if (obj->dbKey.data) {
    1.92 +	PORT_Free(obj->dbKey.data);
    1.93 +	obj->dbKey.data = NULL;
    1.94 +    } 
    1.95 +    if (obj->objectInfo) {
    1.96 +	(*obj->infoFree)(obj->objectInfo);
    1.97 +	obj->objectInfo = NULL;
    1.98 +	obj->infoFree = NULL;
    1.99 +    }
   1.100 +    PORT_Free(obj);
   1.101 +}
   1.102 +/*
   1.103 + * ******************** Attribute Utilities *******************************
   1.104 + */
   1.105 +
   1.106 +static CK_RV
   1.107 +lg_ULongAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, CK_ULONG value)
   1.108 +{
   1.109 +    unsigned char *data;
   1.110 +    int i;
   1.111 +
   1.112 +    if (attr->pValue == NULL) {
   1.113 +	attr->ulValueLen = 4;
   1.114 +	return CKR_OK;
   1.115 +    }
   1.116 +    if (attr->ulValueLen < 4) {
   1.117 +	attr->ulValueLen = (CK_ULONG) -1;
   1.118 +	return CKR_BUFFER_TOO_SMALL;
   1.119 +    }
   1.120 +
   1.121 +    data = (unsigned char *)attr->pValue;
   1.122 +    for (i=0; i < 4; i++) {
   1.123 +	data[i] = (value >> ((3-i)*8)) & 0xff;
   1.124 +    }
   1.125 +    attr->ulValueLen = 4;
   1.126 +    return CKR_OK;
   1.127 +}
   1.128 +
   1.129 +static CK_RV
   1.130 +lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, 
   1.131 +				CK_VOID_PTR value, CK_ULONG len)
   1.132 +{
   1.133 +
   1.134 +    if (attr->pValue == NULL) {
   1.135 +	attr->ulValueLen = len;
   1.136 +	return CKR_OK;
   1.137 +    }
   1.138 +    if (attr->ulValueLen < len) {
   1.139 +	attr->ulValueLen = (CK_ULONG) -1;
   1.140 +	return CKR_BUFFER_TOO_SMALL;
   1.141 +    }
   1.142 +    PORT_Memcpy(attr->pValue,value,len);
   1.143 +    attr->ulValueLen = len;
   1.144 +    return CKR_OK;
   1.145 +}
   1.146 +
   1.147 +static CK_RV
   1.148 +lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 
   1.149 +				void  *value, CK_ULONG len)
   1.150 +{
   1.151 +    unsigned char * dval = (unsigned char *)value;
   1.152 +    if (*dval == 0) {
   1.153 +	dval++;
   1.154 +	len--;
   1.155 +    }
   1.156 +    return lg_CopyAttribute(attribute,type,dval,len);
   1.157 +}
   1.158 +
   1.159 +static CK_RV
   1.160 +lg_CopyPrivAttribute(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 
   1.161 +				void  *value, CK_ULONG len, SDB *sdbpw)
   1.162 +{
   1.163 +    SECItem plainText, *cipherText = NULL;
   1.164 +    CK_RV crv = CKR_USER_NOT_LOGGED_IN;
   1.165 +    SECStatus rv;
   1.166 +
   1.167 +    plainText.data = value;
   1.168 +    plainText.len = len;
   1.169 +    rv = lg_util_encrypt(NULL, sdbpw, &plainText, &cipherText);
   1.170 +    if (rv != SECSuccess) {
   1.171 +	goto loser;
   1.172 +    }
   1.173 +    crv = lg_CopyAttribute(attribute,type,cipherText->data,cipherText->len);
   1.174 +loser:
   1.175 +    if (cipherText) {
   1.176 +	SECITEM_FreeItem(cipherText,PR_TRUE);
   1.177 +    }
   1.178 +    return crv;
   1.179 +}
   1.180 +
   1.181 +static CK_RV
   1.182 +lg_CopyPrivAttrSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, 
   1.183 +				void  *value, CK_ULONG len, SDB *sdbpw)
   1.184 +{
   1.185 +    unsigned char * dval = (unsigned char *)value;
   1.186 +
   1.187 +    if (*dval == 0) {
   1.188 +	dval++;
   1.189 +	len--;
   1.190 +    }
   1.191 +    return lg_CopyPrivAttribute(attribute,type,dval,len,sdbpw);
   1.192 +}
   1.193 +
   1.194 +static CK_RV
   1.195 +lg_invalidAttribute(CK_ATTRIBUTE *attr)
   1.196 +{
   1.197 +    attr->ulValueLen = (CK_ULONG) -1;
   1.198 +    return CKR_ATTRIBUTE_TYPE_INVALID;
   1.199 +}
   1.200 +
   1.201 +
   1.202 +#define LG_DEF_ATTRIBUTE(value,len) \
   1.203 +   { 0, value, len }
   1.204 +
   1.205 +#define LG_CLONE_ATTR(attribute, type, staticAttr) \
   1.206 +    lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen)
   1.207 +
   1.208 +CK_BBOOL lg_staticTrueValue = CK_TRUE;
   1.209 +CK_BBOOL lg_staticFalseValue = CK_FALSE;
   1.210 +static const CK_ATTRIBUTE lg_StaticTrueAttr = 
   1.211 +  LG_DEF_ATTRIBUTE(&lg_staticTrueValue,sizeof(lg_staticTrueValue));
   1.212 +static const CK_ATTRIBUTE lg_StaticFalseAttr = 
   1.213 +  LG_DEF_ATTRIBUTE(&lg_staticFalseValue,sizeof(lg_staticFalseValue));
   1.214 +static const CK_ATTRIBUTE lg_StaticNullAttr = LG_DEF_ATTRIBUTE(NULL,0);
   1.215 +char lg_StaticOneValue = 1;
   1.216 +static const CK_ATTRIBUTE lg_StaticOneAttr = 
   1.217 +  LG_DEF_ATTRIBUTE(&lg_StaticOneValue,sizeof(lg_StaticOneValue));
   1.218 +
   1.219 +/*
   1.220 + * helper functions which get the database and call the underlying 
   1.221 + * low level database function.
   1.222 + */
   1.223 +static char *
   1.224 +lg_FindKeyNicknameByPublicKey(SDB *sdb, SECItem *dbKey)
   1.225 +{
   1.226 +    NSSLOWKEYDBHandle *keyHandle;
   1.227 +    char * label;
   1.228 +
   1.229 +    keyHandle = lg_getKeyDB(sdb);
   1.230 +    if (!keyHandle) {
   1.231 +	return NULL;
   1.232 +    }
   1.233 +
   1.234 +    label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey, 
   1.235 +						 sdb);
   1.236 +    return label;
   1.237 +}
   1.238 +
   1.239 +
   1.240 +NSSLOWKEYPrivateKey *
   1.241 +lg_FindKeyByPublicKey(SDB *sdb, SECItem *dbKey)
   1.242 +{
   1.243 +    NSSLOWKEYPrivateKey *privKey;
   1.244 +    NSSLOWKEYDBHandle   *keyHandle;
   1.245 +
   1.246 +    keyHandle = lg_getKeyDB(sdb);
   1.247 +    if (keyHandle == NULL) {
   1.248 +	return NULL;
   1.249 +    }
   1.250 +    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, sdb);
   1.251 +    if (privKey == NULL) {
   1.252 +	return NULL;
   1.253 +    }
   1.254 +    return privKey;
   1.255 +}
   1.256 +
   1.257 +static certDBEntrySMime *
   1.258 +lg_getSMime(LGObjectCache *obj)
   1.259 +{
   1.260 +    certDBEntrySMime *entry;
   1.261 +    NSSLOWCERTCertDBHandle *certHandle;
   1.262 +
   1.263 +    if (obj->objclass != CKO_NSS_SMIME) {
   1.264 +	return NULL;
   1.265 +    }
   1.266 +    if (obj->objectInfo) {
   1.267 +	return (certDBEntrySMime *)obj->objectInfo;
   1.268 +    }
   1.269 +
   1.270 +    certHandle = lg_getCertDB(obj->sdb);
   1.271 +    if (!certHandle) {
   1.272 +	return NULL;
   1.273 +    }
   1.274 +    entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)obj->dbKey.data);
   1.275 +    obj->objectInfo = (void *)entry;
   1.276 +    obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry;
   1.277 +    return entry;
   1.278 +}
   1.279 +
   1.280 +static certDBEntryRevocation *
   1.281 +lg_getCrl(LGObjectCache *obj)
   1.282 +{
   1.283 +    certDBEntryRevocation *crl;
   1.284 +    PRBool isKrl;
   1.285 +    NSSLOWCERTCertDBHandle *certHandle;
   1.286 +
   1.287 +    if (obj->objclass != CKO_NSS_CRL) {
   1.288 +	return NULL;
   1.289 +    }
   1.290 +    if (obj->objectInfo) {
   1.291 +	return (certDBEntryRevocation *)obj->objectInfo;
   1.292 +    }
   1.293 +
   1.294 +    isKrl = (PRBool) (obj->handle == LG_TOKEN_KRL_HANDLE);
   1.295 +    certHandle = lg_getCertDB(obj->sdb);
   1.296 +    if (!certHandle) {
   1.297 +	return NULL;
   1.298 +    }
   1.299 +
   1.300 +    crl = nsslowcert_FindCrlByKey(certHandle, &obj->dbKey, isKrl);
   1.301 +    obj->objectInfo = (void *)crl;
   1.302 +    obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry;
   1.303 +    return crl;
   1.304 +}
   1.305 +
   1.306 +static NSSLOWCERTCertificate *
   1.307 +lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
   1.308 +{
   1.309 +    NSSLOWCERTCertificate *cert;
   1.310 +    CK_OBJECT_CLASS objClass = obj->objclass;
   1.311 +
   1.312 +    if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NSS_TRUST)) {
   1.313 +	return NULL;
   1.314 +    }
   1.315 +    if (objClass == CKO_CERTIFICATE && obj->objectInfo) {
   1.316 +	return (NSSLOWCERTCertificate *)obj->objectInfo;
   1.317 +    }
   1.318 +    cert = nsslowcert_FindCertByKey(certHandle, &obj->dbKey);
   1.319 +    if (objClass == CKO_CERTIFICATE) {
   1.320 +	obj->objectInfo = (void *)cert;
   1.321 +	obj->infoFree = (LGFreeFunc) nsslowcert_DestroyCertificate ;
   1.322 +    }
   1.323 +    return cert;
   1.324 +}
   1.325 +
   1.326 +static NSSLOWCERTTrust *
   1.327 +lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
   1.328 +{
   1.329 +    NSSLOWCERTTrust *trust;
   1.330 +
   1.331 +    if (obj->objclass != CKO_NSS_TRUST) {
   1.332 +	return NULL;
   1.333 +    }
   1.334 +    if (obj->objectInfo) {
   1.335 +	return (NSSLOWCERTTrust *)obj->objectInfo;
   1.336 +    }
   1.337 +    trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey);
   1.338 +    obj->objectInfo = (void *)trust;
   1.339 +    obj->infoFree = (LGFreeFunc) nsslowcert_DestroyTrust ;
   1.340 +    return trust;
   1.341 +}
   1.342 +
   1.343 +static NSSLOWKEYPublicKey *
   1.344 +lg_GetPublicKey(LGObjectCache *obj)
   1.345 +{
   1.346 +    NSSLOWKEYPublicKey *pubKey;
   1.347 +    NSSLOWKEYPrivateKey *privKey;
   1.348 +
   1.349 +    if (obj->objclass != CKO_PUBLIC_KEY) {
   1.350 +	return NULL;
   1.351 +    }
   1.352 +    if (obj->objectInfo) {
   1.353 +	return (NSSLOWKEYPublicKey *)obj->objectInfo;
   1.354 +    }
   1.355 +    privKey = lg_FindKeyByPublicKey(obj->sdb, &obj->dbKey);
   1.356 +    if (privKey == NULL) {
   1.357 +	return NULL;
   1.358 +    }
   1.359 +    pubKey = lg_nsslowkey_ConvertToPublicKey(privKey);
   1.360 +    lg_nsslowkey_DestroyPrivateKey(privKey);
   1.361 +    obj->objectInfo = (void *) pubKey;
   1.362 +    obj->infoFree = (LGFreeFunc) lg_nsslowkey_DestroyPublicKey ;
   1.363 +    return pubKey;
   1.364 +}
   1.365 +
   1.366 +/*
   1.367 + * we need two versions of lg_GetPrivateKey. One version that takes the 
   1.368 + * DB handle so we can pass the handle we have already acquired in,
   1.369 + *  rather than going through the 'getKeyDB' code again, 
   1.370 + *  which may fail the second time and another which just aquires
   1.371 + *  the key handle from the sdb (where we don't already have a key handle.
   1.372 + * This version does the former.
   1.373 + */
   1.374 +static NSSLOWKEYPrivateKey *
   1.375 +lg_GetPrivateKeyWithDB(LGObjectCache *obj, NSSLOWKEYDBHandle *keyHandle)
   1.376 +{
   1.377 +    NSSLOWKEYPrivateKey *privKey;
   1.378 +
   1.379 +    if ((obj->objclass != CKO_PRIVATE_KEY) && 
   1.380 +			(obj->objclass != CKO_SECRET_KEY)) {
   1.381 +	return NULL;
   1.382 +    }
   1.383 +    if (obj->objectInfo) {
   1.384 +	return (NSSLOWKEYPrivateKey *)obj->objectInfo;
   1.385 +    }
   1.386 +    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &obj->dbKey, obj->sdb);
   1.387 +    if (privKey == NULL) {
   1.388 +	return NULL;
   1.389 +    }
   1.390 +    obj->objectInfo = (void *) privKey;
   1.391 +    obj->infoFree = (LGFreeFunc) lg_nsslowkey_DestroyPrivateKey ;
   1.392 +    return privKey;
   1.393 +}
   1.394 +
   1.395 +/* this version does the latter */
   1.396 +static NSSLOWKEYPrivateKey *
   1.397 +lg_GetPrivateKey(LGObjectCache *obj)
   1.398 +{
   1.399 +    NSSLOWKEYDBHandle *keyHandle;
   1.400 +    NSSLOWKEYPrivateKey *privKey;
   1.401 +
   1.402 +    keyHandle = lg_getKeyDB(obj->sdb);
   1.403 +    if (!keyHandle) {
   1.404 +	return NULL;
   1.405 +    }
   1.406 +    privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
   1.407 +    return privKey;
   1.408 +}
   1.409 +
   1.410 +/* lg_GetPubItem returns data associated with the public key.
   1.411 + * one only needs to free the public key. This comment is here
   1.412 + * because this sematic would be non-obvious otherwise. All callers
   1.413 + * should include this comment.
   1.414 + */
   1.415 +static SECItem *
   1.416 +lg_GetPubItem(NSSLOWKEYPublicKey *pubKey) {
   1.417 +    SECItem *pubItem = NULL;
   1.418 +    /* get value to compare from the cert's public key */
   1.419 +    switch ( pubKey->keyType ) {
   1.420 +    case NSSLOWKEYRSAKey:
   1.421 +	    pubItem = &pubKey->u.rsa.modulus;
   1.422 +	    break;
   1.423 +    case NSSLOWKEYDSAKey:
   1.424 +	    pubItem = &pubKey->u.dsa.publicValue;
   1.425 +	    break;
   1.426 +    case NSSLOWKEYDHKey:
   1.427 +	    pubItem = &pubKey->u.dh.publicValue;
   1.428 +	    break;
   1.429 +#ifndef NSS_DISABLE_ECC
   1.430 +    case NSSLOWKEYECKey:
   1.431 +	    pubItem = &pubKey->u.ec.publicValue;
   1.432 +	    break;
   1.433 +#endif /* NSS_DISABLE_ECC */
   1.434 +    default:
   1.435 +	    break;
   1.436 +    }
   1.437 +    return pubItem;
   1.438 +}
   1.439 +
   1.440 +static const SEC_ASN1Template lg_SerialTemplate[] = {
   1.441 +    { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) },
   1.442 +    { 0 }
   1.443 +};
   1.444 +
   1.445 +static CK_RV
   1.446 +lg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
   1.447 +				CK_ATTRIBUTE *attribute)
   1.448 +{
   1.449 +    unsigned char hash[SHA1_LENGTH];
   1.450 +    CK_KEY_TYPE keyType = CKK_RSA;
   1.451 +
   1.452 +    switch (type) {
   1.453 +    case CKA_KEY_TYPE:
   1.454 +	return lg_ULongAttribute(attribute, type, keyType);
   1.455 +    case CKA_ID:
   1.456 +	SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
   1.457 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.458 +    case CKA_DERIVE:
   1.459 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.460 +    case CKA_ENCRYPT:
   1.461 +    case CKA_VERIFY:
   1.462 +    case CKA_VERIFY_RECOVER:
   1.463 +    case CKA_WRAP:
   1.464 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.465 +    case CKA_MODULUS:
   1.466 +	return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,
   1.467 +					key->u.rsa.modulus.len);
   1.468 +    case CKA_PUBLIC_EXPONENT:
   1.469 +	return lg_CopyAttributeSigned(attribute, type,
   1.470 +				key->u.rsa.publicExponent.data,
   1.471 +				key->u.rsa.publicExponent.len);
   1.472 +    default:
   1.473 +	break;
   1.474 +    }
   1.475 +    return lg_invalidAttribute(attribute);
   1.476 +}
   1.477 +
   1.478 +static CK_RV
   1.479 +lg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
   1.480 +				CK_ATTRIBUTE *attribute)
   1.481 +{
   1.482 +    unsigned char hash[SHA1_LENGTH];
   1.483 +    CK_KEY_TYPE keyType = CKK_DSA;
   1.484 +
   1.485 +    switch (type) {
   1.486 +    case CKA_KEY_TYPE:
   1.487 +	return lg_ULongAttribute(attribute, type, keyType);
   1.488 +    case CKA_ID:
   1.489 +	SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
   1.490 +						key->u.dsa.publicValue.len);
   1.491 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.492 +    case CKA_DERIVE:
   1.493 +    case CKA_ENCRYPT:
   1.494 +    case CKA_VERIFY_RECOVER:
   1.495 +    case CKA_WRAP:
   1.496 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.497 +    case CKA_VERIFY:
   1.498 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.499 +    case CKA_VALUE:
   1.500 +	return lg_CopyAttributeSigned(attribute,type,
   1.501 +					key->u.dsa.publicValue.data,
   1.502 +					key->u.dsa.publicValue.len);
   1.503 +    case CKA_PRIME:
   1.504 +	return lg_CopyAttributeSigned(attribute,type,
   1.505 +					key->u.dsa.params.prime.data,
   1.506 +					key->u.dsa.params.prime.len);
   1.507 +    case CKA_SUBPRIME:
   1.508 +	return lg_CopyAttributeSigned(attribute,type,
   1.509 +				key->u.dsa.params.subPrime.data,
   1.510 +				key->u.dsa.params.subPrime.len);
   1.511 +    case CKA_BASE:
   1.512 +	return lg_CopyAttributeSigned(attribute,type,
   1.513 +					key->u.dsa.params.base.data,
   1.514 +					key->u.dsa.params.base.len);
   1.515 +    default:
   1.516 +	break;
   1.517 +    }
   1.518 +    return lg_invalidAttribute(attribute);
   1.519 +}
   1.520 +
   1.521 +static CK_RV
   1.522 +lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
   1.523 +				CK_ATTRIBUTE *attribute)
   1.524 +{
   1.525 +    unsigned char hash[SHA1_LENGTH];
   1.526 +    CK_KEY_TYPE keyType = CKK_DH;
   1.527 +
   1.528 +    switch (type) {
   1.529 +    case CKA_KEY_TYPE:
   1.530 +	return lg_ULongAttribute(attribute, type, keyType);
   1.531 +    case CKA_ID:
   1.532 +	SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
   1.533 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.534 +    case CKA_DERIVE:
   1.535 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.536 +    case CKA_ENCRYPT:
   1.537 +    case CKA_VERIFY:
   1.538 +    case CKA_VERIFY_RECOVER:
   1.539 +    case CKA_WRAP:
   1.540 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.541 +    case CKA_VALUE:
   1.542 +	return lg_CopyAttributeSigned(attribute,type,
   1.543 +					key->u.dh.publicValue.data,
   1.544 +					key->u.dh.publicValue.len);
   1.545 +    case CKA_PRIME:
   1.546 +	return lg_CopyAttributeSigned(attribute,type,key->u.dh.prime.data,
   1.547 +					key->u.dh.prime.len);
   1.548 +    case CKA_BASE:
   1.549 +	return lg_CopyAttributeSigned(attribute,type,key->u.dh.base.data,
   1.550 +					key->u.dh.base.len);
   1.551 +    default:
   1.552 +	break;
   1.553 +    }
   1.554 +    return lg_invalidAttribute(attribute);
   1.555 +}
   1.556 +
   1.557 +#ifndef NSS_DISABLE_ECC
   1.558 +static CK_RV
   1.559 +lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
   1.560 +				CK_ATTRIBUTE *attribute)
   1.561 +{
   1.562 +    unsigned char hash[SHA1_LENGTH];
   1.563 +    CK_KEY_TYPE keyType = CKK_EC;
   1.564 +
   1.565 +    switch (type) {
   1.566 +    case CKA_KEY_TYPE:
   1.567 +	return lg_ULongAttribute(attribute, type, keyType);
   1.568 +    case CKA_ID:
   1.569 +	SHA1_HashBuf(hash, key->u.ec.publicValue.data,
   1.570 +		     key->u.ec.publicValue.len);
   1.571 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.572 +    case CKA_DERIVE:
   1.573 +    case CKA_VERIFY:
   1.574 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.575 +    case CKA_ENCRYPT:
   1.576 +    case CKA_VERIFY_RECOVER:
   1.577 +    case CKA_WRAP:
   1.578 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.579 +    case CKA_EC_PARAMS:
   1.580 +	return lg_CopyAttributeSigned(attribute,type,
   1.581 +					key->u.ec.ecParams.DEREncoding.data,
   1.582 +					key->u.ec.ecParams.DEREncoding.len);
   1.583 +    case CKA_EC_POINT:
   1.584 +	if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) {
   1.585 +	    return lg_CopyAttributeSigned(attribute, type,
   1.586 +					key->u.ec.publicValue.data,
   1.587 +					key->u.ec.publicValue.len);
   1.588 +	} else {
   1.589 +	    SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, 
   1.590 +					&(key->u.ec.publicValue), 
   1.591 +					SEC_ASN1_GET(SEC_OctetStringTemplate));
   1.592 +	    CK_RV crv;
   1.593 +	    if (!pubValue) {
   1.594 +		return CKR_HOST_MEMORY;
   1.595 +	    }
   1.596 +	    crv = lg_CopyAttributeSigned(attribute, type,
   1.597 +					pubValue->data,
   1.598 +					pubValue->len);
   1.599 +	    SECITEM_FreeItem(pubValue, PR_TRUE);
   1.600 +	    return crv;
   1.601 +	}
   1.602 +    default:
   1.603 +	break;
   1.604 +    }
   1.605 +    return lg_invalidAttribute(attribute);
   1.606 +}
   1.607 +#endif /* NSS_DISABLE_ECC */
   1.608 +
   1.609 +
   1.610 +static CK_RV
   1.611 +lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1.612 +				CK_ATTRIBUTE *attribute)
   1.613 +{
   1.614 +    NSSLOWKEYPublicKey   *key;
   1.615 +    CK_RV crv;
   1.616 +    char *label;
   1.617 +
   1.618 +    switch (type) {
   1.619 +    case CKA_PRIVATE:
   1.620 +    case CKA_SENSITIVE:
   1.621 +    case CKA_ALWAYS_SENSITIVE:
   1.622 +    case CKA_NEVER_EXTRACTABLE:
   1.623 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.624 +    case CKA_MODIFIABLE:
   1.625 +    case CKA_EXTRACTABLE:
   1.626 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.627 +    case CKA_SUBJECT:
   1.628 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.629 +    case CKA_START_DATE:
   1.630 +    case CKA_END_DATE:
   1.631 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.632 +    case CKA_LABEL:
   1.633 +        label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
   1.634 +	if (label == NULL) {
   1.635 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.636 +	}
   1.637 +	crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
   1.638 +	PORT_Free(label);
   1.639 +	return crv;
   1.640 +    default:
   1.641 +	break;
   1.642 +    }
   1.643 +
   1.644 +    key = lg_GetPublicKey(obj);
   1.645 +    if (key == NULL) {
   1.646 +	if (type == CKA_ID) {
   1.647 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.648 +	}
   1.649 +	return CKR_OBJECT_HANDLE_INVALID;
   1.650 +    }
   1.651 +
   1.652 +    switch (key->keyType) {
   1.653 +    case NSSLOWKEYRSAKey:
   1.654 +	return lg_FindRSAPublicKeyAttribute(key,type,attribute);
   1.655 +    case NSSLOWKEYDSAKey:
   1.656 +	return lg_FindDSAPublicKeyAttribute(key,type,attribute);
   1.657 +    case NSSLOWKEYDHKey:
   1.658 +	return lg_FindDHPublicKeyAttribute(key,type,attribute);
   1.659 +#ifndef NSS_DISABLE_ECC
   1.660 +    case NSSLOWKEYECKey:
   1.661 +	return lg_FindECPublicKeyAttribute(key,type,attribute);
   1.662 +#endif /* NSS_DISABLE_ECC */
   1.663 +    default:
   1.664 +	break;
   1.665 +    }
   1.666 +
   1.667 +    return lg_invalidAttribute(attribute);
   1.668 +}
   1.669 +
   1.670 +static CK_RV
   1.671 +lg_FindSecretKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1.672 +				CK_ATTRIBUTE *attribute)
   1.673 +{
   1.674 +    NSSLOWKEYPrivateKey  *key;
   1.675 +    char *label;
   1.676 +    unsigned char *keyString;
   1.677 +    CK_RV crv;
   1.678 +    int keyTypeLen;
   1.679 +    CK_ULONG keyLen;
   1.680 +    CK_KEY_TYPE keyType;
   1.681 +    PRUint32 keyTypeStorage;
   1.682 +
   1.683 +    switch (type) {
   1.684 +    case CKA_PRIVATE:
   1.685 +    case CKA_SENSITIVE:
   1.686 +    case CKA_ALWAYS_SENSITIVE:
   1.687 +    case CKA_EXTRACTABLE:
   1.688 +    case CKA_DERIVE:
   1.689 +    case CKA_ENCRYPT:
   1.690 +    case CKA_DECRYPT:
   1.691 +    case CKA_SIGN:
   1.692 +    case CKA_VERIFY:
   1.693 +    case CKA_WRAP:
   1.694 +    case CKA_UNWRAP:
   1.695 +    case CKA_MODIFIABLE:
   1.696 +    case CKA_LOCAL:
   1.697 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.698 +    case CKA_NEVER_EXTRACTABLE:
   1.699 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.700 +    case CKA_START_DATE:
   1.701 +    case CKA_END_DATE:
   1.702 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.703 +    case CKA_LABEL:
   1.704 +        label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
   1.705 +	if (label == NULL) {
   1.706 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
   1.707 +	}
   1.708 +	crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
   1.709 +	PORT_Free(label);
   1.710 +	return crv;
   1.711 +    case CKA_ID:
   1.712 +	return lg_CopyAttribute(attribute,type,obj->dbKey.data,
   1.713 +						obj->dbKey.len);
   1.714 +    case CKA_KEY_TYPE:
   1.715 +    case CKA_VALUE_LEN:
   1.716 +    case CKA_VALUE:
   1.717 +	break;
   1.718 +    default:
   1.719 +	return lg_invalidAttribute(attribute);
   1.720 +    }
   1.721 +
   1.722 +    key = lg_GetPrivateKey(obj);
   1.723 +    if (key == NULL) {
   1.724 +	return CKR_OBJECT_HANDLE_INVALID;
   1.725 +    }
   1.726 +    switch (type) {
   1.727 +    case CKA_KEY_TYPE:
   1.728 +	/* handle legacy databases. In legacy databases key_type was stored
   1.729 +	 * in host order, with any leading zeros stripped off. Only key types
   1.730 +	 * under 0x1f (AES) were stored. We assume that any values which are
   1.731 +	 * either 1 byte long (big endian), or have byte[0] between 0 and 
   1.732 +	 * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
   1.733 +	 * values are assumed to be from the new database, which is always 4
   1.734 +	 * bytes in network order */
   1.735 +	keyType=0;
   1.736 +	keyString = key->u.rsa.coefficient.data;
   1.737 +	keyTypeLen = key->u.rsa.coefficient.len;
   1.738 +
   1.739 +
   1.740 +	/*
   1.741 + 	 * Because of various endian and word lengths The database may have
   1.742 +	 * stored the keyType value in one of the following formats:
   1.743 +	 *   (kt) <= 0x1f 
   1.744 +	 *                                   length data
   1.745 +	 * Big Endian,     pre-3.9, all lengths: 1  (kt)
   1.746 +	 * Little Endian,  pre-3.9, 32 bits:     4  (kt) 0  0  0
   1.747 +	 * Little Endian,  pre-3.9, 64 bits:     8  (kt) 0  0  0   0  0  0  0
   1.748 +	 * All platforms,      3.9, 32 bits:     4    0  0  0 (kt)
   1.749 +	 * Big Endian,         3.9, 64 bits:     8    0  0  0 (kt) 0  0  0  0
   1.750 +	 * Little  Endian,     3.9, 64 bits:     8    0  0  0  0   0  0  0 (kt)
   1.751 +	 * All platforms, >= 3.9.1, all lengths: 4   (a) k1 k2 k3
   1.752 +	 * where (a) is 0 or >= 0x80. currently (a) can only be 0.
   1.753 +	 */
   1.754 +	/*
   1.755 + 	 * this key was written on a 64 bit platform with a using NSS 3.9
   1.756 +	 * or earlier. Reduce the 64 bit possibilities above. When we are
   1.757 +	 * through, we will only have:
   1.758 +	 * 
   1.759 +	 * Big Endian,     pre-3.9, all lengths: 1  (kt)
   1.760 +	 * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
   1.761 +	 * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
   1.762 +	 * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
   1.763 +	 */
   1.764 +	if (keyTypeLen == 8) {
   1.765 +	    keyTypeStorage = *(PRUint32 *) keyString;
   1.766 +	    if (keyTypeStorage == 0) {
   1.767 +		keyString += sizeof(PRUint32);
   1.768 +	    }
   1.769 +	    keyTypeLen = 4;
   1.770 +	}
   1.771 +	/*
   1.772 +	 * Now Handle:
   1.773 +	 *
   1.774 +	 * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
   1.775 +	 * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
   1.776 +	 *
   1.777 +	 * NOTE: if  kt == 0 or ak1k2k3 == 0, the test fails and
   1.778 +	 * we handle it as:
   1.779 +	 *
   1.780 +	 * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
   1.781 +	 */
   1.782 +	if (keyTypeLen == sizeof(keyTypeStorage) &&
   1.783 +	     (((keyString[0] & 0x80) == 0x80) ||
   1.784 +		!((keyString[1] == 0) && (keyString[2] == 0)
   1.785 +	   				    && (keyString[3] == 0))) ) {
   1.786 +	    PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
   1.787 +	    keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage);
   1.788 +	} else {
   1.789 +	/*
   1.790 +	 * Now Handle:
   1.791 +	 *
   1.792 +	 * Big Endian,     pre-3.9, all lengths: 1  (kt)
   1.793 +	 * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
   1.794 +	 *  -- KeyType == 0 all other cases ---: 4    0  0  0  0
   1.795 +	 */
   1.796 +	    keyType = (CK_KEY_TYPE) keyString[0] ;
   1.797 +        }
   1.798 +	return lg_ULongAttribute(attribute, type, keyType);
   1.799 +    case CKA_VALUE:
   1.800 +	return lg_CopyPrivAttribute(attribute,type,key->u.rsa.privateExponent.data,
   1.801 +				key->u.rsa.privateExponent.len, obj->sdb);
   1.802 +    case CKA_VALUE_LEN:
   1.803 +	keyLen=key->u.rsa.privateExponent.len;
   1.804 +	return lg_ULongAttribute(attribute,type, keyLen);
   1.805 +    }
   1.806 +    return lg_invalidAttribute(attribute);
   1.807 +}
   1.808 +
   1.809 +static CK_RV
   1.810 +lg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
   1.811 +				CK_ATTRIBUTE *attribute, SDB *sdbpw)
   1.812 +{
   1.813 +    unsigned char hash[SHA1_LENGTH];
   1.814 +    CK_KEY_TYPE keyType = CKK_RSA;
   1.815 +
   1.816 +    switch (type) {
   1.817 +    case CKA_KEY_TYPE:
   1.818 +	return lg_ULongAttribute(attribute, type, keyType);
   1.819 +    case CKA_ID:
   1.820 +	SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len);
   1.821 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.822 +    case CKA_DERIVE:
   1.823 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.824 +    case CKA_DECRYPT:
   1.825 +    case CKA_SIGN:
   1.826 +    case CKA_SIGN_RECOVER:
   1.827 +    case CKA_UNWRAP:
   1.828 +	return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr);
   1.829 +    case CKA_MODULUS:
   1.830 +	return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data,
   1.831 +					key->u.rsa.modulus.len);
   1.832 +    case CKA_PUBLIC_EXPONENT:
   1.833 +	return lg_CopyAttributeSigned(attribute, type,
   1.834 +				key->u.rsa.publicExponent.data,
   1.835 +				key->u.rsa.publicExponent.len);
   1.836 +    case CKA_PRIVATE_EXPONENT:
   1.837 +	return lg_CopyPrivAttrSigned(attribute,type,
   1.838 +				key->u.rsa.privateExponent.data,
   1.839 +				key->u.rsa.privateExponent.len, sdbpw);
   1.840 +    case CKA_PRIME_1:
   1.841 +	return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime1.data,
   1.842 +				key->u.rsa.prime1.len, sdbpw);
   1.843 +    case CKA_PRIME_2:
   1.844 +	return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime2.data,
   1.845 +				key->u.rsa.prime2.len, sdbpw);
   1.846 +    case CKA_EXPONENT_1:
   1.847 +	return lg_CopyPrivAttrSigned(attribute, type, 
   1.848 +				key->u.rsa.exponent1.data,
   1.849 +				key->u.rsa.exponent1.len, sdbpw);
   1.850 +    case CKA_EXPONENT_2:
   1.851 +	return lg_CopyPrivAttrSigned(attribute, type, 
   1.852 +				key->u.rsa.exponent2.data,
   1.853 +				key->u.rsa.exponent2.len, sdbpw);
   1.854 +    case CKA_COEFFICIENT:
   1.855 +	return lg_CopyPrivAttrSigned(attribute, type, 
   1.856 +				key->u.rsa.coefficient.data,
   1.857 +				key->u.rsa.coefficient.len, sdbpw);
   1.858 +    default:
   1.859 +	break;
   1.860 +    }
   1.861 +    return lg_invalidAttribute(attribute);
   1.862 +}
   1.863 +
   1.864 +static CK_RV
   1.865 +lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
   1.866 +				CK_ATTRIBUTE *attribute, SDB *sdbpw)
   1.867 +{
   1.868 +    unsigned char hash[SHA1_LENGTH];
   1.869 +    CK_KEY_TYPE keyType = CKK_DSA;
   1.870 +
   1.871 +    switch (type) {
   1.872 +    case CKA_KEY_TYPE:
   1.873 +	return lg_ULongAttribute(attribute, type, keyType);
   1.874 +    case CKA_ID:
   1.875 +	SHA1_HashBuf(hash,key->u.dsa.publicValue.data,
   1.876 +			  key->u.dsa.publicValue.len);
   1.877 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.878 +    case CKA_DERIVE:
   1.879 +    case CKA_DECRYPT:
   1.880 +    case CKA_SIGN_RECOVER:
   1.881 +    case CKA_UNWRAP:
   1.882 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.883 +    case CKA_SIGN:
   1.884 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.885 +    case CKA_VALUE:
   1.886 +	return lg_CopyPrivAttrSigned(attribute, type,
   1.887 +				key->u.dsa.privateValue.data,
   1.888 +				key->u.dsa.privateValue.len, sdbpw);
   1.889 +    case CKA_PRIME:
   1.890 +	return lg_CopyAttributeSigned(attribute, type,
   1.891 +					key->u.dsa.params.prime.data,
   1.892 +					key->u.dsa.params.prime.len);
   1.893 +    case CKA_SUBPRIME:
   1.894 +	return lg_CopyAttributeSigned(attribute, type,
   1.895 +				key->u.dsa.params.subPrime.data,
   1.896 +				key->u.dsa.params.subPrime.len);
   1.897 +    case CKA_BASE:
   1.898 +	return lg_CopyAttributeSigned(attribute, type,
   1.899 +					key->u.dsa.params.base.data,
   1.900 +					key->u.dsa.params.base.len);
   1.901 +    case CKA_NETSCAPE_DB:
   1.902 +	return lg_CopyAttributeSigned(attribute, type,
   1.903 +					key->u.dsa.publicValue.data,
   1.904 +					key->u.dsa.publicValue.len);
   1.905 +    default:
   1.906 +	break;
   1.907 +    }
   1.908 +    return lg_invalidAttribute(attribute);
   1.909 +}
   1.910 +
   1.911 +static CK_RV
   1.912 +lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
   1.913 +				CK_ATTRIBUTE *attribute, SDB *sdbpw)
   1.914 +{
   1.915 +    unsigned char hash[SHA1_LENGTH];
   1.916 +    CK_KEY_TYPE keyType = CKK_DH;
   1.917 +
   1.918 +    switch (type) {
   1.919 +    case CKA_KEY_TYPE:
   1.920 +	return lg_ULongAttribute(attribute, type, keyType);
   1.921 +    case CKA_ID:
   1.922 +	SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len);
   1.923 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.924 +    case CKA_DERIVE:
   1.925 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.926 +    case CKA_DECRYPT:
   1.927 +    case CKA_SIGN:
   1.928 +    case CKA_SIGN_RECOVER:
   1.929 +    case CKA_UNWRAP:
   1.930 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.931 +    case CKA_VALUE:
   1.932 +	return lg_CopyPrivAttrSigned(attribute, type,
   1.933 +					key->u.dh.privateValue.data,
   1.934 +					key->u.dh.privateValue.len, sdbpw);
   1.935 +    case CKA_PRIME:
   1.936 +	return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data,
   1.937 +					key->u.dh.prime.len);
   1.938 +    case CKA_BASE:
   1.939 +	return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
   1.940 +					key->u.dh.base.len);
   1.941 +    case CKA_NETSCAPE_DB:
   1.942 +	return lg_CopyAttributeSigned(attribute, type,
   1.943 +					key->u.dh.publicValue.data,
   1.944 +					key->u.dh.publicValue.len);
   1.945 +    default:
   1.946 +	break;
   1.947 +    }
   1.948 +    return lg_invalidAttribute(attribute);
   1.949 +}
   1.950 +
   1.951 +#ifndef NSS_DISABLE_ECC
   1.952 +static CK_RV
   1.953 +lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
   1.954 +				CK_ATTRIBUTE *attribute, SDB *sdbpw)
   1.955 +{
   1.956 +    unsigned char hash[SHA1_LENGTH];
   1.957 +    CK_KEY_TYPE keyType = CKK_EC;
   1.958 +
   1.959 +    switch (type) {
   1.960 +    case CKA_KEY_TYPE:
   1.961 +	return lg_ULongAttribute(attribute, type, keyType);
   1.962 +    case CKA_ID:
   1.963 +	SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len);
   1.964 +	return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH);
   1.965 +    case CKA_DERIVE:
   1.966 +    case CKA_SIGN:
   1.967 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
   1.968 +    case CKA_DECRYPT:
   1.969 +    case CKA_SIGN_RECOVER:
   1.970 +    case CKA_UNWRAP:
   1.971 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
   1.972 +    case CKA_VALUE:
   1.973 +	return lg_CopyPrivAttrSigned(attribute, type,
   1.974 +					key->u.ec.privateValue.data,
   1.975 +					key->u.ec.privateValue.len, sdbpw);
   1.976 +    case CKA_EC_PARAMS:
   1.977 +	return lg_CopyAttributeSigned(attribute, type,
   1.978 +					key->u.ec.ecParams.DEREncoding.data,
   1.979 +					key->u.ec.ecParams.DEREncoding.len);
   1.980 +    case CKA_NETSCAPE_DB:
   1.981 +	return lg_CopyAttributeSigned(attribute, type,
   1.982 +					key->u.ec.publicValue.data,
   1.983 +					key->u.ec.publicValue.len);
   1.984 +    default:
   1.985 +	break;
   1.986 +    }
   1.987 +    return lg_invalidAttribute(attribute);
   1.988 +}
   1.989 +#endif /* NSS_DISABLE_ECC */
   1.990 +
   1.991 +static CK_RV
   1.992 +lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1.993 +				CK_ATTRIBUTE *attribute)
   1.994 +{
   1.995 +    NSSLOWKEYPrivateKey  *key;
   1.996 +    char *label;
   1.997 +    CK_RV crv;
   1.998 +
   1.999 +    switch (type) {
  1.1000 +    case CKA_PRIVATE:
  1.1001 +    case CKA_SENSITIVE:
  1.1002 +    case CKA_ALWAYS_SENSITIVE:
  1.1003 +    case CKA_EXTRACTABLE:
  1.1004 +    case CKA_MODIFIABLE:
  1.1005 +    case CKA_LOCAL:
  1.1006 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
  1.1007 +    case CKA_NEVER_EXTRACTABLE:
  1.1008 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1009 +    case CKA_SUBJECT:
  1.1010 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1011 +    case CKA_START_DATE:
  1.1012 +    case CKA_END_DATE:
  1.1013 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1014 +    case CKA_LABEL:
  1.1015 +        label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
  1.1016 +	if (label == NULL) {
  1.1017 +	   return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1018 +	}
  1.1019 +	crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label));
  1.1020 +	PORT_Free(label);
  1.1021 +	return crv;
  1.1022 +    default:
  1.1023 +	break;
  1.1024 +    }
  1.1025 +    key = lg_GetPrivateKey(obj);
  1.1026 +    if (key == NULL) {
  1.1027 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1028 +    }
  1.1029 +    switch (key->keyType) {
  1.1030 +    case NSSLOWKEYRSAKey:
  1.1031 +	return lg_FindRSAPrivateKeyAttribute(key,type,attribute,obj->sdb);
  1.1032 +    case NSSLOWKEYDSAKey:
  1.1033 +	return lg_FindDSAPrivateKeyAttribute(key,type,attribute,obj->sdb);
  1.1034 +    case NSSLOWKEYDHKey:
  1.1035 +	return lg_FindDHPrivateKeyAttribute(key,type,attribute,obj->sdb);
  1.1036 +#ifndef NSS_DISABLE_ECC
  1.1037 +    case NSSLOWKEYECKey:
  1.1038 +	return lg_FindECPrivateKeyAttribute(key,type,attribute,obj->sdb);
  1.1039 +#endif /* NSS_DISABLE_ECC */
  1.1040 +    default:
  1.1041 +	break;
  1.1042 +    }
  1.1043 +
  1.1044 +    return lg_invalidAttribute(attribute);
  1.1045 +}
  1.1046 +
  1.1047 +static CK_RV
  1.1048 +lg_FindSMIMEAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
  1.1049 +				CK_ATTRIBUTE *attribute)
  1.1050 +{
  1.1051 +    certDBEntrySMime *entry;
  1.1052 +    switch (type) {
  1.1053 +    case CKA_PRIVATE:
  1.1054 +    case CKA_MODIFIABLE:
  1.1055 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1056 +    case CKA_NSS_EMAIL:
  1.1057 +	return lg_CopyAttribute(attribute,type,obj->dbKey.data,
  1.1058 +						obj->dbKey.len-1);
  1.1059 +    case CKA_NSS_SMIME_TIMESTAMP:
  1.1060 +    case CKA_SUBJECT:
  1.1061 +    case CKA_VALUE:
  1.1062 +	break;
  1.1063 +    default:
  1.1064 +	return lg_invalidAttribute(attribute);
  1.1065 +    }
  1.1066 +    entry = lg_getSMime(obj);
  1.1067 +    if (entry == NULL) {
  1.1068 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1069 +    }
  1.1070 +    switch (type) {
  1.1071 +    case CKA_NSS_SMIME_TIMESTAMP:
  1.1072 +	return lg_CopyAttribute(attribute,type,entry->optionsDate.data,
  1.1073 +					entry->optionsDate.len);
  1.1074 +    case CKA_SUBJECT:
  1.1075 +	return lg_CopyAttribute(attribute,type,entry->subjectName.data,
  1.1076 +					entry->subjectName.len);
  1.1077 +    case CKA_VALUE:
  1.1078 +	return lg_CopyAttribute(attribute,type,entry->smimeOptions.data,
  1.1079 +					entry->smimeOptions.len);
  1.1080 +    default:
  1.1081 +	break;
  1.1082 +    }
  1.1083 +    return lg_invalidAttribute(attribute);
  1.1084 +}
  1.1085 +
  1.1086 +static CK_RV
  1.1087 +lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
  1.1088 +				CK_ATTRIBUTE *attribute)
  1.1089 +{
  1.1090 +    NSSLOWCERTTrust *trust;
  1.1091 +    NSSLOWCERTCertDBHandle *certHandle;
  1.1092 +    NSSLOWCERTCertificate *cert;
  1.1093 +    unsigned char hash[SHA1_LENGTH];
  1.1094 +    unsigned int trustFlags;
  1.1095 +    CK_RV crv;
  1.1096 +
  1.1097 +    switch (type) {
  1.1098 +    case CKA_PRIVATE:
  1.1099 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1100 +    case CKA_MODIFIABLE:
  1.1101 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
  1.1102 +    case CKA_CERT_SHA1_HASH:
  1.1103 +    case CKA_CERT_MD5_HASH:
  1.1104 +    case CKA_TRUST_CLIENT_AUTH:
  1.1105 +    case CKA_TRUST_SERVER_AUTH:
  1.1106 +    case CKA_TRUST_EMAIL_PROTECTION:
  1.1107 +    case CKA_TRUST_CODE_SIGNING:
  1.1108 +    case CKA_TRUST_STEP_UP_APPROVED:
  1.1109 +    case CKA_ISSUER:
  1.1110 +    case CKA_SERIAL_NUMBER:
  1.1111 +	break;
  1.1112 +    default:
  1.1113 +        return lg_invalidAttribute(attribute);
  1.1114 +    }
  1.1115 +    certHandle = lg_getCertDB(obj->sdb);
  1.1116 +    if (!certHandle) {
  1.1117 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1118 +    }
  1.1119 +    trust = lg_getTrust(obj, certHandle);
  1.1120 +    if (trust == NULL) {
  1.1121 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1122 +    }
  1.1123 +    switch (type) {
  1.1124 +    case CKA_CERT_SHA1_HASH:
  1.1125 +	SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len);
  1.1126 +	return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
  1.1127 +    case CKA_CERT_MD5_HASH:
  1.1128 +	MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len);
  1.1129 +	return lg_CopyAttribute(attribute, type, hash, MD5_LENGTH);
  1.1130 +    case CKA_TRUST_CLIENT_AUTH:
  1.1131 +	trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ?
  1.1132 +		trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ;
  1.1133 +	goto trust;
  1.1134 +    case CKA_TRUST_SERVER_AUTH:
  1.1135 +	trustFlags = trust->trust->sslFlags;
  1.1136 +	goto trust;
  1.1137 +    case CKA_TRUST_EMAIL_PROTECTION:
  1.1138 +	trustFlags = trust->trust->emailFlags;
  1.1139 +	goto trust;
  1.1140 +    case CKA_TRUST_CODE_SIGNING:
  1.1141 +	trustFlags = trust->trust->objectSigningFlags;
  1.1142 +trust:
  1.1143 +	if (trustFlags & CERTDB_TRUSTED_CA ) {
  1.1144 +	    return lg_ULongAttribute(attribute, type,
  1.1145 +				     CKT_NSS_TRUSTED_DELEGATOR);
  1.1146 +	}
  1.1147 +	if (trustFlags & CERTDB_TRUSTED) {
  1.1148 +	    return lg_ULongAttribute(attribute, type, CKT_NSS_TRUSTED);
  1.1149 +	}
  1.1150 +	if (trustFlags & CERTDB_MUST_VERIFY) {
  1.1151 +	    return lg_ULongAttribute(attribute, type, 
  1.1152 +				     CKT_NSS_MUST_VERIFY_TRUST);
  1.1153 +	}
  1.1154 +	if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
  1.1155 +	    return lg_ULongAttribute(attribute, type, CKT_NSS_TRUST_UNKNOWN);
  1.1156 +	}
  1.1157 +	if (trustFlags & CERTDB_VALID_CA) {
  1.1158 +	    return lg_ULongAttribute(attribute, type, CKT_NSS_VALID_DELEGATOR);
  1.1159 +	}
  1.1160 +	if (trustFlags & CERTDB_TERMINAL_RECORD) {
  1.1161 +	    return lg_ULongAttribute(attribute, type, CKT_NSS_NOT_TRUSTED);
  1.1162 +	}
  1.1163 +	return lg_ULongAttribute(attribute, type, CKT_NSS_TRUST_UNKNOWN);
  1.1164 +    case CKA_TRUST_STEP_UP_APPROVED:
  1.1165 +	if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
  1.1166 +	    return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
  1.1167 +	} else {
  1.1168 +	    return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1169 +	}
  1.1170 +    default:
  1.1171 +	break;
  1.1172 +    }
  1.1173 +
  1.1174 +
  1.1175 +    switch (type) {
  1.1176 +    case CKA_ISSUER:
  1.1177 +	cert = lg_getCert(obj, certHandle);
  1.1178 +	if (cert == NULL) break;
  1.1179 +	crv = lg_CopyAttribute(attribute,type,cert->derIssuer.data,
  1.1180 +						cert->derIssuer.len);
  1.1181 +	break;
  1.1182 +    case CKA_SERIAL_NUMBER:
  1.1183 +	cert = lg_getCert(obj, certHandle);
  1.1184 +	if (cert == NULL) break;
  1.1185 +	crv =  lg_CopyAttribute(attribute,type,cert->derSN.data,
  1.1186 +						cert->derSN.len);
  1.1187 +	break;
  1.1188 +    default:
  1.1189 +	cert = NULL;
  1.1190 +	break;
  1.1191 +    }
  1.1192 +    if (cert) {
  1.1193 +	nsslowcert_DestroyCertificate(cert);
  1.1194 +	return crv;
  1.1195 +    }
  1.1196 +    return lg_invalidAttribute(attribute);
  1.1197 +}
  1.1198 +
  1.1199 +static CK_RV
  1.1200 +lg_FindCrlAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
  1.1201 +				CK_ATTRIBUTE *attribute)
  1.1202 +{
  1.1203 +    certDBEntryRevocation *crl;
  1.1204 +
  1.1205 +    switch (type) {
  1.1206 +    case CKA_PRIVATE:
  1.1207 +    case CKA_MODIFIABLE:
  1.1208 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1209 +    case CKA_NSS_KRL:
  1.1210 +	return ((obj->handle == LG_TOKEN_KRL_HANDLE) 
  1.1211 +		? LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr)
  1.1212 +		: LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr));
  1.1213 +    case CKA_SUBJECT:
  1.1214 +	return lg_CopyAttribute(attribute,type,obj->dbKey.data,
  1.1215 +						obj->dbKey.len);
  1.1216 +    case CKA_NSS_URL:
  1.1217 +    case CKA_VALUE:
  1.1218 +	break;
  1.1219 +    default:
  1.1220 +	return lg_invalidAttribute(attribute);
  1.1221 +    }
  1.1222 +    crl =  lg_getCrl(obj);
  1.1223 +    if (!crl) {
  1.1224 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1225 +    }
  1.1226 +    switch (type) {
  1.1227 +    case CKA_NSS_URL:
  1.1228 +	if (crl->url == NULL) {
  1.1229 +	    return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1230 +	}
  1.1231 +	return lg_CopyAttribute(attribute, type, crl->url, 
  1.1232 +					PORT_Strlen(crl->url)+1);
  1.1233 +    case CKA_VALUE:
  1.1234 +	return lg_CopyAttribute(attribute, type, crl->derCrl.data, 
  1.1235 +						crl->derCrl.len);
  1.1236 +    default:
  1.1237 +	break;
  1.1238 +    }
  1.1239 +    return lg_invalidAttribute(attribute);
  1.1240 +}
  1.1241 +
  1.1242 +static CK_RV
  1.1243 +lg_FindCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
  1.1244 +				CK_ATTRIBUTE *attribute)
  1.1245 +{
  1.1246 +    NSSLOWCERTCertificate  *cert;
  1.1247 +    NSSLOWCERTCertDBHandle *certHandle;
  1.1248 +    NSSLOWKEYPublicKey     *pubKey;
  1.1249 +    unsigned char hash[SHA1_LENGTH];
  1.1250 +    SECItem *item;
  1.1251 +
  1.1252 +    switch (type) {
  1.1253 +    case CKA_PRIVATE:
  1.1254 +	return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr);
  1.1255 +    case CKA_MODIFIABLE:
  1.1256 +	return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr);
  1.1257 +    case CKA_CERTIFICATE_TYPE:
  1.1258 +        /* hardcoding X.509 into here */
  1.1259 +        return lg_ULongAttribute(attribute, type, CKC_X_509);
  1.1260 +    case CKA_VALUE:
  1.1261 +    case CKA_ID:
  1.1262 +    case CKA_LABEL:
  1.1263 +    case CKA_SUBJECT:
  1.1264 +    case CKA_ISSUER:
  1.1265 +    case CKA_SERIAL_NUMBER:
  1.1266 +    case CKA_NSS_EMAIL:
  1.1267 +	break;
  1.1268 +    default:
  1.1269 +	return lg_invalidAttribute(attribute);
  1.1270 +    }
  1.1271 +
  1.1272 +    certHandle = lg_getCertDB(obj->sdb);
  1.1273 +    if (certHandle == NULL) {
  1.1274 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1275 +    }
  1.1276 +
  1.1277 +    cert = lg_getCert(obj, certHandle);
  1.1278 +    if (cert == NULL) {
  1.1279 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1280 +    }
  1.1281 +    switch (type) {
  1.1282 +    case CKA_VALUE:
  1.1283 +	return lg_CopyAttribute(attribute,type,cert->derCert.data,
  1.1284 +						cert->derCert.len);
  1.1285 +    case CKA_ID:
  1.1286 +	if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
  1.1287 +		((cert->trust->emailFlags & CERTDB_USER) == 0) &&
  1.1288 +		((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
  1.1289 +	    return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1290 +	}
  1.1291 +	pubKey = nsslowcert_ExtractPublicKey(cert);
  1.1292 +	if (pubKey == NULL) break;
  1.1293 +	item = lg_GetPubItem(pubKey);
  1.1294 +	if (item == NULL) {
  1.1295 +	    lg_nsslowkey_DestroyPublicKey(pubKey);
  1.1296 +	    break;
  1.1297 +	}
  1.1298 +	SHA1_HashBuf(hash,item->data,item->len);
  1.1299 +	/* item is imbedded in pubKey, just free the key */
  1.1300 +	lg_nsslowkey_DestroyPublicKey(pubKey);
  1.1301 +	return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
  1.1302 +    case CKA_LABEL:
  1.1303 +	return cert->nickname 
  1.1304 +	       ? lg_CopyAttribute(attribute, type, cert->nickname,
  1.1305 +				        PORT_Strlen(cert->nickname))
  1.1306 +	       : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1307 +    case CKA_SUBJECT:
  1.1308 +	return lg_CopyAttribute(attribute,type,cert->derSubject.data,
  1.1309 +						cert->derSubject.len);
  1.1310 +    case CKA_ISSUER:
  1.1311 +	return lg_CopyAttribute(attribute,type,cert->derIssuer.data,
  1.1312 +						cert->derIssuer.len);
  1.1313 +    case CKA_SERIAL_NUMBER:
  1.1314 +	return lg_CopyAttribute(attribute,type,cert->derSN.data,
  1.1315 +						cert->derSN.len);
  1.1316 +    case CKA_NSS_EMAIL:
  1.1317 +	return (cert->emailAddr && cert->emailAddr[0])
  1.1318 +	    ? lg_CopyAttribute(attribute, type, cert->emailAddr,
  1.1319 +	                             PORT_Strlen(cert->emailAddr))
  1.1320 +	    : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1321 +    default:
  1.1322 +	break;
  1.1323 +    }
  1.1324 +    return lg_invalidAttribute(attribute);
  1.1325 +}
  1.1326 +
  1.1327 +CK_RV
  1.1328 +lg_GetSingleAttribute(LGObjectCache *obj, CK_ATTRIBUTE *attribute)
  1.1329 +{
  1.1330 +    /* handle the common ones */
  1.1331 +    CK_ATTRIBUTE_TYPE type = attribute->type;
  1.1332 +    switch (type) {
  1.1333 +    case CKA_CLASS:
  1.1334 +	return lg_ULongAttribute(attribute,type,obj->objclass);
  1.1335 +    case CKA_TOKEN:
  1.1336 +	return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr);
  1.1337 +    case CKA_LABEL:
  1.1338 +	if (  (obj->objclass == CKO_CERTIFICATE) 
  1.1339 +	   || (obj->objclass == CKO_PRIVATE_KEY)
  1.1340 +	   || (obj->objclass == CKO_PUBLIC_KEY)
  1.1341 +	   || (obj->objclass == CKO_SECRET_KEY)) {
  1.1342 +	    break;
  1.1343 +	}
  1.1344 +	return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr);
  1.1345 +    default:
  1.1346 +	break;
  1.1347 +    }
  1.1348 +    switch (obj->objclass) {
  1.1349 +    case CKO_CERTIFICATE:
  1.1350 +	return lg_FindCertAttribute(obj,type,attribute);
  1.1351 +    case CKO_NSS_CRL:
  1.1352 +	return lg_FindCrlAttribute(obj,type,attribute);
  1.1353 +    case CKO_NSS_TRUST:
  1.1354 +	return lg_FindTrustAttribute(obj,type,attribute);
  1.1355 +    case CKO_NSS_SMIME:
  1.1356 +	return lg_FindSMIMEAttribute(obj,type,attribute);
  1.1357 +    case CKO_PUBLIC_KEY:
  1.1358 +	return lg_FindPublicKeyAttribute(obj,type,attribute);
  1.1359 +    case CKO_PRIVATE_KEY:
  1.1360 +	return lg_FindPrivateKeyAttribute(obj,type,attribute);
  1.1361 +    case CKO_SECRET_KEY:
  1.1362 +	return lg_FindSecretKeyAttribute(obj,type,attribute);
  1.1363 +    default:
  1.1364 +	break;
  1.1365 +    }
  1.1366 +    return lg_invalidAttribute(attribute);
  1.1367 +} 
  1.1368 +
  1.1369 +/*
  1.1370 + * Fill in the attribute template based on the data in the database.
  1.1371 + */    
  1.1372 +CK_RV
  1.1373 +lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *templ, 
  1.1374 +		CK_ULONG count)
  1.1375 +{
  1.1376 +    LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
  1.1377 +    CK_RV crv, crvCollect = CKR_OK;
  1.1378 +    unsigned int i;
  1.1379 +
  1.1380 +    if (obj == NULL) {
  1.1381 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1382 +    }
  1.1383 +
  1.1384 +    for (i=0; i < count; i++) {
  1.1385 +	crv = lg_GetSingleAttribute(obj, &templ[i]);
  1.1386 +	if (crvCollect == CKR_OK) crvCollect = crv;
  1.1387 +    }
  1.1388 +
  1.1389 +    lg_DestroyObjectCache(obj);
  1.1390 +    return crvCollect;
  1.1391 +}
  1.1392 +
  1.1393 +PRBool
  1.1394 +lg_cmpAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attribute)
  1.1395 +{
  1.1396 +    unsigned char buf[LG_BUF_SPACE];
  1.1397 +    CK_ATTRIBUTE testAttr;
  1.1398 +    unsigned char *tempBuf = NULL;
  1.1399 +    PRBool match = PR_TRUE;
  1.1400 +    CK_RV crv;
  1.1401 +
  1.1402 +    /* we're going to compare 'attribute' with the actual attribute from
  1.1403 +     * the object. We'll use the length of 'attribute' to decide how much
  1.1404 +     * space we need to read the test attribute. If 'attribute' doesn't give
  1.1405 +     * enough space, then we know the values don't match and that will
  1.1406 +     * show up as ckr != CKR_OK */
  1.1407 +    testAttr = *attribute;
  1.1408 +    testAttr.pValue = buf;
  1.1409 +
  1.1410 +    /* if we don't have enough space, malloc it */
  1.1411 +    if (attribute->ulValueLen > LG_BUF_SPACE) {
  1.1412 +	tempBuf = PORT_Alloc(attribute->ulValueLen);
  1.1413 +	if (!tempBuf) {
  1.1414 +	    return PR_FALSE;
  1.1415 +	}
  1.1416 +	testAttr.pValue = tempBuf;
  1.1417 +    }
  1.1418 +
  1.1419 +    /* get the attribute */
  1.1420 +    crv = lg_GetSingleAttribute(obj, &testAttr);
  1.1421 +    /* if the attribute was read OK, compare it */
  1.1422 +    if ((crv != CKR_OK) || (attribute->ulValueLen != testAttr.ulValueLen) ||
  1.1423 +     (PORT_Memcmp(attribute->pValue,testAttr.pValue,testAttr.ulValueLen)!= 0)){
  1.1424 +	/* something didn't match, this isn't the object we are looking for */
  1.1425 +	match = PR_FALSE;
  1.1426 +    }
  1.1427 +    /* free the buffer we may have allocated */
  1.1428 +    if (tempBuf) {
  1.1429 +	PORT_Free(tempBuf);
  1.1430 +    }
  1.1431 +    return match;
  1.1432 +}
  1.1433 +
  1.1434 +PRBool
  1.1435 +lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
  1.1436 +		const CK_ATTRIBUTE *templ, CK_ULONG count)
  1.1437 +{
  1.1438 +    PRBool match = PR_TRUE;
  1.1439 +    LGObjectCache *obj = lg_NewObjectCache(sdb, dbKey, class);
  1.1440 +    unsigned int i;
  1.1441 +
  1.1442 +    if (obj == NULL) {
  1.1443 +	return PR_FALSE;
  1.1444 +    }
  1.1445 +
  1.1446 +    for (i=0; i < count; i++) {
  1.1447 +	match = lg_cmpAttribute(obj, &templ[i]);
  1.1448 +	if (!match) {
  1.1449 +	   break;
  1.1450 +	}
  1.1451 +    }
  1.1452 +
  1.1453 +    /* done looking, free up our cache */
  1.1454 +    lg_DestroyObjectCache(obj);
  1.1455 +
  1.1456 +    /* if we get through the whole list without finding a mismatched attribute,
  1.1457 +     * then this object fits the criteria we are matching */
  1.1458 +    return match;
  1.1459 +}
  1.1460 +
  1.1461 +static CK_RV
  1.1462 +lg_SetCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 
  1.1463 +					const void *value, unsigned int len)
  1.1464 +{
  1.1465 +    NSSLOWCERTCertificate  *cert;
  1.1466 +    NSSLOWCERTCertDBHandle *certHandle;
  1.1467 +    char *nickname = NULL;
  1.1468 +    SECStatus rv;
  1.1469 +    CK_RV crv;
  1.1470 +
  1.1471 +    /* we can't change  the EMAIL values, but let the
  1.1472 +     * upper layers feel better about the fact we tried to set these */
  1.1473 +    if (type == CKA_NSS_EMAIL) {
  1.1474 +	return CKR_OK;
  1.1475 +    }
  1.1476 +
  1.1477 +    certHandle = lg_getCertDB(obj->sdb);
  1.1478 +    if (certHandle == NULL) {
  1.1479 +	crv = CKR_TOKEN_WRITE_PROTECTED;
  1.1480 +	goto done;
  1.1481 +    }
  1.1482 +
  1.1483 +    if ((type != CKA_LABEL)  && (type != CKA_ID)) {
  1.1484 +	crv = CKR_ATTRIBUTE_READ_ONLY;
  1.1485 +	goto done;
  1.1486 +    }
  1.1487 +
  1.1488 +    cert = lg_getCert(obj, certHandle);
  1.1489 +    if (cert == NULL) {
  1.1490 +	crv = CKR_OBJECT_HANDLE_INVALID;
  1.1491 +	goto done;
  1.1492 +    }
  1.1493 +
  1.1494 +    /* if the app is trying to set CKA_ID, it's probably because it just
  1.1495 +     * imported the key. Look to see if we need to set the CERTDB_USER bits.
  1.1496 +     */
  1.1497 +    if (type == CKA_ID) {
  1.1498 +	if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
  1.1499 +		((cert->trust->emailFlags & CERTDB_USER) == 0) &&
  1.1500 +		((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
  1.1501 +	    NSSLOWKEYDBHandle      *keyHandle;
  1.1502 +
  1.1503 +	    keyHandle = lg_getKeyDB(obj->sdb);
  1.1504 +	    if (keyHandle) {
  1.1505 +		if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
  1.1506 +		    NSSLOWCERTCertTrust trust = *cert->trust;
  1.1507 +		    trust.sslFlags |= CERTDB_USER;
  1.1508 +		    trust.emailFlags |= CERTDB_USER;
  1.1509 +		    trust.objectSigningFlags |= CERTDB_USER;
  1.1510 +		    nsslowcert_ChangeCertTrust(certHandle,cert,&trust);
  1.1511 +		}
  1.1512 +	    }
  1.1513 +	}
  1.1514 +	crv = CKR_OK;
  1.1515 +	goto done;
  1.1516 +    }
  1.1517 +
  1.1518 +    /* must be CKA_LABEL */
  1.1519 +    if (value != NULL) {
  1.1520 +	nickname = PORT_ZAlloc(len+1);
  1.1521 +	if (nickname == NULL) {
  1.1522 +	    crv = CKR_HOST_MEMORY;
  1.1523 +	    goto done;
  1.1524 +	}
  1.1525 +	PORT_Memcpy(nickname,value,len);
  1.1526 +	nickname[len] = 0;
  1.1527 +    }
  1.1528 +    rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
  1.1529 +    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  1.1530 +
  1.1531 +done:
  1.1532 +    if (nickname) {
  1.1533 +	PORT_Free(nickname);
  1.1534 +    }
  1.1535 +    return crv;
  1.1536 +}
  1.1537 +
  1.1538 +static CK_RV
  1.1539 +lg_SetPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 
  1.1540 +			const void *value, unsigned int len, 
  1.1541 +			PRBool *writePrivate)
  1.1542 +{
  1.1543 +    NSSLOWKEYPrivateKey *privKey;
  1.1544 +    NSSLOWKEYDBHandle   *keyHandle;
  1.1545 +    char *nickname = NULL;
  1.1546 +    SECStatus rv;
  1.1547 +    CK_RV crv;
  1.1548 +
  1.1549 +    /* we can't change the ID and we don't store the subject, but let the
  1.1550 +     * upper layers feel better about the fact we tried to set these */
  1.1551 +    if ((type == CKA_ID) || (type == CKA_SUBJECT) ||
  1.1552 +	(type == CKA_LOCAL) || (type == CKA_NEVER_EXTRACTABLE) ||
  1.1553 +	(type == CKA_ALWAYS_SENSITIVE)) {
  1.1554 +	return CKR_OK;
  1.1555 +    }
  1.1556 +
  1.1557 +    keyHandle = lg_getKeyDB(obj->sdb);
  1.1558 +    if (keyHandle == NULL) {
  1.1559 +	crv = CKR_TOKEN_WRITE_PROTECTED;
  1.1560 +	goto done;
  1.1561 +    }
  1.1562 +
  1.1563 +    privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
  1.1564 +    if (privKey == NULL) {
  1.1565 +	crv = CKR_OBJECT_HANDLE_INVALID;
  1.1566 +	goto done;
  1.1567 +    }
  1.1568 +
  1.1569 +    crv = CKR_ATTRIBUTE_READ_ONLY;
  1.1570 +    switch(type) {
  1.1571 +    case CKA_LABEL:
  1.1572 +	if (value != NULL) {
  1.1573 +	    nickname = PORT_ZAlloc(len+1);
  1.1574 +	    if (nickname == NULL) {
  1.1575 +		crv = CKR_HOST_MEMORY;
  1.1576 +		goto done;
  1.1577 +	    }
  1.1578 +	    PORT_Memcpy(nickname,value,len);
  1.1579 +	    nickname[len] = 0;
  1.1580 +	}
  1.1581 +	rv = nsslowkey_UpdateNickname(keyHandle, privKey, &obj->dbKey, 
  1.1582 +					nickname, obj->sdb);
  1.1583 +	crv = (rv == SECSuccess) ? CKR_OK :  CKR_DEVICE_ERROR;
  1.1584 +	break;
  1.1585 +    case CKA_UNWRAP:
  1.1586 +    case CKA_SIGN:
  1.1587 +    case CKA_DERIVE:
  1.1588 +    case CKA_SIGN_RECOVER:
  1.1589 +    case CKA_DECRYPT:
  1.1590 +	/* ignore attempts to change restrict these.
  1.1591 +	 * legacyDB ignore these flags and always presents all of them 
  1.1592 +	 * that are valid as true. 
  1.1593 +	 * NOTE: We only get here if the current value and the new value do
  1.1594 +	 * not match. */
  1.1595 +	if (*(char *)value == 0) {
  1.1596 +	    crv = CKR_OK;
  1.1597 +	}
  1.1598 +	break;
  1.1599 +    case CKA_VALUE:
  1.1600 +    case CKA_PRIVATE_EXPONENT:
  1.1601 +    case CKA_PRIME_1:
  1.1602 +    case CKA_PRIME_2:
  1.1603 +    case CKA_EXPONENT_1:
  1.1604 +    case CKA_EXPONENT_2:
  1.1605 +    case CKA_COEFFICIENT:
  1.1606 +	/* We aren't really changing these values, we are just triggering
  1.1607 +	 * the database to update it's entry */
  1.1608 +	*writePrivate = PR_TRUE;
  1.1609 +	crv = CKR_OK;
  1.1610 +	break;
  1.1611 +    default:
  1.1612 +	crv = CKR_ATTRIBUTE_READ_ONLY;
  1.1613 +	break;
  1.1614 +    }
  1.1615 +done:
  1.1616 +    if (nickname) {
  1.1617 +	PORT_Free(nickname);
  1.1618 +    }
  1.1619 +    return crv;
  1.1620 +}
  1.1621 +
  1.1622 +static CK_RV
  1.1623 +lg_SetPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, 
  1.1624 +			const void *value, unsigned int len, 
  1.1625 +			PRBool *writePrivate)
  1.1626 +{
  1.1627 +    /* we can't change the ID and we don't store the subject, but let the
  1.1628 +     * upper layers feel better about the fact we tried to set these */
  1.1629 +    if ((type == CKA_ID) || (type == CKA_SUBJECT) || (type == CKA_LABEL)) {
  1.1630 +	return CKR_OK;
  1.1631 +    }
  1.1632 +    return  CKR_ATTRIBUTE_READ_ONLY;
  1.1633 +}
  1.1634 +
  1.1635 +static CK_RV
  1.1636 +lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr)
  1.1637 +{
  1.1638 +    unsigned int flags;
  1.1639 +    CK_TRUST  trust;
  1.1640 +    NSSLOWCERTCertificate  *cert;
  1.1641 +    NSSLOWCERTCertDBHandle *certHandle;
  1.1642 +    NSSLOWCERTCertTrust    dbTrust;
  1.1643 +    SECStatus rv;
  1.1644 +    CK_RV crv;
  1.1645 +
  1.1646 +    if (attr->type == CKA_LABEL) {
  1.1647 +	return CKR_OK;
  1.1648 +    }
  1.1649 +
  1.1650 +    crv = lg_GetULongAttribute(attr->type, attr, 1, &trust);
  1.1651 +    if (crv != CKR_OK) {
  1.1652 +	return crv;
  1.1653 +    }
  1.1654 +    flags = lg_MapTrust(trust, (PRBool) (attr->type == CKA_TRUST_CLIENT_AUTH));
  1.1655 +
  1.1656 +    certHandle = lg_getCertDB(obj->sdb);
  1.1657 +
  1.1658 +    if (certHandle == NULL) {
  1.1659 +	crv = CKR_TOKEN_WRITE_PROTECTED;
  1.1660 +	goto done;
  1.1661 +    }
  1.1662 +
  1.1663 +    cert = lg_getCert(obj, certHandle);
  1.1664 +    if (cert == NULL) {
  1.1665 +	crv = CKR_OBJECT_HANDLE_INVALID;
  1.1666 +	goto done;
  1.1667 +    }
  1.1668 +    dbTrust = *cert->trust;
  1.1669 +
  1.1670 +    switch (attr->type) {
  1.1671 +    case CKA_TRUST_EMAIL_PROTECTION:
  1.1672 +	dbTrust.emailFlags = flags |
  1.1673 +		(cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
  1.1674 +	break;
  1.1675 +    case CKA_TRUST_CODE_SIGNING:
  1.1676 +	dbTrust.objectSigningFlags = flags |
  1.1677 +		(cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
  1.1678 +	break;
  1.1679 +    case CKA_TRUST_CLIENT_AUTH:
  1.1680 +	dbTrust.sslFlags = flags | (cert->trust->sslFlags & 
  1.1681 +				(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA));
  1.1682 +	break;
  1.1683 +    case CKA_TRUST_SERVER_AUTH:
  1.1684 +	dbTrust.sslFlags = flags | (cert->trust->sslFlags & 
  1.1685 +			(CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA));
  1.1686 +	break;
  1.1687 +    default:
  1.1688 +	crv = CKR_ATTRIBUTE_READ_ONLY;
  1.1689 +	goto done;
  1.1690 +    }
  1.1691 +
  1.1692 +    rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
  1.1693 +    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
  1.1694 +done:
  1.1695 +    return crv;
  1.1696 +}
  1.1697 +
  1.1698 +static CK_RV
  1.1699 +lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr, 
  1.1700 +		      PRBool *writePrivate)
  1.1701 +{
  1.1702 +    CK_ATTRIBUTE attribLocal;
  1.1703 +    CK_RV crv;
  1.1704 +
  1.1705 +    if ((attr->type == CKA_NETSCAPE_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
  1.1706 +	*writePrivate = PR_TRUE;
  1.1707 +	return CKR_OK;
  1.1708 +    }
  1.1709 +
  1.1710 +    /* Make sure the attribute exists first */
  1.1711 +    attribLocal.type = attr->type;
  1.1712 +    attribLocal.pValue = NULL;
  1.1713 +    attribLocal.ulValueLen = 0;
  1.1714 +    crv = lg_GetSingleAttribute(obj, &attribLocal);
  1.1715 +    if (crv != CKR_OK) {
  1.1716 +	return crv;
  1.1717 +    }
  1.1718 +
  1.1719 +    /* if we are just setting it to the value we already have,
  1.1720 +     * allow it to happen. Let label setting go through so
  1.1721 +     * we have the opportunity to repair any database corruption. */
  1.1722 +    if (attr->type != CKA_LABEL) {
  1.1723 +	if (lg_cmpAttribute(obj,attr)) {
  1.1724 +	    return CKR_OK;
  1.1725 +	}
  1.1726 +    }
  1.1727 +
  1.1728 +    crv = CKR_ATTRIBUTE_READ_ONLY;
  1.1729 +    switch (obj->objclass) {
  1.1730 +    case CKO_CERTIFICATE:
  1.1731 +	/* change NICKNAME, EMAIL,  */
  1.1732 +	crv = lg_SetCertAttribute(obj,attr->type,
  1.1733 +				  attr->pValue,attr->ulValueLen);
  1.1734 +	break;
  1.1735 +    case CKO_NSS_CRL:
  1.1736 +	/* change URL */
  1.1737 +	break;
  1.1738 +    case CKO_NSS_TRUST:
  1.1739 +	crv = lg_SetTrustAttribute(obj,attr);
  1.1740 +	break;
  1.1741 +    case CKO_PRIVATE_KEY:
  1.1742 +    case CKO_SECRET_KEY:
  1.1743 +	crv = lg_SetPrivateKeyAttribute(obj,attr->type,
  1.1744 +			attr->pValue,attr->ulValueLen, writePrivate);
  1.1745 +	break;
  1.1746 +    case CKO_PUBLIC_KEY:
  1.1747 +	crv = lg_SetPublicKeyAttribute(obj,attr->type,
  1.1748 +			attr->pValue,attr->ulValueLen, writePrivate);
  1.1749 +	break;
  1.1750 +    }
  1.1751 +    return crv;
  1.1752 +}
  1.1753 +
  1.1754 +/*
  1.1755 + * Fill in the attribute template based on the data in the database.
  1.1756 + */    
  1.1757 +CK_RV
  1.1758 +lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, 
  1.1759 +			const CK_ATTRIBUTE *templ, CK_ULONG count)
  1.1760 +{
  1.1761 +    LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
  1.1762 +    CK_RV crv, crvCollect = CKR_OK;
  1.1763 +    PRBool writePrivate = PR_FALSE;
  1.1764 +    unsigned int i;
  1.1765 +
  1.1766 +    if (obj == NULL) {
  1.1767 +	return CKR_OBJECT_HANDLE_INVALID;
  1.1768 +    }
  1.1769 +
  1.1770 +    for (i=0; i < count; i++) {
  1.1771 +	crv = lg_SetSingleAttribute(obj, &templ[i], &writePrivate);
  1.1772 +	if (crvCollect == CKR_OK) crvCollect = crv;
  1.1773 +    }
  1.1774 +
  1.1775 +    /* Write any collected changes out for private and secret keys.
  1.1776 +     *  don't do the write for just the label */
  1.1777 +    if (writePrivate) {
  1.1778 +	NSSLOWKEYPrivateKey *privKey = lg_GetPrivateKey(obj);
  1.1779 +	SECStatus rv = SECFailure;
  1.1780 +	char * label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
  1.1781 +
  1.1782 +	if (privKey) {
  1.1783 +	    rv = nsslowkey_StoreKeyByPublicKeyAlg(lg_getKeyDB(sdb), privKey, 
  1.1784 +		&obj->dbKey, label, sdb, PR_TRUE );
  1.1785 +	}
  1.1786 +	if (rv != SECSuccess) {
  1.1787 +	    crv = CKR_DEVICE_ERROR;
  1.1788 +	}
  1.1789 +    }
  1.1790 +
  1.1791 +    lg_DestroyObjectCache(obj);
  1.1792 +    return crvCollect;
  1.1793 +}

mercurial