OLD | NEW |
| (Empty) |
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 * pkix_pl_publickey.c | |
6 * | |
7 * Certificate Object Functions | |
8 * | |
9 */ | |
10 | |
11 #include "pkix_pl_publickey.h" | |
12 | |
13 /* --Private-Cert-Functions------------------------------------- */ | |
14 | |
15 /* | |
16 * FUNCTION: pkix_pl_PublicKey_ToString_Helper | |
17 * DESCRIPTION: | |
18 * | |
19 * Helper function that creates a string representation of the PublicKey | |
20 * pointed to by "pkixPubKey" and stores it at "pString". | |
21 * | |
22 * PARAMETERS | |
23 * "pkixPubKey" | |
24 * Address of PublicKey whose string representation is desired. | |
25 * Must be non-NULL. | |
26 * "pString" | |
27 * Address where object pointer will be stored. Must be non-NULL. | |
28 * "plContext" - Platform-specific context pointer. | |
29 * THREAD SAFETY: | |
30 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
31 * RETURNS: | |
32 * Returns NULL if the function succeeds. | |
33 * Returns a PublicKey Error if the function fails in a non-fatal way. | |
34 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
35 */ | |
36 static PKIX_Error * | |
37 pkix_pl_PublicKey_ToString_Helper( | |
38 PKIX_PL_PublicKey *pkixPubKey, | |
39 PKIX_PL_String **pString, | |
40 void *plContext) | |
41 { | |
42 SECAlgorithmID algorithm; | |
43 SECOidTag pubKeyTag; | |
44 char *asciiOID = NULL; | |
45 PKIX_Boolean freeAsciiOID = PKIX_FALSE; | |
46 SECItem oidBytes; | |
47 | |
48 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_ToString_Helper"); | |
49 PKIX_NULLCHECK_THREE(pkixPubKey, pkixPubKey->nssSPKI, pString); | |
50 | |
51 /* | |
52 * XXX for now, we print out public key algorithm's | |
53 * description - add params and bytes later | |
54 */ | |
55 | |
56 /* | |
57 * If the algorithm OID is known to NSS, | |
58 * we print out the ASCII description that is | |
59 * registered with NSS. Otherwise, if unknown, | |
60 * we print out the OID numbers (eg. "1.2.840.3") | |
61 */ | |
62 | |
63 algorithm = pkixPubKey->nssSPKI->algorithm; | |
64 | |
65 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n"); | |
66 pubKeyTag = SECOID_GetAlgorithmTag(&algorithm); | |
67 if (pubKeyTag != SEC_OID_UNKNOWN){ | |
68 PKIX_PUBLICKEY_DEBUG | |
69 ("\t\tCalling SECOID_FindOIDTagDescription).\n"); | |
70 asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag); | |
71 if (!asciiOID){ | |
72 PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED); | |
73 } | |
74 } else { /* pubKeyTag == SEC_OID_UNKNOWN */ | |
75 oidBytes = algorithm.algorithm; | |
76 PKIX_CHECK(pkix_pl_oidBytes2Ascii | |
77 (&oidBytes, &asciiOID, plContext), | |
78 PKIX_OIDBYTES2ASCIIFAILED); | |
79 freeAsciiOID = PKIX_TRUE; | |
80 } | |
81 | |
82 PKIX_CHECK(PKIX_PL_String_Create | |
83 (PKIX_ESCASCII, (void *)asciiOID, 0, pString, plContext), | |
84 PKIX_UNABLETOCREATEPSTRING); | |
85 | |
86 cleanup: | |
87 | |
88 /* | |
89 * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii | |
90 */ | |
91 if (freeAsciiOID){ | |
92 PKIX_FREE(asciiOID); | |
93 } | |
94 | |
95 PKIX_RETURN(PUBLICKEY); | |
96 } | |
97 | |
98 /* | |
99 * FUNCTION: pkix_pl_DestroySPKI | |
100 * DESCRIPTION: | |
101 * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to | |
102 * by "nssSPKI". | |
103 * PARAMETERS | |
104 * "nssSPKI" | |
105 * Address of CERTSubjectPublicKeyInfo. Must be non-NULL. | |
106 * "plContext" - Platform-specific context pointer. | |
107 * THREAD SAFETY: | |
108 * Thread Safe (see Thread Safety Definitions in Programmer's Guide) | |
109 * RETURNS: | |
110 * Returns NULL if the function succeeds. | |
111 * Returns an Object Error if the function fails in a non-fatal way. | |
112 * Returns a Fatal Error if the function fails in an unrecoverable way. | |
113 */ | |
114 static PKIX_Error * | |
115 pkix_pl_DestroySPKI( | |
116 CERTSubjectPublicKeyInfo *nssSPKI, | |
117 void *plContext) | |
118 { | |
119 PKIX_ENTER(PUBLICKEY, "pkix_pl_DestroySPKI"); | |
120 | |
121 PKIX_NULLCHECK_ONE(nssSPKI); | |
122 | |
123 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n"); | |
124 SECOID_DestroyAlgorithmID(&nssSPKI->algorithm, PKIX_FALSE); | |
125 | |
126 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n"); | |
127 SECITEM_FreeItem(&nssSPKI->subjectPublicKey, PKIX_FALSE); | |
128 | |
129 PKIX_RETURN(PUBLICKEY); | |
130 } | |
131 | |
132 /* | |
133 * FUNCTION: pkix_pl_PublicKey_Destroy | |
134 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h) | |
135 */ | |
136 static PKIX_Error * | |
137 pkix_pl_PublicKey_Destroy( | |
138 PKIX_PL_Object *object, | |
139 void *plContext) | |
140 { | |
141 PKIX_PL_PublicKey *pubKey = NULL; | |
142 | |
143 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Destroy"); | |
144 | |
145 PKIX_NULLCHECK_ONE(object); | |
146 | |
147 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
148 PKIX_OBJECTNOTPUBLICKEY); | |
149 | |
150 pubKey = (PKIX_PL_PublicKey *)object; | |
151 | |
152 if (pubKey->nssSPKI) { | |
153 | |
154 PKIX_CHECK(pkix_pl_DestroySPKI(pubKey->nssSPKI, plContext), | |
155 PKIX_DESTROYSPKIFAILED); | |
156 | |
157 PKIX_FREE(pubKey->nssSPKI); | |
158 } | |
159 | |
160 cleanup: | |
161 | |
162 PKIX_RETURN(PUBLICKEY); | |
163 } | |
164 | |
165 /* | |
166 * FUNCTION: pkix_pl_PublicKey_ToString | |
167 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h) | |
168 */ | |
169 static PKIX_Error * | |
170 pkix_pl_PublicKey_ToString( | |
171 PKIX_PL_Object *object, | |
172 PKIX_PL_String **pString, | |
173 void *plContext) | |
174 { | |
175 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
176 PKIX_PL_String *pubKeyString = NULL; | |
177 | |
178 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_toString"); | |
179 PKIX_NULLCHECK_TWO(object, pString); | |
180 | |
181 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
182 PKIX_OBJECTNOTPUBLICKEY); | |
183 | |
184 pkixPubKey = (PKIX_PL_PublicKey *)object; | |
185 | |
186 PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper | |
187 (pkixPubKey, &pubKeyString, plContext), | |
188 PKIX_PUBLICKEYTOSTRINGHELPERFAILED); | |
189 | |
190 *pString = pubKeyString; | |
191 | |
192 cleanup: | |
193 | |
194 PKIX_RETURN(PUBLICKEY); | |
195 } | |
196 | |
197 /* | |
198 * FUNCTION: pkix_pl_PublicKey_Hashcode | |
199 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h) | |
200 */ | |
201 static PKIX_Error * | |
202 pkix_pl_PublicKey_Hashcode( | |
203 PKIX_PL_Object *object, | |
204 PKIX_UInt32 *pHashcode, | |
205 void *plContext) | |
206 { | |
207 PKIX_PL_PublicKey *pkixPubKey = NULL; | |
208 SECItem algOID; | |
209 SECItem algParams; | |
210 SECItem nssPubKey; | |
211 PKIX_UInt32 algOIDHash; | |
212 PKIX_UInt32 algParamsHash; | |
213 PKIX_UInt32 pubKeyHash; | |
214 | |
215 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Hashcode"); | |
216 PKIX_NULLCHECK_TWO(object, pHashcode); | |
217 | |
218 PKIX_CHECK(pkix_CheckType(object, PKIX_PUBLICKEY_TYPE, plContext), | |
219 PKIX_OBJECTNOTPUBLICKEY); | |
220 | |
221 pkixPubKey = (PKIX_PL_PublicKey *)object; | |
222 | |
223 PKIX_NULLCHECK_ONE(pkixPubKey->nssSPKI); | |
224 | |
225 algOID = pkixPubKey->nssSPKI->algorithm.algorithm; | |
226 algParams = pkixPubKey->nssSPKI->algorithm.parameters; | |
227 nssPubKey = pkixPubKey->nssSPKI->subjectPublicKey; | |
228 | |
229 PKIX_CHECK(pkix_hash | |
230 (algOID.data, algOID.len, &algOIDHash, plContext), | |
231 PKIX_HASHFAILED); | |
232 | |
233 PKIX_CHECK(pkix_hash | |
234 (algParams.data, algParams.len, &algParamsHash, plContext), | |
235 PKIX_HASHFAILED); | |
236 | |
237 PKIX_CHECK(pkix_hash | |
238 (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext), | |
239 PKIX_HASHFAILED); | |
240 | |
241 *pHashcode = pubKeyHash; | |
242 | |
243 cleanup: | |
244 | |
245 PKIX_RETURN(PUBLICKEY); | |
246 } | |
247 | |
248 | |
249 /* | |
250 * FUNCTION: pkix_pl_PublicKey_Equals | |
251 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h) | |
252 */ | |
253 static PKIX_Error * | |
254 pkix_pl_PublicKey_Equals( | |
255 PKIX_PL_Object *firstObject, | |
256 PKIX_PL_Object *secondObject, | |
257 PKIX_Boolean *pResult, | |
258 void *plContext) | |
259 { | |
260 PKIX_PL_PublicKey *firstPKIXPubKey = NULL; | |
261 PKIX_PL_PublicKey *secondPKIXPubKey = NULL; | |
262 CERTSubjectPublicKeyInfo *firstSPKI = NULL; | |
263 CERTSubjectPublicKeyInfo *secondSPKI = NULL; | |
264 SECComparison cmpResult; | |
265 PKIX_UInt32 secondType; | |
266 | |
267 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_Equals"); | |
268 PKIX_NULLCHECK_THREE(firstObject, secondObject, pResult); | |
269 | |
270 /* test that firstObject is a PublicKey */ | |
271 PKIX_CHECK(pkix_CheckType(firstObject, PKIX_PUBLICKEY_TYPE, plContext), | |
272 PKIX_FIRSTOBJECTNOTPUBLICKEY); | |
273 | |
274 /* | |
275 * Since we know firstObject is a PublicKey, if both references are | |
276 * identical, they must be equal | |
277 */ | |
278 if (firstObject == secondObject){ | |
279 *pResult = PKIX_TRUE; | |
280 goto cleanup; | |
281 } | |
282 | |
283 /* | |
284 * If secondObject isn't a PublicKey, we don't throw an error. | |
285 * We simply return a Boolean result of FALSE | |
286 */ | |
287 *pResult = PKIX_FALSE; | |
288 PKIX_CHECK(PKIX_PL_Object_GetType | |
289 (secondObject, &secondType, plContext), | |
290 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT); | |
291 if (secondType != PKIX_PUBLICKEY_TYPE) goto cleanup; | |
292 | |
293 firstPKIXPubKey = ((PKIX_PL_PublicKey *)firstObject); | |
294 secondPKIXPubKey = (PKIX_PL_PublicKey *)secondObject; | |
295 | |
296 firstSPKI = firstPKIXPubKey->nssSPKI; | |
297 secondSPKI = secondPKIXPubKey->nssSPKI; | |
298 | |
299 PKIX_NULLCHECK_TWO(firstSPKI, secondSPKI); | |
300 | |
301 PKIX_PL_NSSCALLRV(PUBLICKEY, cmpResult, SECOID_CompareAlgorithmID, | |
302 (&firstSPKI->algorithm, &secondSPKI->algorithm)); | |
303 | |
304 if (cmpResult == SECEqual){ | |
305 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n"); | |
306 cmpResult = SECITEM_CompareItem | |
307 (&firstSPKI->subjectPublicKey, | |
308 &secondSPKI->subjectPublicKey); | |
309 } | |
310 | |
311 *pResult = (cmpResult == SECEqual)?PKIX_TRUE:PKIX_FALSE; | |
312 | |
313 cleanup: | |
314 | |
315 PKIX_RETURN(PUBLICKEY); | |
316 } | |
317 | |
318 /* | |
319 * FUNCTION: pkix_pl_PublicKey_RegisterSelf | |
320 * DESCRIPTION: | |
321 * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[] | |
322 * THREAD SAFETY: | |
323 * Not Thread Safe - for performance and complexity reasons | |
324 * | |
325 * Since this function is only called by PKIX_PL_Initialize, which should | |
326 * only be called once, it is acceptable that this function is not | |
327 * thread-safe. | |
328 */ | |
329 PKIX_Error * | |
330 pkix_pl_PublicKey_RegisterSelf(void *plContext) | |
331 { | |
332 | |
333 extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES]; | |
334 pkix_ClassTable_Entry entry; | |
335 | |
336 PKIX_ENTER(PUBLICKEY, "pkix_pl_PublicKey_RegisterSelf"); | |
337 | |
338 entry.description = "PublicKey"; | |
339 entry.objCounter = 0; | |
340 entry.typeObjectSize = sizeof(PKIX_PL_PublicKey); | |
341 entry.destructor = pkix_pl_PublicKey_Destroy; | |
342 entry.equalsFunction = pkix_pl_PublicKey_Equals; | |
343 entry.hashcodeFunction = pkix_pl_PublicKey_Hashcode; | |
344 entry.toStringFunction = pkix_pl_PublicKey_ToString; | |
345 entry.comparator = NULL; | |
346 entry.duplicateFunction = pkix_duplicateImmutable; | |
347 systemClasses[PKIX_PUBLICKEY_TYPE] = entry; | |
348 | |
349 PKIX_RETURN(PUBLICKEY); | |
350 } | |
351 | |
352 /* --Public-Functions------------------------------------------------------- */ | |
353 | |
354 /* | |
355 * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters | |
356 * (see comments in pkix_pl_pki.h) | |
357 */ | |
358 PKIX_Error * | |
359 PKIX_PL_PublicKey_NeedsDSAParameters( | |
360 PKIX_PL_PublicKey *pubKey, | |
361 PKIX_Boolean *pNeedsParams, | |
362 void *plContext) | |
363 { | |
364 CERTSubjectPublicKeyInfo *nssSPKI = NULL; | |
365 KeyType pubKeyType; | |
366 PKIX_Boolean needsParams = PKIX_FALSE; | |
367 | |
368 PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_NeedsDSAParameters"); | |
369 PKIX_NULLCHECK_TWO(pubKey, pNeedsParams); | |
370 | |
371 nssSPKI = pubKey->nssSPKI; | |
372 | |
373 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
374 pubKeyType = CERT_GetCertKeyType(nssSPKI); | |
375 if (!pubKeyType){ | |
376 PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY); | |
377 } | |
378 | |
379 if ((pubKeyType == dsaKey) && | |
380 (nssSPKI->algorithm.parameters.len == 0)){ | |
381 needsParams = PKIX_TRUE; | |
382 } | |
383 | |
384 *pNeedsParams = needsParams; | |
385 | |
386 cleanup: | |
387 | |
388 PKIX_RETURN(PUBLICKEY); | |
389 } | |
390 | |
391 /* | |
392 * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey | |
393 * (see comments in pkix_pl_pki.h) | |
394 */ | |
395 PKIX_Error * | |
396 PKIX_PL_PublicKey_MakeInheritedDSAPublicKey( | |
397 PKIX_PL_PublicKey *firstKey, | |
398 PKIX_PL_PublicKey *secondKey, | |
399 PKIX_PL_PublicKey **pResultKey, | |
400 void *plContext) | |
401 { | |
402 CERTSubjectPublicKeyInfo *firstSPKI = NULL; | |
403 CERTSubjectPublicKeyInfo *secondSPKI = NULL; | |
404 CERTSubjectPublicKeyInfo *thirdSPKI = NULL; | |
405 PKIX_PL_PublicKey *resultKey = NULL; | |
406 KeyType firstPubKeyType; | |
407 KeyType secondPubKeyType; | |
408 SECStatus rv; | |
409 | |
410 PKIX_ENTER(PUBLICKEY, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey"); | |
411 PKIX_NULLCHECK_THREE(firstKey, secondKey, pResultKey); | |
412 PKIX_NULLCHECK_TWO(firstKey->nssSPKI, secondKey->nssSPKI); | |
413 | |
414 firstSPKI = firstKey->nssSPKI; | |
415 secondSPKI = secondKey->nssSPKI; | |
416 | |
417 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
418 firstPubKeyType = CERT_GetCertKeyType(firstSPKI); | |
419 if (!firstPubKeyType){ | |
420 PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY); | |
421 } | |
422 | |
423 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n"); | |
424 secondPubKeyType = CERT_GetCertKeyType(secondSPKI); | |
425 if (!secondPubKeyType){ | |
426 PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY); | |
427 } | |
428 | |
429 if ((firstPubKeyType == dsaKey) && | |
430 (firstSPKI->algorithm.parameters.len == 0)){ | |
431 if (secondPubKeyType != dsaKey) { | |
432 PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY); | |
433 } else if (secondSPKI->algorithm.parameters.len == 0) { | |
434 PKIX_ERROR | |
435 (PKIX_SECONDKEYDSAPUBLICKEY); | |
436 } else { | |
437 PKIX_CHECK(PKIX_PL_Calloc | |
438 (1, | |
439 sizeof (CERTSubjectPublicKeyInfo), | |
440 (void **)&thirdSPKI, | |
441 plContext), | |
442 PKIX_CALLOCFAILED); | |
443 | |
444 PKIX_PUBLICKEY_DEBUG | |
445 ("\t\tCalling" | |
446 "SECKEY_CopySubjectPublicKeyInfo).\n"); | |
447 rv = SECKEY_CopySubjectPublicKeyInfo | |
448 (NULL, thirdSPKI, firstSPKI); | |
449 if (rv != SECSuccess) { | |
450 PKIX_ERROR | |
451 (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED); | |
452 } | |
453 | |
454 PKIX_PUBLICKEY_DEBUG | |
455 ("\t\tCalling SECITEM_CopyItem).\n"); | |
456 rv = SECITEM_CopyItem(NULL, | |
457 &thirdSPKI->algorithm.parameters, | |
458 &secondSPKI->algorithm.parameters); | |
459 | |
460 if (rv != SECSuccess) { | |
461 PKIX_ERROR(PKIX_OUTOFMEMORY); | |
462 } | |
463 | |
464 /* create a PKIX_PL_PublicKey object */ | |
465 PKIX_CHECK(PKIX_PL_Object_Alloc | |
466 (PKIX_PUBLICKEY_TYPE, | |
467 sizeof (PKIX_PL_PublicKey), | |
468 (PKIX_PL_Object **)&resultKey, | |
469 plContext), | |
470 PKIX_COULDNOTCREATEOBJECT); | |
471 | |
472 /* populate the SPKI field */ | |
473 resultKey->nssSPKI = thirdSPKI; | |
474 *pResultKey = resultKey; | |
475 } | |
476 } else { | |
477 *pResultKey = NULL; | |
478 } | |
479 | |
480 cleanup: | |
481 | |
482 if (thirdSPKI && PKIX_ERROR_RECEIVED){ | |
483 PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI, plContext), | |
484 PKIX_DESTROYSPKIFAILED); | |
485 PKIX_FREE(thirdSPKI); | |
486 } | |
487 | |
488 PKIX_RETURN(PUBLICKEY); | |
489 } | |
OLD | NEW |