/services/crypto/tests/unit/test_crypto_crypt.js

http://github.com/zpao/v8monkey · JavaScript · 265 lines · 202 code · 47 blank · 16 comment · 11 complexity · a7031d132563ffd155e4e896eedd1038 MD5 · raw file

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