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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/lib/softoken/legacydb/lgfind.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,915 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +#include "secitem.h"
     1.8 +#include "pkcs11.h"
     1.9 +#include "lgdb.h"
    1.10 +#include "lowkeyi.h"
    1.11 +#include "pcert.h"
    1.12 +#include "blapi.h"
    1.13 +
    1.14 +#include "keydbi.h" 
    1.15 +
    1.16 +/*
    1.17 + * This code maps PKCS #11 Finds to legacy database searches. This code
    1.18 + * was orginally in pkcs11.c in previous versions of NSS.
    1.19 + */
    1.20 +
    1.21 +struct SDBFindStr {
    1.22 +    CK_OBJECT_HANDLE    *handles;
    1.23 +    int                 size;
    1.24 +    int                 index;
    1.25 +    int                 array_size;
    1.26 +};
    1.27 +
    1.28 +
    1.29 +/*
    1.30 + * free a search structure
    1.31 + */
    1.32 +void
    1.33 +lg_FreeSearch(SDBFind *search)
    1.34 +{
    1.35 +    if (search->handles) {
    1.36 +	PORT_Free(search->handles);
    1.37 +    }
    1.38 +    PORT_Free(search);
    1.39 +}
    1.40 +
    1.41 +void
    1.42 +lg_addHandle(SDBFind *search, CK_OBJECT_HANDLE handle)
    1.43 +{
    1.44 +    if (search->handles == NULL) {
    1.45 +	return;
    1.46 +    }
    1.47 +    if (search->size >= search->array_size) {
    1.48 +	search->array_size += LG_SEARCH_BLOCK_SIZE;
    1.49 +	search->handles = (CK_OBJECT_HANDLE *) PORT_Realloc(search->handles,
    1.50 +				 sizeof(CK_OBJECT_HANDLE)* search->array_size);
    1.51 +	if (search->handles == NULL) {
    1.52 +	   return;
    1.53 +	}
    1.54 +    }
    1.55 +    search->handles[search->size] = handle;
    1.56 +    search->size++;
    1.57 +}
    1.58 +
    1.59 +/*
    1.60 + * find any certs that may match the template and load them.
    1.61 + */
    1.62 +#define LG_CERT 	0x00000001
    1.63 +#define LG_TRUST	0x00000002
    1.64 +#define LG_CRL		0x00000004
    1.65 +#define LG_SMIME	0x00000008
    1.66 +#define LG_PRIVATE	0x00000010
    1.67 +#define LG_PUBLIC	0x00000020
    1.68 +#define LG_KEY		0x00000040
    1.69 +
    1.70 +/*
    1.71 + * structure to collect key handles.
    1.72 + */
    1.73 +typedef struct lgEntryDataStr {
    1.74 +    SDB *sdb;
    1.75 +    SDBFind *searchHandles;
    1.76 +    const CK_ATTRIBUTE *template;
    1.77 +    CK_ULONG templ_count;
    1.78 +} lgEntryData;
    1.79 +
    1.80 +
    1.81 +static SECStatus
    1.82 +lg_crl_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
    1.83 +{
    1.84 +    lgEntryData *crlData;
    1.85 +    CK_OBJECT_HANDLE class_handle;
    1.86 +    SDB *sdb;
    1.87 +    
    1.88 +    crlData = (lgEntryData *)arg;
    1.89 +    sdb = crlData->sdb;
    1.90 +
    1.91 +    class_handle = (type == certDBEntryTypeRevocation) ? LG_TOKEN_TYPE_CRL :
    1.92 +							LG_TOKEN_KRL_HANDLE;
    1.93 +    if (lg_tokenMatch(sdb, key, class_handle,
    1.94 +			crlData->template, crlData->templ_count)) {
    1.95 +	lg_addHandle(crlData->searchHandles,
    1.96 +				 lg_mkHandle(sdb,key,class_handle));
    1.97 +    }
    1.98 +    return(SECSuccess);
    1.99 +}
   1.100 +
   1.101 +static void
   1.102 +lg_searchCrls(SDB *sdb, SECItem *derSubject, PRBool isKrl, 
   1.103 +		unsigned long classFlags, SDBFind *search,
   1.104 +		const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
   1.105 +{
   1.106 +    NSSLOWCERTCertDBHandle *certHandle = NULL;
   1.107 +
   1.108 +    certHandle = lg_getCertDB(sdb);
   1.109 +    if (certHandle == NULL) {
   1.110 +	return;
   1.111 +    }
   1.112 +    if (derSubject->data != NULL)  {
   1.113 +	certDBEntryRevocation *crl = 
   1.114 +	    nsslowcert_FindCrlByKey(certHandle, derSubject, isKrl);
   1.115 +
   1.116 +	if (crl != NULL) {
   1.117 +	    lg_addHandle(search, lg_mkHandle(sdb, derSubject,
   1.118 +		isKrl ? LG_TOKEN_KRL_HANDLE : LG_TOKEN_TYPE_CRL));
   1.119 +	    nsslowcert_DestroyDBEntry((certDBEntry *)crl);
   1.120 +	}
   1.121 +    } else {
   1.122 +	lgEntryData crlData;
   1.123 +
   1.124 +	/* traverse */
   1.125 +	crlData.sdb = sdb;
   1.126 +	crlData.searchHandles = search;
   1.127 +	crlData.template = pTemplate;
   1.128 +	crlData.templ_count = ulCount;
   1.129 +	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeRevocation,
   1.130 +		lg_crl_collect, (void *)&crlData);
   1.131 +	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeKeyRevocation,
   1.132 +		lg_crl_collect, (void *)&crlData);
   1.133 +    } 
   1.134 +}
   1.135 +
   1.136 +/*
   1.137 + * structure to collect key handles.
   1.138 + */
   1.139 +typedef struct lgKeyDataStr {
   1.140 +    SDB *sdb;
   1.141 +    NSSLOWKEYDBHandle *keyHandle;
   1.142 +    SDBFind *searchHandles;
   1.143 +    SECItem *id;
   1.144 +    const CK_ATTRIBUTE *template;
   1.145 +    CK_ULONG templ_count;
   1.146 +    unsigned long classFlags;
   1.147 +    PRBool strict;
   1.148 +} lgKeyData;
   1.149 +
   1.150 +static PRBool
   1.151 +isSecretKey(NSSLOWKEYPrivateKey *privKey)
   1.152 +{
   1.153 +  if (privKey->keyType == NSSLOWKEYRSAKey &&
   1.154 +                privKey->u.rsa.publicExponent.len == 1 &&
   1.155 +                                privKey->u.rsa.publicExponent.data[0] == 0)
   1.156 +    return PR_TRUE;
   1.157 +
   1.158 +  return PR_FALSE;
   1.159 +}
   1.160 +
   1.161 +
   1.162 +
   1.163 +static SECStatus
   1.164 +lg_key_collect(DBT *key, DBT *data, void *arg)
   1.165 +{
   1.166 +    lgKeyData *keyData;
   1.167 +    NSSLOWKEYPrivateKey *privKey = NULL;
   1.168 +    SECItem tmpDBKey;
   1.169 +    SDB *sdb;
   1.170 +    unsigned long classFlags;
   1.171 +    
   1.172 +    keyData = (lgKeyData *)arg;
   1.173 +    sdb = keyData->sdb;
   1.174 +    classFlags = keyData->classFlags;
   1.175 +
   1.176 +    tmpDBKey.data = key->data;
   1.177 +    tmpDBKey.len = key->size;
   1.178 +    tmpDBKey.type = siBuffer;
   1.179 +
   1.180 +    PORT_Assert(keyData->keyHandle);
   1.181 +    if (!keyData->strict && keyData->id && keyData->id->data) {
   1.182 +	SECItem result;
   1.183 +	PRBool haveMatch= PR_FALSE;
   1.184 +	unsigned char hashKey[SHA1_LENGTH];
   1.185 +	result.data = hashKey;
   1.186 +	result.len = sizeof(hashKey);
   1.187 +
   1.188 +	if (keyData->id->len == 0) {
   1.189 +	    /* Make sure this isn't a LG_KEY */
   1.190 +	    privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, 
   1.191 +					&tmpDBKey, keyData->sdb/*->password*/);
   1.192 +	    if (privKey) {
   1.193 +		/* turn off the unneeded class flags */
   1.194 +		classFlags &= isSecretKey(privKey) ?  ~(LG_PRIVATE|LG_PUBLIC) :
   1.195 +							~LG_KEY;
   1.196 +		haveMatch = (PRBool)
   1.197 +			((classFlags & (LG_KEY|LG_PRIVATE|LG_PUBLIC)) != 0);
   1.198 +		lg_nsslowkey_DestroyPrivateKey(privKey);
   1.199 +	    }
   1.200 +	} else {
   1.201 +	    SHA1_HashBuf( hashKey, key->data, key->size ); /* match id */
   1.202 +	    haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
   1.203 +	    if (!haveMatch && ((unsigned char *)key->data)[0] == 0) {
   1.204 +		/* This is a fix for backwards compatibility.  The key
   1.205 +		 * database indexes private keys by the public key, and
   1.206 +		 * versions of NSS prior to 3.4 stored the public key as
   1.207 +		 * a signed integer.  The public key is now treated as an
   1.208 +		 * unsigned integer, with no leading zero.  In order to
   1.209 +		 * correctly compute the hash of an old key, it is necessary
   1.210 +		 * to fallback and detect the leading zero.
   1.211 +		 */
   1.212 +		SHA1_HashBuf(hashKey, 
   1.213 +		             (unsigned char *)key->data + 1, key->size - 1);
   1.214 +		haveMatch = SECITEM_ItemsAreEqual(keyData->id,&result);
   1.215 +	    }
   1.216 +	}
   1.217 +	if (haveMatch) {
   1.218 +	    if (classFlags & LG_PRIVATE)  {
   1.219 +		lg_addHandle(keyData->searchHandles,
   1.220 +			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
   1.221 +	    }
   1.222 +	    if (classFlags & LG_PUBLIC) {
   1.223 +		lg_addHandle(keyData->searchHandles,
   1.224 +			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_PUB));
   1.225 +	    }
   1.226 +	    if (classFlags & LG_KEY) {
   1.227 +		lg_addHandle(keyData->searchHandles,
   1.228 +			lg_mkHandle(sdb,&tmpDBKey,LG_TOKEN_TYPE_KEY));
   1.229 +	    }
   1.230 +	}
   1.231 +	return SECSuccess;
   1.232 +    }
   1.233 +
   1.234 +    privKey = nsslowkey_FindKeyByPublicKey(keyData->keyHandle, &tmpDBKey, 
   1.235 +						 keyData->sdb/*->password*/);
   1.236 +    if ( privKey == NULL ) {
   1.237 +	goto loser;
   1.238 +    }
   1.239 +
   1.240 +    if (isSecretKey(privKey)) {
   1.241 +	if ((classFlags & LG_KEY) && 
   1.242 +		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY,
   1.243 +			keyData->template, keyData->templ_count)) {
   1.244 +	    lg_addHandle(keyData->searchHandles,
   1.245 +		lg_mkHandle(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_KEY));
   1.246 +	}
   1.247 +    } else {
   1.248 +	if ((classFlags & LG_PRIVATE) && 
   1.249 +		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PRIV,
   1.250 +			keyData->template, keyData->templ_count)) {
   1.251 +	    lg_addHandle(keyData->searchHandles,
   1.252 +		lg_mkHandle(keyData->sdb,&tmpDBKey,LG_TOKEN_TYPE_PRIV));
   1.253 +	}
   1.254 +	if ((classFlags & LG_PUBLIC) && 
   1.255 +		lg_tokenMatch(keyData->sdb, &tmpDBKey, LG_TOKEN_TYPE_PUB,
   1.256 +			keyData->template, keyData->templ_count)) {
   1.257 +	    lg_addHandle(keyData->searchHandles,
   1.258 +		lg_mkHandle(keyData->sdb, &tmpDBKey,LG_TOKEN_TYPE_PUB));
   1.259 +	}
   1.260 +    }
   1.261 +
   1.262 +loser:
   1.263 +    if ( privKey ) {
   1.264 +	lg_nsslowkey_DestroyPrivateKey(privKey);
   1.265 +    }
   1.266 +    return(SECSuccess);
   1.267 +}
   1.268 +
   1.269 +static void
   1.270 +lg_searchKeys(SDB *sdb, SECItem *key_id,
   1.271 +	unsigned long classFlags, SDBFind *search, PRBool mustStrict,
   1.272 +	const CK_ATTRIBUTE *pTemplate, CK_ULONG ulCount)
   1.273 +{
   1.274 +    NSSLOWKEYDBHandle *keyHandle = NULL;
   1.275 +    NSSLOWKEYPrivateKey *privKey;
   1.276 +    lgKeyData keyData;
   1.277 +    PRBool found = PR_FALSE;
   1.278 +
   1.279 +    keyHandle = lg_getKeyDB(sdb);
   1.280 +    if (keyHandle == NULL) {
   1.281 +	return;
   1.282 +    }
   1.283 +
   1.284 +    if (key_id->data) {
   1.285 +	privKey = nsslowkey_FindKeyByPublicKey(keyHandle, key_id, sdb);
   1.286 +	if (privKey) {
   1.287 +	    if ((classFlags & LG_KEY) && isSecretKey(privKey)) {
   1.288 +    	        lg_addHandle(search,
   1.289 +			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_KEY));
   1.290 +		found = PR_TRUE;
   1.291 +	    }
   1.292 +	    if ((classFlags & LG_PRIVATE) && !isSecretKey(privKey)) {
   1.293 +    	        lg_addHandle(search,
   1.294 +			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PRIV));
   1.295 +		found = PR_TRUE;
   1.296 +	    }
   1.297 +	    if ((classFlags & LG_PUBLIC) && !isSecretKey(privKey)) {
   1.298 +    	        lg_addHandle(search,
   1.299 +			lg_mkHandle(sdb,key_id,LG_TOKEN_TYPE_PUB));
   1.300 +		found = PR_TRUE;
   1.301 +	    }
   1.302 +    	    lg_nsslowkey_DestroyPrivateKey(privKey);
   1.303 +	}
   1.304 +	/* don't do the traversal if we have an up to date db */
   1.305 +	if (keyHandle->version != 3) {
   1.306 +	    goto loser;
   1.307 +	}
   1.308 +	/* don't do the traversal if it can't possibly be the correct id */
   1.309 +	/* all soft token id's are SHA1_HASH_LEN's */
   1.310 +	if (key_id->len != SHA1_LENGTH) {
   1.311 +	    goto loser;
   1.312 +	}
   1.313 +	if (found) {
   1.314 +	   /* if we already found some keys, don't do the traversal */
   1.315 +	   goto loser;
   1.316 +	}
   1.317 +    }
   1.318 +    keyData.sdb = sdb;
   1.319 +    keyData.keyHandle = keyHandle;
   1.320 +    keyData.searchHandles = search;
   1.321 +    keyData.id = key_id;
   1.322 +    keyData.template = pTemplate;
   1.323 +    keyData.templ_count = ulCount;
   1.324 +    keyData.classFlags = classFlags;
   1.325 +    keyData.strict = mustStrict ? mustStrict : LG_STRICT;
   1.326 +
   1.327 +    nsslowkey_TraverseKeys(keyHandle, lg_key_collect, &keyData);
   1.328 +
   1.329 +loser:
   1.330 +    return;
   1.331 +}
   1.332 +
   1.333 +/*
   1.334 + * structure to collect certs into
   1.335 + */
   1.336 +typedef struct lgCertDataStr {
   1.337 +    SDB *sdb;
   1.338 +    int cert_count;
   1.339 +    int max_cert_count;
   1.340 +    NSSLOWCERTCertificate **certs;
   1.341 +    const CK_ATTRIBUTE *template;
   1.342 +    CK_ULONG	templ_count;
   1.343 +    unsigned long classFlags;
   1.344 +    PRBool	strict;
   1.345 +} lgCertData;
   1.346 +
   1.347 +/*
   1.348 + * collect all the certs from the traverse call.
   1.349 + */	
   1.350 +static SECStatus
   1.351 +lg_cert_collect(NSSLOWCERTCertificate *cert,void *arg)
   1.352 +{
   1.353 +    lgCertData *cd = (lgCertData *)arg;
   1.354 +
   1.355 +    if (cert == NULL) {
   1.356 +	return SECSuccess;
   1.357 +    }
   1.358 +
   1.359 +    if (cd->certs == NULL) {
   1.360 +	return SECFailure;
   1.361 +    }
   1.362 +
   1.363 +    if (cd->strict) {
   1.364 +	if ((cd->classFlags & LG_CERT) && !lg_tokenMatch(cd->sdb,
   1.365 +	  &cert->certKey, LG_TOKEN_TYPE_CERT, cd->template,cd->templ_count)) {
   1.366 +	    return SECSuccess;
   1.367 +	}
   1.368 +	if ((cd->classFlags & LG_TRUST) && !lg_tokenMatch(cd->sdb,
   1.369 +	  &cert->certKey, LG_TOKEN_TYPE_TRUST, 
   1.370 +					     cd->template, cd->templ_count)) {
   1.371 +	    return SECSuccess;
   1.372 +	}
   1.373 +    }
   1.374 +
   1.375 +    /* allocate more space if we need it. This should only happen in
   1.376 +     * the general traversal case */
   1.377 +    if (cd->cert_count >= cd->max_cert_count) {
   1.378 +	int size;
   1.379 +	cd->max_cert_count += LG_SEARCH_BLOCK_SIZE;
   1.380 +	size = cd->max_cert_count * sizeof (NSSLOWCERTCertificate *);
   1.381 +	cd->certs = (NSSLOWCERTCertificate **)PORT_Realloc(cd->certs,size);
   1.382 +	if (cd->certs == NULL) {
   1.383 +	    return SECFailure;
   1.384 +	}
   1.385 +    }
   1.386 +
   1.387 +    cd->certs[cd->cert_count++] = nsslowcert_DupCertificate(cert);
   1.388 +    return SECSuccess;
   1.389 +}
   1.390 +
   1.391 +/* provide impedence matching ... */
   1.392 +static SECStatus
   1.393 +lg_cert_collect2(NSSLOWCERTCertificate *cert, SECItem *dymmy, void *arg)
   1.394 +{
   1.395 +    return lg_cert_collect(cert, arg);
   1.396 +}
   1.397 +
   1.398 +static void
   1.399 +lg_searchSingleCert(lgCertData *certData,NSSLOWCERTCertificate *cert)
   1.400 +{
   1.401 +    if (cert == NULL) {
   1.402 +	    return;
   1.403 +    }
   1.404 +    if (certData->strict && 
   1.405 +	!lg_tokenMatch(certData->sdb, &cert->certKey, LG_TOKEN_TYPE_CERT, 
   1.406 +				certData->template,certData->templ_count)) {
   1.407 +	nsslowcert_DestroyCertificate(cert);
   1.408 +	return;
   1.409 +    }
   1.410 +    certData->certs = (NSSLOWCERTCertificate **) 
   1.411 +				PORT_Alloc(sizeof (NSSLOWCERTCertificate *));
   1.412 +    if (certData->certs == NULL) {
   1.413 +	nsslowcert_DestroyCertificate(cert);
   1.414 +	return;
   1.415 +    }
   1.416 +    certData->certs[0] = cert;
   1.417 +    certData->cert_count = 1;
   1.418 +}
   1.419 +
   1.420 +static void
   1.421 +lg_CertSetupData(lgCertData *certData,int count)
   1.422 +{
   1.423 +    certData->max_cert_count = count;
   1.424 +
   1.425 +    if (certData->max_cert_count <= 0) {
   1.426 +	return;
   1.427 +    }
   1.428 +    certData->certs = (NSSLOWCERTCertificate **)
   1.429 +			 PORT_Alloc( count * sizeof(NSSLOWCERTCertificate *));
   1.430 +    return;
   1.431 +}
   1.432 +
   1.433 +static void
   1.434 +lg_searchCertsAndTrust(SDB *sdb, SECItem *derCert, SECItem *name, 
   1.435 +			SECItem *derSubject, NSSLOWCERTIssuerAndSN *issuerSN, 
   1.436 +			SECItem *email,
   1.437 +			unsigned long classFlags, SDBFind *handles, 
   1.438 +			const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   1.439 +{
   1.440 +    NSSLOWCERTCertDBHandle *certHandle = NULL;
   1.441 +    lgCertData certData;
   1.442 +    int i;
   1.443 +
   1.444 +    certHandle = lg_getCertDB(sdb);
   1.445 +    if (certHandle == NULL) return;
   1.446 +
   1.447 +    certData.sdb = sdb;
   1.448 +    certData.max_cert_count = 0;
   1.449 +    certData.certs = NULL;
   1.450 +    certData.cert_count = 0;
   1.451 +    certData.template = pTemplate;
   1.452 +    certData.templ_count = ulCount;
   1.453 +    certData.classFlags = classFlags; 
   1.454 +    certData.strict = LG_STRICT; 
   1.455 +
   1.456 +
   1.457 +    /*
   1.458 +     * Find the Cert.
   1.459 +     */
   1.460 +    if (derCert->data != NULL) {
   1.461 +	NSSLOWCERTCertificate *cert = 
   1.462 +			nsslowcert_FindCertByDERCert(certHandle,derCert);
   1.463 +	lg_searchSingleCert(&certData,cert);
   1.464 +    } else if (name->data != NULL) {
   1.465 +	char *tmp_name = (char*)PORT_Alloc(name->len+1);
   1.466 +	int count;
   1.467 +
   1.468 +	if (tmp_name == NULL) {
   1.469 +	    return;
   1.470 +	}
   1.471 +	PORT_Memcpy(tmp_name,name->data,name->len);
   1.472 +	tmp_name[name->len] = 0;
   1.473 +
   1.474 +	count= nsslowcert_NumPermCertsForNickname(certHandle,tmp_name);
   1.475 +	lg_CertSetupData(&certData,count);
   1.476 +	nsslowcert_TraversePermCertsForNickname(certHandle,tmp_name,
   1.477 +				lg_cert_collect, &certData);
   1.478 +	PORT_Free(tmp_name);
   1.479 +    } else if (derSubject->data != NULL) {
   1.480 +	int count;
   1.481 +
   1.482 +	count = nsslowcert_NumPermCertsForSubject(certHandle,derSubject);
   1.483 +	lg_CertSetupData(&certData,count);
   1.484 +	nsslowcert_TraversePermCertsForSubject(certHandle,derSubject,
   1.485 +				lg_cert_collect, &certData);
   1.486 +    } else if ((issuerSN->derIssuer.data != NULL) && 
   1.487 +			(issuerSN->serialNumber.data != NULL)) {
   1.488 +        if (classFlags & LG_CERT) {
   1.489 +	    NSSLOWCERTCertificate *cert = 
   1.490 +		nsslowcert_FindCertByIssuerAndSN(certHandle,issuerSN);
   1.491 +
   1.492 +	    lg_searchSingleCert(&certData,cert);
   1.493 +	}
   1.494 +	if (classFlags & LG_TRUST) {
   1.495 +	    NSSLOWCERTTrust *trust = 
   1.496 +		nsslowcert_FindTrustByIssuerAndSN(certHandle, issuerSN);
   1.497 +
   1.498 +	    if (trust) {
   1.499 +		lg_addHandle(handles,
   1.500 +		    lg_mkHandle(sdb,&trust->dbKey,LG_TOKEN_TYPE_TRUST));
   1.501 +		nsslowcert_DestroyTrust(trust);
   1.502 +	    }
   1.503 +	}
   1.504 +    } else if (email->data != NULL) {
   1.505 +	char *tmp_name = (char*)PORT_Alloc(email->len+1);
   1.506 +	certDBEntrySMime *entry = NULL;
   1.507 +
   1.508 +	if (tmp_name == NULL) {
   1.509 +	    return;
   1.510 +	}
   1.511 +	PORT_Memcpy(tmp_name,email->data,email->len);
   1.512 +	tmp_name[email->len] = 0;
   1.513 +
   1.514 +	entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
   1.515 +	if (entry) {
   1.516 +	    int count;
   1.517 +	    SECItem *subjectName = &entry->subjectName;
   1.518 +
   1.519 +	    count = nsslowcert_NumPermCertsForSubject(certHandle, subjectName);
   1.520 +	    lg_CertSetupData(&certData,count);
   1.521 +	    nsslowcert_TraversePermCertsForSubject(certHandle, subjectName, 
   1.522 +						lg_cert_collect, &certData);
   1.523 +
   1.524 +	    nsslowcert_DestroyDBEntry((certDBEntry *)entry);
   1.525 +	}
   1.526 +	PORT_Free(tmp_name);
   1.527 +    } else {
   1.528 +	/* we aren't filtering the certs, we are working on all, so turn
   1.529 +	 * on the strict filters. */
   1.530 +	certData.strict = PR_TRUE;
   1.531 +	lg_CertSetupData(&certData,LG_SEARCH_BLOCK_SIZE);
   1.532 +	nsslowcert_TraversePermCerts(certHandle, lg_cert_collect2, &certData);
   1.533 +    }
   1.534 +
   1.535 +    /*
   1.536 +     * build the handles
   1.537 +     */	
   1.538 +    for (i=0 ; i < certData.cert_count ; i++) {
   1.539 +	NSSLOWCERTCertificate *cert = certData.certs[i];
   1.540 +
   1.541 +	/* if we filtered it would have been on the stuff above */
   1.542 +	if (classFlags & LG_CERT) {
   1.543 +	    lg_addHandle(handles,
   1.544 +		lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_CERT));
   1.545 +	}
   1.546 +	if ((classFlags & LG_TRUST) && nsslowcert_hasTrust(cert->trust)) {
   1.547 +	    lg_addHandle(handles,
   1.548 +		lg_mkHandle(sdb,&cert->certKey,LG_TOKEN_TYPE_TRUST));
   1.549 +	}
   1.550 +	nsslowcert_DestroyCertificate(cert);
   1.551 +    }
   1.552 +
   1.553 +    if (certData.certs) PORT_Free(certData.certs);
   1.554 +    return;
   1.555 +}
   1.556 +
   1.557 +static SECStatus
   1.558 +lg_smime_collect(SECItem *data, SECItem *key, certDBEntryType type, void *arg)
   1.559 +{
   1.560 +    lgEntryData *smimeData;
   1.561 +    SDB *sdb;
   1.562 +    
   1.563 +    smimeData = (lgEntryData *)arg;
   1.564 +    sdb = smimeData->sdb;
   1.565 +
   1.566 +    if (lg_tokenMatch(sdb, key, LG_TOKEN_TYPE_SMIME,
   1.567 +			smimeData->template, smimeData->templ_count)) {
   1.568 +	lg_addHandle(smimeData->searchHandles,
   1.569 +				 lg_mkHandle(sdb,key,LG_TOKEN_TYPE_SMIME));
   1.570 +    }
   1.571 +    return(SECSuccess);
   1.572 +}
   1.573 +
   1.574 +static void
   1.575 +lg_searchSMime(SDB *sdb, SECItem *email, SDBFind *handles, 
   1.576 +			const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   1.577 +{
   1.578 +    NSSLOWCERTCertDBHandle *certHandle = NULL;
   1.579 +    certDBEntrySMime *entry;
   1.580 +
   1.581 +    certHandle = lg_getCertDB(sdb);
   1.582 +    if (certHandle == NULL) return;
   1.583 +
   1.584 +    if (email->data != NULL) {
   1.585 +	char *tmp_name = (char*)PORT_Alloc(email->len+1);
   1.586 +
   1.587 +	if (tmp_name == NULL) {
   1.588 +	    return;
   1.589 +	}
   1.590 +	PORT_Memcpy(tmp_name,email->data,email->len);
   1.591 +	tmp_name[email->len] = 0;
   1.592 +
   1.593 +	entry = nsslowcert_ReadDBSMimeEntry(certHandle,tmp_name);
   1.594 +	if (entry) {
   1.595 +	    SECItem emailKey;
   1.596 +
   1.597 +	    emailKey.data = (unsigned char *)tmp_name;
   1.598 +	    emailKey.len = PORT_Strlen(tmp_name)+1;
   1.599 +	    emailKey.type = 0;
   1.600 +	    lg_addHandle(handles,
   1.601 +		lg_mkHandle(sdb,&emailKey,LG_TOKEN_TYPE_SMIME));
   1.602 +	    nsslowcert_DestroyDBEntry((certDBEntry *)entry);
   1.603 +	}
   1.604 +	PORT_Free(tmp_name);
   1.605 +    } else {
   1.606 +	/* traverse */
   1.607 +	lgEntryData smimeData;
   1.608 +
   1.609 +	/* traverse */
   1.610 +	smimeData.sdb = sdb;
   1.611 +	smimeData.searchHandles = handles;
   1.612 +	smimeData.template = pTemplate;
   1.613 +	smimeData.templ_count = ulCount;
   1.614 +	nsslowcert_TraverseDBEntries(certHandle, certDBEntryTypeSMimeProfile,
   1.615 +		lg_smime_collect, (void *)&smimeData);
   1.616 +    }
   1.617 +    return;
   1.618 +}
   1.619 +
   1.620 +static CK_RV
   1.621 +lg_searchTokenList(SDB *sdb, SDBFind *search,
   1.622 +	 		const CK_ATTRIBUTE *pTemplate, CK_LONG ulCount)
   1.623 +{
   1.624 +    int i;
   1.625 +    PRBool isKrl = PR_FALSE;
   1.626 +    SECItem derCert = { siBuffer, NULL, 0 };
   1.627 +    SECItem derSubject = { siBuffer, NULL, 0 };
   1.628 +    SECItem name = { siBuffer, NULL, 0 };
   1.629 +    SECItem email = { siBuffer, NULL, 0 };
   1.630 +    SECItem key_id = { siBuffer, NULL, 0 };
   1.631 +    SECItem cert_sha1_hash = { siBuffer, NULL, 0 };
   1.632 +    SECItem cert_md5_hash  = { siBuffer, NULL, 0 };
   1.633 +    NSSLOWCERTIssuerAndSN issuerSN = {
   1.634 +	{ siBuffer, NULL, 0 },
   1.635 +	{ siBuffer, NULL, 0 }
   1.636 +    };
   1.637 +    SECItem *copy = NULL;
   1.638 +    CK_CERTIFICATE_TYPE certType;
   1.639 +    CK_OBJECT_CLASS objectClass;
   1.640 +    CK_RV crv;
   1.641 +    unsigned long classFlags;
   1.642 +
   1.643 +    if (lg_getCertDB(sdb) == NULL) {
   1.644 +	classFlags = LG_PRIVATE|LG_KEY;
   1.645 +    } else {
   1.646 +	classFlags = LG_CERT|LG_TRUST|LG_PUBLIC|LG_SMIME|LG_CRL;
   1.647 +    }
   1.648 +
   1.649 +    /*
   1.650 +     * look for things to search on token objects for. If the right options
   1.651 +     * are specified, we can use them as direct indeces into the database
   1.652 +     * (rather than using linear searches. We can also use the attributes to
   1.653 +     * limit the kinds of objects we are searching for. Later we can use this
   1.654 +     * array to filter the remaining objects more finely.
   1.655 +     */
   1.656 +    for (i=0 ;classFlags && i < (int)ulCount; i++) {
   1.657 +
   1.658 +	switch (pTemplate[i].type) {
   1.659 +	case CKA_SUBJECT:
   1.660 +	    copy = &derSubject;
   1.661 +	    classFlags &= (LG_CERT|LG_PRIVATE|LG_PUBLIC|LG_SMIME|LG_CRL);
   1.662 +	    break;
   1.663 +	case CKA_ISSUER: 
   1.664 +	    copy = &issuerSN.derIssuer;
   1.665 +	    classFlags &= (LG_CERT|LG_TRUST);
   1.666 +	    break;
   1.667 +	case CKA_SERIAL_NUMBER: 
   1.668 +	    copy = &issuerSN.serialNumber;
   1.669 +	    classFlags &= (LG_CERT|LG_TRUST);
   1.670 +	    break;
   1.671 +	case CKA_VALUE:
   1.672 +	    copy = &derCert;
   1.673 +	    classFlags &= (LG_CERT|LG_CRL|LG_SMIME);
   1.674 +	    break;
   1.675 +	case CKA_LABEL:
   1.676 +	    copy = &name;
   1.677 +	    break;
   1.678 +	case CKA_NETSCAPE_EMAIL:
   1.679 +	    copy = &email;
   1.680 +	    classFlags &= LG_SMIME|LG_CERT;
   1.681 +	    break;
   1.682 +	case CKA_NETSCAPE_SMIME_TIMESTAMP:
   1.683 +	    classFlags &= LG_SMIME;
   1.684 +	    break;
   1.685 +	case CKA_CLASS:
   1.686 +	    crv = lg_GetULongAttribute(CKA_CLASS,&pTemplate[i],1, &objectClass);
   1.687 +	    if (crv != CKR_OK) {
   1.688 +		classFlags = 0;
   1.689 +		break;
   1.690 +	    }
   1.691 +	    switch (objectClass) {
   1.692 +	    case CKO_CERTIFICATE:
   1.693 +		classFlags &= LG_CERT;
   1.694 +		break;
   1.695 +	    case CKO_NETSCAPE_TRUST:
   1.696 +		classFlags &= LG_TRUST;
   1.697 +		break;
   1.698 +	    case CKO_NETSCAPE_CRL:
   1.699 +		classFlags &= LG_CRL;
   1.700 +		break;
   1.701 +	    case CKO_NETSCAPE_SMIME:
   1.702 +		classFlags &= LG_SMIME;
   1.703 +		break;
   1.704 +	    case CKO_PRIVATE_KEY:
   1.705 +		classFlags &= LG_PRIVATE;
   1.706 +		break;
   1.707 +	    case CKO_PUBLIC_KEY:
   1.708 +		classFlags &= LG_PUBLIC;
   1.709 +		break;
   1.710 +	    case CKO_SECRET_KEY:
   1.711 +		classFlags &= LG_KEY;
   1.712 +		break;
   1.713 +	    default:
   1.714 +		classFlags = 0;
   1.715 +		break;
   1.716 +	    }
   1.717 +	    break;
   1.718 +	case CKA_PRIVATE:
   1.719 +	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   1.720 +		classFlags = 0;
   1.721 +		break;
   1.722 +	    }
   1.723 +	    if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
   1.724 +		classFlags &= (LG_PRIVATE|LG_KEY);
   1.725 +	    } else {
   1.726 +		classFlags &= ~(LG_PRIVATE|LG_KEY);
   1.727 +	    }
   1.728 +	    break;
   1.729 +	case CKA_SENSITIVE:
   1.730 +	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   1.731 +		classFlags = 0;
   1.732 +		break;
   1.733 +	    }
   1.734 +	    if (*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE) {
   1.735 +		classFlags &= (LG_PRIVATE|LG_KEY);
   1.736 +	    } else {
   1.737 +		classFlags = 0;
   1.738 +	    }
   1.739 +	    break;
   1.740 +	case CKA_TOKEN:
   1.741 +	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   1.742 +		classFlags = 0;
   1.743 +		break;
   1.744 +	    }
   1.745 +	    if (*((CK_BBOOL *)pTemplate[i].pValue) != CK_TRUE) {
   1.746 +		classFlags = 0;
   1.747 +	    }
   1.748 +	    break;
   1.749 +	case CKA_CERT_SHA1_HASH:
   1.750 +	    classFlags &= LG_TRUST;
   1.751 +	    copy = &cert_sha1_hash; break;
   1.752 +	case CKA_CERT_MD5_HASH:
   1.753 +	    classFlags &= LG_TRUST;
   1.754 +	    copy = &cert_md5_hash; break;
   1.755 +	case CKA_CERTIFICATE_TYPE:
   1.756 +	    crv = lg_GetULongAttribute(CKA_CERTIFICATE_TYPE,&pTemplate[i],
   1.757 +								1,&certType);
   1.758 +	    if (crv != CKR_OK) {
   1.759 +		classFlags = 0;
   1.760 +		break;
   1.761 +	    }
   1.762 +	    classFlags &= LG_CERT;
   1.763 +	    if (certType != CKC_X_509) {
   1.764 +		classFlags = 0;
   1.765 +	    }
   1.766 +	    break;
   1.767 +	case CKA_ID:
   1.768 +	    copy = &key_id;
   1.769 +	    classFlags &= (LG_CERT|LG_PRIVATE|LG_KEY|LG_PUBLIC);
   1.770 +	    break;
   1.771 +	case CKA_NETSCAPE_KRL:
   1.772 +	    if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) {
   1.773 +		classFlags = 0;
   1.774 +		break;
   1.775 +	    }
   1.776 +	    classFlags &= LG_CRL;
   1.777 +	    isKrl = (PRBool)(*((CK_BBOOL *)pTemplate[i].pValue) == CK_TRUE);
   1.778 +	    break;
   1.779 +	case CKA_MODIFIABLE:
   1.780 +	     break;
   1.781 +	case CKA_KEY_TYPE:
   1.782 +	case CKA_DERIVE:
   1.783 +	    classFlags &= LG_PUBLIC|LG_PRIVATE|LG_KEY;
   1.784 +	    break;
   1.785 +	case CKA_VERIFY_RECOVER:
   1.786 +	    classFlags &= LG_PUBLIC;
   1.787 +	    break;
   1.788 +	case CKA_SIGN_RECOVER:
   1.789 +	    classFlags &= LG_PRIVATE;
   1.790 +	    break;
   1.791 +	case CKA_ENCRYPT:
   1.792 +	case CKA_VERIFY:
   1.793 +	case CKA_WRAP:
   1.794 +	    classFlags &= LG_PUBLIC|LG_KEY;
   1.795 +	    break;
   1.796 +	case CKA_DECRYPT:
   1.797 +	case CKA_SIGN:
   1.798 +	case CKA_UNWRAP:
   1.799 +	case CKA_ALWAYS_SENSITIVE:
   1.800 +	case CKA_EXTRACTABLE:
   1.801 +	case CKA_NEVER_EXTRACTABLE:
   1.802 +	    classFlags &= LG_PRIVATE|LG_KEY;
   1.803 +	    break;
   1.804 +	/* can't be a certificate if it doesn't match one of the above 
   1.805 +	 * attributes */
   1.806 +	default: 
   1.807 +	     classFlags  = 0;
   1.808 +	     break;
   1.809 +	}
   1.810 + 	if (copy) {
   1.811 +	    copy->data = (unsigned char*)pTemplate[i].pValue;
   1.812 +	    copy->len = pTemplate[i].ulValueLen;
   1.813 +	}
   1.814 +	copy = NULL;
   1.815 +    }
   1.816 +
   1.817 +    /* certs */
   1.818 +    if (classFlags & (LG_CERT|LG_TRUST)) {
   1.819 +	lg_searchCertsAndTrust(sdb,&derCert,&name,&derSubject,
   1.820 +				 &issuerSN, &email,classFlags,search, 
   1.821 +				pTemplate, ulCount);
   1.822 +    }
   1.823 +
   1.824 +    /* keys */
   1.825 +    if (classFlags & (LG_PRIVATE|LG_PUBLIC|LG_KEY)) {
   1.826 +	PRBool mustStrict = (name.len != 0);
   1.827 +	lg_searchKeys(sdb, &key_id, classFlags, search,
   1.828 +			 mustStrict, pTemplate, ulCount);
   1.829 +    }
   1.830 +
   1.831 +    /* crl's */
   1.832 +    if (classFlags & LG_CRL) {
   1.833 +	lg_searchCrls(sdb, &derSubject, isKrl, classFlags, search,
   1.834 +			pTemplate, ulCount);
   1.835 +    }
   1.836 +    /* Add S/MIME entry stuff */
   1.837 +    if (classFlags & LG_SMIME) {
   1.838 +	lg_searchSMime(sdb, &email, search, pTemplate, ulCount);
   1.839 +    }
   1.840 +    return CKR_OK;
   1.841 +}
   1.842 +	
   1.843 +
   1.844 +/* lg_FindObjectsInit initializes a search for token and session objects 
   1.845 + * that match a template. */
   1.846 +CK_RV lg_FindObjectsInit(SDB *sdb, const CK_ATTRIBUTE *pTemplate,
   1.847 +			 CK_ULONG ulCount, SDBFind **retSearch)
   1.848 +{
   1.849 +    SDBFind *search;
   1.850 +    CK_RV crv = CKR_OK;
   1.851 +  
   1.852 +    *retSearch = NULL; 
   1.853 +
   1.854 +    search = (SDBFind *)PORT_Alloc(sizeof(SDBFind));
   1.855 +    if (search == NULL) {
   1.856 +	crv = CKR_HOST_MEMORY;
   1.857 +	goto loser;
   1.858 +    }
   1.859 +    search->handles = (CK_OBJECT_HANDLE *)
   1.860 +		PORT_Alloc(sizeof(CK_OBJECT_HANDLE) * LG_SEARCH_BLOCK_SIZE);
   1.861 +    if (search->handles == NULL) {
   1.862 +	crv = CKR_HOST_MEMORY;
   1.863 +	goto loser;
   1.864 +    }
   1.865 +    search->index = 0;
   1.866 +    search->size = 0;
   1.867 +    search->array_size = LG_SEARCH_BLOCK_SIZE;
   1.868 +    /* FIXME - do we still need to get Login state? */
   1.869 +
   1.870 +    crv = lg_searchTokenList(sdb, search, pTemplate, ulCount);
   1.871 +    if (crv != CKR_OK) {
   1.872 +	goto loser;
   1.873 +    }
   1.874 +
   1.875 +    *retSearch = search;
   1.876 +    return CKR_OK;
   1.877 +
   1.878 +loser:
   1.879 +    if (search) {
   1.880 +	lg_FreeSearch(search);
   1.881 +    }
   1.882 +    return crv;
   1.883 +}
   1.884 +
   1.885 +
   1.886 +/* lg_FindObjects continues a search for token and session objects 
   1.887 + * that match a template, obtaining additional object handles. */
   1.888 +CK_RV lg_FindObjects(SDB *sdb, SDBFind *search, 
   1.889 +    CK_OBJECT_HANDLE *phObject,CK_ULONG ulMaxObjectCount,
   1.890 +    					CK_ULONG *pulObjectCount)
   1.891 +{
   1.892 +    int	transfer;
   1.893 +    int left;
   1.894 +
   1.895 +    *pulObjectCount = 0;
   1.896 +    left = search->size - search->index;
   1.897 +    transfer = ((int)ulMaxObjectCount > left) ? left : ulMaxObjectCount;
   1.898 +    if (transfer > 0) {
   1.899 +	PORT_Memcpy(phObject,&search->handles[search->index],
   1.900 +                                        transfer*sizeof(CK_OBJECT_HANDLE));
   1.901 +    } else {
   1.902 +       *phObject = CK_INVALID_HANDLE;
   1.903 +    }
   1.904 +
   1.905 +    search->index += transfer;
   1.906 +    *pulObjectCount = transfer;
   1.907 +    return CKR_OK;
   1.908 +}
   1.909 +
   1.910 +/* lg_FindObjectsFinal finishes a search for token and session objects. */
   1.911 +CK_RV lg_FindObjectsFinal(SDB* lgdb, SDBFind *search)
   1.912 +{
   1.913 +
   1.914 +    if (search != NULL) {
   1.915 +	lg_FreeSearch(search);
   1.916 +    }
   1.917 +    return CKR_OK;
   1.918 +}

mercurial