tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

lgattr.c (61837B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 /*
      5 * Internal PKCS #11 functions. Should only be called by pkcs11.c
      6 */
      7 #include "pkcs11.h"
      8 #include "lgdb.h"
      9 
     10 #include "pcertt.h"
     11 #include "lowkeyi.h"
     12 #include "pcert.h"
     13 #include "blapi.h"
     14 #include "secerr.h"
     15 #include "secasn1.h"
     16 
     17 /*
     18 * Cache the object we are working on during Set's and Get's
     19 */
     20 typedef struct LGObjectCacheStr {
     21    CK_OBJECT_CLASS objclass;
     22    CK_OBJECT_HANDLE handle;
     23    SDB *sdb;
     24    void *objectInfo;
     25    LGFreeFunc infoFree;
     26    SECItem dbKey;
     27 } LGObjectCache;
     28 
     29 static const CK_OBJECT_HANDLE lg_classArray[] = {
     30    CKO_TRUST, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY,
     31    CKO_NSS_TRUST, CKO_NSS_CRL, CKO_NSS_SMIME,
     32    CKO_CERTIFICATE
     33 };
     34 
     35 #define handleToClass(handle) \
     36    lg_classArray[((handle & LG_TOKEN_TYPE_MASK)) >> LG_TOKEN_TYPE_SHIFT]
     37 
     38 static void lg_DestroyObjectCache(LGObjectCache *obj);
     39 
     40 static LGObjectCache *
     41 lg_NewObjectCache(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE handle)
     42 {
     43    LGObjectCache *obj = NULL;
     44    SECStatus rv;
     45 
     46    obj = PORT_New(LGObjectCache);
     47    if (obj == NULL) {
     48        return NULL;
     49    }
     50 
     51    obj->objclass = handleToClass(handle);
     52    obj->handle = handle;
     53    obj->sdb = sdb;
     54    obj->objectInfo = NULL;
     55    obj->infoFree = NULL;
     56    obj->dbKey.data = NULL;
     57    obj->dbKey.len = 0;
     58    lg_DBLock(sdb);
     59    if (dbKey == NULL) {
     60        dbKey = lg_lookupTokenKeyByHandle(sdb, handle);
     61    }
     62    if (dbKey == NULL) {
     63        lg_DBUnlock(sdb);
     64        goto loser;
     65    }
     66    rv = SECITEM_CopyItem(NULL, &obj->dbKey, dbKey);
     67    lg_DBUnlock(sdb);
     68    if (rv != SECSuccess) {
     69        goto loser;
     70    }
     71 
     72    return obj;
     73 loser:
     74    (void)lg_DestroyObjectCache(obj);
     75    return NULL;
     76 }
     77 
     78 /*
     79 * free all the data associated with an object. Object reference count must
     80 * be 'zero'.
     81 */
     82 static void
     83 lg_DestroyObjectCache(LGObjectCache *obj)
     84 {
     85    if (obj->dbKey.data) {
     86        PORT_Free(obj->dbKey.data);
     87        obj->dbKey.data = NULL;
     88    }
     89    if (obj->objectInfo) {
     90        (*obj->infoFree)(obj->objectInfo);
     91        obj->objectInfo = NULL;
     92        obj->infoFree = NULL;
     93    }
     94    PORT_Free(obj);
     95 }
     96 /*
     97 * ******************** Attribute Utilities *******************************
     98 */
     99 
    100 static CK_RV
    101 lg_ULongAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, CK_ULONG value)
    102 {
    103    unsigned char *data;
    104    int i;
    105 
    106    if (attr->pValue == NULL) {
    107        attr->ulValueLen = 4;
    108        return CKR_OK;
    109    }
    110    if (attr->ulValueLen < 4) {
    111        attr->ulValueLen = (CK_ULONG)-1;
    112        return CKR_BUFFER_TOO_SMALL;
    113    }
    114 
    115    data = (unsigned char *)attr->pValue;
    116    for (i = 0; i < 4; i++) {
    117        data[i] = (value >> ((3 - i) * 8)) & 0xff;
    118    }
    119    attr->ulValueLen = 4;
    120    return CKR_OK;
    121 }
    122 
    123 static CK_RV
    124 lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type,
    125                 CK_VOID_PTR value, CK_ULONG len)
    126 {
    127 
    128    if (attr->pValue == NULL) {
    129        attr->ulValueLen = len;
    130        return CKR_OK;
    131    }
    132    if (attr->ulValueLen < len) {
    133        attr->ulValueLen = (CK_ULONG)-1;
    134        return CKR_BUFFER_TOO_SMALL;
    135    }
    136    if (len > 0 && value != NULL) {
    137        PORT_Memcpy(attr->pValue, value, len);
    138    }
    139    attr->ulValueLen = len;
    140    return CKR_OK;
    141 }
    142 
    143 static CK_RV
    144 lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
    145                       void *value, CK_ULONG len)
    146 {
    147    unsigned char *dval = (unsigned char *)value;
    148    if (*dval == 0) {
    149        dval++;
    150        len--;
    151    }
    152    return lg_CopyAttribute(attribute, type, dval, len);
    153 }
    154 
    155 static CK_RV
    156 lg_CopyPrivAttribute(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
    157                     void *value, CK_ULONG len, SDB *sdbpw)
    158 {
    159    SECItem plainText, *cipherText = NULL;
    160    CK_RV crv = CKR_USER_NOT_LOGGED_IN;
    161    SECStatus rv;
    162 
    163    plainText.data = value;
    164    plainText.len = len;
    165    rv = lg_util_encrypt(NULL, sdbpw, &plainText, &cipherText);
    166    if (rv != SECSuccess) {
    167        goto loser;
    168    }
    169    crv = lg_CopyAttribute(attribute, type, cipherText->data, cipherText->len);
    170 loser:
    171    if (cipherText) {
    172        SECITEM_FreeItem(cipherText, PR_TRUE);
    173    }
    174    return crv;
    175 }
    176 
    177 static CK_RV
    178 lg_CopyPrivAttrSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type,
    179                      void *value, CK_ULONG len, SDB *sdbpw)
    180 {
    181    unsigned char *dval = (unsigned char *)value;
    182 
    183    if (*dval == 0) {
    184        dval++;
    185        len--;
    186    }
    187    return lg_CopyPrivAttribute(attribute, type, dval, len, sdbpw);
    188 }
    189 
    190 static CK_RV
    191 lg_invalidAttribute(CK_ATTRIBUTE *attr)
    192 {
    193    attr->ulValueLen = (CK_ULONG)-1;
    194    return CKR_ATTRIBUTE_TYPE_INVALID;
    195 }
    196 
    197 #define LG_DEF_ATTRIBUTE(value, len) \
    198    {                                \
    199        0, value, len                \
    200    }
    201 
    202 #define LG_CLONE_ATTR(attribute, type, staticAttr) \
    203    lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen)
    204 
    205 CK_BBOOL lg_staticTrueValue = CK_TRUE;
    206 CK_BBOOL lg_staticFalseValue = CK_FALSE;
    207 static const CK_ATTRIBUTE lg_StaticTrueAttr =
    208    LG_DEF_ATTRIBUTE(&lg_staticTrueValue, sizeof(lg_staticTrueValue));
    209 static const CK_ATTRIBUTE lg_StaticFalseAttr =
    210    LG_DEF_ATTRIBUTE(&lg_staticFalseValue, sizeof(lg_staticFalseValue));
    211 static const CK_ATTRIBUTE lg_StaticNullAttr = LG_DEF_ATTRIBUTE(NULL, 0);
    212 char lg_StaticOneValue = 1;
    213 
    214 /*
    215 * helper functions which get the database and call the underlying
    216 * low level database function.
    217 */
    218 static char *
    219 lg_FindKeyNicknameByPublicKey(SDB *sdb, SECItem *dbKey)
    220 {
    221    NSSLOWKEYDBHandle *keyHandle;
    222    char *label;
    223 
    224    keyHandle = lg_getKeyDB(sdb);
    225    if (!keyHandle) {
    226        return NULL;
    227    }
    228 
    229    label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey,
    230                                                 sdb);
    231    return label;
    232 }
    233 
    234 NSSLOWKEYPrivateKey *
    235 lg_FindKeyByPublicKey(SDB *sdb, SECItem *dbKey)
    236 {
    237    NSSLOWKEYPrivateKey *privKey;
    238    NSSLOWKEYDBHandle *keyHandle;
    239 
    240    keyHandle = lg_getKeyDB(sdb);
    241    if (keyHandle == NULL) {
    242        return NULL;
    243    }
    244    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, sdb);
    245    if (privKey == NULL) {
    246        return NULL;
    247    }
    248    return privKey;
    249 }
    250 
    251 static certDBEntrySMime *
    252 lg_getSMime(LGObjectCache *obj)
    253 {
    254    certDBEntrySMime *entry;
    255    NSSLOWCERTCertDBHandle *certHandle;
    256 
    257    if (obj->objclass != CKO_NSS_SMIME) {
    258        return NULL;
    259    }
    260    if (obj->objectInfo) {
    261        return (certDBEntrySMime *)obj->objectInfo;
    262    }
    263 
    264    certHandle = lg_getCertDB(obj->sdb);
    265    if (!certHandle) {
    266        return NULL;
    267    }
    268    entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)obj->dbKey.data);
    269    obj->objectInfo = (void *)entry;
    270    obj->infoFree = (LGFreeFunc)nsslowcert_DestroyDBEntry;
    271    return entry;
    272 }
    273 
    274 static certDBEntryRevocation *
    275 lg_getCrl(LGObjectCache *obj)
    276 {
    277    certDBEntryRevocation *crl;
    278    PRBool isKrl;
    279    NSSLOWCERTCertDBHandle *certHandle;
    280 
    281    if (obj->objclass != CKO_NSS_CRL) {
    282        return NULL;
    283    }
    284    if (obj->objectInfo) {
    285        return (certDBEntryRevocation *)obj->objectInfo;
    286    }
    287 
    288    isKrl = (PRBool)(obj->handle == LG_TOKEN_KRL_HANDLE);
    289    certHandle = lg_getCertDB(obj->sdb);
    290    if (!certHandle) {
    291        return NULL;
    292    }
    293 
    294    crl = nsslowcert_FindCrlByKey(certHandle, &obj->dbKey, isKrl);
    295    obj->objectInfo = (void *)crl;
    296    obj->infoFree = (LGFreeFunc)nsslowcert_DestroyDBEntry;
    297    return crl;
    298 }
    299 
    300 static NSSLOWCERTCertificate *
    301 lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
    302 {
    303    NSSLOWCERTCertificate *cert;
    304    CK_OBJECT_CLASS objClass = obj->objclass;
    305 
    306    if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NSS_TRUST) &&
    307        (objClass != CKO_TRUST)) {
    308        return NULL;
    309    }
    310    if (objClass == CKO_CERTIFICATE && obj->objectInfo) {
    311        return (NSSLOWCERTCertificate *)obj->objectInfo;
    312    }
    313    cert = nsslowcert_FindCertByKey(certHandle, &obj->dbKey);
    314    if (objClass == CKO_CERTIFICATE) {
    315        obj->objectInfo = (void *)cert;
    316        obj->infoFree = (LGFreeFunc)nsslowcert_DestroyCertificate;
    317    }
    318    return cert;
    319 }
    320 
    321 static NSSLOWCERTTrust *
    322 lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle)
    323 {
    324    NSSLOWCERTTrust *trust;
    325 
    326    if ((obj->objclass != CKO_NSS_TRUST) || (obj->objclass != CKO_TRUST)) {
    327        return NULL;
    328    }
    329    if (obj->objectInfo) {
    330        return (NSSLOWCERTTrust *)obj->objectInfo;
    331    }
    332    trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey);
    333    obj->objectInfo = (void *)trust;
    334    obj->infoFree = (LGFreeFunc)nsslowcert_DestroyTrust;
    335    return trust;
    336 }
    337 
    338 static NSSLOWKEYPublicKey *
    339 lg_GetPublicKey(LGObjectCache *obj)
    340 {
    341    NSSLOWKEYPublicKey *pubKey;
    342    NSSLOWKEYPrivateKey *privKey;
    343 
    344    if (obj->objclass != CKO_PUBLIC_KEY) {
    345        return NULL;
    346    }
    347    if (obj->objectInfo) {
    348        return (NSSLOWKEYPublicKey *)obj->objectInfo;
    349    }
    350    privKey = lg_FindKeyByPublicKey(obj->sdb, &obj->dbKey);
    351    if (privKey == NULL) {
    352        return NULL;
    353    }
    354    pubKey = lg_nsslowkey_ConvertToPublicKey(privKey);
    355    lg_nsslowkey_DestroyPrivateKey(privKey);
    356    obj->objectInfo = (void *)pubKey;
    357    obj->infoFree = (LGFreeFunc)lg_nsslowkey_DestroyPublicKey;
    358    return pubKey;
    359 }
    360 
    361 /*
    362 * we need two versions of lg_GetPrivateKey. One version that takes the
    363 * DB handle so we can pass the handle we have already acquired in,
    364 *  rather than going through the 'getKeyDB' code again,
    365 *  which may fail the second time and another which just aquires
    366 *  the key handle from the sdb (where we don't already have a key handle.
    367 * This version does the former.
    368 */
    369 static NSSLOWKEYPrivateKey *
    370 lg_GetPrivateKeyWithDB(LGObjectCache *obj, NSSLOWKEYDBHandle *keyHandle)
    371 {
    372    NSSLOWKEYPrivateKey *privKey;
    373 
    374    if ((obj->objclass != CKO_PRIVATE_KEY) &&
    375        (obj->objclass != CKO_SECRET_KEY)) {
    376        return NULL;
    377    }
    378    if (obj->objectInfo) {
    379        return (NSSLOWKEYPrivateKey *)obj->objectInfo;
    380    }
    381    privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &obj->dbKey, obj->sdb);
    382    if (privKey == NULL) {
    383        return NULL;
    384    }
    385    obj->objectInfo = (void *)privKey;
    386    obj->infoFree = (LGFreeFunc)lg_nsslowkey_DestroyPrivateKey;
    387    return privKey;
    388 }
    389 
    390 /* this version does the latter */
    391 static NSSLOWKEYPrivateKey *
    392 lg_GetPrivateKey(LGObjectCache *obj)
    393 {
    394    NSSLOWKEYDBHandle *keyHandle;
    395    NSSLOWKEYPrivateKey *privKey;
    396 
    397    keyHandle = lg_getKeyDB(obj->sdb);
    398    if (!keyHandle) {
    399        return NULL;
    400    }
    401    privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
    402    return privKey;
    403 }
    404 
    405 /* lg_GetPubItem returns data associated with the public key.
    406 * one only needs to free the public key. This comment is here
    407 * because this sematic would be non-obvious otherwise. All callers
    408 * should include this comment.
    409 */
    410 static SECItem *
    411 lg_GetPubItem(NSSLOWKEYPublicKey *pubKey)
    412 {
    413    SECItem *pubItem = NULL;
    414    /* get value to compare from the cert's public key */
    415    switch (pubKey->keyType) {
    416        case NSSLOWKEYRSAKey:
    417            pubItem = &pubKey->u.rsa.modulus;
    418            break;
    419        case NSSLOWKEYDSAKey:
    420            pubItem = &pubKey->u.dsa.publicValue;
    421            break;
    422        case NSSLOWKEYDHKey:
    423            pubItem = &pubKey->u.dh.publicValue;
    424            break;
    425        case NSSLOWKEYECKey:
    426            pubItem = &pubKey->u.ec.publicValue;
    427            break;
    428        default:
    429            break;
    430    }
    431    return pubItem;
    432 }
    433 
    434 static CK_RV
    435 lg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
    436                             CK_ATTRIBUTE *attribute)
    437 {
    438    unsigned char hash[SHA1_LENGTH];
    439    CK_KEY_TYPE keyType = CKK_RSA;
    440 
    441    switch (type) {
    442        case CKA_KEY_TYPE:
    443            return lg_ULongAttribute(attribute, type, keyType);
    444        case CKA_ID:
    445            SHA1_HashBuf(hash, key->u.rsa.modulus.data, key->u.rsa.modulus.len);
    446            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    447        case CKA_DERIVE:
    448            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    449        case CKA_ENCRYPT:
    450        case CKA_VERIFY:
    451        case CKA_VERIFY_RECOVER:
    452        case CKA_WRAP:
    453            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    454        case CKA_MODULUS:
    455            return lg_CopyAttributeSigned(attribute, type, key->u.rsa.modulus.data,
    456                                          key->u.rsa.modulus.len);
    457        case CKA_PUBLIC_EXPONENT:
    458            return lg_CopyAttributeSigned(attribute, type,
    459                                          key->u.rsa.publicExponent.data,
    460                                          key->u.rsa.publicExponent.len);
    461        default:
    462            break;
    463    }
    464    return lg_invalidAttribute(attribute);
    465 }
    466 
    467 static CK_RV
    468 lg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
    469                             CK_ATTRIBUTE *attribute)
    470 {
    471    unsigned char hash[SHA1_LENGTH];
    472    CK_KEY_TYPE keyType = CKK_DSA;
    473 
    474    switch (type) {
    475        case CKA_KEY_TYPE:
    476            return lg_ULongAttribute(attribute, type, keyType);
    477        case CKA_ID:
    478            SHA1_HashBuf(hash, key->u.dsa.publicValue.data,
    479                         key->u.dsa.publicValue.len);
    480            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    481        case CKA_DERIVE:
    482        case CKA_ENCRYPT:
    483        case CKA_VERIFY_RECOVER:
    484        case CKA_WRAP:
    485            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    486        case CKA_VERIFY:
    487            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    488        case CKA_VALUE:
    489            return lg_CopyAttributeSigned(attribute, type,
    490                                          key->u.dsa.publicValue.data,
    491                                          key->u.dsa.publicValue.len);
    492        case CKA_PRIME:
    493            return lg_CopyAttributeSigned(attribute, type,
    494                                          key->u.dsa.params.prime.data,
    495                                          key->u.dsa.params.prime.len);
    496        case CKA_SUBPRIME:
    497            return lg_CopyAttributeSigned(attribute, type,
    498                                          key->u.dsa.params.subPrime.data,
    499                                          key->u.dsa.params.subPrime.len);
    500        case CKA_BASE:
    501            return lg_CopyAttributeSigned(attribute, type,
    502                                          key->u.dsa.params.base.data,
    503                                          key->u.dsa.params.base.len);
    504        default:
    505            break;
    506    }
    507    return lg_invalidAttribute(attribute);
    508 }
    509 
    510 static CK_RV
    511 lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
    512                            CK_ATTRIBUTE *attribute)
    513 {
    514    unsigned char hash[SHA1_LENGTH];
    515    CK_KEY_TYPE keyType = CKK_DH;
    516 
    517    switch (type) {
    518        case CKA_KEY_TYPE:
    519            return lg_ULongAttribute(attribute, type, keyType);
    520        case CKA_ID:
    521            SHA1_HashBuf(hash, key->u.dh.publicValue.data, key->u.dh.publicValue.len);
    522            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    523        case CKA_DERIVE:
    524            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    525        case CKA_ENCRYPT:
    526        case CKA_VERIFY:
    527        case CKA_VERIFY_RECOVER:
    528        case CKA_WRAP:
    529            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    530        case CKA_VALUE:
    531            return lg_CopyAttributeSigned(attribute, type,
    532                                          key->u.dh.publicValue.data,
    533                                          key->u.dh.publicValue.len);
    534        case CKA_PRIME:
    535            return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data,
    536                                          key->u.dh.prime.len);
    537        case CKA_BASE:
    538            return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
    539                                          key->u.dh.base.len);
    540        default:
    541            break;
    542    }
    543    return lg_invalidAttribute(attribute);
    544 }
    545 
    546 static CK_RV
    547 lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type,
    548                            CK_ATTRIBUTE *attribute)
    549 {
    550    unsigned char hash[SHA1_LENGTH];
    551    CK_KEY_TYPE keyType = CKK_EC;
    552 
    553    switch (type) {
    554        case CKA_KEY_TYPE:
    555            return lg_ULongAttribute(attribute, type, keyType);
    556        case CKA_ID:
    557            SHA1_HashBuf(hash, key->u.ec.publicValue.data,
    558                         key->u.ec.publicValue.len);
    559            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    560        case CKA_DERIVE:
    561        case CKA_VERIFY:
    562            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    563        case CKA_ENCRYPT:
    564        case CKA_VERIFY_RECOVER:
    565        case CKA_WRAP:
    566            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    567        case CKA_EC_PARAMS:
    568            return lg_CopyAttributeSigned(attribute, type,
    569                                          key->u.ec.ecParams.DEREncoding.data,
    570                                          key->u.ec.ecParams.DEREncoding.len);
    571        case CKA_EC_POINT:
    572            if (PR_GetEnvSecure("NSS_USE_DECODED_CKA_EC_POINT")) {
    573                return lg_CopyAttributeSigned(attribute, type,
    574                                              key->u.ec.publicValue.data,
    575                                              key->u.ec.publicValue.len);
    576            } else {
    577                SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL,
    578                                                       &(key->u.ec.publicValue),
    579                                                       SEC_ASN1_GET(SEC_OctetStringTemplate));
    580                CK_RV crv;
    581                if (!pubValue) {
    582                    return CKR_HOST_MEMORY;
    583                }
    584                crv = lg_CopyAttributeSigned(attribute, type,
    585                                             pubValue->data,
    586                                             pubValue->len);
    587                SECITEM_FreeItem(pubValue, PR_TRUE);
    588                return crv;
    589            }
    590        default:
    591            break;
    592    }
    593    return lg_invalidAttribute(attribute);
    594 }
    595 
    596 static CK_RV
    597 lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
    598                          CK_ATTRIBUTE *attribute)
    599 {
    600    NSSLOWKEYPublicKey *key;
    601    CK_RV crv;
    602    char *label;
    603 
    604    switch (type) {
    605        case CKA_PRIVATE:
    606        case CKA_SENSITIVE:
    607        case CKA_ALWAYS_SENSITIVE:
    608        case CKA_NEVER_EXTRACTABLE:
    609            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    610        case CKA_MODIFIABLE:
    611        case CKA_EXTRACTABLE:
    612            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    613        case CKA_SUBJECT:
    614            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    615        case CKA_START_DATE:
    616        case CKA_END_DATE:
    617            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    618        case CKA_LABEL:
    619            label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
    620            if (label == NULL) {
    621                return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    622            }
    623            crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label));
    624            PORT_Free(label);
    625            return crv;
    626        default:
    627            break;
    628    }
    629 
    630    key = lg_GetPublicKey(obj);
    631    if (key == NULL) {
    632        if (type == CKA_ID) {
    633            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    634        }
    635        return CKR_OBJECT_HANDLE_INVALID;
    636    }
    637 
    638    switch (key->keyType) {
    639        case NSSLOWKEYRSAKey:
    640            return lg_FindRSAPublicKeyAttribute(key, type, attribute);
    641        case NSSLOWKEYDSAKey:
    642            return lg_FindDSAPublicKeyAttribute(key, type, attribute);
    643        case NSSLOWKEYDHKey:
    644            return lg_FindDHPublicKeyAttribute(key, type, attribute);
    645        case NSSLOWKEYECKey:
    646            return lg_FindECPublicKeyAttribute(key, type, attribute);
    647        default:
    648            break;
    649    }
    650 
    651    return lg_invalidAttribute(attribute);
    652 }
    653 
    654 static CK_RV
    655 lg_FindSecretKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
    656                          CK_ATTRIBUTE *attribute)
    657 {
    658    NSSLOWKEYPrivateKey *key;
    659    char *label;
    660    unsigned char *keyString;
    661    CK_RV crv;
    662    int keyTypeLen;
    663    CK_ULONG keyLen;
    664    CK_KEY_TYPE keyType;
    665    PRUint32 keyTypeStorage;
    666 
    667    switch (type) {
    668        case CKA_PRIVATE:
    669        case CKA_SENSITIVE:
    670        case CKA_ALWAYS_SENSITIVE:
    671        case CKA_EXTRACTABLE:
    672        case CKA_DERIVE:
    673        case CKA_ENCRYPT:
    674        case CKA_DECRYPT:
    675        case CKA_SIGN:
    676        case CKA_VERIFY:
    677        case CKA_WRAP:
    678        case CKA_UNWRAP:
    679        case CKA_MODIFIABLE:
    680        case CKA_LOCAL:
    681            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    682        case CKA_NEVER_EXTRACTABLE:
    683            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    684        case CKA_START_DATE:
    685        case CKA_END_DATE:
    686            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    687        case CKA_LABEL:
    688            label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
    689            if (label == NULL) {
    690                return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    691            }
    692            crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label));
    693            PORT_Free(label);
    694            return crv;
    695        case CKA_ID:
    696            return lg_CopyAttribute(attribute, type, obj->dbKey.data,
    697                                    obj->dbKey.len);
    698        case CKA_KEY_TYPE:
    699        case CKA_VALUE_LEN:
    700        case CKA_VALUE:
    701            break;
    702        default:
    703            return lg_invalidAttribute(attribute);
    704    }
    705 
    706    key = lg_GetPrivateKey(obj);
    707    if (key == NULL) {
    708        return CKR_OBJECT_HANDLE_INVALID;
    709    }
    710    switch (type) {
    711        case CKA_KEY_TYPE:
    712            /* handle legacy databases. In legacy databases key_type was stored
    713             * in host order, with any leading zeros stripped off. Only key types
    714             * under 0x1f (AES) were stored. We assume that any values which are
    715             * either 1 byte long (big endian), or have byte[0] between 0 and
    716             * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other
    717             * values are assumed to be from the new database, which is always 4
    718             * bytes in network order */
    719            keyType = 0;
    720            keyString = key->u.rsa.coefficient.data;
    721            keyTypeLen = key->u.rsa.coefficient.len;
    722 
    723            /*
    724             * Because of various endian and word lengths The database may have
    725             * stored the keyType value in one of the following formats:
    726             *   (kt) <= 0x1f
    727             *                                   length data
    728             * Big Endian,     pre-3.9, all lengths: 1  (kt)
    729             * Little Endian,  pre-3.9, 32 bits:     4  (kt) 0  0  0
    730             * Little Endian,  pre-3.9, 64 bits:     8  (kt) 0  0  0   0  0  0  0
    731             * All platforms,      3.9, 32 bits:     4    0  0  0 (kt)
    732             * Big Endian,         3.9, 64 bits:     8    0  0  0 (kt) 0  0  0  0
    733             * Little  Endian,     3.9, 64 bits:     8    0  0  0  0   0  0  0 (kt)
    734             * All platforms, >= 3.9.1, all lengths: 4   (a) k1 k2 k3
    735             * where (a) is 0 or >= 0x80. currently (a) can only be 0.
    736             */
    737            /*
    738             * this key was written on a 64 bit platform with a using NSS 3.9
    739             * or earlier. Reduce the 64 bit possibilities above. When we are
    740             * through, we will only have:
    741             *
    742             * Big Endian,     pre-3.9, all lengths: 1  (kt)
    743             * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
    744             * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
    745             * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
    746             */
    747            if (keyTypeLen == 8) {
    748                keyTypeStorage = *(PRUint32 *)keyString;
    749                if (keyTypeStorage == 0) {
    750                    keyString += sizeof(PRUint32);
    751                }
    752                keyTypeLen = 4;
    753            }
    754            /*
    755             * Now Handle:
    756             *
    757             * All platforms,      3.9, all lengths: 4    0  0  0 (kt)
    758             * All platforms, => 3.9.1, all lengths: 4   (a) k1 k2 k3
    759             *
    760             * NOTE: if  kt == 0 or ak1k2k3 == 0, the test fails and
    761             * we handle it as:
    762             *
    763             * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
    764             */
    765            if (keyTypeLen == sizeof(keyTypeStorage) &&
    766                (((keyString[0] & 0x80) == 0x80) ||
    767                 !((keyString[1] == 0) && (keyString[2] == 0) && (keyString[3] == 0)))) {
    768                PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage));
    769                keyType = (CK_KEY_TYPE)PR_ntohl(keyTypeStorage);
    770            } else {
    771                /*
    772                 * Now Handle:
    773                 *
    774                 * Big Endian,     pre-3.9, all lengths: 1  (kt)
    775                 * Little Endian,  pre-3.9, all lengths: 4  (kt) 0  0  0
    776                 *  -- KeyType == 0 all other cases ---: 4    0  0  0  0
    777                 */
    778                keyType = (CK_KEY_TYPE)keyString[0];
    779            }
    780            return lg_ULongAttribute(attribute, type, keyType);
    781        case CKA_VALUE:
    782            return lg_CopyPrivAttribute(attribute, type, key->u.rsa.privateExponent.data,
    783                                        key->u.rsa.privateExponent.len, obj->sdb);
    784        case CKA_VALUE_LEN:
    785            keyLen = key->u.rsa.privateExponent.len;
    786            return lg_ULongAttribute(attribute, type, keyLen);
    787    }
    788    return lg_invalidAttribute(attribute);
    789 }
    790 
    791 static CK_RV
    792 lg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
    793                              CK_ATTRIBUTE *attribute, SDB *sdbpw)
    794 {
    795    unsigned char hash[SHA1_LENGTH];
    796    CK_KEY_TYPE keyType = CKK_RSA;
    797 
    798    switch (type) {
    799        case CKA_KEY_TYPE:
    800            return lg_ULongAttribute(attribute, type, keyType);
    801        case CKA_ID:
    802            SHA1_HashBuf(hash, key->u.rsa.modulus.data, key->u.rsa.modulus.len);
    803            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    804        case CKA_DERIVE:
    805            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    806        case CKA_DECRYPT:
    807        case CKA_SIGN:
    808        case CKA_SIGN_RECOVER:
    809        case CKA_UNWRAP:
    810            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    811        case CKA_MODULUS:
    812            return lg_CopyAttributeSigned(attribute, type, key->u.rsa.modulus.data,
    813                                          key->u.rsa.modulus.len);
    814        case CKA_PUBLIC_EXPONENT:
    815            return lg_CopyAttributeSigned(attribute, type,
    816                                          key->u.rsa.publicExponent.data,
    817                                          key->u.rsa.publicExponent.len);
    818        case CKA_PRIVATE_EXPONENT:
    819            return lg_CopyPrivAttrSigned(attribute, type,
    820                                         key->u.rsa.privateExponent.data,
    821                                         key->u.rsa.privateExponent.len, sdbpw);
    822        case CKA_PRIME_1:
    823            return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime1.data,
    824                                         key->u.rsa.prime1.len, sdbpw);
    825        case CKA_PRIME_2:
    826            return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime2.data,
    827                                         key->u.rsa.prime2.len, sdbpw);
    828        case CKA_EXPONENT_1:
    829            return lg_CopyPrivAttrSigned(attribute, type,
    830                                         key->u.rsa.exponent1.data,
    831                                         key->u.rsa.exponent1.len, sdbpw);
    832        case CKA_EXPONENT_2:
    833            return lg_CopyPrivAttrSigned(attribute, type,
    834                                         key->u.rsa.exponent2.data,
    835                                         key->u.rsa.exponent2.len, sdbpw);
    836        case CKA_COEFFICIENT:
    837            return lg_CopyPrivAttrSigned(attribute, type,
    838                                         key->u.rsa.coefficient.data,
    839                                         key->u.rsa.coefficient.len, sdbpw);
    840        default:
    841            break;
    842    }
    843    return lg_invalidAttribute(attribute);
    844 }
    845 
    846 static CK_RV
    847 lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
    848                              CK_ATTRIBUTE *attribute, SDB *sdbpw)
    849 {
    850    unsigned char hash[SHA1_LENGTH];
    851    CK_KEY_TYPE keyType = CKK_DSA;
    852 
    853    switch (type) {
    854        case CKA_KEY_TYPE:
    855            return lg_ULongAttribute(attribute, type, keyType);
    856        case CKA_ID:
    857            SHA1_HashBuf(hash, key->u.dsa.publicValue.data,
    858                         key->u.dsa.publicValue.len);
    859            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    860        case CKA_DERIVE:
    861        case CKA_DECRYPT:
    862        case CKA_SIGN_RECOVER:
    863        case CKA_UNWRAP:
    864            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    865        case CKA_SIGN:
    866            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    867        case CKA_VALUE:
    868            return lg_CopyPrivAttrSigned(attribute, type,
    869                                         key->u.dsa.privateValue.data,
    870                                         key->u.dsa.privateValue.len, sdbpw);
    871        case CKA_PRIME:
    872            return lg_CopyAttributeSigned(attribute, type,
    873                                          key->u.dsa.params.prime.data,
    874                                          key->u.dsa.params.prime.len);
    875        case CKA_SUBPRIME:
    876            return lg_CopyAttributeSigned(attribute, type,
    877                                          key->u.dsa.params.subPrime.data,
    878                                          key->u.dsa.params.subPrime.len);
    879        case CKA_BASE:
    880            return lg_CopyAttributeSigned(attribute, type,
    881                                          key->u.dsa.params.base.data,
    882                                          key->u.dsa.params.base.len);
    883        case CKA_NSS_DB:
    884            return lg_CopyAttributeSigned(attribute, type,
    885                                          key->u.dsa.publicValue.data,
    886                                          key->u.dsa.publicValue.len);
    887        default:
    888            break;
    889    }
    890    return lg_invalidAttribute(attribute);
    891 }
    892 
    893 static CK_RV
    894 lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
    895                             CK_ATTRIBUTE *attribute, SDB *sdbpw)
    896 {
    897    unsigned char hash[SHA1_LENGTH];
    898    CK_KEY_TYPE keyType = CKK_DH;
    899 
    900    switch (type) {
    901        case CKA_KEY_TYPE:
    902            return lg_ULongAttribute(attribute, type, keyType);
    903        case CKA_ID:
    904            SHA1_HashBuf(hash, key->u.dh.publicValue.data, key->u.dh.publicValue.len);
    905            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    906        case CKA_DERIVE:
    907            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    908        case CKA_DECRYPT:
    909        case CKA_SIGN:
    910        case CKA_SIGN_RECOVER:
    911        case CKA_UNWRAP:
    912            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    913        case CKA_VALUE:
    914            return lg_CopyPrivAttrSigned(attribute, type,
    915                                         key->u.dh.privateValue.data,
    916                                         key->u.dh.privateValue.len, sdbpw);
    917        case CKA_PRIME:
    918            return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data,
    919                                          key->u.dh.prime.len);
    920        case CKA_BASE:
    921            return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data,
    922                                          key->u.dh.base.len);
    923        case CKA_NSS_DB:
    924            return lg_CopyAttributeSigned(attribute, type,
    925                                          key->u.dh.publicValue.data,
    926                                          key->u.dh.publicValue.len);
    927        default:
    928            break;
    929    }
    930    return lg_invalidAttribute(attribute);
    931 }
    932 
    933 static CK_RV
    934 lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type,
    935                             CK_ATTRIBUTE *attribute, SDB *sdbpw)
    936 {
    937    unsigned char hash[SHA1_LENGTH];
    938    CK_KEY_TYPE keyType = CKK_EC;
    939 
    940    switch (type) {
    941        case CKA_KEY_TYPE:
    942            return lg_ULongAttribute(attribute, type, keyType);
    943        case CKA_ID:
    944            SHA1_HashBuf(hash, key->u.ec.publicValue.data, key->u.ec.publicValue.len);
    945            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
    946        case CKA_DERIVE:
    947        case CKA_SIGN:
    948            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    949        case CKA_DECRYPT:
    950        case CKA_SIGN_RECOVER:
    951        case CKA_UNWRAP:
    952            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    953        case CKA_VALUE:
    954            return lg_CopyPrivAttribute(attribute, type,
    955                                        key->u.ec.privateValue.data,
    956                                        key->u.ec.privateValue.len, sdbpw);
    957        case CKA_EC_PARAMS:
    958            return lg_CopyAttributeSigned(attribute, type,
    959                                          key->u.ec.ecParams.DEREncoding.data,
    960                                          key->u.ec.ecParams.DEREncoding.len);
    961        case CKA_NSS_DB:
    962            return lg_CopyAttributeSigned(attribute, type,
    963                                          key->u.ec.publicValue.data,
    964                                          key->u.ec.publicValue.len);
    965        default:
    966            break;
    967    }
    968    return lg_invalidAttribute(attribute);
    969 }
    970 
    971 static CK_RV
    972 lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
    973                           CK_ATTRIBUTE *attribute)
    974 {
    975    NSSLOWKEYPrivateKey *key;
    976    char *label;
    977    CK_RV crv;
    978 
    979    switch (type) {
    980        case CKA_PRIVATE:
    981        case CKA_SENSITIVE:
    982        case CKA_ALWAYS_SENSITIVE:
    983        case CKA_EXTRACTABLE:
    984        case CKA_MODIFIABLE:
    985        case CKA_LOCAL:
    986            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
    987        case CKA_NEVER_EXTRACTABLE:
    988            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
    989        case CKA_SUBJECT:
    990            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    991        case CKA_START_DATE:
    992        case CKA_END_DATE:
    993            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    994        case CKA_LABEL:
    995            label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
    996            if (label == NULL) {
    997                return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
    998            }
    999            crv = lg_CopyAttribute(attribute, type, label, PORT_Strlen(label));
   1000            PORT_Free(label);
   1001            return crv;
   1002        default:
   1003            break;
   1004    }
   1005    key = lg_GetPrivateKey(obj);
   1006    if (key == NULL) {
   1007        return CKR_OBJECT_HANDLE_INVALID;
   1008    }
   1009    switch (key->keyType) {
   1010        case NSSLOWKEYRSAKey:
   1011            return lg_FindRSAPrivateKeyAttribute(key, type, attribute, obj->sdb);
   1012        case NSSLOWKEYDSAKey:
   1013            return lg_FindDSAPrivateKeyAttribute(key, type, attribute, obj->sdb);
   1014        case NSSLOWKEYDHKey:
   1015            return lg_FindDHPrivateKeyAttribute(key, type, attribute, obj->sdb);
   1016        case NSSLOWKEYECKey:
   1017            return lg_FindECPrivateKeyAttribute(key, type, attribute, obj->sdb);
   1018        default:
   1019            break;
   1020    }
   1021 
   1022    return lg_invalidAttribute(attribute);
   1023 }
   1024 
   1025 static CK_RV
   1026 lg_FindSMIMEAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1027                      CK_ATTRIBUTE *attribute)
   1028 {
   1029    certDBEntrySMime *entry;
   1030    switch (type) {
   1031        case CKA_PRIVATE:
   1032        case CKA_MODIFIABLE:
   1033            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
   1034        case CKA_NSS_EMAIL:
   1035            return lg_CopyAttribute(attribute, type, obj->dbKey.data,
   1036                                    obj->dbKey.len - 1);
   1037        case CKA_NSS_SMIME_TIMESTAMP:
   1038        case CKA_SUBJECT:
   1039        case CKA_VALUE:
   1040            break;
   1041        default:
   1042            return lg_invalidAttribute(attribute);
   1043    }
   1044    entry = lg_getSMime(obj);
   1045    if (entry == NULL) {
   1046        return CKR_OBJECT_HANDLE_INVALID;
   1047    }
   1048    switch (type) {
   1049        case CKA_NSS_SMIME_TIMESTAMP:
   1050            return lg_CopyAttribute(attribute, type, entry->optionsDate.data,
   1051                                    entry->optionsDate.len);
   1052        case CKA_SUBJECT:
   1053            return lg_CopyAttribute(attribute, type, entry->subjectName.data,
   1054                                    entry->subjectName.len);
   1055        case CKA_VALUE:
   1056            return lg_CopyAttribute(attribute, type, entry->smimeOptions.data,
   1057                                    entry->smimeOptions.len);
   1058        default:
   1059            break;
   1060    }
   1061    return lg_invalidAttribute(attribute);
   1062 }
   1063 
   1064 static CK_RV
   1065 lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1066                      CK_ATTRIBUTE *attribute)
   1067 {
   1068    NSSLOWCERTTrust *trust;
   1069    NSSLOWCERTCertDBHandle *certHandle;
   1070    NSSLOWCERTCertificate *cert;
   1071    unsigned char hash[SHA1_LENGTH];
   1072    unsigned int trustFlags;
   1073    CK_RV crv = CKR_CANCEL;
   1074    PRBool isPKCS;
   1075 
   1076    switch (type) {
   1077        case CKA_PRIVATE:
   1078            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
   1079        case CKA_MODIFIABLE:
   1080            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
   1081        case CKA_NSS_CERT_SHA1_HASH:
   1082        case CKA_NSS_CERT_MD5_HASH:
   1083        case CKA_HASH_OF_CERTIFICATE:
   1084        case CKA_NAME_HASH_ALGORITHM:
   1085        case CKA_NSS_TRUST_CLIENT_AUTH:
   1086        case CKA_NSS_TRUST_SERVER_AUTH:
   1087        case CKA_NSS_TRUST_EMAIL_PROTECTION:
   1088        case CKA_NSS_TRUST_CODE_SIGNING:
   1089        case CKA_NSS_TRUST_STEP_UP_APPROVED:
   1090        case CKA_PKCS_TRUST_CLIENT_AUTH:
   1091        case CKA_PKCS_TRUST_SERVER_AUTH:
   1092        case CKA_PKCS_TRUST_EMAIL_PROTECTION:
   1093        case CKA_PKCS_TRUST_CODE_SIGNING:
   1094        case CKA_ISSUER:
   1095        case CKA_SERIAL_NUMBER:
   1096            break;
   1097        default:
   1098            return lg_invalidAttribute(attribute);
   1099    }
   1100    certHandle = lg_getCertDB(obj->sdb);
   1101    if (!certHandle) {
   1102        return CKR_OBJECT_HANDLE_INVALID;
   1103    }
   1104    trust = lg_getTrust(obj, certHandle);
   1105    if (trust == NULL) {
   1106        return CKR_OBJECT_HANDLE_INVALID;
   1107    }
   1108    isPKCS = PR_TRUE;
   1109    switch (type) {
   1110        case CKA_NAME_HASH_ALGORITHM:
   1111            return lg_ULongAttribute(attribute, type, CKM_SHA_1);
   1112        case CKA_NSS_CERT_SHA1_HASH:
   1113        case CKA_HASH_OF_CERTIFICATE:
   1114            SHA1_HashBuf(hash, trust->derCert->data, trust->derCert->len);
   1115            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
   1116        case CKA_NSS_CERT_MD5_HASH:
   1117            MD5_HashBuf(hash, trust->derCert->data, trust->derCert->len);
   1118            return lg_CopyAttribute(attribute, type, hash, MD5_LENGTH);
   1119        case CKA_NSS_TRUST_CLIENT_AUTH:
   1120            isPKCS = PR_FALSE;
   1121        case CKA_PKCS_TRUST_CLIENT_AUTH:
   1122            trustFlags = trust->trust->sslFlags &
   1123                                 CERTDB_TRUSTED_CLIENT_CA
   1124                             ? trust->trust->sslFlags | CERTDB_TRUSTED_CA
   1125                             : 0;
   1126            goto trust;
   1127        case CKA_NSS_TRUST_SERVER_AUTH:
   1128            isPKCS = PR_FALSE;
   1129        case CKA_PKCS_TRUST_SERVER_AUTH:
   1130            trustFlags = trust->trust->sslFlags;
   1131            goto trust;
   1132        case CKA_NSS_TRUST_EMAIL_PROTECTION:
   1133            isPKCS = PR_FALSE;
   1134        case CKA_PKCS_TRUST_EMAIL_PROTECTION:
   1135            trustFlags = trust->trust->emailFlags;
   1136            goto trust;
   1137        case CKA_NSS_TRUST_CODE_SIGNING:
   1138            isPKCS = PR_FALSE;
   1139        case CKA_PKCS_TRUST_CODE_SIGNING:
   1140            trustFlags = trust->trust->objectSigningFlags;
   1141        trust:
   1142            if (trustFlags & CERTDB_TRUSTED_CA) {
   1143                return lg_ULongAttribute(attribute, type,
   1144                                         isPKCS ? CKT_TRUST_ANCHOR : CKT_NSS_TRUSTED_DELEGATOR);
   1145            }
   1146            if (trustFlags & CERTDB_TRUSTED) {
   1147                return lg_ULongAttribute(attribute, type, isPKCS ? CKT_TRUSTED : CKT_NSS_TRUSTED);
   1148            }
   1149            if (trustFlags & CERTDB_MUST_VERIFY) {
   1150                return lg_ULongAttribute(attribute, type,
   1151                                         isPKCS ? CKT_TRUST_MUST_VERIFY_TRUST : CKT_NSS_MUST_VERIFY_TRUST);
   1152            }
   1153            if (trustFlags & CERTDB_TRUSTED_UNKNOWN) {
   1154                return lg_ULongAttribute(attribute, type,
   1155                                         isPKCS ? CKT_TRUST_UNKNOWN : CKT_NSS_TRUST_UNKNOWN);
   1156            }
   1157            if (trustFlags & CERTDB_VALID_CA) {
   1158                return lg_ULongAttribute(attribute, type,
   1159                                         isPKCS ? CKT_TRUST_MUST_VERIFY_TRUST : CKT_NSS_VALID_DELEGATOR);
   1160            }
   1161            if (trustFlags & CERTDB_TERMINAL_RECORD) {
   1162                return lg_ULongAttribute(attribute, type,
   1163                                         isPKCS ? CKT_NOT_TRUSTED : CKT_NSS_NOT_TRUSTED);
   1164            }
   1165            return lg_ULongAttribute(attribute, type, isPKCS ? CKT_TRUST_UNKNOWN : CKT_NSS_TRUST_UNKNOWN);
   1166        case CKA_NSS_TRUST_STEP_UP_APPROVED:
   1167            if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) {
   1168                return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
   1169            } else {
   1170                return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
   1171            }
   1172        default:
   1173            break;
   1174    }
   1175 
   1176    switch (type) {
   1177        case CKA_ISSUER:
   1178            cert = lg_getCert(obj, certHandle);
   1179            if (cert == NULL)
   1180                break;
   1181            crv = lg_CopyAttribute(attribute, type, cert->derIssuer.data,
   1182                                   cert->derIssuer.len);
   1183            break;
   1184        case CKA_SERIAL_NUMBER:
   1185            cert = lg_getCert(obj, certHandle);
   1186            if (cert == NULL)
   1187                break;
   1188            crv = lg_CopyAttribute(attribute, type, cert->derSN.data,
   1189                                   cert->derSN.len);
   1190            break;
   1191        default:
   1192            cert = NULL;
   1193            break;
   1194    }
   1195    if (cert) {
   1196        nsslowcert_DestroyCertificate(cert);
   1197        return crv;
   1198    }
   1199    return lg_invalidAttribute(attribute);
   1200 }
   1201 
   1202 static CK_RV
   1203 lg_FindCrlAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1204                    CK_ATTRIBUTE *attribute)
   1205 {
   1206    certDBEntryRevocation *crl;
   1207 
   1208    switch (type) {
   1209        case CKA_PRIVATE:
   1210        case CKA_MODIFIABLE:
   1211            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
   1212        case CKA_NSS_KRL:
   1213            return ((obj->handle == LG_TOKEN_KRL_HANDLE)
   1214                        ? LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr)
   1215                        : LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr));
   1216        case CKA_SUBJECT:
   1217            return lg_CopyAttribute(attribute, type, obj->dbKey.data,
   1218                                    obj->dbKey.len);
   1219        case CKA_NSS_URL:
   1220        case CKA_VALUE:
   1221            break;
   1222        default:
   1223            return lg_invalidAttribute(attribute);
   1224    }
   1225    crl = lg_getCrl(obj);
   1226    if (!crl) {
   1227        return CKR_OBJECT_HANDLE_INVALID;
   1228    }
   1229    switch (type) {
   1230        case CKA_NSS_URL:
   1231            if (crl->url == NULL) {
   1232                return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
   1233            }
   1234            return lg_CopyAttribute(attribute, type, crl->url,
   1235                                    PORT_Strlen(crl->url) + 1);
   1236        case CKA_VALUE:
   1237            return lg_CopyAttribute(attribute, type, crl->derCrl.data,
   1238                                    crl->derCrl.len);
   1239        default:
   1240            break;
   1241    }
   1242    return lg_invalidAttribute(attribute);
   1243 }
   1244 
   1245 static CK_RV
   1246 lg_FindCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1247                     CK_ATTRIBUTE *attribute)
   1248 {
   1249    NSSLOWCERTCertificate *cert;
   1250    NSSLOWCERTCertDBHandle *certHandle;
   1251    NSSLOWKEYPublicKey *pubKey;
   1252    unsigned char hash[SHA1_LENGTH];
   1253    SECItem *item;
   1254 
   1255    switch (type) {
   1256        case CKA_PRIVATE:
   1257            return LG_CLONE_ATTR(attribute, type, lg_StaticFalseAttr);
   1258        case CKA_MODIFIABLE:
   1259            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
   1260        case CKA_CERTIFICATE_TYPE:
   1261            /* hardcoding X.509 into here */
   1262            return lg_ULongAttribute(attribute, type, CKC_X_509);
   1263        case CKA_VALUE:
   1264        case CKA_ID:
   1265        case CKA_LABEL:
   1266        case CKA_SUBJECT:
   1267        case CKA_ISSUER:
   1268        case CKA_SERIAL_NUMBER:
   1269        case CKA_NSS_EMAIL:
   1270            break;
   1271        default:
   1272            return lg_invalidAttribute(attribute);
   1273    }
   1274 
   1275    certHandle = lg_getCertDB(obj->sdb);
   1276    if (certHandle == NULL) {
   1277        return CKR_OBJECT_HANDLE_INVALID;
   1278    }
   1279 
   1280    cert = lg_getCert(obj, certHandle);
   1281    if (cert == NULL) {
   1282        return CKR_OBJECT_HANDLE_INVALID;
   1283    }
   1284    switch (type) {
   1285        case CKA_VALUE:
   1286            return lg_CopyAttribute(attribute, type, cert->derCert.data,
   1287                                    cert->derCert.len);
   1288        case CKA_ID:
   1289            if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
   1290                ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
   1291                ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
   1292                return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
   1293            }
   1294            pubKey = nsslowcert_ExtractPublicKey(cert);
   1295            if (pubKey == NULL)
   1296                break;
   1297            item = lg_GetPubItem(pubKey);
   1298            if (item == NULL) {
   1299                lg_nsslowkey_DestroyPublicKey(pubKey);
   1300                break;
   1301            }
   1302            SHA1_HashBuf(hash, item->data, item->len);
   1303            /* item is imbedded in pubKey, just free the key */
   1304            lg_nsslowkey_DestroyPublicKey(pubKey);
   1305            return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH);
   1306        case CKA_LABEL:
   1307            return cert->nickname
   1308                       ? lg_CopyAttribute(attribute, type, cert->nickname,
   1309                                          PORT_Strlen(cert->nickname))
   1310                       : LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
   1311        case CKA_SUBJECT:
   1312            return lg_CopyAttribute(attribute, type, cert->derSubject.data,
   1313                                    cert->derSubject.len);
   1314        case CKA_ISSUER:
   1315            return lg_CopyAttribute(attribute, type, cert->derIssuer.data,
   1316                                    cert->derIssuer.len);
   1317        case CKA_SERIAL_NUMBER:
   1318            return lg_CopyAttribute(attribute, type, cert->derSN.data,
   1319                                    cert->derSN.len);
   1320        case CKA_NSS_EMAIL:
   1321            return (cert->emailAddr && cert->emailAddr[0])
   1322                       ? lg_CopyAttribute(attribute, type, cert->emailAddr,
   1323                                          PORT_Strlen(cert->emailAddr))
   1324                       : LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
   1325        default:
   1326            break;
   1327    }
   1328    return lg_invalidAttribute(attribute);
   1329 }
   1330 
   1331 CK_RV
   1332 lg_GetSingleAttribute(LGObjectCache *obj, CK_ATTRIBUTE *attribute)
   1333 {
   1334    /* handle the common ones */
   1335    CK_ATTRIBUTE_TYPE type = attribute->type;
   1336    switch (type) {
   1337        case CKA_CLASS:
   1338            return lg_ULongAttribute(attribute, type, obj->objclass);
   1339        case CKA_TOKEN:
   1340            return LG_CLONE_ATTR(attribute, type, lg_StaticTrueAttr);
   1341        case CKA_LABEL:
   1342            if ((obj->objclass == CKO_CERTIFICATE) ||
   1343                (obj->objclass == CKO_PRIVATE_KEY) ||
   1344                (obj->objclass == CKO_PUBLIC_KEY) ||
   1345                (obj->objclass == CKO_SECRET_KEY)) {
   1346                break;
   1347            }
   1348            return LG_CLONE_ATTR(attribute, type, lg_StaticNullAttr);
   1349        default:
   1350            break;
   1351    }
   1352    switch (obj->objclass) {
   1353        case CKO_CERTIFICATE:
   1354            return lg_FindCertAttribute(obj, type, attribute);
   1355        case CKO_NSS_CRL:
   1356            return lg_FindCrlAttribute(obj, type, attribute);
   1357        case CKO_NSS_TRUST:
   1358        case CKO_TRUST:
   1359            return lg_FindTrustAttribute(obj, type, attribute);
   1360        case CKO_NSS_SMIME:
   1361            return lg_FindSMIMEAttribute(obj, type, attribute);
   1362        case CKO_PUBLIC_KEY:
   1363            return lg_FindPublicKeyAttribute(obj, type, attribute);
   1364        case CKO_PRIVATE_KEY:
   1365            return lg_FindPrivateKeyAttribute(obj, type, attribute);
   1366        case CKO_SECRET_KEY:
   1367            return lg_FindSecretKeyAttribute(obj, type, attribute);
   1368        default:
   1369            break;
   1370    }
   1371    return lg_invalidAttribute(attribute);
   1372 }
   1373 
   1374 /*
   1375 * Fill in the attribute template based on the data in the database.
   1376 */
   1377 CK_RV
   1378 lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *templ,
   1379                     CK_ULONG count)
   1380 {
   1381    LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
   1382    CK_RV crv, crvCollect = CKR_OK;
   1383    unsigned int i;
   1384 
   1385    if (obj == NULL) {
   1386        return CKR_OBJECT_HANDLE_INVALID;
   1387    }
   1388 
   1389    for (i = 0; i < count; i++) {
   1390        crv = lg_GetSingleAttribute(obj, &templ[i]);
   1391        if (crvCollect == CKR_OK)
   1392            crvCollect = crv;
   1393    }
   1394 
   1395    lg_DestroyObjectCache(obj);
   1396    return crvCollect;
   1397 }
   1398 
   1399 PRBool
   1400 lg_cmpAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attribute)
   1401 {
   1402    unsigned char buf[LG_BUF_SPACE];
   1403    CK_ATTRIBUTE testAttr;
   1404    unsigned char *tempBuf = NULL;
   1405    PRBool match = PR_TRUE;
   1406    CK_RV crv;
   1407 
   1408    /* we're going to compare 'attribute' with the actual attribute from
   1409     * the object. We'll use the length of 'attribute' to decide how much
   1410     * space we need to read the test attribute. If 'attribute' doesn't give
   1411     * enough space, then we know the values don't match and that will
   1412     * show up as ckr != CKR_OK */
   1413    testAttr = *attribute;
   1414    testAttr.pValue = buf;
   1415 
   1416    /* if we don't have enough space, malloc it */
   1417    if (attribute->ulValueLen > LG_BUF_SPACE) {
   1418        tempBuf = PORT_Alloc(attribute->ulValueLen);
   1419        if (!tempBuf) {
   1420            return PR_FALSE;
   1421        }
   1422        testAttr.pValue = tempBuf;
   1423    }
   1424 
   1425    /* get the attribute */
   1426    crv = lg_GetSingleAttribute(obj, &testAttr);
   1427    /* if the attribute was read OK, compare it */
   1428    if ((crv != CKR_OK) ||
   1429        (attribute->pValue == NULL) ||
   1430        (attribute->ulValueLen != testAttr.ulValueLen) ||
   1431        (PORT_Memcmp(attribute->pValue, testAttr.pValue, testAttr.ulValueLen) != 0)) {
   1432        /* something didn't match, this isn't the object we are looking for */
   1433        match = PR_FALSE;
   1434    }
   1435    /* free the buffer we may have allocated */
   1436    if (tempBuf) {
   1437        PORT_Free(tempBuf);
   1438    }
   1439    return match;
   1440 }
   1441 
   1442 PRBool
   1443 lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class,
   1444              const CK_ATTRIBUTE *templ, CK_ULONG count)
   1445 {
   1446    PRBool match = PR_TRUE;
   1447    LGObjectCache *obj = lg_NewObjectCache(sdb, dbKey, class);
   1448    unsigned int i;
   1449 
   1450    if (obj == NULL) {
   1451        return PR_FALSE;
   1452    }
   1453 
   1454    for (i = 0; i < count; i++) {
   1455        match = lg_cmpAttribute(obj, &templ[i]);
   1456        if (!match) {
   1457            break;
   1458        }
   1459    }
   1460 
   1461    /* done looking, free up our cache */
   1462    lg_DestroyObjectCache(obj);
   1463 
   1464    /* if we get through the whole list without finding a mismatched attribute,
   1465     * then this object fits the criteria we are matching */
   1466    return match;
   1467 }
   1468 
   1469 static CK_RV
   1470 lg_SetCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1471                    const void *value, unsigned int len)
   1472 {
   1473    NSSLOWCERTCertificate *cert;
   1474    NSSLOWCERTCertDBHandle *certHandle;
   1475    char *nickname = NULL;
   1476    SECStatus rv;
   1477    CK_RV crv;
   1478 
   1479    /* we can't change  the EMAIL values, but let the
   1480     * upper layers feel better about the fact we tried to set these */
   1481    if (type == CKA_NSS_EMAIL) {
   1482        return CKR_OK;
   1483    }
   1484 
   1485    certHandle = lg_getCertDB(obj->sdb);
   1486    if (certHandle == NULL) {
   1487        crv = CKR_TOKEN_WRITE_PROTECTED;
   1488        goto done;
   1489    }
   1490 
   1491    if ((type != CKA_LABEL) && (type != CKA_ID)) {
   1492        crv = CKR_ATTRIBUTE_READ_ONLY;
   1493        goto done;
   1494    }
   1495 
   1496    cert = lg_getCert(obj, certHandle);
   1497    if (cert == NULL) {
   1498        crv = CKR_OBJECT_HANDLE_INVALID;
   1499        goto done;
   1500    }
   1501 
   1502    /* if the app is trying to set CKA_ID, it's probably because it just
   1503     * imported the key. Look to see if we need to set the CERTDB_USER bits.
   1504     */
   1505    if (type == CKA_ID) {
   1506        if (((cert->trust->sslFlags & CERTDB_USER) == 0) &&
   1507            ((cert->trust->emailFlags & CERTDB_USER) == 0) &&
   1508            ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) {
   1509            NSSLOWKEYDBHandle *keyHandle;
   1510 
   1511            keyHandle = lg_getKeyDB(obj->sdb);
   1512            if (keyHandle) {
   1513                if (nsslowkey_KeyForCertExists(keyHandle, cert)) {
   1514                    NSSLOWCERTCertTrust trust = *cert->trust;
   1515                    trust.sslFlags |= CERTDB_USER;
   1516                    trust.emailFlags |= CERTDB_USER;
   1517                    trust.objectSigningFlags |= CERTDB_USER;
   1518                    nsslowcert_ChangeCertTrust(certHandle, cert, &trust);
   1519                }
   1520            }
   1521        }
   1522        crv = CKR_OK;
   1523        goto done;
   1524    }
   1525 
   1526    /* must be CKA_LABEL */
   1527    if (value != NULL) {
   1528        nickname = PORT_ZAlloc(len + 1);
   1529        if (nickname == NULL) {
   1530            crv = CKR_HOST_MEMORY;
   1531            goto done;
   1532        }
   1533        PORT_Memcpy(nickname, value, len);
   1534        nickname[len] = 0;
   1535    }
   1536    rv = nsslowcert_AddPermNickname(certHandle, cert, nickname);
   1537    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1538 
   1539 done:
   1540    if (nickname) {
   1541        PORT_Free(nickname);
   1542    }
   1543    return crv;
   1544 }
   1545 
   1546 static CK_RV
   1547 lg_SetPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1548                          const void *value, unsigned int len,
   1549                          PRBool *writePrivate)
   1550 {
   1551    NSSLOWKEYPrivateKey *privKey;
   1552    NSSLOWKEYDBHandle *keyHandle;
   1553    char *nickname = NULL;
   1554    SECStatus rv;
   1555    CK_RV crv;
   1556 
   1557    /* we can't change the ID and we don't store the subject, but let the
   1558     * upper layers feel better about the fact we tried to set these */
   1559    if ((type == CKA_ID) || (type == CKA_SUBJECT) ||
   1560        (type == CKA_LOCAL) || (type == CKA_NEVER_EXTRACTABLE) ||
   1561        (type == CKA_ALWAYS_SENSITIVE)) {
   1562        return CKR_OK;
   1563    }
   1564 
   1565    keyHandle = lg_getKeyDB(obj->sdb);
   1566    if (keyHandle == NULL) {
   1567        crv = CKR_TOKEN_WRITE_PROTECTED;
   1568        goto done;
   1569    }
   1570 
   1571    privKey = lg_GetPrivateKeyWithDB(obj, keyHandle);
   1572    if (privKey == NULL) {
   1573        crv = CKR_OBJECT_HANDLE_INVALID;
   1574        goto done;
   1575    }
   1576 
   1577    crv = CKR_ATTRIBUTE_READ_ONLY;
   1578    switch (type) {
   1579        case CKA_LABEL:
   1580            if (value != NULL) {
   1581                nickname = PORT_ZAlloc(len + 1);
   1582                if (nickname == NULL) {
   1583                    crv = CKR_HOST_MEMORY;
   1584                    goto done;
   1585                }
   1586                PORT_Memcpy(nickname, value, len);
   1587                nickname[len] = 0;
   1588            }
   1589            rv = nsslowkey_UpdateNickname(keyHandle, privKey, &obj->dbKey,
   1590                                          nickname, obj->sdb);
   1591            crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1592            break;
   1593        case CKA_UNWRAP:
   1594        case CKA_SIGN:
   1595        case CKA_DERIVE:
   1596        case CKA_SIGN_RECOVER:
   1597        case CKA_DECRYPT:
   1598            /* ignore attempts to change restrict these.
   1599             * legacyDB ignore these flags and always presents all of them
   1600             * that are valid as true.
   1601             * NOTE: We only get here if the current value and the new value do
   1602             * not match. */
   1603            if (*(char *)value == 0) {
   1604                crv = CKR_OK;
   1605            }
   1606            break;
   1607        case CKA_VALUE:
   1608        case CKA_PRIVATE_EXPONENT:
   1609        case CKA_PRIME_1:
   1610        case CKA_PRIME_2:
   1611        case CKA_EXPONENT_1:
   1612        case CKA_EXPONENT_2:
   1613        case CKA_COEFFICIENT:
   1614            /* We aren't really changing these values, we are just triggering
   1615             * the database to update it's entry */
   1616            *writePrivate = PR_TRUE;
   1617            crv = CKR_OK;
   1618            break;
   1619        default:
   1620            crv = CKR_ATTRIBUTE_READ_ONLY;
   1621            break;
   1622    }
   1623 done:
   1624    if (nickname) {
   1625        PORT_Free(nickname);
   1626    }
   1627    return crv;
   1628 }
   1629 
   1630 static CK_RV
   1631 lg_SetPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type,
   1632                         const void *value, unsigned int len,
   1633                         PRBool *writePrivate)
   1634 {
   1635    /* we can't change the ID and we don't store the subject, but let the
   1636     * upper layers feel better about the fact we tried to set these */
   1637    if ((type == CKA_ID) || (type == CKA_SUBJECT) || (type == CKA_LABEL)) {
   1638        return CKR_OK;
   1639    }
   1640    return CKR_ATTRIBUTE_READ_ONLY;
   1641 }
   1642 
   1643 static CK_RV
   1644 lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr)
   1645 {
   1646    unsigned int flags;
   1647    CK_TRUST trust;
   1648    NSSLOWCERTCertificate *cert = NULL;
   1649    NSSLOWCERTCertDBHandle *certHandle;
   1650    NSSLOWCERTCertTrust dbTrust;
   1651    SECStatus rv;
   1652    CK_RV crv;
   1653 
   1654    if (attr->type == CKA_LABEL) {
   1655        return CKR_OK;
   1656    }
   1657 
   1658    crv = lg_GetULongAttribute(attr->type, attr, 1, &trust);
   1659    if (crv != CKR_OK) {
   1660        return crv;
   1661    }
   1662    flags = lg_MapTrust(trust, (PRBool)((attr->type == CKA_NSS_TRUST_CLIENT_AUTH) ||
   1663                                        (attr->type == CKA_PKCS_TRUST_CLIENT_AUTH)));
   1664 
   1665    certHandle = lg_getCertDB(obj->sdb);
   1666 
   1667    if (certHandle == NULL) {
   1668        crv = CKR_TOKEN_WRITE_PROTECTED;
   1669        goto done;
   1670    }
   1671 
   1672    cert = lg_getCert(obj, certHandle);
   1673    if (cert == NULL) {
   1674        crv = CKR_OBJECT_HANDLE_INVALID;
   1675        goto done;
   1676    }
   1677    dbTrust = *cert->trust;
   1678 
   1679    switch (attr->type) {
   1680        case CKA_TRUST_EMAIL_PROTECTION:
   1681            dbTrust.emailFlags = flags |
   1682                                 (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS);
   1683            break;
   1684        case CKA_TRUST_CODE_SIGNING:
   1685            dbTrust.objectSigningFlags = flags |
   1686                                         (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS);
   1687            break;
   1688        case CKA_TRUST_CLIENT_AUTH:
   1689            dbTrust.sslFlags = flags | (cert->trust->sslFlags &
   1690                                        (CERTDB_PRESERVE_TRUST_BITS | CERTDB_TRUSTED_CA));
   1691            break;
   1692        case CKA_TRUST_SERVER_AUTH:
   1693            dbTrust.sslFlags = flags | (cert->trust->sslFlags &
   1694                                        (CERTDB_PRESERVE_TRUST_BITS | CERTDB_TRUSTED_CLIENT_CA));
   1695            break;
   1696        default:
   1697            crv = CKR_ATTRIBUTE_READ_ONLY;
   1698            goto done;
   1699    }
   1700 
   1701    rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust);
   1702    crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR;
   1703 done:
   1704    if (cert) {
   1705        nsslowcert_DestroyCertificate(cert);
   1706    }
   1707    return crv;
   1708 }
   1709 
   1710 static CK_RV
   1711 lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr,
   1712                      PRBool *writePrivate)
   1713 {
   1714    CK_ATTRIBUTE attribLocal;
   1715    CK_RV crv;
   1716 
   1717    if ((attr->type == CKA_NSS_DB) && (obj->objclass == CKO_PRIVATE_KEY)) {
   1718        *writePrivate = PR_TRUE;
   1719        return CKR_OK;
   1720    }
   1721 
   1722    /* Make sure the attribute exists first */
   1723    attribLocal.type = attr->type;
   1724    attribLocal.pValue = NULL;
   1725    attribLocal.ulValueLen = 0;
   1726    crv = lg_GetSingleAttribute(obj, &attribLocal);
   1727    if (crv != CKR_OK) {
   1728        return crv;
   1729    }
   1730 
   1731    /* if we are just setting it to the value we already have,
   1732     * allow it to happen. Let label setting go through so
   1733     * we have the opportunity to repair any database corruption. */
   1734    if (attr->type != CKA_LABEL) {
   1735        if (lg_cmpAttribute(obj, attr)) {
   1736            return CKR_OK;
   1737        }
   1738    }
   1739 
   1740    crv = CKR_ATTRIBUTE_READ_ONLY;
   1741    switch (obj->objclass) {
   1742        case CKO_CERTIFICATE:
   1743            /* change NICKNAME, EMAIL,  */
   1744            crv = lg_SetCertAttribute(obj, attr->type,
   1745                                      attr->pValue, attr->ulValueLen);
   1746            break;
   1747        case CKO_NSS_CRL:
   1748            /* change URL */
   1749            break;
   1750        case CKO_NSS_TRUST:
   1751        case CKO_TRUST:
   1752            crv = lg_SetTrustAttribute(obj, attr);
   1753            break;
   1754        case CKO_PRIVATE_KEY:
   1755        case CKO_SECRET_KEY:
   1756            crv = lg_SetPrivateKeyAttribute(obj, attr->type,
   1757                                            attr->pValue, attr->ulValueLen, writePrivate);
   1758            break;
   1759        case CKO_PUBLIC_KEY:
   1760            crv = lg_SetPublicKeyAttribute(obj, attr->type,
   1761                                           attr->pValue, attr->ulValueLen, writePrivate);
   1762            break;
   1763    }
   1764    return crv;
   1765 }
   1766 
   1767 /*
   1768 * Fill in the attribute template based on the data in the database.
   1769 */
   1770 CK_RV
   1771 lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle,
   1772                     const CK_ATTRIBUTE *templ, CK_ULONG count)
   1773 {
   1774    LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK);
   1775    CK_RV crv, crvCollect = CKR_OK;
   1776    PRBool writePrivate = PR_FALSE;
   1777    unsigned int i;
   1778 
   1779    if (obj == NULL) {
   1780        return CKR_OBJECT_HANDLE_INVALID;
   1781    }
   1782 
   1783    for (i = 0; i < count; i++) {
   1784        crv = lg_SetSingleAttribute(obj, &templ[i], &writePrivate);
   1785        if (crvCollect == CKR_OK)
   1786            crvCollect = crv;
   1787    }
   1788 
   1789    /* Write any collected changes out for private and secret keys.
   1790     *  don't do the write for just the label */
   1791    if (writePrivate) {
   1792        NSSLOWKEYPrivateKey *privKey = lg_GetPrivateKey(obj);
   1793        SECStatus rv = SECFailure;
   1794        char *label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey);
   1795 
   1796        if (privKey) {
   1797            rv = nsslowkey_StoreKeyByPublicKeyAlg(lg_getKeyDB(sdb), privKey,
   1798                                                  &obj->dbKey, label, sdb, PR_TRUE);
   1799        }
   1800        if (rv != SECSuccess) {
   1801            crv = CKR_DEVICE_ERROR;
   1802        }
   1803        PORT_Free(label);
   1804    }
   1805 
   1806    lg_DestroyObjectCache(obj);
   1807    return crvCollect;
   1808 }