services/crypto/tests/unit/test_crypto_crypt.js

Wed, 31 Dec 2014 07:53:36 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:53:36 +0100
branch
TOR_BUG_3246
changeset 5
4ab42b5ab56c
permissions
-rw-r--r--

Correct small whitespace inconsistency, lost while renaming variables.

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

mercurial