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_trustanchor.c
6  *
7  * TrustAnchor Object Functions
8  *
9  */
10 
11 #include "pkix_trustanchor.h"
12 
13 /* --Private-Functions-------------------------------------------- */
14 
15 /*
16  * FUNCTION: pkix_TrustAnchor_Destroy
17  * (see comments for PKIX_PL_DestructorCallback in pkix_pl_system.h)
18  */
19 static PKIX_Error *
pkix_TrustAnchor_Destroy(PKIX_PL_Object * object,void * plContext)20 pkix_TrustAnchor_Destroy(
21         PKIX_PL_Object *object,
22         void *plContext)
23 {
24         PKIX_TrustAnchor *anchor = NULL;
25 
26         PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Destroy");
27         PKIX_NULLCHECK_ONE(object);
28 
29         /* Check that this object is a trust anchor */
30         PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
31                     PKIX_OBJECTNOTTRUSTANCHOR);
32 
33         anchor = (PKIX_TrustAnchor *)object;
34 
35         PKIX_DECREF(anchor->trustedCert);
36         PKIX_DECREF(anchor->caName);
37         PKIX_DECREF(anchor->caPubKey);
38         PKIX_DECREF(anchor->nameConstraints);
39 
40 cleanup:
41 
42         PKIX_RETURN(TRUSTANCHOR);
43 }
44 
45 /*
46  * FUNCTION: pkix_TrustAnchor_Equals
47  * (see comments for PKIX_PL_EqualsCallback in pkix_pl_system.h)
48  */
49 static PKIX_Error *
pkix_TrustAnchor_Equals(PKIX_PL_Object * first,PKIX_PL_Object * second,PKIX_Boolean * pResult,void * plContext)50 pkix_TrustAnchor_Equals(
51         PKIX_PL_Object *first,
52         PKIX_PL_Object *second,
53         PKIX_Boolean *pResult,
54         void *plContext)
55 {
56         PKIX_UInt32 secondType;
57         PKIX_Boolean cmpResult;
58         PKIX_TrustAnchor *firstAnchor = NULL;
59         PKIX_TrustAnchor *secondAnchor = NULL;
60         PKIX_PL_Cert *firstCert = NULL;
61         PKIX_PL_Cert *secondCert = NULL;
62 
63         PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Equals");
64         PKIX_NULLCHECK_THREE(first, second, pResult);
65 
66         PKIX_CHECK(pkix_CheckType(first, PKIX_TRUSTANCHOR_TYPE, plContext),
67                     PKIX_FIRSTOBJECTNOTTRUSTANCHOR);
68 
69         PKIX_CHECK(PKIX_PL_Object_GetType(second, &secondType, plContext),
70                     PKIX_COULDNOTGETTYPEOFSECONDARGUMENT);
71 
72         *pResult = PKIX_FALSE;
73 
74         if (secondType != PKIX_TRUSTANCHOR_TYPE) goto cleanup;
75 
76         firstAnchor = (PKIX_TrustAnchor *)first;
77         secondAnchor = (PKIX_TrustAnchor *)second;
78 
79         firstCert = firstAnchor->trustedCert;
80         secondCert = secondAnchor->trustedCert;
81 
82         if ((firstCert && !secondCert) || (!firstCert && secondCert)){
83                 goto cleanup;
84         }
85 
86         if (firstCert && secondCert){
87                 PKIX_CHECK(PKIX_PL_Object_Equals
88                             ((PKIX_PL_Object *)firstCert,
89                             (PKIX_PL_Object *)secondCert,
90                             &cmpResult,
91                             plContext),
92                             PKIX_OBJECTEQUALSFAILED);
93         } else {
94                 PKIX_CHECK(PKIX_PL_Object_Equals
95                             ((PKIX_PL_Object *)firstAnchor->caName,
96                             (PKIX_PL_Object *)secondAnchor->caName,
97                             &cmpResult,
98                             plContext),
99                             PKIX_OBJECTEQUALSFAILED);
100 
101                 if (!cmpResult) goto cleanup;
102 
103                 PKIX_CHECK(PKIX_PL_Object_Equals
104                             ((PKIX_PL_Object *)firstAnchor->caPubKey,
105                             (PKIX_PL_Object *)secondAnchor->caPubKey,
106                             &cmpResult,
107                             plContext),
108                             PKIX_OBJECTEQUALSFAILED);
109 
110                 if (!cmpResult) goto cleanup;
111 
112                 PKIX_EQUALS
113                         (firstAnchor->nameConstraints,
114                         secondAnchor->nameConstraints,
115                         &cmpResult,
116                         plContext,
117                         PKIX_OBJECTEQUALSFAILED);
118 
119                 if (!cmpResult) goto cleanup;
120 
121         }
122 
123         *pResult = cmpResult;
124 
125 cleanup:
126 
127         PKIX_RETURN(TRUSTANCHOR);
128 }
129 
130 /*
131  * FUNCTION: pkix_TrustAnchor_Hashcode
132  * (see comments for PKIX_PL_HashcodeCallback in pkix_pl_system.h)
133  */
134 static PKIX_Error *
pkix_TrustAnchor_Hashcode(PKIX_PL_Object * object,PKIX_UInt32 * pHashcode,void * plContext)135 pkix_TrustAnchor_Hashcode(
136         PKIX_PL_Object *object,
137         PKIX_UInt32 *pHashcode,
138         void *plContext)
139 {
140         PKIX_TrustAnchor *anchor = NULL;
141         PKIX_PL_Cert *cert = NULL;
142         PKIX_UInt32 hash = 0;
143         PKIX_UInt32 certHash = 0;
144         PKIX_UInt32 nameHash = 0;
145         PKIX_UInt32 pubKeyHash = 0;
146         PKIX_UInt32 ncHash = 0;
147 
148         PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_Hashcode");
149         PKIX_NULLCHECK_TWO(object, pHashcode);
150 
151         PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
152                     PKIX_OBJECTNOTTRUSTANCHOR);
153 
154         anchor = (PKIX_TrustAnchor*)object;
155         cert = anchor->trustedCert;
156 
157         if (cert){
158                 PKIX_CHECK(PKIX_PL_Object_Hashcode
159                             ((PKIX_PL_Object *)cert,
160                             &certHash,
161                             plContext),
162                             PKIX_OBJECTHASHCODEFAILED);
163 
164                 hash = certHash;
165 
166         } else {
167                 PKIX_CHECK(PKIX_PL_Object_Hashcode
168                             ((PKIX_PL_Object *)anchor->caName,
169                             &nameHash,
170                             plContext),
171                             PKIX_OBJECTHASHCODEFAILED);
172 
173                 PKIX_CHECK(PKIX_PL_Object_Hashcode
174                             ((PKIX_PL_Object *)anchor->caPubKey,
175                             &pubKeyHash,
176                             plContext),
177                             PKIX_OBJECTHASHCODEFAILED);
178 
179                 PKIX_HASHCODE(anchor->nameConstraints, &ncHash, plContext,
180                         PKIX_OBJECTHASHCODEFAILED);
181 
182                 hash = 31 * nameHash + pubKeyHash + ncHash;
183 
184         }
185 
186         *pHashcode = hash;
187 
188 cleanup:
189 
190         PKIX_RETURN(TRUSTANCHOR);
191 }
192 
193 /*
194  * FUNCTION: pkix_TrustAnchor_ToString
195  * (see comments for PKIX_PL_ToStringCallback in pkix_pl_system.h)
196  */
197 static PKIX_Error *
pkix_TrustAnchor_ToString(PKIX_PL_Object * object,PKIX_PL_String ** pString,void * plContext)198 pkix_TrustAnchor_ToString(
199         PKIX_PL_Object *object,
200         PKIX_PL_String **pString,
201         void *plContext)
202 {
203         PKIX_TrustAnchor *anchor = NULL;
204         char *asciiFormat = NULL;
205         PKIX_PL_String *formatString = NULL;
206         PKIX_PL_String *anchorString = NULL;
207         PKIX_PL_String *certString = NULL;
208         PKIX_PL_String *nameString = NULL;
209         PKIX_PL_String *pubKeyString = NULL;
210         PKIX_PL_String *nameConstraintsString = NULL;
211 
212         PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_ToString");
213         PKIX_NULLCHECK_TWO(object, pString);
214 
215         PKIX_CHECK(pkix_CheckType(object, PKIX_TRUSTANCHOR_TYPE, plContext),
216                     PKIX_OBJECTNOTTRUSTANCHOR);
217 
218         anchor = (PKIX_TrustAnchor*)object;
219 
220         if (anchor->trustedCert){
221                 asciiFormat =
222                         "[\n"
223                         "\tTrusted Cert:	%s\n"
224                         "]\n";
225 
226                 PKIX_CHECK(PKIX_PL_String_Create
227                             (PKIX_ESCASCII,
228                             asciiFormat,
229                             0,
230                             &formatString,
231                             plContext),
232                             PKIX_STRINGCREATEFAILED);
233 
234                 PKIX_CHECK(PKIX_PL_Object_ToString
235                             ((PKIX_PL_Object *)anchor->trustedCert,
236                             &certString,
237                             plContext),
238                             PKIX_OBJECTTOSTRINGFAILED);
239 
240                 PKIX_CHECK(PKIX_PL_Sprintf
241                             (&anchorString,
242                             plContext,
243                             formatString,
244                             certString),
245                             PKIX_SPRINTFFAILED);
246         } else {
247                 asciiFormat =
248                         "[\n"
249                         "\tTrusted CA Name:         %s\n"
250                         "\tTrusted CA PublicKey:    %s\n"
251                         "\tInitial Name Constraints:%s\n"
252                         "]\n";
253 
254                 PKIX_CHECK(PKIX_PL_String_Create
255                             (PKIX_ESCASCII,
256                             asciiFormat,
257                             0,
258                             &formatString,
259                             plContext),
260                             PKIX_STRINGCREATEFAILED);
261 
262                 PKIX_CHECK(PKIX_PL_Object_ToString
263                             ((PKIX_PL_Object *)anchor->caName,
264                             &nameString,
265                             plContext),
266                             PKIX_OBJECTTOSTRINGFAILED);
267 
268                 PKIX_CHECK(PKIX_PL_Object_ToString
269                             ((PKIX_PL_Object *)anchor->caPubKey,
270                             &pubKeyString,
271                             plContext),
272                             PKIX_OBJECTTOSTRINGFAILED);
273 
274                 PKIX_TOSTRING
275                         (anchor->nameConstraints,
276                         &nameConstraintsString,
277                         plContext,
278                         PKIX_OBJECTTOSTRINGFAILED);
279 
280                 PKIX_CHECK(PKIX_PL_Sprintf
281                             (&anchorString,
282                             plContext,
283                             formatString,
284                             nameString,
285                             pubKeyString,
286                             nameConstraintsString),
287                             PKIX_SPRINTFFAILED);
288         }
289 
290         *pString = anchorString;
291 
292 cleanup:
293 
294         PKIX_DECREF(formatString);
295         PKIX_DECREF(certString);
296         PKIX_DECREF(nameString);
297         PKIX_DECREF(pubKeyString);
298         PKIX_DECREF(nameConstraintsString);
299 
300         PKIX_RETURN(TRUSTANCHOR);
301 }
302 
303 /*
304  * FUNCTION: pkix_TrustAnchor_RegisterSelf
305  * DESCRIPTION:
306  *  Registers PKIX_TRUSTANCHOR_TYPE and its related functions with
307  *  systemClasses[]
308  * THREAD SAFETY:
309  *  Not Thread Safe - for performance and complexity reasons
310  *
311  *  Since this function is only called by PKIX_PL_Initialize, which should
312  *  only be called once, it is acceptable that this function is not
313  *  thread-safe.
314  */
315 PKIX_Error *
pkix_TrustAnchor_RegisterSelf(void * plContext)316 pkix_TrustAnchor_RegisterSelf(void *plContext)
317 {
318         extern pkix_ClassTable_Entry systemClasses[PKIX_NUMTYPES];
319         pkix_ClassTable_Entry entry;
320 
321         PKIX_ENTER(TRUSTANCHOR, "pkix_TrustAnchor_RegisterSelf");
322 
323         entry.description = "TrustAnchor";
324         entry.objCounter = 0;
325         entry.typeObjectSize = sizeof(PKIX_TrustAnchor);
326         entry.destructor = pkix_TrustAnchor_Destroy;
327         entry.equalsFunction = pkix_TrustAnchor_Equals;
328         entry.hashcodeFunction = pkix_TrustAnchor_Hashcode;
329         entry.toStringFunction = pkix_TrustAnchor_ToString;
330         entry.comparator = NULL;
331         entry.duplicateFunction = pkix_duplicateImmutable;
332 
333         systemClasses[PKIX_TRUSTANCHOR_TYPE] = entry;
334 
335         PKIX_RETURN(TRUSTANCHOR);
336 }
337 
338 /* --Public-Functions--------------------------------------------- */
339 
340 
341 /*
342  * FUNCTION: PKIX_TrustAnchor_CreateWithCert (see comments in pkix_params.h)
343  */
344 PKIX_Error *
PKIX_TrustAnchor_CreateWithCert(PKIX_PL_Cert * cert,PKIX_TrustAnchor ** pAnchor,void * plContext)345 PKIX_TrustAnchor_CreateWithCert(
346         PKIX_PL_Cert *cert,
347         PKIX_TrustAnchor **pAnchor,
348         void *plContext)
349 {
350         PKIX_TrustAnchor *anchor = NULL;
351 
352         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithCert");
353         PKIX_NULLCHECK_TWO(cert, pAnchor);
354 
355         PKIX_CHECK(PKIX_PL_Object_Alloc
356                     (PKIX_TRUSTANCHOR_TYPE,
357                     sizeof (PKIX_TrustAnchor),
358                     (PKIX_PL_Object **)&anchor,
359                     plContext),
360                     PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
361 
362         /* initialize fields */
363         PKIX_CHECK(
364             PKIX_PL_Cert_SetAsTrustAnchor(cert, plContext),
365             PKIX_CERTSETASTRUSTANCHORFAILED);
366 
367         PKIX_INCREF(cert);
368         anchor->trustedCert = cert;
369 
370         anchor->caName = NULL;
371         anchor->caPubKey = NULL;
372 
373         PKIX_CHECK(PKIX_PL_Cert_GetNameConstraints
374                     (anchor->trustedCert, &anchor->nameConstraints, plContext),
375                     PKIX_CERTGETNAMECONSTRAINTSFAILED);
376 
377 
378         *pAnchor = anchor;
379         anchor = NULL;
380 
381 cleanup:
382 
383         PKIX_DECREF(anchor);
384 
385         PKIX_RETURN(TRUSTANCHOR);
386 
387 }
388 
389 /*
390  * FUNCTION: PKIX_TrustAnchor_CreateWithNameKeyPair
391  *      (see comments in pkix_params.h)
392  */
393 PKIX_Error *
PKIX_TrustAnchor_CreateWithNameKeyPair(PKIX_PL_X500Name * name,PKIX_PL_PublicKey * pubKey,PKIX_PL_CertNameConstraints * nameConstraints,PKIX_TrustAnchor ** pAnchor,void * plContext)394 PKIX_TrustAnchor_CreateWithNameKeyPair(
395         PKIX_PL_X500Name *name,
396         PKIX_PL_PublicKey *pubKey,
397         PKIX_PL_CertNameConstraints *nameConstraints,
398         PKIX_TrustAnchor **pAnchor,
399         void *plContext)
400 {
401         PKIX_TrustAnchor *anchor = NULL;
402 
403         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_CreateWithNameKeyPair");
404 
405 #ifndef BUILD_LIBPKIX_TESTS
406         /* Nss creates trust anchors by using PKIX_TrustAnchor_CreateWithCert
407          * function as the complete trusted cert structure, and not only cert
408          * public key, is required for chain building and validation processes.
409          * Restricting this function for been used only in libpkix unit
410          * tests. */
411         PKIX_ERROR(PKIX_FUNCTIONMUSTNOTBEUSED);
412 #endif
413 
414         PKIX_NULLCHECK_THREE(name, pubKey, pAnchor);
415 
416         PKIX_CHECK(PKIX_PL_Object_Alloc
417                     (PKIX_TRUSTANCHOR_TYPE,
418                     sizeof (PKIX_TrustAnchor),
419                     (PKIX_PL_Object **)&anchor,
420                     plContext),
421                     PKIX_COULDNOTCREATETRUSTANCHOROBJECT);
422 
423         /* initialize fields */
424         anchor->trustedCert = NULL;
425 
426         PKIX_INCREF(name);
427         anchor->caName = name;
428 
429         PKIX_INCREF(pubKey);
430         anchor->caPubKey = pubKey;
431 
432         PKIX_INCREF(nameConstraints);
433         anchor->nameConstraints = nameConstraints;
434 
435         *pAnchor = anchor;
436         anchor = NULL;
437 cleanup:
438 
439         PKIX_DECREF(anchor);
440 
441         PKIX_RETURN(TRUSTANCHOR);
442 }
443 
444 /*
445  * FUNCTION: PKIX_TrustAnchor_GetTrustedCert (see comments in pkix_params.h)
446  */
447 PKIX_Error *
PKIX_TrustAnchor_GetTrustedCert(PKIX_TrustAnchor * anchor,PKIX_PL_Cert ** pCert,void * plContext)448 PKIX_TrustAnchor_GetTrustedCert(
449         PKIX_TrustAnchor *anchor,
450         PKIX_PL_Cert **pCert,
451         void *plContext)
452 {
453         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetTrustedCert");
454         PKIX_NULLCHECK_TWO(anchor, pCert);
455 
456         PKIX_INCREF(anchor->trustedCert);
457 
458         *pCert = anchor->trustedCert;
459 
460 cleanup:
461         PKIX_RETURN(TRUSTANCHOR);
462 
463 }
464 
465 /*
466  * FUNCTION: PKIX_TrustAnchor_GetCAName (see comments in pkix_params.h)
467  */
468 PKIX_Error *
PKIX_TrustAnchor_GetCAName(PKIX_TrustAnchor * anchor,PKIX_PL_X500Name ** pCAName,void * plContext)469 PKIX_TrustAnchor_GetCAName(
470         PKIX_TrustAnchor *anchor,
471         PKIX_PL_X500Name **pCAName,
472         void *plContext)
473 {
474         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAName");
475         PKIX_NULLCHECK_TWO(anchor, pCAName);
476 
477         PKIX_INCREF(anchor->caName);
478 
479         *pCAName = anchor->caName;
480 
481 cleanup:
482         PKIX_RETURN(TRUSTANCHOR);
483 
484 }
485 
486 /*
487  * FUNCTION: PKIX_TrustAnchor_GetCAPublicKey (see comments in pkix_params.h)
488  */
489 PKIX_Error *
PKIX_TrustAnchor_GetCAPublicKey(PKIX_TrustAnchor * anchor,PKIX_PL_PublicKey ** pPubKey,void * plContext)490 PKIX_TrustAnchor_GetCAPublicKey(
491         PKIX_TrustAnchor *anchor,
492         PKIX_PL_PublicKey **pPubKey,
493         void *plContext)
494 {
495         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetCAPublicKey");
496         PKIX_NULLCHECK_TWO(anchor, pPubKey);
497 
498         PKIX_INCREF(anchor->caPubKey);
499 
500         *pPubKey = anchor->caPubKey;
501 
502 cleanup:
503         PKIX_RETURN(TRUSTANCHOR);
504 }
505 
506 /*
507  * FUNCTION: PKIX_TrustAnchor_GetNameConstraints
508  *      (see comments in pkix_params.h)
509  */
510 PKIX_Error *
PKIX_TrustAnchor_GetNameConstraints(PKIX_TrustAnchor * anchor,PKIX_PL_CertNameConstraints ** pNameConstraints,void * plContext)511 PKIX_TrustAnchor_GetNameConstraints(
512         PKIX_TrustAnchor *anchor,
513         PKIX_PL_CertNameConstraints **pNameConstraints,
514         void *plContext)
515 {
516         PKIX_ENTER(TRUSTANCHOR, "PKIX_TrustAnchor_GetNameConstraints");
517         PKIX_NULLCHECK_TWO(anchor, pNameConstraints);
518 
519         PKIX_INCREF(anchor->nameConstraints);
520 
521         *pNameConstraints = anchor->nameConstraints;
522 
523 cleanup:
524         PKIX_RETURN(TRUSTANCHOR);
525 }
526