security/pkix/lib/pkixutil.h

branch
TOR_BUG_9701
changeset 3
141e0f1194b1
equal deleted inserted replaced
-1:000000000000 0:293eb2618afd
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* Copyright 2013 Mozilla Foundation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #ifndef mozilla_pkix__pkixutil_h
19 #define mozilla_pkix__pkixutil_h
20
21 #include "pkix/pkixtypes.h"
22 #include "prerror.h"
23 #include "seccomon.h"
24 #include "secerr.h"
25
26 namespace mozilla { namespace pkix {
27
28 enum Result
29 {
30 Success = 0,
31 FatalError = -1, // An error was encountered that caused path building
32 // to stop immediately. example: out-of-memory.
33 RecoverableError = -2 // an error that will cause path building to continue
34 // searching for alternative paths. example: expired
35 // certificate.
36 };
37
38 // When returning errors, use this function instead of calling PR_SetError
39 // directly. This helps ensure that we always call PR_SetError when we return
40 // an error code. This is a useful place to set a breakpoint when a debugging
41 // a certificate verification failure.
42 inline Result
43 Fail(Result result, PRErrorCode errorCode)
44 {
45 PR_ASSERT(result != Success);
46 PR_SetError(errorCode, 0);
47 return result;
48 }
49
50 inline Result
51 MapSECStatus(SECStatus srv)
52 {
53 if (srv == SECSuccess) {
54 return Success;
55 }
56
57 PRErrorCode error = PORT_GetError();
58 switch (error) {
59 case SEC_ERROR_EXTENSION_NOT_FOUND:
60 return RecoverableError;
61
62 case PR_INVALID_STATE_ERROR:
63 case SEC_ERROR_LIBRARY_FAILURE:
64 case SEC_ERROR_NO_MEMORY:
65 return FatalError;
66 }
67
68 // TODO: PORT_Assert(false); // we haven't classified the error yet
69 return RecoverableError;
70 }
71
72 // During path building and verification, we build a linked list of BackCerts
73 // from the current cert toward the end-entity certificate. The linked list
74 // is used to verify properties that aren't local to the current certificate
75 // and/or the direct link between the current certificate and its issuer,
76 // such as name constraints.
77 //
78 // Each BackCert contains pointers to all the given certificate's extensions
79 // so that we can parse the extension block once and then process the
80 // extensions in an order that may be different than they appear in the cert.
81 class BackCert
82 {
83 public:
84 // ExcludeCN means that GetConstrainedNames won't include the subject CN in
85 // its results. IncludeCN means that GetConstrainedNames will include the
86 // subject CN in its results.
87 enum ConstrainedNameOptions { ExcludeCN = 0, IncludeCN = 1 };
88
89 // nssCert and childCert must be valid for the lifetime of BackCert
90 BackCert(CERTCertificate* nssCert, BackCert* childCert,
91 ConstrainedNameOptions cnOptions)
92 : encodedBasicConstraints(nullptr)
93 , encodedCertificatePolicies(nullptr)
94 , encodedExtendedKeyUsage(nullptr)
95 , encodedKeyUsage(nullptr)
96 , encodedNameConstraints(nullptr)
97 , encodedInhibitAnyPolicy(nullptr)
98 , childCert(childCert)
99 , nssCert(nssCert)
100 , constrainedNames(nullptr)
101 , cnOptions(cnOptions)
102 {
103 }
104
105 Result Init();
106
107 const SECItem* encodedBasicConstraints;
108 const SECItem* encodedCertificatePolicies;
109 const SECItem* encodedExtendedKeyUsage;
110 const SECItem* encodedKeyUsage;
111 const SECItem* encodedNameConstraints;
112 const SECItem* encodedInhibitAnyPolicy;
113
114 BackCert* const childCert;
115
116 // Only non-const so that we can pass this to TrustDomain::IsRevoked,
117 // which only takes a non-const pointer because VerifyEncodedOCSPResponse
118 // requires it, and that is only because the implementation of
119 // VerifyEncodedOCSPResponse does a CERT_DupCertificate. TODO: get rid
120 // of that CERT_DupCertificate so that we can make all these things const.
121 /*const*/ CERTCertificate* GetNSSCert() const { return nssCert; }
122
123 // Returns the names that should be considered when evaluating name
124 // constraints. The list is constructed lazily and cached. The result is a
125 // weak reference; do not try to free it, and do not hold long-lived
126 // references to it.
127 Result GetConstrainedNames(/*out*/ const CERTGeneralName** result);
128
129 // This is the only place where we should be dealing with non-const
130 // CERTCertificates.
131 Result PrependNSSCertToList(CERTCertList* results);
132
133 PLArenaPool* GetArena();
134
135 private:
136 CERTCertificate* nssCert;
137
138 ScopedPLArenaPool arena;
139 CERTGeneralName* constrainedNames;
140 ConstrainedNameOptions cnOptions;
141
142 BackCert(const BackCert&) /* = delete */;
143 void operator=(const BackCert&); /* = delete */;
144 };
145
146 } } // namespace mozilla::pkix
147
148 #endif // mozilla_pkix__pkixutil_h

mercurial