Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Firefox/security/nss/lib/dev/   (Firefox Browser Version 153.0.1©)  Datei vom 27.6.2026 mit Größe 30 kB image not shown  

Quelle  devutil.c   Sprache: C

 

/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */


#ifndef DEVM_H
#include "devm.h"
#endif /* DEVM_H */

#ifndef CKHELPER_H
#include "ckhelper.h"
#endif /* CKHELPER_H */

#include "pk11pub.h"
#include "dev3hack.h"
#include "secerr.h"

NSS_IMPLEMENT nssCryptokiObject *
nssCryptokiObject_Create(
    NSSToken *t,
    nssSession *session,
    CK_OBJECT_HANDLE h)
{
    PRStatus status;
    NSSSlot *slot;
    nssCryptokiObject *object;
    CK_BBOOL *isTokenObject;
    CK_ATTRIBUTE cert_template[] = {
        { CKA_TOKEN, NULL, 0 },
        { CKA_LABEL, NULL, 0 }
    };
    slot = nssToken_GetSlot(t);
    status = nssCKObject_GetAttributes(h, cert_template, 2,
                                       NULL, session, slot);
    nssSlot_Destroy(slot);
    if (status != PR_SUCCESS) {
        /* a failure here indicates a device error */
        return (nssCryptokiObject *)NULL;
    }
    if (cert_template[0].ulValueLen == 0 || !cert_template[0].pValue) {
        nss_ZFreeIf(cert_template[1].pValue);
        return (nssCryptokiObject *)NULL;
    }
    object = nss_ZNEW(NULL, nssCryptokiObject);
    if (!object) {
        nss_ZFreeIf(cert_template[0].pValue);
        nss_ZFreeIf(cert_template[1].pValue);
        return (nssCryptokiObject *)NULL;
    }
    object->handle = h;
    object->token = nssToken_AddRef(t);
    isTokenObject = (CK_BBOOL *)cert_template[0].pValue;
    object->isTokenObject = *isTokenObject;
    object->trustType = CKM_INVALID_MECHANISM;
    nss_ZFreeIf(cert_template[0].pValue);
    NSS_CK_ATTRIBUTE_TO_UTF8(&cert_template[1], object->label);
    return object;
}

NSS_IMPLEMENT void
nssCryptokiObject_Destroy(
    nssCryptokiObject *object)
{
    if (object) {
        (void)nssToken_Destroy(object->token);
        nss_ZFreeIf(object->label);
        nss_ZFreeIf(object);
    }
}

NSS_IMPLEMENT nssCryptokiObject *
nssCryptokiObject_Clone(
    nssCryptokiObject *object)
{
    nssCryptokiObject *rvObject;
    rvObject = nss_ZNEW(NULL, nssCryptokiObject);
    if (rvObject) {
        rvObject->handle = object->handle;
        rvObject->token = nssToken_AddRef(object->token);
        rvObject->isTokenObject = object->isTokenObject;
        if (object->label) {
            rvObject->label = nssUTF8_Duplicate(object->label, NULL);
        }
    }
    return rvObject;
}

NSS_EXTERN PRBool
nssCryptokiObject_Equal(
    nssCryptokiObject *o1,
    nssCryptokiObject *o2)
{
    return (o1->token == o2->token && o1->handle == o2->handle);
}

NSS_IMPLEMENT PRUint32
nssPKCS11String_Length(CK_CHAR *pkcs11Str, PRUint32 bufLen)
{
    PRInt32 i;
    for (i = bufLen - 1; i >= 0;) {
        if (pkcs11Str[i] != ' ' && pkcs11Str[i] != '\0')
            break;
        --i;
    }
    return (PRUint32)(i + 1);
}

/*
 * Slot arrays
 */


NSS_IMPLEMENT NSSSlot **
nssSlotArray_Clone(
    NSSSlot **slots)
{
    NSSSlot **rvSlots = NULL;
    NSSSlot **sp = slots;
    PRUint32 count = 0;
    while (sp && *sp)
        count++;
    if (count > 0) {
        rvSlots = nss_ZNEWARRAY(NULL, NSSSlot *, count + 1);
        if (rvSlots) {
            for (sp = slots, count = 0; *sp; sp++) {
                rvSlots[count++] = nssSlot_AddRef(*sp);
            }
        }
    }
    return rvSlots;
}

