| Index: net/cert/internal/signature_algorithm.cc
|
| diff --git a/net/cert/internal/signature_algorithm.cc b/net/cert/internal/signature_algorithm.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a367d14e5abaf604893fa2c34d2a3df59d12fb8a
|
| --- /dev/null
|
| +++ b/net/cert/internal/signature_algorithm.cc
|
| @@ -0,0 +1,222 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "net/cert/internal/signature_algorithm.h"
|
| +
|
| +#include <stdint.h>
|
| +
|
| +#include "net/der/input.h"
|
| +#include "net/der/parser.h"
|
| +
|
| +namespace net {
|
| +
|
| +namespace {
|
| +
|
| +// From RFC 3279 section 2.2.1:
|
| +// sha-1WithRSAEncryption OBJECT IDENTIFIER ::= {
|
| +// iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1)
|
| +// pkcs-1(1) 5 }
|
| +// In dotted notation: 1.2.840.113549.1.1.5
|
| +const uint8_t kOidSha1WithRsaEncryption[] =
|
| + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x05};
|
| +
|
| +// From RFC 4055 section 6:
|
| +// pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
|
| +// us(840) rsadsi(113549) pkcs(1) 1 }
|
| +
|
| +// From RFC 4055 section 5:
|
| +// sha256WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 11 }
|
| +// In dotted notation: 1.2.840.113549.1.1.11
|
| +const uint8_t kOidSha256WithRsaEncryption[] =
|
| + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b};
|
| +
|
| +// From RFC 4055 section 5:
|
| +// sha384WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 12 }
|
| +// In dotted notation: 1.2.840.113549.1.1.12
|
| +const uint8_t kOidSha384WithRsaEncryption[] =
|
| + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0c};
|
| +
|
| +// From RFC 4055 section 5:
|
| +// sha512WithRSAEncryption OBJECT IDENTIFIER ::= { pkcs-1 13 }
|
| +// In dotted notation: 1.2.840.113549.1.1.13
|
| +const uint8_t kOidSha512WithRsaEncryption[] =
|
| + {0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0d};
|
| +
|
| +// From RFC 3279 section 2.2.3:
|
| +// ansi-X9-62 OBJECT IDENTIFIER ::= {
|
| +// iso(1) member-body(2) us(840) 10045 }
|
| +//
|
| +// id-ecSigType OBJECT IDENTIFIER ::= {
|
| +// ansi-X9-62 signatures(4) }
|
| +//
|
| +// ecdsa-with-SHA1 OBJECT IDENTIFIER ::= {
|
| +// id-ecSigType 1 }
|
| +// In dotted notation: 1.2.840.10045.4.1
|
| +const uint8_t kOidEcdsaWithSha1[] = {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x01};
|
| +
|
| +// From RFC 5758 section 3.2:
|
| +// ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
|
| +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 2 }
|
| +// In dotted notation: 1.2.840.10045.4.3.2
|
| +const uint8_t kOidEcdsaWithSha256[] =
|
| + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02};
|
| +
|
| +// From RFC 5758 section 3.2:
|
| +// ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
|
| +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 3 }
|
| +// In dotted notation: 1.2.840.10045.4.3.3
|
| +const uint8_t kOidEcdsaWithSha384[] =
|
| + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x03};
|
| +
|
| +// From RFC 5758 section 3.2:
|
| +// ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2)
|
| +// us(840) ansi-X9-62(10045) signatures(4) ecdsa-with-SHA2(3) 4 }
|
| +// In dotted notation: 1.2.840.10045.4.3.4
|
| +const uint8_t kOidEcdsaWithSha512[] =
|
| + {0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x04};
|
| +
|
| +// Assigns |out| with the values |algorithm| and |digest|. The passed in
|
| +// |algorithm_identifier_parser| is expected to be positioned after the
|
| +// algorithm OID. The parameters field will be consumed, and it must be either
|
| +// NULL or missing.
|
| +//
|
| +// Returns true on success.
|
| +WARN_UNUSED_RESULT bool AssignFromDerEmptyParams(
|
| + SignatureAlgorithmId algorithm,
|
| + DigestAlgorithmId digest,
|
| + der::Parser* algorithm_identifier_parser,
|
| + SignatureAlgorithm* out) {
|
| + // The specifications for RSA PKCS #1 v1.5 and ECDSA signature algorithm are
|
| + // inconsistent on whether the parameters field must be NULL, omitted, or can
|
| + // be either.
|
| + //
|
| + // This implementation is more permissive, and will accept both NULL and
|
| + // omitted parameters.
|
| + //
|
| + // For reference...
|
| + //
|
| + // RFC 5758 section-3.2:
|
| + // When the ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-SHA384, or
|
| + // ecdsa-with-SHA512 algorithm identifier appears in the algorithm field
|
| + // as an AlgorithmIdentifier, the encoding MUST omit the parameters
|
| + // field. That is, the AlgorithmIdentifier SHALL be a SEQUENCE of one
|
| + // component, the OID ecdsa-with-SHA224, ecdsa-with-SHA256, ecdsa-with-
|
| + // SHA384, or ecdsa-with-SHA512.
|
| + //
|
| + // RFC 3279 section 2.2.1 (in reference to sha-1WithRSAEncryption):
|
| + // When any of these three OIDs appears within the ASN.1 type
|
| + // AlgorithmIdentifier, the parameters component of that type SHALL be
|
| + // the ASN.1 type NULL.
|
| + //
|
| + // RFC 3279 section 2.2.3:
|
| + // When the ecdsa-with-SHA1 algorithm identifier appears as the
|
| + // algorithm field in an AlgorithmIdentifier, the encoding MUST omit the
|
| + // parameters field. That is, the AlgorithmIdentifier SHALL be a
|
| + // SEQUENCE of one component: the OBJECT IDENTIFIER ecdsa-with-SHA1.
|
| + //
|
| + // RFC 4055 section 5 (in reference to sha256WithRSAEncryption et al):
|
| + // When any of these four object identifiers appears within an
|
| + // AlgorithmIdentifier, the parameters MUST be NULL. Implementations
|
| + // MUST accept the parameters being absent as well as present.
|
| +
|
| + if (algorithm_identifier_parser->HasMore()) {
|
| + der::Input null_value;
|
| + if (!algorithm_identifier_parser->ReadTag(der::kNull, &null_value))
|
| + return false;
|
| +
|
| + if (null_value.Length() != 0)
|
| + return false; // Not a NULL value
|
| +
|
| + // Important: After consuming the NULL params there shouldn't be anything
|
| + // left. Because parsed SignatureAlgorithm's maybe be tested for equality,
|
| + // it is important that everything was consumed and understood. Otherwise
|
| + // might mistake different algorithms for being the same.
|
| + if (algorithm_identifier_parser->HasMore())
|
| + return false;
|
| + }
|
| +
|
| + out->algorithm = algorithm;
|
| + out->digest = digest;
|
| +
|
| + return true;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +bool SignatureAlgorithm::AssignFromDer(const der::Input& in) {
|
| + // RFC 5280 section 4.1.1.2 defines signatureAlgorithm as:
|
| + //
|
| + // AlgorithmIdentifier ::= SEQUENCE {
|
| + // algorithm OBJECT IDENTIFIER,
|
| + // parameters ANY DEFINED BY algorithm OPTIONAL }
|
| +
|
| + der::Parser parser(in);
|
| +
|
| + der::Parser algorithm_identifier_parser;
|
| + if (!parser.ReadSequence(&algorithm_identifier_parser))
|
| + return false;
|
| +
|
| + der::Input oid;
|
| + if (!algorithm_identifier_parser.ReadTag(der::kOid, &oid))
|
| + return false;
|
| +
|
| + // TODO(eroman): Each OID is tested for equality in order, which is not
|
| + // particularly efficient.
|
| +
|
| + if (oid.Equals(der::Input(kOidSha1WithRsaEncryption))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5,
|
| + DigestAlgorithmId::Sha1,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidSha256WithRsaEncryption))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5,
|
| + DigestAlgorithmId::Sha256,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidSha384WithRsaEncryption))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5,
|
| + DigestAlgorithmId::Sha384,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidSha512WithRsaEncryption))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::RsaPkcs1_5,
|
| + DigestAlgorithmId::Sha512,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidEcdsaWithSha1))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa,
|
| + DigestAlgorithmId::Sha1,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidEcdsaWithSha256))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa,
|
| + DigestAlgorithmId::Sha256,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidEcdsaWithSha384))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa,
|
| + DigestAlgorithmId::Sha384,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + if (oid.Equals(der::Input(kOidEcdsaWithSha512))) {
|
| + return AssignFromDerEmptyParams(SignatureAlgorithmId::Ecdsa,
|
| + DigestAlgorithmId::Sha512,
|
| + &algorithm_identifier_parser, this);
|
| + }
|
| +
|
| + return false; // Unsupported OID.
|
| +}
|
| +
|
| +bool SignatureAlgorithm::Equals(const SignatureAlgorithm& other) const {
|
| + return algorithm == other.algorithm && digest == other.digest;
|
| +}
|
| +
|
| +} // namespace net
|
|
|