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 |