1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #include "OSKeyStore.h"
9 #include "mozilla/Base64.h"
10 #include "mozilla/dom/Promise.h"
11 #include "nsThreadUtils.h"
15 #if defined(XP_MACOSX)
16 # include "KeychainSecret.h"
18 # include "CredentialManagerSecret.h"
19 #elif defined(MOZ_WIDGET_GTK)
20 # include "LibSecret.h"
21 # include "NSSKeyStore.h"
23 # include "NSSKeyStore.h"
26 NS_IMPL_ISUPPORTS(OSKeyStore
, nsIOSKeyStore
)
28 using namespace mozilla
;
31 OSKeyStore::OSKeyStore() : mKs(nullptr) {
32 MOZ_ASSERT(NS_IsMainThread());
33 if (NS_WARN_IF(!NS_IsMainThread())) {
37 #if defined(XP_MACOSX)
38 mKs
.reset(new KeychainSecret());
40 mKs
.reset(new CredentialManagerSecret());
41 #elif defined(MOZ_WIDGET_GTK)
42 if (NS_SUCCEEDED(MaybeLoadLibSecret())) {
43 mKs
.reset(new LibSecret());
45 mKs
.reset(new NSSKeyStore());
48 mKs
.reset(new NSSKeyStore());
51 (void)NS_CreateBackgroundTaskQueue(
52 "OSKeyStore", getter_AddRefs(mBackgroundSerialEventTarget
));
55 static nsresult
GenerateRandom(std::vector
<uint8_t>& r
) {
57 return NS_ERROR_INVALID_ARG
;
59 UniquePK11SlotInfo
slot(PK11_GetInternalSlot());
61 return NS_ERROR_FAILURE
;
64 SECStatus srv
= PK11_GenerateRandomOnSlot(slot
.get(), r
.data(), r
.size());
65 if (srv
!= SECSuccess
) {
67 return NS_ERROR_FAILURE
;
73 nsresult
OSKeyStore::SecretAvailable(const nsACString
& aLabel
,
74 /* out */ bool* aAvailable
) {
76 *aAvailable
= mKs
->SecretAvailable(aLabel
);
80 nsresult
OSKeyStore::GenerateSecret(const nsACString
& aLabel
,
81 /* out */ nsACString
& aRecoveryPhrase
) {
83 size_t keyByteLength
= mKs
->GetKeyByteLength();
84 std::vector
<uint8_t> secret(keyByteLength
);
85 nsresult rv
= GenerateRandom(secret
);
86 if (NS_FAILED(rv
) || secret
.size() != keyByteLength
) {
87 return NS_ERROR_FAILURE
;
89 nsAutoCString secretString
;
90 secretString
.Assign(BitwiseCast
<char*, uint8_t*>(secret
.data()),
94 rv
= Base64Encode(secretString
, base64
);
99 rv
= mKs
->StoreSecret(secretString
, aLabel
);
104 aRecoveryPhrase
= std::move(base64
);
108 nsresult
OSKeyStore::RecoverSecret(const nsACString
& aLabel
,
109 const nsACString
& aRecoveryPhrase
) {
110 NS_ENSURE_STATE(mKs
);
111 nsAutoCString secret
;
112 nsresult rv
= Base64Decode(aRecoveryPhrase
, secret
);
116 if (secret
.Length() != mKs
->GetKeyByteLength()) {
117 return NS_ERROR_INVALID_ARG
;
119 rv
= mKs
->StoreSecret(secret
, aLabel
);
127 nsresult
OSKeyStore::DeleteSecret(const nsACString
& aLabel
) {
128 NS_ENSURE_STATE(mKs
);
129 return mKs
->DeleteSecret(aLabel
);
132 nsresult
OSKeyStore::RetrieveRecoveryPhrase(
133 const nsACString
& aLabel
,
134 /* out */ nsACString
& aRecoveryPhrase
) {
135 NS_ENSURE_STATE(mKs
);
136 nsAutoCString secretString
;
137 nsresult rv
= mKs
->RetrieveSecret(aLabel
, secretString
);
142 nsCString recoveryPhrase
;
143 rv
= Base64Encode(secretString
, recoveryPhrase
);
148 aRecoveryPhrase
= std::move(recoveryPhrase
);
152 enum Cipher
{ Encrypt
= true, Decrypt
= false };
154 nsresult
OSKeyStore::EncryptBytes(const nsACString
& aLabel
,
155 const std::vector
<uint8_t>& aInBytes
,
156 /*out*/ nsACString
& aEncryptedBase64Text
) {
157 NS_ENSURE_STATE(mKs
);
159 aEncryptedBase64Text
.Truncate();
160 std::vector
<uint8_t> outBytes
;
162 mKs
->EncryptDecrypt(aLabel
, aInBytes
, outBytes
, Cipher::Encrypt
);
166 nsAutoCString ciphertext
;
167 ciphertext
.Assign(BitwiseCast
<char*, uint8_t*>(outBytes
.data()),
170 nsCString base64ciphertext
;
171 rv
= Base64Encode(ciphertext
, base64ciphertext
);
175 aEncryptedBase64Text
= std::move(base64ciphertext
);
179 nsresult
OSKeyStore::DecryptBytes(const nsACString
& aLabel
,
180 const nsACString
& aEncryptedBase64Text
,
181 /*out*/ uint32_t* outLen
,
182 /*out*/ uint8_t** outBytes
) {
183 NS_ENSURE_STATE(mKs
);
184 NS_ENSURE_ARG_POINTER(outLen
);
185 NS_ENSURE_ARG_POINTER(outBytes
);
189 nsAutoCString ciphertext
;
190 nsresult rv
= Base64Decode(aEncryptedBase64Text
, ciphertext
);
194 uint8_t* tmp
= BitwiseCast
<uint8_t*, const char*>(ciphertext
.BeginReading());
195 const std::vector
<uint8_t> ciphertextBytes(tmp
, tmp
+ ciphertext
.Length());
196 std::vector
<uint8_t> plaintextBytes
;
197 rv
= mKs
->EncryptDecrypt(aLabel
, ciphertextBytes
, plaintextBytes
,
203 *outBytes
= (uint8_t*)moz_xmalloc(plaintextBytes
.size());
204 memcpy(*outBytes
, plaintextBytes
.data(), plaintextBytes
.size());
205 *outLen
= plaintextBytes
.size();
209 // Async interfaces that return promises because the key store implementation
210 // might block, e.g. asking for a password.
212 nsresult
GetPromise(JSContext
* aCx
, /* out */ RefPtr
<Promise
>& aPromise
) {
213 nsIGlobalObject
* globalObject
= xpc::CurrentNativeGlobal(aCx
);
214 if (NS_WARN_IF(!globalObject
)) {
215 return NS_ERROR_UNEXPECTED
;
218 aPromise
= Promise::Create(globalObject
, result
);
219 if (NS_WARN_IF(result
.Failed())) {
220 return result
.StealNSResult();
225 void BackgroundGenerateSecret(const nsACString
& aLabel
,
226 RefPtr
<Promise
>& aPromise
,
227 RefPtr
<OSKeyStore
> self
) {
228 nsAutoCString recovery
;
229 nsresult rv
= self
->GenerateSecret(aLabel
, recovery
);
230 nsAutoString recoveryString
;
231 if (NS_SUCCEEDED(rv
)) {
232 CopyUTF8toUTF16(recovery
, recoveryString
);
234 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
235 "BackgroundGenerateSecreteOSKSResolve",
236 [rv
, aPromise
= std::move(aPromise
), recoveryString
]() {
238 aPromise
->MaybeReject(rv
);
240 aPromise
->MaybeResolve(recoveryString
);
243 NS_DispatchToMainThread(runnable
.forget());
247 OSKeyStore::AsyncGenerateSecret(const nsACString
& aLabel
, JSContext
* aCx
,
248 Promise
** promiseOut
) {
249 MOZ_ASSERT(NS_IsMainThread());
250 if (!NS_IsMainThread()) {
251 return NS_ERROR_NOT_SAME_THREAD
;
254 NS_ENSURE_ARG_POINTER(aCx
);
256 if (!mBackgroundSerialEventTarget
) {
257 return NS_ERROR_NOT_AVAILABLE
;
260 RefPtr
<Promise
> promiseHandle
;
261 nsresult rv
= GetPromise(aCx
, promiseHandle
);
266 RefPtr
<OSKeyStore
> self
= this;
267 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
268 "BackgroundGenerateSecret",
269 [self
, promiseHandle
, aLabel
= nsAutoCString(aLabel
)]() mutable {
270 BackgroundGenerateSecret(aLabel
, promiseHandle
, self
);
273 promiseHandle
.forget(promiseOut
);
274 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
275 NS_DISPATCH_EVENT_MAY_BLOCK
);
278 void BackgroundSecretAvailable(const nsACString
& aLabel
,
279 RefPtr
<Promise
>& aPromise
,
280 RefPtr
<OSKeyStore
> self
) {
281 bool available
= false;
282 nsresult rv
= self
->SecretAvailable(aLabel
, &available
);
283 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
284 "BackgroundSecreteAvailableOSKSResolve",
285 [rv
, aPromise
= std::move(aPromise
), available
= available
]() {
287 aPromise
->MaybeReject(rv
);
289 aPromise
->MaybeResolve(available
);
292 NS_DispatchToMainThread(runnable
.forget());
296 OSKeyStore::AsyncSecretAvailable(const nsACString
& aLabel
, JSContext
* aCx
,
297 Promise
** promiseOut
) {
298 MOZ_ASSERT(NS_IsMainThread());
299 if (!NS_IsMainThread()) {
300 return NS_ERROR_NOT_SAME_THREAD
;
303 NS_ENSURE_ARG_POINTER(aCx
);
305 if (!mBackgroundSerialEventTarget
) {
306 return NS_ERROR_NOT_AVAILABLE
;
309 RefPtr
<Promise
> promiseHandle
;
310 nsresult rv
= GetPromise(aCx
, promiseHandle
);
315 RefPtr
<OSKeyStore
> self
= this;
316 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
317 "BackgroundSecretAvailable",
318 [self
, promiseHandle
, aLabel
= nsAutoCString(aLabel
)]() mutable {
319 BackgroundSecretAvailable(aLabel
, promiseHandle
, self
);
322 promiseHandle
.forget(promiseOut
);
323 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
324 NS_DISPATCH_EVENT_MAY_BLOCK
);
327 void BackgroundRecoverSecret(const nsACString
& aLabel
,
328 const nsACString
& aRecoveryPhrase
,
329 RefPtr
<Promise
>& aPromise
,
330 RefPtr
<OSKeyStore
> self
) {
331 nsresult rv
= self
->RecoverSecret(aLabel
, aRecoveryPhrase
);
332 nsCOMPtr
<nsIRunnable
> runnable(
333 NS_NewRunnableFunction("BackgroundRecoverSecreteOSKSResolve",
334 [rv
, aPromise
= std::move(aPromise
)]() {
336 aPromise
->MaybeReject(rv
);
338 aPromise
->MaybeResolveWithUndefined();
341 NS_DispatchToMainThread(runnable
.forget());
345 OSKeyStore::AsyncRecoverSecret(const nsACString
& aLabel
,
346 const nsACString
& aRecoveryPhrase
,
347 JSContext
* aCx
, Promise
** promiseOut
) {
348 MOZ_ASSERT(NS_IsMainThread());
349 if (!NS_IsMainThread()) {
350 return NS_ERROR_NOT_SAME_THREAD
;
353 NS_ENSURE_ARG_POINTER(aCx
);
355 if (!mBackgroundSerialEventTarget
) {
356 return NS_ERROR_NOT_AVAILABLE
;
359 RefPtr
<Promise
> promiseHandle
;
360 nsresult rv
= GetPromise(aCx
, promiseHandle
);
365 RefPtr
<OSKeyStore
> self
= this;
366 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
367 "BackgroundRecoverSecret",
368 [self
, promiseHandle
, aLabel
= nsAutoCString(aLabel
),
369 aRecoveryPhrase
= nsAutoCString(aRecoveryPhrase
)]() mutable {
370 BackgroundRecoverSecret(aLabel
, aRecoveryPhrase
, promiseHandle
, self
);
373 promiseHandle
.forget(promiseOut
);
374 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
375 NS_DISPATCH_EVENT_MAY_BLOCK
);
378 void BackgroundDeleteSecret(const nsACString
& aLabel
, RefPtr
<Promise
>& aPromise
,
379 RefPtr
<OSKeyStore
> self
) {
380 nsresult rv
= self
->DeleteSecret(aLabel
);
381 nsCOMPtr
<nsIRunnable
> runnable(
382 NS_NewRunnableFunction("BackgroundDeleteSecreteOSKSResolve",
383 [rv
, aPromise
= std::move(aPromise
)]() {
385 aPromise
->MaybeReject(rv
);
387 aPromise
->MaybeResolveWithUndefined();
390 NS_DispatchToMainThread(runnable
.forget());
394 OSKeyStore::AsyncDeleteSecret(const nsACString
& aLabel
, JSContext
* aCx
,
395 Promise
** promiseOut
) {
396 MOZ_ASSERT(NS_IsMainThread());
397 if (!NS_IsMainThread()) {
398 return NS_ERROR_NOT_SAME_THREAD
;
401 NS_ENSURE_ARG_POINTER(aCx
);
403 if (!mBackgroundSerialEventTarget
) {
404 return NS_ERROR_NOT_AVAILABLE
;
407 RefPtr
<Promise
> promiseHandle
;
408 nsresult rv
= GetPromise(aCx
, promiseHandle
);
413 RefPtr
<OSKeyStore
> self
= this;
414 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
415 "BackgroundDeleteSecret",
416 [self
, promiseHandle
, aLabel
= nsAutoCString(aLabel
)]() mutable {
417 BackgroundDeleteSecret(aLabel
, promiseHandle
, self
);
420 promiseHandle
.forget(promiseOut
);
421 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
422 NS_DISPATCH_EVENT_MAY_BLOCK
);
425 static void BackgroundEncryptBytes(const nsACString
& aLabel
,
426 const std::vector
<uint8_t>& aInBytes
,
427 RefPtr
<Promise
>& aPromise
,
428 RefPtr
<OSKeyStore
> self
) {
429 nsAutoCString ciphertext
;
430 nsresult rv
= self
->EncryptBytes(aLabel
, aInBytes
, ciphertext
);
432 CopyUTF8toUTF16(ciphertext
, ctext
);
434 nsCOMPtr
<nsIRunnable
> runnable(
435 NS_NewRunnableFunction("BackgroundEncryptOSKSResolve",
436 [rv
, aPromise
= std::move(aPromise
), ctext
]() {
438 aPromise
->MaybeReject(rv
);
440 aPromise
->MaybeResolve(ctext
);
443 NS_DispatchToMainThread(runnable
.forget());
447 OSKeyStore::AsyncEncryptBytes(const nsACString
& aLabel
,
448 const nsTArray
<uint8_t>& inBytes
, JSContext
* aCx
,
449 Promise
** promiseOut
) {
450 MOZ_ASSERT(NS_IsMainThread());
451 if (!NS_IsMainThread()) {
452 return NS_ERROR_NOT_SAME_THREAD
;
455 NS_ENSURE_ARG_POINTER(aCx
);
457 if (!mBackgroundSerialEventTarget
) {
458 return NS_ERROR_NOT_AVAILABLE
;
461 RefPtr
<Promise
> promiseHandle
;
462 nsresult rv
= GetPromise(aCx
, promiseHandle
);
467 RefPtr
<OSKeyStore
> self
= this;
468 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
469 "BackgroundEncryptBytes",
471 inBytes
= std::vector
<uint8_t>(inBytes
.Elements(),
472 inBytes
.Elements() + inBytes
.Length()),
473 aLabel
= nsAutoCString(aLabel
), self
]() mutable {
474 BackgroundEncryptBytes(aLabel
, inBytes
, promiseHandle
, self
);
477 promiseHandle
.forget(promiseOut
);
478 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
479 NS_DISPATCH_EVENT_MAY_BLOCK
);
482 void BackgroundDecryptBytes(const nsACString
& aLabel
,
483 const nsACString
& aEncryptedBase64Text
,
484 RefPtr
<Promise
>& aPromise
,
485 RefPtr
<OSKeyStore
> self
) {
486 uint8_t* plaintext
= nullptr;
487 uint32_t plaintextLen
= 0;
488 nsresult rv
= self
->DecryptBytes(aLabel
, aEncryptedBase64Text
, &plaintextLen
,
490 nsTArray
<uint8_t> plain
;
492 MOZ_ASSERT(plaintextLen
> 0);
493 plain
.AppendElements(plaintext
, plaintextLen
);
497 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
498 "BackgroundDecryptOSKSResolve",
499 [rv
, aPromise
= std::move(aPromise
), plain
= std::move(plain
)]() {
501 aPromise
->MaybeReject(rv
);
503 aPromise
->MaybeResolve(plain
);
506 NS_DispatchToMainThread(runnable
.forget());
510 OSKeyStore::AsyncDecryptBytes(const nsACString
& aLabel
,
511 const nsACString
& aEncryptedBase64Text
,
512 JSContext
* aCx
, Promise
** promiseOut
) {
513 MOZ_ASSERT(NS_IsMainThread());
514 if (!NS_IsMainThread()) {
515 return NS_ERROR_NOT_SAME_THREAD
;
518 NS_ENSURE_ARG_POINTER(aCx
);
520 if (!mBackgroundSerialEventTarget
) {
521 return NS_ERROR_NOT_AVAILABLE
;
524 RefPtr
<Promise
> promiseHandle
;
525 nsresult rv
= GetPromise(aCx
, promiseHandle
);
530 RefPtr
<OSKeyStore
> self
= this;
531 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
532 "BackgroundDecryptBytes",
533 [promiseHandle
, self
,
534 aEncryptedBase64Text
= nsAutoCString(aEncryptedBase64Text
),
535 aLabel
= nsAutoCString(aLabel
)]() mutable {
536 BackgroundDecryptBytes(aLabel
, aEncryptedBase64Text
, promiseHandle
,
540 promiseHandle
.forget(promiseOut
);
541 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
542 NS_DISPATCH_EVENT_MAY_BLOCK
);
545 void BackgroundGetRecoveryPhrase(const nsACString
& aLabel
,
546 RefPtr
<Promise
>& aPromise
,
547 const RefPtr
<OSKeyStore
>& self
) {
548 nsAutoCString recoveryPhrase
;
549 nsresult rv
= self
->RetrieveRecoveryPhrase(aLabel
, recoveryPhrase
);
550 nsAutoString exportedRecoveryPhrase
;
551 if (NS_SUCCEEDED(rv
)) {
552 CopyUTF8toUTF16(recoveryPhrase
, exportedRecoveryPhrase
);
554 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
555 "BackgroundRetrieveRecoveryPhraseResolve",
556 [rv
, aPromise
= std::move(aPromise
), exportedRecoveryPhrase
]() {
558 aPromise
->MaybeReject(rv
);
560 aPromise
->MaybeResolve(exportedRecoveryPhrase
);
563 NS_DispatchToMainThread(runnable
.forget());
567 OSKeyStore::AsyncGetRecoveryPhrase(const nsACString
& aLabel
, JSContext
* aCx
,
568 Promise
** promiseOut
) {
569 MOZ_ASSERT(NS_IsMainThread());
570 if (!NS_IsMainThread()) {
571 return NS_ERROR_NOT_SAME_THREAD
;
574 NS_ENSURE_ARG_POINTER(aCx
);
576 if (!mBackgroundSerialEventTarget
) {
577 return NS_ERROR_NOT_AVAILABLE
;
580 RefPtr
<Promise
> promiseHandle
;
581 nsresult rv
= GetPromise(aCx
, promiseHandle
);
586 RefPtr
<OSKeyStore
> self
= this;
587 nsCOMPtr
<nsIRunnable
> runnable(NS_NewRunnableFunction(
588 "BackgroundGetRecoveryPhrase",
589 [promiseHandle
, self
, aLabel
= nsAutoCString(aLabel
)]() mutable {
590 BackgroundGetRecoveryPhrase(aLabel
, promiseHandle
, self
);
593 promiseHandle
.forget(promiseOut
);
594 return mBackgroundSerialEventTarget
->Dispatch(runnable
.forget(),
595 NS_DISPATCH_EVENT_MAY_BLOCK
);
598 // Generic AES-GCM cipher wrapper for NSS functions.
600 nsresult
AbstractOSKeyStore::BuildAesGcmKey(std::vector
<uint8_t> aKeyBytes
,
601 /* out */ UniquePK11SymKey
& aKey
) {
602 if (aKeyBytes
.size() != mKeyByteLength
) {
603 return NS_ERROR_INVALID_ARG
;
606 UniquePK11SlotInfo
slot(PK11_GetInternalSlot());
608 return NS_ERROR_FAILURE
;
612 UniqueSECItem(SECITEM_AllocItem(nullptr, nullptr, mKeyByteLength
));
614 return NS_ERROR_FAILURE
;
616 key
->type
= siBuffer
;
617 memcpy(key
->data
, aKeyBytes
.data(), mKeyByteLength
);
618 key
->len
= mKeyByteLength
;
620 UniquePK11SymKey
symKey(
621 PK11_ImportSymKey(slot
.get(), CKM_AES_GCM
, PK11_OriginUnwrap
,
622 CKA_DECRYPT
| CKA_ENCRYPT
, key
.get(), nullptr));
625 return NS_ERROR_FAILURE
;
632 nsresult
AbstractOSKeyStore::DoCipher(const UniquePK11SymKey
& aSymKey
,
633 const std::vector
<uint8_t>& inBytes
,
634 std::vector
<uint8_t>& outBytes
,
636 NS_ENSURE_ARG_POINTER(aSymKey
);
640 // We need to get the IV from inBytes if we decrypt.
641 if (!encrypt
&& (inBytes
.size() < mIVLength
|| inBytes
.empty())) {
642 return NS_ERROR_INVALID_ARG
;
645 const uint8_t* ivp
= nullptr;
646 std::vector
<uint8_t> ivBuf
;
648 // Generate a new IV.
649 ivBuf
.resize(mIVLength
);
650 nsresult rv
= GenerateRandom(ivBuf
);
651 if (NS_FAILED(rv
) || ivBuf
.size() != mIVLength
) {
652 return NS_ERROR_FAILURE
;
656 // An IV was passed in. Use the first mIVLength bytes from inBytes as IV.
657 ivp
= inBytes
.data();
660 CK_GCM_PARAMS gcm_params
;
661 gcm_params
.pIv
= const_cast<unsigned char*>(ivp
);
662 gcm_params
.ulIvLen
= mIVLength
;
663 gcm_params
.ulIvBits
= gcm_params
.ulIvLen
* 8;
664 gcm_params
.ulTagBits
= 128;
665 gcm_params
.pAAD
= nullptr;
666 gcm_params
.ulAADLen
= 0;
668 SECItem paramsItem
= {siBuffer
, reinterpret_cast<unsigned char*>(&gcm_params
),
669 sizeof(CK_GCM_PARAMS
)};
671 size_t blockLength
= 16;
672 outBytes
.resize(inBytes
.size() + blockLength
);
673 unsigned int outLen
= 0;
674 SECStatus srv
= SECFailure
;
676 srv
= PK11_Encrypt(aSymKey
.get(), CKM_AES_GCM
, ¶msItem
, outBytes
.data(),
677 &outLen
, inBytes
.size() + blockLength
, inBytes
.data(),
679 // Prepend the used IV to the ciphertext.
680 Unused
<< outBytes
.insert(outBytes
.begin(), ivp
, ivp
+ mIVLength
);
683 // Remove the IV from the input.
684 std::vector
<uint8_t> input(inBytes
);
685 input
.erase(input
.begin(), input
.begin() + mIVLength
);
686 srv
= PK11_Decrypt(aSymKey
.get(), CKM_AES_GCM
, ¶msItem
, outBytes
.data(),
687 &outLen
, input
.size() + blockLength
, input
.data(),
690 if (srv
!= SECSuccess
|| outLen
> outBytes
.size()) {
692 return NS_ERROR_FAILURE
;
694 if (outLen
< outBytes
.size()) {
695 outBytes
.resize(outLen
);
701 bool AbstractOSKeyStore::SecretAvailable(const nsACString
& aLabel
) {
702 nsAutoCString secret
;
703 nsresult rv
= RetrieveSecret(aLabel
, secret
);
704 if (NS_FAILED(rv
) || secret
.Length() == 0) {
710 nsresult
AbstractOSKeyStore::EncryptDecrypt(const nsACString
& aLabel
,
711 const std::vector
<uint8_t>& inBytes
,
712 std::vector
<uint8_t>& outBytes
,
714 nsAutoCString secret
;
715 nsresult rv
= RetrieveSecret(aLabel
, secret
);
716 if (NS_FAILED(rv
) || secret
.Length() == 0) {
717 return NS_ERROR_FAILURE
;
720 uint8_t* p
= BitwiseCast
<uint8_t*, const char*>(secret
.BeginReading());
721 std::vector
<uint8_t> buf(p
, p
+ secret
.Length());
722 UniquePK11SymKey symKey
;
723 rv
= BuildAesGcmKey(buf
, symKey
);
725 return NS_ERROR_FAILURE
;
727 return DoCipher(symKey
, inBytes
, outBytes
, encrypt
);