merge mozilla-inbound to mozilla-central a=merge
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Mon, 18 Apr 2016 14:39:45 +0200
changeset 331425 6066850740cd4711ee5502fda89f422440b7c2cc
parent 331357 0ddbde569eb2bf0de98ca85452c5ac071bb3def8 (current diff)
parent 331424 f02903bd5b2c62aeb46f0f8c4003945a8d6816e6 (diff)
child 331426 d53b301a14e1dfa05324072a7159796a4f5e24c7
child 331471 755eb5d58f6f3ee4e41f9844e4491aa2bbd8e9a1
child 331500 8975734f1546f7ab475037441e9a0591af299e32
push id6048
push userkmoir@mozilla.com
push dateMon, 06 Jun 2016 19:02:08 +0000
treeherdermozilla-beta@46d72a56c57d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone48.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
merge mozilla-inbound to mozilla-central a=merge
devtools/shared/security/LocalCertService.cpp
devtools/shared/security/LocalCertService.h
devtools/shared/security/nsILocalCertService.idl
devtools/shared/security/tests/unit/test_cert.js
dom/manifest/test/test_ImageObjectProcessor_density.html
dom/u2f/NSSToken.cpp
dom/u2f/NSSToken.h
testing/web-platform/meta/cssom-view/scrollingElement.html.ini
--- a/accessible/base/nsCoreUtils.cpp
+++ b/accessible/base/nsCoreUtils.cpp
@@ -108,17 +108,17 @@ nsCoreUtils::DispatchClickEvent(nsITreeB
   tcBoxObj->GetY(&tcY);
 
   // Dispatch mouse events.
   nsWeakFrame tcFrame = tcContent->GetPrimaryFrame();
   nsIFrame* rootFrame = presShell->GetRootFrame();
 
   nsPoint offset;
   nsIWidget *rootWidget =
-    rootFrame->GetViewExternal()->GetNearestWidget(&offset);
+    rootFrame->GetView()->GetNearestWidget(&offset);
 
   RefPtr<nsPresContext> presContext = presShell->GetPresContext();
 
   int32_t cnvdX = presContext->CSSPixelsToDevPixels(tcX + x + 1) +
     presContext->AppUnitsToDevPixels(offset.x);
   int32_t cnvdY = presContext->CSSPixelsToDevPixels(tcY + y + 1) +
     presContext->AppUnitsToDevPixels(offset.y);
 
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -1611,17 +1611,17 @@ Accessible::RelationByType(RelationType 
       // If accessible is in its own Window, or is the root of a document,
       // then we should provide NODE_CHILD_OF relation so that MSAA clients
       // can easily get to true parent instead of getting to oleacc's
       // ROLE_WINDOW accessible which will prevent us from going up further
       // (because it is system generated and has no idea about the hierarchy
       // above it).
       nsIFrame *frame = GetFrame();
       if (frame) {
-        nsView *view = frame->GetViewExternal();
+        nsView *view = frame->GetView();
         if (view) {
           nsIScrollableFrame *scrollFrame = do_QueryFrame(frame);
           if (scrollFrame || view->GetWidget() || !frame->GetParent())
             rel.AppendTarget(Parent());
         }
       }
 
       return rel;
--- a/accessible/mac/RootAccessibleWrap.mm
+++ b/accessible/mac/RootAccessibleWrap.mm
@@ -35,17 +35,17 @@ RootAccessibleWrap::GetNativeType()
   NS_OBJC_END_TRY_ABORT_BLOCK_NIL;
 }
 
 void
 RootAccessibleWrap::GetNativeWidget(void** aOutView)
 {
   nsIFrame *frame = GetFrame();
   if (frame) {
-    nsView *view = frame->GetViewExternal();
+    nsView *view = frame->GetView();
     if (view) {
       nsIWidget *widget = view->GetWidget();
       if (widget) {
         *aOutView = (void**)widget->GetNativeData (NS_NATIVE_WIDGET);
         NS_ASSERTION (*aOutView,
                       "Couldn't get the native NSView parent we need to connect the accessibility hierarchy!");
       }
     }
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -138,17 +138,16 @@
 @RESPATH@/components/commandhandler.xpt
 @RESPATH@/components/commandlines.xpt
 @RESPATH@/components/composer.xpt
 @RESPATH@/components/content_events.xpt
 @RESPATH@/components/content_geckomediaplugins.xpt
 @RESPATH@/components/content_html.xpt
 @RESPATH@/components/content_xslt.xpt
 @RESPATH@/components/cookie.xpt
-@RESPATH@/components/devtools_security.xpt
 @RESPATH@/components/directory.xpt
 @RESPATH@/components/diskspacewatcher.xpt
 @RESPATH@/components/docshell.xpt
 @RESPATH@/components/dom.xpt
 @RESPATH@/components/dom_activities.xpt
 @RESPATH@/components/dom_apps.xpt
 @RESPATH@/components/dom_newapps.xpt
 @RESPATH@/components/dom_audiochannel.xpt
--- a/browser/components/BrowserComponents.manifest
+++ b/browser/components/BrowserComponents.manifest
@@ -20,29 +20,25 @@ contract @mozilla.org/uriloader/content-
 contract @mozilla.org/uriloader/content-handler;1?type=image/vnd.microsoft.icon {5d0ce354-df01-421a-83fb-7ead0990c24e} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 contract @mozilla.org/uriloader/content-handler;1?type=application/http-index-format {5d0ce354-df01-421a-83fb-7ead0990c24e} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 category command-line-handler m-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 category command-line-handler x-default @mozilla.org/browser/final-clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 category command-line-validator b-browser @mozilla.org/browser/clh;1 application={ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 
 # nsBrowserGlue.js
 
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
+# This component must restrict its registration for the app-startup category
+# to the specific list of apps that use it so it doesn't get loaded in xpcshell.
+# Thus we restrict it to these apps:
 #
 #   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
 #   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
 #   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
 
 component {eab9012e-5f74-4cbc-b2b5-a590235513cc} nsBrowserGlue.js
 contract @mozilla.org/browser/browserglue;1 {eab9012e-5f74-4cbc-b2b5-a590235513cc}
 category app-startup nsBrowserGlue service,@mozilla.org/browser/browserglue;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
 component {d8903bf6-68d5-4e97-bcd1-e4d3012f721a} nsBrowserGlue.js
 #ifndef MOZ_MULET
 contract @mozilla.org/content-permission/prompt;1 {d8903bf6-68d5-4e97-bcd1-e4d3012f721a}
 #endif
--- a/browser/components/feeds/BrowserFeeds.manifest
+++ b/browser/components/feeds/BrowserFeeds.manifest
@@ -1,21 +1,17 @@
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
+# This component must restrict its registration for the app-startup category
+# to the specific list of apps that use it so it doesn't get loaded in xpcshell.
+# Thus we restrict it to these apps:
 #
 #   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
 #   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
 #   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
 
 component {229fa115-9412-4d32-baf3-2fc407f76fb1} FeedConverter.js
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.video.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 contract @mozilla.org/streamconv;1?from=application/vnd.mozilla.maybe.audio.feed&to=*/* {229fa115-9412-4d32-baf3-2fc407f76fb1}
 component {2376201c-bbc6-472f-9b62-7548040a61c6} FeedConverter.js
 contract @mozilla.org/browser/feeds/result-service;1 {2376201c-bbc6-472f-9b62-7548040a61c6}
 component {4f91ef2e-57ba-472e-ab7a-b4999e42d6c0} FeedConverter.js
--- a/browser/components/sessionstore/nsSessionStore.manifest
+++ b/browser/components/sessionstore/nsSessionStore.manifest
@@ -1,19 +1,15 @@
-# WebappRT doesn't need these instructions, and they don't necessarily work
-# with it, but it does use a GRE directory that the GRE shares with Firefox,
-# so in order to prevent the instructions from being processed for WebappRT,
-# we need to restrict them to the applications that depend on them, i.e.:
+# This component must restrict its registration for the app-startup category
+# to the specific list of apps that use it so it doesn't get loaded in xpcshell.
+# Thus we restrict it to these apps:
 #
 #   b2g:            {3c2e2abc-06d4-11e1-ac3b-374f68613e61}
 #   browser:        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
 #   mobile/android: {aa3c5121-dab2-40e2-81ca-7ea25febc110}
 #   mobile/xul:     {a23983c0-fd0e-11dc-95ff-0800200c9a66}
 #   graphene:       {d1bfe7d9-c01e-4237-998b-7b5f960a4314}
-#
-# In theory we should do this for all these instructions, but in practice it is
-# sufficient to do it for the app-startup one, and the file is simpler that way.
 
 component {5280606b-2510-4fe0-97ef-9b5a22eafe6b} nsSessionStore.js
 contract @mozilla.org/browser/sessionstore;1 {5280606b-2510-4fe0-97ef-9b5a22eafe6b}
 component {ec7a6c20-e081-11da-8ad9-0800200c9a66} nsSessionStartup.js
 contract @mozilla.org/browser/sessionstartup;1 {ec7a6c20-e081-11da-8ad9-0800200c9a66}
 category app-startup nsSessionStartup service,@mozilla.org/browser/sessionstartup;1 application={3c2e2abc-06d4-11e1-ac3b-374f68613e61} application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} application={aa3c5121-dab2-40e2-81ca-7ea25febc110} application={a23983c0-fd0e-11dc-95ff-0800200c9a66} application={d1bfe7d9-c01e-4237-998b-7b5f960a4314}
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -159,17 +159,16 @@
 @RESPATH@/components/content_events.xpt
 @RESPATH@/components/content_html.xpt
 @RESPATH@/components/content_geckomediaplugins.xpt
 #ifdef MOZ_WEBRTC
 @RESPATH@/components/content_webrtc.xpt
 #endif
 @RESPATH@/components/content_xslt.xpt
 @RESPATH@/components/cookie.xpt
-@RESPATH@/browser/components/devtools_security.xpt
 @RESPATH@/components/directory.xpt
 @RESPATH@/components/docshell.xpt
 @RESPATH@/components/dom.xpt
 #ifdef MOZ_ACTIVITIES
 @RESPATH@/components/dom_activities.xpt
 @RESPATH@/components/dom_messages.xpt
 #endif
 @RESPATH@/components/dom_apps.xpt
--- a/config/external/nss/nss.symbols
+++ b/config/external/nss/nss.symbols
@@ -362,24 +362,26 @@ PK11_GetInternalSlot
 PK11_GetIVLength
 PK11_GetKeyData
 PK11_GetKeyGen
 PK11_GetLowLevelKeyIDForPrivateKey
 PK11_GetMechanism
 PK11_GetMinimumPwdLength
 PK11_GetModInfo
 PK11_GetNextSafe
+PK11_GetNextSymKey
 PK11_GetPadMechanism
 PK11_GetPrivateKeyNickname
 PK11_GetPrivateModulusLen
 PK11_GetSlotID
 PK11_GetSlotInfo
 PK11_GetSlotName
 PK11_GetSlotPWValues
 PK11_GetSlotSeries
+PK11_GetSymKeyNickname
 PK11_GetTokenInfo
 PK11_GetTokenName
 PK11_HashBuf
 PK11_HasRootCerts
 PK11_ImportCert
 PK11_ImportCertForKey
 PK11_ImportCRL
 PK11_ImportDERPrivateKeyInfoAndReturnKey
@@ -395,16 +397,17 @@ PK11_IsLoggedIn
 PK11_IsPresent
 PK11_IsReadOnly
 PK11_IsRemovable
 PK11_KeyForCertExists
 PK11_KeyGen
 PK11_KeyGenWithTemplate
 PK11_ListCerts
 PK11_ListCertsInSlot
+PK11_ListFixedKeysInSlot
 PK11_ListPrivateKeysInSlot
 PK11_ListPrivKeysInSlot
 PK11_LoadPrivKey
 PK11_Logout
 PK11_LogoutAll
 PK11_MakeIDFromPubKey
 PK11_MapSignKeyType
 PK11_MechanismToAlgtag
@@ -424,19 +427,21 @@ PK11_PubWrapSymKey
 PK11_RandomUpdate
 PK11_ReadRawAttribute
 PK11_ReferenceSlot
 PK11_ResetToken
 PK11SDR_Decrypt
 PK11SDR_Encrypt
 PK11_SetPasswordFunc
 PK11_SetSlotPWValues
+PK11_SetSymKeyNickname
 PK11_Sign
 PK11_SignatureLen
 PK11_SignWithMechanism
+PK11_TokenKeyGenWithFlags
 PK11_UnwrapPrivKey
 PK11_UnwrapSymKey
 PK11_UpdateSlotAttribute
 PK11_UserDisableSlot
 PK11_UserEnableSlot
 PK11_VerifyWithMechanism
 PK11_WrapPrivKey
 PK11_WrapSymKey
--- a/devtools/server/actors/webconsole.js
+++ b/devtools/server/actors/webconsole.js
@@ -1297,21 +1297,60 @@ WebConsoleActor.prototype =
         // since it's already being handled elsewhere and we are only interested
         // in initializing bindings.
         try {
           ast = Parser.reflectionAPI.parse(aString);
         } catch (ex) {
           ast = {"body": []};
         }
         for (let line of ast.body) {
-          if (line.type == "VariableDeclaration" &&
-            (line.kind == "let" || line.kind == "const")) {
-            for (let decl of line.declarations)
-              dbgWindow.forceLexicalInitializationByName(decl.id.name);
+          // Only let and const declarations put bindings into an
+          // "initializing" state.
+          if (!(line.kind == "let" || line.kind == "const"))
+                continue;
+
+          let identifiers = [];
+          for (let decl of line.declarations) {
+            switch (decl.id.type) {
+              case "Identifier":
+                // let foo = bar;
+                identifiers.push(decl.id.name);
+                break;
+              case "ArrayPattern":
+                // let [foo, bar]    = [1, 2];
+                // let [foo=99, bar] = [1, 2];
+                for (let e of decl.id.elements) {
+                    if (e.type == "Identifier") {
+                      identifiers.push(e.name);
+                    } else if (e.type == "AssignmentExpression") {
+                      identifiers.push(e.left.name);
+                    }
+                }
+                break;
+              case "ObjectPattern":
+                // let {bilbo, my}    = {bilbo: "baggins", my: "precious"};
+                // let {blah: foo}    = {blah: yabba()}
+                // let {blah: foo=99} = {blah: yabba()}
+                for (let prop of decl.id.properties) {
+                  // key
+                  if (prop.key.type == "Identifier")
+                    identifiers.push(prop.key.name);
+                  // value
+                  if (prop.value.type == "Identifier") {
+                    identifiers.push(prop.value.name);
+                  } else if (prop.value.type == "AssignmentExpression") {
+                    identifiers.push(prop.value.left.name);
+                  }
+                }
+                break;
+            }
           }
+
+          for (let name of identifiers)
+            dbgWindow.forceLexicalInitializationByName(name);
         }
       }
     }
 
     let helperResult = helpers.helperResult;
     delete helpers.evalInput;
     delete helpers.helperResult;
     delete helpers.selectedNode;
--- a/devtools/shared/security/moz.build
+++ b/devtools/shared/security/moz.build
@@ -1,26 +1,14 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
-XPIDL_SOURCES += [
-    'nsILocalCertService.idl',
-]
-
-XPIDL_MODULE = 'devtools_security'
-
-UNIFIED_SOURCES += [
-    'LocalCertService.cpp',
-]
-
-FINAL_LIBRARY = 'xul'
-
 DevToolsModules(
     'auth.js',
     'cert.js',
     'prompt.js',
     'socket.js',
 )
--- a/devtools/shared/security/tests/unit/xpcshell.ini
+++ b/devtools/shared/security/tests/unit/xpcshell.ini
@@ -3,17 +3,16 @@ tags = devtools
 head = head_dbg.js
 tail =
 firefox-appdir = browser
 skip-if = toolkit == 'gonk' && debug # Bug 1206586
 
 support-files=
   testactors.js
 
-[test_cert.js]
 [test_encryption.js]
 # Failures on B2G emulator debug, B2G emulator-x86-kk
 # See bug 1234972 and bug 1199472
 skip-if = toolkit == 'gonk' && (debug || android_version > '15')
 [test_oob_cert_auth.js]
 # Failures on B2G emulator debug, B2G emulator-x86-kk and Android opt
 # See bug 1141544, bug 1163052, bug 1166032 and bug 1241831
 skip-if = (toolkit == 'gonk' && (debug || android_version > '15')) || (toolkit == 'android' && !debug)
--- a/devtools/shared/webconsole/test/test_jsterm.html
+++ b/devtools/shared/webconsole/test/test_jsterm.html
@@ -220,31 +220,76 @@ function* doEvalWithBindingFrame() {
     "Global matches the top global with bindObjectActor");
   ok(!frameWin.temp1,
     "Global doesn't match the object's global with bindObjectActor");
 
   nextTest()
 }
 
 function* forceLexicalInit() {
-  info("test `let x = SomeError` results in x being initialized to undefined");
-  let response = yield evaluateJS("let foopie = wubbalubadubdub;");
-  checkObject(response, {
-    from: gState.actor,
-    input: "let foopie = wubbalubadubdub;",
-    result: undefined,
-  });
-  ok(response.exception, "expected exception");
-  let response2 = yield evaluateJS("foopie;");
-  checkObject(response2, {
-    from: gState.actor,
-    input: "foopie;",
-    result: undefined,
-  });
-  ok(!response2.exception, "unexpected exception");
+  info("test that failed let/const bindings are initialized to undefined");
+
+  const testData = [
+    {
+        stmt: "let foopie = wubbalubadubdub",
+        vars: ["foopie"]
+    },
+    {
+        stmt: "let {z, w={n}=null} = {}",
+        vars: ["z", "w"]
+    },
+    {
+        stmt: "let [a, b, c] = null",
+        vars: ["a", "b", "c"]
+    },
+    {
+        stmt: "const nein1 = rofl, nein2 = copter",
+        vars: ["nein1", "nein2"]
+    },
+    {
+        stmt: "const {ha} = null",
+        vars: ["ha"]
+    },
+    {
+        stmt: "const [haw=[lame]=null] = []",
+        vars: ["haw"]
+    },
+    {
+        stmt: "const [rawr, wat=[lame]=null] = []",
+        vars: ["rawr", "haw"]
+    },
+    {
+        stmt: "let {zzz: xyz=99, zwz: wb} = nexistepas()",
+        vars: ["xyz", "wb"]
+    },
+    {
+        stmt: "let {c3pdoh=101} = null",
+        vars: ["c3pdoh"]
+    }
+  ];
+
+  for (let data of testData) {
+      let response = yield evaluateJS(data.stmt);
+      checkObject(response, {
+        from: gState.actor,
+        input: data.stmt,
+        result: undefined,
+      });
+      ok(response.exception, "expected exception");
+      for (let varName of data.vars) {
+          let response2 = yield evaluateJS(varName);
+          checkObject(response2, {
+            from: gState.actor,
+            input: varName,
+            result: undefined,
+          });
+          ok(!response2.exception, "unexpected exception");
+      }
+  }
+
   nextTest();
 }
 
 function testEnd()
 {
   // If this is the first run, reload the page and do it again.
   // Otherwise, end the test.
   closeDebugger(gState, function() {
--- a/devtools/shared/webconsole/test/test_page_errors.html
+++ b/devtools/shared/webconsole/test/test_page_errors.html
@@ -77,17 +77,17 @@ function doPageErrors()
       errorMessageName: "JSMSG_NEGATIVE_REPETITION_COUNT",
       sourceName: /test_page_errors/,
       category: "chrome javascript",
       timeStamp: /^\d+$/,
       error: false,
       warning: false,
       exception: true,
     },
-    "'a'.repeat(2**28);": {
+    "'a'.repeat(2e28);": {
       errorMessage: /repeat count.*less than infinity/,
       errorMessageName: "JSMSG_RESULTING_STRING_TOO_LARGE",
       sourceName: /test_page_errors/,
       category: "chrome javascript",
       timeStamp: /^\d+$/,
       error: false,
       warning: false,
       exception: true,
--- a/dom/animation/AnimationEffectTiming.cpp
+++ b/dom/animation/AnimationEffectTiming.cpp
@@ -50,17 +50,22 @@ AnimationEffectTiming::SetEndDelay(doubl
   mTiming.mEndDelay = endDelay;
 
   PostSpecifiedTimingUpdated(mEffect);
 }
 
 void
 AnimationEffectTiming::SetFill(const FillMode& aFill)
 {
-  // TODO: Bug 1244637 - implement AnimationEffectTiming fill
+  if (mTiming.mFill == aFill) {
+    return;
+  }
+  mTiming.mFill = aFill;
+
+  PostSpecifiedTimingUpdated(mEffect);
 }
 
 void
 AnimationEffectTiming::SetIterationStart(double aIterationStart,
                                          ErrorResult& aRv)
 {
   if (mTiming.mIterationStart == aIterationStart) {
     return;
--- a/dom/base/Element.cpp
+++ b/dom/base/Element.cpp
@@ -1172,24 +1172,22 @@ Element::GetAttribute(const nsAString& a
   }
 }
 
 void
 Element::SetAttribute(const nsAString& aName,
                       const nsAString& aValue,
                       ErrorResult& aError)
 {
+  aError = nsContentUtils::CheckQName(aName, false);
+  if (aError.Failed()) {
+    return;
+  }
   const nsAttrName* name = InternalGetExistingAttrNameFromQName(aName);
-
   if (!name) {
-    aError = nsContentUtils::CheckQName(aName, false);
-    if (aError.Failed()) {
-      return;
-    }
-
     nsCOMPtr<nsIAtom> nameAtom;
     if (IsHTMLElement() && IsInHTMLDocument()) {
       nsAutoString lower;
       nsContentUtils::ASCIIToLower(aName, lower);
       nameAtom = NS_Atomize(lower);
     }
     else {
       nameAtom = NS_Atomize(aName);
--- a/dom/base/WebSocket.cpp
+++ b/dom/base/WebSocket.cpp
@@ -1240,17 +1240,17 @@ WebSocket::Constructor(const GlobalObjec
     JS::AutoFilename file;
     if (!JS::DescribeScriptedCaller(aGlobal.Context(), &file, &lineno,
                                     &column)) {
       NS_WARNING("Failed to get line number and filename in workers.");
     }
 
     RefPtr<InitRunnable> runnable =
       new InitRunnable(webSocket->mImpl, aUrl, protocolArray,
-                       nsAutoCString(file.get()), lineno, column, aRv,
+                       nsDependentCString(file.get()), lineno, column, aRv,
                        &connectionFailed);
     runnable->Dispatch(aRv);
   }
 
   if (NS_WARN_IF(aRv.Failed())) {
     return nullptr;
   }
 
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1092,39 +1092,39 @@ nsDOMWindowUtils::SendNativeTouchPoint(u
     return NS_ERROR_FAILURE;
   }
 
   if (aPressure < 0 || aPressure > 1 || aOrientation > 359) {
     return NS_ERROR_INVALID_ARG;
   }
 
   NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
-    <uint32_t, nsIWidget::TouchPointerState, ScreenIntPoint, double, uint32_t, nsIObserver*>
+    <uint32_t, nsIWidget::TouchPointerState, LayoutDeviceIntPoint, double, uint32_t, nsIObserver*>
     (widget, &nsIWidget::SynthesizeNativeTouchPoint, aPointerId,
     (nsIWidget::TouchPointerState)aTouchState,
-    ScreenIntPoint(aScreenX, aScreenY),
+    LayoutDeviceIntPoint(aScreenX, aScreenY),
     aPressure, aOrientation, aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX,
                                      int32_t aScreenY,
                                      bool aLongTap,
                                      nsIObserver* aObserver)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
     return NS_ERROR_FAILURE;
   }
 
   NS_DispatchToMainThread(NS_NewRunnableMethodWithArgs
-    <ScreenIntPoint, bool, nsIObserver*>
+    <LayoutDeviceIntPoint, bool, nsIObserver*>
     (widget, &nsIWidget::SynthesizeNativeTouchTap,
-    ScreenIntPoint(aScreenX, aScreenY), aLongTap, aObserver));
+    LayoutDeviceIntPoint(aScreenX, aScreenY), aLongTap, aObserver));
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver)
 {
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (!widget) {
--- a/dom/base/nsDocument.cpp
+++ b/dom/base/nsDocument.cpp
@@ -3173,16 +3173,26 @@ nsDocument::GetUndoManager()
     mUndoManager = new UndoManager(rootElement);
   }
 
   RefPtr<UndoManager> undoManager = mUndoManager;
   return undoManager.forget();
 }
 
 bool
+nsDocument::IsElementAnimateEnabled(JSContext* /*unused*/, JSObject* /*unused*/)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+
+  return nsContentUtils::IsCallerChrome() ||
+         Preferences::GetBool("dom.animations-api.core.enabled") ||
+         Preferences::GetBool("dom.animations-api.element-animate.enabled");
+}
+
+bool
 nsDocument::IsWebAnimationsEnabled(JSContext* /*unused*/, JSObject* /*unused*/)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   return nsContentUtils::IsCallerChrome() ||
          Preferences::GetBool("dom.animations-api.core.enabled");
 }
 
--- a/dom/base/nsDocument.h
+++ b/dom/base/nsDocument.h
@@ -781,16 +781,17 @@ public:
       nsViewManager* aViewManager,
       mozilla::StyleSetHandle aStyleSet) override;
   virtual void DeleteShell() override;
 
   virtual nsresult GetAllowPlugins(bool* aAllowPlugins) override;
 
   virtual already_AddRefed<mozilla::dom::UndoManager> GetUndoManager() override;
 
+  static bool IsElementAnimateEnabled(JSContext* aCx, JSObject* aObject);
   static bool IsWebAnimationsEnabled(JSContext* aCx, JSObject* aObject);
   virtual mozilla::dom::DocumentTimeline* Timeline() override;
   virtual void GetAnimations(
       nsTArray<RefPtr<mozilla::dom::Animation>>& aAnimations) override;
 
   virtual nsresult SetSubDocumentFor(Element* aContent,
                                      nsIDocument* aSubDoc) override;
   virtual nsIDocument* GetSubDocumentFor(nsIContent* aContent) const override;