NSS_IMPLEMENT void
nssSlotArray_Destroy(
    NSSSlot **slots)
{
    if (slots) {
        NSSSlot **slotp;
        for (slotp = slots; *slotp; slotp++) {
            nssSlot_Destroy(*slotp);
        }
        nss_ZFreeIf(slots);
    }
}

NSS_IMPLEMENT void
NSSSlotArray_Destroy(
    NSSSlot **slots)
{
    nssSlotArray_Destroy(slots);
}

NSS_IMPLEMENT void
nssTokenArray_Destroy(
    NSSToken **tokens)
{
    if (tokens) {
        NSSToken **tokenp;
        for (tokenp = tokens; *tokenp; tokenp++) {
            (void)nssToken_Destroy(*tokenp);
        }
        nss_ZFreeIf(tokens);
    }
}

NSS_IMPLEMENT void
nssCryptokiObjectArray_Destroy(
    nssCryptokiObject **objects)
{
    if (objects) {
        nssCryptokiObject **op;
        for (op = objects; *op; op++) {
            nssCryptokiObject_Destroy(*op);
        }
        nss_ZFreeIf(objects);
    }
}

/* object cache for token */

typedef struct
{
    NSSArena *arena;
    nssCryptokiObject *object;
    CK_ATTRIBUTE_PTR attributes;
    CK_ULONG numAttributes;
} nssCryptokiObjectAndAttributes;

enum {
    cachedCerts = 0,
    cachedTrust = 1,
    cachedCRLs = 2
} cachedObjectType;

struct nssTokenObjectCacheStr {
    NSSToken *token;
    PRLock *lock;
    PRBool loggedIn;
    PRBool doObjectType[3];
    PRBool searchedObjectType[3];
    nssCryptokiObjectAndAttributes **objects[3];
};

NSS_IMPLEMENT nssTokenObjectCache *
nssTokenObjectCache_Create(
    NSSToken *token,
    PRBool cacheCerts,
    PRBool cacheTrust,
    PRBool cacheCRLs)
{
    nssTokenObjectCache *rvCache;
    rvCache = nss_ZNEW(NULL, nssTokenObjectCache);
    if (!rvCache) {
        goto loser;
    }
    rvCache->lock = PR_NewLock(); /* XXX */
    if (!rvCache->lock) {
        goto loser;
    }
    rvCache->doObjectType[cachedCerts] = cacheCerts;
    rvCache->doObjectType[cachedTrust] = cacheTrust;
    rvCache->doObjectType[cachedCRLs] = cacheCRLs;
    rvCache->token = token; /* cache goes away with token */
    return rvCache;
loser:
    nssTokenObjectCache_Destroy(rvCache);
    return (nssTokenObjectCache *)NULL;
}

static void
clear_cache(
    nssTokenObjectCache *cache)
{
    nssCryptokiObjectAndAttributes **oa;
    PRUint32 objectType;
    for (objectType = cachedCerts; objectType <= cachedCRLs; objectType++) {
        cache->searchedObjectType[objectType] = PR_FALSE;
        if (!cache->objects[objectType]) {
            continue;
        }
        for (oa = cache->objects[objectType]; *oa; oa++) {
            /* prevent the token from being destroyed */
            (*oa)->object->token = NULL;
            nssCryptokiObject_Destroy((*oa)->object);
            nssArena_Destroy((*oa)->arena);
        }
        nss_ZFreeIf(cache->objects[objectType]);
        cache->objects[objectType] = NULL;
    }
}

NSS_IMPLEMENT void
nssTokenObjectCache_Clear(
    nssTokenObjectCache *cache)
{
    if (cache) {
        PR_Lock(cache->lock);
        clear_cache(cache);
        PR_Unlock(cache->lock);
    }
}

NSS_IMPLEMENT void
nssTokenObjectCache_Destroy(
    nssTokenObjectCache *cache)
{
    if (cache) {
        clear_cache(cache);
        if (cache->lock) {
            PR_DestroyLock(cache->lock);
        }
        nss_ZFreeIf(cache);
    }
}

NSS_IMPLEMENT PRBool
nssTokenObjectCache_HaveObjectClass(
    nssTokenObjectCache *cache,
    CK_OBJECT_CLASS objclass)
{
    PRBool haveIt;
    PR_Lock(cache->lock);
    switch (objclass) {
        case CKO_CERTIFICATE:
            haveIt = cache->doObjectType[cachedCerts];
            break;
        case CKO_NSS_TRUST:
        case CKO_TRUST:
            haveIt = cache->doObjectType[cachedTrust];
            break;
        case CKO_NSS_CRL:
            haveIt = cache->doObjectType[cachedCRLs];
            break;
        default:
            haveIt = PR_FALSE;
    }
    PR_Unlock(cache->lock);
    return haveIt;
}

