###############################################################################
+## testing helpers
+###############################################################################
+
+def _testing_set_AES_GCM_IV_CNT_MAX (vow, n):
+ """
+ Adapt upper file counter bound for testing IV logic. Completely unsafe.
+ """
+ assert vow == "I am fully aware that this will void my warranty."
+ global AES_GCM_IV_CNT_MAX
+ r = AES_GCM_IV_CNT_MAX
+ AES_GCM_IV_CNT_MAX = n
+ return r
+
+###############################################################################
## freestanding invocation
###############################################################################
for i in range (5): addobj (i)
+ def test_crypto_aes_gcm_enc_multiobj_cnt_wrap (self):
+ """
+ Test behavior when the file counter tops out.
+
+ Artificially lower the maximum possible file counter. Considering
+ invalid (0) and reserved (1, 2) values, the least possible file counter
+ for normal objects is 3. Starting from that, the header of the (max -
+ 3)rd object must have both a different IV fixed part and a counter.
+ """
+ minimum = 3
+ new_max = 8
+ old_max = crypto._testing_set_AES_GCM_IV_CNT_MAX \
+ ("I am fully aware that this will void my warranty.",
+ new_max)
+ cnksiz = 1 << 10
+ password = str (os.urandom (42))
+ encryptor = crypto.Encrypt (TEST_VERSION,
+ TEST_PARAMVERSION,
+ password=password,
+ nacl=TEST_STATIC_NACL,
+ strict_ivs=True)
+
+ last_iv = None
+ last_cnt = minimum
+
+ def addobj (i, wrap=False):
+ nonlocal last_iv
+ nonlocal last_cnt
+ pt = fill_mod (1 << 14, off=i)
+ header_dummy = encryptor.next ("%s_%d" % (TEST_DUMMY_FILENAME, i))
+
+ off = 0
+ ct = b""
+ while off < len (pt):
+ upto = min (off + cnksiz, len (pt))
+ cnk = encryptor.process (pt [off:upto])
+ ct += cnk
+ off += cnksiz
+ cnk, header, fixed = encryptor.done (header_dummy)
+ this_iv = crypto.hdr_read (header) ["iv"]
+ if last_iv is not None:
+ this_fixed, this_cnt = struct.unpack (crypto.FMT_I2N_IV, this_iv)
+ last_fixed, last_cnt = struct.unpack (crypto.FMT_I2N_IV, last_iv)
+ if wrap is False:
+ assert last_fixed == this_fixed
+ assert last_cnt == this_cnt - 1
+ else:
+ assert last_fixed != this_fixed
+ assert this_cnt == minimum
+ last_iv = this_iv
+ ct += cnk
+
+ assert len (pt) == len (ct)
+
+ for i in range (minimum, new_max + 1): addobj (i) # counter range: [3, 8]
+ addobj (i + 1, True) # counter wraps to 3
+
+ for j in range (i + 2, i + new_max - 1): addobj (j) # counter range: [4, 8]
+ addobj (j + 1, True) # counter wraps to 3 again
+
+ _ = crypto._testing_set_AES_GCM_IV_CNT_MAX \
+ ("I am fully aware that this will void my warranty.",
+ old_max)
+
+
def test_crypto_aes_gcm_dec_multicnk (self):
cnksiz = 1 << 10
orig_pt = fill_mod (1 << 14)