1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/cert/internal/simple_path_builder_delegate.h"
6
7 #include "net/cert/internal/cert_error_params.h"
8 #include "net/cert/internal/cert_errors.h"
9 #include "net/cert/internal/signature_algorithm.h"
10 #include "net/cert/internal/verify_signed_data.h"
11 #include "third_party/boringssl/src/include/openssl/bn.h"
12 #include "third_party/boringssl/src/include/openssl/bytestring.h"
13 #include "third_party/boringssl/src/include/openssl/digest.h"
14 #include "third_party/boringssl/src/include/openssl/ec.h"
15 #include "third_party/boringssl/src/include/openssl/ec_key.h"
16 #include "third_party/boringssl/src/include/openssl/evp.h"
17 #include "third_party/boringssl/src/include/openssl/nid.h"
18 #include "third_party/boringssl/src/include/openssl/rsa.h"
19
20 namespace net {
21
22 DEFINE_CERT_ERROR_ID(SimplePathBuilderDelegate::kRsaModulusTooSmall,
23 "RSA modulus too small");
24
25 namespace {
26
27 DEFINE_CERT_ERROR_ID(kUnacceptableCurveForEcdsa,
28 "Only P-256, P-384, P-521 are supported for ECDSA");
29
IsAcceptableCurveForEcdsa(int curve_nid)30 bool IsAcceptableCurveForEcdsa(int curve_nid) {
31 switch (curve_nid) {
32 case NID_X9_62_prime256v1:
33 case NID_secp384r1:
34 case NID_secp521r1:
35 return true;
36 }
37
38 return false;
39 }
40
41 } // namespace
42
SimplePathBuilderDelegate(size_t min_rsa_modulus_length_bits,DigestPolicy digest_policy)43 SimplePathBuilderDelegate::SimplePathBuilderDelegate(
44 size_t min_rsa_modulus_length_bits,
45 DigestPolicy digest_policy)
46 : min_rsa_modulus_length_bits_(min_rsa_modulus_length_bits),
47 digest_policy_(digest_policy) {}
48
CheckPathAfterVerification(const CertPathBuilder & path_builder,CertPathBuilderResultPath * path)49 void SimplePathBuilderDelegate::CheckPathAfterVerification(
50 const CertPathBuilder& path_builder,
51 CertPathBuilderResultPath* path) {
52 // Do nothing - consider all candidate paths valid.
53 }
54
IsSignatureAlgorithmAcceptable(const SignatureAlgorithm & algorithm,CertErrors * errors)55 bool SimplePathBuilderDelegate::IsSignatureAlgorithmAcceptable(
56 const SignatureAlgorithm& algorithm,
57 CertErrors* errors) {
58 // Restrict default permitted signature algorithms to:
59 //
60 // RSA PKCS#1 v1.5
61 // RSASSA-PSS
62 // ECDSA
63 switch (algorithm.algorithm()) {
64 case SignatureAlgorithmId::Dsa:
65 return false;
66 case SignatureAlgorithmId::Ecdsa:
67 case SignatureAlgorithmId::RsaPkcs1:
68 return IsAcceptableDigest(algorithm.digest());
69 case SignatureAlgorithmId::RsaPss:
70 return IsAcceptableDigest(algorithm.digest()) &&
71 IsAcceptableDigest(algorithm.ParamsForRsaPss()->mgf1_hash());
72 }
73
74 return false;
75 }
76
IsPublicKeyAcceptable(EVP_PKEY * public_key,CertErrors * errors)77 bool SimplePathBuilderDelegate::IsPublicKeyAcceptable(EVP_PKEY* public_key,
78 CertErrors* errors) {
79 int pkey_id = EVP_PKEY_id(public_key);
80 if (pkey_id == EVP_PKEY_RSA) {
81 // Extract the modulus length from the key.
82 RSA* rsa = EVP_PKEY_get0_RSA(public_key);
83 if (!rsa)
84 return false;
85 unsigned int modulus_length_bits = BN_num_bits(rsa->n);
86
87 if (modulus_length_bits < min_rsa_modulus_length_bits_) {
88 errors->AddError(
89 kRsaModulusTooSmall,
90 CreateCertErrorParams2SizeT("actual", modulus_length_bits, "minimum",
91 min_rsa_modulus_length_bits_));
92 return false;
93 }
94
95 return true;
96 }
97
98 if (pkey_id == EVP_PKEY_EC) {
99 // Extract the curve name.
100 EC_KEY* ec = EVP_PKEY_get0_EC_KEY(public_key);
101 if (!ec)
102 return false; // Unexpected.
103 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
104
105 if (!IsAcceptableCurveForEcdsa(curve_nid)) {
106 errors->AddError(kUnacceptableCurveForEcdsa);
107 return false;
108 }
109
110 return true;
111 }
112
113 // Unexpected key type.
114 return false;
115 }
116
117 // Restricted signature digest algorithms to:
118 //
119 // SHA1 (if digest_policy_ == kWeakAllowSha1)
120 // SHA256
121 // SHA384
122 // SHA512
IsAcceptableDigest(DigestAlgorithm digest) const123 bool SimplePathBuilderDelegate::IsAcceptableDigest(
124 DigestAlgorithm digest) const {
125 switch (digest) {
126 case DigestAlgorithm::Md2:
127 case DigestAlgorithm::Md4:
128 case DigestAlgorithm::Md5:
129 return false;
130
131 case DigestAlgorithm::Sha1:
132 return digest_policy_ ==
133 SimplePathBuilderDelegate::DigestPolicy::kWeakAllowSha1;
134 case DigestAlgorithm::Sha256:
135 case DigestAlgorithm::Sha384:
136 case DigestAlgorithm::Sha512:
137 return true;
138 }
139
140 return false;
141 }
142
143 } // namespace net
144