dom/base/Crypto.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/dom/base/Crypto.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,216 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +#include "Crypto.h"
     1.8 +#include "jsfriendapi.h"
     1.9 +#include "nsCOMPtr.h"
    1.10 +#include "nsIRandomGenerator.h"
    1.11 +#include "nsPIDOMWindow.h"
    1.12 +#include "MainThreadUtils.h"
    1.13 +#include "nsXULAppAPI.h"
    1.14 +
    1.15 +#include "mozilla/dom/ContentChild.h"
    1.16 +#include "mozilla/dom/CryptoBinding.h"
    1.17 +#include "nsServiceManagerUtils.h"
    1.18 +
    1.19 +using mozilla::dom::ContentChild;
    1.20 +
    1.21 +using namespace js::ArrayBufferView;
    1.22 +
    1.23 +namespace mozilla {
    1.24 +namespace dom {
    1.25 +
    1.26 +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Crypto)
    1.27 +  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
    1.28 +  NS_INTERFACE_MAP_ENTRY(nsISupports)
    1.29 +  NS_INTERFACE_MAP_ENTRY(nsIDOMCrypto)
    1.30 +NS_INTERFACE_MAP_END
    1.31 +
    1.32 +NS_IMPL_CYCLE_COLLECTING_ADDREF(Crypto)
    1.33 +NS_IMPL_CYCLE_COLLECTING_RELEASE(Crypto)
    1.34 +
    1.35 +NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE_1(Crypto, mWindow)
    1.36 +
    1.37 +Crypto::Crypto()
    1.38 +{
    1.39 +  MOZ_COUNT_CTOR(Crypto);
    1.40 +  SetIsDOMBinding();
    1.41 +}
    1.42 +
    1.43 +Crypto::~Crypto()
    1.44 +{
    1.45 +  MOZ_COUNT_DTOR(Crypto);
    1.46 +}
    1.47 +
    1.48 +void
    1.49 +Crypto::Init(nsIDOMWindow* aWindow)
    1.50 +{
    1.51 +  mWindow = do_QueryInterface(aWindow);
    1.52 +  MOZ_ASSERT(mWindow);
    1.53 +}
    1.54 +
    1.55 +/* virtual */ JSObject*
    1.56 +Crypto::WrapObject(JSContext* aCx)
    1.57 +{
    1.58 +  return CryptoBinding::Wrap(aCx, this);
    1.59 +}
    1.60 +
    1.61 +void
    1.62 +Crypto::GetRandomValues(JSContext* aCx, const ArrayBufferView& aArray,
    1.63 +			JS::MutableHandle<JSObject*> aRetval,
    1.64 +			ErrorResult& aRv)
    1.65 +{
    1.66 +  NS_ABORT_IF_FALSE(NS_IsMainThread(), "Called on the wrong thread");
    1.67 +
    1.68 +  JS::Rooted<JSObject*> view(aCx, aArray.Obj());
    1.69 +
    1.70 +  // Throw if the wrong type of ArrayBufferView is passed in
    1.71 +  // (Part of the Web Crypto API spec)
    1.72 +  switch (JS_GetArrayBufferViewType(view)) {
    1.73 +    case TYPE_INT8:
    1.74 +    case TYPE_UINT8:
    1.75 +    case TYPE_UINT8_CLAMPED:
    1.76 +    case TYPE_INT16:
    1.77 +    case TYPE_UINT16:
    1.78 +    case TYPE_INT32:
    1.79 +    case TYPE_UINT32:
    1.80 +      break;
    1.81 +    default:
    1.82 +      aRv.Throw(NS_ERROR_DOM_TYPE_MISMATCH_ERR);
    1.83 +      return;
    1.84 +  }
    1.85 +
    1.86 +  aArray.ComputeLengthAndData();
    1.87 +  uint32_t dataLen = aArray.Length();
    1.88 +  if (dataLen == 0) {
    1.89 +    NS_WARNING("ArrayBufferView length is 0, cannot continue");
    1.90 +    aRetval.set(view);
    1.91 +    return;
    1.92 +  } else if (dataLen > 65536) {
    1.93 +    aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
    1.94 +    return;
    1.95 +  }
    1.96 +
    1.97 +  uint8_t* data = aArray.Data();
    1.98 +
    1.99 +  if (XRE_GetProcessType() != GeckoProcessType_Default) {
   1.100 +    InfallibleTArray<uint8_t> randomValues;
   1.101 +    // Tell the parent process to generate random values via PContent
   1.102 +    ContentChild* cc = ContentChild::GetSingleton();
   1.103 +    if (!cc->SendGetRandomValues(dataLen, &randomValues) ||
   1.104 +        randomValues.Length() == 0) {
   1.105 +      aRv.Throw(NS_ERROR_FAILURE);
   1.106 +      return;
   1.107 +    }
   1.108 +    NS_ASSERTION(dataLen == randomValues.Length(),
   1.109 +                 "Invalid length returned from parent process!");
   1.110 +    memcpy(data, randomValues.Elements(), dataLen);
   1.111 +  } else {
   1.112 +    uint8_t *buf = GetRandomValues(dataLen);
   1.113 +
   1.114 +    if (!buf) {
   1.115 +      aRv.Throw(NS_ERROR_FAILURE);
   1.116 +      return;
   1.117 +    }
   1.118 +
   1.119 +    memcpy(data, buf, dataLen);
   1.120 +    NS_Free(buf);
   1.121 +  }
   1.122 +
   1.123 +  aRetval.set(view);
   1.124 +}
   1.125 +
   1.126 +#ifndef MOZ_DISABLE_CRYPTOLEGACY
   1.127 +// Stub out the legacy nsIDOMCrypto methods. The actual
   1.128 +// implementations are in security/manager/ssl/src/nsCrypto.{cpp,h}
   1.129 +
   1.130 +NS_IMETHODIMP
   1.131 +Crypto::GetEnableSmartCardEvents(bool *aEnableSmartCardEvents)
   1.132 +{
   1.133 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.134 +}
   1.135 +
   1.136 +NS_IMETHODIMP
   1.137 +Crypto::SetEnableSmartCardEvents(bool aEnableSmartCardEvents)
   1.138 +{
   1.139 +  return NS_ERROR_NOT_IMPLEMENTED;
   1.140 +}
   1.141 +
   1.142 +bool
   1.143 +Crypto::EnableSmartCardEvents()
   1.144 +{
   1.145 +  return false;
   1.146 +}
   1.147 +
   1.148 +void
   1.149 +Crypto::SetEnableSmartCardEvents(bool aEnable, ErrorResult& aRv)
   1.150 +{
   1.151 +  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   1.152 +}
   1.153 +
   1.154 +void
   1.155 +Crypto::GetVersion(nsString& aVersion)
   1.156 +{
   1.157 +}
   1.158 +
   1.159 +mozilla::dom::CRMFObject*
   1.160 +Crypto::GenerateCRMFRequest(JSContext* aContext,
   1.161 +                            const nsCString& aReqDN,
   1.162 +                            const nsCString& aRegToken,
   1.163 +                            const nsCString& aAuthenticator,
   1.164 +                            const nsCString& aEaCert,
   1.165 +                            const nsCString& aJsCallback,
   1.166 +                            const Sequence<JS::Value>& aArgs,
   1.167 +                            ErrorResult& aRv)
   1.168 +{
   1.169 +  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   1.170 +  return nullptr;
   1.171 +}
   1.172 +
   1.173 +void
   1.174 +Crypto::ImportUserCertificates(const nsAString& aNickname,
   1.175 +                               const nsAString& aCmmfResponse,
   1.176 +                               bool aDoForcedBackup,
   1.177 +                               nsAString& aReturn,
   1.178 +                               ErrorResult& aRv)
   1.179 +{
   1.180 +  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   1.181 +}
   1.182 +
   1.183 +void
   1.184 +Crypto::SignText(JSContext* aContext,
   1.185 +                 const nsAString& aStringToSign,
   1.186 +                 const nsAString& aCaOption,
   1.187 +                 const Sequence<nsCString>& aArgs,
   1.188 +                 nsAString& aReturn)
   1.189 +
   1.190 +{
   1.191 +  aReturn.AssignLiteral("error:internalError");
   1.192 +}
   1.193 +
   1.194 +void
   1.195 +Crypto::Logout(ErrorResult& aRv)
   1.196 +{
   1.197 +  aRv.Throw(NS_ERROR_NOT_IMPLEMENTED);
   1.198 +}
   1.199 +
   1.200 +#endif
   1.201 +
   1.202 +/* static */ uint8_t*
   1.203 +Crypto::GetRandomValues(uint32_t aLength)
   1.204 +{
   1.205 +  nsCOMPtr<nsIRandomGenerator> randomGenerator;
   1.206 +  nsresult rv;
   1.207 +  randomGenerator = do_GetService("@mozilla.org/security/random-generator;1");
   1.208 +  NS_ENSURE_TRUE(randomGenerator, nullptr);
   1.209 +
   1.210 +  uint8_t* buf;
   1.211 +  rv = randomGenerator->GenerateRandomBytes(aLength, &buf);
   1.212 +
   1.213 +  NS_ENSURE_SUCCESS(rv, nullptr);
   1.214 +
   1.215 +  return buf;
   1.216 +}
   1.217 +
   1.218 +} // namespace dom
   1.219 +} // namespace mozilla

mercurial