static nssCryptokiObjectAndAttributes **
create_object_array(
    nssCryptokiObject **objects,
    PRBool *doObjects,
    PRUint32 *numObjects,
    PRStatus *status)
{
    nssCryptokiObjectAndAttributes **rvOandA = NULL;
    *numObjects = 0;
    /* There are no objects for this type */
    if (!objects || !*objects) {
        *status = PR_SUCCESS;
        return rvOandA;
    }
    while (*objects++)
        (*numObjects)++;
    if (*numObjects >= MAX_LOCAL_CACHE_OBJECTS) {
        /* Hit the maximum allowed, so don't use a cache (there are
         * too many objects to make caching worthwhile, presumably, if
         * the token can handle that many objects, it can handle searching.
         */

        *doObjects = PR_FALSE;
        *status = PR_FAILURE;
        *numObjects = 0;
    } else {
        rvOandA = nss_ZNEWARRAY(NULL,
                                nssCryptokiObjectAndAttributes *,
                                *numObjects + 1);
        *status = rvOandA ? PR_SUCCESS : PR_FAILURE;
    }
    return rvOandA;
}

static nssCryptokiObjectAndAttributes *
create_object(
    nssCryptokiObject *object,
    const CK_ATTRIBUTE_TYPE *types,
    PRUint32 numTypes,
    PRStatus *status)
{
    PRUint32 j;
    NSSArena *arena = NULL;
    NSSSlot *slot = NULL;
    nssSession *session = NULL;
    nssCryptokiObjectAndAttributes *rvCachedObject = NULL;

    slot = nssToken_GetSlot(object->token);
    if (!slot) {
        nss_SetError(NSS_ERROR_INVALID_POINTER);
        goto loser;
    }
    session = nssToken_GetDefaultSession(object->token);
    if (!session) {
        nss_SetError(NSS_ERROR_INVALID_POINTER);
        goto loser;
    }
    arena = nssArena_Create();
    if (!arena) {
        goto loser;
    }
    rvCachedObject = nss_ZNEW(arena, nssCryptokiObjectAndAttributes);
    if (!rvCachedObject) {
        goto loser;
    }
    rvCachedObject->arena = arena;
    rvCachedObject->object = object;
    rvCachedObject->attributes = nss_ZNEWARRAY(arena, CK_ATTRIBUTE, numTypes);
    if (!rvCachedObject->attributes) {
        goto loser;
    }
    for (j = 0; j < numTypes; j++) {
        rvCachedObject->attributes[j].type = types[j];
    }
    *status = nssCKObject_GetAttributes(object->handle,
                                        rvCachedObject->attributes,
                                        numTypes,
                                        arena,
                                        session,
                                        slot);
    if (*status != PR_SUCCESS) {
        goto loser;
    }
    rvCachedObject->numAttributes = numTypes;
    *status = PR_SUCCESS;
    nssSlot_Destroy(slot);

    /* The cache is tied to the token, and therefore the objects in it should
     * not hold references to the token. Drop the object's token reference
     * only after success so that on failure the caller can still safely
     * destroy the object (and its token reference) exactly once.
     */

    (void)nssToken_Destroy(object->token);
    return rvCachedObject;
loser:
    *status = PR_FAILURE;
    if (slot) {
        nssSlot_Destroy(slot);
    }
    if (arena)
        nssArena_Destroy(arena);
    return (nssCryptokiObjectAndAttributes *)NULL;
}

/*
 *
 * State diagram for cache:
 *
 *            token !present            token removed
 *        +-------------------------+<----------------------+
 *        |                         ^                       |
 *        v                         |                       |
 *  +----------+   slot friendly    |  token present   +----------+
 *  |   cache  | -----------------> % ---------------> |   cache  |
 *  | unloaded |                                       |  loaded  |
 *  +----------+                                       +----------+
 *    ^   |                                                 ^   |
 *    |   |   slot !friendly           slot logged in       |   |
 *    |   +-----------------------> % ----------------------+   |
 *    |                             |                           |
 *    | slot logged out             v  slot !friendly           |
 *    +-----------------------------+<--------------------------+
 *
 */


