/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/* This file provides a spec of the Poly1305 one-time authenticator.
 * See <https://tools.ietf.org/html/rfc7539> for details. */

module poly1305 where

P : [136]
P = 2^^130 - 5

Poly1305 : {n} (fin n) => [n][8] -> [16][8] -> [16][8] -> [16][8]
Poly1305 msg r s = reverse (groupBy (drop ((rounds ! 0) + s')))
  where
    rounds = [zero] # [ Poly1305_block acc r' b | b <- blocks | acc <- rounds ]
    r' = zero # (Poly1305_clamp (join (reverse r)))
    s' = zero # (join (reverse s))
    blocks = Poly1305_split msg

private
  // 0x0f - for r[3], r[7], r[11], r[15]
  // 0xfc - for r[4], r[8], r[12]
  Poly1305_clamp r = r && 0x0ffffffc0ffffffc0ffffffc0fffffff

  // Poly1305_block : ((acc + msg) * r) % P
  Poly1305_block : [136] -> [136] -> [136] -> [136]
  Poly1305_block acc r msg = drop (prod % (zero # P))
    where
      acc' : [137]
      // Add the current block to the accumulator.
      acc' = (zero # acc) + (zero # msg)
      prod : [273]
      // Multiply the new accumulator value by r.
      prod = ((zero : [137]) # r) * ((zero : [136]) # acc')

  Poly1305_split : {n, nb, nf} (fin n, nf == n / 16, nb == (n + 15) / 16) => [n][8] -> [nb][136]
  Poly1305_split msg = take ((h1 : [nf][136]) # h2)
    where
      // Split all full 16-byte blocks and append 0x01, then convert to LE.
      h1 = [ join (reverse (b # [0x01])) | b <- groupBy`{16} (take msg)]
      // Pad the remaining bytes (if any) and convert to LE.
      h2 = [join (reverse ((drop`{nf * 16} msg) # [0x01] # zero))]

/* -------------------------------------------------------------------------- */
/* -- Tests ----------------------------------------------------------------- */

private
  // https://tools.ietf.org/html/rfc7539#section-2.5.2
  rval1 = [0x85, 0xd6, 0xbe, 0x78, 0x57, 0x55, 0x6d, 0x33,
           0x7f, 0x44, 0x52, 0xfe, 0x42, 0xd5, 0x06, 0xa8]
  sval1 = [0x01, 0x03, 0x80, 0x8a, 0xfb, 0x0d, 0xb2, 0xfd,
           0x4a, 0xbf, 0xf6, 0xaf, 0x41, 0x49, 0xf5, 0x1b]
  text1 = [0x43, 0x72, 0x79, 0x70, 0x74, 0x6f, 0x67, 0x72,
           0x61, 0x70, 0x68, 0x69, 0x63, 0x20, 0x46, 0x6f,
           0x72, 0x75, 0x6d, 0x20, 0x52, 0x65, 0x73, 0x65,
           0x61, 0x72, 0x63, 0x68, 0x20, 0x47, 0x72, 0x6f,
           0x75, 0x70]

  rfctest01 = Poly1305 text1 rval1 sval1
      == [0xa8, 0x06, 0x1d, 0xc1, 0x30, 0x51, 0x36, 0xc6,
          0xc2, 0x2b, 0x8b, 0xaf, 0x0c, 0x01, 0x27, 0xa9]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #1
  rval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text2 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  rfctest02 = Poly1305 text2 rval2 sval2
      == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #2
  rval3 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval3 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
           0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]
  text3 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
           0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
           0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
           0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
           0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
           0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
           0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
           0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
           0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
           0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
           0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
           0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
           0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
           0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
           0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
           0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
           0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
           0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
           0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
           0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
           0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
           0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
           0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
           0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
           0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
           0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
           0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
           0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
           0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
           0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
           0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
           0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
           0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
           0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
           0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
           0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
           0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
           0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
           0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
           0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
           0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
           0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
           0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
           0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
           0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f]

  rfctest03 = Poly1305 text3 rval3 sval3
      == [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
          0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #3
  rval4 = [0x36, 0xe5, 0xf6, 0xb5, 0xc5, 0xe0, 0x60, 0x70,
           0xf0, 0xef, 0xca, 0x96, 0x22, 0x7a, 0x86, 0x3e]
  sval4 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text4 = [0x41, 0x6e, 0x79, 0x20, 0x73, 0x75, 0x62, 0x6d,
           0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x20, 0x74,
           0x6f, 0x20, 0x74, 0x68, 0x65, 0x20, 0x49, 0x45,
           0x54, 0x46, 0x20, 0x69, 0x6e, 0x74, 0x65, 0x6e,
           0x64, 0x65, 0x64, 0x20, 0x62, 0x79, 0x20, 0x74,
           0x68, 0x65, 0x20, 0x43, 0x6f, 0x6e, 0x74, 0x72,
           0x69, 0x62, 0x75, 0x74, 0x6f, 0x72, 0x20, 0x66,
           0x6f, 0x72, 0x20, 0x70, 0x75, 0x62, 0x6c, 0x69,
           0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x61,
           0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x6f, 0x72,
           0x20, 0x70, 0x61, 0x72, 0x74, 0x20, 0x6f, 0x66,
           0x20, 0x61, 0x6e, 0x20, 0x49, 0x45, 0x54, 0x46,
           0x20, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
           0x74, 0x2d, 0x44, 0x72, 0x61, 0x66, 0x74, 0x20,
           0x6f, 0x72, 0x20, 0x52, 0x46, 0x43, 0x20, 0x61,
           0x6e, 0x64, 0x20, 0x61, 0x6e, 0x79, 0x20, 0x73,
           0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e, 0x74,
           0x20, 0x6d, 0x61, 0x64, 0x65, 0x20, 0x77, 0x69,
           0x74, 0x68, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65,
           0x20, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x78, 0x74,
           0x20, 0x6f, 0x66, 0x20, 0x61, 0x6e, 0x20, 0x49,
           0x45, 0x54, 0x46, 0x20, 0x61, 0x63, 0x74, 0x69,
           0x76, 0x69, 0x74, 0x79, 0x20, 0x69, 0x73, 0x20,
           0x63, 0x6f, 0x6e, 0x73, 0x69, 0x64, 0x65, 0x72,
           0x65, 0x64, 0x20, 0x61, 0x6e, 0x20, 0x22, 0x49,
           0x45, 0x54, 0x46, 0x20, 0x43, 0x6f, 0x6e, 0x74,
           0x72, 0x69, 0x62, 0x75, 0x74, 0x69, 0x6f, 0x6e,
           0x22, 0x2e, 0x20, 0x53, 0x75, 0x63, 0x68, 0x20,
           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
           0x74, 0x73, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75,
           0x64, 0x65, 0x20, 0x6f, 0x72, 0x61, 0x6c, 0x20,
           0x73, 0x74, 0x61, 0x74, 0x65, 0x6d, 0x65, 0x6e,
           0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x49, 0x45,
           0x54, 0x46, 0x20, 0x73, 0x65, 0x73, 0x73, 0x69,
           0x6f, 0x6e, 0x73, 0x2c, 0x20, 0x61, 0x73, 0x20,
           0x77, 0x65, 0x6c, 0x6c, 0x20, 0x61, 0x73, 0x20,
           0x77, 0x72, 0x69, 0x74, 0x74, 0x65, 0x6e, 0x20,
           0x61, 0x6e, 0x64, 0x20, 0x65, 0x6c, 0x65, 0x63,
           0x74, 0x72, 0x6f, 0x6e, 0x69, 0x63, 0x20, 0x63,
           0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61,
           0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x6d, 0x61,
           0x64, 0x65, 0x20, 0x61, 0x74, 0x20, 0x61, 0x6e,
           0x79, 0x20, 0x74, 0x69, 0x6d, 0x65, 0x20, 0x6f,
           0x72, 0x20, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x2c,
           0x20, 0x77, 0x68, 0x69, 0x63, 0x68, 0x20, 0x61,
           0x72, 0x65, 0x20, 0x61, 0x64, 0x64, 0x72, 0x65,
           0x73, 0x73, 0x65, 0x64, 0x20, 0x74, 0x6f]

  rfctest04 = Poly1305 text4 rval4 sval4
      == [0xf3, 0x47, 0x7e, 0x7c, 0xd9, 0x54, 0x17, 0xaf,
          0x89, 0xa6, 0xb8, 0x79, 0x4c, 0x31, 0x0c, 0xf0]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #4
  rval5 = [0x1c, 0x92, 0x40, 0xa5, 0xeb, 0x55, 0xd3, 0x8a,
           0xf3, 0x33, 0x88, 0x86, 0x04, 0xf6, 0xb5, 0xf0]
  sval5 = [0x47, 0x39, 0x17, 0xc1, 0x40, 0x2b, 0x80, 0x09,
           0x9d, 0xca, 0x5c, 0xbc, 0x20, 0x70, 0x75, 0xc0]
  text5 = [0x27, 0x54, 0x77, 0x61, 0x73, 0x20, 0x62, 0x72,
           0x69, 0x6c, 0x6c, 0x69, 0x67, 0x2c, 0x20, 0x61,
           0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
           0x6c, 0x69, 0x74, 0x68, 0x79, 0x20, 0x74, 0x6f,
           0x76, 0x65, 0x73, 0x0a, 0x44, 0x69, 0x64, 0x20,
           0x67, 0x79, 0x72, 0x65, 0x20, 0x61, 0x6e, 0x64,
           0x20, 0x67, 0x69, 0x6d, 0x62, 0x6c, 0x65, 0x20,
           0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x77,
           0x61, 0x62, 0x65, 0x3a, 0x0a, 0x41, 0x6c, 0x6c,
           0x20, 0x6d, 0x69, 0x6d, 0x73, 0x79, 0x20, 0x77,
           0x65, 0x72, 0x65, 0x20, 0x74, 0x68, 0x65, 0x20,
           0x62, 0x6f, 0x72, 0x6f, 0x67, 0x6f, 0x76, 0x65,
           0x73, 0x2c, 0x0a, 0x41, 0x6e, 0x64, 0x20, 0x74,
           0x68, 0x65, 0x20, 0x6d, 0x6f, 0x6d, 0x65, 0x20,
           0x72, 0x61, 0x74, 0x68, 0x73, 0x20, 0x6f, 0x75,
           0x74, 0x67, 0x72, 0x61, 0x62, 0x65, 0x2e]

  rfctest05 = Poly1305 text5 rval5 sval5
      == [0x45, 0x41, 0x66, 0x9a, 0x7e, 0xaa, 0xee, 0x61,
          0xe7, 0x08, 0xdc, 0x7c, 0xbc, 0xc5, 0xeb, 0x62]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #5
  rval6 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval6 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text6 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

  rfctest06 = Poly1305 text6 rval6 sval6
      == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #6
  rval7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval7 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]
  text7 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  rfctest07 = Poly1305 text7 rval7 sval7
      == [0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #7
  rval8 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval8 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text8 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  rfctest08 = Poly1305 text8 rval8 sval8
      == [0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #8
  rval9 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval9 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text9 = [0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
           0xfb, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
           0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
           0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
           0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01]

  rfctest09 = Poly1305 text9 rval9 sval9
      == [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #9
  rval10 = [0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval10 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text10 = [0xfd, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
            0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

  rfctest10 = Poly1305 text10 rval10 sval10
      == [0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
          0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #10
  rval11 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval11 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text11 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  rfctest11 = Poly1305 text11 rval11 sval11
      == [0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  // https://tools.ietf.org/html/rfc7539#appendix-A.3
  // Test Vector #11
  rval12 = [0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  sval12 = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]
  text12 = [0xe3, 0x35, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0xb9,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x33, 0x94, 0xd7, 0x50, 0x5e, 0x43, 0x79, 0xcd,
            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

  rfctest12 = Poly1305 text12 rval12 sval12
      == [0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
          0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]

property allTestsPass =
  ([ // Full RFC test vectors
     rfctest01, rfctest02, rfctest03, rfctest04,
     rfctest05, rfctest06, rfctest07, rfctest08,
     rfctest09, rfctest10, rfctest11, rfctest12
   ] : [_]Bit) == ~zero // All test bits should equal one