services/crypto/tests/unit/test_crypto_crypt.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 Cu.import("resource://services-crypto/WeaveCrypto.js");
michael@0 2
michael@0 3 let cryptoSvc = new WeaveCrypto();
michael@0 4
michael@0 5 function run_test() {
michael@0 6
michael@0 7 if ("makeSECItem" in cryptoSvc) // Only for js-ctypes WeaveCrypto.
michael@0 8 test_makeSECItem();
michael@0 9
michael@0 10 if (this.gczeal) {
michael@0 11 _("Running crypto tests with gczeal(2).");
michael@0 12 gczeal(2);
michael@0 13 }
michael@0 14 test_bug_617650();
michael@0 15 test_encrypt_decrypt();
michael@0 16 test_SECItem_byteCompressInts();
michael@0 17 test_key_memoization();
michael@0 18 if (this.gczeal)
michael@0 19 gczeal(0);
michael@0 20 }
michael@0 21
michael@0 22 function test_key_memoization() {
michael@0 23 let oldImport = cryptoSvc.nss && cryptoSvc.nss.PK11_ImportSymKey;
michael@0 24 if (!oldImport) {
michael@0 25 _("Couldn't swizzle PK11_ImportSymKey; returning.");
michael@0 26 return;
michael@0 27 }
michael@0 28
michael@0 29 let iv = cryptoSvc.generateRandomIV();
michael@0 30 let key = cryptoSvc.generateRandomKey();
michael@0 31 let c = 0;
michael@0 32 cryptoSvc.nss.PK11_ImportSymKey = function(slot, type, origin, operation, key, wincx) {
michael@0 33 c++;
michael@0 34 return oldImport(slot, type, origin, operation, key, wincx);
michael@0 35 }
michael@0 36
michael@0 37 // Encryption should cause a single counter increment.
michael@0 38 do_check_eq(c, 0);
michael@0 39 let cipherText = cryptoSvc.encrypt("Hello, world.", key, iv);
michael@0 40 do_check_eq(c, 1);
michael@0 41 let cipherText = cryptoSvc.encrypt("Hello, world.", key, iv);
michael@0 42 do_check_eq(c, 1);
michael@0 43
michael@0 44 // ... as should decryption.
michael@0 45 cryptoSvc.decrypt(cipherText, key, iv);
michael@0 46 cryptoSvc.decrypt(cipherText, key, iv);
michael@0 47 cryptoSvc.decrypt(cipherText, key, iv);
michael@0 48 do_check_eq(c, 2);
michael@0 49
michael@0 50 // Un-swizzle.
michael@0 51 cryptoSvc.nss.PK11_ImportSymKey = oldImport;
michael@0 52 }
michael@0 53
michael@0 54 function multiple_decrypts(iterations) {
michael@0 55 let iv = cryptoSvc.generateRandomIV();
michael@0 56 let key = cryptoSvc.generateRandomKey();
michael@0 57 let cipherText = cryptoSvc.encrypt("Hello, world.", key, iv);
michael@0 58
michael@0 59 for (let i = 0; i < iterations; ++i) {
michael@0 60 let clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 61 do_check_eq(clearText + " " + i, "Hello, world. " + i);
michael@0 62 }
michael@0 63 _("Done with multiple_decrypts.");
michael@0 64 }
michael@0 65
michael@0 66 function test_bug_617650() {
michael@0 67 if (this.gczeal) {
michael@0 68 gczeal(2);
michael@0 69 // Few iterations, because gczeal(2) is expensive... and makes it fail much faster!
michael@0 70 _("gczeal set to 2; attempting 10 iterations of multiple_decrypts.");
michael@0 71 multiple_decrypts(10);
michael@0 72 gczeal(0);
michael@0 73 } else {
michael@0 74 // We can't use gczeal on non-debug builds, so try lots of reps instead.
michael@0 75 _("No gczeal (non-debug build?); attempting 10,000 iterations of multiple_decrypts.");
michael@0 76 multiple_decrypts(10000);
michael@0 77 }
michael@0 78 }
michael@0 79
michael@0 80 // Just verify that it gets populated with the correct bytes.
michael@0 81 function test_makeSECItem() {
michael@0 82 Components.utils.import("resource://gre/modules/ctypes.jsm");
michael@0 83
michael@0 84 let item1 = cryptoSvc.makeSECItem("abcdefghi", false);
michael@0 85 do_check_true(!item1.isNull());
michael@0 86 let intData = ctypes.cast(item1.contents.data, ctypes.uint8_t.array(8).ptr).contents;
michael@0 87 for (let i = 0; i < 8; ++i)
michael@0 88 do_check_eq(intData[i], "abcdefghi".charCodeAt(i));
michael@0 89 }
michael@0 90
michael@0 91 function test_SECItem_byteCompressInts() {
michael@0 92 Components.utils.import("resource://gre/modules/ctypes.jsm");
michael@0 93
michael@0 94 let item1 = cryptoSvc.makeSECItem("abcdefghi", false);
michael@0 95 do_check_true(!item1.isNull());
michael@0 96 let intData = ctypes.cast(item1.contents.data, ctypes.uint8_t.array(8).ptr).contents;
michael@0 97
michael@0 98 // Fill it too short.
michael@0 99 cryptoSvc.byteCompressInts("MMM", intData, 8);
michael@0 100 for (let i = 0; i < 3; ++i)
michael@0 101 do_check_eq(intData[i], [77, 77, 77][i]);
michael@0 102
michael@0 103 // Fill it too much. Doesn't buffer overrun.
michael@0 104 cryptoSvc.byteCompressInts("NNNNNNNNNNNNNNNN", intData, 8);
michael@0 105 for (let i = 0; i < 8; ++i)
michael@0 106 do_check_eq(intData[i], "NNNNNNNNNNNNNNNN".charCodeAt(i));
michael@0 107 }
michael@0 108
michael@0 109 function test_encrypt_decrypt() {
michael@0 110
michael@0 111 // First, do a normal run with expected usage... Generate a random key and
michael@0 112 // iv, encrypt and decrypt a string.
michael@0 113 var iv = cryptoSvc.generateRandomIV();
michael@0 114 do_check_eq(iv.length, 24);
michael@0 115
michael@0 116 var key = cryptoSvc.generateRandomKey();
michael@0 117 do_check_eq(key.length, 44);
michael@0 118
michael@0 119 var mySecret = "bacon is a vegetable";
michael@0 120 var cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 121 do_check_eq(cipherText.length, 44);
michael@0 122
michael@0 123 var clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 124 do_check_eq(clearText.length, 20);
michael@0 125
michael@0 126 // Did the text survive the encryption round-trip?
michael@0 127 do_check_eq(clearText, mySecret);
michael@0 128 do_check_neq(cipherText, mySecret); // just to be explicit
michael@0 129
michael@0 130
michael@0 131 // Do some more tests with a fixed key/iv, to check for reproducable results.
michael@0 132 key = "St1tFCor7vQEJNug/465dQ==";
michael@0 133 iv = "oLjkfrLIOnK2bDRvW4kXYA==";
michael@0 134
michael@0 135 _("Testing small IV.");
michael@0 136 mySecret = "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=";
michael@0 137 shortiv = "YWJj"; // "abc": Less than 16.
michael@0 138 let err;
michael@0 139 try {
michael@0 140 cryptoSvc.encrypt(mySecret, key, shortiv);
michael@0 141 } catch (ex) {
michael@0 142 err = ex;
michael@0 143 }
michael@0 144 do_check_true(!!err);
michael@0 145
michael@0 146 // Test small input sizes
michael@0 147 mySecret = "";
michael@0 148 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 149 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 150 do_check_eq(cipherText, "OGQjp6mK1a3fs9k9Ml4L3w==");
michael@0 151 do_check_eq(clearText, mySecret);
michael@0 152
michael@0 153 mySecret = "x";
michael@0 154 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 155 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 156 do_check_eq(cipherText, "96iMl4vhOxFUW/lVHHzVqg==");
michael@0 157 do_check_eq(clearText, mySecret);
michael@0 158
michael@0 159 mySecret = "xx";
michael@0 160 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 161 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 162 do_check_eq(cipherText, "olpPbETRYROCSqFWcH2SWg==");
michael@0 163 do_check_eq(clearText, mySecret);
michael@0 164
michael@0 165 mySecret = "xxx";
michael@0 166 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 167 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 168 do_check_eq(cipherText, "rRbpHGyVSZizLX/x43Wm+Q==");
michael@0 169 do_check_eq(clearText, mySecret);
michael@0 170
michael@0 171 mySecret = "xxxx";
michael@0 172 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 173 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 174 do_check_eq(cipherText, "HeC7miVGDcpxae9RmiIKAw==");
michael@0 175 do_check_eq(clearText, mySecret);
michael@0 176
michael@0 177 // Test non-ascii input
michael@0 178 // ("testuser1" using similar-looking glyphs)
michael@0 179 mySecret = String.fromCharCode(355, 277, 349, 357, 533, 537, 101, 345, 185);
michael@0 180 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 181 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 182 do_check_eq(cipherText, "Pj4ixByXoH3SU3JkOXaEKPgwRAWplAWFLQZkpJd5Kr4=");
michael@0 183 do_check_eq(clearText, mySecret);
michael@0 184
michael@0 185 // Tests input spanning a block boundary (AES block size is 16 bytes)
michael@0 186 mySecret = "123456789012345";
michael@0 187 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 188 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 189 do_check_eq(cipherText, "e6c5hwphe45/3VN/M0bMUA==");
michael@0 190 do_check_eq(clearText, mySecret);
michael@0 191
michael@0 192 mySecret = "1234567890123456";
michael@0 193 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 194 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 195 do_check_eq(cipherText, "V6aaOZw8pWlYkoIHNkhsP1JOIQF87E2vTUvBUQnyV04=");
michael@0 196 do_check_eq(clearText, mySecret);
michael@0 197
michael@0 198 mySecret = "12345678901234567";
michael@0 199 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 200 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 201 do_check_eq(cipherText, "V6aaOZw8pWlYkoIHNkhsP5GvxWJ9+GIAS6lXw+5fHTI=");
michael@0 202 do_check_eq(clearText, mySecret);
michael@0 203
michael@0 204
michael@0 205 key = "iz35tuIMq4/H+IYw2KTgow==";
michael@0 206 iv = "TJYrvva2KxvkM8hvOIvWp3xgjTXgq5Ss";
michael@0 207 mySecret = "i like pie";
michael@0 208
michael@0 209 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 210 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 211 do_check_eq(cipherText, "DLGx8BWqSCLGG7i/xwvvxg==");
michael@0 212 do_check_eq(clearText, mySecret);
michael@0 213
michael@0 214 key = "c5hG3YG+NC61FFy8NOHQak1ZhMEWO79bwiAfar2euzI=";
michael@0 215 iv = "gsgLRDaxWvIfKt75RjuvFWERt83FFsY2A0TW+0b2iVk=";
michael@0 216 mySecret = "i like pie";
michael@0 217
michael@0 218 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 219 clearText = cryptoSvc.decrypt(cipherText, key, iv);
michael@0 220 do_check_eq(cipherText, "o+ADtdMd8ubzNWurS6jt0Q==");
michael@0 221 do_check_eq(clearText, mySecret);
michael@0 222
michael@0 223 key = "St1tFCor7vQEJNug/465dQ==";
michael@0 224 iv = "oLjkfrLIOnK2bDRvW4kXYA==";
michael@0 225 mySecret = "does thunder read testcases?";
michael@0 226 cipherText = cryptoSvc.encrypt(mySecret, key, iv);
michael@0 227 do_check_eq(cipherText, "T6fik9Ros+DB2ablH9zZ8FWZ0xm/szSwJjIHZu7sjPs=");
michael@0 228
michael@0 229 var badkey = "badkeybadkeybadkeybadk==";
michael@0 230 var badiv = "badivbadivbadivbadivbad=";
michael@0 231 var badcipher = "crapinputcrapinputcrapinputcrapinputcrapinp=";
michael@0 232 var failure;
michael@0 233
michael@0 234 try {
michael@0 235 failure = false;
michael@0 236 clearText = cryptoSvc.decrypt(cipherText, badkey, iv);
michael@0 237 } catch (e) {
michael@0 238 failure = true;
michael@0 239 }
michael@0 240 do_check_true(failure);
michael@0 241
michael@0 242 try {
michael@0 243 failure = false;
michael@0 244 clearText = cryptoSvc.decrypt(cipherText, key, badiv);
michael@0 245 } catch (e) {
michael@0 246 failure = true;
michael@0 247 }
michael@0 248 do_check_true(failure);
michael@0 249
michael@0 250 try {
michael@0 251 failure = false;
michael@0 252 clearText = cryptoSvc.decrypt(cipherText, badkey, badiv);
michael@0 253 } catch (e) {
michael@0 254 failure = true;
michael@0 255 }
michael@0 256 do_check_true(failure);
michael@0 257
michael@0 258 try {
michael@0 259 failure = false;
michael@0 260 clearText = cryptoSvc.decrypt(badcipher, key, iv);
michael@0 261 } catch (e) {
michael@0 262 failure = true;
michael@0 263 }
michael@0 264 do_check_true(failure);
michael@0 265 }

mercurial