1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/lib/ckfw/nssmkey/mfind.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,367 @@ 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 + 1.8 +#ifndef CKMK_H 1.9 +#include "ckmk.h" 1.10 +#endif /* CKMK_H */ 1.11 + 1.12 +/* 1.13 + * nssmkey/mfind.c 1.14 + * 1.15 + * This file implements the NSSCKMDFindObjects object for the 1.16 + * "nssmkey" cryptoki module. 1.17 + */ 1.18 + 1.19 +struct ckmkFOStr { 1.20 + NSSArena *arena; 1.21 + CK_ULONG n; 1.22 + CK_ULONG i; 1.23 + ckmkInternalObject **objs; 1.24 +}; 1.25 + 1.26 +static void 1.27 +ckmk_mdFindObjects_Final 1.28 +( 1.29 + NSSCKMDFindObjects *mdFindObjects, 1.30 + NSSCKFWFindObjects *fwFindObjects, 1.31 + NSSCKMDSession *mdSession, 1.32 + NSSCKFWSession *fwSession, 1.33 + NSSCKMDToken *mdToken, 1.34 + NSSCKFWToken *fwToken, 1.35 + NSSCKMDInstance *mdInstance, 1.36 + NSSCKFWInstance *fwInstance 1.37 +) 1.38 +{ 1.39 + struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc; 1.40 + NSSArena *arena = fo->arena; 1.41 + PRUint32 i; 1.42 + 1.43 + /* walk down an free the unused 'objs' */ 1.44 + for (i=fo->i; i < fo->n ; i++) { 1.45 + nss_ckmk_DestroyInternalObject(fo->objs[i]); 1.46 + } 1.47 + 1.48 + nss_ZFreeIf(fo->objs); 1.49 + nss_ZFreeIf(fo); 1.50 + nss_ZFreeIf(mdFindObjects); 1.51 + if ((NSSArena *)NULL != arena) { 1.52 + NSSArena_Destroy(arena); 1.53 + } 1.54 + 1.55 + return; 1.56 +} 1.57 + 1.58 +static NSSCKMDObject * 1.59 +ckmk_mdFindObjects_Next 1.60 +( 1.61 + NSSCKMDFindObjects *mdFindObjects, 1.62 + NSSCKFWFindObjects *fwFindObjects, 1.63 + NSSCKMDSession *mdSession, 1.64 + NSSCKFWSession *fwSession, 1.65 + NSSCKMDToken *mdToken, 1.66 + NSSCKFWToken *fwToken, 1.67 + NSSCKMDInstance *mdInstance, 1.68 + NSSCKFWInstance *fwInstance, 1.69 + NSSArena *arena, 1.70 + CK_RV *pError 1.71 +) 1.72 +{ 1.73 + struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc; 1.74 + ckmkInternalObject *io; 1.75 + 1.76 + if( fo->i == fo->n ) { 1.77 + *pError = CKR_OK; 1.78 + return (NSSCKMDObject *)NULL; 1.79 + } 1.80 + 1.81 + io = fo->objs[ fo->i ]; 1.82 + fo->i++; 1.83 + 1.84 + return nss_ckmk_CreateMDObject(arena, io, pError); 1.85 +} 1.86 + 1.87 +static CK_BBOOL 1.88 +ckmk_attrmatch 1.89 +( 1.90 + CK_ATTRIBUTE_PTR a, 1.91 + ckmkInternalObject *o 1.92 +) 1.93 +{ 1.94 + PRBool prb; 1.95 + const NSSItem *b; 1.96 + CK_RV error; 1.97 + 1.98 + b = nss_ckmk_FetchAttribute(o, a->type, &error); 1.99 + if (b == NULL) { 1.100 + return CK_FALSE; 1.101 + } 1.102 + 1.103 + if( a->ulValueLen != b->size ) { 1.104 + /* match a decoded serial number */ 1.105 + if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) { 1.106 + int len; 1.107 + unsigned char *data; 1.108 + 1.109 + data = nss_ckmk_DERUnwrap(b->data, b->size, &len, NULL); 1.110 + if ((len == a->ulValueLen) && 1.111 + nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) { 1.112 + return CK_TRUE; 1.113 + } 1.114 + } 1.115 + return CK_FALSE; 1.116 + } 1.117 + 1.118 + prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL); 1.119 + 1.120 + if( PR_TRUE == prb ) { 1.121 + return CK_TRUE; 1.122 + } else { 1.123 + return CK_FALSE; 1.124 + } 1.125 +} 1.126 + 1.127 + 1.128 +static CK_BBOOL 1.129 +ckmk_match 1.130 +( 1.131 + CK_ATTRIBUTE_PTR pTemplate, 1.132 + CK_ULONG ulAttributeCount, 1.133 + ckmkInternalObject *o 1.134 +) 1.135 +{ 1.136 + CK_ULONG i; 1.137 + 1.138 + for( i = 0; i < ulAttributeCount; i++ ) { 1.139 + if (CK_FALSE == ckmk_attrmatch(&pTemplate[i], o)) { 1.140 + return CK_FALSE; 1.141 + } 1.142 + } 1.143 + 1.144 + /* Every attribute passed */ 1.145 + return CK_TRUE; 1.146 +} 1.147 + 1.148 +#define CKMK_ITEM_CHUNK 20 1.149 + 1.150 +#define PUT_OBJECT(obj, err, size, count, list) \ 1.151 + { \ 1.152 + if (count >= size) { \ 1.153 + (list) = (list) ? \ 1.154 + nss_ZREALLOCARRAY(list, ckmkInternalObject *, \ 1.155 + ((size)+CKMK_ITEM_CHUNK) ) : \ 1.156 + nss_ZNEWARRAY(NULL, ckmkInternalObject *, \ 1.157 + ((size)+CKMK_ITEM_CHUNK) ) ; \ 1.158 + if ((ckmkInternalObject **)NULL == list) { \ 1.159 + err = CKR_HOST_MEMORY; \ 1.160 + goto loser; \ 1.161 + } \ 1.162 + (size) += CKMK_ITEM_CHUNK; \ 1.163 + } \ 1.164 + (list)[ count ] = (obj); \ 1.165 + count++; \ 1.166 + } 1.167 + 1.168 + 1.169 +/* find all the certs that represent the appropriate object (cert, priv key, or 1.170 + * pub key) in the cert store. 1.171 + */ 1.172 +static PRUint32 1.173 +collect_class( 1.174 + CK_OBJECT_CLASS objClass, 1.175 + SecItemClass itemClass, 1.176 + CK_ATTRIBUTE_PTR pTemplate, 1.177 + CK_ULONG ulAttributeCount, 1.178 + ckmkInternalObject ***listp, 1.179 + PRUint32 *sizep, 1.180 + PRUint32 count, 1.181 + CK_RV *pError 1.182 +) 1.183 +{ 1.184 + ckmkInternalObject *next = NULL; 1.185 + SecKeychainSearchRef searchRef = 0; 1.186 + SecKeychainItemRef itemRef = 0; 1.187 + OSStatus error; 1.188 + 1.189 + /* future, build the attribute list based on the template 1.190 + * so we can refine the search */ 1.191 + error = SecKeychainSearchCreateFromAttributes( 1.192 + NULL, itemClass, NULL, &searchRef); 1.193 + 1.194 + while (noErr == SecKeychainSearchCopyNext(searchRef, &itemRef)) { 1.195 + /* if we don't have an internal object structure, get one */ 1.196 + if ((ckmkInternalObject *)NULL == next) { 1.197 + next = nss_ZNEW(NULL, ckmkInternalObject); 1.198 + if ((ckmkInternalObject *)NULL == next) { 1.199 + *pError = CKR_HOST_MEMORY; 1.200 + goto loser; 1.201 + } 1.202 + } 1.203 + /* fill in the relevant object data */ 1.204 + next->type = ckmkItem; 1.205 + next->objClass = objClass; 1.206 + next->u.item.itemRef = itemRef; 1.207 + next->u.item.itemClass = itemClass; 1.208 + 1.209 + /* see if this is one of the objects we are looking for */ 1.210 + if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, next) ) { 1.211 + /* yes, put it on the list */ 1.212 + PUT_OBJECT(next, *pError, *sizep, count, *listp); 1.213 + next = NULL; /* this one is on the list, need to allocate a new one now */ 1.214 + } else { 1.215 + /* no , release the current item and clear out the structure for reuse */ 1.216 + CFRelease(itemRef); 1.217 + /* don't cache the values we just loaded */ 1.218 + nsslibc_memset(next, 0, sizeof(*next)); 1.219 + } 1.220 + } 1.221 +loser: 1.222 + if (searchRef) { 1.223 + CFRelease(searchRef); 1.224 + } 1.225 + nss_ZFreeIf(next); 1.226 + return count; 1.227 +} 1.228 + 1.229 +static PRUint32 1.230 +collect_objects( 1.231 + CK_ATTRIBUTE_PTR pTemplate, 1.232 + CK_ULONG ulAttributeCount, 1.233 + ckmkInternalObject ***listp, 1.234 + CK_RV *pError 1.235 +) 1.236 +{ 1.237 + PRUint32 i; 1.238 + PRUint32 count = 0; 1.239 + PRUint32 size = 0; 1.240 + CK_OBJECT_CLASS objClass; 1.241 + 1.242 + /* 1.243 + * first handle the static build in objects (if any) 1.244 + */ 1.245 + for( i = 0; i < nss_ckmk_nObjects; i++ ) { 1.246 + ckmkInternalObject *o = (ckmkInternalObject *)&nss_ckmk_data[i]; 1.247 + 1.248 + if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, o) ) { 1.249 + PUT_OBJECT(o, *pError, size, count, *listp); 1.250 + } 1.251 + } 1.252 + 1.253 + /* 1.254 + * now handle the various object types 1.255 + */ 1.256 + objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, 1.257 + pTemplate, ulAttributeCount, pError); 1.258 + if (CKR_OK != *pError) { 1.259 + objClass = CK_INVALID_HANDLE; 1.260 + } 1.261 + *pError = CKR_OK; 1.262 + switch (objClass) { 1.263 + case CKO_CERTIFICATE: 1.264 + count = collect_class(objClass, kSecCertificateItemClass, 1.265 + pTemplate, ulAttributeCount, listp, 1.266 + &size, count, pError); 1.267 + break; 1.268 + case CKO_PUBLIC_KEY: 1.269 + count = collect_class(objClass, CSSM_DL_DB_RECORD_PUBLIC_KEY, 1.270 + pTemplate, ulAttributeCount, listp, 1.271 + &size, count, pError); 1.272 + break; 1.273 + case CKO_PRIVATE_KEY: 1.274 + count = collect_class(objClass, CSSM_DL_DB_RECORD_PRIVATE_KEY, 1.275 + pTemplate, ulAttributeCount, listp, 1.276 + &size, count, pError); 1.277 + break; 1.278 + /* all of them */ 1.279 + case CK_INVALID_HANDLE: 1.280 + count = collect_class(CKO_CERTIFICATE, kSecCertificateItemClass, 1.281 + pTemplate, ulAttributeCount, listp, 1.282 + &size, count, pError); 1.283 + count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PUBLIC_KEY, 1.284 + pTemplate, ulAttributeCount, listp, 1.285 + &size, count, pError); 1.286 + count = collect_class(CKO_PUBLIC_KEY, CSSM_DL_DB_RECORD_PRIVATE_KEY, 1.287 + pTemplate, ulAttributeCount, listp, 1.288 + &size, count, pError); 1.289 + break; 1.290 + default: 1.291 + break; 1.292 + } 1.293 + if (CKR_OK != *pError) { 1.294 + goto loser; 1.295 + } 1.296 + 1.297 + return count; 1.298 +loser: 1.299 + nss_ZFreeIf(*listp); 1.300 + return 0; 1.301 +} 1.302 + 1.303 + 1.304 +NSS_IMPLEMENT NSSCKMDFindObjects * 1.305 +nss_ckmk_FindObjectsInit 1.306 +( 1.307 + NSSCKFWSession *fwSession, 1.308 + CK_ATTRIBUTE_PTR pTemplate, 1.309 + CK_ULONG ulAttributeCount, 1.310 + CK_RV *pError 1.311 +) 1.312 +{ 1.313 + /* This could be made more efficient. I'm rather rushed. */ 1.314 + NSSArena *arena; 1.315 + NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL; 1.316 + struct ckmkFOStr *fo = (struct ckmkFOStr *)NULL; 1.317 + ckmkInternalObject **temp = (ckmkInternalObject **)NULL; 1.318 + 1.319 + arena = NSSArena_Create(); 1.320 + if( (NSSArena *)NULL == arena ) { 1.321 + goto loser; 1.322 + } 1.323 + 1.324 + rv = nss_ZNEW(arena, NSSCKMDFindObjects); 1.325 + if( (NSSCKMDFindObjects *)NULL == rv ) { 1.326 + *pError = CKR_HOST_MEMORY; 1.327 + goto loser; 1.328 + } 1.329 + 1.330 + fo = nss_ZNEW(arena, struct ckmkFOStr); 1.331 + if( (struct ckmkFOStr *)NULL == fo ) { 1.332 + *pError = CKR_HOST_MEMORY; 1.333 + goto loser; 1.334 + } 1.335 + 1.336 + fo->arena = arena; 1.337 + /* fo->n and fo->i are already zero */ 1.338 + 1.339 + rv->etc = (void *)fo; 1.340 + rv->Final = ckmk_mdFindObjects_Final; 1.341 + rv->Next = ckmk_mdFindObjects_Next; 1.342 + rv->null = (void *)NULL; 1.343 + 1.344 + fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError); 1.345 + if (*pError != CKR_OK) { 1.346 + goto loser; 1.347 + } 1.348 + 1.349 + fo->objs = nss_ZNEWARRAY(arena, ckmkInternalObject *, fo->n); 1.350 + if( (ckmkInternalObject **)NULL == fo->objs ) { 1.351 + *pError = CKR_HOST_MEMORY; 1.352 + goto loser; 1.353 + } 1.354 + 1.355 + (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckmkInternalObject *) * fo->n); 1.356 + nss_ZFreeIf(temp); 1.357 + temp = (ckmkInternalObject **)NULL; 1.358 + 1.359 + return rv; 1.360 + 1.361 + loser: 1.362 + nss_ZFreeIf(temp); 1.363 + nss_ZFreeIf(fo); 1.364 + nss_ZFreeIf(rv); 1.365 + if ((NSSArena *)NULL != arena) { 1.366 + NSSArena_Destroy(arena); 1.367 + } 1.368 + return (NSSCKMDFindObjects *)NULL; 1.369 +} 1.370 +