--- a/dom/cache/DBSchema.cpp
+++ b/dom/cache/DBSchema.cpp
@@ -2153,17 +2153,17 @@ BindId(mozIStorageStatement* aState, con
   if (!aId) {
     rv = aState->BindNullByName(aName);
     if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
     return rv;
   }
 
   char idBuf[NSID_LENGTH];
   aId->ToProvidedString(idBuf);
-  rv = aState->BindUTF8StringByName(aName, nsAutoCString(idBuf));
+  rv = aState->BindUTF8StringByName(aName, nsDependentCString(idBuf));
   if (NS_WARN_IF(NS_FAILED(rv))) { return rv; }
 
   return rv;
 }
 
 nsresult
 ExtractId(mozIStorageStatement* aState, uint32_t aPos, nsID* aIdOut)
 {
--- a/dom/crypto/CryptoBuffer.cpp
+++ b/dom/crypto/CryptoBuffer.cpp
@@ -37,16 +37,23 @@ CryptoBuffer::Assign(const nsACString& a
 uint8_t*
 CryptoBuffer::Assign(const SECItem* aItem)
 {
   MOZ_ASSERT(aItem);
   return Assign(aItem->data, aItem->len);
 }
 
 uint8_t*
+CryptoBuffer::Assign(const InfallibleTArray<uint8_t>& aData)
+{
+  return ReplaceElementsAt(0, Length(), aData.Elements(), aData.Length(),
+                           fallible);
+}
+
+uint8_t*
 CryptoBuffer::Assign(const ArrayBuffer& aData)
 {
   aData.ComputeLengthAndData();
   return Assign(aData.Data(), aData.Length());
 }
 
 uint8_t*
 CryptoBuffer::Assign(const ArrayBufferView& aData)
@@ -80,16 +87,29 @@ CryptoBuffer::Assign(const OwningArrayBu
   }
 
   // If your union is uninitialized, something's wrong
   MOZ_ASSERT(false);
   Clear();
   return nullptr;
 }
 
+uint8_t*
+CryptoBuffer::AppendSECItem(const SECItem* aItem)
+{
+  MOZ_ASSERT(aItem);
+  return AppendElements(aItem->data, aItem->len, fallible);
+}
+
+uint8_t*
+CryptoBuffer::AppendSECItem(const SECItem& aItem)
+{
+  return AppendElements(aItem.data, aItem.len, fallible);
+}
+
 // Helpers to encode/decode JWK's special flavor of Base64
 // * No whitespace
 // * No padding
 // * URL-safe character set
 nsresult
 CryptoBuffer::FromJwkBase64(const nsString& aBase64)
 {
   NS_ConvertUTF16toUTF8 temp(aBase64);
@@ -166,16 +186,33 @@ CryptoBuffer::ToSECItem(PLArenaPool *aAr
 }
 
 JSObject*
 CryptoBuffer::ToUint8Array(JSContext* aCx) const
 {
   return Uint8Array::Create(aCx, Length(), Elements());
 }
 
+bool
+CryptoBuffer::ToNewUnsignedBuffer(uint8_t** aBuf, uint32_t* aBufLen) const
+{
+  MOZ_ASSERT(aBuf);
+  MOZ_ASSERT(aBufLen);
+
+  uint32_t dataLen = Length();
+  uint8_t* tmp = reinterpret_cast<uint8_t*>(moz_xmalloc(dataLen));
+  if (NS_WARN_IF(!tmp)) {
+    return false;
+  }
+
+  memcpy(tmp, Elements(), dataLen);
+  *aBuf = tmp;
+  *aBufLen = dataLen;
+  return true;
+}
 
 // "BigInt" comes from the WebCrypto spec
 // ("unsigned long" isn't very "big", of course)
 // Likewise, the spec calls for big-endian ints
 bool
 CryptoBuffer::GetBigIntValue(unsigned long& aRetVal)
 {
   if (Length() > sizeof(aRetVal)) {
--- a/dom/crypto/CryptoBuffer.h
+++ b/dom/crypto/CryptoBuffer.h
@@ -19,35 +19,40 @@ class OwningArrayBufferViewOrArrayBuffer
 
 class CryptoBuffer : public FallibleTArray<uint8_t>
 {
 public:
   uint8_t* Assign(const CryptoBuffer& aData);
   uint8_t* Assign(const uint8_t* aData, uint32_t aLength);
   uint8_t* Assign(const nsACString& aString);
   uint8_t* Assign(const SECItem* aItem);
+  uint8_t* Assign(const InfallibleTArray<uint8_t>& aData);
   uint8_t* Assign(const ArrayBuffer& aData);
   uint8_t* Assign(const ArrayBufferView& aData);
   uint8_t* Assign(const ArrayBufferViewOrArrayBuffer& aData);
   uint8_t* Assign(const OwningArrayBufferViewOrArrayBuffer& aData);
 
+  uint8_t* AppendSECItem(const SECItem* aItem);
+  uint8_t* AppendSECItem(const SECItem& aItem);
+
   template<typename T,
            JSObject* UnwrapArray(JSObject*),
            void GetLengthAndDataAndSharedness(JSObject*, uint32_t*, bool*, T**)>
   uint8_t* Assign(const TypedArray_base<T, UnwrapArray,
                                         GetLengthAndDataAndSharedness>& aArray)
   {
     aArray.ComputeLengthAndData();
     return Assign(aArray.Data(), aArray.Length());
   }
 
   nsresult FromJwkBase64(const nsString& aBase64);
   nsresult ToJwkBase64(nsString& aBase64);
   bool ToSECItem(PLArenaPool* aArena, SECItem* aItem) const;
   JSObject* ToUint8Array(JSContext* aCx) const;
+  bool ToNewUnsignedBuffer(uint8_t** aBuf, uint32_t* aBufLen) const;
 
   bool GetBigIntValue(unsigned long& aRetVal);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_CryptoBuffer_h
--- a/dom/events/WheelHandlingHelper.cpp
+++ b/dom/events/WheelHandlingHelper.cpp
@@ -230,17 +230,17 @@ WheelTransaction::OnEvent(WidgetEvent* a
       return;
     case eMouseMove:
     case eDragOver: {
       WidgetMouseEvent* mouseEvent = aEvent->AsMouseEvent();
       if (mouseEvent->IsReal()) {
         // If the cursor is moving to be outside the frame,
         // terminate the scrollwheel transaction.
         nsIntPoint pt = GetScreenPoint(mouseEvent);
-        nsIntRect r = sTargetFrame->GetScreenRectExternal();
+        nsIntRect r = sTargetFrame->GetScreenRect();
         if (!r.Contains(pt)) {
           EndTransaction();
           return;
         }
 
         // If the cursor is moving inside the frame, and it is less than
         // ignoremovedelay milliseconds since the last scroll operation, ignore
         // the mouse move; otherwise, record the current mouse move time to be
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -134,16 +134,17 @@
 #include "nsIFormProcessor.h"
 #include "nsIGfxInfo.h"
 #include "nsIIdleService.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMemoryInfoDumper.h"
 #include "nsIMemoryReporter.h"
 #include "nsIMozBrowserFrame.h"
 #include "nsIMutable.h"
+#include "nsINSSU2FToken.h"
 #include "nsIObserverService.h"
 #include "nsIPresShell.h"
 #include "nsIRemoteWindowContext.h"
 #include "nsIScriptError.h"
 #include "nsIScriptSecurityManager.h"
 #include "nsISiteSecurityService.h"
 #include "nsISpellChecker.h"
 #include "nsISupportsPrimitives.h"
@@ -4242,16 +4243,101 @@ ContentParent::RecvSetURITitle(const URI
   nsCOMPtr<IHistory> history = services::GetHistoryService();
   if (history) {
     history->SetURITitle(ourURI, title);
   }
   return true;
 }
 
 bool
+ContentParent::RecvNSSU2FTokenIsCompatibleVersion(const nsString& aVersion,
+                                                  bool* aIsCompatible)
+{
+  MOZ_ASSERT(aIsCompatible);
+
+  nsCOMPtr<nsINSSU2FToken> nssToken(do_GetService(NS_NSSU2FTOKEN_CONTRACTID));
+  if (NS_WARN_IF(!nssToken)) {
+    return false;
+  }
+
+  nsresult rv = nssToken->IsCompatibleVersion(aVersion, aIsCompatible);
+  return NS_SUCCEEDED(rv);
+}
+
+bool
+ContentParent::RecvNSSU2FTokenIsRegistered(nsTArray<uint8_t>&& aKeyHandle,
+                                           bool* aIsValidKeyHandle)
+{
+  MOZ_ASSERT(aIsValidKeyHandle);
+
+  nsCOMPtr<nsINSSU2FToken> nssToken(do_GetService(NS_NSSU2FTOKEN_CONTRACTID));
+  if (NS_WARN_IF(!nssToken)) {
+    return false;
+  }
+
+  nsresult rv = nssToken->IsRegistered(aKeyHandle.Elements(), aKeyHandle.Length(),
+                                       aIsValidKeyHandle);
+  return  NS_SUCCEEDED(rv);
+}
+
+bool
+ContentParent::RecvNSSU2FTokenRegister(nsTArray<uint8_t>&& aApplication,
+                                       nsTArray<uint8_t>&& aChallenge,
+                                       nsTArray<uint8_t>* aRegistration)
+{
+  MOZ_ASSERT(aRegistration);
+
+  nsCOMPtr<nsINSSU2FToken> nssToken(do_GetService(NS_NSSU2FTOKEN_CONTRACTID));
+  if (NS_WARN_IF(!nssToken)) {
+    return false;
+  }
+  uint8_t* buffer;
+  uint32_t bufferlen;
+  nsresult rv = nssToken->Register(aApplication.Elements(), aApplication.Length(),
+                                   aChallenge.Elements(), aChallenge.Length(),
+                                   &buffer, &bufferlen);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  MOZ_ASSERT(buffer);
+  aRegistration->ReplaceElementsAt(0, aRegistration->Length(), buffer, bufferlen);
+  free(buffer);
+  return NS_SUCCEEDED(rv);
+}
+
+bool
+ContentParent::RecvNSSU2FTokenSign(nsTArray<uint8_t>&& aApplication,
+                                   nsTArray<uint8_t>&& aChallenge,
+                                   nsTArray<uint8_t>&& aKeyHandle,
+                                   nsTArray<uint8_t>* aSignature)
+{
+  MOZ_ASSERT(aSignature);
+
+  nsCOMPtr<nsINSSU2FToken> nssToken(do_GetService(NS_NSSU2FTOKEN_CONTRACTID));
+  if (NS_WARN_IF(!nssToken)) {
+    return false;
+  }
+  uint8_t* buffer;
+  uint32_t bufferlen;
+  nsresult rv = nssToken->Sign(aApplication.Elements(), aApplication.Length(),
+                               aChallenge.Elements(), aChallenge.Length(),
+                               aKeyHandle.Elements(), aKeyHandle.Length(),
+                               &buffer, &bufferlen);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return false;
+  }
+
+  MOZ_ASSERT(buffer);
+  aSignature->ReplaceElementsAt(0, aSignature->Length(), buffer, bufferlen);
+  free(buffer);
+  return NS_SUCCEEDED(rv);
+}
+
+bool
 ContentParent::RecvGetSystemMemory(const uint64_t& aGetterId)
 {
   uint32_t memoryTotal = 0;
 
 #if defined(XP_LINUX)
   memoryTotal = mozilla::hal::GetTotalSystemMemoryLevel();
 #endif
 
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -744,16 +744,31 @@ private:
 
   virtual bool
   RecvPBlobConstructor(PBlobParent* aActor,
                        const BlobConstructorParams& params) override;
 
   virtual bool
   DeallocPCrashReporterParent(PCrashReporterParent* crashreporter) override;
 
+  virtual bool RecvNSSU2FTokenIsCompatibleVersion(const nsString& aVersion,
+                                                  bool* aIsCompatible) override;
+
+  virtual bool RecvNSSU2FTokenIsRegistered(nsTArray<uint8_t>&& aKeyHandle,
+                                           bool* aIsValidKeyHandle) override;
+
+  virtual bool RecvNSSU2FTokenRegister(nsTArray<uint8_t>&& aApplication,
+                                       nsTArray<uint8_t>&& aChallenge,
+                                       nsTArray<uint8_t>* aRegistration) override;
+
+  virtual bool RecvNSSU2FTokenSign(nsTArray<uint8_t>&& aApplication,
+                                   nsTArray<uint8_t>&& aChallenge,
+                                   nsTArray<uint8_t>&& aKeyHandle,
+                                   nsTArray<uint8_t>* aSignature) override;
+
   virtual bool RecvIsSecureURI(const uint32_t& aType, const URIParams& aURI,
                                const uint32_t& aFlags, bool* aIsSecureURI) override;
 
   virtual bool RecvAccumulateMixedContentHSTS(const URIParams& aURI,
                                               const bool& aActive) override;
 
   virtual bool DeallocPHalParent(PHalParent*) override;
 
--- a/dom/ipc/PBrowser.ipdl
+++ b/dom/ipc/PBrowser.ipdl
@@ -457,21 +457,21 @@ parent:
                                            double aDeltaX,
                                            double aDeltaY,
                                            double aDeltaZ,
                                            uint32_t aModifierFlags,
                                            uint32_t aAdditionalFlags,
                                            uint64_t aObserverId);
     async SynthesizeNativeTouchPoint(uint32_t aPointerId,
                                      TouchPointerState aPointerState,
-                                     ScreenIntPoint aPointerScreenPoint,
+                                     LayoutDeviceIntPoint aPoint,
                                      double aPointerPressure,
                                      uint32_t aPointerOrientation,
                                      uint64_t aObserverId);
-    async SynthesizeNativeTouchTap(ScreenIntPoint aPointerScreenPoint,
+    async SynthesizeNativeTouchTap(LayoutDeviceIntPoint aPoint,
                                    bool aLongTap,
                                    uint64_t aObserverId);
     async ClearNativeTouchSequence(uint64_t aObserverId);
 
     sync GetTabCount() returns (uint32_t value);
 child:
     async NativeSynthesisResponse(uint64_t aObserverId, nsCString aResponse);
 
--- a/dom/ipc/PContent.ipdl
+++ b/dom/ipc/PContent.ipdl
@@ -759,16 +759,60 @@ parent:
 
     async PJavaScript();
 
     async PRemoteSpellcheckEngine();
     async PDeviceStorageRequest(DeviceStorageParams params);
 
     sync PCrashReporter(NativeThreadId tid, uint32_t processType);
 
+    /**
+     * Is this token compatible with the provided version?
+     *
+     * |version| The offered version to test
+     * Returns |True| if the offered version is compatible
+     */
+    sync NSSU2FTokenIsCompatibleVersion(nsString version)
+        returns (bool result);
+
+    /**
+     * Return whether the provided KeyHandle belongs to this Token
+     *
+     * |keyHandle| Key Handle to evaluate.
+     * Returns |True| if the Key Handle is ours.
+     */
+    sync NSSU2FTokenIsRegistered(uint8_t[] keyHandle)
+        returns (bool isValidKeyHandle);
+
+    /**
+     * Generates a public/private keypair for the provided application
+     * and challenge, returning the pubkey, challenge response, and
+     * key handle in the registration data.
+     *
+     * |application| The FIDO Application data to associate with the key.
+     * |challenge| The Challenge to satisfy in the response.
+     * |registration| An array containing the pubkey, challenge response,
+     *                     and key handle.
+     */
+    sync NSSU2FTokenRegister(uint8_t[] application, uint8_t[] challenge)
+        returns (uint8_t[] registration);
+
+    /**
+     * Creates a signature over the "param" arguments using the private key
+     * provided in the key handle argument.
+     *
+     * |application| The FIDO Application data to associate with the key.
+     * |challenge| The Challenge to satisfy in the response.
+     * |keyHandle| The Key Handle opaque object to use.
+     * |signature| The resulting signature.
+     */
+    sync NSSU2FTokenSign(uint8_t[] application, uint8_t[] challenge,
+                         uint8_t[] keyHandle)
+        returns (uint8_t[] signature);
+
     async GetSystemMemory(uint64_t getterId);
 
     sync IsSecureURI(uint32_t type, URIParams uri, uint32_t flags)
         returns (bool isSecureURI);
 
     async AccumulateMixedContentHSTS(URIParams uri, bool active);
 
     sync GetLookAndFeelCache()
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -1457,40 +1457,39 @@ TabParent::RecvSynthesizeNativeMouseScro
       responder.GetObserver());
   }
   return true;
 }
 
 bool
 TabParent::RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId,
                                           const TouchPointerState& aPointerState,
-                                          const ScreenIntPoint& aPointerScreenPoint,
+                                          const LayoutDeviceIntPoint& aPoint,
                                           const double& aPointerPressure,
                                           const uint32_t& aPointerOrientation,
                                           const uint64_t& aObserverId)
 {
   AutoSynthesizedEventResponder responder(this, aObserverId, "touchpoint");
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (widget) {
-    widget->SynthesizeNativeTouchPoint(aPointerId, aPointerState, aPointerScreenPoint,
+    widget->SynthesizeNativeTouchPoint(aPointerId, aPointerState, aPoint,
       aPointerPressure, aPointerOrientation, responder.GetObserver());
   }
   return true;
 }
 
 bool
-TabParent::RecvSynthesizeNativeTouchTap(const ScreenIntPoint& aPointerScreenPoint,
+TabParent::RecvSynthesizeNativeTouchTap(const LayoutDeviceIntPoint& aPoint,
                                         const bool& aLongTap,
                                         const uint64_t& aObserverId)
 {
   AutoSynthesizedEventResponder responder(this, aObserverId, "touchtap");
   nsCOMPtr<nsIWidget> widget = GetWidget();
   if (widget) {
-    widget->SynthesizeNativeTouchTap(aPointerScreenPoint, aLongTap,
-      responder.GetObserver());
+    widget->SynthesizeNativeTouchTap(aPoint, aLongTap, responder.GetObserver());
   }
   return true;
 }
 
 bool
 TabParent::RecvClearNativeTouchSequence(const uint64_t& aObserverId)
 {
   AutoSynthesizedEventResponder responder(this, aObserverId, "cleartouch");
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -392,23 +392,23 @@ public:
                                        const double& aDeltaZ,
                                        const uint32_t& aModifierFlags,
                                        const uint32_t& aAdditionalFlags,
                                        const uint64_t& aObserverId) override;
 
   virtual bool
   RecvSynthesizeNativeTouchPoint(const uint32_t& aPointerId,
                                  const TouchPointerState& aPointerState,
-                                 const ScreenIntPoint& aPointerScreenPoint,
+                                 const LayoutDeviceIntPoint& aPoint,
                                  const double& aPointerPressure,
                                  const uint32_t& aPointerOrientation,
                                  const uint64_t& aObserverId) override;
 
   virtual bool
-  RecvSynthesizeNativeTouchTap(const ScreenIntPoint& aPointerScreenPoint,
+  RecvSynthesizeNativeTouchTap(const LayoutDeviceIntPoint& aPoint,
                                const bool& aLongTap,
                                const uint64_t& aObserverId) override;
 
   virtual bool
   RecvClearNativeTouchSequence(const uint64_t& aObserverId) override;
 
   void SendMouseEvent(const nsAString& aType, float aX, float aY,
                       int32_t aButton, int32_t aClickCount,
--- a/dom/manifest/ImageObjectProcessor.jsm
+++ b/dom/manifest/ImageObjectProcessor.jsm
@@ -70,17 +70,16 @@ ImageObjectProcessor.prototype.process =
   }
   return images;
 
   function toImageObject(aImageSpec) {
     return {
       'src': processSrcMember(aImageSpec, aBaseURL),
       'type': processTypeMember(aImageSpec),
       'sizes': processSizesMember(aImageSpec),
-      'density': processDensityMember(aImageSpec),
       'background_color': processBackgroundColorMember(aImageSpec)
     };
   }
 
   function processTypeMember(aImage) {
     const charset = {};
     const hadCharset = {};
     const spec = {
@@ -92,23 +91,16 @@ ImageObjectProcessor.prototype.process =
     };
     let value = extractor.extractValue(spec);
     if (value) {
       value = netutil.parseRequestContentType(value, charset, hadCharset);
     }
     return value || undefined;
   }
 
-  function processDensityMember(aImage) {
-    const value = parseFloat(aImage.density);
-    const validNum = Number.isNaN(value) || value === +Infinity || value <=
-      0;
-    return (validNum) ? 1.0 : value;
-  }
-
   function processSrcMember(aImage, aBaseURL) {
     const spec = {
       objectName: 'image',
       object: aImage,
       property: 'src',
       expectedType: 'string',
       trim: false
     };
--- a/dom/manifest/test/mochitest.ini
+++ b/dom/manifest/test/mochitest.ini
@@ -1,15 +1,14 @@
 [DEFAULT]
 support-files =
 	common.js
 	resource.sjs
 	manifestLoader.html
 [test_ImageObjectProcessor_background_color.html]
-[test_ImageObjectProcessor_density.html]
 [test_ImageObjectProcessor_sizes.html]
 [test_ImageObjectProcessor_src.html]
 [test_ImageObjectProcessor_type.html]
 [test_ManifestProcessor_background_color.html]
 [test_ManifestProcessor_dir.html]
 [test_ManifestProcessor_display.html]
 [test_ManifestProcessor_icons.html]
 [test_ManifestProcessor_JSON.html]
deleted file mode 100644
--- a/dom/manifest/test/test_ImageObjectProcessor_density.html
+++ /dev/null
@@ -1,57 +0,0 @@
-<!DOCTYPE HTML>
-<html>
-<!--
-https://bugzilla.mozilla.org/show_bug.cgi?id=1079453
--->
-<head>
-  <meta charset="utf-8">
-  <title>Test for Bug 1079453</title>
-  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
-  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
-  <script src="common.js"></script>
-  <script>
-/**
- * Image object density member
- * https://w3c.github.io/manifest/#density-member
- **/
-'use strict';
-
-var testIcon = {
-  icons: [{
-    src: 'test',
-    density: undefined
-  }]
-};
-
-var iconDensityValueTests = [null, {},
-  [], false, '', -0, '-0', -1.0000, -123131132, -1.2e+200,
-  'Infinity', '-Infinity',
-  '-1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
-  '1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
-];
-
-iconDensityValueTests.forEach((density) => {
-  var expected = `Expect density to default to 1.0.`;
-  testIcon.icons[0].density = density;
-  data.jsonText = JSON.stringify(testIcon);
-  var result = processor.process(data);
-  is(result.icons[0].density, 1.0, expected);
-});
-
-testIcon = {
-  icons: [{
-    src: 'test',
-    density: undefined
-  }]
-};
-
-var parseFloatTests = [3.14, '3.14', `${whiteSpace}3.14${whiteSpace}`, 12e300];
-parseFloatTests.forEach((testNumber) => {
-  var expected = `Expect density to be ${parseFloat(testNumber)}.`;
-  testIcon.icons[0].density = testNumber;
-  data.jsonText = JSON.stringify(testIcon);
-  var result = processor.process(data);
-  is(result.icons[0].density, parseFloat(testNumber), expected);
-});
-  </script>
-</head>
--- a/dom/manifest/test/test_ImageObjectProcessor_src.html
+++ b/dom/manifest/test/test_ImageObjectProcessor_src.html
@@ -18,23 +18,20 @@ https://bugzilla.mozilla.org/show_bug.cg
 var noSrc = {
   icons: [{}, {
     src: []
   }, {
     src: {}
   }, {
     src: null
   }, {
-    density: '1'
-  }, {
     type: 'image/jpg'
   }, {
     sizes: '1x1,2x2'
   }, {
-    density: '1',
     sizes: 'any',
     type: 'image/jpg'
   }]
 };
 
 var expected = `Expect icons without a src prop to be filtered out.`;
 data.jsonText = JSON.stringify(noSrc);
 var result = processor.process(data);
@@ -72,17 +69,16 @@ var result = processor.process(data);
 is(typeof result.icons[0].src, "string", expected);
 
 var expected = `Expect only icons with a src prop to be kept.`;
 var withSrc = {
   icons: [{
     src: 'pass'
   }, {
     src: 'pass',
-    density: 1
   }, {}, {
     foo: 'foo'
   }]
 };
 data.jsonText = JSON.stringify(withSrc);
 var result = processor.process(data);
 is(result.icons.length, 2, expected);
 
--- a/dom/media/MediaInfo.h
+++ b/dom/media/MediaInfo.h
@@ -499,16 +499,20 @@ public:
       : mChannelMap(0)
       , mValid(false)
     {}
     explicit ChannelLayout(uint32_t aChannels)
       : ChannelLayout(aChannels, SMPTEDefault(aChannels))
     {}
     ChannelLayout(uint32_t aChannels, const Channel* aConfig)
     {
+      if (!aConfig) {
+        mValid = false;
+        return;
+      }
       mChannels.AppendElements(aConfig, aChannels);
       UpdateChannelMap();
     }
     bool operator==(const ChannelLayout& aOther) const
     {
       return mChannels == aOther.mChannels;
     }
     bool operator!=(const ChannelLayout& aOther) const
--- a/dom/media/eme/MediaKeySystemAccessManager.cpp
+++ b/dom/media/eme/MediaKeySystemAccessManager.cpp
@@ -113,17 +113,18 @@ MediaKeySystemAccessManager::Request(Det
                       minCdmVersion,
                       MediaKeySystemStatusValues::strings[(size_t)status].value,
                       cdmVersion.get(),
                       message.get());
   LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg));
 
   if ((status == MediaKeySystemStatus::Cdm_not_installed ||
        status == MediaKeySystemStatus::Cdm_insufficient_version) &&
-      keySystem.EqualsLiteral("com.adobe.primetime")) {
+      (keySystem.EqualsLiteral("com.adobe.primetime") ||
+       keySystem.EqualsLiteral("com.widevine.alpha"))) {
     // These are cases which could be resolved by downloading a new(er) CDM.
     // When we send the status to chrome, chrome's GMPProvider will attempt to
     // download or update the CDM. In AwaitInstall() we add listeners to wait
     // for the update to complete, and we'll call this function again with
     // aType==Subsequent once the download has completed and the GMPService
     // has had a new plugin added. AwaitInstall() sets a timer to fail if the
     // update/download takes too long or fails.
     if (aType == RequestType::Initial &&
--- a/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
+++ b/dom/media/platforms/wmf/WMFVideoMFTManager.cpp
@@ -229,17 +229,18 @@ WMFVideoMFTManager::Init()
 
   return success;
 }
 
 bool
 WMFVideoMFTManager::InitInternal(bool aForceD3D9)
 {
   mUseHwAccel = false; // default value; changed if D3D setup succeeds.
-  bool useDxva = InitializeDXVA(aForceD3D9);
+  bool useDxva = InitializeDXVA(aForceD3D9 ||
+                                mStreamType == VP8 || mStreamType == VP9);
 
   RefPtr<MFTDecoder> decoder(new MFTDecoder());
 
   HRESULT hr = decoder->Create(GetMFTGUID());
   NS_ENSURE_TRUE(SUCCEEDED(hr), false);
 
   RefPtr<IMFAttributes> attr(decoder->GetAttributes());
   UINT32 aware = 0;
deleted file mode 100644
--- a/dom/u2f/NSSToken.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "NSSToken.h"
-
-#include "nsNSSComponent.h"
-#include "pk11pub.h"
-
-namespace mozilla {
-namespace dom {
-
-const nsString NSSToken::mVersion = NS_LITERAL_STRING("U2F_V2");
-
-const uint32_t kParamLen = 32;
-const uint32_t kPublicKeyLen = 65;
-const uint32_t kSignedDataLen = (2 * kParamLen) + 1 + 4;
-
-NSSToken::NSSToken()
-  : mInitialized(false)
-  , mMutex("NSSToken::mMutex")
-{}
-
-NSSToken::~NSSToken()
-{
-  nsNSSShutDownPreventionLock locker;
-
-  if (isAlreadyShutDown()) {
-    return;
-  }
-
-  destructorSafeDestroyNSSReference();
-  shutdown(calledFromObject);
-}
-
-void
-NSSToken::virtualDestroyNSSReference()
-{
-  destructorSafeDestroyNSSReference();
-}
-
-void
-NSSToken::destructorSafeDestroyNSSReference()
-{
-  mSlot = nullptr;
-}
-
-nsresult
-NSSToken::Init()
-{
-  MOZ_ASSERT(!mInitialized);
-  if (mInitialized) {
-    return NS_OK;
-  }
-
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  MutexAutoLock lock(mMutex);
-
-  if (!EnsureNSSInitializedChromeOrContent()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  mSlot = PK11_GetInternalSlot();
-  if (!mSlot.get()) {
-    return NS_ERROR_FAILURE;
-  }
-
-  mInitialized = true;
-  return NS_OK;
-}
-
-bool
-NSSToken::IsCompatibleVersion(const nsString& aVersionParam) const
-{
-  MOZ_ASSERT(mInitialized);
-  return mVersion == aVersionParam;
-}
-
-/*
- * IsRegistered determines if the provided key handle is usable by this token.
- */
-bool
-NSSToken::IsRegistered(const CryptoBuffer& aKeyHandle) const
-{
-  MOZ_ASSERT(mInitialized);
-  return false;
-}
-
-/*
- * A U2F Register operation causes a new key pair to be generated by the token.
- * The token then returns the public key of the key pair, and a handle to the
- * private key.  The input parameters are used only for attestation, which this
- * token does not provide.  (We'll see how that works!)
- *
- * The format of the return registration data is as follows:
- *
- * Bytes  Value
- *   1    0x05
- *  65    public key
- *   1    key handle length
- *   *    key handle
- *   *    attestation certificate (omitted for now)
- *   *    attestation signature (omitted for now)
- *
- */
-nsresult
-NSSToken::Register(const CryptoBuffer& /* aChallengeParam */,
-                   const CryptoBuffer& /* aApplicationParam */,
-                   CryptoBuffer& aRegistrationData)
-{
-  MOZ_ASSERT(mInitialized);
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  MutexAutoLock lock(mMutex);
-
-  if (!mInitialized) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  return NS_OK;
-}
-
-/*
- * A U2F Sign operation creates a signature over the "param" arguments (plus
- * some other stuff) using the private key indicated in the key handle argument.
- *
- * The format of the signed data is as follows:
- *
- *  32    Application parameter
- *   1    User presence (0x01)
- *   4    Counter
- *  32    Challenge parameter
- *
- * The format of the signature data is as follows:
- *
- *   1    User presence
- *   4    Counter
- *   *    Signature
- *
- */
-nsresult
-NSSToken::Sign(const CryptoBuffer& aApplicationParam,
-               const CryptoBuffer& aChallengeParam,
-               const CryptoBuffer& aKeyHandle,
-               CryptoBuffer& aSignatureData)
-{
-  MOZ_ASSERT(mInitialized);
-  nsNSSShutDownPreventionLock locker;
-  if (isAlreadyShutDown()) {
-    return NS_ERROR_NOT_AVAILABLE;
-  }
-
-  MutexAutoLock lock(mMutex);
-
-  if (!mInitialized) {
-    return NS_ERROR_NOT_INITIALIZED;
-  }
-
-  return NS_OK;
-}
-
-} // namespace dom
-} // namespace mozilla
deleted file mode 100644
--- a/dom/u2f/NSSToken.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
-/* vim:set ts=2 sw=2 sts=2 et cindent: */
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#ifndef mozilla_dom_NSSToken_h
-#define mozilla_dom_NSSToken_h
-
-#include "mozilla/dom/CryptoBuffer.h"
-#include "mozilla/Mutex.h"
-#include "nsNSSShutDown.h"
-#include "ScopedNSSTypes.h"
-
-namespace mozilla {
-namespace dom {
-
-// NSSToken will support FIDO U2F operations using NSS for the crypto layer.
-// This is a stub. It will be implemented in bug 1244960.
-class NSSToken final : public nsNSSShutDownObject
-{
-public:
-  NSSToken();
-
-  ~NSSToken();
-
-  nsresult Init();
-
-  bool IsCompatibleVersion(const nsString& aVersionParam) const;
-
-  bool IsRegistered(const CryptoBuffer& aKeyHandle) const;
-
-  nsresult Register(const CryptoBuffer& aApplicationParam,
-                    const CryptoBuffer& aChallengeParam,
-                    CryptoBuffer& aRegistrationData);
-
-  nsresult Sign(const CryptoBuffer& aApplicationParam,
-                const CryptoBuffer& aChallengeParam,
-                const CryptoBuffer& aKeyHandle,
-                CryptoBuffer& aSignatureData);
-
-  // For nsNSSShutDownObject
-  virtual void virtualDestroyNSSReference() override;
-  void destructorSafeDestroyNSSReference();
-
-private:
-  bool mInitialized;
-  ScopedPK11SlotInfo mSlot;
-  mozilla::Mutex mMutex;
-
-  static const nsString mVersion;
-};
-
-} // namespace dom
-} // namespace mozilla
-
-#endif // mozilla_dom_NSSToken_h
--- a/dom/u2f/U2F.cpp
+++ b/dom/u2f/U2F.cpp
@@ -1,58 +1,65 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim:set ts=2 sw=2 sts=2 et cindent: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
+#include "hasht.h"
+#include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/CryptoBuffer.h"
 #include "mozilla/dom/U2F.h"
 #include "mozilla/dom/U2FBinding.h"
 #include "mozilla/Preferences.h"
 #include "nsContentUtils.h"
 #include "nsIEffectiveTLDService.h"
+#include "nsNetCID.h"
+#include "nsNSSComponent.h"
 #include "nsURLParsers.h"
-#include "nsNetCID.h"
 #include "pk11pub.h"
 
+using mozilla::dom::ContentChild;
+
 namespace mozilla {
 namespace dom {
 
 // These enumerations are defined in the FIDO U2F Javascript API under the
 // interface "ErrorCode" as constant integers, and thus in the U2F.webidl file.
 // Any changes to these must occur in both locations.
 enum class ErrorCode {
   OK = 0,
   OTHER_ERROR = 1,
   BAD_REQUEST = 2,
   CONFIGURATION_UNSUPPORTED = 3,
   DEVICE_INELIGIBLE = 4,
   TIMEOUT = 5
 };
 
-#define PREF_U2F_SOFTTOKEN_ENABLED "security.webauth.u2f.softtoken"
-#define PREF_U2F_USBTOKEN_ENABLED  "security.webauth.u2f.usbtoken"
+#define PREF_U2F_SOFTTOKEN_ENABLED "security.webauth.u2f_enable_softtoken"
+#define PREF_U2F_USBTOKEN_ENABLED  "security.webauth.u2f_enable_usbtoken"
 
-const nsString
-U2F::FinishEnrollment = NS_LITERAL_STRING("navigator.id.finishEnrollment");
+const nsString U2F::FinishEnrollment =
+  NS_LITERAL_STRING("navigator.id.finishEnrollment");
 
-const nsString
-U2F::GetAssertion = NS_LITERAL_STRING("navigator.id.getAssertion");
+const nsString U2F::GetAssertion =
+  NS_LITERAL_STRING("navigator.id.getAssertion");
 
 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(U2F)
   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
   NS_INTERFACE_MAP_ENTRY(nsISupports)
 NS_INTERFACE_MAP_END
 
 NS_IMPL_CYCLE_COLLECTING_ADDREF(U2F)
 NS_IMPL_CYCLE_COLLECTING_RELEASE(U2F)
 
 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(U2F, mParent)
 
+static mozilla::LazyLogModule gU2FLog("fido_u2f");
+
 U2F::U2F()
 {}
 
 U2F::~U2F()
 {
   nsNSSShutDownPreventionLock locker;
 
   if (isAlreadyShutDown()) {
@@ -83,31 +90,141 @@ U2F::Init(nsPIDOMWindowInner* aParent, E
     return;
   }
 
   if (NS_WARN_IF(mOrigin.IsEmpty())) {
     return;
   }
 
   if (!EnsureNSSInitializedChromeOrContent()) {
+    MOZ_LOG(gU2FLog, LogLevel::Debug, ("Failed to get NSS context for U2F"));
+    aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
-  aRv = mSoftToken.Init();
-  if (NS_WARN_IF(aRv.Failed())) {
-    return;
+  if (XRE_IsParentProcess()) {
+    mNSSToken = do_GetService(NS_NSSU2FTOKEN_CONTRACTID);
+    if (NS_WARN_IF(!mNSSToken)) {
+      aRv.Throw(NS_ERROR_FAILURE);
+      return;
+    }
   }
 
   aRv = mUSBToken.Init();
   if (NS_WARN_IF(aRv.Failed())) {
     return;
   }
 }
 
 nsresult
+U2F::NSSTokenIsCompatible(const nsString& aVersionString, bool* aIsCompatible)
+{
+  MOZ_ASSERT(aIsCompatible);
+
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(mNSSToken);
+    return mNSSToken->IsCompatibleVersion(aVersionString, aIsCompatible);
+  }
+
+  ContentChild* cc = ContentChild::GetSingleton();
+  MOZ_ASSERT(cc);
+  if (!cc->SendNSSU2FTokenIsCompatibleVersion(aVersionString, aIsCompatible)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+nsresult
+U2F::NSSTokenIsRegistered(CryptoBuffer& aKeyHandle, bool* aIsRegistered)
+{
+  MOZ_ASSERT(aIsRegistered);
+
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(mNSSToken);
+    return mNSSToken->IsRegistered(aKeyHandle.Elements(), aKeyHandle.Length(),
+                                   aIsRegistered);
+  }
+
+  ContentChild* cc = ContentChild::GetSingleton();
+  MOZ_ASSERT(cc);
+  if (!cc->SendNSSU2FTokenIsRegistered(aKeyHandle, aIsRegistered)) {
+    return NS_ERROR_FAILURE;
+  }
+  return NS_OK;
+}
+
+nsresult
+U2F::NSSTokenRegister(CryptoBuffer& aApplication, CryptoBuffer& aChallenge,
+                      CryptoBuffer& aRegistrationData)
+{
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(mNSSToken);
+    uint8_t* buffer;
+    uint32_t bufferlen;
+    nsresult rv;
+    rv = mNSSToken->Register(aApplication.Elements(), aApplication.Length(),
+                             aChallenge.Elements(), aChallenge.Length(),
+                             &buffer, &bufferlen);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(buffer);
+    aRegistrationData.Assign(buffer, bufferlen);
+    free(buffer);
+    return NS_OK;
+  }
+
+  nsTArray<uint8_t> registrationBuffer;
+  ContentChild* cc = ContentChild::GetSingleton();
+  MOZ_ASSERT(cc);
+  if (!cc->SendNSSU2FTokenRegister(aApplication, aChallenge,
+                                   &registrationBuffer)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  aRegistrationData.Assign(registrationBuffer);
+  return NS_OK;
+}
+
+nsresult
+U2F::NSSTokenSign(CryptoBuffer& aKeyHandle, CryptoBuffer& aApplication,
+                  CryptoBuffer& aChallenge, CryptoBuffer& aSignatureData)
+{
+  if (XRE_IsParentProcess()) {
+    MOZ_ASSERT(mNSSToken);
+    uint8_t* buffer;
+    uint32_t bufferlen;
+    nsresult rv = mNSSToken->Sign(aApplication.Elements(), aApplication.Length(),
+                                  aChallenge.Elements(), aChallenge.Length(),
+                                  aKeyHandle.Elements(), aKeyHandle.Length(),
+                                  &buffer, &bufferlen);
+    if (NS_WARN_IF(NS_FAILED(rv))) {
+      return rv;
+    }
+
+    MOZ_ASSERT(buffer);
+    aSignatureData.Assign(buffer, bufferlen);
+    free(buffer);
+    return NS_OK;
+  }
+
+  nsTArray<uint8_t> signatureBuffer;
+  ContentChild* cc = ContentChild::GetSingleton();
+  MOZ_ASSERT(cc);
+  if (!cc->SendNSSU2FTokenSign(aApplication, aChallenge, aKeyHandle,
+                               &signatureBuffer)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  aSignatureData.Assign(signatureBuffer);
+  return NS_OK;
+}
+
+nsresult
 U2F::AssembleClientData(const nsAString& aTyp,
                         const nsAString& aChallenge,
                         CryptoBuffer& aClientData) const
 {
   ClientData clientDataObject;
   clientDataObject.mTyp.Construct(aTyp); // "Typ" from the U2F specification
   clientDataObject.mChallenge.Construct(aChallenge);
   clientDataObject.mOrigin.Construct(mOrigin);
@@ -184,34 +301,16 @@ U2F::ValidAppID(/* in/out */ nsString& a
     return false;
   }
 
   // If the facetId and the appId auths match, accept
   if (facetAuth == appIdAuth) {
     return true;
   }
 
-  nsAutoCString appIdTld;
-  nsAutoCString facetTld;
-
-  rv = tldService->GetBaseDomainFromHost(appIdAuth, 0, appIdTld);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return false;
-  }
-  rv = tldService->GetBaseDomainFromHost(facetAuth, 0, facetTld);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return false;
-  }
-
-  // If this AppID's registered domain matches the Facet's, accept
-  if (!facetTld.IsEmpty() && !appIdTld.IsEmpty() &&
-      (facetTld == appIdTld)) {
-    return true;
-  }
-
   // TODO(Bug 1244959) Implement the remaining algorithm.
   return false;
 }
 
 template <class CB, class Rsp>
 void
 SendError(CB& aCallback, ErrorCode aErrorCode)
 {
@@ -253,17 +352,17 @@ U2F::Register(const nsAString& aAppId,
     SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
                                                      ErrorCode::BAD_REQUEST);
     return;
   }
 
   for (size_t i = 0; i < aRegisteredKeys.Length(); ++i) {
     RegisteredKey request(aRegisteredKeys[i]);
 
-    // Check for equired attributes
+    // Check for required attributes
     if (!(request.mKeyHandle.WasPassed() &&
           request.mVersion.WasPassed())) {
       continue;
     }
 
     // Verify the appId for this Registered Key, if set
     if (request.mAppId.WasPassed() &&
         !ValidAppID(request.mAppId.Value())) {
@@ -277,32 +376,48 @@ U2F::Register(const nsAString& aAppId,
       SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
                                                        ErrorCode::BAD_REQUEST);
       return;
     }
 
     // We ignore mTransports, as it is intended to be used for sorting the
     // available devices by preference, but is not an exclusion factor.
 
+    bool isCompatible = false;
+    bool isRegistered = false;
+
     // Determine if the provided keyHandle is registered at any device. If so,
     // then we'll return DEVICE_INELIGIBLE to signify we're already registered.
     if (usbTokenEnabled &&
         mUSBToken.IsCompatibleVersion(request.mVersion.Value()) &&
         mUSBToken.IsRegistered(keyHandle)) {
       SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
                                                   ErrorCode::DEVICE_INELIGIBLE);
       return;
     }
+    if (softTokenEnabled) {
+      rv = NSSTokenIsCompatible(request.mVersion.Value(), &isCompatible);
+      if (NS_FAILED(rv)) {
+        SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
+                                                         ErrorCode::OTHER_ERROR);
+        return;
+      }
 
-    if (softTokenEnabled &&
-        mSoftToken.IsCompatibleVersion(request.mVersion.Value()) &&
-        mSoftToken.IsRegistered(keyHandle)) {
-      SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
-                                                  ErrorCode::DEVICE_INELIGIBLE);
-      return;
+      rv = NSSTokenIsRegistered(keyHandle, &isRegistered);
+      if (NS_FAILED(rv)) {
+        SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
+                                                         ErrorCode::OTHER_ERROR);
+        return;
+      }
+
+      if (isCompatible && isRegistered) {
+        SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
+                                                         ErrorCode::DEVICE_INELIGIBLE);
+        return;
+      }
     }
   }
 
   // Search the requests in order for the first some token can fulfill
   for (size_t i = 0; i < aRegisterRequests.Length(); ++i) {
     RegisterRequest request(aRegisterRequests[i]);
 
     // Check for equired attributes
@@ -348,38 +463,41 @@ U2F::Register(const nsAString& aAppId,
       SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
                                                        ErrorCode::OTHER_ERROR);
       return;
     }
 
     // Get the registration data from the token
     CryptoBuffer registrationData;
     bool registerSuccess = false;
-
-    if (usbTokenEnabled &&
-        mUSBToken.IsCompatibleVersion(request.mVersion.Value())) {
-      rv = mUSBToken.Register(opt_aTimeoutSeconds, challengeParam,
-                              appParam, registrationData);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
-        SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
-                                                      ErrorCode::OTHER_ERROR);
-        return;
-      }
-      registerSuccess = true;
+    bool isCompatible = false;
+    if (usbTokenEnabled) {
+      // TODO: Implement in Bug 1245527
+      SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
+                                                       ErrorCode::OTHER_ERROR);
+      return;
     }
 
-    if (!registerSuccess && softTokenEnabled &&
-        mSoftToken.IsCompatibleVersion(request.mVersion.Value())) {
-      rv = mSoftToken.Register(challengeParam, appParam, registrationData);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
+    if (!registerSuccess && softTokenEnabled) {
+      rv = NSSTokenIsCompatible(request.mVersion.Value(), &isCompatible);
+      if (NS_FAILED(rv)) {
         SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
                                                         ErrorCode::OTHER_ERROR);
         return;
       }
-      registerSuccess = true;
+
+      if (isCompatible) {
+        rv = NSSTokenRegister(appParam, challengeParam, registrationData);
+        if (NS_FAILED(rv)) {
+          SendError<U2FRegisterCallback, RegisterResponse>(aCallback,
+                                                        ErrorCode::OTHER_ERROR);
+          return;
+        }
+        registerSuccess = true;
+      }
     }
 
     if (!registerSuccess) {
       // Try another request
       continue;
     }
 
     // Assemble a response object to return
@@ -516,35 +634,49 @@ U2F::Sign(const nsAString& aAppId,
     CryptoBuffer signatureData;
     bool signSuccess = false;
 
     // We ignore mTransports, as it is intended to be used for sorting the
     // available devices by preference, but is not an exclusion factor.
 
     if (usbTokenEnabled &&
         mUSBToken.IsCompatibleVersion(request.mVersion.Value())) {
-      rv = mUSBToken.Sign(opt_aTimeoutSeconds, appParam, challengeParam,
-                          keyHandle, signatureData);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
+      // TODO: Implement in Bug 1245527
+      SendError<U2FSignCallback, SignResponse>(aCallback,
+                                               ErrorCode::OTHER_ERROR);
+      return;
+    }
+
+    if (!signSuccess && softTokenEnabled) {
+      bool isCompatible = false;
+      bool isRegistered = false;
+
+      rv = NSSTokenIsCompatible(request.mVersion.Value(), &isCompatible);
+      if (NS_FAILED(rv)) {
         SendError<U2FSignCallback, SignResponse>(aCallback,
                                                  ErrorCode::OTHER_ERROR);
         return;
       }
-      signSuccess = true;
-    }
 
-    if (!signSuccess && softTokenEnabled &&
-        mSoftToken.IsCompatibleVersion(request.mVersion.Value())) {
-      rv = mSoftToken.Sign(appParam, challengeParam, keyHandle, signatureData);
-      if (NS_WARN_IF(NS_FAILED(rv))) {
+      rv = NSSTokenIsRegistered(keyHandle, &isRegistered);
+      if (NS_FAILED(rv)) {
         SendError<U2FSignCallback, SignResponse>(aCallback,
                                                  ErrorCode::OTHER_ERROR);
         return;
       }
-      signSuccess = true;
+
+      if (isCompatible && isRegistered) {
+        rv = NSSTokenSign(keyHandle, appParam, challengeParam, signatureData);
+        if (NS_FAILED(rv)) {
+          SendError<U2FSignCallback, SignResponse>(aCallback,
+                                                   ErrorCode::OTHER_ERROR);
+          return;
+        }
+        signSuccess = true;
+      }
     }
 
     if (!signSuccess) {
       // Try another request
       continue;
     }
 
     // Assemble a response object to return
--- a/dom/u2f/U2F.h
+++ b/dom/u2f/U2F.h
@@ -8,20 +8,21 @@
 #define mozilla_dom_U2F_h
 
 #include "js/TypeDecls.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/dom/BindingDeclarations.h"
 #include "mozilla/dom/Nullable.h"
 #include "mozilla/ErrorResult.h"
 #include "nsCycleCollectionParticipant.h"
+#include "nsINSSU2FToken.h"
+#include "nsNSSShutDown.h"
 #include "nsPIDOMWindow.h"
 #include "nsWrapperCache.h"
 
-#include "NSSToken.h"
 #include "USBToken.h"
 
 namespace mozilla {
 namespace dom {
 
 struct RegisterRequest;
 struct RegisteredKey;
 class U2FRegisterCallback;
@@ -73,18 +74,18 @@ public:
 
   // No NSS resources to release.
   virtual
   void virtualDestroyNSSReference() override {};
 
 private:
   nsCOMPtr<nsPIDOMWindowInner> mParent;
   nsString mOrigin;
-  NSSToken mSoftToken;
   USBToken mUSBToken;
+  nsCOMPtr<nsINSSU2FToken> mNSSToken;
 
   static const nsString FinishEnrollment;
   static const nsString GetAssertion;
 
   ~U2F();
 
   nsresult
   AssembleClientData(const nsAString& aTyp,
@@ -93,14 +94,28 @@ private:
 
   // ValidAppID determines whether the supplied FIDO AppID is valid for
   // the current FacetID, e.g., the current origin. If the supplied
   // aAppId param is null or empty, it will be filled in per the algorithm.
   // See https://fidoalliance.org/specs/fido-u2f-v1.0-nfc-bt-amendment-20150514/fido-appid-and-facets.html
   // for a description of the algorithm.
   bool
   ValidAppID(/* in/out */ nsString& aAppId) const;
+
+  nsresult
+  NSSTokenIsCompatible(const nsString& versionString, bool* isCompatible);
+
+  nsresult
+  NSSTokenIsRegistered(CryptoBuffer& keyHandle, bool* isRegistered);
+
+  nsresult
+  NSSTokenRegister(CryptoBuffer& application, CryptoBuffer& challenge,
+                   CryptoBuffer& registrationData);
+
+  nsresult
+  NSSTokenSign(CryptoBuffer& keyHandle, CryptoBuffer& application,
+               CryptoBuffer& challenge, CryptoBuffer& signatureData);
 };
 
 } // namespace dom
 } // namespace mozilla
 
 #endif // mozilla_dom_U2F_h
--- a/dom/u2f/moz.build
+++ b/dom/u2f/moz.build
@@ -1,26 +1,26 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 EXPORTS.mozilla.dom += [
-    'NSSToken.h',
     'U2F.h',
     'USBToken.h',
 ]
 
 UNIFIED_SOURCES += [
-    'NSSToken.cpp',
     'U2F.cpp',
     'USBToken.cpp',
 ]
 
+include('/ipc/chromium/chromium-config.mozbuild')
+
 FINAL_LIBRARY = 'xul'
 
 LOCAL_INCLUDES += [
     '/dom/base',
     '/dom/crypto',
     '/security/manager/ssl',
     '/security/pkix/include',
 ]
--- a/dom/u2f/tests/mochitest.ini
+++ b/dom/u2f/tests/mochitest.ini
@@ -1,20 +1,25 @@
 [DEFAULT]
 support-files =
   frame_no_token.html
   u2futil.js
   test_frame_appid_facet.html
   test_frame_register.html
+  test_frame_register_sign.html
   test_frame_appid_facet_remoteload.html
   test_frame_appid_facet_insecure.html
   test_frame_appid_facet_subdomain.html
   facet/facetList.txt
   facet/facetList-good
   facet/facetList-good^headers^
   facet/facetList-no_overlap
   facet/facetList-no_overlap^headers^
   facet/facetList-invalid_format
   facet/facetList-invalid_format^headers^
+  pkijs/common.js
+  pkijs/asn1.js
+  pkijs/x509_schema.js
+  pkijs/x509_simpl.js
 
 [test_util_methods.html]
 [test_no_token.html]
 [test_frame.html]
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2014, GMO GlobalSign
+Copyright (c) 2015, Peculiar Ventures
+All rights reserved.
+
+Author 2014-2015, Yury Strozhevsky
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+  list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice, this
+  list of conditions and the following disclaimer in the documentation and/or
+  other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+  contributors may be used to endorse or promote products derived from
+  this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/README
@@ -0,0 +1,1 @@
+PKIjs and ASN1js are from https://pkijs.org/ and https://asn1js.org/.
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/asn1.js
@@ -0,0 +1,5466 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.asn1" namespace 
+    if(typeof in_window.org.pkijs.asn1 === "undefined")
+        in_window.org.pkijs.asn1 = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.asn1 !== "object")
+            throw new Error("Name org.pkijs.asn1 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.asn1));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Aux-functions 
+    //**************************************************************************************
+    function util_frombase(input_buffer, input_base)
+    {
+        /// <summary>Convert number from 2^base to 2^10</summary>
+        /// <param name="input_buffer" type="Uint8Array">Array of bytes representing the number to convert</param>
+        /// <param name="input_base" type="Number">The base of initial number</param>
+
+        var result = 0; 
+
+        for(var i = (input_buffer.length - 1); i >= 0; i-- )
+            result += input_buffer[(input_buffer.length - 1) - i] * Math.pow(2, input_base * i);
+
+        return result;
+    }
+    //**************************************************************************************
+    function util_tobase(value, base, reserved)
+    {
+        /// <summary>Convert number from 2^10 to 2^base</summary>
+        /// <param name="value" type="Number">The number to convert</param>
+        /// <param name="base" type="Number">The base for 2^base</param>
+        /// <param name="reserved" type="Number">Pre-defined number of bytes in output array (-1 = limited by function itself)</param>
+
+        reserved = reserved || (-1);
+
+        var result = 0;
+        var biggest = Math.pow(2, base);
+
+        for(var i = 1; i < 8; i++)
+        {
+            if(value < biggest)
+            {
+                var ret_buf;
+
+                if( reserved < 0 )
+                {
+                    ret_buf = new ArrayBuffer(i);
+                    result = i;
+                }
+                else
+                {
+                    if(reserved < i)
+                        return (new ArrayBuffer(0));
+
+                    ret_buf = new ArrayBuffer(reserved);
+
+                    result = reserved;
+                }
+
+                var ret_view = new Uint8Array(ret_buf);
+
+                for(var j = ( i - 1 ); j >= 0; j-- )
+                {
+                    var basis = Math.pow(2, j * base);
+
+                    ret_view[ result - j - 1 ] = Math.floor( value / basis );
+                    value -= ( ret_view[ result - j - 1 ] ) * basis;
+                }
+
+                return ret_buf;
+            }
+
+            biggest *= Math.pow(2, base);
+        }
+    }
+    //**************************************************************************************
+    function util_encode_tc(value)
+    {
+        /// <summary>Encode integer value to "two complement" format</summary>
+        /// <param name="value" type="Number">Value to encode</param>
+
+        var mod_value = (value < 0) ? (value * (-1)) : value;
+        var big_int = 128;
+
+        for(var i = 1; i < 8; i++) 
+        {
+            if( mod_value <= big_int )
+            {
+                if( value < 0 )
+                {
+                    var small_int = big_int - mod_value;
+
+                    var ret_buf = util_tobase( small_int, 8, i );
+                    var ret_view = new Uint8Array(ret_buf);
+
+                    ret_view[ 0 ] |= 0x80;
+
+                    return ret_buf;
+                }
+                else
+                {
+                    var ret_buf = util_tobase( mod_value, 8, i );
+                    var ret_view = new Uint8Array(ret_buf);
+
+                    if( ret_view[ 0 ] & 0x80 )
+                    {
+                        var temp_buf = util_copybuf(ret_buf);
+                        var temp_view = new Uint8Array(temp_buf);
+
+                        ret_buf = new ArrayBuffer( ret_buf.byteLength + 1 );
+                        ret_view = new Uint8Array(ret_buf);
+
+                        for(var k = 0; k < temp_buf.byteLength; k++)
+                            ret_view[k + 1] = temp_view[k];
+
+                        ret_view[0] = 0x00;
+                    }
+
+                    return ret_buf;
+                }
+            }
+
+            big_int *= Math.pow(2, 8);
+        }
+
+        return (new ArrayBuffer(0));
+    }
+    //**************************************************************************************
+    function util_decode_tc()
+    {
+        /// <summary>Decoding of "two complement" values</summary>
+        /// <remarks>The function must be called in scope of instance of "hex_block" class ("value_hex" and "warnings" properties must be present)</remarks>
+
+        var buf = new Uint8Array(this.value_hex);
+
+        if(this.value_hex.byteLength >= 2)
+        {
+            var condition_1 = (buf[0] == 0xFF) && (buf[1] & 0x80);
+            var condition_2 = (buf[0] == 0x00) && ((buf[1] & 0x80) == 0x00);
+
+            if(condition_1 || condition_2)
+                this.warnings.push("Needlessly long format");
+        }
+
+        // #region Create big part of the integer
+        var big_int_buffer = new ArrayBuffer(this.value_hex.byteLength);
+        var big_int_view = new Uint8Array(big_int_buffer);
+        for(var i = 0; i < this.value_hex.byteLength; i++)
+            big_int_view[i] = 0;
+
+        big_int_view[0] = (buf[0] & 0x80); // mask only the biggest bit
+
+        var big_int = util_frombase(big_int_view, 8);
+        // #endregion   
+
+        // #region Create small part of the integer 
+        var small_int_buffer = new ArrayBuffer(this.value_hex.byteLength);
+        var small_int_view = new Uint8Array(small_int_buffer);
+        for(var j = 0; j < this.value_hex.byteLength; j++)
+            small_int_view[j] = buf[j];
+
+        small_int_view[0] &= 0x7F; // mask biggest bit
+
+        var small_int = util_frombase(small_int_view, 8);
+        // #endregion 
+
+        return (small_int - big_int);
+    }
+    //**************************************************************************************
+    function util_copybuf(input_buffer)
+    {
+        /// <summary>Creating a copy of input ArrayBuffer</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param>
+
+        if(check_buffer_params(input_buffer, 0, input_buffer.byteLength) === false)
+            return (new ArrayBuffer(0));
+
+        var input_view = new Uint8Array(input_buffer);
+
+        var ret_buf = new ArrayBuffer(input_buffer.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buffer.byteLength; i++)
+            ret_view[i] = input_view[i];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function util_copybuf_offset(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Creating a copy of input ArrayBuffer</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ArrayBuffer for coping</param>
+
+        if(check_buffer_params(input_buffer, input_offset, input_length) === false)
+            return (new ArrayBuffer(0));
+
+        var input_view = new Uint8Array(input_buffer, input_offset, input_length);
+
+        var ret_buf = new ArrayBuffer(input_length);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_length; i++)
+            ret_view[i] = input_view[i];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function util_concatbuf(input_buf1, input_buf2)
+    {
+        /// <summary>Concatenate two ArrayBuffers</summary>
+        /// <param name="input_buf1" type="ArrayBuffer">First ArrayBuffer (first part of concatenated array)</param>
+        /// <param name="input_buf2" type="ArrayBuffer">Second ArrayBuffer (second part of concatenated array)</param>
+
+        var input_view1 = new Uint8Array(input_buf1);
+        var input_view2 = new Uint8Array(input_buf2);
+
+        var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buf1.byteLength; i++)
+            ret_view[i] = input_view1[i];
+
+        for(var j = 0; j < input_buf2.byteLength; j++)
+            ret_view[input_buf1.byteLength + j] = input_view2[j];
+
+        return ret_buf;
+    }
+    //**************************************************************************************
+    function check_buffer_params(input_buffer, input_offset, input_length)
+    {
+        if((input_buffer instanceof ArrayBuffer) === false)
+        {
+            this.error = "Wrong parameter: input_buffer must be \"ArrayBuffer\"";
+            return false;
+        }
+
+        if(input_buffer.byteLength === 0)
+        {
+            this.error = "Wrong parameter: input_buffer has zero length";
+            return false;
+        }
+
+        if(input_offset < 0)
+        {
+            this.error = "Wrong parameter: input_offset less than zero";
+            return false;
+        }
+
+        if(input_length < 0)
+        {
+            this.error = "Wrong parameter: input_length less than zero";
+            return false;
+        }
+
+        if((input_buffer.byteLength - input_offset - input_length) < 0)
+        {
+            this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+            return false;
+        }
+
+        return true;
+    }
+    //**************************************************************************************
+    function to_hex_codes(input_buffer, input_offset, input_lenght)
+    {
+        if(check_buffer_params(input_buffer, input_offset, input_lenght) === false)
+            return "";
+
+        var result = "";
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght);
+        
+        for(var i = 0; i < int_buffer.length; i++)
+        {
+            var str = int_buffer[i].toString(16).toUpperCase();
+            result = result + ((str.length === 1) ? " 0" : " ") + str;
+        }
+
+        return result;
+    }
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of base block class 
+    //**************************************************************************************
+    local.base_block =
+    function()
+    {
+        /// <summary>General class of all ASN.1 blocks</summary>
+
+        if(arguments[0] instanceof Object)
+        {
+            this.block_length = in_window.org.pkijs.getValue(arguments[0], "block_length", 0);
+            this.error = in_window.org.pkijs.getValue(arguments[0], "error", new String());
+            this.warnings = in_window.org.pkijs.getValue(arguments[0], "warnings", new Array());
+            if("value_before_decode" in arguments[0])
+                this.value_before_decode = util_copybuf(arguments[0].value_before_decode);
+            else
+                this.value_before_decode = new ArrayBuffer(0);
+        }
+        else
+        {
+            this.block_length = 0;
+            this.error = new String();
+            this.warnings = new Array();
+            /// <field>Copy of the value of incoming ArrayBuffer done before decoding</field>
+            this.value_before_decode = new ArrayBuffer(0);
+        }
+    };
+    //**************************************************************************************
+    local.base_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "base_block";
+    };
+    //**************************************************************************************
+    local.base_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        return {
+            block_name: local.base_block.prototype.block_name.call(this),
+            block_length: this.block_length,
+            error: this.error,
+            warnings: this.warnings,
+            value_before_decode: in_window.org.pkijs.bufferToHexCodes(this.value_before_decode, 0, this.value_before_decode.byteLength)
+        };
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of hex block class 
+    //**************************************************************************************
+    local.hex_block =
+    function()
+    {
+        /// <summary>Descendant of "base_block" with internal ArrayBuffer. Need to have it in case it is not possible to store ASN.1 value in native formats</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+        }
+        else
+        {
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+        }
+    };
+    //**************************************************************************************
+    local.hex_block.prototype = new local.base_block();
+    local.hex_block.constructor = local.hex_block;
+    //**************************************************************************************
+    local.hex_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "hex_block";
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Copy input buffer to internal buffer 
+        this.value_hex = new ArrayBuffer(input_length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only !== true)
+        {
+            this.error = "Flag \"is_hex_only\" is not set, abort";
+            return (new ArrayBuffer(0));
+        }
+
+        var ret_buf = new ArrayBuffer(this.value_hex.byteLength);
+
+        if(size_only === true)
+            return ret_buf;
+
+        var ret_view = new Uint8Array(ret_buf);
+        var cur_view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < cur_view.length; i++)
+            ret_view[i] = cur_view[i];
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.hex_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.hex_block.prototype.block_name.call(this);
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of identification block class 
+    //**************************************************************************************
+    local.identification_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 "identification block"</summary>
+
+        local.hex_block.call(this, arguments[0]);
+
+        this.tag_class = (-1);
+        this.tag_number = (-1);
+        this.is_constructed = false;
+
+        if(arguments[0] instanceof Object)
+        {
+            if("id_block" in arguments[0])
+            {
+                // #region Properties from hex_block class 
+                this.is_hex_only = in_window.org.pkijs.getValue(arguments[0].id_block, "is_hex_only", false);
+                this.value_hex = in_window.org.pkijs.getValue(arguments[0].id_block, "value_hex", new ArrayBuffer(0));
+                // #endregion   
+
+                this.tag_class = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_class", (-1));
+                this.tag_number = in_window.org.pkijs.getValue(arguments[0].id_block, "tag_number", (-1));
+                this.is_constructed = in_window.org.pkijs.getValue(arguments[0].id_block, "is_constructed", false);
+            }
+        }
+    };
+    //**************************************************************************************
+    local.identification_block.prototype = new local.hex_block();
+    local.identification_block.constructor = local.identification_block;
+    //**************************************************************************************
+    local.identification_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "identification_block";
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var first_octet = 0;
+
+        switch(this.tag_class)
+        {
+            case 1:
+                first_octet |= 0x00; // UNIVERSAL
+                break;
+            case 2:
+                first_octet |= 0x40; // APPLICATION
+                break;
+            case 3:
+                first_octet |= 0x80; // CONTEXT-SPECIFIC
+                break;
+            case 4:
+                first_octet |= 0xC0; // PRIVATE
+                break;
+            default:
+                this.error = "Unknown tag class";
+                return (new ArrayBuffer(0));
+        }
+
+        if(this.is_constructed)
+            first_octet |= 0x20;
+
+        if((this.tag_number < 31) && (!this.is_hex_only))
+        {
+            var ret_buf = new ArrayBuffer(1);
+            var ret_view = new Uint8Array(ret_buf);
+
+            if(!size_only)
+            {
+                var number = this.tag_number;
+                number &= 0x1F;
+                first_octet |= number;
+
+                ret_view[0] = first_octet;
+            }
+
+            return ret_buf;
+        }
+        else
+        {
+            if(this.is_hex_only === false)
+            {
+                var encoded_buf = util_tobase(this.tag_number, 7);
+                var encoded_view = new Uint8Array(encoded_buf);
+                var size = encoded_buf.byteLength;
+
+                var ret_buf = new ArrayBuffer(size + 1);
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = (first_octet | 0x1F);
+
+                if(!size_only)
+                {
+                    for(var i = 0; i < (size - 1) ; i++)
+                        ret_view[i + 1] = encoded_view[i] | 0x80;
+
+                    ret_view[size] = encoded_view[size - 1];
+                }
+
+                return ret_buf;
+            }
+            else
+            {
+                var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1);
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = (first_octet | 0x1F);
+
+                if(size_only === false)
+                {
+                    var cur_view = new Uint8Array(this.value_hex);
+
+                    for(var i = 0; i < (cur_view.length - 1); i++)
+                        ret_view[i + 1] = cur_view[i] | 0x80;
+
+                    ret_view[this.value_hex.byteLength] = cur_view[cur_view.length - 1];
+                }
+
+                return ret_buf;
+            }
+        }
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return (-1);
+        }
+        // #endregion 
+
+        // #region Find tag class 
+        var tag_class_mask = int_buffer[0] & 0xC0;
+
+        switch(tag_class_mask)
+        {
+            case 0x00:
+                this.tag_class = (1); // UNIVERSAL
+                break;
+            case 0x40:
+                this.tag_class = (2); // APPLICATION
+                break;
+            case 0x80:
+                this.tag_class = (3); // CONTEXT-SPECIFIC
+                break;
+            case 0xC0:
+                this.tag_class = (4); // PRIVATE
+                break;
+            default:
+                this.error = "Unknown tag class";
+                return ( -1 );
+        }
+        // #endregion 
+
+        // #region Find it's constructed or not 
+        this.is_constructed = (int_buffer[0] & 0x20) == 0x20;
+        // #endregion 
+
+        // #region Find tag number 
+        this.is_hex_only = false;
+
+        var tag_number_mask = int_buffer[0] & 0x1F;
+
+        // #region Simple case (tag number < 31)
+        if(tag_number_mask != 0x1F) 
+        {
+            this.tag_number = (tag_number_mask);
+            this.block_length = 1;
+        }
+            // #endregion 
+        // #region Tag number bigger or equal to 31 
+        else
+        {
+            var count = 1;
+
+            this.value_hex = new ArrayBuffer(255);
+            var tag_number_buffer_max_length = 255;
+            var int_tag_number_buffer = new Uint8Array(this.value_hex);
+
+            while(int_buffer[count] & 0x80)
+            {
+                int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F;
+                count++;
+
+                if(count >= int_buffer.length)
+                {
+                    this.error = "End of input reached before message was fully decoded";
+                    return (-1);
+                }
+
+                // #region In case if tag number length is greater than 255 bytes (rare but possible case)
+                if(count == tag_number_buffer_max_length)
+                {
+                    tag_number_buffer_max_length += 255;
+
+                    var temp_buffer = new ArrayBuffer(tag_number_buffer_max_length);
+                    var temp_buffer_view = new Uint8Array(temp_buffer);
+
+                    for(var i = 0; i < int_tag_number_buffer.length; i++)
+                        temp_buffer_view[i] = int_tag_number_buffer[i];
+
+                    this.value_hex = new ArrayBuffer(tag_number_buffer_max_length);
+                    int_tag_number_buffer = new Uint8Array(this.value_hex);
+                }
+                // #endregion 
+            }
+
+            this.block_length = (count + 1);
+            int_tag_number_buffer[count - 1] = int_buffer[count] & 0x7F; // Write last byte to buffer
+
+            // #region Cut buffer 
+            var temp_buffer = new ArrayBuffer(count);
+            var temp_buffer_view = new Uint8Array(temp_buffer);
+            for(var i = 0; i < count; i++)
+                temp_buffer_view[i] = int_tag_number_buffer[i];
+
+            this.value_hex = new ArrayBuffer(count);
+            int_tag_number_buffer = new Uint8Array(this.value_hex);
+            int_tag_number_buffer.set(temp_buffer_view);
+            // #endregion 
+
+            // #region Try to convert long tag number to short form 
+            if(this.block_length <= 9)
+                this.tag_number = util_frombase(int_tag_number_buffer, 7);
+            else
+            {
+                this.is_hex_only = true;
+                this.warnings.push("Tag too long, represented as hex-coded");
+            }
+            // #endregion 
+        }
+        // #endregion 
+        // #endregion 
+
+        // #region Check if constructed encoding was using for primitive type 
+        if(((this.tag_class == 1)) &&
+            (this.is_constructed))
+        {
+            switch(this.tag_number)
+            {
+                case 1:  // BOOLEAN
+                case 2:  // REAL
+                case 5:  // NULL
+                case 6:  // OBJECT IDENTIFIER
+                case 9:  // REAL
+                case 14: // TIME
+                case 23:
+                case 24:
+                case 31:
+                case 32:
+                case 33:
+                case 34:
+                    this.error = "Constructed encoding used for primitive type";
+                    return (-1);
+                default:
+                    ;
+            }
+        }
+        // #endregion 
+
+        return ( input_offset + this.block_length ); // Return current offset in input buffer
+    };
+    //**************************************************************************************
+    local.identification_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.identification_block.prototype.block_name.call(this);
+        _object.tag_class = this.tag_class;
+        _object.tag_number = this.tag_number;
+        _object.is_constructed = this.is_constructed;
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of length block class 
+    //**************************************************************************************
+    local.length_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 "length block"</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        this.is_indefinite_form = false;
+        this.long_form_used = false;
+        this.length = (0);
+
+        if(arguments[0] instanceof Object)
+        {
+            if("len_block" in arguments[0])
+            {
+                this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0].len_block, "is_indefinite_form", false);
+                this.long_form_used = in_window.org.pkijs.getValue(arguments[0].len_block, "long_form_used", false);
+                this.length = in_window.org.pkijs.getValue(arguments[0].len_block, "length", 0);
+            }
+        }
+    };
+    //**************************************************************************************
+    local.length_block.prototype = new local.base_block();
+    local.length_block.constructor = local.length_block;
+    //**************************************************************************************
+    local.length_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "length_block";
+    };
+    //**************************************************************************************
+    local.length_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return (-1);
+        }
+
+        if(int_buffer[0] == 0xFF)
+        {
+            this.error = "Length block 0xFF is reserved by standard";
+            return (-1);
+        }
+        // #endregion 
+
+        // #region Check for length form type 
+        this.is_indefinite_form = int_buffer[0] == 0x80;
+        // #endregion 
+
+        // #region Stop working in case of indefinite length form 
+        if(this.is_indefinite_form == true)
+        {
+            this.block_length = 1;
+            return (input_offset + this.block_length);
+        }
+        // #endregion 
+
+        // #region Check is long form of length encoding using 
+        this.long_form_used = !!(int_buffer[0] & 0x80);
+        // #endregion 
+
+        // #region Stop working in case of short form of length value 
+        if(this.long_form_used == false)
+        {
+            this.length = (int_buffer[0]);
+            this.block_length = 1;
+            return (input_offset + this.block_length);
+        }
+        // #endregion 
+
+        // #region Calculate length value in case of long form 
+        var count = int_buffer[0] & 0x7F;
+
+        if(count > 8) // Too big length value
+        {
+            this.error = "Too big integer";
+            return (-1);
+        }
+
+        if((count + 1) > int_buffer.length)
+        {
+            this.error = "End of input reached before message was fully decoded";
+            return (-1);
+        }
+
+        var length_buffer_view = new Uint8Array(count);
+
+        for(var i = 0; i < count; i++)
+            length_buffer_view[i] = int_buffer[i + 1];
+
+        if(length_buffer_view[count - 1] == 0x00)
+            this.warnings.push("Needlessly long encoded length");
+
+        this.length = util_frombase(length_buffer_view, 8);
+
+        if(this.long_form_used && (this.length <= 127))
+            this.warnings.push("Unneccesary usage of long length form");
+
+        this.block_length = count + 1;
+        // #endregion 
+
+        return (input_offset + this.block_length); // Return current offset in input buffer
+    };
+    //**************************************************************************************
+    local.length_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.length > 127)
+            this.long_form_used = true;
+
+        if(this.is_indefinite_form)
+        {
+            var ret_buf = new ArrayBuffer(1);
+
+            if(size_only === false)
+            {
+                var ret_view = new Uint8Array(ret_buf);
+                ret_view[0] = 0x80;
+            }
+
+            return ret_buf;
+        }
+
+        if(this.long_form_used === true)
+        {
+            var encoded_buf = util_tobase(this.length, 8);
+
+            if(encoded_buf.byteLength > 127)
+            {
+                this.error = "Too big length";
+                return (new ArrayBuffer(0));
+            }
+
+            var ret_buf = new ArrayBuffer(encoded_buf.byteLength + 1);
+
+            if(size_only === true)
+                return ret_buf;
+
+            var encoded_view = new Uint8Array(encoded_buf);
+            var ret_view = new Uint8Array(ret_buf);
+
+            ret_view[0] = encoded_buf.byteLength | 0x80;
+
+            for(var i = 0; i < encoded_buf.byteLength; i++)
+                ret_view[i + 1] = encoded_view[i];
+
+            return ret_buf;
+        }
+        else
+        {
+            var ret_buf = new ArrayBuffer(1);
+
+            if(size_only === false)
+            {
+                var ret_view = new Uint8Array(ret_buf);
+
+                ret_view[0] = this.length;
+            }
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.length_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.length_block.prototype.block_name.call(this);
+        _object.is_indefinite_form = this.is_indefinite_form;
+        _object.long_form_used = this.long_form_used;
+        _object.length = this.length;
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of value block class 
+    //**************************************************************************************
+    local.value_block =
+    function()
+    {
+        /// <summary>Generic class of ASN.1 "value block"</summary>
+        local.base_block.call(this, arguments[0]);
+    };
+    //**************************************************************************************
+    local.value_block.prototype = new local.base_block();
+    local.value_block.constructor = local.value_block;
+    //**************************************************************************************
+    local.value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "value_block";
+    };
+    //**************************************************************************************
+    local.value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.value_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic ASN.1 block class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block (identification block + length block + value block)</summary>
+
+        local.base_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+
+            if("primitive_schema" in arguments[0])
+                this.primitive_schema = arguments[0].primitive_schema;
+        }
+
+        this.id_block = new local.identification_block(arguments[0]);
+        this.len_block = new local.length_block(arguments[0]);
+        this.value_block = new local.value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype = new local.base_block();
+    in_window.org.pkijs.asn1.ASN1_block.constructor = in_window.org.pkijs.asn1.ASN1_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_block";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf;
+
+        var id_block_buf = this.id_block.toBER(size_only);
+        var value_block_size_buf = this.value_block.toBER(true);
+
+        this.len_block.length = value_block_size_buf.byteLength;
+        var len_block_buf = this.len_block.toBER(size_only);
+
+        ret_buf = util_concatbuf(id_block_buf, len_block_buf);
+
+        var value_block_buf;
+
+        if(size_only === false)
+            value_block_buf = this.value_block.toBER(size_only);
+        else
+            value_block_buf = new ArrayBuffer(this.len_block.length);
+
+        ret_buf = util_concatbuf(ret_buf, value_block_buf);
+
+        if(this.len_block.is_indefinite_form === true)
+        {
+            var indef_buf = new ArrayBuffer(2);
+
+            if(size_only === false)
+            {
+                var indef_view = new Uint8Array(indef_buf);
+
+                indef_view[0] = 0x00;
+                indef_view[1] = 0x00;
+            }
+
+            ret_buf = util_concatbuf(ret_buf, indef_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.base_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_block.prototype.block_name.call(this);
+        _object.id_block = this.id_block.toJSON();
+        _object.len_block = this.len_block.toJSON();
+        _object.value_block = this.value_block.toJSON();
+
+        if("name" in this)
+            _object.name = this.name;
+        if("optional" in this)
+            _object.optional = this.optional;
+        if("primitive_schema" in this)
+            _object.primitive_schema = this.primitive_schema.toJSON();
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic block for all PRIMITIVE types 
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 value block for primitive values (non-constructive encoding)</summary>
+
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            // #region Variables from "hex_block" class 
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", true);
+            // #endregion 
+        }
+        else
+        {
+            // #region Variables from "hex_block" class 
+            this.value_hex = new ArrayBuffer(0);
+            this.is_hex_only = true;
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype = new local.value_block();
+    local.ASN1_PRIMITIVE_value_block.constructor = local.ASN1_PRIMITIVE_value_block;
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Copy input buffer into internal buffer 
+        this.value_hex = new ArrayBuffer(int_buffer.length);
+        var value_hex_view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            value_hex_view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        return util_copybuf(this.value_hex);
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_PRIMITIVE_value_block";
+    };
+    //**************************************************************************************
+    local.ASN1_PRIMITIVE_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.ASN1_PRIMITIVE_value_block.prototype.block_name.call(this);
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+        _object.is_hex_only = this.is_hex_only;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block for primitive values (non-constructive encoding)</summary>
+
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.is_constructed = false;
+        this.value_block = new local.ASN1_PRIMITIVE_value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.constructor = in_window.org.pkijs.asn1.ASN1_PRIMITIVE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "PRIMITIVE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_PRIMITIVE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of basic block for all CONSTRUCTED types 
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block =
+    function()
+    {
+        /// <summary>Base class of ASN.1 value block for constructive values (constructive encoding)</summary>
+
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array());
+            this.is_indefinite_form = in_window.org.pkijs.getValue(arguments[0], "is_indefinite_form", false);
+        }
+        else
+        {
+            this.value = new Array();
+            this.is_indefinite_form = false;
+        }
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype = new local.value_block();
+    local.ASN1_CONSTRUCTED_value_block.constructor = local.ASN1_CONSTRUCTED_value_block;
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Store initial offset and length 
+        var initial_offset = input_offset;
+        var initial_length = input_length;
+        // #endregion 
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.warnings.push("Zero buffer length");
+            return input_offset;
+        }
+        // #endregion 
+
+        // #region Aux function 
+        function check_len(_indefinite_length, _length)
+        {
+            if(_indefinite_length == true)
+                return 1;
+
+            return _length;
+        }
+        // #endregion 
+
+        var current_offset = input_offset;
+
+        while(check_len(this.is_indefinite_form, input_length) > 0)
+        {
+            var return_object = fromBER_raw(input_buffer, current_offset, input_length);
+            if(return_object.offset == (-1))
+            {
+                this.error = return_object.result.error;
+                this.warnings.concat(return_object.result.warnings);
+                return (-1);
+            }
+
+            current_offset = return_object.offset;
+
+            this.block_length += return_object.result.block_length;
+            input_length -= return_object.result.block_length;
+
+            this.value.push(return_object.result);
+
+            if((this.is_indefinite_form == true) && (return_object.result.block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name()))
+                break;
+        }
+
+        if(this.is_indefinite_form == true)
+        {
+            if(this.value[this.value.length - 1].block_name() == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                this.value.pop();
+            else
+                this.warnings.push("No EOC block encoded");
+        }
+
+        // #region Copy "input_buffer" to "value_before_decode" 
+        this.value_before_decode = util_copybuf_offset(input_buffer, initial_offset, initial_length);
+        // #endregion 
+
+        return current_offset;
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(0);
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            var value_buf = this.value[i].toBER(size_only);
+            ret_buf = util_concatbuf(ret_buf, value_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ASN1_CONSTRUCTED_value_block";
+    };
+    //**************************************************************************************
+    local.ASN1_CONSTRUCTED_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.ASN1_CONSTRUCTED_value_block.prototype.block_name.call(this);
+        _object.is_indefinite_form = this.is_indefinite_form;
+        _object.value = new Array();
+        for(var i = 0; i < this.value.length; i++)
+            _object.value.push(this.value[i].toJSON());
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED =
+    function()
+    {
+        /// <summary>Base class of ASN.1 block for constructive values (constructive encoding)</summary>
+
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.is_constructed = true;
+        this.value_block = new local.ASN1_CONSTRUCTED_value_block(arguments[0]);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.constructor = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "CONSTRUCTED";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 EOC type class
+    //**************************************************************************************
+    local.EOC_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype = new local.value_block();
+    local.EOC_value_block.constructor = local.EOC_value_block;
+    //**************************************************************************************
+    local.EOC_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region There is no "value block" for EOC type and we need to return the same offset 
+        return input_offset;
+        // #endregion 
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "EOC_value_block";
+    };
+    //**************************************************************************************
+    local.EOC_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.EOC_value_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.EOC_value_block();
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 0; // EOC
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.EOC.constructor = local.EOC_value_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "END_OF_CONTENT";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.EOC.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.EOC.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 BOOLEAN type class
+    //**************************************************************************************
+    local.BOOLEAN_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", false);
+
+            // #region Variables from hex_block class 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+            {
+                this.value_hex = new ArrayBuffer(1);
+                if(this.value === true)
+                {
+                    var view = new Uint8Array(this.value_hex);
+                    view[0] = 0xFF;
+                }
+            }
+            // #endregion 
+        }
+        else
+        {
+            this.value = false;
+
+            // #region Variables from hex_block class 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(1);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype = new local.value_block();
+    local.BOOLEAN_value_block.constructor = local.BOOLEAN_value_block;
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        if(input_length > 1)
+            this.warnings.push("BOOLEAN value encoded in more then 1 octet");
+
+        this.value = int_buffer[0] != 0x00;
+
+        this.is_hex_only = true;
+
+        // #region Copy input buffer to internal array 
+        this.value_hex = new ArrayBuffer(int_buffer.length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < int_buffer.length; i++)
+            view[i] = int_buffer[i];
+        // #endregion 
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        return this.value_hex;
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BOOLEAN_value_block";
+    };
+    //**************************************************************************************
+    local.BOOLEAN_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BOOLEAN_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BOOLEAN_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 1; // BOOLEAN
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BOOLEAN.constructor = local.BOOLEAN_value_block;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BOOLEAN";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BOOLEAN.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BOOLEAN.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 SEQUENCE and SET type classes
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 16; // SEQUENCE
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+    in_window.org.pkijs.asn1.SEQUENCE.constructor = in_window.org.pkijs.asn1.SEQUENCE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SEQUENCE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SEQUENCE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.SEQUENCE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 17; // SET
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+    in_window.org.pkijs.asn1.SET.constructor = in_window.org.pkijs.asn1.SET;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SET";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.SET.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.SET.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 NULL type class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 5; // NULL
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.NULL.constructor = in_window.org.pkijs.asn1.NULL;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "NULL";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        if(this.len_block.length > 0)
+            this.warnings.push("Non-zero length of value block for NULL type");
+
+        if(this.id_block.error.length === 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length === 0)
+            this.block_length += this.len_block.block_length;
+
+        this.block_length += input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(2);
+
+        if(size_only === true)
+            return ret_buf;
+
+        var ret_view = new Uint8Array(ret_buf);
+        ret_view[0] = 0x05;
+        ret_view[1] = 0x00;
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NULL.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.NULL.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 OCTETSTRING type class 
+    //**************************************************************************************
+    local.OCTETSTRING_value_block =
+    function()
+    {
+        /// <param name="input_value_hex" type="ArrayBuffer"></param>
+        /// <param name="input_value" type="Array"></param>
+        /// <param name="input_constructed" type="Boolean"></param>
+        /// <remarks>Value for the OCTETSTRING may be as hex, as well as a constructed value.</remarks>
+        /// <remarks>Constructed values consists of other OCTETSTRINGs</remarks>
+
+        local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+        else
+        {
+            this.is_constructed = false;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block();
+    local.OCTETSTRING_value_block.constructor = local.OCTETSTRING_value_block;
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = 0;
+
+        if(this.is_constructed == true)
+        {
+            this.is_hex_only = false;
+
+            result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            if(result_offset == (-1))
+                return result_offset;
+
+            for(var i = 0; i < this.value.length; i++)
+            {
+                var current_block_name = this.value[i].block_name();
+
+                if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                {
+                    if(this.is_indefinite_form == true)
+                        break;
+                    else
+                    {
+                        this.error = "EOC is unexpected, OCTET STRING may consists of OCTET STRINGs only";
+                        return (-1);
+                    }
+                }
+
+                if(current_block_name != in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name())
+                {
+                    this.error = "OCTET STRING may consists of OCTET STRINGs only";
+                    return (-1);
+                }
+            }
+        }
+        else
+        {
+            this.is_hex_only = true;
+
+            result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            this.block_length = input_length;
+        }
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_constructed === true)
+            return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only);
+        else
+        {
+            var ret_buf = new ArrayBuffer(this.value_hex.byteLength);
+
+            if(size_only === true)
+                return ret_buf;
+
+            if(this.value_hex.byteLength == 0)
+                return ret_buf;
+
+            ret_buf = util_copybuf(this.value_hex);
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OCTETSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.OCTETSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.OCTETSTRING_value_block.prototype.block_name.call(this);
+        _object.is_constructed = this.is_constructed;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.OCTETSTRING_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 4; // OCTETSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.OCTETSTRING.constructor = in_window.org.pkijs.asn1.OCTETSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        this.value_block.is_constructed = this.id_block.is_constructed;
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        // #region Ability to encode empty OCTET STRING 
+        if(input_length == 0)
+        {
+            if(this.id_block.error.length == 0)
+                this.block_length += this.id_block.block_length;
+
+            if(this.len_block.error.length == 0)
+                this.block_length += this.len_block.block_length;
+
+            return input_offset;
+        }
+        // #endregion 
+
+        return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name =
+    function()
+    {
+        return "OCTETSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.OCTETSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OCTETSTRING.prototype.isEqual =
+    function(octetString)
+    {
+        /// <summaryChecking that two OCTETSTRINGs are equal></summary>
+        /// <param name="octetString" type="in_window.org.pkijs.asn1.OCTETSTRING">The OCTETSTRING to compare with</param>
+
+        // #region Check input type 
+        if((octetString instanceof in_window.org.pkijs.asn1.OCTETSTRING) == false)
+            return false;
+        // #endregion 
+
+        // #region Compare two JSON strings 
+        if(JSON.stringify(this) != JSON.stringify(octetString))
+            return false;
+        // #endregion 
+
+        return true;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 BITSTRING type class
+    //**************************************************************************************
+    local.BITSTRING_value_block =
+    function()
+    {
+        local.ASN1_CONSTRUCTED_value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.unused_bits = in_window.org.pkijs.getValue(arguments[0], "unused_bits", 0);
+            this.is_constructed = in_window.org.pkijs.getValue(arguments[0], "is_constructed", false);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+
+            if("value_hex" in arguments[0])
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+            else
+                this.value_hex = new ArrayBuffer(0);
+
+            this.block_length = this.value_hex.byteLength;
+            // #endregion 
+        }
+        else
+        {
+            this.unused_bits = 0;
+            this.is_constructed = false;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype = new local.ASN1_CONSTRUCTED_value_block();
+    local.BITSTRING_value_block.constructor = local.BITSTRING_value_block;
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Ability to decode zero-length BITSTRING value 
+        if(input_length == 0)
+            return input_offset;
+        // #endregion 
+
+        var result_offset = (-1);
+
+        // #region If the BISTRING supposed to be a constructed value 
+        if(this.is_constructed == true)
+        {
+            result_offset = local.ASN1_CONSTRUCTED_value_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+            if(result_offset == (-1))
+                return result_offset;
+
+            for(var i = 0; i < this.value.length; i++)
+            {
+                var current_block_name = this.value[i].block_name();
+
+                if(current_block_name == in_window.org.pkijs.asn1.EOC.prototype.block_name())
+                {
+                    if(this.is_indefinite_form == true)
+                        break;
+                    else
+                    {
+                        this.error = "EOC is unexpected, BIT STRING may consists of BIT STRINGs only";
+                        return (-1);
+                    }
+                }
+
+                if(current_block_name != in_window.org.pkijs.asn1.BITSTRING.prototype.block_name())
+                {
+                    this.error = "BIT STRING may consists of BIT STRINGs only";
+                    return (-1);
+                }
+
+                if((this.unused_bits > 0) && (this.value[i].unused_bits > 0))
+                {
+                    this.error = "Usign of \"unused bits\" inside constructive BIT STRING allowed for least one only";
+                    return (-1);
+                }
+                else
+                {
+                    this.unused_bits = this.value[i].unused_bits;
+                    if(this.unused_bits > 7)
+                    {
+                        this.error = "Unused bits for BITSTRING must be in range 0-7";
+                        return (-1);
+                    }
+                }
+            }
+
+            return result_offset;
+        }
+            // #endregion 
+        // #region If the BITSTRING supposed to be a primitive value
+        else
+        {
+            // #region Basic check for parameters 
+            if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+                return (-1);
+            // #endregion 
+
+            var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+
+            this.unused_bits = int_buffer[0];
+            if(this.unused_bits > 7)
+            {
+                this.error = "Unused bits for BITSTRING must be in range 0-7";
+                return (-1);
+            }
+
+            // #region Copy input buffer to internal buffer 
+            this.value_hex = new ArrayBuffer(int_buffer.length - 1);
+            var view = new Uint8Array(this.value_hex);
+            for(var i = 0; i < (input_length - 1) ; i++)
+                view[i] = int_buffer[i + 1];
+            // #endregion 
+
+            this.block_length = int_buffer.length;
+
+            return (input_offset + input_length);
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_constructed === true)
+            return local.ASN1_CONSTRUCTED_value_block.prototype.toBER.call(this, size_only);
+        else
+        {
+            if(size_only === true)
+                return (new ArrayBuffer(this.value_hex.byteLength + 1));
+
+            if(this.value_hex.byteLength == 0)
+                return (new ArrayBuffer(0));
+
+            var cur_view = new Uint8Array(this.value_hex);
+
+            var ret_buf = new ArrayBuffer(this.value_hex.byteLength + 1);
+            var ret_view = new Uint8Array(ret_buf);
+
+            ret_view[0] = this.unused_bits;
+
+            for(var i = 0; i < this.value_hex.byteLength; i++)
+                ret_view[i + 1] = cur_view[i];
+
+            return ret_buf;
+        }
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BITSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.BITSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.ASN1_CONSTRUCTED_value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BITSTRING_value_block.prototype.block_name.call(this);
+        _object.unused_bits = this.unused_bits;
+        _object.is_constructed = this.is_constructed;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BITSTRING_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 3; // BITSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BITSTRING.constructor = in_window.org.pkijs.asn1.BITSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BITSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        // #region Ability to encode empty BITSTRING 
+        if(input_length == 0)
+            return input_offset;
+        // #endregion 
+
+        this.value_block.is_constructed = this.id_block.is_constructed;
+        this.value_block.is_indefinite_form = this.len_block.is_indefinite_form;
+
+        return in_window.org.pkijs.asn1.ASN1_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BITSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BITSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 INTEGER type class 
+    //**************************************************************************************
+    local.INTEGER_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value", 0);
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = in_window.org.pkijs.getValue(arguments[0], "is_hex_only", false);
+            if("value_hex" in arguments[0])
+            {
+                this.value_hex = util_copybuf(arguments[0].value_hex);
+
+                if(this.value_hex.byteLength >= 4) // Dummy's protection
+                    this.is_hex_only = true;
+                else
+                    this.value_dec = util_decode_tc.call(this);
+            }
+            else
+                this.value_hex = util_encode_tc(this.value_dec);
+            // #endregion 
+        }
+        else
+        {
+            this.value_dec = 0;
+
+            // #region Variables from hex_block type 
+            this.is_hex_only = false;
+            this.value_hex = new ArrayBuffer(0);
+            // #endregion 
+        }
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype = new local.value_block();
+    local.INTEGER_value_block.constructor = local.INTEGER_value_block;
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = local.hex_block.prototype.fromBER.call(this, input_buffer, input_offset, input_length);
+        if(result_offset == (-1))
+            return result_offset;
+
+        if(this.value_hex.byteLength > 4) // In JavaScript we can effectively work with 32-bit integers only
+        {
+            this.warnings.push("Too big INTEGER for decoding, hex only");
+            this.is_hex_only = true;
+        }
+        else
+            this.value_dec = util_decode_tc.call(this);
+
+        this.block_length = input_length;
+
+        return (input_offset + input_length);
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only === false)
+        {
+            var encoded_buf = util_encode_tc(this.value_dec);
+            if(encoded_buf.byteLength == 0)
+            {
+                this.error = "Error during encoding INTEGER value";
+                return (new ArrayBuffer(0));
+            }
+
+            return util_copybuf(encoded_buf);
+        }
+        else
+            return util_copybuf(this.value_hex);
+
+        return (new ArrayBuffer(0));
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "INTEGER_value_block";
+    };
+    //**************************************************************************************
+    local.INTEGER_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.INTEGER_value_block.prototype.block_name.call(this);
+        _object.value_dec = this.value_dec;
+        _object.is_hex_only = this.is_hex_only;
+        _object.value_hex = in_window.org.pkijs.bufferToHexCodes(this.value_hex, 0, this.value_hex.byteLength);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.INTEGER_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 2; // INTEGER
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.INTEGER.constructor = in_window.org.pkijs.asn1.INTEGER;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "INTEGER";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.isEqual =
+    function()
+    {
+        /// <summary>Compare two INTEGER object, or INTEGER and ArrayBuffer objects</summary>
+        /// <returns type="Boolean"></returns>
+
+        if(arguments[0] instanceof in_window.org.pkijs.asn1.INTEGER)
+        {
+            if(this.value_block.is_hex_only && arguments[0].value_block.is_hex_only) // Compare two ArrayBuffers
+                return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0].value_block.value_hex);
+            else
+            {
+                if(this.value_block.is_hex_only === arguments[0].value_block.is_hex_only)
+                    return (this.value_block.value_dec == arguments[0].value_block.value_dec);
+                else
+                    return false;
+            }
+        }
+        else
+        {
+            if(arguments[0] instanceof ArrayBuffer)
+                return in_window.org.pkijs.isEqual_buffer(this.value_block.value_hex, arguments[0]);
+            else
+                return false;
+        }
+
+        return false;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.INTEGER.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.INTEGER.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 ENUMERATED type class 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED =
+    function()
+    {
+        in_window.org.pkijs.asn1.INTEGER.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 10; // ENUMERATED
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype = new in_window.org.pkijs.asn1.INTEGER();
+    in_window.org.pkijs.asn1.ENUMERATED.constructor = in_window.org.pkijs.asn1.ENUMERATED;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "ENUMERATED";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ENUMERATED.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.INTEGER.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.ENUMERATED.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of ASN.1 OBJECT IDENTIFIER type class 
+    //**************************************************************************************
+    local.SID_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        if(arguments[0] instanceof Object)
+        {
+            this.value_dec = in_window.org.pkijs.getValue(arguments[0], "value_dec", -1);
+            this.is_first_sid = in_window.org.pkijs.getValue(arguments[0], "is_first_sid", false);
+        }
+        else
+        {
+            this.value_dec = (-1);
+            this.is_first_sid = false;
+        }
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype = new local.hex_block();
+    local.SID_value_block.constructor = local.SID_value_block;
+    //**************************************************************************************
+    local.SID_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "sid_block";
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        if(input_length == 0)
+            return input_offset;
+
+        // #region Basic check for parameters 
+        if(check_buffer_params.call(this, input_buffer, input_offset, input_length) === false)
+            return (-1);
+        // #endregion 
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+
+        this.value_hex = new ArrayBuffer(input_length);
+        var view = new Uint8Array(this.value_hex);
+
+        for(var i = 0; i < input_length; i++)
+        {
+            view[i] = int_buffer[i] & 0x7F;
+
+            this.block_length++;
+
+            if((int_buffer[i] & 0x80) == 0x00)
+                break;
+        }
+
+        // #region Ajust size of value_hex buffer 
+        var temp_value_hex = new ArrayBuffer(this.block_length);
+        var temp_view = new Uint8Array(temp_value_hex);
+
+        for(var i = 0; i < this.block_length; i++)
+            temp_view[i] = view[i];
+
+        this.value_hex = util_copybuf(temp_value_hex);
+        view = new Uint8Array(this.value_hex);
+        // #endregion   
+
+        if((int_buffer[this.block_length - 1] & 0x80) != 0x00)
+        {
+            this.error = "End of input reached before message was fully decoded";
+            return (-1);
+        }
+
+        if(view[0] == 0x00)
+            this.warnings.push("Needlessly long format of SID encoding");
+
+        if(this.block_length <= 8)
+            this.value_dec = util_frombase(view, 7);
+        else
+        {
+            this.is_hex_only = true;
+            this.warnings.push("Too big SID for decoding, hex only");
+        }
+
+        return (input_offset + this.block_length);
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        if(this.is_hex_only)
+        {
+            if(size_only === true)
+                return (new ArrayBuffer(this.value_hex.byteLength));
+
+            var cur_view = new Uint8Array(this.value_hex);
+
+            var ret_buf = new ArrayBuffer(this.block_length);
+            var ret_view = new Uint8Array(ret_buf);
+
+            for(var i = 0; i < (this.block_length - 1) ; i++)
+                ret_view[i] = cur_view[i] | 0x80;
+
+            ret_view[this.block_length - 1] = cur_view[this.block_length - 1];
+
+            return ret_buf;
+        }
+        else
+        {
+            var encoded_buf = util_tobase(this.value_dec, 7);
+            if(encoded_buf.byteLength === 0)
+            {
+                this.error = "Error during encoding SID value";
+                return (new ArrayBuffer(0));
+            }
+
+            var ret_buf = new ArrayBuffer(encoded_buf.byteLength);
+
+            if(size_only === false)
+            {
+                var encoded_view = new Uint8Array(encoded_buf);
+                var ret_view = new Uint8Array(ret_buf);
+
+                for(var i = 0; i < (encoded_buf.byteLength - 1) ; i++)
+                    ret_view[i] = encoded_view[i] | 0x80;
+
+                ret_view[encoded_buf.byteLength - 1] = encoded_view[encoded_buf.byteLength - 1];
+            }
+
+            return ret_buf;
+        }
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toString =
+    function()
+    {
+        var result = "";
+
+        if(this.is_hex_only === true)
+            result = to_hex_codes(this.value_hex);
+        else
+        {
+            if(this.is_first_sid)
+            {
+                var sid_value = this.value_dec;
+
+                if(this.value_dec <= 39)
+                    result = "0.";
+                else
+                {
+                    if(this.value_dec <= 79)
+                    {
+                        result = "1.";
+                        sid_value -= 40;
+                    }
+                    else
+                    {
+                        result = "2.";
+                        sid_value -= 80;
+                    }
+                }
+
+                result = result + sid_value.toString();
+            }
+            else
+                result = this.value_dec.toString();
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    local.SID_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SID_value_block.prototype.block_name.call(this);
+        _object.value_dec = this.value_dec;
+        _object.is_first_sid = this.is_first_sid;
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.OID_value_block =
+    function()
+    {
+        local.value_block.call(this, arguments[0]);
+
+        this.value = new Array();
+
+        if(arguments[0] instanceof Object)
+            this.fromString(in_window.org.pkijs.getValue(arguments[0], "value", ""));
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype = new local.value_block();
+    local.OID_value_block.constructor = local.OID_value_block;
+    //**************************************************************************************
+    local.OID_value_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = input_offset;
+
+        while(input_length > 0)
+        {
+            var sid_block = new local.SID_value_block();
+            result_offset = sid_block.fromBER(input_buffer, result_offset, input_length);
+            if(result_offset == (-1))
+            {
+                this.block_length = 0;
+                this.error = sid_block.error;
+                return result_offset;
+            }
+
+            if(this.value.length == 0)
+                sid_block.is_first_sid = true;
+
+            this.block_length += sid_block.block_length;
+            input_length -= sid_block.block_length;
+
+            this.value.push(sid_block);
+        }
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toBER =
+    function(size_only)
+    {
+        /// <summary>Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)</summary>
+        /// <param name="size_only" type="Boolean">Flag that we need only a size of encoding, not a real array of bytes</param>
+
+        if(typeof size_only === "undefined")
+            size_only = false;
+
+        var ret_buf = new ArrayBuffer(0);
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            var value_buf = this.value[i].toBER(size_only);
+            if(value_buf.byteLength === 0)
+            {
+                this.error = this.value[i].error;
+                return (new ArrayBuffer(0));
+            }
+
+            ret_buf = util_concatbuf(ret_buf, value_buf);
+        }
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.fromString =
+    function(str)
+    {
+        this.value = new Array(); // Clear existing SID values
+
+        var pos1 = 0;
+        var pos2 = 0;
+
+        var sid = "";
+
+        var flag = false;
+
+        do
+        {
+            pos2 = str.indexOf('.', pos1);
+            if(pos2 === (-1))
+                sid = str.substr(pos1);
+            else
+                sid = str.substr(pos1, pos2 - pos1);
+
+            pos1 = pos2 + 1;
+
+            if(flag)
+            {
+                var sid_block = this.value[0];
+
+                var plus = 0;
+
+                switch(sid_block.value_dec)
+                {
+                    case 0:
+                        break;
+                    case 1:
+                        plus = 40;
+                        break;
+                    case 2:
+                        plus = 80;
+                        break;
+                    default:
+                        this.value = new Array(); // clear SID array
+                        return false; // ???
+                }
+
+                var parsedSID = parseInt(sid, 10);
+                if(isNaN(parsedSID))
+                    return true;
+
+                sid_block.value_dec = parsedSID + plus;
+
+                flag = false;
+            }
+            else
+            {
+                var sid_block = new local.SID_value_block();
+                sid_block.value_dec = parseInt(sid, 10);
+                if(isNaN(sid_block.value_dec))
+                    return true;
+
+                if(this.value.length === 0)
+                {
+                    sid_block.is_first_sid = true;
+                    flag = true;
+                }
+
+                this.value.push(sid_block);
+            }
+
+        } while(pos2 !== (-1));
+
+        return true;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toString =
+    function()
+    {
+        var result = "";
+        var is_hex_only = false;
+
+        for(var i = 0; i < this.value.length; i++)
+        {
+            is_hex_only = this.value[i].is_hex_only;
+
+            var sid_str = this.value[i].toString();
+
+            if(i !== 0)
+                result = result + ".";
+
+            if(is_hex_only)
+            {
+                sid_str = "{" + sid_str + "}";
+
+                if(this.value[i].is_first_sid)
+                    result = "2.{" + sid_str + " - 80}";
+                else
+                    result = result + sid_str;
+            }
+            else
+                result = result + sid_str;
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OID_value_block";
+    };
+    //**************************************************************************************
+    local.OID_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.value_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.OID_value_block.prototype.block_name.call(this);
+        _object.value = local.OID_value_block.prototype.toString.call(this);
+        _object.sid_array = new Array();
+        for(var i = 0; i < this.value.length; i++)
+            _object.sid_array.push(this.value[i].toJSON());
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.OID_value_block(arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 6; // OBJECT IDENTIFIER
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.OID.constructor = in_window.org.pkijs.asn1.OID;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "OID";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.OID.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.OID.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion   
+    //**************************************************************************************
+    // #region Declaration of all string's classes 
+    //**************************************************************************************
+    local.UTF8STRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = ""; // String representation of decoded ArrayBuffer
+    };
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype = new local.hex_block();
+    local.UTF8STRING_value_block.constructor = local.UTF8STRING_value_block;
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTF8STRING_value_block";
+    };
+    //**************************************************************************************
+    local.UTF8STRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.UTF8STRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.UTF8STRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString.call(this,arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 12; // UTF8STRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.UTF8STRING.constructor = in_window.org.pkijs.asn1.UTF8STRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTF8STRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+        this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer));
+
+        try
+        {
+            this.value_block.value = decodeURIComponent(escape(this.value_block.value));
+        }
+        catch(ex)
+        {
+            this.warnings.push("Error during \"decodeURIComponent\": " + ex + ", using raw string");
+        }
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str = unescape(encodeURIComponent(input_string));
+        var str_len = str.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_len);
+        var view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_len; i++)
+            view[i] = str.charCodeAt(i);
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UTF8STRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = "";
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype = new local.hex_block();
+    local.BMPSTRING_value_block.constructor = local.BMPSTRING_value_block;
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BMPSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.BMPSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.BMPSTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.BMPSTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString.call(this, arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 30; // BMPSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.BMPSTRING.constructor = in_window.org.pkijs.asn1.BMPSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "BMPSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer);
+
+        var value_view = new Uint8Array(copy_buffer);
+
+        for(var i = 0; i < value_view.length; i = i + 2)
+        {
+            var temp = value_view[i];
+
+            value_view[i] = value_view[i + 1];
+            value_view[i + 1] = temp;
+        }
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint16Array(copy_buffer));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str_length = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_length * 2);
+        var value_hex_view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_length; i++)
+        {
+            var code_buf = util_tobase(input_string.charCodeAt(i), 8);
+            var code_view = new Uint8Array(code_buf);
+            if(code_view.length > 2)
+                continue;
+
+            var dif = 2 - code_view.length;
+
+            for(var j = (code_view.length - 1) ; j >= 0; j--)
+                value_hex_view[i * 2 + j + dif] = code_view[j];
+        }
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.BMPSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.BMPSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        this.is_hex_only = true;
+        this.value = "";
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype = new local.hex_block();
+    local.UNIVERSALSTRING_value_block.constructor = local.UNIVERSALSTRING_value_block;
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UNIVERSALSTRING_value_block";
+    };
+    //**************************************************************************************
+    local.UNIVERSALSTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.UNIVERSALSTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.UNIVERSALSTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString.call(this, arguments[0].value);
+        }
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 28; // UNIVERSALSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.constructor = in_window.org.pkijs.asn1.UNIVERSALSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UNIVERSALSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        var copy_buffer = in_window.org.pkijs.copyBuffer(input_buffer);
+
+        var value_view = new Uint8Array(copy_buffer);
+
+        for(var i = 0; i < value_view.length; i = i + 4)
+        {
+            value_view[i] = value_view[i + 3];
+            value_view[i + 1] = value_view[i + 2];
+            value_view[i + 2] = 0x00;
+            value_view[i + 3] = 0x00;
+        }
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint32Array(copy_buffer));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+
+        var str_length = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_length * 4);
+        var value_hex_view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_length; i++)
+        {
+            var code_buf = util_tobase(input_string.charCodeAt(i), 8);
+            var code_view = new Uint8Array(code_buf);
+            if(code_view.length > 4)
+                continue;
+
+            var dif = 4 - code_view.length;
+
+            for(var j = (code_view.length - 1) ; j >= 0; j--)
+                value_hex_view[i*4 + j + dif] = code_view[j];
+        }
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UNIVERSALSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block =
+    function()
+    {
+        local.hex_block.call(this, arguments[0]);
+
+        /// <field type="String">Native string representation</field>
+        this.value = "";
+        this.is_hex_only = true;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype = new local.hex_block();
+    local.SIMPLESTRING_value_block.constructor = local.SIMPLESTRING_value_block;
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SIMPLESTRING_value_block";
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_value_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.hex_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SIMPLESTRING_value_block.prototype.block_name.call(this);
+        _object.value = this.value;
+
+        return _object;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block =
+    function()
+    {
+        in_window.org.pkijs.asn1.ASN1_block.call(this, arguments[0]);
+
+        this.value_block = new local.SIMPLESTRING_value_block();
+
+        if(arguments[0] instanceof Object)
+        {
+            if("value" in arguments[0])
+                local.SIMPLESTRING_block.prototype.fromString.call(this, arguments[0].value);
+        }
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype = new in_window.org.pkijs.asn1.ASN1_block();
+    local.SIMPLESTRING_block.constructor = local.SIMPLESTRING_block;
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "SIMPLESTRING";
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        local.SIMPLESTRING_block.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        /// <param name="input_buffer" type="ArrayBuffer">Array with encoded string</param>
+
+        this.value_block.value = String.fromCharCode.apply(null, new Uint8Array(input_buffer));
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.fromString =
+    function(input_string)
+    {
+        /// <param name="input_string" type="String">String with UNIVERSALSTRING value</param>
+        var str_len = input_string.length;
+
+        this.value_block.value_hex = new ArrayBuffer(str_len);
+        var view = new Uint8Array(this.value_block.value_hex);
+
+        for(var i = 0; i < str_len; i++)
+            view[i] = input_string.charCodeAt(i);
+
+        this.value_block.value = input_string;
+    };
+    //**************************************************************************************
+    local.SIMPLESTRING_block.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.ASN1_block.prototype.toJSON.call(this);
+
+        _object.block_name = local.SIMPLESTRING_block.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 18; // NUMERICSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.NUMERICSTRING.constructor = in_window.org.pkijs.asn1.NUMERICSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "NUMERICSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.NUMERICSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.NUMERICSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 19; // PRINTABLESTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.PRINTABLESTRING.constructor = in_window.org.pkijs.asn1.PRINTABLESTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "PRINTABLESTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.PRINTABLESTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 20; // TELETEXSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.TELETEXSTRING.constructor = in_window.org.pkijs.asn1.TELETEXSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TELETEXSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TELETEXSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TELETEXSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 21; // VIDEOTEXSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.constructor = in_window.org.pkijs.asn1.VIDEOTEXSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "VIDEOTEXSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.VIDEOTEXSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 22; // IA5STRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.IA5STRING.constructor = in_window.org.pkijs.asn1.IA5STRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "IA5STRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.IA5STRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.IA5STRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 25; // GRAPHICSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.GRAPHICSTRING.constructor = in_window.org.pkijs.asn1.GRAPHICSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GRAPHICSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GRAPHICSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 26; // VISIBLESTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.VISIBLESTRING.constructor = in_window.org.pkijs.asn1.VISIBLESTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "VISIBLESTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 27; // GENERALSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.GENERALSTRING.constructor = in_window.org.pkijs.asn1.GENERALSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GENERALSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GENERALSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING =
+    function()
+    {
+        local.SIMPLESTRING_block.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 29; // CHARACTERSTRING
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype = new local.SIMPLESTRING_block();
+    in_window.org.pkijs.asn1.CHARACTERSTRING.constructor = in_window.org.pkijs.asn1.CHARACTERSTRING;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "CHARACTERSTRING";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = local.SIMPLESTRING_block.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.CHARACTERSTRING.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of all date and time classes 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]);
+
+        this.year = 0;
+        this.month = 0;
+        this.day = 0;
+        this.hour = 0;
+        this.minute = 0;
+        this.second = 0;
+
+        // #region Create UTCTIME from ASN.1 UTC string value 
+        if((arguments[0] instanceof Object) && ("value" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, arguments[0].value);
+
+            this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length);
+            var view = new Uint8Array(this.value_block.value_hex);
+
+            for(var i = 0; i < arguments[0].value.length; i++)
+                view[i] = arguments[0].value.charCodeAt(i);
+        }
+        // #endregion 
+        // #region Create UTCTIME from JavaScript Date type 
+        if((arguments[0] instanceof Object) && ("value_date" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate.call(this, arguments[0].value_date);
+            this.value_block.value_hex = in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer.call(this);
+        }
+        // #endregion 
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 23; // UTCTIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING();
+    in_window.org.pkijs.asn1.UTCTIME.constructor = in_window.org.pkijs.asn1.UTCTIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        in_window.org.pkijs.asn1.UTCTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toBuffer =
+    function()
+    {
+        var str = in_window.org.pkijs.asn1.UTCTIME.prototype.toString.call(this);
+
+        var buffer = new ArrayBuffer(str.length);
+        var view = new Uint8Array(buffer);
+
+        for(var i = 0; i < str.length; i++)
+            view[i] = str.charCodeAt(i);
+
+        return buffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromDate =
+    function(input_date)
+    {
+        /// <summary>Create "UTCTime" ASN.1 type from JavaScript "Date" type</summary>
+
+        this.year = input_date.getUTCFullYear();
+        this.month = input_date.getUTCMonth() + 1;
+        this.day = input_date.getUTCDate();
+        this.hour = input_date.getUTCHours();
+        this.minute = input_date.getUTCMinutes();
+        this.second = input_date.getUTCSeconds();
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toDate =
+    function()
+    {
+        return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.fromString =
+    function(input_string)
+    {
+        /// <summary>Create "UTCTime" ASN.1 type from JavaScript "String" type</summary>
+
+        // #region Parse input string 
+        var parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
+        var parser_array = parser.exec(input_string);
+        if(parser_array === null)
+        {
+            this.error = "Wrong input string for convertion";
+            return;
+        }
+        // #endregion 
+
+        // #region Store parsed values 
+        var year = parseInt(parser_array[1], 10);
+        if(year >= 50)
+            this.year = 1900 + year;
+        else
+            this.year = 2000 + year;
+
+        this.month = parseInt(parser_array[2], 10);
+        this.day = parseInt(parser_array[3], 10);
+        this.hour = parseInt(parser_array[4], 10);
+        this.minute = parseInt(parser_array[5], 10);
+        this.second = parseInt(parser_array[6], 10);
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toString =
+    function()
+    {
+        var output_array = new Array(7);
+
+        output_array[0] = in_window.org.pkijs.padNumber(((this.year < 2000) ? (this.year - 1900) : (this.year - 2000)), 2);
+        output_array[1] = in_window.org.pkijs.padNumber(this.month, 2);
+        output_array[2] = in_window.org.pkijs.padNumber(this.day, 2);
+        output_array[3] = in_window.org.pkijs.padNumber(this.hour, 2);
+        output_array[4] = in_window.org.pkijs.padNumber(this.minute, 2);
+        output_array[5] = in_window.org.pkijs.padNumber(this.second, 2);
+        output_array[6] = "Z";
+
+        return output_array.join('');
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "UTCTIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.UTCTIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.UTCTIME.prototype.block_name.call(this);
+        _object.year = this.year;
+        _object.month = this.month;
+        _object.day = this.day;
+        _object.hour = this.hour;
+        _object.minute = this.minute;
+        _object.second = this.second;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.VISIBLESTRING.call(this, arguments[0]);
+
+        this.year = 0;
+        this.month = 0;
+        this.day = 0;
+        this.hour = 0;
+        this.minute = 0;
+        this.second = 0;
+        this.millisecond = 0;
+
+        // #region Create GeneralizedTime from ASN.1 string value 
+        if((arguments[0] instanceof Object) && ("value" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, arguments[0].value);
+
+            this.value_block.value_hex = new ArrayBuffer(arguments[0].value.length);
+            var view = new Uint8Array(this.value_block.value_hex);
+
+            for(var i = 0; i < arguments[0].value.length; i++)
+                view[i] = arguments[0].value.charCodeAt(i);
+        }
+        // #endregion 
+        // #region Create GeneralizedTime from JavaScript Date type 
+        if((arguments[0] instanceof Object) && ("value_date" in arguments[0]))
+        {
+            in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate.call(this, arguments[0].value_date);
+            this.value_block.value_hex = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer.call(this);
+        }
+        // #endregion 
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 24; // GENERALIZEDTIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype = new in_window.org.pkijs.asn1.VISIBLESTRING();
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.constructor = in_window.org.pkijs.asn1.GENERALIZEDTIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBER =
+    function(input_buffer, input_offset, input_length)
+    {
+        /// <summary>Base function for converting block from BER encoded array of bytes</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array</param>
+        /// <param name="input_offset" type="Number">Offset in ASN.1 BER encoded array where decoding should be started</param>
+        /// <param name="input_length" type="Number">Maximum length of array of bytes which can be using in this function</param>
+
+        var result_offset = this.value_block.fromBER(input_buffer, input_offset, (this.len_block.is_indefinite_form == true) ? input_length : this.len_block.length);
+        if(result_offset == (-1))
+        {
+            this.error = this.value_block.error;
+            return result_offset;
+        }
+
+        in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer.call(this, this.value_block.value_hex);
+
+        if(this.id_block.error.length == 0)
+            this.block_length += this.id_block.block_length;
+
+        if(this.len_block.error.length == 0)
+            this.block_length += this.len_block.block_length;
+
+        if(this.value_block.error.length == 0)
+            this.block_length += this.value_block.block_length;
+
+        return result_offset;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromBuffer =
+    function(input_buffer)
+    {
+        in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString.call(this, String.fromCharCode.apply(null, new Uint8Array(input_buffer)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toBuffer =
+    function()
+    {
+        var str = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString.call(this);
+
+        var buffer = new ArrayBuffer(str.length);
+        var view = new Uint8Array(buffer);
+
+        for(var i = 0; i < str.length; i++)
+            view[i] = str.charCodeAt(i);
+
+        return buffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromDate =
+    function(input_date)
+    {
+        /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "Date" type</summary>
+
+        this.year = input_date.getUTCFullYear();
+        this.month = input_date.getUTCMonth();
+        this.day = input_date.getUTCDate();
+        this.hour = input_date.getUTCHours();
+        this.minute = input_date.getUTCMinutes();
+        this.second = input_date.getUTCSeconds();
+        this.millisecond = input_date.getUTCMilliseconds();
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toDate =
+    function()
+    {
+        return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond)));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.fromString =
+    function(input_string)
+    {
+        /// <summary>Create "GeneralizedTime" ASN.1 type from JavaScript "String" type</summary>
+
+        // #region Initial variables 
+        var isUTC = false;
+
+        var timeString = "";
+        var dateTimeString = "";
+        var fractionPart = 0;
+
+        var parser;
+
+        var hourDifference = 0;
+        var minuteDifference = 0;
+        // #endregion 
+
+        // #region Convert as UTC time 
+        if(input_string[input_string.length - 1] == "Z")
+        {
+            timeString = input_string.substr(0, input_string.length - 1);
+
+            isUTC = true;
+        }
+        // #endregion 
+        // #region Convert as local time 
+        else
+        {
+            var number = new Number(input_string[input_string.length - 1]);
+
+            if(isNaN(number.valueOf()))
+                throw new Error("Wrong input string for convertion");
+
+            timeString = input_string;
+        }
+        // #endregion 
+
+        // #region Check that we do not have a "+" and "-" symbols inside UTC time 
+        if(isUTC)
+        {
+            if(timeString.indexOf("+") != (-1))
+                throw new Error("Wrong input string for convertion");
+
+            if(timeString.indexOf("-") != (-1))
+                throw new Error("Wrong input string for convertion");
+        }
+        // #endregion 
+        // #region Get "UTC time difference" in case of local time
+        else
+        {
+            var multiplier = 1;
+            var differencePosition = timeString.indexOf("+");
+            var differenceString = "";
+
+            if(differencePosition == (-1))
+            {
+                differencePosition = timeString.indexOf("-");
+                multiplier = (-1);
+            }
+
+            if(differencePosition != (-1))
+            {
+                differenceString = timeString.substr(differencePosition + 1);
+                timeString = timeString.substr(0, differencePosition);
+
+                if((differenceString.length != 2) && (differenceString.length != 4))
+                    throw new Error("Wrong input string for convertion");
+
+                var number = new Number(differenceString.substr(0, 2));
+
+                if(isNaN(number.valueOf()))
+                    throw new Error("Wrong input string for convertion");
+
+                hourDifference = multiplier * number;
+
+                if(differenceString.length == 4)
+                {
+                    number = new Number(differenceString.substr(2, 2));
+
+                    if(isNaN(number.valueOf()))
+                        throw new Error("Wrong input string for convertion");
+
+                    minuteDifference = multiplier * number;
+                }
+            }
+        }
+        // #endregion 
+
+        // #region Get position of fraction point 
+        var fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
+        if(fractionPointPosition == (-1))
+            fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
+        // #endregion 
+
+        // #region Get fraction part 
+        if(fractionPointPosition != (-1))
+        {
+            var fractionPartCheck = new Number("0" + timeString.substr(fractionPointPosition));
+
+            if(isNaN(fractionPartCheck.valueOf()))
+                throw new Error("Wrong input string for convertion");
+
+            fractionPart = fractionPartCheck.valueOf();
+
+            dateTimeString = timeString.substr(0, fractionPointPosition);
+        }
+        else
+            dateTimeString = timeString;
+        // #endregion 
+
+        // #region Parse internal date 
+        switch(true)
+        {
+            case (dateTimeString.length == 8): // "YYYYMMDD"
+                parser = /(\d{4})(\d{2})(\d{2})/ig;
+                if(fractionPointPosition !== (-1))
+                    throw new Error("Wrong input string for convertion"); // Here we should not have a "fraction point"
+                break;
+            case (dateTimeString.length == 10): // "YYYYMMDDHH"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 60 * fractionPart;
+                    this.minute = Math.floor(fractionResult);
+
+                    fractionResult = 60 * (fractionResult - this.minute);
+                    this.second = Math.floor(fractionResult);
+
+                    fractionResult = 1000 * (fractionResult - this.second);
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            case (dateTimeString.length == 12): // "YYYYMMDDHHMM"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 60 * fractionPart;
+                    this.second = Math.floor(fractionResult);
+
+                    fractionResult = 1000 * (fractionResult - this.second);
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            case (dateTimeString.length == 14): // "YYYYMMDDHHMMSS"
+                parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+                if(fractionPointPosition !== (-1))
+                {
+                    var fractionResult = 1000 * fractionPart;
+                    this.millisecond = Math.floor(fractionResult);
+                }
+                break;
+            default:
+                throw new Error("Wrong input string for convertion");
+        }
+        // #endregion 
+
+        // #region Put parsed values at right places 
+        var parser_array = parser.exec(dateTimeString);
+        if(parser_array == null)
+            throw new Error("Wrong input string for convertion");
+
+        for(var j = 1; j < parser_array.length; j++)
+        {
+            switch(j)
+            {
+                case 1:
+                    this.year = parseInt(parser_array[j], 10);
+                    break;
+                case 2:
+                    this.month = parseInt(parser_array[j], 10) - 1; // In JavaScript we have month range as "0 - 11"
+                    break;
+                case 3:
+                    this.day = parseInt(parser_array[j], 10);
+                    break;
+                case 4:
+                    this.hour = parseInt(parser_array[j], 10) + hourDifference;
+                    break;
+                case 5:
+                    this.minute = parseInt(parser_array[j], 10) + minuteDifference;
+                    break;
+                case 6:
+                    this.second = parseInt(parser_array[j], 10);
+                    break;
+                default:
+                    throw new Error("Wrong input string for convertion");
+            }
+        }
+        // #endregion 
+
+        // #region Get final date 
+        if(isUTC == false)
+        {
+            var tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
+
+            this.year = tempDate.getUTCFullYear();
+            this.month = tempDate.getUTCMonth();
+            this.day = tempDate.getUTCDay();
+            this.hour = tempDate.getUTCHours();
+            this.minute = tempDate.getUTCMinutes();
+            this.second = tempDate.getUTCSeconds();
+            this.millisecond = tempDate.getUTCMilliseconds();
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toString =
+    function()
+    {
+        var output_array = new Array();
+
+        output_array.push(in_window.org.pkijs.padNumber(this.year, 4));
+        output_array.push(in_window.org.pkijs.padNumber(this.month, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.day, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.hour, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.minute, 2));
+        output_array.push(in_window.org.pkijs.padNumber(this.second, 2));
+        if(this.millisecond != 0)
+        {
+            output_array.push(".");
+            output_array.push(in_window.org.pkijs.padNumber(this.millisecond, 3));
+        }
+        output_array.push("Z");
+
+        return output_array.join('');
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "GENERALIZEDTIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.VISIBLESTRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.GENERALIZEDTIME.prototype.block_name.call(this);
+        _object.year = this.year;
+        _object.month = this.month;
+        _object.day = this.day;
+        _object.hour = this.hour;
+        _object.minute = this.minute;
+        _object.second = this.second;
+        _object.millisecond = this.millisecond;
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 31; // DATE
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DATE.constructor = in_window.org.pkijs.asn1.DATE;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DATE";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATE.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DATE.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 32; // TIMEOFDAY
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.TIMEOFDAY.constructor = in_window.org.pkijs.asn1.TIMEOFDAY;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TIMEOFDAY";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIMEOFDAY.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TIMEOFDAY.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 33; // DATETIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DATETIME.constructor = in_window.org.pkijs.asn1.DATETIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DATETIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DATETIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DATETIME.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 34; // DURATION
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.DURATION.constructor = in_window.org.pkijs.asn1.DURATION;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "DURATION";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.DURATION.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.DURATION.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME =
+    function()
+    {
+        in_window.org.pkijs.asn1.UTF8STRING.call(this, arguments[0]);
+
+        this.id_block.tag_class = 1; // UNIVERSAL
+        this.id_block.tag_number = 14; // TIME
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype = new in_window.org.pkijs.asn1.UTF8STRING();
+    in_window.org.pkijs.asn1.TIME.constructor = in_window.org.pkijs.asn1.TIME;
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype.block_name =
+    function()
+    {
+        /// <summary>Aux function, need to get a block name. Need to have it here for inhiritence</summary>
+
+        return "TIME";
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.TIME.prototype.toJSON =
+    function()
+    {
+        /// <summary>Convertion for the block to JSON object</summary>
+
+        var _object = in_window.org.pkijs.asn1.UTF8STRING.prototype.toJSON.call(this);
+
+        _object.block_name = in_window.org.pkijs.asn1.TIME.prototype.block_name.call(this);
+
+        return _object;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type CHOICE 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.CHOICE =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new Array()); // Array of ASN.1 types for make a choice from
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type ANY 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.ANY =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of special ASN.1 schema type REPEATED 
+    //**************************************************************************************
+    in_window.org.pkijs.asn1.REPEATED =
+    function()
+    {
+        if(arguments[0] instanceof Object)
+        {
+            this.name = in_window.org.pkijs.getValue(arguments[0], "name", "");
+            this.optional = in_window.org.pkijs.getValue(arguments[0], "optional", false);
+            this.value = in_window.org.pkijs.getValue(arguments[0], "value", new in_window.org.pkijs.asn1.ANY());
+            this.local = in_window.org.pkijs.getValue(arguments[0], "local", false); // Could local or global array to store elements
+        }
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major ASN.1 BER decoding function
+    //**************************************************************************************
+    function fromBER_raw(input_buffer, input_offset, input_length)
+    {
+        var incoming_offset = input_offset; // Need to store initial offset since "input_offset" is changing in the function
+
+        // #region Local function changing a type for ASN.1 classes 
+        function local_change_type(input_object, new_type)
+        {
+            if(input_object instanceof new_type)
+                return input_object;
+
+            var new_object = new new_type();
+            new_object.id_block = input_object.id_block;
+            new_object.len_block = input_object.len_block;
+            new_object.warnings = input_object.warnings;
+            new_object.value_before_decode = util_copybuf(input_object.value_before_decode);
+
+            return new_object;
+        }
+        // #endregion 
+
+        // #region Create a basic ASN.1 type since we need to return errors and warnings from the function 
+        var return_object = new in_window.org.pkijs.asn1.ASN1_block();
+        // #endregion 
+
+        // #region Basic check for parameters 
+        if(check_buffer_params(input_buffer, input_offset, input_length) === false)
+        {
+            return_object.error = "Wrong input parameters";
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Getting Uint8Array from ArrayBuffer 
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_length);
+        // #endregion 
+
+        // #region Initial checks 
+        if(int_buffer.length == 0)
+        {
+            this.error = "Zero buffer length";
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Decode indentifcation block of ASN.1 BER structure 
+        var result_offset = return_object.id_block.fromBER(input_buffer, input_offset, input_length);
+        return_object.warnings.concat(return_object.id_block.warnings);
+        if(result_offset == (-1))
+        {
+            return_object.error = return_object.id_block.error;
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+
+        input_offset = result_offset;
+        input_length -= return_object.id_block.block_length;
+        // #endregion 
+
+        // #region Decode length block of ASN.1 BER structure 
+        result_offset = return_object.len_block.fromBER(input_buffer, input_offset, input_length);
+        return_object.warnings.concat(return_object.len_block.warnings);
+        if(result_offset == (-1))
+        {
+            return_object.error = return_object.len_block.error;
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+
+        input_offset = result_offset;
+        input_length -= return_object.len_block.block_length;
+        // #endregion 
+
+        // #region Check for usign indefinite length form in encoding for primitive types 
+        if((return_object.id_block.is_constructed == false) &&
+           (return_object.len_block.is_indefinite_form == true))
+        {
+            return_object.error = new String("Indefinite length form used for primitive encoding form");
+            return {
+                offset: (-1),
+                result: return_object
+            };
+        }
+        // #endregion 
+
+        // #region Switch ASN.1 block type 
+        var new_asn1_type = in_window.org.pkijs.asn1.ASN1_block;
+
+        switch(return_object.id_block.tag_class)
+        {
+            // #region UNIVERSAL 
+            case 1: 
+                // #region Check for reserved tag numbers 
+                if((return_object.id_block.tag_number >= 37) &&
+                   (return_object.id_block.is_hex_only == false))
+                {
+                    return_object.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
+                    return {
+                        offset: (-1),
+                        result: return_object
+                    };
+                }
+                // #endregion 
+
+                switch(return_object.id_block.tag_number)
+                {
+                    // #region EOC type 
+                    case 0:
+                        // #region Check for EOC type 
+                        if((return_object.id_block.is_constructed == true) &&
+                           (return_object.len_block.length > 0))
+                        {
+                            return_object.error = "Type [UNIVERSAL 0] is reserved";
+                            return {
+                                offset: (-1),
+                                result: return_object
+                            };
+                        }
+                        // #endregion 
+
+                        new_asn1_type = in_window.org.pkijs.asn1.EOC;
+
+                        break;
+                        // #endregion 
+                    // #region BOOLEAN type 
+                    case 1:
+                        new_asn1_type = in_window.org.pkijs.asn1.BOOLEAN;
+                        break;
+                    // #endregion 
+                    // #region INTEGER type 
+                    case 2:
+                        new_asn1_type = in_window.org.pkijs.asn1.INTEGER;
+                        break;
+                    // #endregion 
+                    // #region BITSTRING type 
+                    case 3:
+                        new_asn1_type = in_window.org.pkijs.asn1.BITSTRING;
+                        break;
+                    // #endregion 
+                    // #region OCTETSTRING type 
+                    case 4:
+                        new_asn1_type = in_window.org.pkijs.asn1.OCTETSTRING;
+                        break;
+                    // #endregion 
+                    // #region NULL type 
+                    case 5:
+                        new_asn1_type = in_window.org.pkijs.asn1.NULL;
+                        break;
+                    // #endregion 
+                    // #region OBJECT IDENTIFIER type 
+                    case 6:
+                        new_asn1_type = in_window.org.pkijs.asn1.OID;
+                        break;
+                    // #endregion 
+                    // #region ENUMERATED type 
+                    case 10:
+                        new_asn1_type = in_window.org.pkijs.asn1.ENUMERATED;
+                        break;
+                    // #endregion 
+                    // #region UTF8STRING type 
+                    case 12:
+                        new_asn1_type = in_window.org.pkijs.asn1.UTF8STRING;
+                        break;
+                    // #endregion 
+                    // #region TIME type 
+                    case 14:
+                        new_asn1_type = in_window.org.pkijs.asn1.TIME;
+                        break;
+                    // #endregion 
+                    // #region ASN.1 reserved type 
+                    case 15:
+                        return_object.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
+                        return {
+                            offset: (-1),
+                            result: return_object
+                        };
+                        break;
+                    // #endregion 
+                    // #region SEQUENCE type 
+                    case 16:
+                        new_asn1_type = in_window.org.pkijs.asn1.SEQUENCE;
+                        break;
+                    // #endregion 
+                    // #region SET type 
+                    case 17:
+                        new_asn1_type = in_window.org.pkijs.asn1.SET;
+                        break;
+                    // #endregion 
+                    // #region NUMERICSTRING type 
+                    case 18:
+                        new_asn1_type = in_window.org.pkijs.asn1.NUMERICSTRING;
+                        break;
+                    // #endregion 
+                    // #region PRINTABLESTRING type 
+                    case 19:
+                        new_asn1_type = in_window.org.pkijs.asn1.PRINTABLESTRING;
+                        break;
+                    // #endregion 
+                    // #region TELETEXSTRING type 
+                    case 20:
+                        new_asn1_type = in_window.org.pkijs.asn1.TELETEXSTRING;
+                        break;
+                    // #endregion 
+                    // #region VIDEOTEXSTRING type 
+                    case 21:
+                        new_asn1_type = in_window.org.pkijs.asn1.VIDEOTEXSTRING;
+                        break;
+                    // #endregion 
+                    // #region IA5STRING type 
+                    case 22:
+                        new_asn1_type = in_window.org.pkijs.asn1.IA5STRING;
+                        break;
+                    // #endregion 
+                    // #region UTCTIME type 
+                    case 23:
+                        new_asn1_type = in_window.org.pkijs.asn1.UTCTIME;
+                        break;
+                    // #endregion 
+                    // #region GENERALIZEDTIME type 
+                    case 24:
+                        new_asn1_type = in_window.org.pkijs.asn1.GENERALIZEDTIME;
+                        break;
+                    // #endregion 
+                    // #region GRAPHICSTRING type 
+                    case 25:
+                        new_asn1_type = in_window.org.pkijs.asn1.GRAPHICSTRING;
+                        break;
+                    // #endregion 
+                    // #region VISIBLESTRING type 
+                    case 26:
+                        new_asn1_type = in_window.org.pkijs.asn1.VISIBLESTRING;
+                        break;
+                    // #endregion 
+                    // #region GENERALSTRING type 
+                    case 27:
+                        new_asn1_type = in_window.org.pkijs.asn1.GENERALSTRING;
+                        break;
+                    // #endregion 
+                    // #region UNIVERSALSTRING type 
+                    case 28:
+                        new_asn1_type = in_window.org.pkijs.asn1.UNIVERSALSTRING;
+                        break;
+                    // #endregion 
+                    // #region CHARACTERSTRING type 
+                    case 29:
+                        new_asn1_type = in_window.org.pkijs.asn1.CHARACTERSTRING;
+                        break;
+                    // #endregion 
+                    // #region BMPSTRING type 
+                    case 30:
+                        new_asn1_type = in_window.org.pkijs.asn1.BMPSTRING;
+                        break;
+                    // #endregion 
+                    // #region DATE type 
+                    case 31:
+                        new_asn1_type = in_window.org.pkijs.asn1.DATE;
+                        break;
+                    // #endregion 
+                    // #region TIMEOFDAY type 
+                    case 32:
+                        new_asn1_type = in_window.org.pkijs.asn1.TIMEOFDAY;
+                        break;
+                    // #endregion 
+                    // #region DATE-TIME type 
+                    case 33:
+                        new_asn1_type = in_window.org.pkijs.asn1.DATETIME;
+                        break;
+                    // #endregion 
+                    // #region DURATION type 
+                    case 34:
+                        new_asn1_type = in_window.org.pkijs.asn1.DURATION;
+                        break;
+                    // #endregion 
+                    // #region default 
+                    default:
+                        {
+                            var new_object;
+
+                            if(return_object.id_block.is_constructed == true)
+                                new_object = new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED();
+                            else
+                                new_object = new in_window.org.pkijs.asn1.ASN1_PRIMITIVE();
+
+                            new_object.id_block = return_object.id_block;
+                            new_object.len_block = return_object.len_block;
+                            new_object.warnings = return_object.warnings;
+
+                            return_object = new_object;
+
+                            result_offset = return_object.fromBER(input_buffer, input_offset, input_length);
+                        }
+                    // #endregion 
+                }
+                break;
+            // #endregion 
+            // #region All other tag classes 
+            case 2: // APPLICATION
+            case 3: // CONTEXT-SPECIFIC
+            case 4: // PRIVATE
+            default:
+                {
+                    if(return_object.id_block.is_constructed == true)
+                        new_asn1_type = in_window.org.pkijs.asn1.ASN1_CONSTRUCTED;
+                    else
+                        new_asn1_type = in_window.org.pkijs.asn1.ASN1_PRIMITIVE;
+                }
+            // #endregion 
+        }
+        // #endregion 
+
+        // #region Change type and perform BER decoding 
+        return_object = local_change_type(return_object, new_asn1_type);
+        result_offset = return_object.fromBER(input_buffer, input_offset, (return_object.len_block.is_indefinite_form == true) ? input_length : return_object.len_block.length);
+        // #endregion 
+
+        // #region Coping incoming buffer for entire ASN.1 block 
+        return_object.value_before_decode = util_copybuf_offset(input_buffer, incoming_offset, return_object.block_length);
+        // #endregion 
+
+        return {
+            offset: result_offset,
+            result: return_object
+        };
+    }
+    //**************************************************************************************
+    in_window.org.pkijs.fromBER = 
+    function(input_buffer)
+    {
+        /// <summary>Major function for decoding ASN.1 BER array into internal library structuries</summary>
+        /// <param name="input_buffer" type="ArrayBuffer">ASN.1 BER encoded array of bytes</param>
+
+        if(input_buffer.byteLength == 0)
+        {
+            var result = new in_window.org.pkijs.asn1.ASN1_block();
+            result.error = "Input buffer has zero length";
+
+            return {
+                offset: (-1),
+                result: result
+            };
+        }
+
+        return fromBER_raw(input_buffer, 0, input_buffer.byteLength);
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major scheme verification function 
+    //**************************************************************************************
+    in_window.org.pkijs.compareSchema =
+    function(root, input_asn1_data, input_asn1_schema)
+    {
+        // #region Special case for CHOICE schema element type 
+        if(input_asn1_schema instanceof in_window.org.pkijs.asn1.CHOICE)
+        {
+            var choice_result = false;
+
+            for(var j = 0; j < input_asn1_schema.value.length; j++)
+            {
+                var result = in_window.org.pkijs.compareSchema(root, input_asn1_data, input_asn1_schema.value[j]);
+                if(result.verified === true)
+                    return {
+                        verified: true,
+                        result: root
+                    };
+            }
+
+            if(choice_result === false)
+            {
+                var _result = {
+                    verified: false,
+                    result: {
+                        error: "Wrong values for CHOICE type"
+                    }
+                };
+
+                if(input_asn1_schema.hasOwnProperty('name'))
+                    _result.name = input_asn1_schema.name;
+
+                return _result;
+            }
+        }
+        // #endregion 
+
+        // #region Special case for ANY schema element type 
+        if(input_asn1_schema instanceof in_window.org.pkijs.asn1.ANY)
+        {
+            // #region Add named component of ASN.1 schema 
+            if(input_asn1_schema.hasOwnProperty('name'))
+                root[input_asn1_schema.name] = input_asn1_data;
+            // #endregion 
+
+            return {
+                verified: true,
+                result: root
+            };
+        }
+        // #endregion 
+
+        // #region Initial check 
+        if((root instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong root object" }
+            };
+
+        if((input_asn1_data instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 data" }
+            };
+
+        if((input_asn1_schema instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(('id_block' in input_asn1_schema) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+        // #endregion 
+
+        // #region Comparing id_block properties in ASN.1 data and ASN.1 schema 
+        // #region Encode and decode ASN.1 schema id_block 
+        /// <remarks>This encoding/decoding is neccessary because could be an errors in schema definition</remarks>
+        if(('fromBER' in input_asn1_schema.id_block) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(('toBER' in input_asn1_schema.id_block) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        var encoded_id = input_asn1_schema.id_block.toBER(false);
+        if(encoded_id.byteLength === 0)
+            return {
+                verified: false,
+                result: { error: "Error encoding id_block for ASN.1 schema" }
+            };
+
+        var decoded_offset = input_asn1_schema.id_block.fromBER(encoded_id, 0, encoded_id.byteLength);
+        if(decoded_offset === (-1))
+            return {
+                verified: false,
+                result: { error: "Error decoding id_block for ASN.1 schema" }
+            };
+        // #endregion 
+
+        // #region tag_class 
+        if(input_asn1_schema.id_block.hasOwnProperty('tag_class') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.tag_class !== input_asn1_data.id_block.tag_class)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region tag_number 
+        if(input_asn1_schema.id_block.hasOwnProperty('tag_number') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.tag_number !== input_asn1_data.id_block.tag_number)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region is_constructed 
+        if(input_asn1_schema.id_block.hasOwnProperty('is_constructed') === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.is_constructed !== input_asn1_data.id_block.is_constructed)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region is_hex_only 
+        if(('is_hex_only' in input_asn1_schema.id_block) === false) // Since 'is_hex_only' is an inhirited property
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema" }
+            };
+
+        if(input_asn1_schema.id_block.is_hex_only !== input_asn1_data.id_block.is_hex_only)
+            return {
+                verified: false,
+                result: root
+            };
+        // #endregion 
+        // #region value_hex 
+        if(input_asn1_schema.id_block.is_hex_only === true)
+        {
+            if(('value_hex' in input_asn1_schema.id_block) === false) // Since 'value_hex' is an inhirited property
+                return {
+                    verified: false,
+                    result: { error: "Wrong ASN.1 schema" }
+                };
+
+            var schema_view = new Uint8Array(input_asn1_schema.id_block.value_hex);
+            var asn1_view = new Uint8Array(input_asn1_data.id_block.value_hex);
+
+            if(schema_view.length !== asn1_view.length)
+                return {
+                    verified: false,
+                    result: root
+                };
+
+            for(var i = 0; i < schema_view.length; i++)
+            {
+                if(schema_view[i] !== asn1_view[1])
+                    return {
+                        verified: false,
+                        result: root
+                    };
+            }
+        }
+        // #endregion 
+        // #endregion 
+
+        // #region Add named component of ASN.1 schema 
+        if(input_asn1_schema.hasOwnProperty('name'))
+        {
+            input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+            if(input_asn1_schema.name !== "")
+                root[input_asn1_schema.name] = input_asn1_data;
+        }
+        // #endregion 
+
+        // #region Getting next ASN.1 block for comparition 
+        if(input_asn1_schema.id_block.is_constructed === true)
+        {
+            var admission = 0;
+            var result = { verified: false };
+
+            var max_length = input_asn1_schema.value_block.value.length;
+
+            if(max_length > 0)
+            {
+                if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED)
+                    max_length = input_asn1_data.value_block.value.length;
+            }
+
+            // #region Special case when constructive value has no elements 
+            if(max_length === 0)
+                return {
+                    verified: true,
+                    result: root
+                };
+            // #endregion 
+
+            // #region Special case when "input_asn1_data" has no values and "input_asn1_schema" has all optional values
+            if((input_asn1_data.value_block.value.length === 0) && 
+               (input_asn1_schema.value_block.value.length !== 0))
+            {
+                var _optional = true;
+
+                for(var i = 0; i < input_asn1_schema.value_block.value.length; i++)
+                    _optional = _optional && (input_asn1_schema.value_block.value[i].optional || false);
+
+                if(_optional === true)
+                {
+                    return {
+                        verified: true,
+                        result: root
+                    };
+                }
+                else
+                {
+                    // #region Delete early added name of block 
+                    if(input_asn1_schema.hasOwnProperty('name'))
+                    {
+                        input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                        if(input_asn1_schema.name !== "")
+                            delete root[input_asn1_schema.name];
+                    }
+                    // #endregion 
+
+                    root.error = "Inconsistent object length";
+
+                    return {
+                        verified: false,
+                        result: root
+                    };
+                }
+            }
+            // #endregion 
+
+            for(var i = 0; i < max_length; i++)
+            {
+                // #region Special case when there is an "optional" element of ASN.1 schema at the end 
+                if((i - admission) >= input_asn1_data.value_block.value.length)
+                {
+                    if(input_asn1_schema.value_block.value[i].optional === false)
+                    {
+                        var _result = {
+                            verified: false,
+                            result: root
+                        };
+
+                        root.error = "Inconsistent length between ASN.1 data and schema";
+
+                        // #region Delete early added name of block 
+                        if(input_asn1_schema.hasOwnProperty('name'))
+                        {
+                            input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                            if(input_asn1_schema.name !== "")
+                            {
+                                delete root[input_asn1_schema.name];
+                                _result.name = input_asn1_schema.name;
+                            }
+                        }
+                        // #endregion 
+
+                        return _result;
+                    }
+                }
+                    // #endregion 
+                else
+                {
+                    // #region Special case for REPEATED type of ASN.1 schema element 
+                    if(input_asn1_schema.value_block.value[0] instanceof in_window.org.pkijs.asn1.REPEATED)
+                    {
+                        result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i], input_asn1_schema.value_block.value[0].value);
+                        if(result.verified === false)
+                        {
+                            if(input_asn1_schema.value_block.value[0].optional === true)
+                                admission++;
+                            else
+                            {
+                                // #region Delete early added name of block 
+                                if(input_asn1_schema.hasOwnProperty('name'))
+                                {
+                                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                                    if(input_asn1_schema.name !== "")
+                                        delete root[input_asn1_schema.name];
+                                }
+                                // #endregion 
+
+                                return result;
+                            }
+                        }
+
+                        if(("name" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].name.length > 0))
+                        {
+                            var array_root = {};
+
+                            if(("local" in input_asn1_schema.value_block.value[0]) && (input_asn1_schema.value_block.value[0].local === true))
+                                array_root = input_asn1_data;
+                            else
+                                array_root = root;
+
+                            if(typeof array_root[input_asn1_schema.value_block.value[0].name] === "undefined")
+                                array_root[input_asn1_schema.value_block.value[0].name] = new Array();
+
+                            array_root[input_asn1_schema.value_block.value[0].name].push(input_asn1_data.value_block.value[i]);
+                        }
+                    }
+                        // #endregion 
+                    else
+                    {
+                        result = in_window.org.pkijs.compareSchema(root, input_asn1_data.value_block.value[i - admission], input_asn1_schema.value_block.value[i]);
+                        if(result.verified === false)
+                        {
+                            if(input_asn1_schema.value_block.value[i].optional === true)
+                                admission++;
+                            else
+                            {
+                                // #region Delete early added name of block 
+                                if(input_asn1_schema.hasOwnProperty('name'))
+                                {
+                                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                                    if(input_asn1_schema.name !== "")
+                                        delete root[input_asn1_schema.name];
+                                }
+                                // #endregion 
+
+                                return result;
+                            }
+                        }
+                    }
+                }
+            }
+
+            if(result.verified === false) // The situation may take place if last element is "optional" and verification failed
+            {
+                var _result = {
+                    verified: false,
+                    result: root
+                };
+
+                // #region Delete early added name of block 
+                if(input_asn1_schema.hasOwnProperty('name'))
+                {
+                    input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                    if(input_asn1_schema.name !== "")
+                    {
+                        delete root[input_asn1_schema.name];
+                        _result.name = input_asn1_schema.name;
+                    }
+                }
+                // #endregion 
+
+                return _result;
+            }
+
+            return {
+                verified: true,
+                result: root
+            };
+        }
+        // #endregion 
+        // #region Ability to parse internal value for primitive-encoded value (value of OCTETSTRING, for example)
+        else
+        {
+            if( ("primitive_schema" in input_asn1_schema) &&
+                ("value_hex" in input_asn1_data.value_block) )
+            {
+                // #region Decoding of raw ASN.1 data 
+                var asn1 = in_window.org.pkijs.fromBER(input_asn1_data.value_block.value_hex);
+                if(asn1.offset === (-1))
+                {
+                    var _result = {
+                        verified: false,
+                        result: asn1.result
+                    };
+
+                    // #region Delete early added name of block 
+                    if(input_asn1_schema.hasOwnProperty('name'))
+                    {
+                        input_asn1_schema.name = input_asn1_schema.name.replace(/^\s+|\s+$/g, '');
+                        if(input_asn1_schema.name !== "")
+                        {
+                            delete root[input_asn1_schema.name];
+                            _result.name = input_asn1_schema.name;
+                        }
+                    }
+                    // #endregion 
+
+                    return _result;
+                }
+                // #endregion 
+
+                return in_window.org.pkijs.compareSchema(root, asn1.result, input_asn1_schema.primitive_schema);
+            }
+            else
+                return {
+                    verified: true,
+                    result: root
+                };
+        }
+        // #endregion 
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.verifySchema =
+    function(input_buffer, input_schema)
+    {
+        // #region Initial check 
+        if((input_schema instanceof Object) === false)
+            return {
+                verified: false,
+                result: { error: "Wrong ASN.1 schema type" }
+            };
+        // #endregion 
+
+        // #region Decoding of raw ASN.1 data 
+        var asn1 = in_window.org.pkijs.fromBER(input_buffer);
+        if(asn1.offset === (-1))
+            return {
+                verified: false,
+                result: asn1.result
+            };
+        // #endregion 
+
+        // #region Compare ASN.1 struct with input schema 
+        return in_window.org.pkijs.compareSchema(asn1.result, asn1.result, input_schema);
+        // #endregion 
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Major function converting JSON to ASN.1 objects 
+    //**************************************************************************************
+    in_window.org.pkijs.fromJSON = 
+    function(json)
+    {
+        /// <summary>Converting from JSON to ASN.1 objects</summary>
+        /// <param name="json" type="String|Object">JSON string or object to convert to ASN.1 objects</param>
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+}
+)(typeof exports !== "undefined" ? exports : window);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/common.js
@@ -0,0 +1,1542 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Settings for "crypto engine" 
+    //**************************************************************************************
+    local.engine = {
+        name: "none",
+        crypto: null,
+        subtle: null
+    };
+
+    if(typeof window != "undefined")
+    {
+        if("crypto" in window)
+        {
+            var engineName = "webcrypto";
+            var cryptoObject = window.crypto;
+            var subtleObject = null;
+
+            // Apple Safari support
+            if("webkitSubtle" in window.crypto)
+                subtleObject = window.crypto.webkitSubtle;
+
+            if("subtle" in window.crypto)
+                subtleObject = window.crypto.subtle;
+
+            local.engine = {
+                name: engineName,
+                crypto: cryptoObject,
+                subtle: subtleObject
+            };
+        }
+    }
+    //**************************************************************************************
+    in_window.org.pkijs.setEngine =
+    function(name, crypto, subtle)
+    {
+        /// <summary>Setting the global "crypto engine" parameters</summary>
+        /// <param name="name" type="String">Auxiliary name for "crypto engine"</param>
+        /// <param name="crypto" type="Object">Object handling all root cryptographic requests (in fact currently it must handle only "getRandomValues")</param>
+        /// <param name="subtle" type="Object">Object handling all main cryptographic requests</param>
+
+        local.engine = {
+            name: name,
+            crypto: crypto,
+            subtle: subtle
+        };
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getEngine =
+    function()
+    {
+        return local.engine;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region Declaration of common functions 
+    //**************************************************************************************
+    in_window.org.pkijs.emptyObject =
+    function()
+    {
+        this.toJSON = function()
+        {
+            return {};
+        };
+        this.toSchema = function()
+        {
+            return {};
+        };
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getNames =
+    function(arg)
+    {
+        /// <summary>Get correct "names" array for all "schema" objects</summary>
+
+        var names = {};
+
+        if(arg instanceof Object)
+            names = (arg.names || {});
+
+        return names;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.inheriteObjectFields =
+    function(from)
+    {
+        for(var i in from.prototype)
+        {
+            if(typeof from.prototype[i] === "function")
+                continue;
+
+            this[i] = from.prototype[i];
+        }
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getUTCDate =
+    function(date)
+    {
+        /// <summary>Making UTC date from local date</summary>
+        /// <param name="date" type="Date">Date to convert from</param>
+
+        var current_date = date;
+        return new Date(current_date.getTime() + (current_date.getTimezoneOffset() * 60000));
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.padNumber =
+    function(input_number, full_length)
+    {
+        var str = input_number.toString(10);
+        var dif = full_length - str.length;
+
+        var padding = new Array(dif);
+        for(var i = 0; i < dif; i++)
+            padding[i] = '0';
+
+        var padding_string = padding.join('');
+
+        return padding_string.concat(str);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getValue =
+    function(args, item, default_value)
+    {
+        if(item in args)
+            return args[item];
+        else
+            return default_value;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.isEqual_view =
+    function(input_view1, input_view2)
+    {
+        /// <summary>Compare two Uint8Arrays</summary>
+        /// <param name="input_view1" type="Uint8Array">First Uint8Array for comparision</param>
+        /// <param name="input_view2" type="Uint8Array">Second Uint8Array for comparision</param>
+
+        if(input_view1.length !== input_view2.length)
+            return false;
+
+        for(var i = 0; i < input_view1.length; i++)
+        {
+            if(input_view1[i] != input_view2[i])
+                return false;
+        }
+
+        return true;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.isEqual_buffer =
+    function(input_buffer1, input_buffer2)
+    {
+        /// <summary>Compare two array buffers</summary>
+        /// <param name="input_buffer1" type="ArrayBuffer">First ArrayBuffer for comparision</param>
+        /// <param name="input_buffer2" type="ArrayBuffer">Second ArrayBuffer for comparision</param>
+
+        if(input_buffer1.byteLength != input_buffer2.byteLength)
+            return false;
+
+        var view1 = new Uint8Array(input_buffer1);
+        var view2 = new Uint8Array(input_buffer2);
+
+        return in_window.org.pkijs.isEqual_view(view1, view2);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.concat_buffers =
+    function(input_buf1, input_buf2)
+    {
+        /// <summary>Concatenate two ArrayBuffers</summary>
+        /// <param name="input_buf1" type="ArrayBuffer">First ArrayBuffer (first part of concatenated array)</param>
+        /// <param name="input_buf2" type="ArrayBuffer">Second ArrayBuffer (second part of concatenated array)</param>
+
+        var input_view1 = new Uint8Array(input_buf1);
+        var input_view2 = new Uint8Array(input_buf2);
+
+        var ret_buf = new ArrayBuffer(input_buf1.byteLength + input_buf2.byteLength);
+        var ret_view = new Uint8Array(ret_buf);
+
+        for(var i = 0; i < input_buf1.byteLength; i++)
+            ret_view[i] = input_view1[i];
+
+        for(var j = 0; j < input_buf2.byteLength; j++)
+            ret_view[input_buf1.byteLength + j] = input_view2[j];
+
+        return ret_buf;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.copyBuffer =
+    function(input_buffer)
+    {
+        var result = new ArrayBuffer(input_buffer.byteLength);
+
+        var resultView = new Uint8Array(result);
+        var inputView = new Uint8Array(input_buffer);
+
+        for(var i = 0; i < inputView.length; i++)
+            resultView[i] = inputView[i];
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getCrypto =
+    function()
+    {
+        var crypto_temp;
+
+        if(local.engine.subtle !== null)
+            crypto_temp = local.engine.subtle;
+
+        return crypto_temp;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.stringPrep =
+    function(input_string)
+    {
+        /// <summary>String preparation function. In a future here will be realization of algorithm from RFC4518.</summary>
+        /// <param name="input_string" type="String">JavaScript string. As soon as for each ASN.1 string type we have a specific transformation function here we will work with pure JavaScript string</param>
+        /// <returns type="String">Formated string</returns>
+
+        var result = input_string.replace(/^\s+|\s+$/g, ""); // Trim input string
+        result = result.replace(/\s+/g, " "); // Change all sequence of SPACE down to SPACE char
+        result = result.toLowerCase();
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.bufferToHexCodes =
+    function(input_buffer, input_offset, input_lenght)
+    {
+        var result = "";
+
+        var int_buffer = new Uint8Array(input_buffer, input_offset, input_lenght);
+
+        for(var i = 0; i < int_buffer.length; i++)
+        {
+            var str = int_buffer[i].toString(16).toUpperCase();
+            result = result + ((str.length === 1) ? "0" : "") + str;
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.bufferFromHexCodes =
+    function(hexString)
+    {
+        /// <summary>Create an ArrayBuffer from string having hexdecimal codes</summary>
+        /// <param name="hexString" type="String">String to create ArrayBuffer from</param>
+
+        // #region Initial variables 
+        var stringLength = hexString.length;
+
+        var resultBuffer = new ArrayBuffer(stringLength >> 1);
+        var resultView = new Uint8Array(resultBuffer);
+
+        var hex_map = {};
+
+        hex_map['0'] = 0x00;
+        hex_map['1'] = 0x01;
+        hex_map['2'] = 0x02;
+        hex_map['3'] = 0x03;
+        hex_map['4'] = 0x04;
+        hex_map['5'] = 0x05;
+        hex_map['6'] = 0x06;
+        hex_map['7'] = 0x07;
+        hex_map['8'] = 0x08;
+        hex_map['9'] = 0x09;
+        hex_map['A'] = 0x0A;
+        hex_map['a'] = 0x0A;
+        hex_map['B'] = 0x0B;
+        hex_map['b'] = 0x0B;
+        hex_map['C'] = 0x0C;
+        hex_map['c'] = 0x0C;
+        hex_map['D'] = 0x0D;
+        hex_map['d'] = 0x0D;
+        hex_map['E'] = 0x0E;
+        hex_map['e'] = 0x0E;
+        hex_map['F'] = 0x0F;
+        hex_map['f'] = 0x0F;
+
+        var j = 0;
+        var temp = 0x00;
+        // #endregion 
+
+        // #region Convert char-by-char 
+        for(var i = 0; i < stringLength; i++)
+        {
+            if(!(i % 2))
+                temp = hex_map[hexString.charAt(i)] << 4;
+            else
+            {
+                temp |= hex_map[hexString.charAt(i)];
+
+                resultView[j] = temp;
+                j++;
+            }
+        }
+        // #endregion 
+
+        return resultBuffer;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getRandomValues =
+    function(view)
+    {
+        /// <param name="view" type="Uint8Array">New array which gives a length for random value</param>
+
+        if(local.engine.crypto !== null)
+            return local.engine.crypto.getRandomValues(view);
+        else
+            throw new Error("No support for Web Cryptography API");
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmParameters =
+    function(algorithmName, operation)
+    {
+        /// <param name="algorithmName" type="String">Algorithm name to get common parameters for</param>
+        /// <param name="operation" type="String">Kind of operation: "sign", "encrypt", "generatekey", "importkey", "exportkey", "verify"</param>
+
+        var result = {
+            algorithm: {},
+            usages: []
+        };
+
+        switch(algorithmName.toUpperCase())
+        {
+            case "RSASSA-PKCS1-V1_5":
+                switch(operation.toLowerCase())
+                {
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "verify":
+                    case "sign":
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSASSA-PKCS1-v1_5"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "RSA-PSS":
+                switch(operation.toLowerCase())
+                {
+                    case "sign":
+                    case "verify":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                hash: {
+                                    name: "SHA-1"
+                                },
+                                saltLength: 20
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-1"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-PSS",
+                                hash: {
+                                    name: "SHA-1"
+                                }
+                            },
+                            usages: ["verify"] // For importKey("pkcs8") usage must be "sign" only
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSA-PSS"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "RSA-OAEP":
+                switch(operation.toLowerCase())
+                {
+                    case "encrypt":
+                    case "decrypt":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP"
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                        break;
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP",
+                                modulusLength: 2048,
+                                publicExponent: new Uint8Array([0x01, 0x00, 0x01]),
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "RSA-OAEP",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["encrypt"] // encrypt for "spki" and decrypt for "pkcs8"
+                        };
+                        break;
+                    case "exportkey":
+                    default:
+                        return {
+                            algorithm: {
+                                name: "RSA-OAEP"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "ECDSA":
+                switch(operation.toLowerCase())
+                {
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["verify"] // "sign" for "pkcs8"
+                        };
+                        break;
+                    case "verify":
+                    case "sign":
+                        result = {
+                            algorithm: {
+                                name: "ECDSA",
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "ECDSA"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "ECDH":
+                switch(operation.toLowerCase())
+                {
+                    case "exportkey":
+                    case "importkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "ECDH",
+                                namedCurve: "P-256"
+                            },
+                            usages: ["deriveKey", "deriveBits"]
+                        };
+                        break;
+                    case "derivekey":
+                    case "derivebits":
+                        result = {
+                            algorithm: {
+                                name: "ECDH",
+                                namedCurve: "P-256",
+                                public: [] // Must be a "publicKey"
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "ECDH"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-CTR":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-CTR",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-CTR",
+                                counter: new Uint8Array(16),
+                                length: 10
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-CTR"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-CBC":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-CBC",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-CBC",
+                                iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-CBC"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-GCM":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "AES-GCM",
+                                length: 256
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    case "decrypt":
+                    case "encrypt":
+                        result = {
+                            algorithm: {
+                                name: "AES-GCM",
+                                iv: in_window.org.pkijs.getRandomValues(new Uint8Array(16)) // For "decrypt" the value should be replaced with value got on "encrypt" step
+                            },
+                            usages: ["encrypt", "decrypt", "wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-GCM"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "AES-KW":
+                switch(operation.toLowerCase())
+                {
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                    case "wrapkey":
+                    case "unwrapkey":
+                        result = {
+                            algorithm: {
+                                name: "AES-KW",
+                                length: 256
+                            },
+                            usages: ["wrapKey", "unwrapKey"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "AES-KW"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "HMAC":
+                switch(operation.toLowerCase())
+                {
+                    case "sign":
+                    case "verify":
+                        result = {
+                            algorithm: {
+                                name: "HMAC"
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    case "importkey":
+                    case "exportkey":
+                    case "generatekey":
+                        result = {
+                            algorithm: {
+                                name: "HMAC",
+                                length: 32,
+                                hash: {
+                                    name: "SHA-256"
+                                }
+                            },
+                            usages: ["sign", "verify"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "HMAC"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "HKDF":
+                switch(operation.toLowerCase())
+                {
+                    case "derivekey":
+                        result = {
+                            algorithm: {
+                                name: "HKDF",
+                                hash: "SHA-256",
+                                salt: new Uint8Array(),
+                                info: new Uint8Array()
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "HKDF"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            case "PBKDF2":
+                switch(operation.toLowerCase())
+                {
+                    case "derivekey":
+                        result = {
+                            algorithm: {
+                                name: "PBKDF2",
+                                hash: { name: "SHA-256" },
+                                salt: new Uint8Array(),
+                                iterations: 1000
+                            },
+                            usages: ["encrypt", "decrypt"]
+                        };
+                        break;
+                    default:
+                        return {
+                            algorithm: {
+                                name: "PBKDF2"
+                            },
+                            usages: []
+                        };
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getOIDByAlgorithm =
+    function(algorithm)
+    {
+        /// <summary>Get OID for each specific WebCrypto algorithm</summary>
+        /// <param name="algorithm" type="Object">WebCrypto algorithm</param>
+
+        var result = "";
+
+        switch(algorithm.name.toUpperCase())
+        {
+            case "RSASSA-PKCS1-V1_5":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.113549.1.1.5";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.113549.1.1.11";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.113549.1.1.12";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.113549.1.1.13";
+                        break;
+                    default:
+                }
+                break;
+            case "RSA-PSS":
+                result = "1.2.840.113549.1.1.10";
+                break;
+            case "RSA-OAEP":
+                result = "1.2.840.113549.1.1.7";
+                break;
+            case "ECDSA":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.10045.4.1";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.10045.4.3.2";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.10045.4.3.3";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.10045.4.3.4";
+                        break;
+                    default:
+                }
+                break;
+            case "ECDH":
+                switch(algorithm.kdf.toUpperCase()) // Non-standard addition - hash algorithm of KDF function
+                {
+                    case "SHA-1":
+                        result = "1.3.133.16.840.63.0.2"; // dhSinglePass-stdDH-sha1kdf-scheme
+                        break;
+                    case "SHA-256":
+                        result = "1.3.132.1.11.1"; // dhSinglePass-stdDH-sha256kdf-scheme 
+                        break;
+                    case "SHA-384":
+                        result = "1.3.132.1.11.2"; // dhSinglePass-stdDH-sha384kdf-scheme
+                        break;
+                    case "SHA-512":
+                        result = "1.3.132.1.11.3"; // dhSinglePass-stdDH-sha512kdf-scheme
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CTR":
+                break;
+            case "AES-CBC":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.2";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.22";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.42";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CMAC":
+                break;
+            case "AES-GCM":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.6";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.26";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.46";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-CFB":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.4";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.24";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.44";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-KW":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.5";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.25";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.45";
+                        break;
+                    default:
+                }
+                break;
+            case "HMAC":
+                switch(algorithm.hash.name.toUpperCase())
+                {
+                    case "SHA-1":
+                        result = "1.2.840.113549.2.7";
+                        break;
+                    case "SHA-256":
+                        result = "1.2.840.113549.2.9";
+                        break;
+                    case "SHA-384":
+                        result = "1.2.840.113549.2.10";
+                        break;
+                    case "SHA-512":
+                        result = "1.2.840.113549.2.11";
+                        break;
+                    default:
+                }
+                break;
+            case "DH":
+                result = "1.2.840.113549.1.9.16.3.5";
+                break;
+            case "SHA-1":
+                result = "1.3.14.3.2.26";
+                break;
+            case "SHA-256":
+                result = "2.16.840.1.101.3.4.2.1";
+                break;
+            case "SHA-384":
+                result = "2.16.840.1.101.3.4.2.2";
+                break;
+            case "SHA-512":
+                result = "2.16.840.1.101.3.4.2.3";
+                break;
+            case "CONCAT":
+                break;
+            case "HKDF":
+                break;
+            case "PBKDF2":
+                result = "1.2.840.113549.1.5.12";
+                break;
+            // #region Special case - OIDs for ECC curves 
+            case "P-256":
+                result = "1.2.840.10045.3.1.7";
+                break;
+            case "P-384":
+                result = "1.3.132.0.34";
+                break;
+            case "P-521":
+                result = "1.3.132.0.35";
+                break;
+            // #endregion 
+
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmByOID =
+    function(oid)
+    {
+        /// <summary>Get WebCrypto algorithm by wel-known OID</summary>
+        /// <param name="oid" type="String">Wel-known OID to search for</param>
+
+        var result = {};
+
+        switch(oid)
+        {
+            case "1.2.840.113549.1.1.5":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.11":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.12":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.13":
+                result = {
+                    name: "RSASSA-PKCS1-v1_5",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.1.10":
+                result = {
+                    name: "RSA-PSS"
+                };
+                break;
+            case "1.2.840.113549.1.1.7":
+                result = {
+                    name: "RSA-OAEP"
+                };
+                break;
+            case "1.2.840.10045.4.1":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.2":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.3":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.10045.4.3.4":
+                result = {
+                    name: "ECDSA",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.3.133.16.840.63.0.2":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-1"
+                };
+                break;
+            case "1.3.132.1.11.1":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-256"
+                };
+                break;
+            case "1.3.132.1.11.2":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-384"
+                };
+                break;
+            case "1.3.132.1.11.3":
+                result = {
+                    name: "ECDH",
+                    kdf: "SHA-512"
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.2":
+                result = {
+                    name: "AES-CBC",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.22":
+                result = {
+                    name: "AES-CBC",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.42":
+                result = {
+                    name: "AES-CBC",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.6":
+                result = {
+                    name: "AES-GCM",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.26":
+                result = {
+                    name: "AES-GCM",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.46":
+                result = {
+                    name: "AES-GCM",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.4":
+                result = {
+                    name: "AES-CFB",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.24":
+                result = {
+                    name: "AES-CFB",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.44":
+                result = {
+                    name: "AES-CFB",
+                    length: 256
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.5":
+                result = {
+                    name: "AES-KW",
+                    length: 128
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.25":
+                result = {
+                    name: "AES-KW",
+                    length: 192
+                };
+                break;
+            case "2.16.840.1.101.3.4.1.45":
+                result = {
+                    name: "AES-KW",
+                    length: 256
+                };
+                break;
+            case "1.2.840.113549.2.7":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-1"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.9":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-256"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.10":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-384"
+                    }
+                };
+                break;
+            case "1.2.840.113549.2.11":
+                result = {
+                    name: "HMAC",
+                    hash: {
+                        name: "SHA-512"
+                    }
+                };
+                break;
+            case "1.2.840.113549.1.9.16.3.5":
+                result = {
+                    name: "DH"
+                };
+                break;
+            case "1.3.14.3.2.26":
+                result = {
+                    name: "SHA-1"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.1":
+                result = {
+                    name: "SHA-256"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.2":
+                result = {
+                    name: "SHA-384"
+                };
+                break;
+            case "2.16.840.1.101.3.4.2.3":
+                result = {
+                    name: "SHA-512"
+                };
+                break;
+            case "1.2.840.113549.1.5.12":
+                result = {
+                    name: "PBKDF2"
+                };
+                break;
+            // #region Special case - OIDs for ECC curves 
+            case "1.2.840.10045.3.1.7":
+                result = {
+                    name: "P-256"
+                };
+                break;
+            case "1.3.132.0.34":
+                result = {
+                    name: "P-384"
+                };
+                break;
+            case "1.3.132.0.35":
+                result = {
+                    name: "P-521"
+                };
+                break;
+            // #endregion 
+
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getHashAlgorithm =
+    function(signatureAlgorithm)
+    {
+        /// <summary>Getting hash algorithm by signature algorithm</summary>
+        /// <param name="signatureAlgorithm" type="in_window.org.pkijs.simpl.ALGORITHM_IDENTIFIER">Signature algorithm</param>
+
+        var result = "";
+
+        switch(signatureAlgorithm.algorithm_id)
+        {
+            case "1.2.840.10045.4.1": // ecdsa-with-SHA1
+            case "1.2.840.113549.1.1.5":
+                result = "SHA-1";
+                break;
+            case "1.2.840.10045.4.3.2": // ecdsa-with-SHA256
+            case "1.2.840.113549.1.1.11":
+                result = "SHA-256";
+                break;
+            case "1.2.840.10045.4.3.3": // ecdsa-with-SHA384
+            case "1.2.840.113549.1.1.12":
+                result = "SHA-384";
+                break;
+            case "1.2.840.10045.4.3.4": // ecdsa-with-SHA512
+            case "1.2.840.113549.1.1.13":
+                result = "SHA-512";
+                break;
+            case "1.2.840.113549.1.1.10": // RSA-PSS
+                {
+                    var params;
+
+                    try
+                    {
+                        params = new in_window.org.pkijs.simpl.x509.RSASSA_PSS_params({ schema: signatureAlgorithm.algorithm_params });
+                        if("hashAlgorithm" in params)
+                        {
+                            var algorithm = in_window.org.pkijs.getAlgorithmByOID(params.hashAlgorithm.algorithm_id);
+                            if(("name" in algorithm) === false)
+                                return "";
+
+                            result = algorithm.name;
+                        }
+                        else
+                            result = "SHA-1";
+                    }
+                    catch(ex)
+                    {
+                    }
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.createCMSECDSASignature =
+    function(signatureBuffer)
+    {
+        /// <summary>Create CMS ECDSA signature from WebCrypto ECDSA signature</summary>
+        /// <param name="signatureBuffer" type="ArrayBuffer">WebCrypto result of "sign" function</param>
+
+        // #region Initial check for correct length 
+        if((signatureBuffer.byteLength % 2) != 0)
+            return new ArrayBuffer(0);
+        // #endregion 
+
+        // #region Initial variables 
+        var i = 0;
+        var length = signatureBuffer.byteLength / 2; // There are two equal parts inside incoming ArrayBuffer
+
+        var signatureView = new Uint8Array(signatureBuffer);
+
+        var r_buffer = new ArrayBuffer(length);
+        var r_view = new Uint8Array(r_buffer);
+        var r_corrected_buffer;
+        var r_corrected_view;
+
+        var s_buffer = new ArrayBuffer(length);
+        var s_view = new Uint8Array(s_buffer);
+        var s_corrected_buffer;
+        var s_corrected_view;
+        // #endregion   
+
+        // #region Get "r" part of ECDSA signature 
+        for(; i < length; i++)
+            r_view[i] = signatureView[i];
+
+        if(r_view[0] & 0x80)
+        {
+            r_corrected_buffer = new ArrayBuffer(length + 1);
+            r_corrected_view = new Uint8Array(r_corrected_buffer);
+
+            r_corrected_view[0] = 0x00;
+
+            for(var j = 0; j < length; j++)
+                r_corrected_view[j + 1] = r_view[j];
+        }
+        else
+        {
+            r_corrected_buffer = r_buffer;
+            r_corrected_view = r_view;
+        }
+        // #endregion 
+
+        // #region Get "s" part of ECDSA signature 
+        for(; i < signatureBuffer.byteLength; i++)
+            s_view[i - length] = signatureView[i];
+
+
+        if(s_view[0] & 0x80)
+        {
+            s_corrected_buffer = new ArrayBuffer(length + 1);
+            s_corrected_view = new Uint8Array(s_corrected_buffer);
+
+            s_corrected_view[0] = 0x00;
+
+            for(var j = 0; j < length; j++)
+                s_corrected_view[j + 1] = s_view[j];
+        }
+        else
+        {
+            s_corrected_buffer = s_buffer;
+            s_corrected_view = s_view;
+        }
+        // #endregion 
+
+        // #region Create ASN.1 structure of CMS ECDSA signature 
+        var r_integer = new in_window.org.pkijs.asn1.INTEGER();
+        r_integer.value_block.is_hex_only = true;
+        r_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(r_corrected_buffer);
+
+        var s_integer = new in_window.org.pkijs.asn1.INTEGER();
+        s_integer.value_block.is_hex_only = true;
+        s_integer.value_block.value_hex = in_window.org.pkijs.copyBuffer(s_corrected_buffer);
+
+        var asn1 = new in_window.org.pkijs.asn1.SEQUENCE({
+            value: [
+                r_integer,
+                s_integer
+            ]
+        });
+        // #endregion   
+
+        return asn1.toBER(false);
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.createECDSASignatureFromCMS =
+    function(cmsSignature)
+    {
+        /// <summary>Create a single ArrayBuffer from CMS ECDSA signature</summary>
+        /// <param name="cmsSignature" type="in_window.org.pkijs.asn1.SEQUENCE">ASN.1 SEQUENCE contains CMS ECDSA signature</param>
+
+        // #region Initial variables 
+        var length = 0;
+
+        var r_start = 0;
+        var s_start = 0;
+
+        var r_length = cmsSignature.value_block.value[0].value_block.value_hex.byteLength;
+        var s_length = cmsSignature.value_block.value[1].value_block.value_hex.byteLength;
+        // #endregion 
+
+        // #region Get length of final "ArrayBuffer" 
+        var r_view = new Uint8Array(cmsSignature.value_block.value[0].value_block.value_hex);
+        if((r_view[0] === 0x00) && (r_view[1] & 0x80))
+        {
+            length = r_length - 1;
+            r_start = 1;
+        }
+        else
+            length = r_length;
+
+        var s_view = new Uint8Array(cmsSignature.value_block.value[1].value_block.value_hex);
+        if((s_view[0] === 0x00) && (s_view[1] & 0x80))
+        {
+            length += s_length - 1;
+            s_start = 1;
+        }
+        else
+            length += s_length;
+        // #endregion 
+
+        // #region Copy values from CMS ECDSA signature 
+        var result = new ArrayBuffer(length);
+        var result_view = new Uint8Array(result);
+
+        for(var i = r_start; i < r_length; i++)
+            result_view[i - r_start] = r_view[i];
+
+        for(var i = s_start; i < s_length; i++)
+            result_view[i - s_start + r_length - r_start] = s_view[i];
+        // #endregion 
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getEncryptionAlgorithm =
+    function(algorithm)
+    {
+        /// <summary>Get encryption algorithm OID by WebCrypto algorithm's object</summary>
+        /// <param name="algorithm" type="WebCryptoAlgorithm">WebCrypto algorithm object</param>
+
+        var result = "";
+
+        switch(algorithm.name.toUpperCase())
+        {
+            case "AES-CBC":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.2";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.22";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.42";
+                        break;
+                    default:
+                }
+                break;
+            case "AES-GCM":
+                switch(algorithm.length)
+                {
+                    case 128:
+                        result = "2.16.840.1.101.3.4.1.6";
+                        break;
+                    case 192:
+                        result = "2.16.840.1.101.3.4.1.26";
+                        break;
+                    case 256:
+                        result = "2.16.840.1.101.3.4.1.46";
+                        break;
+                    default:
+                }
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    in_window.org.pkijs.getAlgorithmByEncryptionOID =
+    function(oid)
+    {
+        /// <summary>Get encryption algorithm name by OID</summary>
+        /// <param name="oid" type="String">OID of encryption algorithm</param>
+
+        var result = "";
+
+        switch(oid)
+        {
+            case "2.16.840.1.101.3.4.1.2":
+            case "2.16.840.1.101.3.4.1.22":
+            case "2.16.840.1.101.3.4.1.42":
+                result = "AES-CBC";
+                break;
+            case "2.16.840.1.101.3.4.1.6":
+            case "2.16.840.1.101.3.4.1.26":
+            case "2.16.840.1.101.3.4.1.46":
+                result = "AES-GCM";
+                break;
+            default:
+        }
+
+        return result;
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+}
+)(typeof exports !== "undefined" ? exports : window);
\ No newline at end of file
new file mode 100644
--- /dev/null
+++ b/dom/u2f/tests/pkijs/x509_schema.js
@@ -0,0 +1,1889 @@
+/*
+ * Copyright (c) 2014, GMO GlobalSign
+ * Copyright (c) 2015, Peculiar Ventures
+ * All rights reserved.
+ *
+ * Author 2014-2015, Yury Strozhevsky <www.strozhevsky.com>.
+ *
+ * Redistribution and use in source and binary forms, with or without modification, 
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, 
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice, 
+ *    this list of conditions and the following disclaimer in the documentation 
+ *    and/or other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors 
+ *    may be used to endorse or promote products derived from this software without 
+ *    specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
+ * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY 
+ * OF SUCH DAMAGE. 
+ *
+ */
+(
+function(in_window)
+{
+    //**************************************************************************************
+    // #region Declaration of global variables 
+    //**************************************************************************************
+    // #region "org" namespace 
+    if(typeof in_window.org === "undefined")
+        in_window.org = {};
+    else
+    {
+        if(typeof in_window.org !== "object")
+            throw new Error("Name org already exists and it's not an object");
+    }
+    // #endregion 
+
+    // #region "org.pkijs" namespace 
+    if(typeof in_window.org.pkijs === "undefined")
+        in_window.org.pkijs = {};
+    else
+    {
+        if(typeof in_window.org.pkijs !== "object")
+            throw new Error("Name org.pkijs already exists and it's not an object" + " but " + (typeof in_window.org.pkijs));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.schema" namespace 
+    if(typeof in_window.org.pkijs.schema === "undefined")
+        in_window.org.pkijs.schema = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.schema !== "object")
+            throw new Error("Name org.pkijs.schema already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema));
+    }
+    // #endregion 
+
+    // #region "org.pkijs.schema.x509" namespace 
+    if(typeof in_window.org.pkijs.schema.x509 === "undefined")
+        in_window.org.pkijs.schema.x509 = {};
+    else
+    {
+        if(typeof in_window.org.pkijs.schema.x509 !== "object")
+            throw new Error("Name org.pkijs.schema.x509 already exists and it's not an object" + " but " + (typeof in_window.org.pkijs.schema.x509));
+    }
+    // #endregion 
+
+    // #region "local" namespace 
+    var local = {};
+    // #endregion   
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for "Time" type 
+    //**************************************************************************************
+    in_window.org.pkijs.schema.TIME =
+    function(input_names, input_optional)
+    {
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+        var optional = (input_optional || false);
+
+        return (new in_window.org.pkijs.asn1.CHOICE({
+            optional: optional,
+            value: [
+                new in_window.org.pkijs.asn1.UTCTIME({ name: (names.utcTimeName || "") }),
+                new in_window.org.pkijs.asn1.GENERALIZEDTIME({ name: (names.generalTimeName || "") })
+            ]
+        }));
+    };
+    //**************************************************************************************
+    // #endregion 
+    //**************************************************************************************
+    // #region ASN.1 schema definition for X.509 v3 certificate (RFC5280)
+    //**************************************************************************************
+    local.tbsCertificate =
+    function()
+    {
+        //TBSCertificate  ::=  SEQUENCE  {
+        //    version         [0]  EXPLICIT Version DEFAULT v1,
+        //    serialNumber         CertificateSerialNumber,
+        //    signature            AlgorithmIdentifier,
+        //    issuer               Name,
+        //    validity             Validity,
+        //    subject              Name,
+        //    subjectPublicKeyInfo SubjectPublicKeyInfo,
+        //    issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
+        //                         -- If present, version MUST be v2 or v3
+        //    subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
+        //                         -- If present, version MUST be v2 or v3
+        //    extensions      [3]  EXPLICIT Extensions OPTIONAL
+        //    -- If present, version MUST be v3
+        //}
+
+        var names = in_window.org.pkijs.getNames(arguments[0]);
+
+        return (new in_window.org.pkijs.asn1.SEQUENCE({
+            name: (names.block_name || "tbsCertificate"),
+            value: [
+                new in_window.org.pkijs.asn1.ASN1_CONSTRUCTED({
+                    optional: true,
+                    id_block: {
+                        tag_class: 3, // CONTEXT-SPECIFIC
+                        tag_number: 0 // [0]
+                    },
+                value: [
+                    new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_version || "tbsCertificate.version") }) // EXPLICIT integer value
+                ]
+            }),
+                new in_window.org.pkijs.asn1.INTEGER({ name: (names.tbsCertificate_serialNumber || "tbsCertificate.serialNumber") }),
+                in_window.org.pkijs.schema.ALGORITHM_IDENTIFIER(names.signature || {
+                    names: {
+                        block_name: "tbsCertificate.signature"
+                    }
+                }),
+                in_window.org.pkijs.schema.RDN(names.issuer || {
+                    names: {
+                        block_name: "tbsCertificate.issuer"
+                    }
+                }),
+                new in_window.org.pkijs.asn1.SEQUENCE({
+                    name: (names.tbsCertificate_validity || "tbsCertificate.validity"),
+                    value: [
+                        in_window.org.pkijs.schema.TIME(names.not_before || {
+                            names: {
+                                utcTimeName: "tbsCertificate.notBefore",
+                                generalTimeName: "tbsCertificate.notBefore"
+                            }
+                        }),
+                        in_window.org.pkijs.schema.TIME(names.not_after || {
+                            names: {
+                                utcTimeName: "tbsCertificate.notAfter",
+                                generalTimeName: "tbsCertificate.notAfter"
+                            }
+                        })
+                    ]
+                }),
+                in_window.org.pkijs.schema.RDN(names.subject || {
+                    names: {
+                        block_name: "tbsCertificate.subject"
+                    }
+                }),
+                in_window.org.pkijs.schema.PUBLIC_KEY_INFO(names.subjectPublicKeyInfo || {
+                    names: {
+