1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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"
16 CryptoBuffer::Assign(const CryptoBuffer
& aData
)
18 // Same as in nsTArray_Impl::operator=, but return the value
19 // returned from ReplaceElementsAt to enable OOM detection
20 return ReplaceElementsAt(0, Length(), aData
.Elements(), aData
.Length());
24 CryptoBuffer::Assign(const uint8_t* aData
, uint32_t aLength
)
26 return ReplaceElementsAt(0, Length(), aData
, aLength
);
30 CryptoBuffer::Assign(const SECItem
* aItem
)
33 return Assign(aItem
->data
, aItem
->len
);
37 CryptoBuffer::Assign(const ArrayBuffer
& aData
)
39 aData
.ComputeLengthAndData();
40 return Assign(aData
.Data(), aData
.Length());
44 CryptoBuffer::Assign(const ArrayBufferView
& aData
)
46 aData
.ComputeLengthAndData();
47 return Assign(aData
.Data(), aData
.Length());
51 CryptoBuffer::Assign(const ArrayBufferViewOrArrayBuffer
& aData
)
53 if (aData
.IsArrayBufferView()) {
54 return Assign(aData
.GetAsArrayBufferView());
55 } else if (aData
.IsArrayBuffer()) {
56 return Assign(aData
.GetAsArrayBuffer());
59 // If your union is uninitialized, something's wrong
66 CryptoBuffer::Assign(const OwningArrayBufferViewOrArrayBuffer
& aData
)
68 if (aData
.IsArrayBufferView()) {
69 return Assign(aData
.GetAsArrayBufferView());
70 } else if (aData
.IsArrayBuffer()) {
71 return Assign(aData
.GetAsArrayBuffer());
74 // If your union is uninitialized, something's wrong
80 // Helpers to encode/decode JWK's special flavor of Base64
83 // * URL-safe character set
85 CryptoBuffer::FromJwkBase64(const nsString
& aBase64
)
87 NS_ConvertUTF16toUTF8
temp(aBase64
);
88 temp
.StripWhitespace();
91 if (temp
.Length() % 4 == 3) {
92 temp
.AppendLiteral("=");
93 } else if (temp
.Length() % 4 == 2) {
94 temp
.AppendLiteral("==");
95 } if (temp
.Length() % 4 == 1) {
96 return NS_ERROR_FAILURE
; // bad Base64
99 // Translate from URL-safe character set to normal
100 temp
.ReplaceChar('-', '+');
101 temp
.ReplaceChar('_', '/');
103 // Perform the actual base64 decode
104 nsCString binaryData
;
105 nsresult rv
= Base64Decode(temp
, binaryData
);
106 NS_ENSURE_SUCCESS(rv
, rv
);
108 if (!Assign((const uint8_t*) binaryData
.BeginReading(),
109 binaryData
.Length())) {
110 return NS_ERROR_FAILURE
;
117 CryptoBuffer::ToJwkBase64(nsString
& aBase64
)
119 // Shortcut for the empty octet string
125 // Perform the actual base64 encode
127 nsDependentCSubstring
binaryData((const char*) Elements(),
128 (const char*) (Elements() + Length()));
129 nsresult rv
= Base64Encode(binaryData
, base64
);
130 NS_ENSURE_SUCCESS(rv
, rv
);
135 // Translate to the URL-safe charset
136 base64
.ReplaceChar('+', '-');
137 base64
.ReplaceChar('/', '_');
138 if (base64
.FindCharInSet("+/", 0) != kNotFound
) {
139 return NS_ERROR_FAILURE
;
142 CopyASCIItoUTF16(base64
, aBase64
);
147 CryptoBuffer::ToSECItem() const
149 uint8_t* data
= (uint8_t*) moz_malloc(Length());
154 SECItem
* item
= ::SECITEM_AllocItem(nullptr, nullptr, 0);
155 item
->type
= siBuffer
;
157 item
->len
= Length();
159 memcpy(item
->data
, Elements(), Length());
165 CryptoBuffer::ToUint8Array(JSContext
* aCx
) const
167 return Uint8Array::Create(aCx
, Length(), Elements());
171 // "BigInt" comes from the WebCrypto spec
172 // ("unsigned long" isn't very "big", of course)
173 // Likewise, the spec calls for big-endian ints
175 CryptoBuffer::GetBigIntValue(unsigned long& aRetVal
)
177 if (Length() > sizeof(aRetVal
)) {
182 for (size_t i
=0; i
< Length(); ++i
) {
183 aRetVal
= (aRetVal
<< 8) + ElementAt(i
);
189 } // namespace mozilla