/* This function must not be called with cache->lock locked. */
static PRBool
token_is_present(
    nssTokenObjectCache *cache)
{
    NSSSlot *slot = nssToken_GetSlot(cache->token);
    PRBool tokenPresent = nssSlot_IsTokenPresent(slot);
    nssSlot_Destroy(slot);
    return tokenPresent;
}

static PRBool
search_for_objects(
    nssTokenObjectCache *cache)
{
    PRBool doSearch = PR_FALSE;
    NSSSlot *slot = nssToken_GetSlot(cache->token);
    /* Handle non-friendly slots (slots which require login for objects) */
    if (!nssSlot_IsFriendly(slot)) {
        if (nssSlot_IsLoggedIn(slot)) {
            /* Either no state change, or went from !logged in -> logged in */
            cache->loggedIn = PR_TRUE;
            doSearch = PR_TRUE;
        } else {
            if (cache->loggedIn) {
                /* went from logged in -> !logged in, destroy cached objects */
                clear_cache(cache);
                cache->loggedIn = PR_FALSE;
            } /* else no state change, still not logged in, so exit */
        }
    } else {
        /* slot is friendly, thus always available for search */
        doSearch = PR_TRUE;
    }
    nssSlot_Destroy(slot);
    return doSearch;
}

static nssCryptokiObjectAndAttributes *
create_cert(
    nssCryptokiObject *object,
    PRStatus *status)
{
    static const CK_ATTRIBUTE_TYPE certAttr[] = {
        CKA_CLASS,
        CKA_TOKEN,
        CKA_LABEL,
        CKA_CERTIFICATE_TYPE,
        CKA_ID,
        CKA_VALUE,
        CKA_ISSUER,
        CKA_SERIAL_NUMBER,
        CKA_SUBJECT,
        CKA_NSS_EMAIL
    };
    static const PRUint32 numCertAttr = sizeof(certAttr) / sizeof(certAttr[0]);
    return create_object(object, certAttr, numCertAttr, status);
}

static nssCryptokiObjectAndAttributes *
create_trust(
    nssCryptokiObject *object,
    PRStatus *status)
{
    static const CK_ATTRIBUTE_TYPE nssTrustAttr[] = {
        CKA_CLASS,
        CKA_TOKEN,
        CKA_LABEL,
        CKA_NSS_CERT_SHA1_HASH,
        CKA_NSS_CERT_MD5_HASH,
        CKA_ISSUER,
        CKA_SUBJECT,
        CKA_NSS_TRUST_SERVER_AUTH,
        CKA_NSS_TRUST_CLIENT_AUTH,
        CKA_NSS_TRUST_EMAIL_PROTECTION,
        CKA_NSS_TRUST_CODE_SIGNING
    };
    static const CK_ATTRIBUTE_TYPE pkcsTrustAttr[] = {
        CKA_CLASS,
        CKA_TOKEN,
        CKA_LABEL,
        CKA_HASH_OF_CERTIFICATE,
        CKA_NAME_HASH_ALGORITHM,
        CKA_ISSUER,
        CKA_SUBJECT,
        CKA_PKCS_TRUST_SERVER_AUTH,
        CKA_PKCS_TRUST_CLIENT_AUTH,
        CKA_PKCS_TRUST_EMAIL_PROTECTION,
        CKA_PKCS_TRUST_CODE_SIGNING
    };
    static const PRUint32 numNSSTrustAttr = PR_ARRAY_SIZE(nssTrustAttr);
    static const PRUint32 numPKCSTrustAttr = PR_ARRAY_SIZE(pkcsTrustAttr);
    const CK_ATTRIBUTE_TYPE *trustAttr;
    PRUint32 numTrustAttr;

    trustAttr = (object->trustType == CKO_TRUST) ? pkcsTrustAttr
                                                 : nssTrustAttr;
    numTrustAttr = (object->trustType == CKO_TRUST) ? numPKCSTrustAttr
                                                    : numNSSTrustAttr;
    return create_object(object, trustAttr, numTrustAttr, status);
}

