summaryrefslogtreecommitdiffstats
path: root/dom/media/webrtc/tests/mochitests/test_peerConnection_certificates.html
blob: 17b05c8a255d21d6a8b9abc907dbef0e39c56322 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
<!DOCTYPE HTML>
<html>
<head>
  <script type="application/javascript" src="pc.js"></script>
</head>
<body>
<pre id="test">
<script type="application/javascript">
  createHTML({
    bug: "1172785",
    title: "Certificate management"
  });

  function badCertificate(config, expectedError, message) {
    return RTCPeerConnection.generateCertificate(config)
      .then(() => ok(false, message),
            e => is(e.name, expectedError, message));
  }

  // Checks a handful of obviously bad options to RTCCertificate.create().  Most
  // of the checking is done by the WebCrypto code underpinning this, hence the
  // baffling error codes, but a sanity check is still in order.
  function checkBadParameters() {
    return Promise.all([
      badCertificate({
        name: "RSASSA-PKCS1-v1_5",
        hash: "SHA-256",
        modulusLength: 1023,
        publicExponent: new Uint8Array([1, 0, 1])
      }, "NotSupportedError", "1023-bit is too small to succeed"),

      badCertificate({
        name: "RSASSA-PKCS1-v1_5",
          hash: "SHA-384",
          modulusLength: 2048,
          publicExponent: new Uint8Array([1, 0, 1])
      }, "NotSupportedError", "SHA-384 isn't supported yet"),

      // A SyntaxError happens in the "generate key operation" step, but
      // webrtc-pc does not say to reject the promise if this step fails.
      // It does say to throw NotSupportedError if we have passed "an
      // algorithm that the user agent cannot or will not use to generate a
      // certificate".
      badCertificate({
        name: "ECDH",
        namedCurve: "P-256"
      }, "NotSupportedError", "ECDH is rejected because the usage is neither \"deriveKey\" or \"deriveBits\""),

      badCertificate({
        name: "not a valid algorithm"
      }, "NotSupportedError", "not a valid algorithm"),

      badCertificate("ECDSA", "NotSupportedError", "a bare name is not enough"),

      badCertificate({
        name: "ECDSA",
        namedCurve: "not a curve"
      }, "NotSupportedError", "ECDSA with an unknown curve")
    ]);
  }

  function createDB() {
    var openDB = indexedDB.open("genericstore");
    openDB.onupgradeneeded = e => {
      var db = e.target.result;
      db.createObjectStore("data");
    };
    return new Promise(resolve => {
      openDB.onsuccess = e => resolve(e.target.result);
    });
  }

  function resultPromise(tx, op) {
    return new Promise((resolve, reject) => {
      op.onsuccess = e => resolve(e.target.result);
      op.onerror = () => reject(op.error);
      tx.onabort = () => reject(tx.error);
    });
  }

  function store(db, value) {
    var tx = db.transaction("data", "readwrite");
    var store = tx.objectStore("data");
    return resultPromise(tx, store.put(value, "value"));
  }

  function retrieve(db) {
    var tx = db.transaction("data", "readonly");
    var store = tx.objectStore("data");
    return resultPromise(tx, store.get("value"));
  }

  // Creates a database, stores a value, retrieves it.
  function storeAndRetrieve(value) {
    return createDB().then(db => {
      return store(db, value)
        .then(() => retrieve(db))
        .then(retrieved => {
          db.close();
          return retrieved;
        });
    });
  }

  var test;
  runNetworkTest(function (options) {
    var expiredCert;
    return Promise.resolve()
      .then(() => RTCPeerConnection.generateCertificate({
        name: "ECDSA",
        namedCurve: "P-256",
        expires: 1 // smallest possible expiration window
      }))
      .then(cert => {
        ok(!isNaN(cert.expires), 'cert has expiration time');
        info('Expires at ' + new Date(cert.expires));
        expiredCert = cert;
      })

      .then(() => checkBadParameters())

      .then(() => {
        var delay = expiredCert.expires - Date.now();
        // Hopefully this delay is never needed.
        if (delay > 0) {
          return new Promise(r => setTimeout(r, delay));
        }
        return Promise.resolve();
      })
      .then(() => {
        ok(expiredCert.expires <= Date.now(), 'Cert should be at or past expiration');
        try {
          new RTCPeerConnection({ certificates: [expiredCert] });
          ok(false, 'Constructing peer connection with an expired cert is not allowed');
        } catch(e) {
          is(e.name, 'InvalidAccessError',
             'Constructing peer connection with an expired certs is not allowed');
        }
      })

      .then(() => Promise.all([
        RTCPeerConnection.generateCertificate({
          name: "ECDSA",
          namedCurve: "P-256"
        }),
        RTCPeerConnection.generateCertificate({
          name: "RSASSA-PKCS1-v1_5",
          hash: "SHA-256",
          modulusLength: 2048,
          publicExponent: new Uint8Array([1, 0, 1])
        })
      ]))

    // A round trip through indexedDB should not do anything.
      .then(storeAndRetrieve)
      .then(certs => {
        try {
          new RTCPeerConnection({ certificates: certs });
          ok(false, 'Constructing peer connection with multiple certs is not allowed');
        } catch(e) {
          is(e.name, 'NotSupportedError',
             'Constructing peer connection with multiple certs is not allowed');
        }
        return certs;
      })
      .then(certs => {
        test = new PeerConnectionTest({
          config_local: {
            certificates: [certs[0]]
          },
          config_remote: {
            certificates: [certs[1]]
          }
        });
        test.setMediaConstraints([{audio: true}], [{audio: true}]);
        return test.run();
      })
      .catch(e => {
        console.log('test failure', e);
        ok(false, 'test failed: ' + e);
      });
  });
</script>
</pre>
</body>
</html>