blake2s: add 128-bit digest support.

Although a 128-bit digest provides little collision resistance it can be
used as a MAC, as found in the WireGuard protocol.

Change-Id: I06ee528e5711035da8f1b254c223a6fda8890abf
Reviewed-on: https://go-review.googlesource.com/39370
Reviewed-by: Adam Langley <agl@golang.org>
diff --git a/blake2s/blake2s.go b/blake2s/blake2s.go
index 7e3fc4f..f2d8221 100644
--- a/blake2s/blake2s.go
+++ b/blake2s/blake2s.go
@@ -15,8 +15,12 @@
 const (
 	// The blocksize of BLAKE2s in bytes.
 	BlockSize = 64
+
 	// The hash size of BLAKE2s-256 in bytes.
 	Size = 32
+
+	// The hash size of BLAKE2s-128 in bytes.
+	Size128 = 16
 )
 
 var errKeySize = errors.New("blake2s: invalid key size")
@@ -37,6 +41,17 @@
 // key turns the hash into a MAC. The key must between zero and 32 bytes long.
 func New256(key []byte) (hash.Hash, error) { return newDigest(Size, key) }
 
+// New128 returns a new hash.Hash computing the BLAKE2s-128 checksum given a
+// non-empty key. Note that a 128-bit digest is too small to be secure as a
+// cryptographic hash and should only be used as a MAC, thus the key argument
+// is not optional.
+func New128(key []byte) (hash.Hash, error) {
+	if len(key) == 0 {
+		return nil, errors.New("blake2s: a key is required for a 128-bit hash")
+	}
+	return newDigest(Size128, key)
+}
+
 func newDigest(hashSize int, key []byte) (*digest, error) {
 	if len(key) > Size {
 		return nil, errKeySize
diff --git a/blake2s/blake2s_test.go b/blake2s/blake2s_test.go
index e6f2eeb..ff41670 100644
--- a/blake2s/blake2s_test.go
+++ b/blake2s/blake2s_test.go
@@ -18,21 +18,25 @@
 	if useSSE4 {
 		t.Log("SSE4 version")
 		testHashes(t)
+		testHashes128(t)
 		useSSE4 = false
 	}
 	if useSSSE3 {
 		t.Log("SSSE3 version")
 		testHashes(t)
+		testHashes128(t)
 		useSSSE3 = false
 	}
 	if useSSE2 {
 		t.Log("SSE2 version")
 		testHashes(t)
+		testHashes128(t)
 		useSSE2 = false
 	}
 	if useGeneric {
 		t.Log("generic version")
 		testHashes(t)
+		testHashes128(t)
 	}
 }
 
@@ -69,6 +73,39 @@
 	}
 }
 
+func testHashes128(t *testing.T) {
+	key, _ := hex.DecodeString("000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f")
+
+	input := make([]byte, 255)
+	for i := range input {
+		input[i] = byte(i)
+	}
+
+	for i, expectedHex := range hashes128 {
+		h, err := New128(key)
+		if err != nil {
+			t.Fatalf("#%d: error from New128: %v", i, err)
+		}
+
+		h.Write(input[:i])
+		sum := h.Sum(nil)
+
+		if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+			t.Fatalf("#%d (single write): got %s, wanted %s", i, gotHex, expectedHex)
+		}
+
+		h.Reset()
+		for j := 0; j < i; j++ {
+			h.Write(input[j : j+1])
+		}
+
+		sum = h.Sum(sum[:0])
+		if gotHex := fmt.Sprintf("%x", sum); gotHex != expectedHex {
+			t.Fatalf("#%d (byte-by-byte): got %s, wanted %s", i, gotHex, expectedHex)
+		}
+	}
+}
+
 // Benchmarks
 
 func benchmarkSum(b *testing.B, size int) {
@@ -355,3 +392,262 @@
 	"db444c15597b5f1a03d1f9edd16e4a9f43a667cc275175dfa2b704e3bb1a9b83",
 	"3fb735061abc519dfe979e54c1ee5bfad0a9d858b3315bad34bde999efd724dd",
 }
