Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(45)

Side by Side Diff: net/cert/internal/verify_signed_data.cc

Issue 1259313002: Add some policy controls for VerifySignedData(). (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@add_python
Patch Set: Address more comments Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/cert/internal/verify_signed_data.h" 5 #include "net/cert/internal/verify_signed_data.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "net/der/parse_values.h" 8 #include "net/der/parse_values.h"
9 9
10 // TODO(eroman): There is no intention to implement this for non-OpenSSL. Remove 10 // TODO(eroman): There is no intention to implement this for non-OpenSSL. Remove
11 // this branch once the migration is complete. This could have been done as a 11 // this branch once the migration is complete. This could have been done as a
12 // conditional file (_openssl.cc) in the build file instead, but that is likely 12 // conditional file (_openssl.cc) in the build file instead, but that is likely
13 // not worth the effort at this point. 13 // not worth the effort at this point.
14 14
15 #if !defined(USE_OPENSSL) 15 #if !defined(USE_OPENSSL)
16 16
17 namespace net { 17 namespace net {
18 18
19 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, 19 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm,
20 const der::Input& signed_data, 20 const der::Input& signed_data,
21 const der::BitString& signature_value, 21 const der::BitString& signature_value,
22 const der::Input& public_key) { 22 const der::Input& public_key,
23 const SignaturePolicy* policy) {
23 NOTIMPLEMENTED(); 24 NOTIMPLEMENTED();
24 return false; 25 return false;
25 } 26 }
26 27
27 } // namespace net 28 } // namespace net
28 29
29 #else 30 #else
30 31
31 #include <openssl/digest.h> 32 #include <openssl/digest.h>
32 #include <openssl/ec.h> 33 #include <openssl/ec.h>
33 #include <openssl/ec_key.h> 34 #include <openssl/ec_key.h>
34 #include <openssl/evp.h> 35 #include <openssl/evp.h>
35 #include <openssl/rsa.h> 36 #include <openssl/rsa.h>
36 #include <openssl/x509.h> 37 #include <openssl/x509.h>
37 38
38 #include "base/compiler_specific.h" 39 #include "base/compiler_specific.h"
39 #include "crypto/openssl_util.h" 40 #include "crypto/openssl_util.h"
40 #include "crypto/scoped_openssl_types.h" 41 #include "crypto/scoped_openssl_types.h"
41 #include "net/cert/internal/signature_algorithm.h" 42 #include "net/cert/internal/signature_algorithm.h"
43 #include "net/cert/internal/signature_policy.h"
42 #include "net/der/input.h" 44 #include "net/der/input.h"
43 #include "net/der/parser.h" 45 #include "net/der/parser.h"
44 46
45 namespace net { 47 namespace net {
46 48
47 namespace { 49 namespace {
48 50
49 // Converts a DigestAlgorithm to an equivalent EVP_MD*. 51 // Converts a DigestAlgorithm to an equivalent EVP_MD*.
50 WARN_UNUSED_RESULT bool GetDigest(DigestAlgorithm digest, const EVP_MD** out) { 52 WARN_UNUSED_RESULT bool GetDigest(DigestAlgorithm digest, const EVP_MD** out) {
51 *out = nullptr; 53 *out = nullptr;
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 // COMPATIBILITY NOTE: RFC 5912 and RFC 3279 are in disagreement on the value 156 // COMPATIBILITY NOTE: RFC 5912 and RFC 3279 are in disagreement on the value
155 // of parameters for rsaEncryption. Whereas RFC 5912 says they must be absent, 157 // of parameters for rsaEncryption. Whereas RFC 5912 says they must be absent,
156 // RFC 3279 says they must be NULL: 158 // RFC 3279 says they must be NULL:
157 // 159 //
158 // The rsaEncryption OID is intended to be used in the algorithm field 160 // The rsaEncryption OID is intended to be used in the algorithm field
159 // of a value of type AlgorithmIdentifier. The parameters field MUST 161 // of a value of type AlgorithmIdentifier. The parameters field MUST
160 // have ASN.1 type NULL for this algorithm identifier. 162 // have ASN.1 type NULL for this algorithm identifier.
161 // 163 //
162 // Following RFC 3279 in this case. 164 // Following RFC 3279 in this case.
163 WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki, 165 WARN_UNUSED_RESULT bool ParseRsaKeyFromSpki(const der::Input& public_key_spki,
164 crypto::ScopedEVP_PKEY* pkey) { 166 crypto::ScopedEVP_PKEY* pkey,
165 return ImportPkeyFromSpki(public_key_spki, EVP_PKEY_RSA, pkey); 167 const SignaturePolicy* policy) {
168 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_RSA, pkey))
169 return false;
170
171 // Extract the modulus length from the key.
172 crypto::ScopedRSA rsa(EVP_PKEY_get1_RSA(pkey->get()));
173 if (!rsa)
174 return false;
175 unsigned int modulus_length_bits = BN_num_bits(rsa->n);
176
177 return policy->IsAcceptableModulusLengthForRsa(modulus_length_bits);
166 } 178 }
167 179
168 // Does signature verification using either RSA or ECDSA. 180 // Does signature verification using either RSA or ECDSA.
169 WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm, 181 WARN_UNUSED_RESULT bool DoVerify(const SignatureAlgorithm& algorithm,
170 const der::Input& signed_data, 182 const der::Input& signed_data,
171 const der::BitString& signature_value, 183 const der::BitString& signature_value,
172 EVP_PKEY* public_key) { 184 EVP_PKEY* public_key) {
173 DCHECK(algorithm.algorithm() == SignatureAlgorithmId::RsaPkcs1 || 185 DCHECK(algorithm.algorithm() == SignatureAlgorithmId::RsaPkcs1 ||
174 algorithm.algorithm() == SignatureAlgorithmId::RsaPss || 186 algorithm.algorithm() == SignatureAlgorithmId::RsaPss ||
175 algorithm.algorithm() == SignatureAlgorithmId::Ecdsa); 187 algorithm.algorithm() == SignatureAlgorithmId::Ecdsa);
(...skipping 25 matching lines...) Expand all
201 if (!EVP_DigestVerifyUpdate(ctx.get(), signed_data.UnsafeData(), 213 if (!EVP_DigestVerifyUpdate(ctx.get(), signed_data.UnsafeData(),
202 signed_data.Length())) { 214 signed_data.Length())) {
203 return false; 215 return false;
204 } 216 }
205 217
206 return 1 == EVP_DigestVerifyFinal(ctx.get(), 218 return 1 == EVP_DigestVerifyFinal(ctx.get(),
207 signature_value_bytes.UnsafeData(), 219 signature_value_bytes.UnsafeData(),
208 signature_value_bytes.Length()); 220 signature_value_bytes.Length());
209 } 221 }
210 222
211 // Returns true if the given curve is allowed for ECDSA. The input is a
212 // BoringSSL NID.
213 //
214 // TODO(eroman): Extract policy decisions such as allowed curves, hashes, RSA
215 // modulus size, to somewhere more central.
216 WARN_UNUSED_RESULT bool IsAllowedCurveName(int curve_nid) {
217 switch (curve_nid) {
218 case NID_X9_62_prime256v1:
219 case NID_secp384r1:
220 case NID_secp521r1:
221 return true;
222 }
223 return false;
224 }
225
226 // Parses an EC public key from SPKI to an EVP_PKEY. 223 // Parses an EC public key from SPKI to an EVP_PKEY.
227 // 224 //
228 // Returns true on success. 225 // Returns true on success.
229 // 226 //
230 // RFC 5912 describes all the ECDSA signature algorithms as requiring a public 227 // RFC 5912 describes all the ECDSA signature algorithms as requiring a public
231 // key of type "pk-ec": 228 // key of type "pk-ec":
232 // 229 //
233 // pk-ec PUBLIC-KEY ::= { 230 // pk-ec PUBLIC-KEY ::= {
234 // IDENTIFIER id-ecPublicKey 231 // IDENTIFIER id-ecPublicKey
235 // KEY ECPoint 232 // KEY ECPoint
(...skipping 25 matching lines...) Expand all
261 // 258 //
262 // NamedCurve CURVE ::= { 259 // NamedCurve CURVE ::= {
263 // { ID secp192r1 } | { ID sect163k1 } | { ID sect163r2 } | 260 // { ID secp192r1 } | { ID sect163k1 } | { ID sect163r2 } |
264 // { ID secp224r1 } | { ID sect233k1 } | { ID sect233r1 } | 261 // { ID secp224r1 } | { ID sect233k1 } | { ID sect233r1 } |
265 // { ID secp256r1 } | { ID sect283k1 } | { ID sect283r1 } | 262 // { ID secp256r1 } | { ID sect283k1 } | { ID sect283r1 } |
266 // { ID secp384r1 } | { ID sect409k1 } | { ID sect409r1 } | 263 // { ID secp384r1 } | { ID sect409k1 } | { ID sect409r1 } |
267 // { ID secp521r1 } | { ID sect571k1 } | { ID sect571r1 }, 264 // { ID secp521r1 } | { ID sect571k1 } | { ID sect571r1 },
268 // ... -- Extensible 265 // ... -- Extensible
269 // } 266 // }
270 WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki, 267 WARN_UNUSED_RESULT bool ParseEcKeyFromSpki(const der::Input& public_key_spki,
271 crypto::ScopedEVP_PKEY* pkey) { 268 crypto::ScopedEVP_PKEY* pkey,
269 const SignaturePolicy* policy) {
272 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_EC, pkey)) 270 if (!ImportPkeyFromSpki(public_key_spki, EVP_PKEY_EC, pkey))
273 return false; 271 return false;
274 272
275 // Enforce policy on allowed curves in case ImportPkeyFromSpki() were to 273 // Extract the curve name.
276 // recognize and allow use of a weak curve.
277 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey->get())); 274 crypto::ScopedEC_KEY ec(EVP_PKEY_get1_EC_KEY(pkey->get()));
278 if (!ec.get()) 275 if (!ec.get())
279 return false; // Unexpected. 276 return false; // Unexpected.
277 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get()));
280 278
281 int curve_nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec.get())); 279 return policy->IsAcceptableCurveForEcdsa(curve_nid);
282 return IsAllowedCurveName(curve_nid);
283 } 280 }
284 281
285 } // namespace 282 } // namespace
286 283
287 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm, 284 bool VerifySignedData(const SignatureAlgorithm& signature_algorithm,
288 const der::Input& signed_data, 285 const der::Input& signed_data,
289 const der::BitString& signature_value, 286 const der::BitString& signature_value,
290 const der::Input& public_key_spki) { 287 const der::Input& public_key_spki,
288 const SignaturePolicy* policy) {
289 if (!policy->IsAcceptableSignatureAlgorithm(signature_algorithm))
290 return false;
291
291 crypto::ScopedEVP_PKEY public_key; 292 crypto::ScopedEVP_PKEY public_key;
292 293
293 // Parse the SPKI to an EVP_PKEY appropriate for the signature algorithm. 294 // Parse the SPKI to an EVP_PKEY appropriate for the signature algorithm.
294 switch (signature_algorithm.algorithm()) { 295 switch (signature_algorithm.algorithm()) {
295 case SignatureAlgorithmId::RsaPkcs1: 296 case SignatureAlgorithmId::RsaPkcs1:
296 case SignatureAlgorithmId::RsaPss: 297 case SignatureAlgorithmId::RsaPss:
297 if (!ParseRsaKeyFromSpki(public_key_spki, &public_key)) 298 if (!ParseRsaKeyFromSpki(public_key_spki, &public_key, policy))
298 return false; 299 return false;
299 break; 300 break;
300 case SignatureAlgorithmId::Ecdsa: 301 case SignatureAlgorithmId::Ecdsa:
301 if (!ParseEcKeyFromSpki(public_key_spki, &public_key)) 302 if (!ParseEcKeyFromSpki(public_key_spki, &public_key, policy))
302 return false; 303 return false;
303 break; 304 break;
304 } 305 }
305 306
306 return DoVerify(signature_algorithm, signed_data, signature_value, 307 return DoVerify(signature_algorithm, signed_data, signature_value,
307 public_key.get()); 308 public_key.get());
308 } 309 }
309 310
310 } // namespace net 311 } // namespace net
311 312
312 #endif 313 #endif
OLDNEW
« no previous file with comments | « net/cert/internal/verify_signed_data.h ('k') | net/cert/internal/verify_signed_data_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698