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