Line data Source code
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 file,
5 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 : #include "Crypto.h"
7 : #include "jsfriendapi.h"
8 : #include "nsCOMPtr.h"
9 : #include "nsIRandomGenerator.h"
10 : #include "MainThreadUtils.h"
11 : #include "nsXULAppAPI.h"
12 :
13 : #include "mozilla/dom/ContentChild.h"
14 : #include "mozilla/dom/CryptoBinding.h"
15 : #include "nsServiceManagerUtils.h"
16 :
17 : using mozilla::dom::ContentChild;
18 :
19 : namespace mozilla {
20 : namespace dom {
21 :
22 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Crypto)
23 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
24 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
25 0 : NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto)
26 0 : NS_INTERFACE_MAP_END
27 :
28 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(Crypto)
29 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(Crypto)
30 :
31 0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Crypto, mParent, mSubtle)
32 :
33 0 : Crypto::Crypto()
34 : {
35 0 : }
36 :
37 0 : Crypto::~Crypto()
38 : {
39 0 : }
40 :
41 : void
42 0 : Crypto::Init(nsIGlobalObject* aParent)
43 : {
44 0 : mParent = do_QueryInterface(aParent);
45 0 : MOZ_ASSERT(mParent);
46 0 : }
47 :
48 : /* virtual */ JSObject*
49 0 : Crypto::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
50 : {
51 0 : return CryptoBinding::Wrap(aCx, this, aGivenProto);
52 : }
53 :
54 : void
55 0 : Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
56 : JS::MutableHandle<JSObject*> aRetval,
57 : ErrorResult& aRv)
58 : {
59 0 : JS::Rooted<JSObject*> view(aCx, aArray.Obj());
60 :
61 0 : if (JS_IsTypedArrayObject(view) && JS_GetTypedArraySharedness(view)) {
62 : // Throw if the object is mapping shared memory (must opt in).
63 0 : aRv.ThrowTypeError<MSG_TYPEDARRAY_IS_SHARED>(NS_LITERAL_STRING("Argument of Crypto.getRandomValues"));
64 0 : return;
65 : }
66 :
67 : // Throw if the wrong type of ArrayBufferView is passed in
68 : // (Part of the Web Crypto API spec)
69 0 : switch (JS_GetArrayBufferViewType(view)) {
70 : case js::Scalar::Int8:
71 : case js::Scalar::Uint8:
72 : case js::Scalar::Uint8Clamped:
73 : case js::Scalar::Int16:
74 : case js::Scalar::Uint16:
75 : case js::Scalar::Int32:
76 : case js::Scalar::Uint32:
77 0 : break;
78 : default:
79 0 : aRv.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
80 0 : return;
81 : }
82 :
83 0 : aArray.ComputeLengthAndData();
84 0 : uint32_t dataLen = aArray.Length();
85 0 : if (dataLen == 0) {
86 0 : NS_WARNING("ArrayBufferView length is 0, cannot continue");
87 0 : aRetval.set(view);
88 0 : return;
89 0 : } else if (dataLen > 65536) {
90 0 : aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
91 0 : return;
92 : }
93 :
94 : nsCOMPtr<nsIRandomGenerator> randomGenerator =
95 0 : do_GetService("@mozilla.org/security/random-generator;1");
96 0 : if (!randomGenerator) {
97 0 : aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
98 0 : return;
99 : }
100 :
101 : uint8_t* buf;
102 0 : nsresult rv = randomGenerator->GenerateRandomBytes(dataLen, &buf);
103 0 : if (NS_FAILED(rv) || !buf) {
104 0 : aRv.Throw(NS_ERROR_DOM_OPERATION_ERR);
105 0 : return;
106 : }
107 :
108 : // Copy random bytes to ABV.
109 0 : memcpy(aArray.Data(), buf, dataLen);
110 0 : free(buf);
111 :
112 0 : aRetval.set(view);
113 : }
114 :
115 : SubtleCrypto*
116 0 : Crypto::Subtle()
117 : {
118 0 : if(!mSubtle) {
119 0 : mSubtle = new SubtleCrypto(GetParentObject());
120 : }
121 0 : return mSubtle;
122 : }
123 :
124 : } // namespace dom
125 : } // namespace mozilla
|