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.
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"
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 "
35 CK_MECHANISM_TYPE
WebCryptoHashToMGFMechanism(
36 const blink::WebCryptoAlgorithm
& algorithm
) {
37 switch (algorithm
.id()) {
38 case blink::WebCryptoAlgorithmIdSha1
:
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
;
47 return CKM_INVALID_MECHANISM
;
51 CK_MECHANISM_TYPE
WebCryptoHashToDigestMechanism(
52 const blink::WebCryptoAlgorithm
& algorithm
) {
53 switch (algorithm
.id()) {
54 case blink::WebCryptoAlgorithmIdSha1
:
56 case blink::WebCryptoAlgorithmIdSha256
:
58 case blink::WebCryptoAlgorithmIdSha384
:
60 case blink::WebCryptoAlgorithmIdSha512
:
63 // Not a supported algorithm.
64 return CKM_INVALID_MECHANISM
;
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
);
77 if (oaep_params
->mgf
== CKM_INVALID_MECHANISM
||
78 oaep_params
->hashAlg
== CKM_INVALID_MECHANISM
) {
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();
95 param
.type
= siBuffer
;
96 param
.data
= reinterpret_cast<unsigned char*>(&oaep_params
);
97 param
.len
= sizeof(oaep_params
);
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();
109 CHECK_LE(output_len
, buffer
->size());
110 buffer
->resize(output_len
);
111 return Status::Success();
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())
123 CK_RSA_PKCS_OAEP_PARAMS oaep_params
= {0};
124 if (!InitializeRsaOaepParams(hash
, label
, &oaep_params
))
125 return Status::ErrorUnsupported();
128 param
.type
= siBuffer
;
129 param
.data
= reinterpret_cast<unsigned char*>(&oaep_params
);
130 param
.len
= sizeof(oaep_params
);
132 const int modulus_length_bytes
= PK11_GetPrivateModulusLen(key
);
133 if (modulus_length_bytes
<= 0)
134 return Status::ErrorUnexpected();
136 buffer
->resize(modulus_length_bytes
);
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();
146 CHECK_LE(output_len
, buffer
->size());
147 buffer
->resize(output_len
);
148 return Status::Success();
151 class RsaOaepImplementation
: public RsaHashedAlgorithm
{
153 RsaOaepImplementation()
154 : RsaHashedAlgorithm(
155 CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
,
156 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageWrapKey
,
157 blink::WebCryptoKeyUsageDecrypt
|
158 blink::WebCryptoKeyUsageUnwrapKey
) {}
160 Status
GenerateKey(const blink::WebCryptoAlgorithm
& algorithm
,
162 blink::WebCryptoKeyUsageMask usages
,
163 GenerateKeyResult
* result
) const override
{
164 Status status
= NssSupportsRsaOaep();
165 if (status
.IsError())
167 return RsaHashedAlgorithm::GenerateKey(algorithm
, extractable
, usages
,
171 Status
VerifyKeyUsagesBeforeImportKey(
172 blink::WebCryptoKeyFormat format
,
173 blink::WebCryptoKeyUsageMask usages
) const override
{
174 Status status
= NssSupportsRsaOaep();
175 if (status
.IsError())
177 return RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(format
, usages
);
180 const char* GetJwkAlgorithm(
181 const blink::WebCryptoAlgorithmId hash
) const override
{
183 case blink::WebCryptoAlgorithmIdSha1
:
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";
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();
203 return EncryptRsaOaep(
204 PublicKeyNss::Cast(key
)->key(),
205 key
.algorithm().rsaHashedParams()->hash(),
206 CryptoData(algorithm
.rsaOaepParams()->optionalLabel()), data
, buffer
);
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();
216 return DecryptRsaOaep(
217 PrivateKeyNss::Cast(key
)->key(),
218 key
.algorithm().rsaHashedParams()->hash(),
219 CryptoData(algorithm
.rsaOaepParams()->optionalLabel()), data
, buffer
);
225 AlgorithmImplementation
* CreatePlatformRsaOaepImplementation() {
226 return new RsaOaepImplementation
;
229 } // namespace webcrypto
231 } // namespace content