1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
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 "CryptoBuffer.h"
9 #include "mozilla/Base64.h"
10 #include "mozilla/dom/UnionTypes.h"
12 namespace mozilla::dom
{
14 uint8_t* CryptoBuffer::Assign(const CryptoBuffer
& aData
) {
15 // Same as in nsTArray_Impl::operator=, but return the value
16 // returned from ReplaceElementsAt to enable OOM detection
17 return ReplaceElementsAt(0, Length(), aData
.Elements(), aData
.Length(),
21 uint8_t* CryptoBuffer::Assign(const uint8_t* aData
, uint32_t aLength
) {
22 return ReplaceElementsAt(0, Length(), aData
, aLength
, fallible
);
25 uint8_t* CryptoBuffer::Assign(const nsACString
& aString
) {
26 return Assign(reinterpret_cast<uint8_t const*>(aString
.BeginReading()),
30 uint8_t* CryptoBuffer::Assign(const SECItem
* aItem
) {
32 return Assign(aItem
->data
, aItem
->len
);
35 uint8_t* CryptoBuffer::Assign(const nsTArray
<uint8_t>& aData
) {
36 return ReplaceElementsAt(0, Length(), aData
.Elements(), aData
.Length(),
40 uint8_t* CryptoBuffer::Assign(const ArrayBuffer
& aData
) {
42 return aData
.AppendDataTo(*this) ? Elements() : nullptr;
45 uint8_t* CryptoBuffer::Assign(const ArrayBufferView
& aData
) {
47 return aData
.AppendDataTo(*this) ? Elements() : nullptr;
50 uint8_t* CryptoBuffer::Assign(const ArrayBufferViewOrArrayBuffer
& aData
) {
53 return AppendTypedArrayDataTo(aData
, *this) ? Elements() : nullptr;
56 uint8_t* CryptoBuffer::Assign(const OwningArrayBufferViewOrArrayBuffer
& aData
) {
59 return AppendTypedArrayDataTo(aData
, *this) ? Elements() : nullptr;
62 uint8_t* CryptoBuffer::Assign(const Uint8Array
& aArray
) {
64 return aArray
.AppendDataTo(*this) ? Elements() : nullptr;
67 uint8_t* CryptoBuffer::AppendSECItem(const SECItem
* aItem
) {
69 return AppendElements(aItem
->data
, aItem
->len
, fallible
);
72 uint8_t* CryptoBuffer::AppendSECItem(const SECItem
& aItem
) {
73 return AppendElements(aItem
.data
, aItem
.len
, fallible
);
76 // Helpers to encode/decode JWK's special flavor of Base64
79 // * URL-safe character set
80 nsresult
CryptoBuffer::FromJwkBase64(const nsString
& aBase64
) {
81 NS_ConvertUTF16toUTF8
temp(aBase64
);
82 temp
.StripWhitespace();
84 // JWK prohibits padding per RFC 7515, section 2.
86 Base64URLDecode(temp
, Base64URLDecodePaddingPolicy::Reject
, *this);
87 NS_ENSURE_SUCCESS(rv
, rv
);
92 nsresult
CryptoBuffer::ToJwkBase64(nsString
& aBase64
) const {
93 // Shortcut for the empty octet string
100 nsresult rv
= Base64URLEncode(Length(), Elements(),
101 Base64URLEncodePaddingPolicy::Omit
, base64
);
102 NS_ENSURE_SUCCESS(rv
, rv
);
104 CopyASCIItoUTF16(base64
, aBase64
);
108 bool CryptoBuffer::ToSECItem(PLArenaPool
* aArena
, SECItem
* aItem
) const {
109 aItem
->type
= siBuffer
;
110 aItem
->data
= nullptr;
112 if (!::SECITEM_AllocItem(aArena
, aItem
, Length())) {
115 // If this CryptoBuffer is of 0 length, aItem->data will be null. Passing
116 // null to memcpy is not valid, even if the length is 0, so return early.
118 MOZ_ASSERT(Length() == 0);
121 memcpy(aItem
->data
, Elements(), Length());
125 JSObject
* CryptoBuffer::ToUint8Array(JSContext
* aCx
,
126 ErrorResult
& aError
) const {
127 return Uint8Array::Create(aCx
, *this, aError
);
130 JSObject
* CryptoBuffer::ToArrayBuffer(JSContext
* aCx
,
131 ErrorResult
& aError
) const {
132 return ArrayBuffer::Create(aCx
, *this, aError
);
135 // "BigInt" comes from the WebCrypto spec
136 // ("unsigned long" isn't very "big", of course)
137 // Likewise, the spec calls for big-endian ints
138 bool CryptoBuffer::GetBigIntValue(unsigned long& aRetVal
) {
139 if (Length() > sizeof(aRetVal
)) {
144 for (size_t i
= 0; i
< Length(); ++i
) {
145 aRetVal
= (aRetVal
<< 8) + ElementAt(i
);
150 } // namespace mozilla::dom