1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the PKIX-C library.
16 * The Initial Developer of the Original Code is
17 * Sun Microsystems, Inc.
18 * Portions created by the Initial Developer are
19 * Copyright 2004-2007 Sun Microsystems, Inc. All Rights Reserved.
22 * Sun Microsystems, Inc.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 2 or later (the "GPL"), or
26 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
40 * Certificate Object Functions
44 #include "pkix_pl_publickey.h"
46 /* --Private-Cert-Functions------------------------------------- */
49 * FUNCTION: pkix_pl_PublicKey_ToString_Helper
52 * Helper function that creates a string representation of the PublicKey
53 * pointed to by "pkixPubKey" and stores it at "pString".
57 * Address of PublicKey whose string representation is desired.
60 * Address where object pointer will be stored. Must be non-NULL.
61 * "plContext" - Platform-specific context pointer.
63 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
65 * Returns NULL if the function succeeds.
66 * Returns a PublicKey Error if the function fails in a non-fatal way.
67 * Returns a Fatal Error if the function fails in an unrecoverable way.
70 pkix_pl_PublicKey_ToString_Helper(
71 PKIX_PL_PublicKey
*pkixPubKey
,
72 PKIX_PL_String
**pString
,
75 SECAlgorithmID algorithm
;
77 char *asciiOID
= NULL
;
78 PKIX_Boolean freeAsciiOID
= PKIX_FALSE
;
81 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_ToString_Helper");
82 PKIX_NULLCHECK_THREE(pkixPubKey
, pkixPubKey
->nssSPKI
, pString
);
85 * XXX for now, we print out public key algorithm's
86 * description - add params and bytes later
90 * If the algorithm OID is known to NSS,
91 * we print out the ASCII description that is
92 * registered with NSS. Otherwise, if unknown,
93 * we print out the OID numbers (eg. "1.2.840.3")
96 algorithm
= pkixPubKey
->nssSPKI
->algorithm
;
98 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_GetAlgorithmTag).\n");
99 pubKeyTag
= SECOID_GetAlgorithmTag(&algorithm
);
100 if (pubKeyTag
!= SEC_OID_UNKNOWN
){
102 ("\t\tCalling SECOID_FindOIDTagDescription).\n");
103 asciiOID
= (char *)SECOID_FindOIDTagDescription(pubKeyTag
);
105 PKIX_ERROR(PKIX_SECOIDFINDOIDTAGDESCRIPTIONFAILED
);
107 } else { /* pubKeyTag == SEC_OID_UNKNOWN */
108 oidBytes
= algorithm
.algorithm
;
109 PKIX_CHECK(pkix_pl_oidBytes2Ascii
110 (&oidBytes
, &asciiOID
, plContext
),
111 PKIX_OIDBYTES2ASCIIFAILED
);
112 freeAsciiOID
= PKIX_TRUE
;
115 PKIX_CHECK(PKIX_PL_String_Create
116 (PKIX_ESCASCII
, (void *)asciiOID
, 0, pString
, plContext
),
117 PKIX_UNABLETOCREATEPSTRING
);
122 * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii
128 PKIX_RETURN(PUBLICKEY
);
132 * FUNCTION: pkix_pl_DestroySPKI
134 * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to
138 * Address of CERTSubjectPublicKeyInfo. Must be non-NULL.
139 * "plContext" - Platform-specific context pointer.
141 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
143 * Returns NULL if the function succeeds.
144 * Returns an Object Error if the function fails in a non-fatal way.
145 * Returns a Fatal Error if the function fails in an unrecoverable way.
149 CERTSubjectPublicKeyInfo
*nssSPKI
,
152 PKIX_ENTER(PUBLICKEY
, "pkix_pl_DestroySPKI");
154 PKIX_NULLCHECK_ONE(nssSPKI
);
156 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECOID_DestroyAlgorithmID).\n");
157 SECOID_DestroyAlgorithmID(&nssSPKI
->algorithm
, PKIX_FALSE
);
159 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_FreeItem).\n");
160 SECITEM_FreeItem(&nssSPKI
->subjectPublicKey
, PKIX_FALSE
);
162 PKIX_RETURN(PUBLICKEY
);
166 * FUNCTION: pkix_pl_PublicKey_Destroy
167 * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
170 pkix_pl_PublicKey_Destroy(
171 PKIX_PL_Object
*object
,
174 PKIX_PL_PublicKey
*pubKey
= NULL
;
176 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_Destroy");
178 PKIX_NULLCHECK_ONE(object
);
180 PKIX_CHECK(pkix_CheckType(object
, PKIX_PUBLICKEY_TYPE
, plContext
),
181 PKIX_OBJECTNOTPUBLICKEY
);
183 pubKey
= (PKIX_PL_PublicKey
*)object
;
185 if (pubKey
->nssSPKI
) {
187 PKIX_CHECK(pkix_pl_DestroySPKI(pubKey
->nssSPKI
, plContext
),
188 PKIX_DESTROYSPKIFAILED
);
190 PKIX_FREE(pubKey
->nssSPKI
);
195 PKIX_RETURN(PUBLICKEY
);
199 * FUNCTION: pkix_pl_PublicKey_ToString
200 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
203 pkix_pl_PublicKey_ToString(
204 PKIX_PL_Object
*object
,
205 PKIX_PL_String
**pString
,
208 PKIX_PL_PublicKey
*pkixPubKey
= NULL
;
209 PKIX_PL_String
*pubKeyString
= NULL
;
211 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_toString");
212 PKIX_NULLCHECK_TWO(object
, pString
);
214 PKIX_CHECK(pkix_CheckType(object
, PKIX_PUBLICKEY_TYPE
, plContext
),
215 PKIX_OBJECTNOTPUBLICKEY
);
217 pkixPubKey
= (PKIX_PL_PublicKey
*)object
;
219 PKIX_CHECK(pkix_pl_PublicKey_ToString_Helper
220 (pkixPubKey
, &pubKeyString
, plContext
),
221 PKIX_PUBLICKEYTOSTRINGHELPERFAILED
);
223 *pString
= pubKeyString
;
227 PKIX_RETURN(PUBLICKEY
);
231 * FUNCTION: pkix_pl_PublicKey_Hashcode
232 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
235 pkix_pl_PublicKey_Hashcode(
236 PKIX_PL_Object
*object
,
237 PKIX_UInt32
*pHashcode
,
240 PKIX_PL_PublicKey
*pkixPubKey
= NULL
;
244 PKIX_UInt32 algOIDHash
;
245 PKIX_UInt32 algParamsHash
;
246 PKIX_UInt32 pubKeyHash
;
247 PKIX_UInt32 fullHash
;
249 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_Hashcode");
250 PKIX_NULLCHECK_TWO(object
, pHashcode
);
252 PKIX_CHECK(pkix_CheckType(object
, PKIX_PUBLICKEY_TYPE
, plContext
),
253 PKIX_OBJECTNOTPUBLICKEY
);
255 pkixPubKey
= (PKIX_PL_PublicKey
*)object
;
257 PKIX_NULLCHECK_ONE(pkixPubKey
->nssSPKI
);
259 algOID
= pkixPubKey
->nssSPKI
->algorithm
.algorithm
;
260 algParams
= pkixPubKey
->nssSPKI
->algorithm
.parameters
;
261 nssPubKey
= pkixPubKey
->nssSPKI
->subjectPublicKey
;
264 (algOID
.data
, algOID
.len
, &algOIDHash
, plContext
),
268 (algParams
.data
, algParams
.len
, &algParamsHash
, plContext
),
272 (nssPubKey
.data
, nssPubKey
.len
, &pubKeyHash
, plContext
),
275 fullHash
= algOIDHash
+ algParamsHash
+ pubKeyHash
;
277 *pHashcode
= pubKeyHash
;
281 PKIX_RETURN(PUBLICKEY
);
286 * FUNCTION: pkix_pl_PublicKey_Equals
287 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
290 pkix_pl_PublicKey_Equals(
291 PKIX_PL_Object
*firstObject
,
292 PKIX_PL_Object
*secondObject
,
293 PKIX_Boolean
*pResult
,
296 PKIX_PL_PublicKey
*firstPKIXPubKey
= NULL
;
297 PKIX_PL_PublicKey
*secondPKIXPubKey
= NULL
;
298 CERTSubjectPublicKeyInfo
*firstSPKI
= NULL
;
299 CERTSubjectPublicKeyInfo
*secondSPKI
= NULL
;
300 SECComparison cmpResult
;
301 PKIX_UInt32 secondType
;
303 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_Equals");
304 PKIX_NULLCHECK_THREE(firstObject
, secondObject
, pResult
);
306 /* test that firstObject is a PublicKey */
307 PKIX_CHECK(pkix_CheckType(firstObject
, PKIX_PUBLICKEY_TYPE
, plContext
),
308 PKIX_FIRSTOBJECTNOTPUBLICKEY
);
311 * Since we know firstObject is a PublicKey, if both references are
312 * identical, they must be equal
314 if (firstObject
== secondObject
){
315 *pResult
= PKIX_TRUE
;
320 * If secondObject isn't a PublicKey, we don't throw an error.
321 * We simply return a Boolean result of FALSE
323 *pResult
= PKIX_FALSE
;
324 PKIX_CHECK(PKIX_PL_Object_GetType
325 (secondObject
, &secondType
, plContext
),
326 PKIX_COULDNOTGETTYPEOFSECONDARGUMENT
);
327 if (secondType
!= PKIX_PUBLICKEY_TYPE
) goto cleanup
;
329 firstPKIXPubKey
= ((PKIX_PL_PublicKey
*)firstObject
);
330 secondPKIXPubKey
= (PKIX_PL_PublicKey
*)secondObject
;
332 firstSPKI
= firstPKIXPubKey
->nssSPKI
;
333 secondSPKI
= secondPKIXPubKey
->nssSPKI
;
335 PKIX_NULLCHECK_TWO(firstSPKI
, secondSPKI
);
337 PKIX_PL_NSSCALLRV(PUBLICKEY
, cmpResult
, SECOID_CompareAlgorithmID
,
338 (&firstSPKI
->algorithm
, &secondSPKI
->algorithm
));
340 if (cmpResult
== SECEqual
){
341 PKIX_PUBLICKEY_DEBUG("\t\tCalling SECITEM_CompareItem).\n");
342 cmpResult
= SECITEM_CompareItem
343 (&firstSPKI
->subjectPublicKey
,
344 &secondSPKI
->subjectPublicKey
);
347 *pResult
= (cmpResult
== SECEqual
)?PKIX_TRUE
:PKIX_FALSE
;
351 PKIX_RETURN(PUBLICKEY
);
355 * FUNCTION: pkix_pl_PublicKey_RegisterSelf
357 * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[]
359 * Not Thread Safe - for performance and complexity reasons
361 * Since this function is only called by PKIX_PL_Initialize, which should
362 * only be called once, it is acceptable that this function is not
366 pkix_pl_PublicKey_RegisterSelf(void *plContext
)
369 extern pkix_ClassTable_Entry systemClasses
[PKIX_NUMTYPES
];
370 pkix_ClassTable_Entry entry
;
372 PKIX_ENTER(PUBLICKEY
, "pkix_pl_PublicKey_RegisterSelf");
374 entry
.description
= "PublicKey";
375 entry
.objCounter
= 0;
376 entry
.typeObjectSize
= sizeof(PKIX_PL_PublicKey
);
377 entry
.destructor
= pkix_pl_PublicKey_Destroy
;
378 entry
.equalsFunction
= pkix_pl_PublicKey_Equals
;
379 entry
.hashcodeFunction
= pkix_pl_PublicKey_Hashcode
;
380 entry
.toStringFunction
= pkix_pl_PublicKey_ToString
;
381 entry
.comparator
= NULL
;
382 entry
.duplicateFunction
= pkix_duplicateImmutable
;
383 systemClasses
[PKIX_PUBLICKEY_TYPE
] = entry
;
385 PKIX_RETURN(PUBLICKEY
);
388 /* --Public-Functions------------------------------------------------------- */
391 * FUNCTION: PKIX_PL_PublicKey_NeedsDSAParameters
392 * (see comments in pkix_pl_pki.h)
395 PKIX_PL_PublicKey_NeedsDSAParameters(
396 PKIX_PL_PublicKey
*pubKey
,
397 PKIX_Boolean
*pNeedsParams
,
400 CERTSubjectPublicKeyInfo
*nssSPKI
= NULL
;
402 PKIX_Boolean needsParams
= PKIX_FALSE
;
404 PKIX_ENTER(PUBLICKEY
, "PKIX_PL_PublicKey_NeedsDSAParameters");
405 PKIX_NULLCHECK_TWO(pubKey
, pNeedsParams
);
407 nssSPKI
= pubKey
->nssSPKI
;
409 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
410 pubKeyType
= CERT_GetCertKeyType(nssSPKI
);
412 PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY
);
415 if ((pubKeyType
== dsaKey
) &&
416 (nssSPKI
->algorithm
.parameters
.len
== 0)){
417 needsParams
= PKIX_TRUE
;
420 *pNeedsParams
= needsParams
;
424 PKIX_RETURN(PUBLICKEY
);
428 * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
429 * (see comments in pkix_pl_pki.h)
432 PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(
433 PKIX_PL_PublicKey
*firstKey
,
434 PKIX_PL_PublicKey
*secondKey
,
435 PKIX_PL_PublicKey
**pResultKey
,
438 CERTSubjectPublicKeyInfo
*firstSPKI
= NULL
;
439 CERTSubjectPublicKeyInfo
*secondSPKI
= NULL
;
440 CERTSubjectPublicKeyInfo
*thirdSPKI
= NULL
;
441 PKIX_PL_PublicKey
*resultKey
= NULL
;
442 KeyType firstPubKeyType
;
443 KeyType secondPubKeyType
;
446 PKIX_ENTER(PUBLICKEY
, "PKIX_PL_PublicKey_MakeInheritedDSAPublicKey");
447 PKIX_NULLCHECK_THREE(firstKey
, secondKey
, pResultKey
);
448 PKIX_NULLCHECK_TWO(firstKey
->nssSPKI
, secondKey
->nssSPKI
);
450 firstSPKI
= firstKey
->nssSPKI
;
451 secondSPKI
= secondKey
->nssSPKI
;
453 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
454 firstPubKeyType
= CERT_GetCertKeyType(firstSPKI
);
455 if (!firstPubKeyType
){
456 PKIX_ERROR(PKIX_FIRSTPUBKEYTYPENULLKEY
);
459 PKIX_PUBLICKEY_DEBUG("\t\tCalling CERT_GetCertKeyType).\n");
460 secondPubKeyType
= CERT_GetCertKeyType(secondSPKI
);
461 if (!secondPubKeyType
){
462 PKIX_ERROR(PKIX_SECONDPUBKEYTYPENULLKEY
);
465 if ((firstPubKeyType
== dsaKey
) &&
466 (firstSPKI
->algorithm
.parameters
.len
== 0)){
467 if (secondPubKeyType
!= dsaKey
) {
468 PKIX_ERROR(PKIX_SECONDKEYNOTDSAPUBLICKEY
);
469 } else if (secondSPKI
->algorithm
.parameters
.len
== 0) {
471 (PKIX_SECONDKEYDSAPUBLICKEY
);
473 PKIX_CHECK(PKIX_PL_Calloc
475 sizeof (CERTSubjectPublicKeyInfo
),
482 "SECKEY_CopySubjectPublicKeyInfo).\n");
483 rv
= SECKEY_CopySubjectPublicKeyInfo
484 (NULL
, thirdSPKI
, firstSPKI
);
485 if (rv
!= SECSuccess
) {
487 (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED
);
491 ("\t\tCalling SECITEM_CopyItem).\n");
492 rv
= SECITEM_CopyItem(NULL
,
493 &thirdSPKI
->algorithm
.parameters
,
494 &secondSPKI
->algorithm
.parameters
);
496 if (rv
!= SECSuccess
) {
497 PKIX_ERROR(PKIX_OUTOFMEMORY
);
500 /* create a PKIX_PL_PublicKey object */
501 PKIX_CHECK(PKIX_PL_Object_Alloc
502 (PKIX_PUBLICKEY_TYPE
,
503 sizeof (PKIX_PL_PublicKey
),
504 (PKIX_PL_Object
**)&resultKey
,
506 PKIX_COULDNOTCREATEOBJECT
);
508 /* populate the SPKI field */
509 resultKey
->nssSPKI
= thirdSPKI
;
510 *pResultKey
= resultKey
;
518 if (thirdSPKI
&& PKIX_ERROR_RECEIVED
){
519 PKIX_CHECK(pkix_pl_DestroySPKI(thirdSPKI
, plContext
),
520 PKIX_DESTROYSPKIFAILED
);
521 PKIX_FREE(thirdSPKI
);
524 PKIX_RETURN(PUBLICKEY
);