/* 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/. */ #include"secitem.h" #include"pkcs11.h" #include"lgdb.h" #include"lowkeyi.h" #include"pcert.h" #include"blapi.h"
#include"keydbi.h"
/* * This code maps PKCS #11 Finds to legacy database searches. This code * was orginally in pkcs11.c in previous versions of NSS.
*/
struct SDBFindStr {
CK_OBJECT_HANDLE *handles; int size; int index; int array_size;
};
/* * free a search structure
*/ void
lg_FreeSearch(SDBFind *search)
{ if (search->handles) {
PORT_Free(search->handles);
}
PORT_Free(search);
}
if (keyData->id->len == 0) { /* Make sure this isn't a LG_KEY */
privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle,
&tmpDBKey, keyData->sdb /*->password*/); if (privKey) { /* turn off the unneeded class flags */
classFlags &= isSecretKey(privKey) ? ~(LG_PRIVATE | LG_PUBLIC) : ~LG_KEY;
haveMatch = (PRBool)((classFlags & (LG_KEY | LG_PRIVATE | LG_PUBLIC)) != 0);
lg_nsslowkey_DestroyPrivateKey(privKey);
}
} else {
SHA1_HashBuf(hashKey, key->data, key->size); /* match id */
haveMatch = SECITEM_ItemsAreEqual(keyData->id, &result); if (!haveMatch && ((unsignedchar *)key->data)[0] == 0) { /* This is a fix for backwards compatibility. The key * database indexes private keys by the public key, and * versions of NSS prior to 3.4 stored the public key as * a signed integer. The public key is now treated as an * unsigned integer, with no leading zero. In order to * correctly compute the hash of an old key, it is necessary * to fallback and detect the leading zero.
*/
SHA1_HashBuf(hashKey,
(unsignedchar *)key->data + 1, key->size - 1);
haveMatch = SECITEM_ItemsAreEqual(keyData->id, &result);
}
} if (haveMatch) { if (classFlags & LG_PRIVATE) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV));
} if (classFlags & LG_PUBLIC) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB));
} if (classFlags & LG_KEY) {
lg_addHandle(keyData->searchHandles,
lg_mkHandle(sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
}
} return SECSuccess;
}
keyHandle = lg_getKeyDB(sdb); if (keyHandle == NULL) { return;
}
if (key_id->data) {
privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb); if (privKey) { if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_KEY));
found = PR_TRUE;
} if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_PRIV));
found = PR_TRUE;
} if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
lg_addHandle(search,
lg_mkHandle(sdb, key_id, LG_TOKEN_TYPE_PUB));
found = PR_TRUE;
}
lg_nsslowkey_DestroyPrivateKey(privKey);
} /* don't do the traversal if we have an up to date db */ if (keyHandle->version != 3) { goto loser;
} /* don't do the traversal if it can't possibly be the correct id */ /* all soft token id's are SHA1_HASH_LEN's */ if (key_id->len != SHA1_LENGTH) { goto loser;
} if (found) { /* if we already found some keys, don't do the traversal */ goto loser;
}
}
keyData.sdb = sdb;
keyData.keyHandle = keyHandle;
keyData.searchHandles = search;
keyData.id = key_id;
keyData.template = pTemplate;
keyData.templ_count = ulCount;
keyData.classFlags = classFlags;
keyData.strict = mustStrict ? mustStrict : LG_STRICT;
/* allocate more space if we need it. This should only happen in
* the general traversal case */ if (cd->cert_count >= cd->max_cert_count) { int size;
cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
size = cd->max_cert_count * sizeof(NSSLOWCERTCertificate *);
cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs, size); if (cd->certs == NULL) { return SECFailure;
}
}
nsslowcert_DestroyDBEntry((certDBEntry *)entry);
}
PORT_Free(tmp_name);
} else { /* we aren't filtering the certs, we are working on all, so turn
* on the strict filters. */
certData.strict = PR_TRUE;
lg_CertSetupData(&certData, LG_SEARCH_BLOCK_SIZE);
nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
}
/* * build the handles
*/ for (i = 0; i < certData.cert_count; i++) {
NSSLOWCERTCertificate *cert = certData.certs[i];
/* if we filtered it would have been on the stuff above */ if (classFlags & LG_CERT) {
lg_addHandle(handles,
lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_CERT));
} if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
lg_addHandle(handles,
lg_mkHandle(sdb, &cert->certKey, LG_TOKEN_TYPE_TRUST));
}
nsslowcert_DestroyCertificate(cert);
}
if (certData.certs)
PORT_Free(certData.certs); return;
}
/* * look for things to search on token objects for. If the right options * are specified, we can use them as direct indeces into the database * (rather than using linear searches. We can also use the attributes to * limit the kinds of objects we are searching for. Later we can use this * array to filter the remaining objects more finely.
*/ for (i = 0; classFlags && i < (int)ulCount; i++) {
switch (pTemplate[i].type) { case CKA_SUBJECT:
copy = &derSubject;
classFlags &= (LG_CERT | LG_PRIVATE | LG_PUBLIC | LG_SMIME | LG_CRL); break; case CKA_ISSUER:
copy = &issuerSN.derIssuer;
classFlags &= (LG_CERT | LG_TRUST); break; case CKA_SERIAL_NUMBER:
copy = &issuerSN.serialNumber;
classFlags &= (LG_CERT | LG_TRUST); break; case CKA_VALUE:
copy = &derCert;
classFlags &= (LG_CERT | LG_CRL | LG_SMIME); break; case CKA_LABEL:
copy = &name; break; case CKA_NSS_EMAIL:
copy = &email;
classFlags &= LG_SMIME | LG_CERT; break; case CKA_NSS_SMIME_TIMESTAMP:
classFlags &= LG_SMIME; break; case CKA_CLASS:
crv = lg_GetULongAttribute(CKA_CLASS, &pTemplate[i], 1, &objectClass); if (crv != CKR_OK) {
classFlags = 0; break;
} switch (objectClass) { case CKO_CERTIFICATE:
classFlags &= LG_CERT; break; case CKO_NSS_TRUST:
classFlags &= LG_TRUST; break; case CKO_NSS_CRL:
classFlags &= LG_CRL; break; case CKO_NSS_SMIME:
classFlags &= LG_SMIME; break; case CKO_PRIVATE_KEY:
classFlags &= LG_PRIVATE; break; case CKO_PUBLIC_KEY:
classFlags &= LG_PUBLIC; break; case CKO_SECRET_KEY:
classFlags &= LG_KEY; break; default:
classFlags = 0; break;
} break; case CKA_PRIVATE: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0; break;
} if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
classFlags &= (LG_PRIVATE | LG_KEY);
} else {
classFlags &= ~(LG_PRIVATE | LG_KEY);
} break; case CKA_SENSITIVE: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0; break;
} if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
classFlags &= (LG_PRIVATE | LG_KEY);
} else {
classFlags = 0;
} break; case CKA_TOKEN: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0; break;
} if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
classFlags = 0;
} break; case CKA_CERT_SHA1_HASH:
classFlags &= LG_TRUST;
copy = &cert_sha1_hash; break; case CKA_CERT_MD5_HASH:
classFlags &= LG_TRUST;
copy = &cert_md5_hash; break; case CKA_CERTIFICATE_TYPE:
crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE, &pTemplate[i],
1, &certType); if (crv != CKR_OK) {
classFlags = 0; break;
}
classFlags &= LG_CERT; if (certType != CKC_X_509) {
classFlags = 0;
} break; case CKA_ID:
copy = &key_id;
classFlags &= (LG_CERT | LG_PRIVATE | LG_KEY | LG_PUBLIC); break; case CKA_NSS_KRL: if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
classFlags = 0; break;
}
classFlags &= LG_CRL;
isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE); break; case CKA_MODIFIABLE: break; case CKA_KEY_TYPE: case CKA_DERIVE:
classFlags &= LG_PUBLIC | LG_PRIVATE | LG_KEY; break; case CKA_VERIFY_RECOVER:
classFlags &= LG_PUBLIC; break; case CKA_SIGN_RECOVER:
classFlags &= LG_PRIVATE; break; case CKA_ENCRYPT: case CKA_VERIFY: case CKA_WRAP:
classFlags &= LG_PUBLIC | LG_KEY; break; case CKA_DECRYPT: case CKA_SIGN: case CKA_UNWRAP: case CKA_ALWAYS_SENSITIVE: case CKA_EXTRACTABLE: case CKA_NEVER_EXTRACTABLE:
classFlags &= LG_PRIVATE | LG_KEY; break; /* can't be a certificate if it doesn't match one of the above
* attributes */ default:
classFlags = 0; break;
} if (copy) {
copy->data = (unsignedchar *)pTemplate[i].pValue;
copy->len = pTemplate[i].ulValueLen;
}
copy = NULL;
}
loser: if (search) {
lg_FreeSearch(search);
} return crv;
}
/* lg_FindObjects continues a search for token and session objects
* that match a template, obtaining additional object handles. */
CK_RV
lg_FindObjects(SDB *sdb, SDBFind *search,
CK_OBJECT_HANDLE *phObject, CK_ULONG ulMaxObjectCount,
CK_ULONG *pulObjectCount)
{ int transfer; int left;
*pulObjectCount = 0;
left = search->size - search->index;
transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount; if (transfer > 0) {
PORT_Memcpy(phObject, &search->handles[search->index],
transfer * sizeof(CK_OBJECT_HANDLE));
} else {
*phObject = CK_INVALID_HANDLE;
}
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.