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 Assign(aData
.Data(), aData
.Length());
45 uint8_t* CryptoBuffer::Assign(const ArrayBufferView
& aData
) {
47 return Assign(aData
.Data(), aData
.Length());
50 uint8_t* CryptoBuffer::Assign(const ArrayBufferViewOrArrayBuffer
& aData
) {
51 if (aData
.IsArrayBufferView()) {
52 return Assign(aData
.GetAsArrayBufferView());
54 if (aData
.IsArrayBuffer()) {
55 return Assign(aData
.GetAsArrayBuffer());
58 // If your union is uninitialized, something's wrong
64 uint8_t* CryptoBuffer::Assign(const OwningArrayBufferViewOrArrayBuffer
& aData
) {
65 if (aData
.IsArrayBufferView()) {
66 return Assign(aData
.GetAsArrayBufferView());
68 if (aData
.IsArrayBuffer()) {
69 return Assign(aData
.GetAsArrayBuffer());
72 // If your union is uninitialized, something's wrong
78 uint8_t* CryptoBuffer::Assign(const Uint8Array
& aArray
) {
79 aArray
.ComputeState();
80 return Assign(aArray
.Data(), aArray
.Length());
83 uint8_t* CryptoBuffer::AppendSECItem(const SECItem
* aItem
) {
85 return AppendElements(aItem
->data
, aItem
->len
, fallible
);
88 uint8_t* CryptoBuffer::AppendSECItem(const SECItem
& aItem
) {
89 return AppendElements(aItem
.data
, aItem
.len
, fallible
);
92 // Helpers to encode/decode JWK's special flavor of Base64
95 // * URL-safe character set
96 nsresult
CryptoBuffer::FromJwkBase64(const nsString
& aBase64
) {
97 NS_ConvertUTF16toUTF8
temp(aBase64
);
98 temp
.StripWhitespace();
100 // JWK prohibits padding per RFC 7515, section 2.
102 Base64URLDecode(temp
, Base64URLDecodePaddingPolicy::Reject
, *this);
103 NS_ENSURE_SUCCESS(rv
, rv
);
108 nsresult
CryptoBuffer::ToJwkBase64(nsString
& aBase64
) const {
109 // Shortcut for the empty octet string
115 nsAutoCString base64
;
116 nsresult rv
= Base64URLEncode(Length(), Elements(),
117 Base64URLEncodePaddingPolicy::Omit
, base64
);
118 NS_ENSURE_SUCCESS(rv
, rv
);
120 CopyASCIItoUTF16(base64
, aBase64
);
124 bool CryptoBuffer::ToSECItem(PLArenaPool
* aArena
, SECItem
* aItem
) const {
125 aItem
->type
= siBuffer
;
126 aItem
->data
= nullptr;
128 if (!::SECITEM_AllocItem(aArena
, aItem
, Length())) {
132 memcpy(aItem
->data
, Elements(), Length());
136 JSObject
* CryptoBuffer::ToUint8Array(JSContext
* aCx
) const {
137 return Uint8Array::Create(aCx
, Length(), Elements());
140 JSObject
* CryptoBuffer::ToArrayBuffer(JSContext
* aCx
) const {
141 return ArrayBuffer::Create(aCx
, Length(), Elements());
144 bool CryptoBuffer::ToNewUnsignedBuffer(uint8_t** aBuf
,
145 uint32_t* aBufLen
) const {
149 uint32_t dataLen
= Length();
150 uint8_t* tmp
= reinterpret_cast<uint8_t*>(moz_xmalloc(dataLen
));
152 memcpy(tmp
, Elements(), dataLen
);
158 // "BigInt" comes from the WebCrypto spec
159 // ("unsigned long" isn't very "big", of course)
160 // Likewise, the spec calls for big-endian ints
161 bool CryptoBuffer::GetBigIntValue(unsigned long& aRetVal
) {
162 if (Length() > sizeof(aRetVal
)) {
167 for (size_t i
= 0; i
< Length(); ++i
) {
168 aRetVal
= (aRetVal
<< 8) + ElementAt(i
);
173 } // namespace mozilla::dom