Changeset 159379 in webkit


Ignore:
Timestamp:
Nov 16, 2013 10:58:39 AM (10 years ago)
Author:
ap@apple.com
Message:

WebCrypto no longer uses sequences of ArrayBuffers
https://bugs.webkit.org/show_bug.cgi?id=124451

Reviewed by Sam Weinig.

Source/WebCore:

Covered by existing tests.

Changed all operations to take single CryptoOperationData objects.

  • bindings/js/JSCryptoOperationData.cpp:
  • bindings/js/JSCryptoOperationData.h:
  • bindings/js/JSSubtleCryptoCustom.cpp:

(WebCore::JSSubtleCrypto::encrypt):
(WebCore::JSSubtleCrypto::decrypt):
(WebCore::JSSubtleCrypto::sign):
(WebCore::JSSubtleCrypto::verify):
(WebCore::JSSubtleCrypto::digest):

  • crypto/CryptoAlgorithm.cpp:

(WebCore::CryptoAlgorithm::encrypt):
(WebCore::CryptoAlgorithm::decrypt):
(WebCore::CryptoAlgorithm::sign):
(WebCore::CryptoAlgorithm::verify):
(WebCore::CryptoAlgorithm::digest):

  • crypto/CryptoAlgorithm.h:
  • crypto/CryptoAlgorithmRSASSA_PKCS1_v1_5Mac.cpp:

(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::sign):
(WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::verify):

  • crypto/algorithms/CryptoAlgorithmAES_CBC.h:
  • crypto/algorithms/CryptoAlgorithmHMAC.h:
  • crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.h:
  • crypto/algorithms/CryptoAlgorithmSHA1.cpp:

(WebCore::CryptoAlgorithmSHA1::digest):

  • crypto/algorithms/CryptoAlgorithmSHA1.h:
  • crypto/algorithms/CryptoAlgorithmSHA224.cpp:

(WebCore::CryptoAlgorithmSHA224::digest):

  • crypto/algorithms/CryptoAlgorithmSHA224.h:
  • crypto/algorithms/CryptoAlgorithmSHA256.cpp:

(WebCore::CryptoAlgorithmSHA256::digest):

  • crypto/algorithms/CryptoAlgorithmSHA256.h:
  • crypto/algorithms/CryptoAlgorithmSHA384.cpp:

(WebCore::CryptoAlgorithmSHA384::digest):

  • crypto/algorithms/CryptoAlgorithmSHA384.h:
  • crypto/algorithms/CryptoAlgorithmSHA512.cpp:

(WebCore::CryptoAlgorithmSHA512::digest):

  • crypto/algorithms/CryptoAlgorithmSHA512.h:
  • crypto/mac/CryptoAlgorithmAES_CBCMac.cpp:

(WebCore::transformAES_CBC):
(WebCore::CryptoAlgorithmAES_CBC::encrypt):
(WebCore::CryptoAlgorithmAES_CBC::decrypt):

  • crypto/mac/CryptoAlgorithmHMACMac.cpp:

(WebCore::calculateSignature):
(WebCore::CryptoAlgorithmHMAC::sign):
(WebCore::CryptoAlgorithmHMAC::verify):

  • crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h:

LayoutTests:

Updated tests accordingly.

  • crypto/subtle/aes-cbc-192-encrypt-decrypt.html:
  • crypto/subtle/aes-cbc-256-encrypt-decrypt.html:
  • crypto/subtle/aes-cbc-encrypt-decrypt-expected.txt:
  • crypto/subtle/aes-cbc-encrypt-decrypt-with-padding.html:
  • crypto/subtle/aes-cbc-encrypt-decrypt.html:
  • crypto/subtle/aes-cbc-import-jwk.html:
  • crypto/subtle/aes-cbc-wrong-key-class-expected.txt:
  • crypto/subtle/aes-cbc-wrong-key-class.html:
  • crypto/subtle/argument-conversion-expected.txt:
  • crypto/subtle/argument-conversion.html:
  • crypto/subtle/hmac-import-jwk.html:
  • crypto/subtle/hmac-sign-verify-empty-key.html:
  • crypto/subtle/hmac-sign-verify.html:
  • crypto/subtle/rsassa-pkcs1-v1_5-sign-verify.html:
  • crypto/subtle/sha-1-expected.txt:
  • crypto/subtle/sha-1.html:
  • crypto/subtle/sha-224-expected.txt:
  • crypto/subtle/sha-224.html:
  • crypto/subtle/sha-256-expected.txt:
  • crypto/subtle/sha-256.html:
  • crypto/subtle/sha-384-expected.txt:
  • crypto/subtle/sha-384.html:
  • crypto/subtle/sha-512-expected.txt:
  • crypto/subtle/sha-512.html:
