Mercurial > trustbridge > nss-cmake-static
comparison nss/lib/softoken/legacydb/lgattr.c @ 3:150b72113545
Add DBM and legacydb support
author | Andre Heinecke <andre.heinecke@intevation.de> |
---|---|
date | Tue, 05 Aug 2014 18:32:02 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:a945361df361 | 3:150b72113545 |
---|---|
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 * Internal PKCS #11 functions. Should only be called by pkcs11.c | |
6 */ | |
7 #include "pkcs11.h" | |
8 #include "lgdb.h" | |
9 | |
10 #include "pcertt.h" | |
11 #include "lowkeyi.h" | |
12 #include "pcert.h" | |
13 #include "blapi.h" | |
14 #include "secerr.h" | |
15 #include "secasn1.h" | |
16 | |
17 /* | |
18 * Cache the object we are working on during Set's and Get's | |
19 */ | |
20 typedef struct LGObjectCacheStr { | |
21 CK_OBJECT_CLASS objclass; | |
22 CK_OBJECT_HANDLE handle; | |
23 SDB *sdb; | |
24 void *objectInfo; | |
25 LGFreeFunc infoFree; | |
26 SECItem dbKey; | |
27 } LGObjectCache; | |
28 | |
29 static const CK_OBJECT_HANDLE lg_classArray[] = { | |
30 0, CKO_PRIVATE_KEY, CKO_PUBLIC_KEY, CKO_SECRET_KEY, | |
31 CKO_NSS_TRUST, CKO_NSS_CRL, CKO_NSS_SMIME, | |
32 CKO_CERTIFICATE }; | |
33 | |
34 #define handleToClass(handle) \ | |
35 lg_classArray[((handle & LG_TOKEN_TYPE_MASK))>>LG_TOKEN_TYPE_SHIFT] | |
36 | |
37 | |
38 static void lg_DestroyObjectCache(LGObjectCache *obj); | |
39 | |
40 static LGObjectCache * | |
41 lg_NewObjectCache(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE handle) | |
42 { | |
43 LGObjectCache *obj = NULL; | |
44 SECStatus rv; | |
45 | |
46 obj = PORT_New(LGObjectCache); | |
47 if (obj == NULL) { | |
48 return NULL; | |
49 } | |
50 | |
51 obj->objclass = handleToClass(handle); | |
52 obj->handle = handle; | |
53 obj->sdb = sdb; | |
54 obj->objectInfo = NULL; | |
55 obj->infoFree = NULL; | |
56 obj->dbKey.data = NULL; | |
57 obj->dbKey.len = 0; | |
58 lg_DBLock(sdb); | |
59 if (dbKey == NULL) { | |
60 dbKey = lg_lookupTokenKeyByHandle(sdb,handle); | |
61 } | |
62 if (dbKey == NULL) { | |
63 lg_DBUnlock(sdb); | |
64 goto loser; | |
65 } | |
66 rv = SECITEM_CopyItem(NULL,&obj->dbKey,dbKey); | |
67 lg_DBUnlock(sdb); | |
68 if (rv != SECSuccess) { | |
69 goto loser; | |
70 } | |
71 | |
72 return obj; | |
73 loser: | |
74 if (obj) { | |
75 (void) lg_DestroyObjectCache(obj); | |
76 } | |
77 return NULL; | |
78 | |
79 } | |
80 | |
81 /* | |
82 * free all the data associated with an object. Object reference count must | |
83 * be 'zero'. | |
84 */ | |
85 static void | |
86 lg_DestroyObjectCache(LGObjectCache *obj) | |
87 { | |
88 if (obj->dbKey.data) { | |
89 PORT_Free(obj->dbKey.data); | |
90 obj->dbKey.data = NULL; | |
91 } | |
92 if (obj->objectInfo) { | |
93 (*obj->infoFree)(obj->objectInfo); | |
94 obj->objectInfo = NULL; | |
95 obj->infoFree = NULL; | |
96 } | |
97 PORT_Free(obj); | |
98 } | |
99 /* | |
100 * ******************** Attribute Utilities ******************************* | |
101 */ | |
102 | |
103 static CK_RV | |
104 lg_ULongAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, CK_ULONG value) | |
105 { | |
106 unsigned char *data; | |
107 int i; | |
108 | |
109 if (attr->pValue == NULL) { | |
110 attr->ulValueLen = 4; | |
111 return CKR_OK; | |
112 } | |
113 if (attr->ulValueLen < 4) { | |
114 attr->ulValueLen = (CK_ULONG) -1; | |
115 return CKR_BUFFER_TOO_SMALL; | |
116 } | |
117 | |
118 data = (unsigned char *)attr->pValue; | |
119 for (i=0; i < 4; i++) { | |
120 data[i] = (value >> ((3-i)*8)) & 0xff; | |
121 } | |
122 attr->ulValueLen = 4; | |
123 return CKR_OK; | |
124 } | |
125 | |
126 static CK_RV | |
127 lg_CopyAttribute(CK_ATTRIBUTE *attr, CK_ATTRIBUTE_TYPE type, | |
128 CK_VOID_PTR value, CK_ULONG len) | |
129 { | |
130 | |
131 if (attr->pValue == NULL) { | |
132 attr->ulValueLen = len; | |
133 return CKR_OK; | |
134 } | |
135 if (attr->ulValueLen < len) { | |
136 attr->ulValueLen = (CK_ULONG) -1; | |
137 return CKR_BUFFER_TOO_SMALL; | |
138 } | |
139 PORT_Memcpy(attr->pValue,value,len); | |
140 attr->ulValueLen = len; | |
141 return CKR_OK; | |
142 } | |
143 | |
144 static CK_RV | |
145 lg_CopyAttributeSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, | |
146 void *value, CK_ULONG len) | |
147 { | |
148 unsigned char * dval = (unsigned char *)value; | |
149 if (*dval == 0) { | |
150 dval++; | |
151 len--; | |
152 } | |
153 return lg_CopyAttribute(attribute,type,dval,len); | |
154 } | |
155 | |
156 static CK_RV | |
157 lg_CopyPrivAttribute(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, | |
158 void *value, CK_ULONG len, SDB *sdbpw) | |
159 { | |
160 SECItem plainText, *cipherText = NULL; | |
161 CK_RV crv = CKR_USER_NOT_LOGGED_IN; | |
162 SECStatus rv; | |
163 | |
164 plainText.data = value; | |
165 plainText.len = len; | |
166 rv = lg_util_encrypt(NULL, sdbpw, &plainText, &cipherText); | |
167 if (rv != SECSuccess) { | |
168 goto loser; | |
169 } | |
170 crv = lg_CopyAttribute(attribute,type,cipherText->data,cipherText->len); | |
171 loser: | |
172 if (cipherText) { | |
173 SECITEM_FreeItem(cipherText,PR_TRUE); | |
174 } | |
175 return crv; | |
176 } | |
177 | |
178 static CK_RV | |
179 lg_CopyPrivAttrSigned(CK_ATTRIBUTE *attribute, CK_ATTRIBUTE_TYPE type, | |
180 void *value, CK_ULONG len, SDB *sdbpw) | |
181 { | |
182 unsigned char * dval = (unsigned char *)value; | |
183 | |
184 if (*dval == 0) { | |
185 dval++; | |
186 len--; | |
187 } | |
188 return lg_CopyPrivAttribute(attribute,type,dval,len,sdbpw); | |
189 } | |
190 | |
191 static CK_RV | |
192 lg_invalidAttribute(CK_ATTRIBUTE *attr) | |
193 { | |
194 attr->ulValueLen = (CK_ULONG) -1; | |
195 return CKR_ATTRIBUTE_TYPE_INVALID; | |
196 } | |
197 | |
198 | |
199 #define LG_DEF_ATTRIBUTE(value,len) \ | |
200 { 0, value, len } | |
201 | |
202 #define LG_CLONE_ATTR(attribute, type, staticAttr) \ | |
203 lg_CopyAttribute(attribute, type, staticAttr.pValue, staticAttr.ulValueLen) | |
204 | |
205 CK_BBOOL lg_staticTrueValue = CK_TRUE; | |
206 CK_BBOOL lg_staticFalseValue = CK_FALSE; | |
207 static const CK_ATTRIBUTE lg_StaticTrueAttr = | |
208 LG_DEF_ATTRIBUTE(&lg_staticTrueValue,sizeof(lg_staticTrueValue)); | |
209 static const CK_ATTRIBUTE lg_StaticFalseAttr = | |
210 LG_DEF_ATTRIBUTE(&lg_staticFalseValue,sizeof(lg_staticFalseValue)); | |
211 static const CK_ATTRIBUTE lg_StaticNullAttr = LG_DEF_ATTRIBUTE(NULL,0); | |
212 char lg_StaticOneValue = 1; | |
213 static const CK_ATTRIBUTE lg_StaticOneAttr = | |
214 LG_DEF_ATTRIBUTE(&lg_StaticOneValue,sizeof(lg_StaticOneValue)); | |
215 | |
216 /* | |
217 * helper functions which get the database and call the underlying | |
218 * low level database function. | |
219 */ | |
220 static char * | |
221 lg_FindKeyNicknameByPublicKey(SDB *sdb, SECItem *dbKey) | |
222 { | |
223 NSSLOWKEYDBHandle *keyHandle; | |
224 char * label; | |
225 | |
226 keyHandle = lg_getKeyDB(sdb); | |
227 if (!keyHandle) { | |
228 return NULL; | |
229 } | |
230 | |
231 label = nsslowkey_FindKeyNicknameByPublicKey(keyHandle, dbKey, | |
232 sdb); | |
233 return label; | |
234 } | |
235 | |
236 | |
237 NSSLOWKEYPrivateKey * | |
238 lg_FindKeyByPublicKey(SDB *sdb, SECItem *dbKey) | |
239 { | |
240 NSSLOWKEYPrivateKey *privKey; | |
241 NSSLOWKEYDBHandle *keyHandle; | |
242 | |
243 keyHandle = lg_getKeyDB(sdb); | |
244 if (keyHandle == NULL) { | |
245 return NULL; | |
246 } | |
247 privKey = nsslowkey_FindKeyByPublicKey(keyHandle, dbKey, sdb); | |
248 if (privKey == NULL) { | |
249 return NULL; | |
250 } | |
251 return privKey; | |
252 } | |
253 | |
254 static certDBEntrySMime * | |
255 lg_getSMime(LGObjectCache *obj) | |
256 { | |
257 certDBEntrySMime *entry; | |
258 NSSLOWCERTCertDBHandle *certHandle; | |
259 | |
260 if (obj->objclass != CKO_NSS_SMIME) { | |
261 return NULL; | |
262 } | |
263 if (obj->objectInfo) { | |
264 return (certDBEntrySMime *)obj->objectInfo; | |
265 } | |
266 | |
267 certHandle = lg_getCertDB(obj->sdb); | |
268 if (!certHandle) { | |
269 return NULL; | |
270 } | |
271 entry = nsslowcert_ReadDBSMimeEntry(certHandle, (char *)obj->dbKey.data); | |
272 obj->objectInfo = (void *)entry; | |
273 obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry; | |
274 return entry; | |
275 } | |
276 | |
277 static certDBEntryRevocation * | |
278 lg_getCrl(LGObjectCache *obj) | |
279 { | |
280 certDBEntryRevocation *crl; | |
281 PRBool isKrl; | |
282 NSSLOWCERTCertDBHandle *certHandle; | |
283 | |
284 if (obj->objclass != CKO_NSS_CRL) { | |
285 return NULL; | |
286 } | |
287 if (obj->objectInfo) { | |
288 return (certDBEntryRevocation *)obj->objectInfo; | |
289 } | |
290 | |
291 isKrl = (PRBool) (obj->handle == LG_TOKEN_KRL_HANDLE); | |
292 certHandle = lg_getCertDB(obj->sdb); | |
293 if (!certHandle) { | |
294 return NULL; | |
295 } | |
296 | |
297 crl = nsslowcert_FindCrlByKey(certHandle, &obj->dbKey, isKrl); | |
298 obj->objectInfo = (void *)crl; | |
299 obj->infoFree = (LGFreeFunc) nsslowcert_DestroyDBEntry; | |
300 return crl; | |
301 } | |
302 | |
303 static NSSLOWCERTCertificate * | |
304 lg_getCert(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle) | |
305 { | |
306 NSSLOWCERTCertificate *cert; | |
307 CK_OBJECT_CLASS objClass = obj->objclass; | |
308 | |
309 if ((objClass != CKO_CERTIFICATE) && (objClass != CKO_NSS_TRUST)) { | |
310 return NULL; | |
311 } | |
312 if (objClass == CKO_CERTIFICATE && obj->objectInfo) { | |
313 return (NSSLOWCERTCertificate *)obj->objectInfo; | |
314 } | |
315 cert = nsslowcert_FindCertByKey(certHandle, &obj->dbKey); | |
316 if (objClass == CKO_CERTIFICATE) { | |
317 obj->objectInfo = (void *)cert; | |
318 obj->infoFree = (LGFreeFunc) nsslowcert_DestroyCertificate ; | |
319 } | |
320 return cert; | |
321 } | |
322 | |
323 static NSSLOWCERTTrust * | |
324 lg_getTrust(LGObjectCache *obj, NSSLOWCERTCertDBHandle *certHandle) | |
325 { | |
326 NSSLOWCERTTrust *trust; | |
327 | |
328 if (obj->objclass != CKO_NSS_TRUST) { | |
329 return NULL; | |
330 } | |
331 if (obj->objectInfo) { | |
332 return (NSSLOWCERTTrust *)obj->objectInfo; | |
333 } | |
334 trust = nsslowcert_FindTrustByKey(certHandle, &obj->dbKey); | |
335 obj->objectInfo = (void *)trust; | |
336 obj->infoFree = (LGFreeFunc) nsslowcert_DestroyTrust ; | |
337 return trust; | |
338 } | |
339 | |
340 static NSSLOWKEYPublicKey * | |
341 lg_GetPublicKey(LGObjectCache *obj) | |
342 { | |
343 NSSLOWKEYPublicKey *pubKey; | |
344 NSSLOWKEYPrivateKey *privKey; | |
345 | |
346 if (obj->objclass != CKO_PUBLIC_KEY) { | |
347 return NULL; | |
348 } | |
349 if (obj->objectInfo) { | |
350 return (NSSLOWKEYPublicKey *)obj->objectInfo; | |
351 } | |
352 privKey = lg_FindKeyByPublicKey(obj->sdb, &obj->dbKey); | |
353 if (privKey == NULL) { | |
354 return NULL; | |
355 } | |
356 pubKey = lg_nsslowkey_ConvertToPublicKey(privKey); | |
357 lg_nsslowkey_DestroyPrivateKey(privKey); | |
358 obj->objectInfo = (void *) pubKey; | |
359 obj->infoFree = (LGFreeFunc) lg_nsslowkey_DestroyPublicKey ; | |
360 return pubKey; | |
361 } | |
362 | |
363 /* | |
364 * we need two versions of lg_GetPrivateKey. One version that takes the | |
365 * DB handle so we can pass the handle we have already acquired in, | |
366 * rather than going through the 'getKeyDB' code again, | |
367 * which may fail the second time and another which just aquires | |
368 * the key handle from the sdb (where we don't already have a key handle. | |
369 * This version does the former. | |
370 */ | |
371 static NSSLOWKEYPrivateKey * | |
372 lg_GetPrivateKeyWithDB(LGObjectCache *obj, NSSLOWKEYDBHandle *keyHandle) | |
373 { | |
374 NSSLOWKEYPrivateKey *privKey; | |
375 | |
376 if ((obj->objclass != CKO_PRIVATE_KEY) && | |
377 (obj->objclass != CKO_SECRET_KEY)) { | |
378 return NULL; | |
379 } | |
380 if (obj->objectInfo) { | |
381 return (NSSLOWKEYPrivateKey *)obj->objectInfo; | |
382 } | |
383 privKey = nsslowkey_FindKeyByPublicKey(keyHandle, &obj->dbKey, obj->sdb); | |
384 if (privKey == NULL) { | |
385 return NULL; | |
386 } | |
387 obj->objectInfo = (void *) privKey; | |
388 obj->infoFree = (LGFreeFunc) lg_nsslowkey_DestroyPrivateKey ; | |
389 return privKey; | |
390 } | |
391 | |
392 /* this version does the latter */ | |
393 static NSSLOWKEYPrivateKey * | |
394 lg_GetPrivateKey(LGObjectCache *obj) | |
395 { | |
396 NSSLOWKEYDBHandle *keyHandle; | |
397 NSSLOWKEYPrivateKey *privKey; | |
398 | |
399 keyHandle = lg_getKeyDB(obj->sdb); | |
400 if (!keyHandle) { | |
401 return NULL; | |
402 } | |
403 privKey = lg_GetPrivateKeyWithDB(obj, keyHandle); | |
404 return privKey; | |
405 } | |
406 | |
407 /* lg_GetPubItem returns data associated with the public key. | |
408 * one only needs to free the public key. This comment is here | |
409 * because this sematic would be non-obvious otherwise. All callers | |
410 * should include this comment. | |
411 */ | |
412 static SECItem * | |
413 lg_GetPubItem(NSSLOWKEYPublicKey *pubKey) { | |
414 SECItem *pubItem = NULL; | |
415 /* get value to compare from the cert's public key */ | |
416 switch ( pubKey->keyType ) { | |
417 case NSSLOWKEYRSAKey: | |
418 pubItem = &pubKey->u.rsa.modulus; | |
419 break; | |
420 case NSSLOWKEYDSAKey: | |
421 pubItem = &pubKey->u.dsa.publicValue; | |
422 break; | |
423 case NSSLOWKEYDHKey: | |
424 pubItem = &pubKey->u.dh.publicValue; | |
425 break; | |
426 #ifndef NSS_DISABLE_ECC | |
427 case NSSLOWKEYECKey: | |
428 pubItem = &pubKey->u.ec.publicValue; | |
429 break; | |
430 #endif /* NSS_DISABLE_ECC */ | |
431 default: | |
432 break; | |
433 } | |
434 return pubItem; | |
435 } | |
436 | |
437 static const SEC_ASN1Template lg_SerialTemplate[] = { | |
438 { SEC_ASN1_INTEGER, offsetof(NSSLOWCERTCertificate,serialNumber) }, | |
439 { 0 } | |
440 }; | |
441 | |
442 static CK_RV | |
443 lg_FindRSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, | |
444 CK_ATTRIBUTE *attribute) | |
445 { | |
446 unsigned char hash[SHA1_LENGTH]; | |
447 CK_KEY_TYPE keyType = CKK_RSA; | |
448 | |
449 switch (type) { | |
450 case CKA_KEY_TYPE: | |
451 return lg_ULongAttribute(attribute, type, keyType); | |
452 case CKA_ID: | |
453 SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); | |
454 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
455 case CKA_DERIVE: | |
456 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
457 case CKA_ENCRYPT: | |
458 case CKA_VERIFY: | |
459 case CKA_VERIFY_RECOVER: | |
460 case CKA_WRAP: | |
461 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
462 case CKA_MODULUS: | |
463 return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data, | |
464 key->u.rsa.modulus.len); | |
465 case CKA_PUBLIC_EXPONENT: | |
466 return lg_CopyAttributeSigned(attribute, type, | |
467 key->u.rsa.publicExponent.data, | |
468 key->u.rsa.publicExponent.len); | |
469 default: | |
470 break; | |
471 } | |
472 return lg_invalidAttribute(attribute); | |
473 } | |
474 | |
475 static CK_RV | |
476 lg_FindDSAPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, | |
477 CK_ATTRIBUTE *attribute) | |
478 { | |
479 unsigned char hash[SHA1_LENGTH]; | |
480 CK_KEY_TYPE keyType = CKK_DSA; | |
481 | |
482 switch (type) { | |
483 case CKA_KEY_TYPE: | |
484 return lg_ULongAttribute(attribute, type, keyType); | |
485 case CKA_ID: | |
486 SHA1_HashBuf(hash,key->u.dsa.publicValue.data, | |
487 key->u.dsa.publicValue.len); | |
488 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
489 case CKA_DERIVE: | |
490 case CKA_ENCRYPT: | |
491 case CKA_VERIFY_RECOVER: | |
492 case CKA_WRAP: | |
493 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
494 case CKA_VERIFY: | |
495 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
496 case CKA_VALUE: | |
497 return lg_CopyAttributeSigned(attribute,type, | |
498 key->u.dsa.publicValue.data, | |
499 key->u.dsa.publicValue.len); | |
500 case CKA_PRIME: | |
501 return lg_CopyAttributeSigned(attribute,type, | |
502 key->u.dsa.params.prime.data, | |
503 key->u.dsa.params.prime.len); | |
504 case CKA_SUBPRIME: | |
505 return lg_CopyAttributeSigned(attribute,type, | |
506 key->u.dsa.params.subPrime.data, | |
507 key->u.dsa.params.subPrime.len); | |
508 case CKA_BASE: | |
509 return lg_CopyAttributeSigned(attribute,type, | |
510 key->u.dsa.params.base.data, | |
511 key->u.dsa.params.base.len); | |
512 default: | |
513 break; | |
514 } | |
515 return lg_invalidAttribute(attribute); | |
516 } | |
517 | |
518 static CK_RV | |
519 lg_FindDHPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, | |
520 CK_ATTRIBUTE *attribute) | |
521 { | |
522 unsigned char hash[SHA1_LENGTH]; | |
523 CK_KEY_TYPE keyType = CKK_DH; | |
524 | |
525 switch (type) { | |
526 case CKA_KEY_TYPE: | |
527 return lg_ULongAttribute(attribute, type, keyType); | |
528 case CKA_ID: | |
529 SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); | |
530 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
531 case CKA_DERIVE: | |
532 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
533 case CKA_ENCRYPT: | |
534 case CKA_VERIFY: | |
535 case CKA_VERIFY_RECOVER: | |
536 case CKA_WRAP: | |
537 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
538 case CKA_VALUE: | |
539 return lg_CopyAttributeSigned(attribute,type, | |
540 key->u.dh.publicValue.data, | |
541 key->u.dh.publicValue.len); | |
542 case CKA_PRIME: | |
543 return lg_CopyAttributeSigned(attribute,type,key->u.dh.prime.data, | |
544 key->u.dh.prime.len); | |
545 case CKA_BASE: | |
546 return lg_CopyAttributeSigned(attribute,type,key->u.dh.base.data, | |
547 key->u.dh.base.len); | |
548 default: | |
549 break; | |
550 } | |
551 return lg_invalidAttribute(attribute); | |
552 } | |
553 | |
554 #ifndef NSS_DISABLE_ECC | |
555 static CK_RV | |
556 lg_FindECPublicKeyAttribute(NSSLOWKEYPublicKey *key, CK_ATTRIBUTE_TYPE type, | |
557 CK_ATTRIBUTE *attribute) | |
558 { | |
559 unsigned char hash[SHA1_LENGTH]; | |
560 CK_KEY_TYPE keyType = CKK_EC; | |
561 | |
562 switch (type) { | |
563 case CKA_KEY_TYPE: | |
564 return lg_ULongAttribute(attribute, type, keyType); | |
565 case CKA_ID: | |
566 SHA1_HashBuf(hash, key->u.ec.publicValue.data, | |
567 key->u.ec.publicValue.len); | |
568 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
569 case CKA_DERIVE: | |
570 case CKA_VERIFY: | |
571 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
572 case CKA_ENCRYPT: | |
573 case CKA_VERIFY_RECOVER: | |
574 case CKA_WRAP: | |
575 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
576 case CKA_EC_PARAMS: | |
577 return lg_CopyAttributeSigned(attribute,type, | |
578 key->u.ec.ecParams.DEREncoding.data, | |
579 key->u.ec.ecParams.DEREncoding.len); | |
580 case CKA_EC_POINT: | |
581 if (getenv("NSS_USE_DECODED_CKA_EC_POINT")) { | |
582 return lg_CopyAttributeSigned(attribute, type, | |
583 key->u.ec.publicValue.data, | |
584 key->u.ec.publicValue.len); | |
585 } else { | |
586 SECItem *pubValue = SEC_ASN1EncodeItem(NULL, NULL, | |
587 &(key->u.ec.publicValue), | |
588 SEC_ASN1_GET(SEC_OctetStringTemplate)); | |
589 CK_RV crv; | |
590 if (!pubValue) { | |
591 return CKR_HOST_MEMORY; | |
592 } | |
593 crv = lg_CopyAttributeSigned(attribute, type, | |
594 pubValue->data, | |
595 pubValue->len); | |
596 SECITEM_FreeItem(pubValue, PR_TRUE); | |
597 return crv; | |
598 } | |
599 default: | |
600 break; | |
601 } | |
602 return lg_invalidAttribute(attribute); | |
603 } | |
604 #endif /* NSS_DISABLE_ECC */ | |
605 | |
606 | |
607 static CK_RV | |
608 lg_FindPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
609 CK_ATTRIBUTE *attribute) | |
610 { | |
611 NSSLOWKEYPublicKey *key; | |
612 CK_RV crv; | |
613 char *label; | |
614 | |
615 switch (type) { | |
616 case CKA_PRIVATE: | |
617 case CKA_SENSITIVE: | |
618 case CKA_ALWAYS_SENSITIVE: | |
619 case CKA_NEVER_EXTRACTABLE: | |
620 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
621 case CKA_MODIFIABLE: | |
622 case CKA_EXTRACTABLE: | |
623 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
624 case CKA_SUBJECT: | |
625 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
626 case CKA_START_DATE: | |
627 case CKA_END_DATE: | |
628 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
629 case CKA_LABEL: | |
630 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); | |
631 if (label == NULL) { | |
632 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
633 } | |
634 crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label)); | |
635 PORT_Free(label); | |
636 return crv; | |
637 default: | |
638 break; | |
639 } | |
640 | |
641 key = lg_GetPublicKey(obj); | |
642 if (key == NULL) { | |
643 if (type == CKA_ID) { | |
644 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
645 } | |
646 return CKR_OBJECT_HANDLE_INVALID; | |
647 } | |
648 | |
649 switch (key->keyType) { | |
650 case NSSLOWKEYRSAKey: | |
651 return lg_FindRSAPublicKeyAttribute(key,type,attribute); | |
652 case NSSLOWKEYDSAKey: | |
653 return lg_FindDSAPublicKeyAttribute(key,type,attribute); | |
654 case NSSLOWKEYDHKey: | |
655 return lg_FindDHPublicKeyAttribute(key,type,attribute); | |
656 #ifndef NSS_DISABLE_ECC | |
657 case NSSLOWKEYECKey: | |
658 return lg_FindECPublicKeyAttribute(key,type,attribute); | |
659 #endif /* NSS_DISABLE_ECC */ | |
660 default: | |
661 break; | |
662 } | |
663 | |
664 return lg_invalidAttribute(attribute); | |
665 } | |
666 | |
667 static CK_RV | |
668 lg_FindSecretKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
669 CK_ATTRIBUTE *attribute) | |
670 { | |
671 NSSLOWKEYPrivateKey *key; | |
672 char *label; | |
673 unsigned char *keyString; | |
674 CK_RV crv; | |
675 int keyTypeLen; | |
676 CK_ULONG keyLen; | |
677 CK_KEY_TYPE keyType; | |
678 PRUint32 keyTypeStorage; | |
679 | |
680 switch (type) { | |
681 case CKA_PRIVATE: | |
682 case CKA_SENSITIVE: | |
683 case CKA_ALWAYS_SENSITIVE: | |
684 case CKA_EXTRACTABLE: | |
685 case CKA_DERIVE: | |
686 case CKA_ENCRYPT: | |
687 case CKA_DECRYPT: | |
688 case CKA_SIGN: | |
689 case CKA_VERIFY: | |
690 case CKA_WRAP: | |
691 case CKA_UNWRAP: | |
692 case CKA_MODIFIABLE: | |
693 case CKA_LOCAL: | |
694 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
695 case CKA_NEVER_EXTRACTABLE: | |
696 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
697 case CKA_START_DATE: | |
698 case CKA_END_DATE: | |
699 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
700 case CKA_LABEL: | |
701 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); | |
702 if (label == NULL) { | |
703 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
704 } | |
705 crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label)); | |
706 PORT_Free(label); | |
707 return crv; | |
708 case CKA_ID: | |
709 return lg_CopyAttribute(attribute,type,obj->dbKey.data, | |
710 obj->dbKey.len); | |
711 case CKA_KEY_TYPE: | |
712 case CKA_VALUE_LEN: | |
713 case CKA_VALUE: | |
714 break; | |
715 default: | |
716 return lg_invalidAttribute(attribute); | |
717 } | |
718 | |
719 key = lg_GetPrivateKey(obj); | |
720 if (key == NULL) { | |
721 return CKR_OBJECT_HANDLE_INVALID; | |
722 } | |
723 switch (type) { | |
724 case CKA_KEY_TYPE: | |
725 /* handle legacy databases. In legacy databases key_type was stored | |
726 * in host order, with any leading zeros stripped off. Only key types | |
727 * under 0x1f (AES) were stored. We assume that any values which are | |
728 * either 1 byte long (big endian), or have byte[0] between 0 and | |
729 * 0x7f and bytes[1]-bytes[3] equal to '0' (little endian). All other | |
730 * values are assumed to be from the new database, which is always 4 | |
731 * bytes in network order */ | |
732 keyType=0; | |
733 keyString = key->u.rsa.coefficient.data; | |
734 keyTypeLen = key->u.rsa.coefficient.len; | |
735 | |
736 | |
737 /* | |
738 * Because of various endian and word lengths The database may have | |
739 * stored the keyType value in one of the following formats: | |
740 * (kt) <= 0x1f | |
741 * length data | |
742 * Big Endian, pre-3.9, all lengths: 1 (kt) | |
743 * Little Endian, pre-3.9, 32 bits: 4 (kt) 0 0 0 | |
744 * Little Endian, pre-3.9, 64 bits: 8 (kt) 0 0 0 0 0 0 0 | |
745 * All platforms, 3.9, 32 bits: 4 0 0 0 (kt) | |
746 * Big Endian, 3.9, 64 bits: 8 0 0 0 (kt) 0 0 0 0 | |
747 * Little Endian, 3.9, 64 bits: 8 0 0 0 0 0 0 0 (kt) | |
748 * All platforms, >= 3.9.1, all lengths: 4 (a) k1 k2 k3 | |
749 * where (a) is 0 or >= 0x80. currently (a) can only be 0. | |
750 */ | |
751 /* | |
752 * this key was written on a 64 bit platform with a using NSS 3.9 | |
753 * or earlier. Reduce the 64 bit possibilities above. When we are | |
754 * through, we will only have: | |
755 * | |
756 * Big Endian, pre-3.9, all lengths: 1 (kt) | |
757 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 | |
758 * All platforms, 3.9, all lengths: 4 0 0 0 (kt) | |
759 * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 | |
760 */ | |
761 if (keyTypeLen == 8) { | |
762 keyTypeStorage = *(PRUint32 *) keyString; | |
763 if (keyTypeStorage == 0) { | |
764 keyString += sizeof(PRUint32); | |
765 } | |
766 keyTypeLen = 4; | |
767 } | |
768 /* | |
769 * Now Handle: | |
770 * | |
771 * All platforms, 3.9, all lengths: 4 0 0 0 (kt) | |
772 * All platforms, => 3.9.1, all lengths: 4 (a) k1 k2 k3 | |
773 * | |
774 * NOTE: if kt == 0 or ak1k2k3 == 0, the test fails and | |
775 * we handle it as: | |
776 * | |
777 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 | |
778 */ | |
779 if (keyTypeLen == sizeof(keyTypeStorage) && | |
780 (((keyString[0] & 0x80) == 0x80) || | |
781 !((keyString[1] == 0) && (keyString[2] == 0) | |
782 && (keyString[3] == 0))) ) { | |
783 PORT_Memcpy(&keyTypeStorage, keyString, sizeof(keyTypeStorage)); | |
784 keyType = (CK_KEY_TYPE) PR_ntohl(keyTypeStorage); | |
785 } else { | |
786 /* | |
787 * Now Handle: | |
788 * | |
789 * Big Endian, pre-3.9, all lengths: 1 (kt) | |
790 * Little Endian, pre-3.9, all lengths: 4 (kt) 0 0 0 | |
791 * -- KeyType == 0 all other cases ---: 4 0 0 0 0 | |
792 */ | |
793 keyType = (CK_KEY_TYPE) keyString[0] ; | |
794 } | |
795 return lg_ULongAttribute(attribute, type, keyType); | |
796 case CKA_VALUE: | |
797 return lg_CopyPrivAttribute(attribute,type,key->u.rsa.privateExponent.data, | |
798 key->u.rsa.privateExponent.len, obj->sdb); | |
799 case CKA_VALUE_LEN: | |
800 keyLen=key->u.rsa.privateExponent.len; | |
801 return lg_ULongAttribute(attribute,type, keyLen); | |
802 } | |
803 return lg_invalidAttribute(attribute); | |
804 } | |
805 | |
806 static CK_RV | |
807 lg_FindRSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, | |
808 CK_ATTRIBUTE *attribute, SDB *sdbpw) | |
809 { | |
810 unsigned char hash[SHA1_LENGTH]; | |
811 CK_KEY_TYPE keyType = CKK_RSA; | |
812 | |
813 switch (type) { | |
814 case CKA_KEY_TYPE: | |
815 return lg_ULongAttribute(attribute, type, keyType); | |
816 case CKA_ID: | |
817 SHA1_HashBuf(hash,key->u.rsa.modulus.data,key->u.rsa.modulus.len); | |
818 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
819 case CKA_DERIVE: | |
820 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
821 case CKA_DECRYPT: | |
822 case CKA_SIGN: | |
823 case CKA_SIGN_RECOVER: | |
824 case CKA_UNWRAP: | |
825 return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr); | |
826 case CKA_MODULUS: | |
827 return lg_CopyAttributeSigned(attribute,type,key->u.rsa.modulus.data, | |
828 key->u.rsa.modulus.len); | |
829 case CKA_PUBLIC_EXPONENT: | |
830 return lg_CopyAttributeSigned(attribute, type, | |
831 key->u.rsa.publicExponent.data, | |
832 key->u.rsa.publicExponent.len); | |
833 case CKA_PRIVATE_EXPONENT: | |
834 return lg_CopyPrivAttrSigned(attribute,type, | |
835 key->u.rsa.privateExponent.data, | |
836 key->u.rsa.privateExponent.len, sdbpw); | |
837 case CKA_PRIME_1: | |
838 return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime1.data, | |
839 key->u.rsa.prime1.len, sdbpw); | |
840 case CKA_PRIME_2: | |
841 return lg_CopyPrivAttrSigned(attribute, type, key->u.rsa.prime2.data, | |
842 key->u.rsa.prime2.len, sdbpw); | |
843 case CKA_EXPONENT_1: | |
844 return lg_CopyPrivAttrSigned(attribute, type, | |
845 key->u.rsa.exponent1.data, | |
846 key->u.rsa.exponent1.len, sdbpw); | |
847 case CKA_EXPONENT_2: | |
848 return lg_CopyPrivAttrSigned(attribute, type, | |
849 key->u.rsa.exponent2.data, | |
850 key->u.rsa.exponent2.len, sdbpw); | |
851 case CKA_COEFFICIENT: | |
852 return lg_CopyPrivAttrSigned(attribute, type, | |
853 key->u.rsa.coefficient.data, | |
854 key->u.rsa.coefficient.len, sdbpw); | |
855 default: | |
856 break; | |
857 } | |
858 return lg_invalidAttribute(attribute); | |
859 } | |
860 | |
861 static CK_RV | |
862 lg_FindDSAPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, | |
863 CK_ATTRIBUTE *attribute, SDB *sdbpw) | |
864 { | |
865 unsigned char hash[SHA1_LENGTH]; | |
866 CK_KEY_TYPE keyType = CKK_DSA; | |
867 | |
868 switch (type) { | |
869 case CKA_KEY_TYPE: | |
870 return lg_ULongAttribute(attribute, type, keyType); | |
871 case CKA_ID: | |
872 SHA1_HashBuf(hash,key->u.dsa.publicValue.data, | |
873 key->u.dsa.publicValue.len); | |
874 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
875 case CKA_DERIVE: | |
876 case CKA_DECRYPT: | |
877 case CKA_SIGN_RECOVER: | |
878 case CKA_UNWRAP: | |
879 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
880 case CKA_SIGN: | |
881 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
882 case CKA_VALUE: | |
883 return lg_CopyPrivAttrSigned(attribute, type, | |
884 key->u.dsa.privateValue.data, | |
885 key->u.dsa.privateValue.len, sdbpw); | |
886 case CKA_PRIME: | |
887 return lg_CopyAttributeSigned(attribute, type, | |
888 key->u.dsa.params.prime.data, | |
889 key->u.dsa.params.prime.len); | |
890 case CKA_SUBPRIME: | |
891 return lg_CopyAttributeSigned(attribute, type, | |
892 key->u.dsa.params.subPrime.data, | |
893 key->u.dsa.params.subPrime.len); | |
894 case CKA_BASE: | |
895 return lg_CopyAttributeSigned(attribute, type, | |
896 key->u.dsa.params.base.data, | |
897 key->u.dsa.params.base.len); | |
898 case CKA_NETSCAPE_DB: | |
899 return lg_CopyAttributeSigned(attribute, type, | |
900 key->u.dsa.publicValue.data, | |
901 key->u.dsa.publicValue.len); | |
902 default: | |
903 break; | |
904 } | |
905 return lg_invalidAttribute(attribute); | |
906 } | |
907 | |
908 static CK_RV | |
909 lg_FindDHPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, | |
910 CK_ATTRIBUTE *attribute, SDB *sdbpw) | |
911 { | |
912 unsigned char hash[SHA1_LENGTH]; | |
913 CK_KEY_TYPE keyType = CKK_DH; | |
914 | |
915 switch (type) { | |
916 case CKA_KEY_TYPE: | |
917 return lg_ULongAttribute(attribute, type, keyType); | |
918 case CKA_ID: | |
919 SHA1_HashBuf(hash,key->u.dh.publicValue.data,key->u.dh.publicValue.len); | |
920 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
921 case CKA_DERIVE: | |
922 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
923 case CKA_DECRYPT: | |
924 case CKA_SIGN: | |
925 case CKA_SIGN_RECOVER: | |
926 case CKA_UNWRAP: | |
927 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
928 case CKA_VALUE: | |
929 return lg_CopyPrivAttrSigned(attribute, type, | |
930 key->u.dh.privateValue.data, | |
931 key->u.dh.privateValue.len, sdbpw); | |
932 case CKA_PRIME: | |
933 return lg_CopyAttributeSigned(attribute, type, key->u.dh.prime.data, | |
934 key->u.dh.prime.len); | |
935 case CKA_BASE: | |
936 return lg_CopyAttributeSigned(attribute, type, key->u.dh.base.data, | |
937 key->u.dh.base.len); | |
938 case CKA_NETSCAPE_DB: | |
939 return lg_CopyAttributeSigned(attribute, type, | |
940 key->u.dh.publicValue.data, | |
941 key->u.dh.publicValue.len); | |
942 default: | |
943 break; | |
944 } | |
945 return lg_invalidAttribute(attribute); | |
946 } | |
947 | |
948 #ifndef NSS_DISABLE_ECC | |
949 static CK_RV | |
950 lg_FindECPrivateKeyAttribute(NSSLOWKEYPrivateKey *key, CK_ATTRIBUTE_TYPE type, | |
951 CK_ATTRIBUTE *attribute, SDB *sdbpw) | |
952 { | |
953 unsigned char hash[SHA1_LENGTH]; | |
954 CK_KEY_TYPE keyType = CKK_EC; | |
955 | |
956 switch (type) { | |
957 case CKA_KEY_TYPE: | |
958 return lg_ULongAttribute(attribute, type, keyType); | |
959 case CKA_ID: | |
960 SHA1_HashBuf(hash,key->u.ec.publicValue.data,key->u.ec.publicValue.len); | |
961 return lg_CopyAttribute(attribute,type,hash,SHA1_LENGTH); | |
962 case CKA_DERIVE: | |
963 case CKA_SIGN: | |
964 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
965 case CKA_DECRYPT: | |
966 case CKA_SIGN_RECOVER: | |
967 case CKA_UNWRAP: | |
968 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
969 case CKA_VALUE: | |
970 return lg_CopyPrivAttrSigned(attribute, type, | |
971 key->u.ec.privateValue.data, | |
972 key->u.ec.privateValue.len, sdbpw); | |
973 case CKA_EC_PARAMS: | |
974 return lg_CopyAttributeSigned(attribute, type, | |
975 key->u.ec.ecParams.DEREncoding.data, | |
976 key->u.ec.ecParams.DEREncoding.len); | |
977 case CKA_NETSCAPE_DB: | |
978 return lg_CopyAttributeSigned(attribute, type, | |
979 key->u.ec.publicValue.data, | |
980 key->u.ec.publicValue.len); | |
981 default: | |
982 break; | |
983 } | |
984 return lg_invalidAttribute(attribute); | |
985 } | |
986 #endif /* NSS_DISABLE_ECC */ | |
987 | |
988 static CK_RV | |
989 lg_FindPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
990 CK_ATTRIBUTE *attribute) | |
991 { | |
992 NSSLOWKEYPrivateKey *key; | |
993 char *label; | |
994 CK_RV crv; | |
995 | |
996 switch (type) { | |
997 case CKA_PRIVATE: | |
998 case CKA_SENSITIVE: | |
999 case CKA_ALWAYS_SENSITIVE: | |
1000 case CKA_EXTRACTABLE: | |
1001 case CKA_MODIFIABLE: | |
1002 case CKA_LOCAL: | |
1003 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
1004 case CKA_NEVER_EXTRACTABLE: | |
1005 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1006 case CKA_SUBJECT: | |
1007 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1008 case CKA_START_DATE: | |
1009 case CKA_END_DATE: | |
1010 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1011 case CKA_LABEL: | |
1012 label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); | |
1013 if (label == NULL) { | |
1014 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1015 } | |
1016 crv = lg_CopyAttribute(attribute,type,label,PORT_Strlen(label)); | |
1017 PORT_Free(label); | |
1018 return crv; | |
1019 default: | |
1020 break; | |
1021 } | |
1022 key = lg_GetPrivateKey(obj); | |
1023 if (key == NULL) { | |
1024 return CKR_OBJECT_HANDLE_INVALID; | |
1025 } | |
1026 switch (key->keyType) { | |
1027 case NSSLOWKEYRSAKey: | |
1028 return lg_FindRSAPrivateKeyAttribute(key,type,attribute,obj->sdb); | |
1029 case NSSLOWKEYDSAKey: | |
1030 return lg_FindDSAPrivateKeyAttribute(key,type,attribute,obj->sdb); | |
1031 case NSSLOWKEYDHKey: | |
1032 return lg_FindDHPrivateKeyAttribute(key,type,attribute,obj->sdb); | |
1033 #ifndef NSS_DISABLE_ECC | |
1034 case NSSLOWKEYECKey: | |
1035 return lg_FindECPrivateKeyAttribute(key,type,attribute,obj->sdb); | |
1036 #endif /* NSS_DISABLE_ECC */ | |
1037 default: | |
1038 break; | |
1039 } | |
1040 | |
1041 return lg_invalidAttribute(attribute); | |
1042 } | |
1043 | |
1044 static CK_RV | |
1045 lg_FindSMIMEAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1046 CK_ATTRIBUTE *attribute) | |
1047 { | |
1048 certDBEntrySMime *entry; | |
1049 switch (type) { | |
1050 case CKA_PRIVATE: | |
1051 case CKA_MODIFIABLE: | |
1052 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1053 case CKA_NSS_EMAIL: | |
1054 return lg_CopyAttribute(attribute,type,obj->dbKey.data, | |
1055 obj->dbKey.len-1); | |
1056 case CKA_NSS_SMIME_TIMESTAMP: | |
1057 case CKA_SUBJECT: | |
1058 case CKA_VALUE: | |
1059 break; | |
1060 default: | |
1061 return lg_invalidAttribute(attribute); | |
1062 } | |
1063 entry = lg_getSMime(obj); | |
1064 if (entry == NULL) { | |
1065 return CKR_OBJECT_HANDLE_INVALID; | |
1066 } | |
1067 switch (type) { | |
1068 case CKA_NSS_SMIME_TIMESTAMP: | |
1069 return lg_CopyAttribute(attribute,type,entry->optionsDate.data, | |
1070 entry->optionsDate.len); | |
1071 case CKA_SUBJECT: | |
1072 return lg_CopyAttribute(attribute,type,entry->subjectName.data, | |
1073 entry->subjectName.len); | |
1074 case CKA_VALUE: | |
1075 return lg_CopyAttribute(attribute,type,entry->smimeOptions.data, | |
1076 entry->smimeOptions.len); | |
1077 default: | |
1078 break; | |
1079 } | |
1080 return lg_invalidAttribute(attribute); | |
1081 } | |
1082 | |
1083 static CK_RV | |
1084 lg_FindTrustAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1085 CK_ATTRIBUTE *attribute) | |
1086 { | |
1087 NSSLOWCERTTrust *trust; | |
1088 NSSLOWCERTCertDBHandle *certHandle; | |
1089 NSSLOWCERTCertificate *cert; | |
1090 unsigned char hash[SHA1_LENGTH]; | |
1091 unsigned int trustFlags; | |
1092 CK_RV crv; | |
1093 | |
1094 switch (type) { | |
1095 case CKA_PRIVATE: | |
1096 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1097 case CKA_MODIFIABLE: | |
1098 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
1099 case CKA_CERT_SHA1_HASH: | |
1100 case CKA_CERT_MD5_HASH: | |
1101 case CKA_TRUST_CLIENT_AUTH: | |
1102 case CKA_TRUST_SERVER_AUTH: | |
1103 case CKA_TRUST_EMAIL_PROTECTION: | |
1104 case CKA_TRUST_CODE_SIGNING: | |
1105 case CKA_TRUST_STEP_UP_APPROVED: | |
1106 case CKA_ISSUER: | |
1107 case CKA_SERIAL_NUMBER: | |
1108 break; | |
1109 default: | |
1110 return lg_invalidAttribute(attribute); | |
1111 } | |
1112 certHandle = lg_getCertDB(obj->sdb); | |
1113 if (!certHandle) { | |
1114 return CKR_OBJECT_HANDLE_INVALID; | |
1115 } | |
1116 trust = lg_getTrust(obj, certHandle); | |
1117 if (trust == NULL) { | |
1118 return CKR_OBJECT_HANDLE_INVALID; | |
1119 } | |
1120 switch (type) { | |
1121 case CKA_CERT_SHA1_HASH: | |
1122 SHA1_HashBuf(hash,trust->derCert->data,trust->derCert->len); | |
1123 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); | |
1124 case CKA_CERT_MD5_HASH: | |
1125 MD5_HashBuf(hash,trust->derCert->data,trust->derCert->len); | |
1126 return lg_CopyAttribute(attribute, type, hash, MD5_LENGTH); | |
1127 case CKA_TRUST_CLIENT_AUTH: | |
1128 trustFlags = trust->trust->sslFlags & CERTDB_TRUSTED_CLIENT_CA ? | |
1129 trust->trust->sslFlags | CERTDB_TRUSTED_CA : 0 ; | |
1130 goto trust; | |
1131 case CKA_TRUST_SERVER_AUTH: | |
1132 trustFlags = trust->trust->sslFlags; | |
1133 goto trust; | |
1134 case CKA_TRUST_EMAIL_PROTECTION: | |
1135 trustFlags = trust->trust->emailFlags; | |
1136 goto trust; | |
1137 case CKA_TRUST_CODE_SIGNING: | |
1138 trustFlags = trust->trust->objectSigningFlags; | |
1139 trust: | |
1140 if (trustFlags & CERTDB_TRUSTED_CA ) { | |
1141 return lg_ULongAttribute(attribute, type, | |
1142 CKT_NSS_TRUSTED_DELEGATOR); | |
1143 } | |
1144 if (trustFlags & CERTDB_TRUSTED) { | |
1145 return lg_ULongAttribute(attribute, type, CKT_NSS_TRUSTED); | |
1146 } | |
1147 if (trustFlags & CERTDB_MUST_VERIFY) { | |
1148 return lg_ULongAttribute(attribute, type, | |
1149 CKT_NSS_MUST_VERIFY_TRUST); | |
1150 } | |
1151 if (trustFlags & CERTDB_TRUSTED_UNKNOWN) { | |
1152 return lg_ULongAttribute(attribute, type, CKT_NSS_TRUST_UNKNOWN); | |
1153 } | |
1154 if (trustFlags & CERTDB_VALID_CA) { | |
1155 return lg_ULongAttribute(attribute, type, CKT_NSS_VALID_DELEGATOR); | |
1156 } | |
1157 if (trustFlags & CERTDB_TERMINAL_RECORD) { | |
1158 return lg_ULongAttribute(attribute, type, CKT_NSS_NOT_TRUSTED); | |
1159 } | |
1160 return lg_ULongAttribute(attribute, type, CKT_NSS_TRUST_UNKNOWN); | |
1161 case CKA_TRUST_STEP_UP_APPROVED: | |
1162 if (trust->trust->sslFlags & CERTDB_GOVT_APPROVED_CA) { | |
1163 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
1164 } else { | |
1165 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1166 } | |
1167 default: | |
1168 break; | |
1169 } | |
1170 | |
1171 | |
1172 switch (type) { | |
1173 case CKA_ISSUER: | |
1174 cert = lg_getCert(obj, certHandle); | |
1175 if (cert == NULL) break; | |
1176 crv = lg_CopyAttribute(attribute,type,cert->derIssuer.data, | |
1177 cert->derIssuer.len); | |
1178 break; | |
1179 case CKA_SERIAL_NUMBER: | |
1180 cert = lg_getCert(obj, certHandle); | |
1181 if (cert == NULL) break; | |
1182 crv = lg_CopyAttribute(attribute,type,cert->derSN.data, | |
1183 cert->derSN.len); | |
1184 break; | |
1185 default: | |
1186 cert = NULL; | |
1187 break; | |
1188 } | |
1189 if (cert) { | |
1190 nsslowcert_DestroyCertificate(cert); | |
1191 return crv; | |
1192 } | |
1193 return lg_invalidAttribute(attribute); | |
1194 } | |
1195 | |
1196 static CK_RV | |
1197 lg_FindCrlAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1198 CK_ATTRIBUTE *attribute) | |
1199 { | |
1200 certDBEntryRevocation *crl; | |
1201 | |
1202 switch (type) { | |
1203 case CKA_PRIVATE: | |
1204 case CKA_MODIFIABLE: | |
1205 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1206 case CKA_NSS_KRL: | |
1207 return ((obj->handle == LG_TOKEN_KRL_HANDLE) | |
1208 ? LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr) | |
1209 : LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr)); | |
1210 case CKA_SUBJECT: | |
1211 return lg_CopyAttribute(attribute,type,obj->dbKey.data, | |
1212 obj->dbKey.len); | |
1213 case CKA_NSS_URL: | |
1214 case CKA_VALUE: | |
1215 break; | |
1216 default: | |
1217 return lg_invalidAttribute(attribute); | |
1218 } | |
1219 crl = lg_getCrl(obj); | |
1220 if (!crl) { | |
1221 return CKR_OBJECT_HANDLE_INVALID; | |
1222 } | |
1223 switch (type) { | |
1224 case CKA_NSS_URL: | |
1225 if (crl->url == NULL) { | |
1226 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1227 } | |
1228 return lg_CopyAttribute(attribute, type, crl->url, | |
1229 PORT_Strlen(crl->url)+1); | |
1230 case CKA_VALUE: | |
1231 return lg_CopyAttribute(attribute, type, crl->derCrl.data, | |
1232 crl->derCrl.len); | |
1233 default: | |
1234 break; | |
1235 } | |
1236 return lg_invalidAttribute(attribute); | |
1237 } | |
1238 | |
1239 static CK_RV | |
1240 lg_FindCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1241 CK_ATTRIBUTE *attribute) | |
1242 { | |
1243 NSSLOWCERTCertificate *cert; | |
1244 NSSLOWCERTCertDBHandle *certHandle; | |
1245 NSSLOWKEYPublicKey *pubKey; | |
1246 unsigned char hash[SHA1_LENGTH]; | |
1247 SECItem *item; | |
1248 | |
1249 switch (type) { | |
1250 case CKA_PRIVATE: | |
1251 return LG_CLONE_ATTR(attribute,type,lg_StaticFalseAttr); | |
1252 case CKA_MODIFIABLE: | |
1253 return LG_CLONE_ATTR(attribute,type,lg_StaticTrueAttr); | |
1254 case CKA_CERTIFICATE_TYPE: | |
1255 /* hardcoding X.509 into here */ | |
1256 return lg_ULongAttribute(attribute, type, CKC_X_509); | |
1257 case CKA_VALUE: | |
1258 case CKA_ID: | |
1259 case CKA_LABEL: | |
1260 case CKA_SUBJECT: | |
1261 case CKA_ISSUER: | |
1262 case CKA_SERIAL_NUMBER: | |
1263 case CKA_NSS_EMAIL: | |
1264 break; | |
1265 default: | |
1266 return lg_invalidAttribute(attribute); | |
1267 } | |
1268 | |
1269 certHandle = lg_getCertDB(obj->sdb); | |
1270 if (certHandle == NULL) { | |
1271 return CKR_OBJECT_HANDLE_INVALID; | |
1272 } | |
1273 | |
1274 cert = lg_getCert(obj, certHandle); | |
1275 if (cert == NULL) { | |
1276 return CKR_OBJECT_HANDLE_INVALID; | |
1277 } | |
1278 switch (type) { | |
1279 case CKA_VALUE: | |
1280 return lg_CopyAttribute(attribute,type,cert->derCert.data, | |
1281 cert->derCert.len); | |
1282 case CKA_ID: | |
1283 if (((cert->trust->sslFlags & CERTDB_USER) == 0) && | |
1284 ((cert->trust->emailFlags & CERTDB_USER) == 0) && | |
1285 ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { | |
1286 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1287 } | |
1288 pubKey = nsslowcert_ExtractPublicKey(cert); | |
1289 if (pubKey == NULL) break; | |
1290 item = lg_GetPubItem(pubKey); | |
1291 if (item == NULL) { | |
1292 lg_nsslowkey_DestroyPublicKey(pubKey); | |
1293 break; | |
1294 } | |
1295 SHA1_HashBuf(hash,item->data,item->len); | |
1296 /* item is imbedded in pubKey, just free the key */ | |
1297 lg_nsslowkey_DestroyPublicKey(pubKey); | |
1298 return lg_CopyAttribute(attribute, type, hash, SHA1_LENGTH); | |
1299 case CKA_LABEL: | |
1300 return cert->nickname | |
1301 ? lg_CopyAttribute(attribute, type, cert->nickname, | |
1302 PORT_Strlen(cert->nickname)) | |
1303 : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1304 case CKA_SUBJECT: | |
1305 return lg_CopyAttribute(attribute,type,cert->derSubject.data, | |
1306 cert->derSubject.len); | |
1307 case CKA_ISSUER: | |
1308 return lg_CopyAttribute(attribute,type,cert->derIssuer.data, | |
1309 cert->derIssuer.len); | |
1310 case CKA_SERIAL_NUMBER: | |
1311 return lg_CopyAttribute(attribute,type,cert->derSN.data, | |
1312 cert->derSN.len); | |
1313 case CKA_NSS_EMAIL: | |
1314 return (cert->emailAddr && cert->emailAddr[0]) | |
1315 ? lg_CopyAttribute(attribute, type, cert->emailAddr, | |
1316 PORT_Strlen(cert->emailAddr)) | |
1317 : LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1318 default: | |
1319 break; | |
1320 } | |
1321 return lg_invalidAttribute(attribute); | |
1322 } | |
1323 | |
1324 CK_RV | |
1325 lg_GetSingleAttribute(LGObjectCache *obj, CK_ATTRIBUTE *attribute) | |
1326 { | |
1327 /* handle the common ones */ | |
1328 CK_ATTRIBUTE_TYPE type = attribute->type; | |
1329 switch (type) { | |
1330 case CKA_CLASS: | |
1331 return lg_ULongAttribute(attribute,type,obj->objclass); | |
1332 case CKA_TOKEN: | |
1333 return LG_CLONE_ATTR(attribute, type,lg_StaticTrueAttr); | |
1334 case CKA_LABEL: | |
1335 if ( (obj->objclass == CKO_CERTIFICATE) | |
1336 || (obj->objclass == CKO_PRIVATE_KEY) | |
1337 || (obj->objclass == CKO_PUBLIC_KEY) | |
1338 || (obj->objclass == CKO_SECRET_KEY)) { | |
1339 break; | |
1340 } | |
1341 return LG_CLONE_ATTR(attribute,type,lg_StaticNullAttr); | |
1342 default: | |
1343 break; | |
1344 } | |
1345 switch (obj->objclass) { | |
1346 case CKO_CERTIFICATE: | |
1347 return lg_FindCertAttribute(obj,type,attribute); | |
1348 case CKO_NSS_CRL: | |
1349 return lg_FindCrlAttribute(obj,type,attribute); | |
1350 case CKO_NSS_TRUST: | |
1351 return lg_FindTrustAttribute(obj,type,attribute); | |
1352 case CKO_NSS_SMIME: | |
1353 return lg_FindSMIMEAttribute(obj,type,attribute); | |
1354 case CKO_PUBLIC_KEY: | |
1355 return lg_FindPublicKeyAttribute(obj,type,attribute); | |
1356 case CKO_PRIVATE_KEY: | |
1357 return lg_FindPrivateKeyAttribute(obj,type,attribute); | |
1358 case CKO_SECRET_KEY: | |
1359 return lg_FindSecretKeyAttribute(obj,type,attribute); | |
1360 default: | |
1361 break; | |
1362 } | |
1363 return lg_invalidAttribute(attribute); | |
1364 } | |
1365 | |
1366 /* | |
1367 * Fill in the attribute template based on the data in the database. | |
1368 */ | |
1369 CK_RV | |
1370 lg_GetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, CK_ATTRIBUTE *templ, | |
1371 CK_ULONG count) | |
1372 { | |
1373 LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK); | |
1374 CK_RV crv, crvCollect = CKR_OK; | |
1375 unsigned int i; | |
1376 | |
1377 if (obj == NULL) { | |
1378 return CKR_OBJECT_HANDLE_INVALID; | |
1379 } | |
1380 | |
1381 for (i=0; i < count; i++) { | |
1382 crv = lg_GetSingleAttribute(obj, &templ[i]); | |
1383 if (crvCollect == CKR_OK) crvCollect = crv; | |
1384 } | |
1385 | |
1386 lg_DestroyObjectCache(obj); | |
1387 return crvCollect; | |
1388 } | |
1389 | |
1390 PRBool | |
1391 lg_cmpAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attribute) | |
1392 { | |
1393 unsigned char buf[LG_BUF_SPACE]; | |
1394 CK_ATTRIBUTE testAttr; | |
1395 unsigned char *tempBuf = NULL; | |
1396 PRBool match = PR_TRUE; | |
1397 CK_RV crv; | |
1398 | |
1399 /* we're going to compare 'attribute' with the actual attribute from | |
1400 * the object. We'll use the length of 'attribute' to decide how much | |
1401 * space we need to read the test attribute. If 'attribute' doesn't give | |
1402 * enough space, then we know the values don't match and that will | |
1403 * show up as ckr != CKR_OK */ | |
1404 testAttr = *attribute; | |
1405 testAttr.pValue = buf; | |
1406 | |
1407 /* if we don't have enough space, malloc it */ | |
1408 if (attribute->ulValueLen > LG_BUF_SPACE) { | |
1409 tempBuf = PORT_Alloc(attribute->ulValueLen); | |
1410 if (!tempBuf) { | |
1411 return PR_FALSE; | |
1412 } | |
1413 testAttr.pValue = tempBuf; | |
1414 } | |
1415 | |
1416 /* get the attribute */ | |
1417 crv = lg_GetSingleAttribute(obj, &testAttr); | |
1418 /* if the attribute was read OK, compare it */ | |
1419 if ((crv != CKR_OK) || (attribute->ulValueLen != testAttr.ulValueLen) || | |
1420 (PORT_Memcmp(attribute->pValue,testAttr.pValue,testAttr.ulValueLen)!= 0)){ | |
1421 /* something didn't match, this isn't the object we are looking for */ | |
1422 match = PR_FALSE; | |
1423 } | |
1424 /* free the buffer we may have allocated */ | |
1425 if (tempBuf) { | |
1426 PORT_Free(tempBuf); | |
1427 } | |
1428 return match; | |
1429 } | |
1430 | |
1431 PRBool | |
1432 lg_tokenMatch(SDB *sdb, const SECItem *dbKey, CK_OBJECT_HANDLE class, | |
1433 const CK_ATTRIBUTE *templ, CK_ULONG count) | |
1434 { | |
1435 PRBool match = PR_TRUE; | |
1436 LGObjectCache *obj = lg_NewObjectCache(sdb, dbKey, class); | |
1437 unsigned int i; | |
1438 | |
1439 if (obj == NULL) { | |
1440 return PR_FALSE; | |
1441 } | |
1442 | |
1443 for (i=0; i < count; i++) { | |
1444 match = lg_cmpAttribute(obj, &templ[i]); | |
1445 if (!match) { | |
1446 break; | |
1447 } | |
1448 } | |
1449 | |
1450 /* done looking, free up our cache */ | |
1451 lg_DestroyObjectCache(obj); | |
1452 | |
1453 /* if we get through the whole list without finding a mismatched attribute, | |
1454 * then this object fits the criteria we are matching */ | |
1455 return match; | |
1456 } | |
1457 | |
1458 static CK_RV | |
1459 lg_SetCertAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1460 const void *value, unsigned int len) | |
1461 { | |
1462 NSSLOWCERTCertificate *cert; | |
1463 NSSLOWCERTCertDBHandle *certHandle; | |
1464 char *nickname = NULL; | |
1465 SECStatus rv; | |
1466 CK_RV crv; | |
1467 | |
1468 /* we can't change the EMAIL values, but let the | |
1469 * upper layers feel better about the fact we tried to set these */ | |
1470 if (type == CKA_NSS_EMAIL) { | |
1471 return CKR_OK; | |
1472 } | |
1473 | |
1474 certHandle = lg_getCertDB(obj->sdb); | |
1475 if (certHandle == NULL) { | |
1476 crv = CKR_TOKEN_WRITE_PROTECTED; | |
1477 goto done; | |
1478 } | |
1479 | |
1480 if ((type != CKA_LABEL) && (type != CKA_ID)) { | |
1481 crv = CKR_ATTRIBUTE_READ_ONLY; | |
1482 goto done; | |
1483 } | |
1484 | |
1485 cert = lg_getCert(obj, certHandle); | |
1486 if (cert == NULL) { | |
1487 crv = CKR_OBJECT_HANDLE_INVALID; | |
1488 goto done; | |
1489 } | |
1490 | |
1491 /* if the app is trying to set CKA_ID, it's probably because it just | |
1492 * imported the key. Look to see if we need to set the CERTDB_USER bits. | |
1493 */ | |
1494 if (type == CKA_ID) { | |
1495 if (((cert->trust->sslFlags & CERTDB_USER) == 0) && | |
1496 ((cert->trust->emailFlags & CERTDB_USER) == 0) && | |
1497 ((cert->trust->objectSigningFlags & CERTDB_USER) == 0)) { | |
1498 NSSLOWKEYDBHandle *keyHandle; | |
1499 | |
1500 keyHandle = lg_getKeyDB(obj->sdb); | |
1501 if (keyHandle) { | |
1502 if (nsslowkey_KeyForCertExists(keyHandle, cert)) { | |
1503 NSSLOWCERTCertTrust trust = *cert->trust; | |
1504 trust.sslFlags |= CERTDB_USER; | |
1505 trust.emailFlags |= CERTDB_USER; | |
1506 trust.objectSigningFlags |= CERTDB_USER; | |
1507 nsslowcert_ChangeCertTrust(certHandle,cert,&trust); | |
1508 } | |
1509 } | |
1510 } | |
1511 crv = CKR_OK; | |
1512 goto done; | |
1513 } | |
1514 | |
1515 /* must be CKA_LABEL */ | |
1516 if (value != NULL) { | |
1517 nickname = PORT_ZAlloc(len+1); | |
1518 if (nickname == NULL) { | |
1519 crv = CKR_HOST_MEMORY; | |
1520 goto done; | |
1521 } | |
1522 PORT_Memcpy(nickname,value,len); | |
1523 nickname[len] = 0; | |
1524 } | |
1525 rv = nsslowcert_AddPermNickname(certHandle, cert, nickname); | |
1526 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; | |
1527 | |
1528 done: | |
1529 if (nickname) { | |
1530 PORT_Free(nickname); | |
1531 } | |
1532 return crv; | |
1533 } | |
1534 | |
1535 static CK_RV | |
1536 lg_SetPrivateKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1537 const void *value, unsigned int len, | |
1538 PRBool *writePrivate) | |
1539 { | |
1540 NSSLOWKEYPrivateKey *privKey; | |
1541 NSSLOWKEYDBHandle *keyHandle; | |
1542 char *nickname = NULL; | |
1543 SECStatus rv; | |
1544 CK_RV crv; | |
1545 | |
1546 /* we can't change the ID and we don't store the subject, but let the | |
1547 * upper layers feel better about the fact we tried to set these */ | |
1548 if ((type == CKA_ID) || (type == CKA_SUBJECT) || | |
1549 (type == CKA_LOCAL) || (type == CKA_NEVER_EXTRACTABLE) || | |
1550 (type == CKA_ALWAYS_SENSITIVE)) { | |
1551 return CKR_OK; | |
1552 } | |
1553 | |
1554 keyHandle = lg_getKeyDB(obj->sdb); | |
1555 if (keyHandle == NULL) { | |
1556 crv = CKR_TOKEN_WRITE_PROTECTED; | |
1557 goto done; | |
1558 } | |
1559 | |
1560 privKey = lg_GetPrivateKeyWithDB(obj, keyHandle); | |
1561 if (privKey == NULL) { | |
1562 crv = CKR_OBJECT_HANDLE_INVALID; | |
1563 goto done; | |
1564 } | |
1565 | |
1566 crv = CKR_ATTRIBUTE_READ_ONLY; | |
1567 switch(type) { | |
1568 case CKA_LABEL: | |
1569 if (value != NULL) { | |
1570 nickname = PORT_ZAlloc(len+1); | |
1571 if (nickname == NULL) { | |
1572 crv = CKR_HOST_MEMORY; | |
1573 goto done; | |
1574 } | |
1575 PORT_Memcpy(nickname,value,len); | |
1576 nickname[len] = 0; | |
1577 } | |
1578 rv = nsslowkey_UpdateNickname(keyHandle, privKey, &obj->dbKey, | |
1579 nickname, obj->sdb); | |
1580 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; | |
1581 break; | |
1582 case CKA_UNWRAP: | |
1583 case CKA_SIGN: | |
1584 case CKA_DERIVE: | |
1585 case CKA_SIGN_RECOVER: | |
1586 case CKA_DECRYPT: | |
1587 /* ignore attempts to change restrict these. | |
1588 * legacyDB ignore these flags and always presents all of them | |
1589 * that are valid as true. | |
1590 * NOTE: We only get here if the current value and the new value do | |
1591 * not match. */ | |
1592 if (*(char *)value == 0) { | |
1593 crv = CKR_OK; | |
1594 } | |
1595 break; | |
1596 case CKA_VALUE: | |
1597 case CKA_PRIVATE_EXPONENT: | |
1598 case CKA_PRIME_1: | |
1599 case CKA_PRIME_2: | |
1600 case CKA_EXPONENT_1: | |
1601 case CKA_EXPONENT_2: | |
1602 case CKA_COEFFICIENT: | |
1603 /* We aren't really changing these values, we are just triggering | |
1604 * the database to update it's entry */ | |
1605 *writePrivate = PR_TRUE; | |
1606 crv = CKR_OK; | |
1607 break; | |
1608 default: | |
1609 crv = CKR_ATTRIBUTE_READ_ONLY; | |
1610 break; | |
1611 } | |
1612 done: | |
1613 if (nickname) { | |
1614 PORT_Free(nickname); | |
1615 } | |
1616 return crv; | |
1617 } | |
1618 | |
1619 static CK_RV | |
1620 lg_SetPublicKeyAttribute(LGObjectCache *obj, CK_ATTRIBUTE_TYPE type, | |
1621 const void *value, unsigned int len, | |
1622 PRBool *writePrivate) | |
1623 { | |
1624 /* we can't change the ID and we don't store the subject, but let the | |
1625 * upper layers feel better about the fact we tried to set these */ | |
1626 if ((type == CKA_ID) || (type == CKA_SUBJECT) || (type == CKA_LABEL)) { | |
1627 return CKR_OK; | |
1628 } | |
1629 return CKR_ATTRIBUTE_READ_ONLY; | |
1630 } | |
1631 | |
1632 static CK_RV | |
1633 lg_SetTrustAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr) | |
1634 { | |
1635 unsigned int flags; | |
1636 CK_TRUST trust; | |
1637 NSSLOWCERTCertificate *cert; | |
1638 NSSLOWCERTCertDBHandle *certHandle; | |
1639 NSSLOWCERTCertTrust dbTrust; | |
1640 SECStatus rv; | |
1641 CK_RV crv; | |
1642 | |
1643 if (attr->type == CKA_LABEL) { | |
1644 return CKR_OK; | |
1645 } | |
1646 | |
1647 crv = lg_GetULongAttribute(attr->type, attr, 1, &trust); | |
1648 if (crv != CKR_OK) { | |
1649 return crv; | |
1650 } | |
1651 flags = lg_MapTrust(trust, (PRBool) (attr->type == CKA_TRUST_CLIENT_AUTH)); | |
1652 | |
1653 certHandle = lg_getCertDB(obj->sdb); | |
1654 | |
1655 if (certHandle == NULL) { | |
1656 crv = CKR_TOKEN_WRITE_PROTECTED; | |
1657 goto done; | |
1658 } | |
1659 | |
1660 cert = lg_getCert(obj, certHandle); | |
1661 if (cert == NULL) { | |
1662 crv = CKR_OBJECT_HANDLE_INVALID; | |
1663 goto done; | |
1664 } | |
1665 dbTrust = *cert->trust; | |
1666 | |
1667 switch (attr->type) { | |
1668 case CKA_TRUST_EMAIL_PROTECTION: | |
1669 dbTrust.emailFlags = flags | | |
1670 (cert->trust->emailFlags & CERTDB_PRESERVE_TRUST_BITS); | |
1671 break; | |
1672 case CKA_TRUST_CODE_SIGNING: | |
1673 dbTrust.objectSigningFlags = flags | | |
1674 (cert->trust->objectSigningFlags & CERTDB_PRESERVE_TRUST_BITS); | |
1675 break; | |
1676 case CKA_TRUST_CLIENT_AUTH: | |
1677 dbTrust.sslFlags = flags | (cert->trust->sslFlags & | |
1678 (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CA)); | |
1679 break; | |
1680 case CKA_TRUST_SERVER_AUTH: | |
1681 dbTrust.sslFlags = flags | (cert->trust->sslFlags & | |
1682 (CERTDB_PRESERVE_TRUST_BITS|CERTDB_TRUSTED_CLIENT_CA)); | |
1683 break; | |
1684 default: | |
1685 crv = CKR_ATTRIBUTE_READ_ONLY; | |
1686 goto done; | |
1687 } | |
1688 | |
1689 rv = nsslowcert_ChangeCertTrust(certHandle, cert, &dbTrust); | |
1690 crv = (rv == SECSuccess) ? CKR_OK : CKR_DEVICE_ERROR; | |
1691 done: | |
1692 return crv; | |
1693 } | |
1694 | |
1695 static CK_RV | |
1696 lg_SetSingleAttribute(LGObjectCache *obj, const CK_ATTRIBUTE *attr, | |
1697 PRBool *writePrivate) | |
1698 { | |
1699 CK_ATTRIBUTE attribLocal; | |
1700 CK_RV crv; | |
1701 | |
1702 if ((attr->type == CKA_NETSCAPE_DB) && (obj->objclass == CKO_PRIVATE_KEY)) { | |
1703 *writePrivate = PR_TRUE; | |
1704 return CKR_OK; | |
1705 } | |
1706 | |
1707 /* Make sure the attribute exists first */ | |
1708 attribLocal.type = attr->type; | |
1709 attribLocal.pValue = NULL; | |
1710 attribLocal.ulValueLen = 0; | |
1711 crv = lg_GetSingleAttribute(obj, &attribLocal); | |
1712 if (crv != CKR_OK) { | |
1713 return crv; | |
1714 } | |
1715 | |
1716 /* if we are just setting it to the value we already have, | |
1717 * allow it to happen. Let label setting go through so | |
1718 * we have the opportunity to repair any database corruption. */ | |
1719 if (attr->type != CKA_LABEL) { | |
1720 if (lg_cmpAttribute(obj,attr)) { | |
1721 return CKR_OK; | |
1722 } | |
1723 } | |
1724 | |
1725 crv = CKR_ATTRIBUTE_READ_ONLY; | |
1726 switch (obj->objclass) { | |
1727 case CKO_CERTIFICATE: | |
1728 /* change NICKNAME, EMAIL, */ | |
1729 crv = lg_SetCertAttribute(obj,attr->type, | |
1730 attr->pValue,attr->ulValueLen); | |
1731 break; | |
1732 case CKO_NSS_CRL: | |
1733 /* change URL */ | |
1734 break; | |
1735 case CKO_NSS_TRUST: | |
1736 crv = lg_SetTrustAttribute(obj,attr); | |
1737 break; | |
1738 case CKO_PRIVATE_KEY: | |
1739 case CKO_SECRET_KEY: | |
1740 crv = lg_SetPrivateKeyAttribute(obj,attr->type, | |
1741 attr->pValue,attr->ulValueLen, writePrivate); | |
1742 break; | |
1743 case CKO_PUBLIC_KEY: | |
1744 crv = lg_SetPublicKeyAttribute(obj,attr->type, | |
1745 attr->pValue,attr->ulValueLen, writePrivate); | |
1746 break; | |
1747 } | |
1748 return crv; | |
1749 } | |
1750 | |
1751 /* | |
1752 * Fill in the attribute template based on the data in the database. | |
1753 */ | |
1754 CK_RV | |
1755 lg_SetAttributeValue(SDB *sdb, CK_OBJECT_HANDLE handle, | |
1756 const CK_ATTRIBUTE *templ, CK_ULONG count) | |
1757 { | |
1758 LGObjectCache *obj = lg_NewObjectCache(sdb, NULL, handle & ~LG_TOKEN_MASK); | |
1759 CK_RV crv, crvCollect = CKR_OK; | |
1760 PRBool writePrivate = PR_FALSE; | |
1761 unsigned int i; | |
1762 | |
1763 if (obj == NULL) { | |
1764 return CKR_OBJECT_HANDLE_INVALID; | |
1765 } | |
1766 | |
1767 for (i=0; i < count; i++) { | |
1768 crv = lg_SetSingleAttribute(obj, &templ[i], &writePrivate); | |
1769 if (crvCollect == CKR_OK) crvCollect = crv; | |
1770 } | |
1771 | |
1772 /* Write any collected changes out for private and secret keys. | |
1773 * don't do the write for just the label */ | |
1774 if (writePrivate) { | |
1775 NSSLOWKEYPrivateKey *privKey = lg_GetPrivateKey(obj); | |
1776 SECStatus rv = SECFailure; | |
1777 char * label = lg_FindKeyNicknameByPublicKey(obj->sdb, &obj->dbKey); | |
1778 | |
1779 if (privKey) { | |
1780 rv = nsslowkey_StoreKeyByPublicKeyAlg(lg_getKeyDB(sdb), privKey, | |
1781 &obj->dbKey, label, sdb, PR_TRUE ); | |
1782 } | |
1783 if (rv != SECSuccess) { | |
1784 crv = CKR_DEVICE_ERROR; | |
1785 } | |
1786 } | |
1787 | |
1788 lg_DestroyObjectCache(obj); | |
1789 return crvCollect; | |
1790 } |