Re-subimission of https://codereview.chromium.org/1041213003/
[chromium-blink-merge.git] / content / child / webcrypto / nss / rsa_oaep_nss.cc
blobcd181563fff5aa97f7a6deb7a99f01ea650be674
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 "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"
21 namespace content {
23 namespace webcrypto {
25 namespace {
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");
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;
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;
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) {
79 return false;
82 return true;
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();
94 SECItem param;
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, &param, 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())
121 return status;
123 CK_RSA_PKCS_OAEP_PARAMS oaep_params = {0};
124 if (!InitializeRsaOaepParams(hash, label, &oaep_params))
125 return Status::ErrorUnsupported();
127 SECItem param;
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, &param, 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 {
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) {}
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);
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);
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;
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);
223 } // namespace
225 AlgorithmImplementation* CreatePlatformRsaOaepImplementation() {
226 return new RsaOaepImplementation;
229 } // namespace webcrypto
231 } // namespace content