tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

test_peerConnection_certificates.html (5727B)


      1 <!DOCTYPE HTML>
      2 <html>
      3 <head>
      4  <script type="application/javascript" src="pc.js"></script>
      5 </head>
      6 <body>
      7 <pre id="test">
      8 <script type="application/javascript">
      9  createHTML({
     10    bug: "1172785",
     11    title: "Certificate management"
     12  });
     13 
     14  function badCertificate(config, expectedError, message) {
     15    return RTCPeerConnection.generateCertificate(config)
     16      .then(() => ok(false, message),
     17            e => is(e.name, expectedError, message));
     18  }
     19 
     20  // Checks a handful of obviously bad options to RTCCertificate.create().  Most
     21  // of the checking is done by the WebCrypto code underpinning this, hence the
     22  // baffling error codes, but a sanity check is still in order.
     23  function checkBadParameters() {
     24    return Promise.all([
     25      badCertificate({
     26        name: "RSASSA-PKCS1-v1_5",
     27        hash: "SHA-256",
     28        modulusLength: 1023,
     29        publicExponent: new Uint8Array([1, 0, 1])
     30      }, "NotSupportedError", "1023-bit is too small to succeed"),
     31 
     32      badCertificate({
     33        name: "RSASSA-PKCS1-v1_5",
     34          hash: "SHA-384",
     35          modulusLength: 2048,
     36          publicExponent: new Uint8Array([1, 0, 1])
     37      }, "NotSupportedError", "SHA-384 isn't supported yet"),
     38 
     39      // A SyntaxError happens in the "generate key operation" step, but
     40      // webrtc-pc does not say to reject the promise if this step fails.
     41      // It does say to throw NotSupportedError if we have passed "an
     42      // algorithm that the user agent cannot or will not use to generate a
     43      // certificate".
     44      badCertificate({
     45        name: "ECDH",
     46        namedCurve: "P-256"
     47      }, "NotSupportedError", "ECDH is rejected because the usage is neither \"deriveKey\" or \"deriveBits\""),
     48 
     49      badCertificate({
     50        name: "not a valid algorithm"
     51      }, "NotSupportedError", "not a valid algorithm"),
     52 
     53      badCertificate("ECDSA", "NotSupportedError", "a bare name is not enough"),
     54 
     55      badCertificate({
     56        name: "ECDSA",
     57        namedCurve: "not a curve"
     58      }, "NotSupportedError", "ECDSA with an unknown curve")
     59    ]);
     60  }
     61 
     62  function createDB() {
     63    var openDB = indexedDB.open("genericstore");
     64    openDB.onupgradeneeded = e => {
     65      var db = e.target.result;
     66      db.createObjectStore("data");
     67    };
     68    return new Promise(resolve => {
     69      openDB.onsuccess = e => resolve(e.target.result);
     70    });
     71  }
     72 
     73  function resultPromise(tx, op) {
     74    return new Promise((resolve, reject) => {
     75      op.onsuccess = e => resolve(e.target.result);
     76      op.onerror = () => reject(op.error);
     77      tx.onabort = () => reject(tx.error);
     78    });
     79  }
     80 
     81  function store(db, value) {
     82    var tx = db.transaction("data", "readwrite");
     83    var store = tx.objectStore("data");
     84    return resultPromise(tx, store.put(value, "value"));
     85  }
     86 
     87  function retrieve(db) {
     88    var tx = db.transaction("data", "readonly");
     89    var store = tx.objectStore("data");
     90    return resultPromise(tx, store.get("value"));
     91  }
     92 
     93  // Creates a database, stores a value, retrieves it.
     94  function storeAndRetrieve(value) {
     95    return createDB().then(db => {
     96      return store(db, value)
     97        .then(() => retrieve(db))
     98        .then(retrieved => {
     99          db.close();
    100          return retrieved;
    101        });
    102    });
    103  }
    104 
    105  var test;
    106  runNetworkTest(function (options) {
    107    var expiredCert;
    108    return Promise.resolve()
    109      .then(() => RTCPeerConnection.generateCertificate({
    110        name: "ECDSA",
    111        namedCurve: "P-256",
    112        expires: 1 // smallest possible expiration window
    113      }))
    114      .then(cert => {
    115        ok(!isNaN(cert.expires), 'cert has expiration time');
    116        info('Expires at ' + new Date(cert.expires));
    117        expiredCert = cert;
    118      })
    119 
    120      .then(() => checkBadParameters())
    121 
    122      .then(() => {
    123        var delay = expiredCert.expires - Date.now();
    124        // Hopefully this delay is never needed.
    125        if (delay > 0) {
    126          return new Promise(r => setTimeout(r, delay));
    127        }
    128        return Promise.resolve();
    129      })
    130      .then(() => {
    131        ok(expiredCert.expires <= Date.now(), 'Cert should be at or past expiration');
    132        try {
    133          new RTCPeerConnection({ certificates: [expiredCert] });
    134          ok(false, 'Constructing peer connection with an expired cert is not allowed');
    135        } catch(e) {
    136          is(e.name, 'InvalidAccessError',
    137             'Constructing peer connection with an expired certs is not allowed');
    138        }
    139      })
    140 
    141      .then(() => Promise.all([
    142        RTCPeerConnection.generateCertificate({
    143          name: "ECDSA",
    144          namedCurve: "P-256"
    145        }),
    146        RTCPeerConnection.generateCertificate({
    147          name: "RSASSA-PKCS1-v1_5",
    148          hash: "SHA-256",
    149          modulusLength: 2048,
    150          publicExponent: new Uint8Array([1, 0, 1])
    151        })
    152      ]))
    153 
    154    // A round trip through indexedDB should not do anything.
    155      .then(storeAndRetrieve)
    156      .then(certs => {
    157        try {
    158          new RTCPeerConnection({ certificates: certs });
    159          ok(false, 'Constructing peer connection with multiple certs is not allowed');
    160        } catch(e) {
    161          is(e.name, 'NotSupportedError',
    162             'Constructing peer connection with multiple certs is not allowed');
    163        }
    164        return certs;
    165      })
    166      .then(certs => {
    167        test = new PeerConnectionTest({
    168          config_local: {
    169            certificates: [certs[0]]
    170          },
    171          config_remote: {
    172            certificates: [certs[1]]
    173          }
    174        });
    175        test.setMediaConstraints([{audio: true}], [{audio: true}]);
    176        return test.run();
    177      })
    178      .catch(e => {
    179        console.log('test failure', e);
    180        ok(false, 'test failed: ' + e);
    181      });
    182  });
    183 </script>
    184 </pre>
    185 </body>
    186 </html>