PageRenderTime 25ms CodeModel.GetById 2ms app.highlight 19ms RepoModel.GetById 1ms app.codeStats 1ms

/security/nss/lib/ckfw/nssmkey/mfind.c

http://github.com/zpao/v8monkey
C | 404 lines | 292 code | 46 blank | 66 comment | 54 complexity | 455191a3fede912ffdae164876b7d919 MD5 | raw file
  1/* ***** BEGIN LICENSE BLOCK *****
  2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3 *
  4 * The contents of this file are subject to the Mozilla Public License Version
  5 * 1.1 (the "License"); you may not use this file except in compliance with
  6 * the License. You may obtain a copy of the License at
  7 * http://www.mozilla.org/MPL/
  8 *
  9 * Software distributed under the License is distributed on an "AS IS" basis,
 10 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 11 * for the specific language governing rights and limitations under the
 12 * License.
 13 *
 14 * The Original Code is the Netscape security libraries.
 15 *
 16 * The Initial Developer of the Original Code is
 17 * Netscape Communications Corporation.
 18 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 19 * the Initial Developer. All Rights Reserved.
 20 * Portions created by Red Hat, Inc, are Copyright (C) 2005
 21 *
 22 * Contributor(s):
 23 *   Bob Relyea (rrelyea@redhat.com)
 24 *
 25 * Alternatively, the contents of this file may be used under the terms of
 26 * either the GNU General Public License Version 2 or later (the "GPL"), or
 27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 28 * in which case the provisions of the GPL or the LGPL are applicable instead
 29 * of those above. If you wish to allow use of your version of this file only
 30 * under the terms of either the GPL or the LGPL, and not to allow others to
 31 * use your version of this file under the terms of the MPL, indicate your
 32 * decision by deleting the provisions above and replace them with the notice
 33 * and other provisions required by the GPL or the LGPL. If you do not delete
 34 * the provisions above, a recipient may use your version of this file under
 35 * the terms of any one of the MPL, the GPL or the LGPL.
 36 *
 37 * ***** END LICENSE BLOCK ***** */
 38#ifdef DEBUG
 39static const char CVS_ID[] = "@(#) $RCSfile: mfind.c,v $ $Revision: 1.1 $ $Date: 2005/11/23 23:04:08 $";
 40#endif /* DEBUG */
 41
 42#ifndef CKMK_H
 43#include "ckmk.h"
 44#endif /* CKMK_H */
 45
 46/*
 47 * nssmkey/mfind.c
 48 *
 49 * This file implements the NSSCKMDFindObjects object for the
 50 * "nssmkey" cryptoki module.
 51 */
 52
 53struct ckmkFOStr {
 54  NSSArena *arena;
 55  CK_ULONG n;
 56  CK_ULONG i;
 57  ckmkInternalObject **objs;
 58};
 59
 60static void
 61ckmk_mdFindObjects_Final
 62(
 63  NSSCKMDFindObjects *mdFindObjects,
 64  NSSCKFWFindObjects *fwFindObjects,
 65  NSSCKMDSession *mdSession,
 66  NSSCKFWSession *fwSession,
 67  NSSCKMDToken *mdToken,
 68  NSSCKFWToken *fwToken,
 69  NSSCKMDInstance *mdInstance,
 70  NSSCKFWInstance *fwInstance
 71)
 72{
 73  struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
 74  NSSArena *arena = fo->arena;
 75  PRUint32 i;
 76
 77  /* walk down an free the unused 'objs' */
 78  for (i=fo->i; i < fo->n ; i++) {
 79    nss_ckmk_DestroyInternalObject(fo->objs[i]);
 80  }
 81
 82  nss_ZFreeIf(fo->objs);
 83  nss_ZFreeIf(fo);
 84  nss_ZFreeIf(mdFindObjects);
 85  if ((NSSArena *)NULL != arena) {
 86    NSSArena_Destroy(arena);
 87  }
 88
 89  return;
 90}
 91
 92static NSSCKMDObject *
 93ckmk_mdFindObjects_Next
 94(
 95  NSSCKMDFindObjects *mdFindObjects,
 96  NSSCKFWFindObjects *fwFindObjects,
 97  NSSCKMDSession *mdSession,
 98  NSSCKFWSession *fwSession,
 99  NSSCKMDToken *mdToken,
100  NSSCKFWToken *fwToken,
101  NSSCKMDInstance *mdInstance,
102  NSSCKFWInstance *fwInstance,
103  NSSArena *arena,
104  CK_RV *pError
105)
106{
107  struct ckmkFOStr *fo = (struct ckmkFOStr *)mdFindObjects->etc;
108  ckmkInternalObject *io;
109
110  if( fo->i == fo->n ) {
111    *pError = CKR_OK;
112    return (NSSCKMDObject *)NULL;
113  }
114
115  io = fo->objs[ fo->i ];
116  fo->i++;
117
118  return nss_ckmk_CreateMDObject(arena, io, pError);
119}
120
121static CK_BBOOL
122ckmk_attrmatch
123(
124  CK_ATTRIBUTE_PTR a,
125  ckmkInternalObject *o
126)
127{
128  PRBool prb;
129  const NSSItem *b;
130  CK_RV error;
131
132  b = nss_ckmk_FetchAttribute(o, a->type,  &error);
133  if (b == NULL) {
134    return CK_FALSE;
135  }
136
137  if( a->ulValueLen != b->size ) {
138    /* match a decoded serial number */
139    if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) {
140	int len;
141	unsigned char *data;
142
143	data = nss_ckmk_DERUnwrap(b->data, b->size, &len, NULL);
144	if ((len == a->ulValueLen) && 
145		nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) {
146	    return CK_TRUE;
147	}
148    }
149    return CK_FALSE;
150  }
151
152  prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL);
153
154  if( PR_TRUE == prb ) {
155    return CK_TRUE;
156  } else {
157    return CK_FALSE;
158  }
159}
160
161
162static CK_BBOOL
163ckmk_match
164(
165  CK_ATTRIBUTE_PTR pTemplate,
166  CK_ULONG ulAttributeCount,
167  ckmkInternalObject *o
168)
169{
170  CK_ULONG i;
171
172  for( i = 0; i < ulAttributeCount; i++ ) {
173    if (CK_FALSE == ckmk_attrmatch(&pTemplate[i], o)) {
174      return CK_FALSE;
175    }
176  }
177
178  /* Every attribute passed */
179  return CK_TRUE;
180}
181
182#define CKMK_ITEM_CHUNK  20
183
184#define PUT_OBJECT(obj, err, size, count, list) \
185  { \
186    if (count >= size) { \
187    (list) = (list) ? \
188		nss_ZREALLOCARRAY(list, ckmkInternalObject *, \
189		               ((size)+CKMK_ITEM_CHUNK) ) : \
190		nss_ZNEWARRAY(NULL, ckmkInternalObject *, \
191		               ((size)+CKMK_ITEM_CHUNK) ) ; \
192      if ((ckmkInternalObject **)NULL == list) { \
193        err = CKR_HOST_MEMORY; \
194        goto loser; \
195      } \
196      (size) += CKMK_ITEM_CHUNK; \
197    } \
198    (list)[ count ] = (obj); \
199    count++; \
200  }
201
202
203/* find all the certs that represent the appropriate object (cert, priv key, or
204 *  pub key) in the cert store.
205 */
206static PRUint32
207collect_class(
208  CK_OBJECT_CLASS objClass,
209  SecItemClass itemClass,
210  CK_ATTRIBUTE_PTR pTemplate, 
211  CK_ULONG ulAttributeCount, 
212  ckmkInternalObject ***listp,
213  PRUint32 *sizep,
214  PRUint32 count,
215  CK_RV *pError
216)
217{
218  ckmkInternalObject *next = NULL;
219  SecKeychainSearchRef searchRef = 0;
220  SecKeychainItemRef itemRef = 0;
221  OSStatus error;
222
223  /* future, build the attribute list based on the template
224   * so we can refine the search */
225  error = SecKeychainSearchCreateFromAttributes( 
226		NULL, itemClass, NULL, &searchRef);
227
228  while (noErr == SecKeychainSearchCopyNext(searchRef, &itemRef)) {
229    /* if we don't have an internal object structure, get one */
230    if ((ckmkInternalObject *)NULL == next) {
231      next = nss_ZNEW(NULL, ckmkInternalObject);
232      if ((ckmkInternalObject *)NULL == next) {
233        *pError = CKR_HOST_MEMORY;
234        goto loser;
235      }
236    }
237    /* fill in the relevant object data */
238    next->type = ckmkItem;
239    next->objClass = objClass;
240    next->u.item.itemRef = itemRef;
241    next->u.item.itemClass = itemClass;
242
243    /* see if this is one of the objects we are looking for */
244    if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, next) ) {
245      /* yes, put it on the list */
246      PUT_OBJECT(next, *pError, *sizep, count, *listp);
247      next = NULL; /* this one is on the list, need to allocate a new one now */
248    } else {
249      /* no , release the current item and clear out the structure for reuse */
250      CFRelease(itemRef);
251      /* don't cache the values we just loaded */
252      nsslibc_memset(next, 0, sizeof(*next));
253    }
254  }
255loser:
256  if (searchRef) {
257    CFRelease(searchRef);
258  }
259  nss_ZFreeIf(next);
260  return count;
261}
262
263static PRUint32
264collect_objects(
265  CK_ATTRIBUTE_PTR pTemplate, 
266  CK_ULONG ulAttributeCount, 
267  ckmkInternalObject ***listp,
268  CK_RV *pError
269)
270{
271  PRUint32 i;
272  PRUint32 count = 0;
273  PRUint32 size = 0;
274  CK_OBJECT_CLASS objClass;
275
276  /*
277   * first handle the static build in objects (if any)
278   */
279  for( i = 0; i < nss_ckmk_nObjects; i++ ) {
280    ckmkInternalObject *o = (ckmkInternalObject *)&nss_ckmk_data[i];
281
282    if( CK_TRUE == ckmk_match(pTemplate, ulAttributeCount, o) ) {
283      PUT_OBJECT(o, *pError, size, count, *listp);
284    }
285  }
286
287  /*
288   * now handle the various object types
289   */
290  objClass = nss_ckmk_GetULongAttribute(CKA_CLASS, 
291		pTemplate, ulAttributeCount, pError);
292  if (CKR_OK != *pError) {
293    objClass = CK_INVALID_HANDLE;
294  }
295  *pError = CKR_OK;
296  switch (objClass) {
297  case CKO_CERTIFICATE:
298    count = collect_class(objClass, kSecCertificateItemClass,
299                              pTemplate, ulAttributeCount, listp, 
300                              &size, count, pError);
301    break;
302  case CKO_PUBLIC_KEY:
303    count = collect_class(objClass,  CSSM_DL_DB_RECORD_PUBLIC_KEY,
304                              pTemplate, ulAttributeCount, listp, 
305                              &size, count, pError);
306    break;
307  case CKO_PRIVATE_KEY:
308    count = collect_class(objClass,  CSSM_DL_DB_RECORD_PRIVATE_KEY,
309                              pTemplate, ulAttributeCount, listp, 
310                              &size, count, pError);
311    break;
312  /* all of them */
313  case CK_INVALID_HANDLE:
314    count = collect_class(CKO_CERTIFICATE, kSecCertificateItemClass,
315                              pTemplate, ulAttributeCount, listp, 
316                              &size, count, pError);
317    count = collect_class(CKO_PUBLIC_KEY,  CSSM_DL_DB_RECORD_PUBLIC_KEY,
318                              pTemplate, ulAttributeCount, listp, 
319                              &size, count, pError);
320    count = collect_class(CKO_PUBLIC_KEY,  CSSM_DL_DB_RECORD_PRIVATE_KEY,
321                              pTemplate, ulAttributeCount, listp, 
322                              &size, count, pError);
323    break;
324  default:
325    break;
326  }
327  if (CKR_OK != *pError) {
328    goto loser;
329  }
330
331  return count;
332loser:
333  nss_ZFreeIf(*listp);
334  return 0;
335}
336
337
338NSS_IMPLEMENT NSSCKMDFindObjects *
339nss_ckmk_FindObjectsInit
340(
341  NSSCKFWSession *fwSession,
342  CK_ATTRIBUTE_PTR pTemplate,
343  CK_ULONG ulAttributeCount,
344  CK_RV *pError
345)
346{
347  /* This could be made more efficient.  I'm rather rushed. */
348  NSSArena *arena;
349  NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL;
350  struct ckmkFOStr *fo = (struct ckmkFOStr *)NULL;
351  ckmkInternalObject **temp = (ckmkInternalObject **)NULL;
352
353  arena = NSSArena_Create();
354  if( (NSSArena *)NULL == arena ) {
355    goto loser;
356  }
357
358  rv = nss_ZNEW(arena, NSSCKMDFindObjects);
359  if( (NSSCKMDFindObjects *)NULL == rv ) {
360    *pError = CKR_HOST_MEMORY;
361    goto loser;
362  }
363
364  fo = nss_ZNEW(arena, struct ckmkFOStr);
365  if( (struct ckmkFOStr *)NULL == fo ) {
366    *pError = CKR_HOST_MEMORY;
367    goto loser;
368  }
369
370  fo->arena = arena;
371  /* fo->n and fo->i are already zero */
372
373  rv->etc = (void *)fo;
374  rv->Final = ckmk_mdFindObjects_Final;
375  rv->Next = ckmk_mdFindObjects_Next;
376  rv->null = (void *)NULL;
377
378  fo->n = collect_objects(pTemplate, ulAttributeCount, &temp, pError);
379  if (*pError != CKR_OK) {
380    goto loser;
381  }
382
383  fo->objs = nss_ZNEWARRAY(arena, ckmkInternalObject *, fo->n);
384  if( (ckmkInternalObject **)NULL == fo->objs ) {
385    *pError = CKR_HOST_MEMORY;
386    goto loser;
387  }
388
389  (void)nsslibc_memcpy(fo->objs, temp, sizeof(ckmkInternalObject *) * fo->n);
390  nss_ZFreeIf(temp);
391  temp = (ckmkInternalObject **)NULL;
392
393  return rv;
394
395 loser:
396  nss_ZFreeIf(temp);
397  nss_ZFreeIf(fo);
398  nss_ZFreeIf(rv);
399  if ((NSSArena *)NULL != arena) {
400     NSSArena_Destroy(arena);
401  }
402  return (NSSCKMDFindObjects *)NULL;
403}
404