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 "components/webcrypto/crypto_data.h"
13 #include "components/webcrypto/nss/key_nss.h"
14 #include "components/webcrypto/nss/rsa_hashed_algorithm_nss.h"
15 #include "components/webcrypto/nss/util_nss.h"
16 #include "components/webcrypto/status.h"
17 #include "components/webcrypto/webcrypto_util.h"
18 #include "third_party/WebKit/public/platform/WebCryptoAlgorithmParams.h"
19 #include "third_party/WebKit/public/platform/WebCryptoKeyAlgorithm.h"
25 Status
NssSupportsRsaOaep() {
26 if (NssRuntimeSupport::Get()->IsRsaOaepSupported())
27 return Status::Success();
28 return Status::ErrorUnsupported(
29 "NSS version doesn't support RSA-OAEP. Try using version 3.16.2 or "
33 CK_MECHANISM_TYPE
WebCryptoHashToMGFMechanism(
34 const blink::WebCryptoAlgorithm
& algorithm
) {
35 switch (algorithm
.id()) {
36 case blink::WebCryptoAlgorithmIdSha1
:
38 case blink::WebCryptoAlgorithmIdSha256
:
39 return CKG_MGF1_SHA256
;
40 case blink::WebCryptoAlgorithmIdSha384
:
41 return CKG_MGF1_SHA384
;
42 case blink::WebCryptoAlgorithmIdSha512
:
43 return CKG_MGF1_SHA512
;
45 return CKM_INVALID_MECHANISM
;
49 CK_MECHANISM_TYPE
WebCryptoHashToDigestMechanism(
50 const blink::WebCryptoAlgorithm
& algorithm
) {
51 switch (algorithm
.id()) {
52 case blink::WebCryptoAlgorithmIdSha1
:
54 case blink::WebCryptoAlgorithmIdSha256
:
56 case blink::WebCryptoAlgorithmIdSha384
:
58 case blink::WebCryptoAlgorithmIdSha512
:
61 // Not a supported algorithm.
62 return CKM_INVALID_MECHANISM
;
66 bool InitializeRsaOaepParams(const blink::WebCryptoAlgorithm
& hash
,
67 const CryptoData
& label
,
68 CK_RSA_PKCS_OAEP_PARAMS
* oaep_params
) {
69 oaep_params
->source
= CKZ_DATA_SPECIFIED
;
70 oaep_params
->pSourceData
= const_cast<unsigned char*>(label
.bytes());
71 oaep_params
->ulSourceDataLen
= label
.byte_length();
72 oaep_params
->mgf
= WebCryptoHashToMGFMechanism(hash
);
73 oaep_params
->hashAlg
= WebCryptoHashToDigestMechanism(hash
);
75 if (oaep_params
->mgf
== CKM_INVALID_MECHANISM
||
76 oaep_params
->hashAlg
== CKM_INVALID_MECHANISM
) {
83 Status
EncryptRsaOaep(SECKEYPublicKey
* key
,
84 const blink::WebCryptoAlgorithm
& hash
,
85 const CryptoData
& label
,
86 const CryptoData
& data
,
87 std::vector
<uint8_t>* buffer
) {
88 CK_RSA_PKCS_OAEP_PARAMS oaep_params
= {0};
89 if (!InitializeRsaOaepParams(hash
, label
, &oaep_params
))
90 return Status::ErrorUnsupported();
93 param
.type
= siBuffer
;
94 param
.data
= reinterpret_cast<unsigned char*>(&oaep_params
);
95 param
.len
= sizeof(oaep_params
);
97 buffer
->resize(SECKEY_PublicKeyStrength(key
));
98 unsigned char* buffer_data
= vector_as_array(buffer
);
99 unsigned int output_len
;
100 if (NssRuntimeSupport::Get()->pk11_pub_encrypt_func()(
101 key
, CKM_RSA_PKCS_OAEP
, ¶m
, buffer_data
, &output_len
,
102 buffer
->size(), data
.bytes(), data
.byte_length(),
103 NULL
) != SECSuccess
) {
104 return Status::OperationError();
107 CHECK_LE(output_len
, buffer
->size());
108 buffer
->resize(output_len
);
109 return Status::Success();
112 Status
DecryptRsaOaep(SECKEYPrivateKey
* key
,
113 const blink::WebCryptoAlgorithm
& hash
,
114 const CryptoData
& label
,
115 const CryptoData
& data
,
116 std::vector
<uint8_t>* buffer
) {
117 Status status
= NssSupportsRsaOaep();
118 if (status
.IsError())
121 CK_RSA_PKCS_OAEP_PARAMS oaep_params
= {0};
122 if (!InitializeRsaOaepParams(hash
, label
, &oaep_params
))
123 return Status::ErrorUnsupported();
126 param
.type
= siBuffer
;
127 param
.data
= reinterpret_cast<unsigned char*>(&oaep_params
);
128 param
.len
= sizeof(oaep_params
);
130 const int modulus_length_bytes
= PK11_GetPrivateModulusLen(key
);
131 if (modulus_length_bytes
<= 0)
132 return Status::ErrorUnexpected();
134 buffer
->resize(modulus_length_bytes
);
136 unsigned char* buffer_data
= vector_as_array(buffer
);
137 unsigned int output_len
;
138 if (NssRuntimeSupport::Get()->pk11_priv_decrypt_func()(
139 key
, CKM_RSA_PKCS_OAEP
, ¶m
, buffer_data
, &output_len
,
140 buffer
->size(), data
.bytes(), data
.byte_length()) != SECSuccess
) {
141 return Status::OperationError();
144 CHECK_LE(output_len
, buffer
->size());
145 buffer
->resize(output_len
);
146 return Status::Success();
149 class RsaOaepImplementation
: public RsaHashedAlgorithm
{
151 RsaOaepImplementation()
152 : RsaHashedAlgorithm(
153 CKF_ENCRYPT
| CKF_DECRYPT
| CKF_WRAP
| CKF_UNWRAP
,
154 blink::WebCryptoKeyUsageEncrypt
| blink::WebCryptoKeyUsageWrapKey
,
155 blink::WebCryptoKeyUsageDecrypt
|
156 blink::WebCryptoKeyUsageUnwrapKey
) {}
158 Status
GenerateKey(const blink::WebCryptoAlgorithm
& algorithm
,
160 blink::WebCryptoKeyUsageMask usages
,
161 GenerateKeyResult
* result
) const override
{
162 Status status
= NssSupportsRsaOaep();
163 if (status
.IsError())
165 return RsaHashedAlgorithm::GenerateKey(algorithm
, extractable
, usages
,
169 Status
VerifyKeyUsagesBeforeImportKey(
170 blink::WebCryptoKeyFormat format
,
171 blink::WebCryptoKeyUsageMask usages
) const override
{
172 Status status
= NssSupportsRsaOaep();
173 if (status
.IsError())
175 return RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(format
, usages
);
178 const char* GetJwkAlgorithm(
179 const blink::WebCryptoAlgorithmId hash
) const override
{
181 case blink::WebCryptoAlgorithmIdSha1
:
183 case blink::WebCryptoAlgorithmIdSha256
:
184 return "RSA-OAEP-256";
185 case blink::WebCryptoAlgorithmIdSha384
:
186 return "RSA-OAEP-384";
187 case blink::WebCryptoAlgorithmIdSha512
:
188 return "RSA-OAEP-512";
194 Status
Encrypt(const blink::WebCryptoAlgorithm
& algorithm
,
195 const blink::WebCryptoKey
& key
,
196 const CryptoData
& data
,
197 std::vector
<uint8_t>* buffer
) const override
{
198 if (key
.type() != blink::WebCryptoKeyTypePublic
)
199 return Status::ErrorUnexpectedKeyType();
201 return EncryptRsaOaep(
202 PublicKeyNss::Cast(key
)->key(),
203 key
.algorithm().rsaHashedParams()->hash(),
204 CryptoData(algorithm
.rsaOaepParams()->optionalLabel()), data
, buffer
);
207 Status
Decrypt(const blink::WebCryptoAlgorithm
& algorithm
,
208 const blink::WebCryptoKey
& key
,
209 const CryptoData
& data
,
210 std::vector
<uint8_t>* buffer
) const override
{
211 if (key
.type() != blink::WebCryptoKeyTypePrivate
)
212 return Status::ErrorUnexpectedKeyType();
214 return DecryptRsaOaep(
215 PrivateKeyNss::Cast(key
)->key(),
216 key
.algorithm().rsaHashedParams()->hash(),
217 CryptoData(algorithm
.rsaOaepParams()->optionalLabel()), data
, buffer
);
223 AlgorithmImplementation
* CreatePlatformRsaOaepImplementation() {
224 return new RsaOaepImplementation
;
227 } // namespace webcrypto