static nssCryptokiObjectAndAttributes *
create_crl(
    nssCryptokiObject *object,
    PRStatus *status)
{
    static const CK_ATTRIBUTE_TYPE crlAttr[] = {
        CKA_CLASS,
        CKA_TOKEN,
        CKA_LABEL,
        CKA_VALUE,
        CKA_SUBJECT,
        CKA_NSS_KRL,
        CKA_NSS_URL
    };
    static const PRUint32 numCRLAttr = sizeof(crlAttr) / sizeof(crlAttr[0]);
    return create_object(object, crlAttr, numCRLAttr, status);
}

/* Dispatch to the create function for the object type */
static nssCryptokiObjectAndAttributes *
create_object_of_type(
    nssCryptokiObject *object,
    PRUint32 objectType,
    PRStatus *status)
{
    if (objectType == cachedCerts) {
        return create_cert(object, status);
    }
    if (objectType == cachedTrust) {
        return create_trust(object, status);
    }
    if (objectType == cachedCRLs) {
        return create_crl(object, status);
    }
    return (nssCryptokiObjectAndAttributes *)NULL;
}

static PRStatus
get_token_objects_for_cache(
    nssTokenObjectCache *cache,
    PRUint32 objectType,
    CK_OBJECT_CLASS objclass)
{
    PRStatus status;
    nssCryptokiObject **objects;
    PRBool *doIt = &cache->doObjectType[objectType];
    PRUint32 i, numObjects;

    if (!search_for_objects(cache) ||
        cache->searchedObjectType[objectType] ||
        !cache->doObjectType[objectType]) {
        /* Either there was a state change that prevents a search
         * (token logged out), or the search was already done,
         * or objects of this type are not being cached.
         */

        return PR_SUCCESS;
    }
    objects = nssToken_FindObjects(cache->token, NULL, objclass,
                                   nssTokenSearchType_TokenForced,
                                   MAX_LOCAL_CACHE_OBJECTS, &status);
    if (status != PR_SUCCESS) {
        return status;
    }
    cache->objects[objectType] = create_object_array(objects,
                                                     doIt,
                                                     &numObjects,
                                                     &status);
    if (status != PR_SUCCESS) {
        nssCryptokiObjectArray_Destroy(objects);
        return status;
    }
    for (i = 0; i < numObjects; i++) {
        cache->objects[objectType][i] = create_object_of_type(objects[i],
                                                              objectType,
                                                              &status);
        if (status != PR_SUCCESS) {
            break;
        }
    }
    if (status == PR_SUCCESS) {
        nss_ZFreeIf(objects);
    } else {
        PRUint32 j;
        for (j = 0; j < i; j++) {
            /* Objects that were successfully added to the cache do not own a
             * token reference (they share a reference with the cache itself).
             * Nulling out the pointer here prevents the token's refcount
             * from being decremented in nssCryptokiObject_Destroy */

            cache->objects[objectType][j]->object->token = NULL;
            nssArena_Destroy(cache->objects[objectType][j]->arena);
        }
        nss_ZFreeIf(cache->objects[objectType]);
        cache->objects[objectType] = NULL;
        nssCryptokiObjectArray_Destroy(objects);
    }
    cache->searchedObjectType[objectType] = PR_TRUE;
    return status;
}

static CK_ATTRIBUTE_PTR
find_attribute_in_object(
    nssCryptokiObjectAndAttributes *obj,
    CK_ATTRIBUTE_TYPE attrType)
{
    PRUint32 j;
    for (j = 0; j < obj->numAttributes; j++) {
        if (attrType == obj->attributes[j].type) {
            return &obj->attributes[j];
        }
    }
    return (CK_ATTRIBUTE_PTR)NULL;
}

