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

Unified Diff: content/child/webcrypto/platform_crypto_nss.cc

Issue 275943004: Add support for RSA-OAEP when using NSS 3.16.2 or later (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 7 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 side-by-side diff with in-line comments
Download patch
Index: content/child/webcrypto/platform_crypto_nss.cc
diff --git a/content/child/webcrypto/platform_crypto_nss.cc b/content/child/webcrypto/platform_crypto_nss.cc
index eebd9e071b445b39baec6ae805a7f52d6456405e..f922c970fe20a0d9759a47228005267c45ae95fe 100644
--- a/content/child/webcrypto/platform_crypto_nss.cc
+++ b/content/child/webcrypto/platform_crypto_nss.cc
@@ -60,6 +60,8 @@ struct CK_GCM_PARAMS {
};
#endif // !defined(CKM_AES_GCM)
+namespace {
+
// Signature for PK11_Encrypt and PK11_Decrypt.
typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*,
CK_MECHANISM_TYPE,
@@ -70,10 +72,36 @@ typedef SECStatus (*PK11_EncryptDecryptFunction)(PK11SymKey*,
const unsigned char*,
unsigned int);
+// Signature for PK11_PubEncrypt
+typedef SECStatus (*PK11_PubEncryptFunction)(SECKEYPublicKey*,
+ CK_MECHANISM_TYPE,
+ SECItem*,
+ unsigned char*,
+ unsigned int*,
+ unsigned int,
+ const unsigned char*,
+ unsigned int);
+
+// Signature for PK11_PubDecrypt
+typedef SECStatus (*PK11_PubDecryptFunction)(SECKEYPrivateKey*,
+ CK_MECHANISM_TYPE,
+ SECItem*,
+ unsigned char*,
+ unsigned int*,
+ unsigned int,
+ const unsigned char*,
+ unsigned int);
+
// Singleton to abstract away dynamically loading libnss3.so
-class AesGcmSupport {
+class NssRuntimeSupport {
public:
- bool IsSupported() const { return pk11_encrypt_func_ && pk11_decrypt_func_; }
+ bool IsAesGcmSupported() const {
+ return pk11_encrypt_func_ && pk11_decrypt_func_;
+ }
+
+ bool IsRsaOaepSupported() const {
+ return pk11_pub_encrypt_func_ && pk11_pub_decrypt_func_;
+ }
Ryan Sleevi 2014/05/14 01:26:00 Note: For both the AES-GCM case and the RSA-OAEP,
// Returns NULL if unsupported.
PK11_EncryptDecryptFunction pk11_encrypt_func() const {
@@ -85,14 +113,26 @@ class AesGcmSupport {
return pk11_decrypt_func_;
}
+ // Returns NULL if unsupported.
+ PK11_PubEncryptFunction pk11_pub_encrypt_func() const {
+ return pk11_pub_encrypt_func_;
+ }
+
+ // Returns NULL if unsupported.
+ PK11_PubDecryptFunction pk11_pub_decrypt_func() const {
+ return pk11_pub_decrypt_func_;
+ }
+
private:
- friend struct base::DefaultLazyInstanceTraits<AesGcmSupport>;
+ friend struct base::DefaultLazyInstanceTraits<NssRuntimeSupport>;
- AesGcmSupport() {
+ NssRuntimeSupport() {
#if !defined(USE_NSS)
// Using a bundled version of NSS that is guaranteed to have this symbol.
pk11_encrypt_func_ = PK11_Encrypt;
pk11_decrypt_func_ = PK11_Decrypt;
+ pk11_pub_encrypt_func_ = PK11_PubEncrypt;
+ pk11_pub_decrypt_func_ = PK11_PubDecrypt;
#else
// Using system NSS libraries and PCKS #11 modules, which may not have the
// necessary function (PK11_Encrypt) or mechanism support (CKM_AES_GCM).
@@ -103,16 +143,24 @@ class AesGcmSupport {
dlsym(RTLD_DEFAULT, "PK11_Encrypt"));
pk11_decrypt_func_ = reinterpret_cast<PK11_EncryptDecryptFunction>(
dlsym(RTLD_DEFAULT, "PK11_Decrypt"));
+ pk11_pub_encrypt_func_ = reinterpret_cast<PK11_PubEncryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_PubEncrypt"));
+ pk11_pub_decrypt_func_ = reinterpret_cast<PK11_PubDecryptFunction>(
+ dlsym(RTLD_DEFAULT, "PK11_PubDecrypt"));
#endif
}
PK11_EncryptDecryptFunction pk11_encrypt_func_;
PK11_EncryptDecryptFunction pk11_decrypt_func_;
+ PK11_PubEncryptFunction pk11_pub_encrypt_func_;
+ PK11_PubDecryptFunction pk11_pub_decrypt_func_;
};
-base::LazyInstance<AesGcmSupport>::Leaky g_aes_gcm_support =
+base::LazyInstance<NssRuntimeSupport>::Leaky g_nss_runtime_support =
LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
namespace content {
namespace webcrypto {
@@ -260,6 +308,49 @@ CK_MECHANISM_TYPE WebCryptoHashToHMACMechanism(
}
}
+CK_MECHANISM_TYPE WebCryptoHashToDigestMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKM_SHA_1;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKM_SHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return CKM_SHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return CKM_SHA512;
+ default:
+ // Not a supported algorithm.
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+CK_MECHANISM_TYPE WebCryptoHashToMGFMechanism(
+ const blink::WebCryptoAlgorithm& algorithm) {
+ switch (algorithm.id()) {
+ case blink::WebCryptoAlgorithmIdSha1:
+ return CKG_MGF1_SHA1;
+ case blink::WebCryptoAlgorithmIdSha256:
+ return CKG_MGF1_SHA256;
+ case blink::WebCryptoAlgorithmIdSha384:
+ return CKG_MGF1_SHA384;
+ case blink::WebCryptoAlgorithmIdSha512:
+ return CKG_MGF1_SHA512;
+ default:
+ return CKM_INVALID_MECHANISM;
+ }
+}
+
+void InitializeRsaOaepParams(const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ CK_RSA_PKCS_OAEP_PARAMS* oaep_params) {
+ oaep_params->source = CKZ_DATA_SPECIFIED;
+ oaep_params->pSourceData = const_cast<unsigned char*>(label.bytes());
+ oaep_params->ulSourceDataLen = label.byte_length();
+ oaep_params->mgf = WebCryptoHashToMGFMechanism(hash);
eroman 2014/05/14 01:50:47 What is the consequence of failure for WebCryptoHa
Ryan Sleevi 2014/05/14 06:09:57 Officially: "It depends". Practically: No PKCS#11
+ oaep_params->hashAlg = WebCryptoHashToDigestMechanism(hash);
eroman 2014/05/14 01:50:47 Same question above, for the sake of future proofi
+}
+
Status AesCbcEncryptDecrypt(EncryptOrDecrypt mode,
SymKey* key,
const CryptoData& iv,
@@ -337,7 +428,7 @@ Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
const CryptoData& additional_data,
unsigned int tag_length_bits,
std::vector<uint8>* buffer) {
- if (!g_aes_gcm_support.Get().IsSupported())
+ if (!g_nss_runtime_support.Get().IsAesGcmSupported())
return Status::ErrorUnsupported();
unsigned int tag_length_bytes = tag_length_bits / 8;
@@ -383,8 +474,8 @@ Status AesGcmEncryptDecrypt(EncryptOrDecrypt mode,
unsigned char* buffer_data = Uint8VectorStart(buffer);
PK11_EncryptDecryptFunction func =
- (mode == ENCRYPT) ? g_aes_gcm_support.Get().pk11_encrypt_func()
- : g_aes_gcm_support.Get().pk11_decrypt_func();
+ (mode == ENCRYPT) ? g_nss_runtime_support.Get().pk11_encrypt_func()
+ : g_nss_runtime_support.Get().pk11_decrypt_func();
unsigned int output_len = 0;
SECStatus result = func(key->key(),
@@ -522,7 +613,7 @@ Status WebCryptoAlgorithmToNssMechFlags(
break;
}
case blink::WebCryptoAlgorithmIdAesGcm: {
- if (!g_aes_gcm_support.Get().IsSupported())
+ if (!g_nss_runtime_support.Get().IsAesGcmSupported())
return Status::ErrorUnsupported();
*mechanism = CKM_AES_GCM;
*flags = CKF_ENCRYPT | CKF_DECRYPT;
@@ -1176,6 +1267,86 @@ Status DecryptRsaEsPkcs1v1_5(PrivateKey* key,
}
// -----------------------------------
+// RsaOaep
+// -----------------------------------
+Status EncryptRsaOaep(PublicKey* key,
eroman 2014/05/14 01:50:47 nit: for consistency add a new line after --------
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) {
+ if (!g_nss_runtime_support.Get().IsRsaOaepSupported())
+ return Status::ErrorUnsupported();
+
+ CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
+ InitializeRsaOaepParams(hash, label, &oaep_params);
+
padolph 2014/05/14 02:00:03 Do we need to check the length of the input |data|
+ SECItem param;
+ param.type = siBuffer;
+ param.data = reinterpret_cast<unsigned char*>(&oaep_params);
+ param.len = sizeof(oaep_params);
+
+ buffer->resize(SECKEY_PublicKeyStrength(key->key()));
+ unsigned char* buffer_data = Uint8VectorStart(buffer);
+ unsigned int output_len;
+ if (g_nss_runtime_support.Get().pk11_pub_encrypt_func()(
+ key->key(),
+ CKM_RSA_PKCS_OAEP,
+ &param,
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length() != SECSuccess)) {
+ return Status::OperationError();
+ }
+
+ DCHECK_LE(output_len, buffer->size());
+ buffer->resize(output_len);
+ return Status::Success();
+}
+
+Status DecryptRsaOaep(PrivateKey* key,
+ const blink::WebCryptoAlgorithm& hash,
+ const CryptoData& label,
+ const CryptoData& data,
+ std::vector<uint8>* buffer) {
+ if (!g_nss_runtime_support.Get().IsRsaOaepSupported())
eroman 2014/05/14 01:50:47 We might consider failing with ErrorUnsupported du
Ryan Sleevi 2014/05/14 02:34:30 Good point.
+ return Status::ErrorUnsupported();
+
+ CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
+ InitializeRsaOaepParams(hash, label, &oaep_params);
+
+ SECItem param;
+ param.type = siBuffer;
+ param.data = reinterpret_cast<unsigned char*>(&oaep_params);
+ param.len = sizeof(oaep_params);
+
+ const int modulus_length_bytes = PK11_GetPrivateModulusLen(key->key());
+ if (modulus_length_bytes <= 0)
+ return Status::ErrorUnexpected();
+
+ buffer->resize(modulus_length_bytes);
+
+ unsigned char* buffer_data = Uint8VectorStart(buffer);
+ unsigned int output_len;
+ if (g_nss_runtime_support.Get().pk11_pub_decrypt_func()(
+ key->key(),
+ CKM_RSA_PKCS_OAEP,
+ &param,
+ buffer_data,
+ &output_len,
+ buffer->size(),
+ data.bytes(),
+ data.byte_length() != SECSuccess)) {
+ return Status::OperationError();
+ }
+
+ DCHECK_LE(output_len, buffer->size());
+ buffer->resize(output_len);
+ return Status::Success();
+}
+
+// -----------------------------------
// RsaSsaPkcs1v1_5
// -----------------------------------

Powered by Google App Engine
This is Rietveld 408576698