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 +}