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

Side by Side Diff: content/child/webcrypto/openssl/rsa_sign_openssl.cc

Issue 661653002: [webcrypto] Implement RSA-PSS using BoringSSL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@refactor_rsassa
Patch Set: Add some tests from fips 186-2, covering sha-{256, 384, 512} Created 6 years, 2 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 "base/numerics/safe_math.h"
5 #include "content/child/webcrypto/crypto_data.h" 6 #include "content/child/webcrypto/crypto_data.h"
6 #include "content/child/webcrypto/openssl/key_openssl.h" 7 #include "content/child/webcrypto/openssl/key_openssl.h"
7 #include "content/child/webcrypto/openssl/rsa_key_openssl.h" 8 #include "content/child/webcrypto/openssl/rsa_key_openssl.h"
8 #include "content/child/webcrypto/openssl/rsa_sign_openssl.h" 9 #include "content/child/webcrypto/openssl/rsa_sign_openssl.h"
9 #include "content/child/webcrypto/openssl/util_openssl.h" 10 #include "content/child/webcrypto/openssl/util_openssl.h"
10 #include "content/child/webcrypto/status.h" 11 #include "content/child/webcrypto/status.h"
11 #include "crypto/openssl_util.h" 12 #include "crypto/openssl_util.h"
12 #include "crypto/scoped_openssl_types.h" 13 #include "crypto/scoped_openssl_types.h"
13 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" 14 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
14 15
(...skipping 10 matching lines...) Expand all
25 const EVP_MD** digest) { 26 const EVP_MD** digest) {
26 *pkey = AsymKeyOpenSsl::Cast(key)->key(); 27 *pkey = AsymKeyOpenSsl::Cast(key)->key();
27 28
28 *digest = GetDigest(key.algorithm().rsaHashedParams()->hash().id()); 29 *digest = GetDigest(key.algorithm().rsaHashedParams()->hash().id());
29 if (!*digest) 30 if (!*digest)
30 return Status::ErrorUnsupported(); 31 return Status::ErrorUnsupported();
31 32
32 return Status::Success(); 33 return Status::Success();
33 } 34 }
34 35
36 // Sets the PSS parameters on |pctx| if the key is for RSA-PSS.
37 //
38 // Otherwise returns Success without doing anything.
39 Status ApplyRsaPssOptions(const blink::WebCryptoKey& key,
40 const EVP_MD* const mgf_digest,
41 unsigned int salt_length_bytes,
42 EVP_PKEY_CTX* pctx) {
43 // Only apply RSA-PSS options if the key is for RSA-PSS.
44 if (key.algorithm().id() != blink::WebCryptoAlgorithmIdRsaPss) {
45 DCHECK_EQ(0u, salt_length_bytes);
46 DCHECK_EQ(blink::WebCryptoAlgorithmIdRsaSsaPkcs1v1_5, key.algorithm().id());
47 return Status::Success();
48 }
49
50 // BoringSSL takes a signed int for the salt length, and interprets
51 // negative values in a special manner. Make sure not to silently underflow.
52 base::CheckedNumeric<int> salt_length_bytes_int(salt_length_bytes);
53 if (!salt_length_bytes_int.IsValid()) {
54 // TODO(eroman): Give a better error message.
55 return Status::OperationError();
56 }
57
58 if (!EVP_PKEY_CTX_set_rsa_padding(pctx, RSA_PKCS1_PSS_PADDING) ||
59 !EVP_PKEY_CTX_set_rsa_mgf1_md(pctx, mgf_digest) ||
60 !EVP_PKEY_CTX_set_rsa_pss_saltlen(pctx,
61 salt_length_bytes_int.ValueOrDie())) {
davidben 2014/10/19 03:42:34 These should all be != 1 rather than !. The random
eroman 2014/10/20 18:44:53 Done. Thanks for spotting this!
62 return Status::OperationError();
63 }
64
65 return Status::Success();
66 }
67
35 } // namespace 68 } // namespace
36 69
37 Status RsaSign(const blink::WebCryptoKey& key, 70 Status RsaSign(const blink::WebCryptoKey& key,
71 unsigned int pss_salt_length_bytes,
38 const CryptoData& data, 72 const CryptoData& data,
39 std::vector<uint8_t>* buffer) { 73 std::vector<uint8_t>* buffer) {
40 if (key.type() != blink::WebCryptoKeyTypePrivate) 74 if (key.type() != blink::WebCryptoKeyTypePrivate)
41 return Status::ErrorUnexpectedKeyType(); 75 return Status::ErrorUnexpectedKeyType();
42 76
43 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 77 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
44 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); 78 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
79 EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
45 80
46 EVP_PKEY* private_key = NULL; 81 EVP_PKEY* private_key = NULL;
47 const EVP_MD* digest = NULL; 82 const EVP_MD* digest = NULL;
48 Status status = GetPKeyAndDigest(key, &private_key, &digest); 83 Status status = GetPKeyAndDigest(key, &private_key, &digest);
49 if (status.IsError()) 84 if (status.IsError())
50 return status; 85 return status;
51 86
52 // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter 87 // NOTE: A call to EVP_DigestSignFinal() with a NULL second parameter
53 // returns a maximum allocation size, while the call without a NULL returns 88 // returns a maximum allocation size, while the call without a NULL returns
54 // the real one, which may be smaller. 89 // the real one, which may be smaller.
55 size_t sig_len = 0; 90 size_t sig_len = 0;
56 if (!ctx.get() || 91 if (!ctx.get() ||
57 !EVP_DigestSignInit(ctx.get(), NULL, digest, NULL, private_key) || 92 !EVP_DigestSignInit(ctx.get(), &pctx, digest, NULL, private_key)) {
58 !EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) || 93 return Status::OperationError();
94 }
95
96 // Set PSS-specific options (if applicable).
97 status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
98 if (status.IsError())
99 return status;
100
101 if (!EVP_DigestSignUpdate(ctx.get(), data.bytes(), data.byte_length()) ||
59 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) { 102 !EVP_DigestSignFinal(ctx.get(), NULL, &sig_len)) {
60 return Status::OperationError(); 103 return Status::OperationError();
61 } 104 }
62 105
63 buffer->resize(sig_len); 106 buffer->resize(sig_len);
64 if (!EVP_DigestSignFinal(ctx.get(), &buffer->front(), &sig_len)) 107 if (!EVP_DigestSignFinal(ctx.get(), &buffer->front(), &sig_len))
65 return Status::OperationError(); 108 return Status::OperationError();
66 109
67 buffer->resize(sig_len); 110 buffer->resize(sig_len);
68 return Status::Success(); 111 return Status::Success();
69 } 112 }
70 113
71 Status RsaVerify(const blink::WebCryptoKey& key, 114 Status RsaVerify(const blink::WebCryptoKey& key,
115 unsigned int pss_salt_length_bytes,
72 const CryptoData& signature, 116 const CryptoData& signature,
73 const CryptoData& data, 117 const CryptoData& data,
74 bool* signature_match) { 118 bool* signature_match) {
75 if (key.type() != blink::WebCryptoKeyTypePublic) 119 if (key.type() != blink::WebCryptoKeyTypePublic)
76 return Status::ErrorUnexpectedKeyType(); 120 return Status::ErrorUnexpectedKeyType();
77 121
78 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE); 122 crypto::OpenSSLErrStackTracer err_tracer(FROM_HERE);
79 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create()); 123 crypto::ScopedEVP_MD_CTX ctx(EVP_MD_CTX_create());
124 EVP_PKEY_CTX* pctx = NULL; // Owned by |ctx|.
80 125
81 EVP_PKEY* public_key = NULL; 126 EVP_PKEY* public_key = NULL;
82 const EVP_MD* digest = NULL; 127 const EVP_MD* digest = NULL;
83 Status status = GetPKeyAndDigest(key, &public_key, &digest); 128 Status status = GetPKeyAndDigest(key, &public_key, &digest);
84 if (status.IsError()) 129 if (status.IsError())
85 return status; 130 return status;
86 131
87 if (!EVP_DigestVerifyInit(ctx.get(), NULL, digest, NULL, public_key)) 132 if (!EVP_DigestVerifyInit(ctx.get(), &pctx, digest, NULL, public_key))
88 return Status::OperationError(); 133 return Status::OperationError();
89 134
135 // Set PSS-specific options (if applicable).
136 status = ApplyRsaPssOptions(key, digest, pss_salt_length_bytes, pctx);
137 if (status.IsError())
138 return status;
139
90 if (!EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) { 140 if (!EVP_DigestVerifyUpdate(ctx.get(), data.bytes(), data.byte_length())) {
91 return Status::OperationError(); 141 return Status::OperationError();
92 } 142 }
93 143
94 // Note that the return value can be: 144 // Note that the return value can be:
95 // 1 --> Success 145 // 1 --> Success
96 // 0 --> Verification failed 146 // 0 --> Verification failed
97 // <0 --> Operation error 147 // <0 --> Operation error
98 int rv = EVP_DigestVerifyFinal( 148 int rv = EVP_DigestVerifyFinal(
99 ctx.get(), signature.bytes(), signature.byte_length()); 149 ctx.get(), signature.bytes(), signature.byte_length());
100 *signature_match = rv == 1; 150 *signature_match = rv == 1;
101 return rv >= 0 ? Status::Success() : Status::OperationError(); 151 return rv >= 0 ? Status::Success() : Status::OperationError();
102 } 152 }
103 153
104 } // namespace webcrypto 154 } // namespace webcrypto
105 155
106 } // namespace content 156 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698