add 1200 byte HKDF test vector and a generator/verifier for it (#4074)

* add 1200 byte HKDF test vector and a generator/verifier for it

* exit non-zero when failing

* ugh
diff --git a/docs/development/custom-vectors/hkdf.rst b/docs/development/custom-vectors/hkdf.rst
new file mode 100644
index 0000000..0e1a729
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf.rst
@@ -0,0 +1,28 @@
+HKDF vector creation
+====================
+
+This page documents the code that was used to generate a longer
+HKDF test vector (1200 bytes) than is available in RFC 5869. All
+the vectors were generated using OpenSSL and verified with Go.
+
+Creation
+--------
+
+The following Python script was run to generate the vector files.
+
+.. literalinclude:: /development/custom-vectors/hkdf/generate_hkdf.py
+
+Download link: :download:`generate_hkdf.py
+</development/custom-vectors/hkdf/generate_hkdf.py>`
+
+
+Verification
+------------
+
+The following Go code was used to verify the vectors.
+
+.. literalinclude:: /development/custom-vectors/hkdf/verify_hkdf.go
+    :language: go
+
+Download link: :download:`verify_hkdf.go
+</development/custom-vectors/hkdf/verify_hkdf.go>`
diff --git a/docs/development/custom-vectors/hkdf/generate_hkdf.py b/docs/development/custom-vectors/hkdf/generate_hkdf.py
new file mode 100644
index 0000000..767aedd
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/generate_hkdf.py
@@ -0,0 +1,39 @@
+# This file is dual licensed under the terms of the Apache License, Version
+# 2.0, and the BSD License. See the LICENSE file in the root of this repository
+# for complete details.
+
+from __future__ import absolute_import, division, print_function
+
+import binascii
+
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.kdf.hkdf import HKDF
+
+IKM = binascii.unhexlify(b"0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b")
+L = 1200
+OKM = HKDF(
+    algorithm=hashes.SHA256(), length=L, salt=None, info=None,
+    backend=default_backend()
+).derive(IKM)
+
+
+def _build_vectors():
+    output = []
+    output.append("COUNT = 0")
+    output.append("Hash = SHA-256")
+    output.append("IKM = " + binascii.hexlify(IKM).decode("ascii"))
+    output.append("salt = ")
+    output.append("info = ")
+    output.append("L = {}".format(L))
+    output.append("OKM = " + binascii.hexlify(OKM).decode("ascii"))
+    return "\n".join(output)
+
+
+def _write_file(data, filename):
+    with open(filename, 'w') as f:
+        f.write(data)
+
+
+if __name__ == '__main__':
+    _write_file(_build_vectors(), 'hkdf.txt')
diff --git a/docs/development/custom-vectors/hkdf/verify_hkdf.go b/docs/development/custom-vectors/hkdf/verify_hkdf.go
new file mode 100644
index 0000000..ddeb3d8
--- /dev/null
+++ b/docs/development/custom-vectors/hkdf/verify_hkdf.go
@@ -0,0 +1,69 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/sha256"
+	"encoding/hex"
+	"fmt"
+	"golang.org/x/crypto/hkdf"
+	"io"
+	"os"
+	"strconv"
+	"strings"
+)
+
+func unhexlify(s string) []byte {
+	bytes, err := hex.DecodeString(s)
+	if err != nil {
+		panic(err)
+	}
+	return bytes
+}
+
+func verifier(l uint64, ikm, okm []byte) bool {
+	hash := sha256.New
+	hkdf := hkdf.New(hash, ikm, nil, nil)
+	okmComputed := make([]byte, l)
+	io.ReadFull(hkdf, okmComputed)
+	return bytes.Equal(okmComputed, okm)
+}
+
+func validateVectors(filename string) bool {
+	vectors, err := os.Open(filename)
+	if err != nil {
+		panic(err)
+	}
+	defer vectors.Close()
+
+	var segments []string
+	var l uint64
+	var ikm, okm string
+
+	scanner := bufio.NewScanner(vectors)
+	for scanner.Scan() {
+		segments = strings.Split(scanner.Text(), " = ")
+
+		switch {
+		case strings.ToUpper(segments[0]) == "L":
+			l, err = strconv.ParseUint(segments[1], 10, 64)
+			if err != nil {
+				panic(err)
+			}
+		case strings.ToUpper(segments[0]) == "IKM":
+			ikm = segments[1]
+		case strings.ToUpper(segments[0]) == "OKM":
+			okm = segments[1]
+		}
+	}
+	return verifier(l, unhexlify(ikm), unhexlify(okm))
+}
+
+func main() {
+	if validateVectors("vectors/cryptography_vectors/KDF/hkdf-generated.txt") {
+		fmt.Println("HKDF OK.")
+	} else {
+		fmt.Println("HKDF failed.")
+		os.Exit(1)
+	}
+}
diff --git a/docs/development/test-vectors.rst b/docs/development/test-vectors.rst
index 6cee4fe..817bdaf 100644
--- a/docs/development/test-vectors.rst
+++ b/docs/development/test-vectors.rst
@@ -476,8 +476,8 @@
 When official vectors are unavailable ``cryptography`` may choose to build
 its own using existing vectors as source material.
 
-Custom Symmetric Vectors
-~~~~~~~~~~~~~~~~~~~~~~~~
+Created Vectors
+~~~~~~~~~~~~~~~
 
 .. toctree::
     :maxdepth: 1
@@ -486,6 +486,8 @@
     custom-vectors/cast5
     custom-vectors/idea
     custom-vectors/seed
+    custom-vectors/hkdf
+
 
 If official test vectors appear in the future the custom generated vectors
 should be discarded.