/* Find all objects in the array that match the supplied template */
static nssCryptokiObject **
find_objects_in_array(
    nssCryptokiObjectAndAttributes **objArray,
    CK_ATTRIBUTE_PTR ot,
    CK_ULONG otlen,
    PRUint32 maximumOpt)
{
    PRIntn oi = 0;
    PRUint32 i;
    NSSArena *arena;
    PRUint32 size = 8;
    PRUint32 numMatches = 0;
    nssCryptokiObject **objects = NULL;
    nssCryptokiObjectAndAttributes **matches = NULL;
    CK_ATTRIBUTE_PTR attr;

    if (!objArray) {
        return (nssCryptokiObject **)NULL;
    }
    arena = nssArena_Create();
    if (!arena) {
        return (nssCryptokiObject **)NULL;
    }
    matches = nss_ZNEWARRAY(arena, nssCryptokiObjectAndAttributes *, size);
    if (!matches) {
        goto loser;
    }
    if (maximumOpt == 0)
        maximumOpt = ~0;
    /* loop over the cached objects */
    for (; *objArray && numMatches < maximumOpt; objArray++) {
        nssCryptokiObjectAndAttributes *obj = *objArray;
        /* loop over the test template */
        for (i = 0; i < otlen; i++) {
            /* see if the object has the attribute */
            attr = find_attribute_in_object(obj, ot[i].type);
            if (!attr) {
                /* nope, match failed */
                break;
            }
            /* compare the attribute against the test value */
            if (ot[i].ulValueLen != attr->ulValueLen ||
                !nsslibc_memequal(ot[i].pValue,
                                  attr->pValue,
                                  attr->ulValueLen, NULL)) {
                /* nope, match failed */
                break;
            }
        }
        if (i == otlen) {
            /* all of the attributes in the test template were found
             * in the object's template, and they all matched
             */

            matches[numMatches++] = obj;
            if (numMatches == size) {
                size *= 2;
                matches = nss_ZREALLOCARRAY(matches,
                                            nssCryptokiObjectAndAttributes *,
                                            size);
                if (!matches) {
                    goto loser;
                }
            }
        }
    }
    if (numMatches > 0) {
        objects = nss_ZNEWARRAY(NULL, nssCryptokiObject *, numMatches + 1);
        if (!objects) {
            goto loser;
        }
        for (oi = 0; oi < (PRIntn)numMatches; oi++) {
            objects[oi] = nssCryptokiObject_Clone(matches[oi]->object);
            if (!objects[oi]) {
                goto loser;
            }
        }
    }
    nssArena_Destroy(arena);
    return objects;
loser:
    nssCryptokiObjectArray_Destroy(objects);
    nssArena_Destroy(arena);
    return (nssCryptokiObject **)NULL;
}

NSS_IMPLEMENT nssCryptokiObject **
nssTokenObjectCache_FindObjectsByTemplate(
    nssTokenObjectCache *cache,
    CK_OBJECT_CLASS objclass,
    CK_ATTRIBUTE_PTR otemplate,
    CK_ULONG otlen,
    PRUint32 maximumOpt,
    PRStatus *statusOpt)
{
    PRStatus status = PR_FAILURE;
    nssCryptokiObject **rvObjects = NULL;
    PRUint32 objectType;
    if (!token_is_present(cache)) {
        status = PR_SUCCESS;
        goto finish;
    }
    switch (objclass) {
        case CKO_CERTIFICATE:
            objectType = cachedCerts;
            break;
        case CKO_NSS_TRUST:
        case CKO_TRUST:
            objectType = cachedTrust;
            break;
        case CKO_NSS_CRL:
            objectType = cachedCRLs;
            break;
        default:
            goto finish;
    }
    PR_Lock(cache->lock);
    if (cache->doObjectType[objectType]) {
        status = get_token_objects_for_cache(cache, objectType, objclass);
        if (status == PR_SUCCESS) {
            rvObjects = find_objects_in_array(cache->objects[objectType],
                                              otemplate, otlen, maximumOpt);
        }
    }
    PR_Unlock(cache->lock);
finish:
    if (statusOpt) {
        *statusOpt = status;
    }
    return rvObjects;
}

static PRBool
cache_available_for_object_type(
    nssTokenObjectCache *cache,
    PRUint32 objectType)
{
    if (!cache->doObjectType[objectType]) {
        /* not caching this object kind */
        return PR_FALSE;
    }
    if (!cache->searchedObjectType[objectType]) {
        /* objects are not cached yet */
        return PR_FALSE;
    }
    if (!search_for_objects(cache)) {
        /* not logged in */
        return PR_FALSE;
    }
    return PR_TRUE;
}