+
+var hashes128 = []string{
+	"9536f9b267655743dee97b8a670f9f53",
+	"13bacfb85b48a1223c595f8c1e7e82cb",
+	"d47a9b1645e2feae501cd5fe44ce6333",
+	"1e2a79436a7796a3e9826bfedf07659f",
+	"7640360ed3c4f3054dba79a21dda66b7",
+	"d1207ac2bf5ac84fc9ef016da5a46a86",
+	"3123987871e59305ece3125abfc0099a",
+	"cf9e072ad522f2cda2d825218086731c",
+	"95d22870392efe2846b12b6e8e84efbb",
+	"7d63c30e2d51333f245601b038c0b93b",
+	"ed608b98e13976bdf4bedc63fa35e443",
+	"ed704b5cd1abf8e0dd67a6ac667a3fa5",
+	"77dc70109827dc74c70fd26cba379ae5",
+	"d2bf34508b07825ee934f33958f4560e",
+	"a340baa7b8a93a6e658adef42e78eeb7",
+	"b85c5ceaecbe9a251eac76f6932ba395",
+	"246519722001f6e8e97a2183f5985e53",
+	"5bce5aa0b7c6cac2ecf6406183cd779a",
+	"13408f1647c02f6efd0047ad8344f695",
+	"a63970f196760aa36cb965ab62f0e0fa",
+	"bc26f48421dd99fd45e15e736d3e7dac",
+	"4c6f70f9e3237cde918afb52d26f1823",
+	"45ed610cfbc37db80c4bf0eef14ae8d6",
+	"87c4c150705ea5078209ec008200539c",
+	"54de21f5e0e6f2afe04daeb822b6931e",
+	"9732a04e505064e19de3d542e7e71631",
+	"d2bd27e95531d6957eef511c4ba64ad4",
+	"7a36c9f70dcc7c3063b547101a5f6c35",
+	"322007d1a44c4257bc7903b183305529",
+	"dbcc9a09f412290ca2e0d53dfd142ddb",
+	"df12ed43b8e53a56db20e0f83764002c",
+	"d114cc11e7d5b33a360c45f18d4c7c6e",
+	"c43b5e836af88620a8a71b1652cb8640",
+	"9491c653e8867ed73c1b4ac6b5a9bb4d",
+	"06d0e988df94ada6c6f9f36f588ab7c5",
+	"561efad2480e93262c8eeaa3677615c4",
+	"ba8ffc702e5adc93503045eca8702312",
+	"5782be6ccdc78c8425285e85de8ccdc6",
+	"aa1c4393e4c07b53ea6e2b5b1e970771",
+	"42a229dc50e52271c51e8666023ebc1e",
+	"53706110e919f84de7f8d6c7f0e7b831",
+	"fc5ac8ee39cc1dd1424391323e2901bd",
+	"bed27b62ff66cac2fbb68193c727106a",
+	"cd5e689b96d0b9ea7e08dac36f7b211e",
+	"0b4c7f604eba058d18e322c6e1baf173",
+	"eb838227fdfad09a27f0f8413120675d",
+	"3149cf9d19a7fd529e6154a8b4c3b3ad",
+	"ca1e20126df930fd5fb7afe4422191e5",
+	"b23398f910599f3c09b6549fa81bcb46",
+	"27fb17c11b34fa5d8b5afe5ee3321ead",
+	"0f665f5f04cf2d46b7fead1a1f328158",
+	"8f068be73b3681f99f3b282e3c02bba5",
+	"ba189bbd13808dcf4e002a4dd21660d5",
+	"2732dcd1b16668ae6ab6a61595d0d62a",
+	"d410ccdd059f0e02b472ec9ec54bdd3c",
+	"b2eaa07b055b3a03a399971327f7e8c2",
+	"2e8a225655e9f99b69c60dc8b4d8e566",
+	"4eb55416c853f2152e67f8a224133cec",
+	"49552403790d8de0505a8e317a443687",
+	"7f2747cd41f56942752e868212c7d5ac",
+	"02a28f10e193b430df7112d2d98cf759",
+	"d4213404a9f1cf759017747cf5958270",
+	"faa34884344f9c65e944882db8476d34",
+	"ece382a8bd5018f1de5da44b72cea75b",
+	"f1efa90d2547036841ecd3627fafbc36",
+	"811ff8686d23a435ecbd0bdafcd27b1b",
+	"b21beea9c7385f657a76558530438721",
+	"9cb969da4f1b4fc5b13bf78fe366f0c4",
+	"8850d16d7b614d3268ccfa009d33c7fc",
+	"aa98a2b6176ea86415b9aff3268c6f6d",
+	"ec3e1efa5ed195eff667e16b1af1e39e",
+	"e40787dca57411d2630db2de699beb08",
+	"554835890735babd06318de23d31e78a",
+	"493957feecddc302ee2bb2086b6ebfd3",
+	"f6069709ad5b0139163717e9ce1114ab",
+	"ba5ed386098da284484b211555505a01",
+	"9244c8dfad8cbb68c118fa51465b3ae4",
+	"51e309a5008eb1f5185e5cc007cfb36f",
+	"6ce9ff712121b4f6087955f4911eafd4",
+	"59b51d8dcda031218ccdd7c760828155",
+	"0012878767a3d4f1c8194458cf1f8832",
+	"82900708afd5b6582dc16f008c655edd",
+	"21302c7e39b5a4cdf1d6f86b4f00c9b4",
+	"e894c7431591eab8d1ce0fe2aa1f01df",
+	"b67e1c40ee9d988226d605621854d955",
+	"6237bdafa34137cbbec6be43ea9bd22c",
+	"4172a8e19b0dcb09b978bb9eff7af52b",
+	"5714abb55bd4448a5a6ad09fbd872fdf",
+	"7ce1700bef423e1f958a94a77a94d44a",
+	"3742ec50cded528527775833453e0b26",
+	"5d41b135724c7c9c689495324b162f18",
+	"85c523333c6442c202e9e6e0f1185f93",
+	"5c71f5222d40ff5d90e7570e71ab2d30",
+	"6e18912e83d012efb4c66250ced6f0d9",
+	"4add4448c2e35e0b138a0bac7b4b1775",
+	"c0376c6bc5e7b8b9d2108ec25d2aab53",
+	"f72261d5ed156765c977751c8a13fcc1",
+	"cff4156c48614b6ceed3dd6b9058f17e",
+	"36bfb513f76c15f514bcb593419835aa",
+	"166bf48c6bffaf8291e6fdf63854bef4",
+	"0b67d33f8b859c3157fbabd9e6e47ed0",
+	"e4da659ca76c88e73a9f9f10f3d51789",
+	"33c1ae2a86b3f51c0642e6ed5b5aa1f1",
+	"27469b56aca2334449c1cf4970dcd969",
+	"b7117b2e363378aa0901b0d6a9f6ddc0",
+	"a9578233b09e5cd5231943fdb12cd90d",
+	"486d7d75253598b716a068243c1c3e89",
+	"66f6b02d682b78ffdc85e9ec86852489",
+	"38a07b9a4b228fbcc305476e4d2e05d2",
+	"aedb61c7970e7d05bf9002dae3c6858c",
+	"c03ef441f7dd30fdb61ad2d4d8e4c7da",
+	"7f45cc1eea9a00cb6aeb2dd748361190",
+	"a59538b358459132e55160899e47bd65",
+	"137010fef72364411820c3fbed15c8df",
+	"d8362b93fc504500dbd33ac74e1b4d70",
+	"a7e49f12c8f47e3b29cf8c0889b0a9c8",
+	"072e94ffbfc684bd8ab2a1b9dade2fd5",
+	"5ab438584bd2229e452052e002631a5f",
+	"f233d14221097baef57d3ec205c9e086",
+	"3a95db000c4a8ff98dc5c89631a7f162",
+	"0544f18c2994ab4ddf1728f66041ff16",
+	"0bc02116c60a3cc331928d6c9d3ba37e",
+	"b189dca6cb5b813c74200834fba97f29",
+	"ac8aaab075b4a5bc24419da239212650",
+	"1e9f19323dc71c29ae99c479dc7e8df9",
+	"12d944c3fa7caa1b3d62adfc492274dd",
+	"b4c68f1fffe8f0030e9b18aad8c9dc96",
+	"25887fab1422700d7fa3edc0b20206e2",
+	"8c09f698d03eaf88abf69f8147865ef6",
+	"5c363ae42a5bec26fbc5e996428d9bd7",
+	"7fdfc2e854fbb3928150d5e3abcf56d6",
+	"f0c944023f714df115f9e4f25bcdb89b",
+	"6d19534b4c332741c8ddd79a9644de2d",
+	"32595eb23764fbfc2ee7822649f74a12",
+	"5a51391aab33c8d575019b6e76ae052a",
+	"98b861ce2c620f10f913af5d704a5afd",
+	"b7fe2fc8b77fb1ce434f8465c7ddf793",
+	"0e8406e0cf8e9cc840668ece2a0fc64e",
+	"b89922db99c58f6a128ccffe19b6ce60",
+	"e1be9af665f0932b77d7f5631a511db7",
+	"74b96f20f58de8dc9ff5e31f91828523",
+	"36a4cfef5a2a7d8548db6710e50b3009",
+	"007e95e8d3b91948a1dedb91f75de76b",
+	"a87a702ce08f5745edf765bfcd5fbe0d",
+	"847e69a388a749a9c507354d0dddfe09",
+	"07176eefbc107a78f058f3d424ca6a54",
+	"ad7e80682333b68296f6cb2b4a8e446d",
+	"53c4aba43896ae422e5de5b9edbd46bf",
+	"33bd6c20ca2a7ab916d6e98003c6c5f8",
+	"060d088ea94aa093f9981a79df1dfcc8",
+	"5617b214b9df08d4f11e58f5e76d9a56",
+	"ca3a60ee85bd971e1daf9f7db059d909",
+	"cd2b7754505d8c884eddf736f1ec613e",
+	"f496163b252f1439e7e113ba2ecabd8e",
+	"5719c7dcf9d9f756d6213354acb7d5cf",
+	"6f7dd40b245c54411e7a9be83ae5701c",
+	"c8994dd9fdeb077a45ea04a30358b637",
+	"4b1184f1e35458c1c747817d527a252f",
+	"fc7df674afeac7a3fd994183f4c67a74",
+	"4f68e05ce4dcc533acf9c7c01d95711e",
+	"d4ebc59e918400720035dfc88e0c486a",
+	"d3105dd6fa123e543b0b3a6e0eeaea9e",
+	"874196128ed443f5bdb2800ca048fcad",
+	"01645f134978dc8f9cf0abc93b53780e",
+	"5b8b64caa257873a0ffd47c981ef6c3f",
+	"4ee208fc50ba0a6e65c5b58cec44c923",
+	"53f409a52427b3b7ffabb057ca088428",
+	"c1d6cd616f5341a93d921e356e5887a9",
+	"e85c20fea67fa7320dc23379181183c8",
+	"7912b6409489df001b7372bc94aebde7",
+	"e559f761ec866a87f1f331767fafc60f",
+	"20a6f5a36bc37043d977ed7708465ef8",
+	"6a72f526965ab120826640dd784c6cc4",
+	"bf486d92ad68e87c613689dd370d001b",
+	"d339fd0eb35edf3abd6419c8d857acaf",
+	"9521cd7f32306d969ddabc4e6a617f52",
+	"a1cd9f3e81520842f3cf6cc301cb0021",
+	"18e879b6f154492d593edd3f4554e237",
+	"66e2329c1f5137589e051592587e521e",
+	"e899566dd6c3e82cbc83958e69feb590",
+	"8a4b41d7c47e4e80659d77b4e4bfc9ae",
+	"f1944f6fcfc17803405a1101998c57dd",
+	"f6bcec07567b4f72851b307139656b18",
+	"22e7bb256918fe9924dce9093e2d8a27",
+	"dd25b925815fe7b50b7079f5f65a3970",
+	"0457f10f299acf0c230dd4007612e58f",
+	"ecb420c19efd93814fae2964d69b54af",
+	"14eb47b06dff685d88751c6e32789db4",
+	"e8f072dbb50d1ab6654aa162604a892d",
+	"69cff9c62092332f03a166c7b0034469",
+	"d3619f98970b798ca32c6c14cd25af91",
+	"2246d423774ee9d51a551e89c0539d9e",
+	"75e5d1a1e374a04a699247dad827b6cf",
+	"6d087dd1d4cd15bf47db07c7a96b1db8",
+	"967e4c055ac51b4b2a3e506cebd5826f",
+	"7417aa79247e473401bfa92a25b62e2a",
+	"24f3f4956da34b5c533d9a551ccd7b16",
+	"0c40382de693a5304e2331eb951cc962",
+	"9436f949d51b347db5c8e6258dafaaac",
+	"d2084297fe84c4ba6e04e4fb73d734fe",
+	"42a6f8ff590af21b512e9e088257aa34",
+	"c484ad06b1cdb3a54f3f6464a7a2a6fd",
+	"1b8ac860f5ceb4365400a201ed2917aa",
+	"c43eadabbe7b7473f3f837fc52650f54",
+	"0e5d3205406126b1f838875deb150d6a",
+	"6bf4946f8ec8a9c417f50cd1e67565be",
+	"42f09a2522314799c95b3fc121a0e3e8",
+	"06b8f1487f691a3f7c3f74e133d55870",
+	"1a70a65fb4f314dcf6a31451a9d2704f",
+	"7d4acdd0823279fd28a1e48b49a04669",
+	"09545cc8822a5dfc93bbab708fd69174",
+	"efc063db625013a83c9a426d39a9bddb",
+	"213bbf89b3f5be0ffdb14854bbcb2588",
+	"b69624d89fe2774df9a6f43695d755d4",
+	"c0f9ff9ded82bd73c512e365a894774d",
+	"d1b68507ed89c17ead6f69012982db71",
+	"14cf16db04648978e35c44850855d1b0",
+	"9f254d4eccab74cd91d694df863650a8",
+	"8f8946e2967baa4a814d36ff01d20813",
+	"6b9dc4d24ecba166cb2915d7a6cba43b",
+	"eb35a80418a0042b850e294db7898d4d",
+	"f55f925d280c637d54055c9df088ef5f",
+	"f48427a04f67e33f3ba0a17f7c9704a7",
+	"4a9f5bfcc0321aea2eced896cee65894",
+	"8723a67d1a1df90f1cef96e6fe81e702",
+	"c166c343ee25998f80bad4067960d3fd",
+	"dab67288d16702e676a040fd42344d73",
+	"c8e9e0d80841eb2c116dd14c180e006c",
+	"92294f546bacf0dea9042c93ecba8b34",
+	"013705b1502b37369ad22fe8237d444e",
+	"9b97f8837d5f2ebab0768fc9a6446b93",
+	"7e7e5236b05ec35f89edf8bf655498e7",
+	"7be8f2362c174c776fb9432fe93bf259",
+	"2422e80420276d2df5702c6470879b01",
+	"df645795db778bcce23bbe819a76ba48",
+	"3f97a4ac87dfc58761cda1782d749074",
+	"50e3f45df21ebfa1b706b9c0a1c245a8",
+	"7879541c7ff612c7ddf17cb8f7260183",
+	"67f6542b903b7ba1945eba1a85ee6b1c",
+	"b34b73d36ab6234b8d3f5494d251138e",
+	"0aea139641fdba59ab1103479a96e05f",
+	"02776815a87b8ba878453666d42afe3c",
+	"5929ab0a90459ebac5a16e2fb37c847e",
+	"c244def5b20ce0468f2b5012d04ac7fd",
+	"12116add6fefce36ed8a0aeccce9b6d3",
+	"3cd743841e9d8b878f34d91b793b4fad",
+	"45e87510cf5705262185f46905fae35f",
+	"276047016b0bfb501b2d4fc748165793",
+	"ddd245df5a799417d350bd7f4e0b0b7e",
+	"d34d917a54a2983f3fdbc4b14caae382",
+	"7730fbc09d0c1fb1939a8fc436f6b995",
+	"eb4899ef257a1711cc9270a19702e5b5",
+	"8a30932014bce35bba620895d374df7a",
+	"1924aabf9c50aa00bee5e1f95b5d9e12",
+	"1758d6f8b982aec9fbe50f20e3082b46",
+	"cd075928ab7e6883e697fe7fd3ac43ee",
+}