Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / dom / crypto / CryptoBuffer.cpp
blob73a5f81d68e56e0197c7b23b84bad6b9560dc060
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"
8 #include "secitem.h"
9 #include "mozilla/Base64.h"
10 #include "mozilla/dom/UnionTypes.h"
12 namespace mozilla {
13 namespace dom {
15 uint8_t*
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());
23 uint8_t*
24 CryptoBuffer::Assign(const uint8_t* aData, uint32_t aLength)
26 return ReplaceElementsAt(0, Length(), aData, aLength);
29 uint8_t*
30 CryptoBuffer::Assign(const SECItem* aItem)
32 MOZ_ASSERT(aItem);
33 return Assign(aItem->data, aItem->len);
36 uint8_t*
37 CryptoBuffer::Assign(const ArrayBuffer& aData)
39 aData.ComputeLengthAndData();
40 return Assign(aData.Data(), aData.Length());
43 uint8_t*
44 CryptoBuffer::Assign(const ArrayBufferView& aData)
46 aData.ComputeLengthAndData();
47 return Assign(aData.Data(), aData.Length());
50 uint8_t*
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
60 MOZ_ASSERT(false);
61 SetLength(0);
62 return nullptr;
65 uint8_t*
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
75 MOZ_ASSERT(false);
76 SetLength(0);
77 return nullptr;
80 // Helpers to encode/decode JWK's special flavor of Base64
81 // * No whitespace
82 // * No padding
83 // * URL-safe character set
84 nsresult
85 CryptoBuffer::FromJwkBase64(const nsString& aBase64)
87 NS_ConvertUTF16toUTF8 temp(aBase64);
88 temp.StripWhitespace();
90 // Re-add padding
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;
113 return NS_OK;
116 nsresult
117 CryptoBuffer::ToJwkBase64(nsString& aBase64)
119 // Shortcut for the empty octet string
120 if (Length() == 0) {
121 aBase64.Truncate();
122 return NS_OK;
125 // Perform the actual base64 encode
126 nsCString base64;
127 nsDependentCSubstring binaryData((const char*) Elements(),
128 (const char*) (Elements() + Length()));
129 nsresult rv = Base64Encode(binaryData, base64);
130 NS_ENSURE_SUCCESS(rv, rv);
132 // Strip padding
133 base64.Trim("=");
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);
143 return NS_OK;
146 SECItem*
147 CryptoBuffer::ToSECItem() const
149 uint8_t* data = (uint8_t*) moz_malloc(Length());
150 if (!data) {
151 return nullptr;
154 SECItem* item = ::SECITEM_AllocItem(nullptr, nullptr, 0);
155 item->type = siBuffer;
156 item->data = data;
157 item->len = Length();
159 memcpy(item->data, Elements(), Length());
161 return item;
164 JSObject*
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
174 bool
175 CryptoBuffer::GetBigIntValue(unsigned long& aRetVal)
177 if (Length() > sizeof(aRetVal)) {
178 return false;
181 aRetVal = 0;
182 for (size_t i=0; i < Length(); ++i) {
183 aRetVal = (aRetVal << 8) + ElementAt(i);
185 return true;
188 } // namespace dom
189 } // namespace mozilla