Location:
trunk
Files:
48 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r159377 r159379  
     12013-11-16  Alexey Proskuryakov  <ap@apple.com>
     2
     3        WebCrypto no longer uses sequences of ArrayBuffers
     4        https://bugs.webkit.org/show_bug.cgi?id=124451
     5
     6        Reviewed by Sam Weinig.
     7
     8        Updated tests accordingly.
     9
     10        * crypto/subtle/aes-cbc-192-encrypt-decrypt.html:
     11        * crypto/subtle/aes-cbc-256-encrypt-decrypt.html:
     12        * crypto/subtle/aes-cbc-encrypt-decrypt-expected.txt:
     13        * crypto/subtle/aes-cbc-encrypt-decrypt-with-padding.html:
     14        * crypto/subtle/aes-cbc-encrypt-decrypt.html:
     15        * crypto/subtle/aes-cbc-import-jwk.html:
     16        * crypto/subtle/aes-cbc-wrong-key-class-expected.txt:
     17        * crypto/subtle/aes-cbc-wrong-key-class.html:
     18        * crypto/subtle/argument-conversion-expected.txt:
     19        * crypto/subtle/argument-conversion.html:
     20        * crypto/subtle/hmac-import-jwk.html:
     21        * crypto/subtle/hmac-sign-verify-empty-key.html:
     22        * crypto/subtle/hmac-sign-verify.html:
     23        * crypto/subtle/rsassa-pkcs1-v1_5-sign-verify.html:
     24        * crypto/subtle/sha-1-expected.txt:
     25        * crypto/subtle/sha-1.html:
     26        * crypto/subtle/sha-224-expected.txt:
     27        * crypto/subtle/sha-224.html:
     28        * crypto/subtle/sha-256-expected.txt:
     29        * crypto/subtle/sha-256.html:
     30        * crypto/subtle/sha-384-expected.txt:
     31        * crypto/subtle/sha-384.html:
     32        * crypto/subtle/sha-512-expected.txt:
     33        * crypto/subtle/sha-512.html:
     34
    1352013-11-15  Alexey Proskuryakov  <ap@apple.com>
    236
  • trunk/LayoutTests/crypto/subtle/aes-cbc-192-encrypt-decrypt.html

    r159327 r159379  
    2929
    3030    debug("Using the key to encrypt plaintext...");
    31     return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]);
     31    return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext);
    3232}).then(function(result) {
    3333    encryptionResult = result;
     
    3535
    3636    debug("Decrypting it back...");
    37     return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, [result]);
     37    return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, result);
    3838}).then(function(result) {
    3939    decryptionResult = result;
  • trunk/LayoutTests/crypto/subtle/aes-cbc-256-encrypt-decrypt.html

    r159327 r159379  
    2929
    3030    debug("Using the key to encrypt plaintext...");
    31     return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]);
     31    return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext);
    3232}).then(function(result) {
    3333    encryptionResult = result;
     
    3535
    3636    debug("Decrypting it back...");
    37     return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, [result]);
     37    return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, result);
    3838}).then(function(result) {
    3939    decryptionResult = result;
  • trunk/LayoutTests/crypto/subtle/aes-cbc-encrypt-decrypt-expected.txt

    r159327 r159379  
    1515PASS new Uint8Array(decryptionResult) is plaintext
    1616Testing initialization vector bindings...
    17 PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: null}, key, [plaintext]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
    18 PASS crypto.subtle.encrypt({name: 'AES-CBC'}, key, [plaintext]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
    19 PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: 3}, key, [plaintext]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
    20 PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array([0])}, key, [plaintext]) threw exception Error: AES-CBC initialization data must be 16 bytes.
     17PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: null}, key, plaintext) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     18PASS crypto.subtle.encrypt({name: 'AES-CBC'}, key, plaintext) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     19PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: 3}, key, plaintext) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     20PASS crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array([0])}, key, plaintext) threw exception Error: AES-CBC initialization data must be 16 bytes.
    2121PASS successfullyParsed is true
    2222
  • trunk/LayoutTests/crypto/subtle/aes-cbc-encrypt-decrypt-with-padding.html

    r159327 r159379  
    2929
    3030    debug("Using the key to encrypt plaintext...");
    31     return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]);
     31    return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext);
    3232}).then(function(result) {
    3333    cyphertext = result;
     
    3535
    3636    debug("Decrypting it back...");
    37     return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, [result]);
     37    return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, result);
    3838}).then(function(result) {
    3939    decryptionResult = result;
  • trunk/LayoutTests/crypto/subtle/aes-cbc-encrypt-decrypt.html

    r159327 r159379  
    2929
    3030    debug("Using the key to encrypt plaintext...");
    31     return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]);
     31    return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext);
    3232}).then(function(result) {
    3333    encryptionResult = result;
     
    3535
    3636    debug("Decrypting it back...");
    37     return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, [result]);
     37    return crypto.subtle.decrypt({name: "aes-cbc", iv: iv}, key, result);
    3838}).then(function(result) {
    3939    decryptionResult = result;
     
    4141
    4242    debug("Testing initialization vector bindings...");
    43     shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: null}, key, [plaintext])");
    44     shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC'}, key, [plaintext])");
    45     shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: 3}, key, [plaintext])");
    46     shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array([0])}, key, [plaintext])");
     43    shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: null}, key, plaintext)");
     44    shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC'}, key, plaintext)");
     45    shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: 3}, key, plaintext)");
     46    shouldThrow("crypto.subtle.encrypt({name: 'AES-CBC', iv: new Uint8Array([0])}, key, plaintext)");
    4747
    4848    finishJSTest();
  • trunk/LayoutTests/crypto/subtle/aes-cbc-import-jwk.html

    r159327 r159379  
    4040
    4141    debug("\nUsing the key to encrypt plaintext...");
    42     return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]);
     42    return crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext);
    4343}).then(function(result) {
    4444    encryptionResult = result;
  • trunk/LayoutTests/crypto/subtle/aes-cbc-wrong-key-class-expected.txt

    r158485 r159379  
    66Importing a raw HMAC key from string literal...
    77Using the key to encrypt plaintext...
    8 PASS crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext]) threw exception Error: NotSupportedError: DOM Exception 9.
     8PASS crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext) threw exception Error: NotSupportedError: DOM Exception 9.
    99PASS successfullyParsed is true
    1010
  • trunk/LayoutTests/crypto/subtle/aes-cbc-wrong-key-class.html

    r159327 r159379  
    2323    key = result;
    2424    debug("Using the key to encrypt plaintext...");
    25     shouldThrow('crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, [plaintext])')
     25    shouldThrow('crypto.subtle.encrypt({name: "aes-cbc", iv: iv}, key, plaintext)')
    2626
    2727    finishJSTest();
  • trunk/LayoutTests/crypto/subtle/argument-conversion-expected.txt

    r159327 r159379  
    44
    55
    6 SHA1 of new Uint8Array([]))
    7 PASS bytesToHexString(new Uint8Array(digest)) is 'da39a3ee5e6b4b0d3255bfef95601890afd80709'
    86
    97Passing algorithm name as a string object...
     
    1816Passing invalid data to digest()
    1917PASS crypto.subtle.digest({name: 'sha-1'}) threw exception TypeError: Not enough arguments.
    20 PASS crypto.subtle.digest({name: 'sha-1'}, null) threw exception TypeError: Value is not a sequence.
    21 PASS crypto.subtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Value is not a sequence.
    22 PASS crypto.subtle.digest({name: 'sha-1'}, [10]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be part of CryptoOperationData sequence.
    23 PASS crypto.subtle.digest({name: 'sha-1'}, new Uint8Array([0])) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be part of CryptoOperationData sequence.
     18PASS crypto.subtle.digest({name: 'sha-1'}, null) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     19PASS crypto.subtle.digest({name: 'sha-1'}, 10) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     20PASS crypto.subtle.digest({name: 'sha-1'}, [10]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
     21PASS crypto.subtle.digest({name: 'sha-1'}, [new Uint8Array([0])]) threw exception TypeError: Only ArrayBuffer and ArrayBufferView objects can be passed as CryptoOperationData.
    2422
    2523Passing invalid algorithmIdentifiers to digest()
    26 PASS crypto.subtle.digest({ toString:function() { return 'sha-1' } }, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    27 PASS crypto.subtle.digest({name: ''}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    28 PASS crypto.subtle.digest({name: null}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    29 PASS crypto.subtle.digest({name: undefined}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    30 PASS crypto.subtle.digest({name: 'sha'}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    31 PASS crypto.subtle.digest({name: 1}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    32 PASS crypto.subtle.digest('', [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    33 PASS crypto.subtle.digest(null, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    34 PASS crypto.subtle.digest(undefined, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    35 PASS crypto.subtle.digest(1, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
    36 PASS crypto.subtle.digest({}, [data]) threw exception Error: NotSupportedError: DOM Exception 9.
     24PASS crypto.subtle.digest({ toString:function() { return 'sha-1' } }, data) threw exception Error: NotSupportedError: DOM Exception 9.
     25PASS crypto.subtle.digest({name: ''}, data) threw exception Error: NotSupportedError: DOM Exception 9.
     26PASS crypto.subtle.digest({name: null}, data) threw exception Error: NotSupportedError: DOM Exception 9.
     27PASS crypto.subtle.digest({name: undefined}, data) threw exception Error: NotSupportedError: DOM Exception 9.
     28PASS crypto.subtle.digest({name: 'sha'}, data) threw exception Error: NotSupportedError: DOM Exception 9.
     29PASS crypto.subtle.digest({name: 1}, data) threw exception Error: NotSupportedError: DOM Exception 9.
     30PASS crypto.subtle.digest('', data) threw exception Error: NotSupportedError: DOM Exception 9.
     31PASS crypto.subtle.digest(null, data) threw exception Error: NotSupportedError: DOM Exception 9.
     32PASS crypto.subtle.digest(undefined, data) threw exception Error: NotSupportedError: DOM Exception 9.
     33PASS crypto.subtle.digest(1, data) threw exception Error: NotSupportedError: DOM Exception 9.
     34PASS crypto.subtle.digest({}, data) threw exception Error: NotSupportedError: DOM Exception 9.
    3735PASS successfullyParsed is true
    3836
  • trunk/LayoutTests/crypto/subtle/argument-conversion.html

    r159327 r159379  
    1515
    1616Promise.fulfill(null).then(function() {
    17     // This looks like invalid input, but it actually isn't - Uint8Array is a sequence too,
    18     // so it's just an empty sequence, same as passing [].
    19     debug("SHA1 of new Uint8Array([]))");
    20     return crypto.subtle.digest('sha-1', new Uint8Array([]));
    21 }).then(function(result) {
    22     digest = result;
    23     shouldBe("bytesToHexString(new Uint8Array(digest))", "'da39a3ee5e6b4b0d3255bfef95601890afd80709'");
    24 
    2517    debug("\nPassing algorithm name as a string object...");
    26     return crypto.subtle.digest(new String('sha-1'), []);
     18    return crypto.subtle.digest(new String('sha-1'), new Uint8Array([]));
    2719}).then(function(result) {
    2820    testPassed("...succeeded");
    2921    debug("\nPassing algorithm name as a string object in a dictionary...");
    30     return crypto.subtle.digest({name: new String('sha-1')}, []);
     22    return crypto.subtle.digest({name: new String('sha-1')}, new Uint8Array([]));
    3123}).then(function(result) {
    3224    testPassed("...succeeded");
    3325    debug("\nPassing algorithm name as an object with toString");
    34     return crypto.subtle.digest({name: { toString:function() { return 'sha-1' } } }, []);
     26    return crypto.subtle.digest({name: { toString:function() { return 'sha-1' } } }, new Uint8Array([]));
    3527}).then(function(result) {
    3628    testPassed("...succeeded");
     
    4133    shouldThrow("crypto.subtle.digest({name: 'sha-1'}, 10)");
    4234    shouldThrow("crypto.subtle.digest({name: 'sha-1'}, [10])");
    43     shouldThrow("crypto.subtle.digest({name: 'sha-1'}, new Uint8Array([0]))");
     35    shouldThrow("crypto.subtle.digest({name: 'sha-1'}, [new Uint8Array([0])])");
    4436
    4537    debug("\nPassing invalid algorithmIdentifiers to digest()");
    4638    data = new Uint8Array([0]);
    47     shouldThrow("crypto.subtle.digest({ toString:function() { return 'sha-1' } }, [data])"); // Algorithm normalization doesn't attempt to call toString.
    48     shouldThrow("crypto.subtle.digest({name: ''}, [data])");
    49     shouldThrow("crypto.subtle.digest({name: null}, [data])");
    50     shouldThrow("crypto.subtle.digest({name: undefined}, [data])");
    51     shouldThrow("crypto.subtle.digest({name: 'sha'}, [data])");
    52     shouldThrow("crypto.subtle.digest({name: 1}, [data])");
    53     shouldThrow("crypto.subtle.digest('', [data])");
    54     shouldThrow("crypto.subtle.digest(null, [data])");
    55     shouldThrow("crypto.subtle.digest(undefined, [data])");
    56     shouldThrow("crypto.subtle.digest(1, [data])");
    57     shouldThrow("crypto.subtle.digest({}, [data])");
     39    shouldThrow("crypto.subtle.digest({ toString:function() { return 'sha-1' } }, data)"); // Algorithm normalization doesn't attempt to call toString.
     40    shouldThrow("crypto.subtle.digest({name: ''}, data)");
     41    shouldThrow("crypto.subtle.digest({name: null}, data)");
     42    shouldThrow("crypto.subtle.digest({name: undefined}, data)");
     43    shouldThrow("crypto.subtle.digest({name: 'sha'}, data)");
     44    shouldThrow("crypto.subtle.digest({name: 1}, data)");
     45    shouldThrow("crypto.subtle.digest('', data)");
     46    shouldThrow("crypto.subtle.digest(null, data)");
     47    shouldThrow("crypto.subtle.digest(undefined, data)");
     48    shouldThrow("crypto.subtle.digest(1, data)");
     49    shouldThrow("crypto.subtle.digest({}, data)");
    5850}).then(finishJSTest);
    5951
  • trunk/LayoutTests/crypto/subtle/hmac-import-jwk.html

    r159327 r159379  
    3737
    3838    debug("\nUsing the key to sign message 'foo'...");
    39     return crypto.subtle.sign(key.algorithm, key, [asciiToUint8Array('foo')]);
     39    return crypto.subtle.sign(key.algorithm, key, asciiToUint8Array('foo'));
    4040}).then(function(result) {
    4141    signature = result;
     
    4343
    4444    debug("\nVerifying the signature...");
    45     return crypto.subtle.verify(key.algorithm, key, result, [asciiToUint8Array('foo')]);
     45    return crypto.subtle.verify(key.algorithm, key, result, asciiToUint8Array('foo'));
    4646}).then(function(result) {
    4747    verificationResult = result;
  • trunk/LayoutTests/crypto/subtle/hmac-sign-verify-empty-key.html

    r159327 r159379  
    2828
    2929    debug("Using the key to sign 'foo'...");
    30     return crypto.subtle.sign(key.algorithm, key, [asciiToUint8Array('foo')]);
     30    return crypto.subtle.sign(key.algorithm, key, asciiToUint8Array('foo'));
    3131}).then(function(result) {
    3232    signature = result;
     
    3434
    3535    debug("Verifying the signature...");
    36     return crypto.subtle.verify(key.algorithm, key, result, [asciiToUint8Array('foo')]);
     36    return crypto.subtle.verify(key.algorithm, key, result, asciiToUint8Array('foo'));
    3737}).then(function(result) {
    3838    verificationResult = result;
  • trunk/LayoutTests/crypto/subtle/hmac-sign-verify.html

    r159327 r159379  
    2828
    2929    debug("Using the key to sign 'foo'...");
    30     return crypto.subtle.sign(key.algorithm, key, [asciiToUint8Array('foo')]);
     30    return crypto.subtle.sign(key.algorithm, key, asciiToUint8Array('foo'));
    3131}).then(function(result) {
    3232    signature = result;
     
    3434
    3535    debug("Verifying the signature...");
    36     return crypto.subtle.verify(key.algorithm, key, result, [asciiToUint8Array('foo')]);
     36    return crypto.subtle.verify(key.algorithm, key, result, asciiToUint8Array('foo'));
    3737}).then(function(result) {
    3838    verificationResult = result;
  • trunk/LayoutTests/crypto/subtle/rsassa-pkcs1-v1_5-sign-verify.html

    r159327 r159379  
    4646    privateKey = result;
    4747    debug("\nSigning some text...");
    48     return crypto.subtle.sign({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, privateKey, [data]);
     48    return crypto.subtle.sign({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, privateKey, data);
    4949}).then(function(result) {
    5050    signature = result;
     
    5252
    5353    debug("\nVerifying the signature...");
    54     return crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, publicKey, signature, [data]);
     54    return crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, publicKey, signature, data);
    5555}).then(function(result) {
    5656    verificationResult = result;
    5757    shouldBe("verificationResult", "true");
    5858    debug("\nVerifying a bad signature...");
    59     return crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, publicKey, new Uint8Array(256), [data]);
     59    return crypto.subtle.verify({ name: "RSASSA-PKCS1-v1_5", hash: "SHA-256" }, publicKey, new Uint8Array(256), data);
    6060}).then(function(result) {
    6161    verificationResult = result;
  • trunk/LayoutTests/crypto/subtle/sha-1-expected.txt

    r159327 r159379  
    1010SHA1 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    1111PASS bytesToHexString(new Uint8Array(digest)) is '2c7e7c384f7829694282b1e3a6216def8082d055'
    12 SHA1 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]
    13 PASS bytesToHexString(new Uint8Array(digest)) is '2c7e7c384f7829694282b1e3a6216def8082d055'
    1412PASS crypto.subtle.generateKey('sha-1') threw exception Error: NotSupportedError: DOM Exception 9.
    1513PASS successfullyParsed is true
  • trunk/LayoutTests/crypto/subtle/sha-1.html

    r159327 r159379  
    1616Promise.fulfill(null).then(function() {
    1717    debug("SHA1 of []");
    18     return crypto.subtle.digest('sha-1', [new Uint8Array([])]);
     18    return crypto.subtle.digest('sha-1', new Uint8Array([]));
    1919}).then(function(result) {
    2020    digest = result;
     
    2222
    2323    debug("SHA1 of [0x0]")
    24     return crypto.subtle.digest({name: 'sha-1'}, [new Uint8Array([0])]);
     24    return crypto.subtle.digest({name: 'sha-1'}, new Uint8Array([0]));
    2525}).then(function(result) {
    2626    digest = result;
     
    2929    debug("SHA1 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
    3030    var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    31     return crypto.subtle.digest({name: 'sha-1'}, [data]);
     31    return crypto.subtle.digest({name: 'sha-1'}, data);
    3232}).then(function(result) {
    3333    digest = result;
    3434    shouldBe("bytesToHexString(new Uint8Array(digest))", "'2c7e7c384f7829694282b1e3a6216def8082d055'");
    3535
    36     debug("SHA1 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]");
    37     return crypto.subtle.digest({name: 'sha-1'}, [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array([5, 6, 7, 8, 9, 10])]);
    38 }).then(function(result) {
    39     digest = result;
    40     shouldBe("bytesToHexString(new Uint8Array(digest))", "'2c7e7c384f7829694282b1e3a6216def8082d055'");
    4136    // All SHA-1 can do is digest.
    4237    shouldThrow("crypto.subtle.generateKey('sha-1')");
  • trunk/LayoutTests/crypto/subtle/sha-224-expected.txt

    r159327 r159379  
    1010SHA224 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    1111PASS bytesToHexString(new Uint8Array(digest)) is '767d0cdc11079ba8dca276df5c4b85507de67dce47eda4cd9196d312'
    12 SHA224 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]
    13 PASS bytesToHexString(new Uint8Array(digest)) is '767d0cdc11079ba8dca276df5c4b85507de67dce47eda4cd9196d312'
    1412PASS successfullyParsed is true
    1513
  • trunk/LayoutTests/crypto/subtle/sha-224.html

    r159327 r159379  
    1616Promise.fulfill(null).then(function() {
    1717    debug("SHA224 of []");
    18     return crypto.subtle.digest('sha-224', [new Uint8Array([])]);
     18    return crypto.subtle.digest('sha-224', new Uint8Array([]));
    1919}).then(function(result) {
    2020    digest = result;
     
    2222
    2323    debug("SHA224 of [0x0]")
    24     return crypto.subtle.digest({name: 'sha-224'}, [new Uint8Array([0])]);
     24    return crypto.subtle.digest({name: 'sha-224'}, new Uint8Array([0]));
    2525}).then(function(result) {
    2626    digest = result;
     
    2929    debug("SHA224 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
    3030    var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    31     return crypto.subtle.digest({name: 'sha-224'}, [data]);
    32 }).then(function(result) {
    33     digest = result;
    34     shouldBe("bytesToHexString(new Uint8Array(digest))", "'767d0cdc11079ba8dca276df5c4b85507de67dce47eda4cd9196d312'");
    35 
    36     debug("SHA224 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]");
    37     return crypto.subtle.digest({name: 'sha-224'}, [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array([5, 6, 7, 8, 9, 10])]);
     31    return crypto.subtle.digest({name: 'sha-224'}, data);
    3832}).then(function(result) {
    3933    digest = result;
  • trunk/LayoutTests/crypto/subtle/sha-256-expected.txt

    r159327 r159379  
    1010SHA256 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    1111PASS bytesToHexString(new Uint8Array(digest)) is '78a6273103d17c39a0b6126e226cec70e33337f4bc6a38067401b54a33e78ead'
    12 SHA256 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]
    13 PASS bytesToHexString(new Uint8Array(digest)) is '78a6273103d17c39a0b6126e226cec70e33337f4bc6a38067401b54a33e78ead'
    1412PASS successfullyParsed is true
    1513
  • trunk/LayoutTests/crypto/subtle/sha-256.html

    r159327 r159379  
    1616Promise.fulfill(null).then(function() {
    1717    debug("SHA256 of []");
    18     return crypto.subtle.digest('sha-256', [new Uint8Array([])]);
     18    return crypto.subtle.digest('sha-256', new Uint8Array([]));
    1919}).then(function(result) {
    2020    digest = result;
     
    2222
    2323    debug("SHA256 of [0x0]")
    24     return crypto.subtle.digest({name: 'sha-256'}, [new Uint8Array([0])]);
     24    return crypto.subtle.digest({name: 'sha-256'}, new Uint8Array([0]));
    2525}).then(function(result) {
    2626    digest = result;
     
    2929    debug("SHA256 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
    3030    var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    31     return crypto.subtle.digest({name: 'sha-256'}, [data]);
    32 }).then(function(result) {
    33     digest = result;
    34     shouldBe("bytesToHexString(new Uint8Array(digest))", "'78a6273103d17c39a0b6126e226cec70e33337f4bc6a38067401b54a33e78ead'");
    35 
    36     debug("SHA256 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]");
    37     return crypto.subtle.digest({name: 'sha-256'}, [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array([5, 6, 7, 8, 9, 10])]);
     31    return crypto.subtle.digest({name: 'sha-256'}, data);
    3832}).then(function(result) {
    3933    digest = result;
  • trunk/LayoutTests/crypto/subtle/sha-384-expected.txt

    r159327 r159379  
    1010SHA384 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    1111PASS bytesToHexString(new Uint8Array(digest)) is '89bfcf569ae4af718510da78c67414109f5739bb5c40d51c9c8c50e2b2cee86f2f80c8b9d68f7c01201a0714572fe602'
    12 SHA384 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]
    13 PASS bytesToHexString(new Uint8Array(digest)) is '89bfcf569ae4af718510da78c67414109f5739bb5c40d51c9c8c50e2b2cee86f2f80c8b9d68f7c01201a0714572fe602'
    1412PASS successfullyParsed is true
    1513
  • trunk/LayoutTests/crypto/subtle/sha-384.html

    r159327 r159379  
    1616Promise.fulfill(null).then(function() {
    1717    debug("SHA384 of []");
    18     return crypto.subtle.digest('sha-384', [new Uint8Array([])]);
     18    return crypto.subtle.digest('sha-384', new Uint8Array([]));
    1919}).then(function(result) {
    2020    digest = result;
     
    2222
    2323    debug("SHA384 of [0x0]")
    24     return crypto.subtle.digest({name: 'sha-384'}, [new Uint8Array([0])]);
     24    return crypto.subtle.digest({name: 'sha-384'}, new Uint8Array([0]));
    2525}).then(function(result) {
    2626    digest = result;
     
    2929    debug("SHA384 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
    3030    var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    31     return crypto.subtle.digest({name: 'sha-384'}, [data]);
    32 }).then(function(result) {
    33     digest = result;
    34     shouldBe("bytesToHexString(new Uint8Array(digest))", "'89bfcf569ae4af718510da78c67414109f5739bb5c40d51c9c8c50e2b2cee86f2f80c8b9d68f7c01201a0714572fe602'");
    35 
    36     debug("SHA384 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]");
    37     return crypto.subtle.digest({name: 'sha-384'}, [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array([5, 6, 7, 8, 9, 10])]);
     31    return crypto.subtle.digest({name: 'sha-384'}, data);
    3832}).then(function(result) {
    3933    digest = result;
  • trunk/LayoutTests/crypto/subtle/sha-512-expected.txt

    r159327 r159379  
    1010SHA512 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
    1111PASS bytesToHexString(new Uint8Array(digest)) is '8ffaee0cccc162851faf051ae38667eefd423c0164c50055f8ade00afc3705e3cdeb9900004b0e426ca66ab63aa3b99b075273f44fd37c22a3555c6fd1f37ccb'
    12 SHA512 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]
    13 PASS bytesToHexString(new Uint8Array(digest)) is '8ffaee0cccc162851faf051ae38667eefd423c0164c50055f8ade00afc3705e3cdeb9900004b0e426ca66ab63aa3b99b075273f44fd37c22a3555c6fd1f37ccb'
    1412PASS successfullyParsed is true
    1513
  • trunk/LayoutTests/crypto/subtle/sha-512.html

    r159327 r159379  
    1616Promise.fulfill(null).then(function() {
    1717    debug("SHA512 of []");
    18     return crypto.subtle.digest('sha-512', [new Uint8Array([])]);
     18    return crypto.subtle.digest('sha-512', new Uint8Array([]));
    1919}).then(function(result) {
    2020    digest = result;
     
    2222
    2323    debug("SHA512 of [0x0]")
    24     return crypto.subtle.digest({name: 'sha-512'}, [new Uint8Array([0])]);
     24    return crypto.subtle.digest({name: 'sha-512'}, new Uint8Array([0]));
    2525}).then(function(result) {
    2626    digest = result;
     
    2929    debug("SHA512 of [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]");
    3030    var data = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
    31     return crypto.subtle.digest({name: 'sha-512'}, [data]);
    32 }).then(function(result) {
    33     digest = result;
    34     shouldBe("bytesToHexString(new Uint8Array(digest))", "'8ffaee0cccc162851faf051ae38667eefd423c0164c50055f8ade00afc3705e3cdeb9900004b0e426ca66ab63aa3b99b075273f44fd37c22a3555c6fd1f37ccb'");
    35 
    36     debug("SHA512 of [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array(5, 6, 7, 8, 9, 10])]");
    37     return crypto.subtle.digest({name: 'sha-512'}, [new Uint8Array([0, 1, 2, 3, 4]), new Uint8Array([5, 6, 7, 8, 9, 10])]);
     31    return crypto.subtle.digest({name: 'sha-512'}, data);
    3832}).then(function(result) {
    3933    digest = result;
  • trunk/Source/WebCore/ChangeLog

    r159378 r159379  
     12013-11-16  Alexey Proskuryakov  <ap@apple.com>
     2
     3        WebCrypto no longer uses sequences of ArrayBuffers
     4        https://bugs.webkit.org/show_bug.cgi?id=124451
     5
     6        Reviewed by Sam Weinig.
     7
     8        Covered by existing tests.
     9
     10        Changed all operations to take single CryptoOperationData objects.
     11
     12        * bindings/js/JSCryptoOperationData.cpp:
     13        * bindings/js/JSCryptoOperationData.h:
     14        * bindings/js/JSSubtleCryptoCustom.cpp:
     15        (WebCore::JSSubtleCrypto::encrypt):
     16        (WebCore::JSSubtleCrypto::decrypt):
     17        (WebCore::JSSubtleCrypto::sign):
     18        (WebCore::JSSubtleCrypto::verify):
     19        (WebCore::JSSubtleCrypto::digest):
     20        * crypto/CryptoAlgorithm.cpp:
     21        (WebCore::CryptoAlgorithm::encrypt):
     22        (WebCore::CryptoAlgorithm::decrypt):
     23        (WebCore::CryptoAlgorithm::sign):
     24        (WebCore::CryptoAlgorithm::verify):
     25        (WebCore::CryptoAlgorithm::digest):
     26        * crypto/CryptoAlgorithm.h:
     27        * crypto/CryptoAlgorithmRSASSA_PKCS1_v1_5Mac.cpp:
     28        (WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::sign):
     29        (WebCore::CryptoAlgorithmRSASSA_PKCS1_v1_5::verify):
     30        * crypto/algorithms/CryptoAlgorithmAES_CBC.h:
     31        * crypto/algorithms/CryptoAlgorithmHMAC.h:
     32        * crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.h:
     33        * crypto/algorithms/CryptoAlgorithmSHA1.cpp:
     34        (WebCore::CryptoAlgorithmSHA1::digest):
     35        * crypto/algorithms/CryptoAlgorithmSHA1.h:
     36        * crypto/algorithms/CryptoAlgorithmSHA224.cpp:
     37        (WebCore::CryptoAlgorithmSHA224::digest):
     38        * crypto/algorithms/CryptoAlgorithmSHA224.h:
     39        * crypto/algorithms/CryptoAlgorithmSHA256.cpp:
     40        (WebCore::CryptoAlgorithmSHA256::digest):
     41        * crypto/algorithms/CryptoAlgorithmSHA256.h:
     42        * crypto/algorithms/CryptoAlgorithmSHA384.cpp:
     43        (WebCore::CryptoAlgorithmSHA384::digest):
     44        * crypto/algorithms/CryptoAlgorithmSHA384.h:
     45        * crypto/algorithms/CryptoAlgorithmSHA512.cpp:
     46        (WebCore::CryptoAlgorithmSHA512::digest):
     47        * crypto/algorithms/CryptoAlgorithmSHA512.h:
     48        * crypto/mac/CryptoAlgorithmAES_CBCMac.cpp:
     49        (WebCore::transformAES_CBC):
     50        (WebCore::CryptoAlgorithmAES_CBC::encrypt):
     51        (WebCore::CryptoAlgorithmAES_CBC::decrypt):
     52        * crypto/mac/CryptoAlgorithmHMACMac.cpp:
     53        (WebCore::calculateSignature):
     54        (WebCore::CryptoAlgorithmHMAC::sign):
     55        (WebCore::CryptoAlgorithmHMAC::verify):
     56        * crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h:
     57
    1582013-11-16  Zoltan Horvath  <zoltan@webkit.org>
    259
  • trunk/Source/WebCore/bindings/js/JSCryptoOperationData.cpp

    r158485 r159379  
    3535namespace WebCore {
    3636
    37 bool sequenceOfCryptoOperationDataFromJSValue(ExecState* exec, JSValue value, Vector<CryptoOperationData>& result)
    38 {
    39     unsigned sequenceLength;
    40     JSObject* sequence = toJSSequence(exec, value, sequenceLength);
    41     if (!sequence) {
    42         ASSERT(exec->hadException());
    43         return false;
    44     }
    45 
    46     for (unsigned i = 0; i < sequenceLength; ++i) {
    47         JSValue item = sequence->get(exec, i);
    48         if (ArrayBuffer* buffer = toArrayBuffer(item))
    49             result.append(std::make_pair(static_cast<char*>(buffer->data()), buffer->byteLength()));
    50         else if (RefPtr<ArrayBufferView> bufferView = toArrayBufferView(item))
    51             result.append(std::make_pair(static_cast<char*>(bufferView->baseAddress()), bufferView->byteLength()));
    52         else {
    53             throwTypeError(exec, "Only ArrayBuffer and ArrayBufferView objects can be part of CryptoOperationData sequence");
    54             return false;
    55         }
    56     }
    57     return true;
    58 }
    59 
    6037bool cryptoOperationDataFromJSValue(ExecState* exec, JSValue value, CryptoOperationData& result)
    6138{
  • trunk/Source/WebCore/bindings/js/JSCryptoOperationData.h

    r158485 r159379  
    2727#define JSCryptoOperationData_h
    2828
    29 #include <wtf/Vector.h>
    30 
    3129#if ENABLE(SUBTLE_CRYPTO)
    3230
     
    4038typedef std::pair<const char*, size_t> CryptoOperationData;
    4139
    42 bool sequenceOfCryptoOperationDataFromJSValue(JSC::ExecState*, JSC::JSValue, Vector<CryptoOperationData>&);
    4340bool cryptoOperationDataFromJSValue(JSC::ExecState*, JSC::JSValue, CryptoOperationData&);
    4441
  • trunk/Source/WebCore/bindings/js/JSSubtleCryptoCustom.cpp

    r159377 r159379  
    156156    }
    157157
    158     Vector<CryptoOperationData> data;
    159     if (!sequenceOfCryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
     158    CryptoOperationData data;
     159    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
    160160        ASSERT(exec->hadException());
    161161        return jsUndefined();
     
    202202    }
    203203
    204     Vector<CryptoOperationData> data;
    205     if (!sequenceOfCryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
     204    CryptoOperationData data;
     205    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
    206206        ASSERT(exec->hadException());
    207207        return jsUndefined();
     
    248248    }
    249249
    250     Vector<CryptoOperationData> data;
    251     if (!sequenceOfCryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
     250    CryptoOperationData data;
     251    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(2), data)) {
    252252        ASSERT(exec->hadException());
    253253        return jsUndefined();
     
    300300    }
    301301
    302     Vector<CryptoOperationData> data;
    303     if (!sequenceOfCryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(3), data)) {
     302    CryptoOperationData data;
     303    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(3), data)) {
    304304        ASSERT(exec->hadException());
    305305        return jsUndefined();
     
    336336    }
    337337
    338     Vector<CryptoOperationData> data;
    339     if (!sequenceOfCryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) {
     338    CryptoOperationData data;
     339    if (!cryptoOperationDataFromJSValue(exec, exec->uncheckedArgument(1), data)) {
    340340        ASSERT(exec->hadException());
    341341        return jsUndefined();
  • trunk/Source/WebCore/crypto/CryptoAlgorithm.cpp

    r158943 r159379  
    4141}
    4242
    43 void CryptoAlgorithm::encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
     43void CryptoAlgorithm::encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
    4444{
    4545    ec = NOT_SUPPORTED_ERR;
    4646}
    4747
    48 void CryptoAlgorithm::decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
     48void CryptoAlgorithm::decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
    4949{
    5050    ec = NOT_SUPPORTED_ERR;
    5151}
    5252
    53 void CryptoAlgorithm::sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
     53void CryptoAlgorithm::sign(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
    5454{
    5555    ec = NOT_SUPPORTED_ERR;
    5656}
    5757
    58 void CryptoAlgorithm::verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
     58void CryptoAlgorithm::verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
    5959{
    6060    ec = NOT_SUPPORTED_ERR;
    6161}
    6262
    63 void CryptoAlgorithm::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
     63void CryptoAlgorithm::digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode& ec)
    6464{
    6565    ec = NOT_SUPPORTED_ERR;
  • trunk/Source/WebCore/crypto/CryptoAlgorithm.h

    r158943 r159379  
    2929#include "CryptoAlgorithmIdentifier.h"
    3030#include "CryptoKeyUsage.h"
    31 #include <wtf/Vector.h>
     31#include <wtf/Noncopyable.h>
    3232
    3333#if ENABLE(SUBTLE_CRYPTO)
     
    5252    virtual CryptoAlgorithmIdentifier identifier() const = 0;
    5353
    54     virtual void encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    55     virtual void decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    56     virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    57     virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    58     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
     54    virtual void encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
     55    virtual void decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
     56    virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
     57    virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
     58    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    5959    virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
    6060    virtual void deriveKey(const CryptoAlgorithmParameters&, const CryptoKey& baseKey, CryptoAlgorithm* derivedKeyType, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&);
  • trunk/Source/WebCore/crypto/CryptoAlgorithmRSASSA_PKCS1_v1_5Mac.cpp

    r159296 r159379  
    9090}
    9191
    92 void CryptoAlgorithmRSASSA_PKCS1_v1_5::sign(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     92void CryptoAlgorithmRSASSA_PKCS1_v1_5::sign(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    9393{
    9494    const CryptoAlgorithmRsaSsaParams& rsaSSAParameters = toCryptoAlgorithmRsaSsaParams(parameters);
     
    112112    }
    113113
    114     for (size_t i = 0; i != data.size(); ++i)
    115         digest->addBytes(data[i].first, data[i].second);
     114    digest->addBytes(data.first, data.second);
    116115
    117116    Vector<unsigned char> digestData = digest->computeHash();
     
    130129}
    131130
    132 void CryptoAlgorithmRSASSA_PKCS1_v1_5::verify(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& signature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     131void CryptoAlgorithmRSASSA_PKCS1_v1_5::verify(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& signature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    133132{
    134133    const CryptoAlgorithmRsaSsaParams& rsaSSAParameters = toCryptoAlgorithmRsaSsaParams(parameters);
     
    152151    }
    153152
    154     for (size_t i = 0; i != data.size(); ++i)
    155         digest->addBytes(data[i].first, data[i].second);
     153    digest->addBytes(data.first, data.second);
    156154
    157155    Vector<unsigned char> digestData = digest->computeHash();
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmAES_CBC.h

    r158943 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    45     virtual void decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void encrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     45    virtual void decrypt(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4646    virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4747    virtual void importKey(const CryptoAlgorithmParameters&, const CryptoKeyData&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmHMAC.h

    r158943 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    45     virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     45    virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4646    virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4747    virtual void importKey(const CryptoAlgorithmParameters&, const CryptoKeyData&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmRSASSA_PKCS1_v1_5.h

    r159180 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    45     virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void sign(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     45    virtual void verify(const CryptoAlgorithmParameters&, const CryptoKey&, const CryptoOperationData& signature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4646    virtual void generateKey(const CryptoAlgorithmParameters&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4747    virtual void importKey(const CryptoAlgorithmParameters&, const CryptoKeyData&, bool extractable, CryptoKeyUsage, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.cpp

    r159292 r159379  
    5454}
    5555
    56 void CryptoAlgorithmSHA1::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
     56void CryptoAlgorithmSHA1::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
    5757{
    5858    std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_1);
     
    6262    }
    6363
    64     for (size_t i = 0, size = data.size(); i < size; ++i)
    65         digest->addBytes(data[i].first, data[i].second);
     64    digest->addBytes(data.first, data.second);
    6665
    6766    promise->fulfill(digest->computeHash());
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA1.h

    r158387 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4545
    4646private:
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.cpp

    r159292 r159379  
    5454}
    5555
    56 void CryptoAlgorithmSHA224::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
     56void CryptoAlgorithmSHA224::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
    5757{
    5858    std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_224);
     
    6262    }
    6363
    64     for (size_t i = 0, size = data.size(); i < size; ++i)
    65         digest->addBytes(data[i].first, data[i].second);
     64    digest->addBytes(data.first, data.second);
    6665
    6766    promise->fulfill(digest->computeHash());
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA224.h

    r158494 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4545
    4646private:
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.cpp

    r159292 r159379  
    5454}
    5555
    56 void CryptoAlgorithmSHA256::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
     56void CryptoAlgorithmSHA256::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
    5757{
    5858    std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_256);
     
    6262    }
    6363
    64     for (size_t i = 0, size = data.size(); i < size; ++i)
    65         digest->addBytes(data[i].first, data[i].second);
     64    digest->addBytes(data.first, data.second);
    6665
    6766    promise->fulfill(digest->computeHash());
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA256.h

    r158494 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4545
    4646private:
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.cpp

    r159292 r159379  
    5454}
    5555
    56 void CryptoAlgorithmSHA384::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
     56void CryptoAlgorithmSHA384::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
    5757{
    5858    std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_384);
     
    6262    }
    6363
    64     for (size_t i = 0, size = data.size(); i < size; ++i)
    65         digest->addBytes(data[i].first, data[i].second);
     64    digest->addBytes(data.first, data.second);
    6665
    6766    promise->fulfill(digest->computeHash());
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA384.h

    r158494 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4545
    4646private:
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.cpp

    r159292 r159379  
    5454}
    5555
    56 void CryptoAlgorithmSHA512::digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
     56void CryptoAlgorithmSHA512::digest(const CryptoAlgorithmParameters&, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode&)
    5757{
    5858    std::unique_ptr<CryptoDigest> digest = CryptoDigest::create(CryptoAlgorithmIdentifier::SHA_512);
     
    6262    }
    6363
    64     for (size_t i = 0, size = data.size(); i < size; ++i)
    65         digest->addBytes(data[i].first, data[i].second);
     64    digest->addBytes(data.first, data.second);
    6665
    6766    promise->fulfill(digest->computeHash());
  • trunk/Source/WebCore/crypto/algorithms/CryptoAlgorithmSHA512.h

    r158494 r159379  
    4242    virtual CryptoAlgorithmIdentifier identifier() const OVERRIDE;
    4343
    44     virtual void digest(const CryptoAlgorithmParameters&, const Vector<CryptoOperationData>&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
     44    virtual void digest(const CryptoAlgorithmParameters&, const CryptoOperationData&, std::unique_ptr<PromiseWrapper>, ExceptionCode&) OVERRIDE;
    4545
    4646private:
  • trunk/Source/WebCore/crypto/mac/CryptoAlgorithmAES_CBCMac.cpp

    r159213 r159379  
    3737namespace WebCore {
    3838
    39 static void transformAES_CBC(CCOperation operation, const CryptoAlgorithmAesCbcParams& parameters, const CryptoKeyAES& key, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise)
     39static void transformAES_CBC(CCOperation operation, const CryptoAlgorithmAesCbcParams& parameters, const CryptoKeyAES& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise)
    4040{
    4141    static_assert(sizeof(parameters.iv) == kCCBlockSizeAES128, "Initialization vector size must be the same as algorithm block size");
     
    5959    }
    6060
    61     size_t inputSize = 0;
    62     for (size_t i = 0, size = data.size(); i < size; ++i)
    63         inputSize += data[i].second;
     61    Vector<unsigned char> result(CCCryptorGetOutputLength(cryptor, data.second, true));
    6462
    65     Vector<unsigned char> result(CCCryptorGetOutputLength(cryptor, inputSize, true));
     63    size_t bytesWritten;
     64    status = CCCryptorUpdate(cryptor, data.first, data.second, result.data(), result.size(), &bytesWritten);
     65    if (status) {
     66        promise->reject(nullptr);
     67        return;
     68    }
    6669
    67     unsigned char* p = result.data();
    68     size_t resultChunkSize;
    69     for (size_t i = 0, size = data.size(); i < size; ++i) {
    70         status = CCCryptorUpdate(cryptor, data[i].first, data[i].second, p, result.end() - p, &resultChunkSize);
    71         if (status) {
    72             promise->reject(nullptr);
    73             return;
    74         }
    75         p += resultChunkSize;
    76     }
    77     status = CCCryptorFinal(cryptor, p, result.end() - p, &resultChunkSize);
    78     p += resultChunkSize;
     70    unsigned char* p = result.data() + bytesWritten;
     71    status = CCCryptorFinal(cryptor, p, result.end() - p, &bytesWritten);
     72    p += bytesWritten;
    7973    if (status) {
    8074        promise->reject(nullptr);
     
    9084}
    9185
    92 void CryptoAlgorithmAES_CBC::encrypt(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     86void CryptoAlgorithmAES_CBC::encrypt(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    9387{
    9488    const CryptoAlgorithmAesCbcParams& aesCBCParameters = toCryptoAlgorithmAesCbcParams(parameters);
     
    10397}
    10498
    105 void CryptoAlgorithmAES_CBC::decrypt(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     99void CryptoAlgorithmAES_CBC::decrypt(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    106100{
    107101    const CryptoAlgorithmAesCbcParams& aesCBCParameters = toCryptoAlgorithmAesCbcParams(parameters);
  • trunk/Source/WebCore/crypto/mac/CryptoAlgorithmHMACMac.cpp

    r159299 r159379  
    6060}
    6161
    62 static Vector<unsigned char> calculateSignature(CCHmacAlgorithm algorithm, const Vector<char>& key, const Vector<CryptoOperationData>& data)
     62static Vector<unsigned char> calculateSignature(CCHmacAlgorithm algorithm, const Vector<char>& key, const CryptoOperationData& data)
    6363{
    6464    size_t digestLength;
     
    8383    }
    8484
    85     CCHmacContext context;
     85    Vector<unsigned char> result(digestLength);
    8686    const char* keyData = key.data() ? key.data() : ""; // <rdar://problem/15467425> HMAC crashes when key pointer is null.
    87     CCHmacInit(&context, algorithm, keyData, key.size());
    88     for (size_t i = 0, size = data.size(); i < size; ++i)
    89         CCHmacUpdate(&context, data[i].first, data[i].second);
    90 
    91     Vector<unsigned char> result(digestLength);
    92     CCHmacFinal(&context, result.data());
     87    CCHmac(algorithm, keyData, key.size(), data.first, data.second, result.data());
    9388    return result;
    9489}
    9590
    96 void CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     91void CryptoAlgorithmHMAC::sign(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    9792{
    9893    const CryptoAlgorithmHmacParams& hmacParameters = toCryptoAlgorithmHmacParams(parameters);
     
    115110}
    116111
    117 void CryptoAlgorithmHMAC::verify(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& expectedSignature, const Vector<CryptoOperationData>& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
     112void CryptoAlgorithmHMAC::verify(const CryptoAlgorithmParameters& parameters, const CryptoKey& key, const CryptoOperationData& expectedSignature, const CryptoOperationData& data, std::unique_ptr<PromiseWrapper> promise, ExceptionCode& ec)
    118113{
    119114    const CryptoAlgorithmHmacParams& hmacParameters = toCryptoAlgorithmHmacParams(parameters);
  • trunk/Source/WebCore/crypto/parameters/CryptoAlgorithmRsaKeyGenParams.h

    r159213 r159379  
    2828
    2929#include "CryptoAlgorithmParameters.h"
     30#include <wtf/Vector.h>
    3031
    3132#if ENABLE(SUBTLE_CRYPTO)
Note: See TracChangeset for help on using the changeset viewer.