nss: import at 3.0.1 beta 1
[mozilla-nss.git] / security / nss / lib / libpkix / pkix_pl_nss / pki / pkix_pl_publickey.c
blob68cf098ab469d0e3f5a62be0c1bea6e07838a27d
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
12 * License.
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.
21 * Contributor(s):
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 ***** */
38 * pkix_pl_publickey.c
40 * Certificate Object Functions
44 #include "pkix_pl_publickey.h"
46 /* --Private-Cert-Functions------------------------------------- */
49 * FUNCTION: pkix_pl_PublicKey_ToString_Helper
50 * DESCRIPTION:
52 * Helper function that creates a string representation of the PublicKey
53 * pointed to by "pkixPubKey" and stores it at "pString".
55 * PARAMETERS
56 * "pkixPubKey"
57 * Address of PublicKey whose string representation is desired.
58 * Must be non-NULL.
59 * "pString"
60 * Address where object pointer will be stored. Must be non-NULL.
61 * "plContext" - Platform-specific context pointer.
62 * THREAD SAFETY:
63 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
64 * RETURNS:
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.
69 static PKIX_Error *
70 pkix_pl_PublicKey_ToString_Helper(
71 PKIX_PL_PublicKey *pkixPubKey,
72 PKIX_PL_String **pString,
73 void *plContext)
75 SECAlgorithmID algorithm;
76 SECOidTag pubKeyTag;
77 char *asciiOID = NULL;
78 PKIX_Boolean freeAsciiOID = PKIX_FALSE;
79 SECItem oidBytes;
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){
101 PKIX_PUBLICKEY_DEBUG
102 ("\t\tCalling SECOID_FindOIDTagDescription).\n");
103 asciiOID = (char *)SECOID_FindOIDTagDescription(pubKeyTag);
104 if (!asciiOID){
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);
119 cleanup:
122 * we only free asciiOID if it was malloc'ed by pkix_pl_oidBytes2Ascii
124 if (freeAsciiOID){
125 PKIX_FREE(asciiOID);
128 PKIX_RETURN(PUBLICKEY);
132 * FUNCTION: pkix_pl_DestroySPKI
133 * DESCRIPTION:
134 * Frees all memory associated with the CERTSubjectPublicKeyInfo pointed to
135 * by "nssSPKI".
136 * PARAMETERS
137 * "nssSPKI"
138 * Address of CERTSubjectPublicKeyInfo. Must be non-NULL.
139 * "plContext" - Platform-specific context pointer.
140 * THREAD SAFETY:
141 * Thread Safe (see Thread Safety Definitions in Programmer's Guide)
142 * RETURNS:
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.
147 static PKIX_Error *
148 pkix_pl_DestroySPKI(
149 CERTSubjectPublicKeyInfo *nssSPKI,
150 void *plContext)
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)
169 static PKIX_Error *
170 pkix_pl_PublicKey_Destroy(
171 PKIX_PL_Object *object,
172 void *plContext)
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);
193 cleanup:
195 PKIX_RETURN(PUBLICKEY);
199 * FUNCTION: pkix_pl_PublicKey_ToString
200 * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
202 static PKIX_Error *
203 pkix_pl_PublicKey_ToString(
204 PKIX_PL_Object *object,
205 PKIX_PL_String **pString,
206 void *plContext)
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;
225 cleanup:
227 PKIX_RETURN(PUBLICKEY);
231 * FUNCTION: pkix_pl_PublicKey_Hashcode
232 * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
234 static PKIX_Error *
235 pkix_pl_PublicKey_Hashcode(
236 PKIX_PL_Object *object,
237 PKIX_UInt32 *pHashcode,
238 void *plContext)
240 PKIX_PL_PublicKey *pkixPubKey = NULL;
241 SECItem algOID;
242 SECItem algParams;
243 SECItem nssPubKey;
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;
263 PKIX_CHECK(pkix_hash
264 (algOID.data, algOID.len, &algOIDHash, plContext),
265 PKIX_HASHFAILED);
267 PKIX_CHECK(pkix_hash
268 (algParams.data, algParams.len, &algParamsHash, plContext),
269 PKIX_HASHFAILED);
271 PKIX_CHECK(pkix_hash
272 (nssPubKey.data, nssPubKey.len, &pubKeyHash, plContext),
273 PKIX_HASHFAILED);
275 fullHash = algOIDHash + algParamsHash + pubKeyHash;
277 *pHashcode = pubKeyHash;
279 cleanup:
281 PKIX_RETURN(PUBLICKEY);
286 * FUNCTION: pkix_pl_PublicKey_Equals
287 * (see comments for PKIX_PL_Equals_Callback in pkix_pl_system.h)
289 static PKIX_Error *
290 pkix_pl_PublicKey_Equals(
291 PKIX_PL_Object *firstObject,
292 PKIX_PL_Object *secondObject,
293 PKIX_Boolean *pResult,
294 void *plContext)
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;
316 goto cleanup;
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;
349 cleanup:
351 PKIX_RETURN(PUBLICKEY);
355 * FUNCTION: pkix_pl_PublicKey_RegisterSelf
356 * DESCRIPTION:
357 * Registers PKIX_PUBLICKEY_TYPE and its related functions with systemClasses[]
358 * THREAD SAFETY:
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
363 * thread-safe.
365 PKIX_Error *
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)
394 PKIX_Error *
395 PKIX_PL_PublicKey_NeedsDSAParameters(
396 PKIX_PL_PublicKey *pubKey,
397 PKIX_Boolean *pNeedsParams,
398 void *plContext)
400 CERTSubjectPublicKeyInfo *nssSPKI = NULL;
401 KeyType pubKeyType;
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);
411 if (!pubKeyType){
412 PKIX_ERROR(PKIX_PUBKEYTYPENULLKEY);
415 if ((pubKeyType == dsaKey) &&
416 (nssSPKI->algorithm.parameters.len == 0)){
417 needsParams = PKIX_TRUE;
420 *pNeedsParams = needsParams;
422 cleanup:
424 PKIX_RETURN(PUBLICKEY);
428 * FUNCTION: PKIX_PL_PublicKey_MakeInheritedDSAPublicKey
429 * (see comments in pkix_pl_pki.h)
431 PKIX_Error *
432 PKIX_PL_PublicKey_MakeInheritedDSAPublicKey(
433 PKIX_PL_PublicKey *firstKey,
434 PKIX_PL_PublicKey *secondKey,
435 PKIX_PL_PublicKey **pResultKey,
436 void *plContext)
438 CERTSubjectPublicKeyInfo *firstSPKI = NULL;
439 CERTSubjectPublicKeyInfo *secondSPKI = NULL;
440 CERTSubjectPublicKeyInfo *thirdSPKI = NULL;
441 PKIX_PL_PublicKey *resultKey = NULL;
442 KeyType firstPubKeyType;
443 KeyType secondPubKeyType;
444 SECStatus rv;
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) {
470 PKIX_ERROR
471 (PKIX_SECONDKEYDSAPUBLICKEY);
472 } else {
473 PKIX_CHECK(PKIX_PL_Calloc
475 sizeof (CERTSubjectPublicKeyInfo),
476 (void **)&thirdSPKI,
477 plContext),
478 PKIX_CALLOCFAILED);
480 PKIX_PUBLICKEY_DEBUG
481 ("\t\tCalling"
482 "SECKEY_CopySubjectPublicKeyInfo).\n");
483 rv = SECKEY_CopySubjectPublicKeyInfo
484 (NULL, thirdSPKI, firstSPKI);
485 if (rv != SECSuccess) {
486 PKIX_ERROR
487 (PKIX_SECKEYCOPYSUBJECTPUBLICKEYINFOFAILED);
490 PKIX_PUBLICKEY_DEBUG
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,
505 plContext),
506 PKIX_COULDNOTCREATEOBJECT);
508 /* populate the SPKI field */
509 resultKey->nssSPKI = thirdSPKI;
510 *pResultKey = resultKey;
512 } else {
513 *pResultKey = NULL;
516 cleanup:
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);