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 |