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