Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Bug 1038828: Replace mozilla::pkix::der::Result with uses of mozilla:…
…:pkix::Result, r=mmc

--HG--
rename : lib/mozpkix/lib/pkixutil.h => lib/mozpkix/include/pkix/Result.h
extra : rebase_source : e385af4bab665627aa5d434db04830065cbc641f
  • Loading branch information
briansmith committed Jul 15, 2014
1 parent 98efd83 commit 72477d8
Show file tree
Hide file tree
Showing 11 changed files with 662 additions and 584 deletions.
81 changes: 81 additions & 0 deletions lib/mozpkix/include/pkix/Result.h
@@ -0,0 +1,81 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This code is made available to you under your choice of the following sets
* of licensing terms:
*/
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* Copyright 2013 Mozilla Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef mozilla_pkix__Result_h
#define mozilla_pkix__Result_h

#include "prerror.h"
#include "seccomon.h"
#include "secerr.h"

namespace mozilla { namespace pkix {

enum Result
{
Success = 0,
FatalError = -1, // An error was encountered that caused path building
// to stop immediately. example: out-of-memory.
RecoverableError = -2 // an error that will cause path building to continue
// searching for alternative paths. example: expired
// certificate.
};

// When returning errors, use this function instead of calling PR_SetError
// directly. This helps ensure that we always call PR_SetError when we return
// an error code. This is a useful place to set a breakpoint when a debugging
// a certificate verification failure.
inline Result
Fail(Result result, PRErrorCode errorCode)
{
PR_ASSERT(result != Success);
PR_SetError(errorCode, 0);
return result;
}

inline Result
MapSECStatus(SECStatus srv)
{
if (srv == SECSuccess) {
return Success;
}

PRErrorCode error = PORT_GetError();
switch (error) {
case SEC_ERROR_EXTENSION_NOT_FOUND:
return RecoverableError;

case PR_INVALID_STATE_ERROR:
case SEC_ERROR_INVALID_ARGS:
case SEC_ERROR_LIBRARY_FAILURE:
case SEC_ERROR_NO_MEMORY:
return FatalError;
}

// TODO: PORT_Assert(false); // we haven't classified the error yet
return RecoverableError;
}

} } // namespace mozilla::pkix

#endif // mozilla_pkix__Result_h
100 changes: 53 additions & 47 deletions lib/mozpkix/lib/pkixcert.cpp
Expand Up @@ -30,6 +30,8 @@ namespace mozilla { namespace pkix {
Result
BackCert::Init()
{
Result rv;

// Certificate ::= SEQUENCE {
// tbsCertificate TBSCertificate,
// signatureAlgorithm AlgorithmIdentifier,
Expand All @@ -41,23 +43,26 @@ BackCert::Init()
// don't accidentally confuse them for tbsCertificate later.
{
der::Input input;
if (input.Init(der.data, der.len) != der::Success) {
return MapSECStatus(SECFailure);
rv = input.Init(der.data, der.len);
if (rv != Success) {
return rv;
}
der::Input certificate;
if (der::ExpectTagAndGetValue(input, der::SEQUENCE, certificate)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndGetValue(input, der::SEQUENCE, certificate);
if (rv != Success) {
return rv;
}
if (der::End(input) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::End(input);
if (rv != Success) {
return rv;
}
if (der::SignedData(certificate, tbsCertificate, signedData)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::SignedData(certificate, tbsCertificate, signedData);
if (rv != Success) {
return rv;
}
if (der::End(certificate) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::End(certificate);
if (rv != Success) {
return rv;
}
}

Expand All @@ -76,36 +81,37 @@ BackCert::Init()
// extensions [3] EXPLICIT Extensions OPTIONAL
// -- If present, version MUST be v3
// }
if (der::OptionalVersion(tbsCertificate, version) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::OptionalVersion(tbsCertificate, version);
if (rv != Success) {
return rv;
}
if (der::CertificateSerialNumber(tbsCertificate, serialNumber)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::CertificateSerialNumber(tbsCertificate, serialNumber);
if (rv != Success) {
return rv;
}
// XXX: Ignored. What are we supposed to check? This seems totally redundant
// with Certificate.signatureAlgorithm. Is it important to check that they
// are consistent with each other? It doesn't seem to matter!
SignatureAlgorithm signature;
if (der::SignatureAlgorithmIdentifier(tbsCertificate, signature)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::SignatureAlgorithmIdentifier(tbsCertificate, signature);
if (rv != Success) {
return rv;
}
if (der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, issuer)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, issuer);
if (rv != Success) {
return rv;
}
if (der::ExpectTagAndGetValue(tbsCertificate, der::SEQUENCE, validity)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndGetValue(tbsCertificate, der::SEQUENCE, validity);
if (rv != Success) {
return rv;
}
// TODO(bug XXXXXXX): We rely on the the caller of mozilla::pkix to validate
// that the name is syntactically valid, if they care. In Gecko we do this
// implicitly by parsing the certificate into a CERTCertificate object.
// Instead of relying on the caller to do this, we should do it ourselves.
if (der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, subject)
!= der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE, subject);
if (rv != Success) {
return rv;
}
// TODO(bug XXXXXXX): We defer parsing/validating subjectPublicKeyInfo to
// the point where the public key is needed. For end-entity certificates, we
Expand All @@ -114,9 +120,10 @@ BackCert::Init()
// the other hand, if the caller never uses the key then in some ways it
// doesn't matter. Regardless, we should parse and validate
// subjectPublicKeyKeyInfo internally.
if (der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE,
subjectPublicKeyInfo) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndGetTLV(tbsCertificate, der::SEQUENCE,
subjectPublicKeyInfo);
if (rv != Success) {
return rv;
}

static const uint8_t CSC = der::CONTEXT_SPECIFIC | der::CONSTRUCTED;
Expand All @@ -127,36 +134,35 @@ BackCert::Init()

// Ignore issuerUniqueID if present.
if (tbsCertificate.Peek(CSC | 1)) {
if (der::ExpectTagAndSkipValue(tbsCertificate, CSC | 1) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 1);
if (rv != Success) {
return rv;
}
}

// Ignore subjectUniqueID if present.
if (tbsCertificate.Peek(CSC | 2)) {
if (der::ExpectTagAndSkipValue(tbsCertificate, CSC | 2) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::ExpectTagAndSkipValue(tbsCertificate, CSC | 2);
if (rv != Success) {
return rv;
}
}
}

// Extensions were added in v3, so only accept extensions in v3 certificates.
if (version == der::Version::v3) {
if (der::OptionalExtensions(tbsCertificate, CSC | 3,
bind(&BackCert::RememberExtension, this, _1, _2,
_3)) != der::Success) {
return MapSECStatus(SECFailure);
rv = der::OptionalExtensions(tbsCertificate, CSC | 3,
bind(&BackCert::RememberExtension, this, _1,
_2, _3));
if (rv != Success) {
return rv;
}
}

if (der::End(tbsCertificate) != der::Success) {
return MapSECStatus(SECFailure);
}

return Success;
return der::End(tbsCertificate);
}

der::Result
Result
BackCert::RememberExtension(der::Input& extnID, const SECItem& extnValue,
/*out*/ bool& understood)
{
Expand Down Expand Up @@ -247,7 +253,7 @@ BackCert::RememberExtension(der::Input& extnID, const SECItem& extnValue,
understood = true;
}

return der::Success;
return Success;
}

} } // namespace mozilla::pkix

0 comments on commit 72477d8

Please sign in to comment.