OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Must be packed to ../enterprise_platform_keys.crx using the private key | 5 // Must be packed to ../enterprise_platform_keys.crx using the private key |
6 // ../enterprise_platform_keys.pem . | 6 // ../enterprise_platform_keys.pem . |
7 | 7 |
| 8 'use strict'; |
| 9 |
8 var assertEq = chrome.test.assertEq; | 10 var assertEq = chrome.test.assertEq; |
9 var assertTrue = chrome.test.assertTrue; | 11 var assertTrue = chrome.test.assertTrue; |
10 var assertThrows = chrome.test.assertThrows; | 12 var assertThrows = chrome.test.assertThrows; |
11 var fail = chrome.test.fail; | 13 var fail = chrome.test.fail; |
12 var succeed = chrome.test.succeed; | 14 var succeed = chrome.test.succeed; |
13 var callbackPass = chrome.test.callbackPass; | 15 var callbackPass = chrome.test.callbackPass; |
14 var callbackFail= chrome.test.callbackFail; | 16 var callbackFail= chrome.test.callbackFail; |
15 | 17 |
16 // openssl req -new -x509 -key privkey.pem \ | 18 // openssl req -new -x509 -key privkey.pem \ |
17 // -outform der -out cert.der -days 36500 | 19 // -outform der -out cert.der -days 36500 |
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 assertTrue(!!chrome.enterprise.platformKeys, "No platformKeys namespace."); | 245 assertTrue(!!chrome.enterprise.platformKeys, "No platformKeys namespace."); |
244 assertTrue(!!chrome.enterprise.platformKeys.getTokens, | 246 assertTrue(!!chrome.enterprise.platformKeys.getTokens, |
245 "No getTokens function."); | 247 "No getTokens function."); |
246 assertTrue(!!chrome.enterprise.platformKeys.importCertificate, | 248 assertTrue(!!chrome.enterprise.platformKeys.importCertificate, |
247 "No importCertificate function."); | 249 "No importCertificate function."); |
248 assertTrue(!!chrome.enterprise.platformKeys.removeCertificate, | 250 assertTrue(!!chrome.enterprise.platformKeys.removeCertificate, |
249 "No removeCertificate function."); | 251 "No removeCertificate function."); |
250 | 252 |
251 getUserToken(function(userToken) { | 253 getUserToken(function(userToken) { |
252 if (!userToken) | 254 if (!userToken) |
253 chrome.test.fail('no user token'); | 255 fail('no user token'); |
254 if (userToken.id != 'user') | 256 if (userToken.id != 'user') |
255 chrome.test.fail('token is not named "user".'); | 257 fail('token is not named "user".'); |
256 | 258 |
257 callback(userToken); | 259 callback(userToken); |
258 }); | 260 }); |
259 } | 261 } |
260 | 262 |
| 263 function checkKeyPairCommonFormat(keyPair) { |
| 264 function checkReadOnly(object, key) { |
| 265 var original = object[key]; |
| 266 try { |
| 267 object[key] = {}; |
| 268 fail('Expected that the property is read only and an exception to ' + |
| 269 'be thrown'); |
| 270 } catch (error) { |
| 271 assertTrue(object[key] === original); |
| 272 } |
| 273 } |
| 274 |
| 275 checkReadOnly(keyPair, 'privateKey'); |
| 276 var privateKey = keyPair.privateKey; |
| 277 assertEq('private', privateKey.type); |
| 278 assertEq(false, privateKey.extractable); |
| 279 checkReadOnly(privateKey, 'algorithm'); |
| 280 checkReadOnly(privateKey.algorithm, 'hash'); |
| 281 checkReadOnly(privateKey.algorithm, 'modulusLength'); |
| 282 checkReadOnly(privateKey.algorithm, 'name'); |
| 283 |
| 284 checkReadOnly(keyPair, 'publicKey'); |
| 285 var publicKey = keyPair.publicKey; |
| 286 assertEq('public', publicKey.type); |
| 287 assertEq(true, publicKey.extractable); |
| 288 checkReadOnly(publicKey, 'algorithm'); |
| 289 checkReadOnly(publicKey.algorithm, 'hash'); |
| 290 checkReadOnly(publicKey.algorithm, 'modulusLength'); |
| 291 checkReadOnly(publicKey.algorithm, 'name'); |
| 292 } |
| 293 |
261 function runTests(userToken) { | 294 function runTests(userToken) { |
262 chrome.test.runTests([ | 295 chrome.test.runTests([ |
263 function hasSubtleCryptoMethods() { | 296 function hasSubtleCryptoMethods() { |
264 assertTrue(!!userToken.subtleCrypto.generateKey, | 297 assertTrue(!!userToken.subtleCrypto.generateKey, |
265 "user token has no generateKey method"); | 298 "user token has no generateKey method"); |
266 assertTrue(!!userToken.subtleCrypto.sign, | 299 assertTrue(!!userToken.subtleCrypto.sign, |
267 "user token has no sign method"); | 300 "user token has no sign method"); |
268 assertTrue(!!userToken.subtleCrypto.exportKey, | 301 assertTrue(!!userToken.subtleCrypto.exportKey, |
269 "user token has no exportKey method"); | 302 "user token has no exportKey method"); |
270 succeed(); | 303 succeed(); |
271 }, | 304 }, |
272 function initiallyNoCerts() { assertCertsStored(userToken, []); }, | 305 function initiallyNoCerts() { assertCertsStored(userToken, []); }, |
273 | 306 |
274 // Generates a key and sign some data with it. Verifies the signature using | 307 // Generates a key and sign some data with it. Verifies the signature using |
275 // WebCrypto. | 308 // WebCrypto. |
276 function generateKeyAndSign() { | 309 function generateKeyAndSign() { |
277 var algorithm = { | 310 var algorithm = { |
278 name: "RSASSA-PKCS1-v1_5", | 311 name: "RSASSA-PKCS1-v1_5", |
279 // RsaHashedKeyGenParams | 312 // RsaHashedKeyGenParams |
280 modulusLength: 512, | 313 modulusLength: 512, |
281 publicExponent: | 314 // Equivalent to 65537 |
282 new Uint8Array([0x01, 0x00, 0x01]), // Equivalent to 65537 | 315 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), |
283 hash: { | 316 hash: { |
284 name: "SHA-1", | 317 name: "SHA-1", |
285 } | 318 } |
286 }; | 319 }; |
287 // Some random data to sign. | 320 // Some random data to sign. |
288 var data = new Uint8Array([0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6]); | 321 var data = new Uint8Array([0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 6]); |
289 var cachedKeyPair; | 322 var cachedKeyPair; |
290 var cachedSpki; | 323 var cachedSpki; |
291 var cachedSignature; | 324 var cachedSignature; |
292 userToken.subtleCrypto.generateKey(algorithm, false, ["sign"]) | 325 userToken.subtleCrypto.generateKey(algorithm, false, ["sign"]) |
293 .then(callbackPass(function(keyPair) { | 326 .then(callbackPass(function(keyPair) { |
294 assertTrue(!!keyPair, "No key pair."); | 327 assertTrue(!!keyPair, "No key pair."); |
295 cachedKeyPair = keyPair; | 328 cachedKeyPair = keyPair; |
296 return userToken.subtleCrypto.exportKey('spki', | 329 return userToken.subtleCrypto.exportKey('spki', |
297 keyPair.publicKey); | 330 keyPair.publicKey); |
298 }), | 331 }), |
299 function(error) { | 332 function(error) { fail("GenerateKey failed: " + error); }) |
300 assertTrue(false, "GenerateKey failed: " + error); | |
301 }) | |
302 .then(callbackPass(function(publicKeySpki) { | 333 .then(callbackPass(function(publicKeySpki) { |
| 334 // Ensure that the returned key pair has the expected format. |
| 335 // Some parameter independent checks: |
| 336 checkKeyPairCommonFormat(cachedKeyPair); |
| 337 |
| 338 // Checks depending on the generateKey arguments: |
| 339 var privateKey = cachedKeyPair.privateKey; |
| 340 assertEq(['sign'], privateKey.usages); |
| 341 assertEq(algorithm, privateKey.algorithm); |
| 342 |
| 343 var publicKey = cachedKeyPair.publicKey; |
| 344 assertEq([], publicKey.usages); |
| 345 assertEq(algorithm, publicKey.algorithm); |
| 346 |
303 cachedSpki = publicKeySpki; | 347 cachedSpki = publicKeySpki; |
304 var signParams = {name: 'RSASSA-PKCS1-v1_5'}; | 348 var signParams = {name: 'RSASSA-PKCS1-v1_5'}; |
305 return userToken.subtleCrypto.sign( | 349 return userToken.subtleCrypto.sign( |
306 signParams, cachedKeyPair.privateKey, data); | 350 signParams, privateKey, data); |
307 }), | 351 }), |
308 function(error) { | 352 function(error) { fail("Export failed: " + error); }) |
309 assertTrue(false, "Export failed: " + error); | |
310 }) | |
311 .then(callbackPass(function(signature) { | 353 .then(callbackPass(function(signature) { |
312 var importParams = { | 354 var importParams = { |
313 name: algorithm.name, | 355 name: algorithm.name, |
314 // RsaHashedImportParams | 356 // RsaHashedImportParams |
315 hash: { | 357 hash: { |
316 name: "SHA-1", | 358 name: "SHA-1", |
317 } | 359 } |
318 }; | 360 }; |
319 assertTrue(!!signature, "No signature."); | 361 assertTrue(!!signature, "No signature."); |
320 assertTrue(signature.length != 0, "Signature is empty."); | 362 assertTrue(signature.length != 0, "Signature is empty."); |
321 cachedSignature = signature; | 363 cachedSignature = signature; |
322 return window.crypto.subtle.importKey( | 364 return window.crypto.subtle.importKey( |
323 "spki", cachedSpki, importParams, false, ["verify"]); | 365 "spki", cachedSpki, importParams, false, ["verify"]); |
324 }), | 366 }), |
325 function(error) { assertTrue(false, "Sign failed: " + error); }) | 367 function(error) { fail("Sign failed: " + error); }) |
326 .then(callbackPass(function(webCryptoPublicKey) { | 368 .then(callbackPass(function(webCryptoPublicKey) { |
327 assertTrue(!!webCryptoPublicKey); | 369 assertTrue(!!webCryptoPublicKey); |
328 assertEq(algorithm.modulusLength, | 370 assertEq(algorithm.modulusLength, |
329 webCryptoPublicKey.algorithm.modulusLength); | 371 webCryptoPublicKey.algorithm.modulusLength); |
330 assertEq(algorithm.publicExponent, | 372 assertEq(algorithm.publicExponent, |
331 webCryptoPublicKey.algorithm.publicExponent); | 373 webCryptoPublicKey.algorithm.publicExponent); |
332 return window.crypto.subtle.verify( | 374 return window.crypto.subtle.verify( |
333 algorithm, webCryptoPublicKey, cachedSignature, data); | 375 algorithm, webCryptoPublicKey, cachedSignature, data); |
334 }), | 376 }), |
335 function(error) { | 377 function(error) { fail("Import failed: " + error); }) |
336 assertTrue(false, "Import failed: " + error); | |
337 }) | |
338 .then(callbackPass(function(success) { | 378 .then(callbackPass(function(success) { |
339 assertEq(true, success, "Signature invalid."); | 379 assertEq(true, success, "Signature invalid."); |
340 }), | 380 }), |
341 function(error) { | 381 function(error) { fail("Verification failed: " + error); }); |
342 assertTrue(false, "Verification failed: " + error); | |
343 }); | |
344 }, | 382 }, |
345 | 383 |
346 // Imports and removes certificates for privateKeyPkcs8, which was imported | 384 // Imports and removes certificates for privateKeyPkcs8, which was imported |
347 // by on C++'s side. | 385 // by on C++'s side. |
348 // Note: After this test, privateKeyPkcs8 is not stored anymore! | 386 // Note: After this test, privateKeyPkcs8 is not stored anymore! |
349 function importAndRemoveCerts() { | 387 function importAndRemoveCerts() { |
350 runAsyncSequence([ | 388 runAsyncSequence([ |
351 chrome.enterprise.platformKeys.importCertificate.bind( | 389 chrome.enterprise.platformKeys.importCertificate.bind( |
352 null, userToken.id, cert1a.buffer), | 390 null, userToken.id, cert1a.buffer), |
353 assertCertsStored.bind(null, userToken, [cert1a]), | 391 assertCertsStored.bind(null, userToken, [cert1a]), |
(...skipping 19 matching lines...) Expand all Loading... |
373 function algorithmParameterMissingModulusLength() { | 411 function algorithmParameterMissingModulusLength() { |
374 var algorithm = { | 412 var algorithm = { |
375 name: "RSASSA-PKCS1-v1_5", | 413 name: "RSASSA-PKCS1-v1_5", |
376 // Equivalent to 65537 | 414 // Equivalent to 65537 |
377 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | 415 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), |
378 hash: { | 416 hash: { |
379 name: "SHA-1", | 417 name: "SHA-1", |
380 } | 418 } |
381 }; | 419 }; |
382 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( | 420 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( |
383 function(keyPair) { | 421 function(keyPair) { fail('generateKey was expected to fail'); }, |
384 assertTrue(false, 'generateKey was expected to fail'); | |
385 }, | |
386 callbackPass(function(error) { | 422 callbackPass(function(error) { |
387 assertTrue(error instanceof Error); | 423 assertTrue(error instanceof Error); |
388 assertEq('A required parameter was missing or out-of-range', | 424 assertEq('A required parameter was missing or out-of-range', |
389 error.message); | 425 error.message); |
390 })); | 426 })); |
391 }, | 427 }, |
392 | 428 |
393 // Call generate key with invalid algorithm parameter, missing hash. | 429 // Call generate key with invalid algorithm parameter, missing hash. |
394 function algorithmParameterMissingHash() { | 430 function algorithmParameterMissingHash() { |
395 var algorithm = { | 431 var algorithm = { |
396 name: 'RSASSA-PKCS1-v1_5', | 432 name: 'RSASSA-PKCS1-v1_5', |
397 modulusLength: 512, | 433 modulusLength: 512, |
398 // Equivalent to 65537 | 434 // Equivalent to 65537 |
399 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), | 435 publicExponent: new Uint8Array([0x01, 0x00, 0x01]), |
400 }; | 436 }; |
401 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( | 437 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( |
402 function(keyPair) { | 438 function(keyPair) { fail('generateKey was expected to fail'); }, |
403 assertTrue(false, 'generateKey was expected to fail'); | |
404 }, | |
405 callbackPass(function(error) { | 439 callbackPass(function(error) { |
406 assertEq( | 440 assertEq( |
407 new Error('Error: A required parameter was missing our out-of-range'), | 441 new Error('Error: A required parameter was missing our out-of-range'), |
408 error); | 442 error); |
409 })); | 443 })); |
410 }, | 444 }, |
411 | 445 |
412 // Call generate key with invalid algorithm parameter, unsupported public | 446 // Call generate key with invalid algorithm parameter, unsupported public |
413 // exponent. | 447 // exponent. |
414 function algorithmParameterUnsupportedPublicExponent() { | 448 function algorithmParameterUnsupportedPublicExponent() { |
415 var algorithm = { | 449 var algorithm = { |
416 name: 'RSASSA-PKCS1-v1_5', | 450 name: 'RSASSA-PKCS1-v1_5', |
417 modulusLength: 512, | 451 modulusLength: 512, |
418 // Different from 65537. | 452 // Different from 65537. |
419 publicExponent: new Uint8Array([0x01, 0x01]), | 453 publicExponent: new Uint8Array([0x01, 0x01]), |
420 }; | 454 }; |
421 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( | 455 userToken.subtleCrypto.generateKey(algorithm, false, ['sign']).then( |
422 function(keyPair) { | 456 function(keyPair) { fail('generateKey was expected to fail'); }, |
423 assertTrue(false, 'generateKey was expected to fail'); | |
424 }, | |
425 callbackPass(function(error) { | 457 callbackPass(function(error) { |
426 assertTrue(error instanceof Error); | 458 assertTrue(error instanceof Error); |
427 assertEq('A required parameter was missing or out-of-range', | 459 assertEq('A required parameter was missing or out-of-range', |
428 error.message); | 460 error.message); |
429 })); | 461 })); |
430 }, | 462 }, |
431 | 463 |
432 // Imports a certificate for which now private key was imported/generated | 464 // Imports a certificate for which now private key was imported/generated |
433 // before. | 465 // before. |
434 function missingPrivateKey() { | 466 function missingPrivateKey() { |
(...skipping 21 matching lines...) Expand all Loading... |
456 callbackFail('Certificate is not a valid X.509 certificate.')); | 488 callbackFail('Certificate is not a valid X.509 certificate.')); |
457 }, | 489 }, |
458 function getCertsInvalidToken() { | 490 function getCertsInvalidToken() { |
459 chrome.enterprise.platformKeys.getCertificates( | 491 chrome.enterprise.platformKeys.getCertificates( |
460 'invalid token id', callbackFail('The token is not valid.')); | 492 'invalid token id', callbackFail('The token is not valid.')); |
461 } | 493 } |
462 ]); | 494 ]); |
463 } | 495 } |
464 | 496 |
465 beforeTests(runTests); | 497 beforeTests(runTests); |
OLD | NEW |