Allow only one bookmark to be added for multiple fast starring
[chromium-blink-merge.git] / components / webcrypto / nss / rsa_oaep_nss.cc
blobd66b6c3b4ff0ddca1ea4fd87a3f889c75da08c66
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.
5 #include <cryptohi.h>
6 #include <keyhi.h>
7 #include <pk11pub.h>
8 #include <secerr.h>
9 #include <sechash.h>
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"
21 namespace webcrypto {
23 namespace {
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 "
30 "later");
33 CK_MECHANISM_TYPE WebCryptoHashToMGFMechanism(
34 const blink::WebCryptoAlgorithm& algorithm) {
35 switch (algorithm.id()) {
36 case blink::WebCryptoAlgorithmIdSha1:
37 return CKG_MGF1_SHA1;
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;
44 default:
45 return CKM_INVALID_MECHANISM;
49 CK_MECHANISM_TYPE WebCryptoHashToDigestMechanism(
50 const blink::WebCryptoAlgorithm& algorithm) {
51 switch (algorithm.id()) {
52 case blink::WebCryptoAlgorithmIdSha1:
53 return CKM_SHA_1;
54 case blink::WebCryptoAlgorithmIdSha256:
55 return CKM_SHA256;
56 case blink::WebCryptoAlgorithmIdSha384:
57 return CKM_SHA384;
58 case blink::WebCryptoAlgorithmIdSha512:
59 return CKM_SHA512;
60 default:
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) {
77 return false;
80 return true;
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();
92 SECItem param;
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, &param, 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())
119 return status;
121 CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
122 if (!InitializeRsaOaepParams(hash, label, &oaep_params))
123 return Status::ErrorUnsupported();
125 SECItem param;
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, &param, 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 {
150 public:
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,
159 bool extractable,
160 blink::WebCryptoKeyUsageMask usages,
161 GenerateKeyResult* result) const override {
162 Status status = NssSupportsRsaOaep();
163 if (status.IsError())
164 return status;
165 return RsaHashedAlgorithm::GenerateKey(algorithm, extractable, usages,
166 result);
169 Status VerifyKeyUsagesBeforeImportKey(
170 blink::WebCryptoKeyFormat format,
171 blink::WebCryptoKeyUsageMask usages) const override {
172 Status status = NssSupportsRsaOaep();
173 if (status.IsError())
174 return status;
175 return RsaHashedAlgorithm::VerifyKeyUsagesBeforeImportKey(format, usages);
178 const char* GetJwkAlgorithm(
179 const blink::WebCryptoAlgorithmId hash) const override {
180 switch (hash) {
181 case blink::WebCryptoAlgorithmIdSha1:
182 return "RSA-OAEP";
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";
189 default:
190 return NULL;
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);
221 } // namespace
223 AlgorithmImplementation* CreatePlatformRsaOaepImplementation() {
224 return new RsaOaepImplementation;
227 } // namespace webcrypto