bfind.c (6824B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef BUILTINS_H 6 #include "builtins.h" 7 #endif /* BUILTINS_H */ 8 9 /* 10 * builtins/find.c 11 * 12 * This file implements the NSSCKMDFindObjects object for the 13 * "builtin objects" cryptoki module. 14 */ 15 16 struct builtinsFOStr { 17 NSSArena *arena; 18 CK_ULONG n; 19 CK_ULONG i; 20 builtinsInternalObject **objs; 21 }; 22 23 static void 24 builtins_mdFindObjects_Final( 25 NSSCKMDFindObjects *mdFindObjects, 26 NSSCKFWFindObjects *fwFindObjects, 27 NSSCKMDSession *mdSession, 28 NSSCKFWSession *fwSession, 29 NSSCKMDToken *mdToken, 30 NSSCKFWToken *fwToken, 31 NSSCKMDInstance *mdInstance, 32 NSSCKFWInstance *fwInstance) 33 { 34 struct builtinsFOStr *fo = (struct builtinsFOStr *)mdFindObjects->etc; 35 NSSArena *arena = fo->arena; 36 37 nss_ZFreeIf(fo->objs); 38 nss_ZFreeIf(fo); 39 nss_ZFreeIf(mdFindObjects); 40 if ((NSSArena *)NULL != arena) { 41 NSSArena_Destroy(arena); 42 } 43 44 return; 45 } 46 47 static NSSCKMDObject * 48 builtins_mdFindObjects_Next( 49 NSSCKMDFindObjects *mdFindObjects, 50 NSSCKFWFindObjects *fwFindObjects, 51 NSSCKMDSession *mdSession, 52 NSSCKFWSession *fwSession, 53 NSSCKMDToken *mdToken, 54 NSSCKFWToken *fwToken, 55 NSSCKMDInstance *mdInstance, 56 NSSCKFWInstance *fwInstance, 57 NSSArena *arena, 58 CK_RV *pError) 59 { 60 struct builtinsFOStr *fo = (struct builtinsFOStr *)mdFindObjects->etc; 61 builtinsInternalObject *io; 62 63 if (fo->i == fo->n) { 64 *pError = CKR_OK; 65 return (NSSCKMDObject *)NULL; 66 } 67 68 io = fo->objs[fo->i]; 69 fo->i++; 70 71 return nss_builtins_CreateMDObject(arena, io, pError); 72 } 73 74 static int 75 builtins_derUnwrapInt(unsigned char *src, int size, unsigned char **dest) 76 { 77 unsigned char *start = src; 78 int len = 0; 79 80 if (*src++ != 2) { 81 return 0; 82 } 83 len = *src++; 84 if (len & 0x80) { 85 int count = len & 0x7f; 86 len = 0; 87 88 if (count + 2 > size) { 89 return 0; 90 } 91 while (count-- > 0) { 92 len = (len << 8) | *src++; 93 } 94 } 95 if (len + (src - start) != size) { 96 return 0; 97 } 98 *dest = src; 99 return len; 100 } 101 102 static CK_BBOOL 103 builtins_attrmatch( 104 CK_ATTRIBUTE_PTR a, 105 const NSSItem *b) 106 { 107 PRBool prb; 108 109 if (a->ulValueLen != b->size) { 110 /* match a decoded serial number */ 111 if ((a->type == CKA_SERIAL_NUMBER) && (a->ulValueLen < b->size)) { 112 int len; 113 unsigned char *data = NULL; 114 115 len = builtins_derUnwrapInt(b->data, b->size, &data); 116 if (data && 117 (len == a->ulValueLen) && 118 nsslibc_memequal(a->pValue, data, len, (PRStatus *)NULL)) { 119 return CK_TRUE; 120 } 121 } 122 return CK_FALSE; 123 } 124 125 prb = nsslibc_memequal(a->pValue, b->data, b->size, (PRStatus *)NULL); 126 127 if (PR_TRUE == prb) { 128 return CK_TRUE; 129 } else { 130 return CK_FALSE; 131 } 132 } 133 134 static CK_BBOOL 135 builtins_match( 136 CK_ATTRIBUTE_PTR pTemplate, 137 CK_ULONG ulAttributeCount, 138 builtinsInternalObject *o) 139 { 140 CK_ULONG i; 141 142 for (i = 0; i < ulAttributeCount; i++) { 143 CK_ULONG j; 144 145 for (j = 0; j < o->n; j++) { 146 if (o->types[j] == pTemplate[i].type) { 147 if (CK_FALSE == builtins_attrmatch(&pTemplate[i], &o->items[j])) { 148 return CK_FALSE; 149 } else { 150 break; 151 } 152 } 153 } 154 155 if (j == o->n) { 156 /* Loop ran to the end: no matching attribute */ 157 return CK_FALSE; 158 } 159 } 160 161 /* Every attribute passed */ 162 return CK_TRUE; 163 } 164 165 NSS_IMPLEMENT NSSCKMDFindObjects * 166 nss_builtins_FindObjectsInit( 167 NSSCKFWSession *fwSession, 168 CK_ATTRIBUTE_PTR pTemplate, 169 CK_ULONG ulAttributeCount, 170 CK_RV *pError) 171 { 172 /* This could be made more efficient. I'm rather rushed. */ 173 NSSArena *arena; 174 NSSCKMDFindObjects *rv = (NSSCKMDFindObjects *)NULL; 175 struct builtinsFOStr *fo = (struct builtinsFOStr *)NULL; 176 177 /* 178 * 99% of the time we get 0 or 1 matches. So we start with a small 179 * stack-allocated array to hold the matches and switch to a heap-allocated 180 * array later if the number of matches exceeds STACK_BUF_LENGTH. 181 */ 182 #define STACK_BUF_LENGTH 1 183 builtinsInternalObject *stackTemp[STACK_BUF_LENGTH]; 184 builtinsInternalObject **temp = stackTemp; 185 PRBool tempIsHeapAllocated = PR_FALSE; 186 PRUint32 i; 187 188 arena = NSSArena_Create(); 189 if ((NSSArena *)NULL == arena) { 190 goto loser; 191 } 192 193 rv = nss_ZNEW(arena, NSSCKMDFindObjects); 194 if ((NSSCKMDFindObjects *)NULL == rv) { 195 *pError = CKR_HOST_MEMORY; 196 goto loser; 197 } 198 199 fo = nss_ZNEW(arena, struct builtinsFOStr); 200 if ((struct builtinsFOStr *)NULL == fo) { 201 *pError = CKR_HOST_MEMORY; 202 goto loser; 203 } 204 205 fo->arena = arena; 206 /* fo->n and fo->i are already zero */ 207 208 rv->etc = (void *)fo; 209 rv->Final = builtins_mdFindObjects_Final; 210 rv->Next = builtins_mdFindObjects_Next; 211 rv->null = (void *)NULL; 212 213 for (i = 0; i < nss_builtins_nObjects; i++) { 214 builtinsInternalObject *o = (builtinsInternalObject *)&nss_builtins_data[i]; 215 216 if (CK_TRUE == builtins_match(pTemplate, ulAttributeCount, o)) { 217 if (fo->n == STACK_BUF_LENGTH) { 218 /* Switch from the small stack array to a heap-allocated array large 219 * enough to handle matches in all remaining cases. */ 220 temp = nss_ZNEWARRAY((NSSArena *)NULL, builtinsInternalObject *, 221 fo->n + nss_builtins_nObjects - i); 222 if ((builtinsInternalObject **)NULL == temp) { 223 *pError = 224 CKR_HOST_MEMORY; 225 goto loser; 226 } 227 tempIsHeapAllocated = PR_TRUE; 228 (void)nsslibc_memcpy(temp, stackTemp, 229 sizeof(builtinsInternalObject *) * fo->n); 230 } 231 232 temp[fo->n] = o; 233 fo->n++; 234 } 235 } 236 237 fo->objs = nss_ZNEWARRAY(arena, builtinsInternalObject *, fo->n); 238 if ((builtinsInternalObject **)NULL == fo->objs) { 239 *pError = CKR_HOST_MEMORY; 240 goto loser; 241 } 242 243 (void)nsslibc_memcpy(fo->objs, temp, sizeof(builtinsInternalObject *) * fo->n); 244 if (tempIsHeapAllocated) { 245 nss_ZFreeIf(temp); 246 temp = (builtinsInternalObject **)NULL; 247 } 248 249 return rv; 250 251 loser: 252 if (tempIsHeapAllocated) { 253 nss_ZFreeIf(temp); 254 } 255 nss_ZFreeIf(fo); 256 nss_ZFreeIf(rv); 257 if ((NSSArena *)NULL != arena) { 258 NSSArena_Destroy(arena); 259 } 260 return (NSSCKMDFindObjects *)NULL; 261 }