1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/pkix/lib/pkixutil.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,148 @@ 1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 1.5 +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ 1.6 +/* Copyright 2013 Mozilla Foundation 1.7 + * 1.8 + * Licensed under the Apache License, Version 2.0 (the "License"); 1.9 + * you may not use this file except in compliance with the License. 1.10 + * You may obtain a copy of the License at 1.11 + * 1.12 + * http://www.apache.org/licenses/LICENSE-2.0 1.13 + * 1.14 + * Unless required by applicable law or agreed to in writing, software 1.15 + * distributed under the License is distributed on an "AS IS" BASIS, 1.16 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1.17 + * See the License for the specific language governing permissions and 1.18 + * limitations under the License. 1.19 + */ 1.20 + 1.21 +#ifndef mozilla_pkix__pkixutil_h 1.22 +#define mozilla_pkix__pkixutil_h 1.23 + 1.24 +#include "pkix/pkixtypes.h" 1.25 +#include "prerror.h" 1.26 +#include "seccomon.h" 1.27 +#include "secerr.h" 1.28 + 1.29 +namespace mozilla { namespace pkix { 1.30 + 1.31 +enum Result 1.32 +{ 1.33 + Success = 0, 1.34 + FatalError = -1, // An error was encountered that caused path building 1.35 + // to stop immediately. example: out-of-memory. 1.36 + RecoverableError = -2 // an error that will cause path building to continue 1.37 + // searching for alternative paths. example: expired 1.38 + // certificate. 1.39 +}; 1.40 + 1.41 +// When returning errors, use this function instead of calling PR_SetError 1.42 +// directly. This helps ensure that we always call PR_SetError when we return 1.43 +// an error code. This is a useful place to set a breakpoint when a debugging 1.44 +// a certificate verification failure. 1.45 +inline Result 1.46 +Fail(Result result, PRErrorCode errorCode) 1.47 +{ 1.48 + PR_ASSERT(result != Success); 1.49 + PR_SetError(errorCode, 0); 1.50 + return result; 1.51 +} 1.52 + 1.53 +inline Result 1.54 +MapSECStatus(SECStatus srv) 1.55 +{ 1.56 + if (srv == SECSuccess) { 1.57 + return Success; 1.58 + } 1.59 + 1.60 + PRErrorCode error = PORT_GetError(); 1.61 + switch (error) { 1.62 + case SEC_ERROR_EXTENSION_NOT_FOUND: 1.63 + return RecoverableError; 1.64 + 1.65 + case PR_INVALID_STATE_ERROR: 1.66 + case SEC_ERROR_LIBRARY_FAILURE: 1.67 + case SEC_ERROR_NO_MEMORY: 1.68 + return FatalError; 1.69 + } 1.70 + 1.71 + // TODO: PORT_Assert(false); // we haven't classified the error yet 1.72 + return RecoverableError; 1.73 +} 1.74 + 1.75 +// During path building and verification, we build a linked list of BackCerts 1.76 +// from the current cert toward the end-entity certificate. The linked list 1.77 +// is used to verify properties that aren't local to the current certificate 1.78 +// and/or the direct link between the current certificate and its issuer, 1.79 +// such as name constraints. 1.80 +// 1.81 +// Each BackCert contains pointers to all the given certificate's extensions 1.82 +// so that we can parse the extension block once and then process the 1.83 +// extensions in an order that may be different than they appear in the cert. 1.84 +class BackCert 1.85 +{ 1.86 +public: 1.87 + // ExcludeCN means that GetConstrainedNames won't include the subject CN in 1.88 + // its results. IncludeCN means that GetConstrainedNames will include the 1.89 + // subject CN in its results. 1.90 + enum ConstrainedNameOptions { ExcludeCN = 0, IncludeCN = 1 }; 1.91 + 1.92 + // nssCert and childCert must be valid for the lifetime of BackCert 1.93 + BackCert(CERTCertificate* nssCert, BackCert* childCert, 1.94 + ConstrainedNameOptions cnOptions) 1.95 + : encodedBasicConstraints(nullptr) 1.96 + , encodedCertificatePolicies(nullptr) 1.97 + , encodedExtendedKeyUsage(nullptr) 1.98 + , encodedKeyUsage(nullptr) 1.99 + , encodedNameConstraints(nullptr) 1.100 + , encodedInhibitAnyPolicy(nullptr) 1.101 + , childCert(childCert) 1.102 + , nssCert(nssCert) 1.103 + , constrainedNames(nullptr) 1.104 + , cnOptions(cnOptions) 1.105 + { 1.106 + } 1.107 + 1.108 + Result Init(); 1.109 + 1.110 + const SECItem* encodedBasicConstraints; 1.111 + const SECItem* encodedCertificatePolicies; 1.112 + const SECItem* encodedExtendedKeyUsage; 1.113 + const SECItem* encodedKeyUsage; 1.114 + const SECItem* encodedNameConstraints; 1.115 + const SECItem* encodedInhibitAnyPolicy; 1.116 + 1.117 + BackCert* const childCert; 1.118 + 1.119 + // Only non-const so that we can pass this to TrustDomain::IsRevoked, 1.120 + // which only takes a non-const pointer because VerifyEncodedOCSPResponse 1.121 + // requires it, and that is only because the implementation of 1.122 + // VerifyEncodedOCSPResponse does a CERT_DupCertificate. TODO: get rid 1.123 + // of that CERT_DupCertificate so that we can make all these things const. 1.124 + /*const*/ CERTCertificate* GetNSSCert() const { return nssCert; } 1.125 + 1.126 + // Returns the names that should be considered when evaluating name 1.127 + // constraints. The list is constructed lazily and cached. The result is a 1.128 + // weak reference; do not try to free it, and do not hold long-lived 1.129 + // references to it. 1.130 + Result GetConstrainedNames(/*out*/ const CERTGeneralName** result); 1.131 + 1.132 + // This is the only place where we should be dealing with non-const 1.133 + // CERTCertificates. 1.134 + Result PrependNSSCertToList(CERTCertList* results); 1.135 + 1.136 + PLArenaPool* GetArena(); 1.137 + 1.138 +private: 1.139 + CERTCertificate* nssCert; 1.140 + 1.141 + ScopedPLArenaPool arena; 1.142 + CERTGeneralName* constrainedNames; 1.143 + ConstrainedNameOptions cnOptions; 1.144 + 1.145 + BackCert(const BackCert&) /* = delete */; 1.146 + void operator=(const BackCert&); /* = delete */; 1.147 +}; 1.148 + 1.149 +} } // namespace mozilla::pkix 1.150 + 1.151 +#endif // mozilla_pkix__pkixutil_h