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 DCHECK_LE(output_len, buffer->size()); | |
Ryan Sleevi
2014/07/17 00:06:54
CHECK?
eroman
2014/07/17 20:37:26
Done.
Thanks for reading through everything in de
| |
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 DCHECK_LE(output_len, buffer->size()); | |
Ryan Sleevi
2014/07/17 00:06:54
CHECK?
eroman
2014/07/17 20:37:26
Done.
| |
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 |