NSS_IMPLEMENT PRStatus
nssTokenObjectCache_GetObjectAttributes(
    nssTokenObjectCache *cache,
    NSSArena *arenaOpt,
    nssCryptokiObject *object,
    CK_OBJECT_CLASS objclass,
    CK_ATTRIBUTE_PTR atemplate,
    CK_ULONG atlen)
{
    PRUint32 i, j;
    NSSArena *arena = NULL;
    nssArenaMark *mark = NULL;
    nssCryptokiObjectAndAttributes *cachedOA = NULL;
    nssCryptokiObjectAndAttributes **oa = NULL;
    PRUint32 objectType;
    if (!token_is_present(cache)) {
        return PR_FAILURE;
    }
    PR_Lock(cache->lock);
    switch (objclass) {
        case CKO_CERTIFICATE:
            objectType = cachedCerts;
            break;
        case CKO_NSS_TRUST:
        case CKO_TRUST:
            objectType = cachedTrust;
            break;
        case CKO_NSS_CRL:
            objectType = cachedCRLs;
            break;
        default:
            goto loser;
    }
    if (!cache_available_for_object_type(cache, objectType)) {
        goto loser;
    }
    oa = cache->objects[objectType];
    if (!oa) {
        goto loser;
    }
    for (; *oa; oa++) {
        if (nssCryptokiObject_Equal((*oa)->object, object)) {
            cachedOA = *oa;
            break;
        }
    }
    if (!cachedOA) {
        goto loser; /* don't have this object */
    }
    if (arenaOpt) {
        arena = arenaOpt;
        mark = nssArena_Mark(arena);
    }
    for (i = 0; i < atlen; i++) {
        for (j = 0; j < cachedOA->numAttributes; j++) {
            if (atemplate[i].type == cachedOA->attributes[j].type) {
                CK_ATTRIBUTE_PTR attr = &cachedOA->attributes[j];
                if (cachedOA->attributes[j].ulValueLen == 0 ||
                    cachedOA->attributes[j].ulValueLen == (CK_ULONG)-1) {
                    break; /* invalid attribute */
                }
                if (atemplate[i].ulValueLen > 0) {
                    if (atemplate[i].pValue == NULL ||
                        atemplate[i].ulValueLen < attr->ulValueLen) {
                        goto loser;
                    }
                } else {
                    atemplate[i].pValue = nss_ZAlloc(arena, attr->ulValueLen);
                    if (!atemplate[i].pValue) {
                        goto loser;
                    }
                }
                nsslibc_memcpy(atemplate[i].pValue,
                               attr->pValue, attr->ulValueLen);
                atemplate[i].ulValueLen = attr->ulValueLen;
                break;
            }
        }
        if (j == cachedOA->numAttributes) {
            atemplate[i].ulValueLen = (CK_ULONG)-1;
        }
    }
    PR_Unlock(cache->lock);
    if (mark) {
        nssArena_Unmark(arena, mark);
    }
    return PR_SUCCESS;
loser:
    PR_Unlock(cache->lock);
    if (mark) {
        nssArena_Release(arena, mark);
    }
    return PR_FAILURE;
}

NSS_IMPLEMENT PRStatus
nssTokenObjectCache_ImportObject(
    nssTokenObjectCache *cache,
    nssCryptokiObject *object,
    CK_OBJECT_CLASS objclass,
    CK_ATTRIBUTE_PTR ot,
    CK_ULONG otlen)
{
    PRStatus status = PR_SUCCESS;
    PRUint32 count;
    nssCryptokiObjectAndAttributes **oa, ***otype;
    PRUint32 objectType;
    PRBool haveIt = PR_FALSE;

    if (!token_is_present(cache)) {
        return PR_SUCCESS; /* cache not active, ignored */
    }
    PR_Lock(cache->lock);
    switch (objclass) {
        case CKO_CERTIFICATE:
            objectType = cachedCerts;
            break;
        case CKO_NSS_TRUST:
        case CKO_TRUST:
            objectType = cachedTrust;
            object->trustType = objclass;
            break;
        case CKO_NSS_CRL:
            objectType = cachedCRLs;
            break;
        default:
            PR_Unlock(cache->lock);
            return PR_SUCCESS; /* don't need to import it here */
    }
    if (!cache_available_for_object_type(cache, objectType)) {
        PR_Unlock(cache->lock);
        return PR_SUCCESS; /* cache not active, ignored */
    }
    count = 0;
    otype = &cache->objects[objectType]; /* index into array of types */
    oa = *otype;                         /* the array of objects for this type */
    while (oa && *oa) {
        if (nssCryptokiObject_Equal((*oa)->object, object)) {
            haveIt = PR_TRUE;
            break;
        }
        count++;
        oa++;
    }
    if (haveIt) {
        /* Destroy the old entry */
        (*oa)->object->token = NULL;
        nssCryptokiObject_Destroy((*oa)->object);
        nssArena_Destroy((*oa)->arena);
    } else {
        /* Create space for a new entry */
        if (count > 0) {
            *otype = nss_ZREALLOCARRAY(*otype,
                                       nssCryptokiObjectAndAttributes *,
                                       count + 2);
        } else {
            *otype = nss_ZNEWARRAY(NULL, nssCryptokiObjectAndAttributes *, 2);
        }
    }
    if (*otype) {
        nssCryptokiObject *copyObject = nssCryptokiObject_Clone(object);
        (*otype)[count] = create_object_of_type(copyObject, objectType,
                                                &status);
    } else {
        status = PR_FAILURE;
    }
    PR_Unlock(cache->lock);
    return status;
}

