| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include <cryptohi.h> | |
| 6 #include <keyhi.h> | |
| 7 #include <pk11pub.h> | |
| 8 #include <secerr.h> | |
| 9 #include <sechash.h> | |
| 10 | |
| 11 #include "base/stl_util.h" | |
| 12 #include "content/child/webcrypto/crypto_data.h" | |
| 13 #include "content/child/webcrypto/nss/key_nss.h" | |
| 14 #include "content/child/webcrypto/nss/rsa_hashed_algorithm_nss.h" | |
| 15 #include "content/child/webcrypto/nss/util_nss.h" | |
| 16 #include "content/child/webcrypto/status.h" | |
| 17 #include "content/child/webcrypto/webcrypto_util.h" | |
| 18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h" | |
| 19 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h" | |
| 20 | |
| 21 namespace content { | |
| 22 | |
| 23 namespace webcrypto { | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 Status NssSupportsRsaOaep() { | |
| 28 if (NssRuntimeSupport::Get()->IsRsaOaepSupported()) | |
| 29 return Status::Success(); | |
| 30 return Status::ErrorUnsupported( | |
| 31 "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or " | |
| 32 "later"); | |
| 33 } | |
| 34 | |
| 35 CK_MECHANISM_TYPE WebCryptoHashToMGFMechanism( | |
| 36 const blink::WebCryptoAlgorithm& algorithm) { | |
| 37 switch (algorithm.id()) { | |
| 38 case blink::WebCryptoAlgorithmIdSha1: | |
| 39 return CKG_MGF1_SHA1; | |
| 40 case blink::WebCryptoAlgorithmIdSha256: | |
| 41 return CKG_MGF1_SHA256; | |
| 42 case blink::WebCryptoAlgorithmIdSha384: | |
| 43 return CKG_MGF1_SHA384; | |
| 44 case blink::WebCryptoAlgorithmIdSha512: | |
| 45 return CKG_MGF1_SHA512; | |
| 46 default: | |
| 47 return CKM_INVALID_MECHANISM; | |
| 48 } | |
| 49 } | |
| 50 | |
| 51 CK_MECHANISM_TYPE WebCryptoHashToDigestMechanism( | |
| 52 const blink::WebCryptoAlgorithm& algorithm) { | |
| 53 switch (algorithm.id()) { | |
| 54 case blink::WebCryptoAlgorithmIdSha1: | |
| 55 return CKM_SHA_1; | |
| 56 case blink::WebCryptoAlgorithmIdSha256: | |
| 57 return CKM_SHA256; | |
| 58 case blink::WebCryptoAlgorithmIdSha384: | |
| 59 return CKM_SHA384; | |
| 60 case blink::WebCryptoAlgorithmIdSha512: | |
| 61 return CKM_SHA512; | |
| 62 default: | |
| 63 // Not a supported algorithm. | |
| 64 return CKM_INVALID_MECHANISM; | |
| 65 } | |
| 66 } | |
| 67 | |
| 68 bool InitializeRsaOaepParams(const blink::WebCryptoAlgorithm& hash, | |
| 69 const CryptoData& label, | |
| 70 CK_RSA_PKCS_OAEP_PARAMS* oaep_params) { | |
| 71 oaep_params->source = CKZ_DATA_SPECIFIED; | |
| 72 oaep_params->pSourceData = const_cast<unsigned char*>(label.bytes()); | |
| 73 oaep_params->ulSourceDataLen = label.byte_length(); | |
| 74 oaep_params->mgf = WebCryptoHashToMGFMechanism(hash); | |
| 75 oaep_params->hashAlg = WebCryptoHashToDigestMechanism(hash); | |
| 76 | |
| 77 if (oaep_params->mgf == CKM_INVALID_MECHANISM || | |
| 78 oaep_params->hashAlg == CKM_INVALID_MECHANISM) { | |
| 79 return false; | |
| 80 } | |
| 81 | |
| 82 return true; | |
| 83 } | |
| 84 | |
| 85 Status EncryptRsaOaep(SECKEYPublicKey* key, | |
| 86 const blink::WebCryptoAlgorithm& hash, | |
| 87 const CryptoData& label, | |
| 88 const CryptoData& data, | |
| 89 std::vector<uint8_t>* buffer) { | |
| 90 CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0}; | |
| 91 if (!InitializeRsaOaepParams(hash, label, &oaep_params)) | |
| 92 return Status::ErrorUnsupported(); | |
| 93 | |
| 94 SECItem param; | |
| 95 param.type = siBuffer; | |
| 96 param.data = reinterpret_cast<unsigned char*>(&oaep_params); | |
| 97 param.len = sizeof(oaep_params); | |
| 98 | |
| 99 buffer->resize(SECKEY_PublicKeyStrength(key)); | |
| 100 unsigned char* buffer_data = vector_as_array(buffer); | |
| 101 unsigned int output_len; | |
| 102 if (NssRuntimeSupport::Get()->pk11_pub_encrypt_func()( | |
| 103 key, CKM_RSA_PKCS_OAEP, ¶m, buffer_data, &output_len, | |
| 104 buffer->size(), data.bytes(), data.byte_length(), | |
| 105 NULL) != SECSuccess) { | |
| 106 return Status::OperationError(); | |
| 107 } | |
| 108 | |
| 109 CHECK_LE(output_len, buffer->size()); | |
| 110 buffer->resize(output_len); | |
| 111 return Status::Success(); | |
| 112 } | |
| 113 | |
| 114 Status DecryptRsaOaep(SECKEYPrivateKey* key, | |
| 115 const blink::WebCryptoAlgorithm& hash, | |
| 116 const CryptoData& label, | |
| 117 const CryptoData& data, | |
| 118 std::vector<uint8_t>* buffer) { | |
| 119 Status status = NssSupportsRsaOaep(); | |
| 120 if (status.IsError()) | |
| 121 return status; | |
| 122 | |
| 123 CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0}; | |
| 124 if (!InitializeRsaOaepParams(hash, label, &oaep_params)) | |
| 125 return Status::ErrorUnsupported(); | |
| 126 | |
| 127 SECItem param; | |
| 128 param.type = siBuffer; | |
| 129 param.data = reinterpret_cast<unsigned char*>(&oaep_params); | |
| 130 param.len = sizeof(oaep_params); | |
| 131 | |
| 132 const int modulus_length_bytes = PK11_GetPrivateModulusLen(key); | |
| 133 if (modulus_length_bytes <= 0) | |
| 134 return Status::ErrorUnexpected(); | |
| 135 | |
| 136 buffer->resize(modulus_length_bytes); | |
| 137 | |
| 138 unsigned char* buffer_data = vector_as_array(buffer); | |
| 139 unsigned int output_len; | |
| 140 if (NssRuntimeSupport::Get()->pk11_priv_decrypt_func()( | |
| 141 key, CKM_RSA_PKCS_OAEP, ¶m, buffer_data, &output_len, | |
| 142 buffer->size(), data.bytes(), data.byte_length()) != SECSuccess) { | |
| 143 return Status::OperationError(); | |
| 144 } | |
| 145 | |
| 146 CHECK_LE(output_len, buffer->size()); | |
| 147 buffer->resize(output_len); | |
| 148 return Status::Success(); | |
| 149 } | |
| 150 | |
| 151 class RsaOaepImplementation : public RsaHashedAlgorithm { | |
| 152 public: | |
| 153 RsaOaepImplementation() | |
| 154 : RsaHashedAlgorithm( | |
| 155 CKF_ENCRYPT | CKF_DECRYPT | CKF_WRAP | CKF_UNWRAP, | |
| 156 blink::WebCryptoKeyUsageEncrypt | blink::WebCryptoKeyUsageWrapKey, | |
| 157 blink::WebCryptoKeyUsageDecrypt | | |
| 158 blink::WebCryptoKeyUsageUnwrapKey) {} | |
| 159 | |
| 160 Status GenerateKey(const blink::WebCryptoAlgorithm& algorithm, | |
| 161 bool extractable, | |
| 162 blink::WebCryptoKeyUsageMask usages, | |
| 163 GenerateKeyResult* result) const override { | |
| 164 Status status = NssSupportsRsaOaep(); | |
| 165 if (status.IsError()) | |
| 166 return status; | |
| 167 return RsaHashedAlgorithm::GenerateKey(algorithm, extractable, usages, | |
| 168 result); | |
| 169 } | |
| 170 | |
| 171 Status VerifyKeyUsagesBeforeImportKey( | |
| 172 blink::WebCryptoKeyFormat format, | |
| 173 blink::WebCryptoKeyUsageMask usages) const override { | |
| 174 Status status = NssSupportsRsaOaep(); | |
| 175 if (status.IsError()) | |
| 176 return status; | |
| 177 return RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(format, usages); | |
| 178 } | |
| 179 | |
| 180 const char* GetJwkAlgorithm( | |
| 181 const blink::WebCryptoAlgorithmId hash) const override { | |
| 182 switch (hash) { | |
| 183 case blink::WebCryptoAlgorithmIdSha1: | |
| 184 return "RSA-OAEP"; | |
| 185 case blink::WebCryptoAlgorithmIdSha256: | |
| 186 return "RSA-OAEP-256"; | |
| 187 case blink::WebCryptoAlgorithmIdSha384: | |
| 188 return "RSA-OAEP-384"; | |
| 189 case blink::WebCryptoAlgorithmIdSha512: | |
| 190 return "RSA-OAEP-512"; | |
| 191 default: | |
| 192 return NULL; | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 Status Encrypt(const blink::WebCryptoAlgorithm& algorithm, | |
| 197 const blink::WebCryptoKey& key, | |
| 198 const CryptoData& data, | |
| 199 std::vector<uint8_t>* buffer) const override { | |
| 200 if (key.type() != blink::WebCryptoKeyTypePublic) | |
| 201 return Status::ErrorUnexpectedKeyType(); | |
| 202 | |
| 203 return EncryptRsaOaep( | |
| 204 PublicKeyNss::Cast(key)->key(), | |
| 205 key.algorithm().rsaHashedParams()->hash(), | |
| 206 CryptoData(algorithm.rsaOaepParams()->optionalLabel()), data, buffer); | |
| 207 } | |
| 208 | |
| 209 Status Decrypt(const blink::WebCryptoAlgorithm& algorithm, | |
| 210 const blink::WebCryptoKey& key, | |
| 211 const CryptoData& data, | |
| 212 std::vector<uint8_t>* buffer) const override { | |
| 213 if (key.type() != blink::WebCryptoKeyTypePrivate) | |
| 214 return Status::ErrorUnexpectedKeyType(); | |
| 215 | |
| 216 return DecryptRsaOaep( | |
| 217 PrivateKeyNss::Cast(key)->key(), | |
| 218 key.algorithm().rsaHashedParams()->hash(), | |
| 219 CryptoData(algorithm.rsaOaepParams()->optionalLabel()), data, buffer); | |
| 220 } | |
| 221 }; | |
| 222 | |
| 223 } // namespace | |
| 224 | |
| 225 AlgorithmImplementation* CreatePlatformRsaOaepImplementation() { | |
| 226 return new RsaOaepImplementation; | |
| 227 } | |
| 228 | |
| 229 } // namespace webcrypto | |
| 230 | |
| 231 } // namespace content | |
| OLD | NEW |