NSS_IMPLEMENT void
nssTokenObjectCache_RemoveObject(
    nssTokenObjectCache *cache,
    nssCryptokiObject *object)
{
    PRUint32 oType;
    nssCryptokiObjectAndAttributes **oa, **swp = NULL;
    if (!token_is_present(cache)) {
        return;
    }
    PR_Lock(cache->lock);
    for (oType = 0; oType < 3; oType++) {
        if (!cache_available_for_object_type(cache, oType) ||
            !cache->objects[oType]) {
            continue;
        }
        for (oa = cache->objects[oType]; *oa; oa++) {
            if (nssCryptokiObject_Equal((*oa)->object, object)) {
                swp = oa; /* the entry to remove */
                while (oa[1])
                    oa++; /* go to the tail */
                (*swp)->object->token = NULL;
                nssCryptokiObject_Destroy((*swp)->object);
                nssArena_Destroy((*swp)->arena); /* destroy it */
                *swp = *oa;                      /* swap the last with the removed */
                *oa = NULL;                      /* null-terminate the array */
                break;
            }
        }
        if (swp) {
            break;
        }
    }
    if ((oType < 3) &&
        cache->objects[oType] && cache->objects[oType][0] == NULL) {
        nss_ZFreeIf(cache->objects[oType]); /* no entries remaining */
        cache->objects[oType] = NULL;
    }
    PR_Unlock(cache->lock);
}

/* We need a general hash to support CKO_TRUST
** Replace the algorithm specific version used for
** CKA_CERT_SHA1_HASH and CKA_CERT_MD5_HASH attributes.
** CKA_HASH_OF_CERTIFICATE uses the mechanism specified
** in CKA_NAME_HASH_ALGORITHM, with can be passed to this
** function.
*/

/* XXX of course this doesn't belong here */
NSS_IMPLEMENT NSSAlgorithmAndParameters *
NSSAlgorithmAndParameters_CreateDigest(
    NSSArena *arenaOpt, CK_MECHANISM_TYPE hashMech)
{
    NSSAlgorithmAndParameters *rvAP = NULL;
    rvAP = nss_ZNEW(arenaOpt, NSSAlgorithmAndParameters);
    if (rvAP) {
        rvAP->mechanism.mechanism = hashMech;
        rvAP->mechanism.pParameter = NULL;
        rvAP->mechanism.ulParameterLen = 0;
    }
    return rvAP;
}

/*
 * we need a DigestBuf for both create and verify trust objects.
 * So put it here for now. We don't have any Stan based crypto operations
 * yet.
 */

NSS_IMPLEMENT PRStatus
NSSAlgorithm_DigestBuf(CK_MECHANISM_TYPE type, NSSItem *input, NSSItem *output)
{
    PRStatus ret = PR_FAILURE;
    NSSAlgorithmAndParameters *ap = NULL;
    PK11SlotInfo *internal = NULL;
    NSSToken *token = NULL;
    NSSItem *dummy = NULL;

    internal = PK11_GetInternalSlot();
    if (!internal) {
        goto done;
    }
    token = PK11Slot_GetNSSToken(internal);
    if (!token) {
        goto done;
    }
    ap = NSSAlgorithmAndParameters_CreateDigest(NULL, type);
    if (!token) {
        goto done;
    }

    dummy = nssToken_Digest(token, NULL, ap, input, output, NULL);
    if (dummy) {
        ret = PR_SUCCESS;
    }

done:
    nss_ZFreeIf(ap);
    if (token) {
        (void)nssToken_Destroy(token);
    }
    if (internal) {
        PK11_FreeSlot(internal);
    }
    return ret;
}

Messung V0.5 in Prozent
C=96 H=69 G=83

¤ Dauer der Verarbeitung: 0.14 Sekunden  (vorverarbeitet am  2026-09-27) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.