blob: 0b215543b9fe5f382a5a607ae7545ccc78413e99 [file] [log] [blame]
Alex Gaynorf312a5c2013-08-10 15:23:38 -04001# Licensed under the Apache License, Version 2.0 (the "License");
2# you may not use this file except in compliance with the License.
3# You may obtain a copy of the License at
4#
5# http://www.apache.org/licenses/LICENSE-2.0
6#
7# Unless required by applicable law or agreed to in writing, software
8# distributed under the License is distributed on an "AS IS" BASIS,
9# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
10# implied.
11# See the License for the specific language governing permissions and
12# limitations under the License.
13
Donald Stufft9e1a48b2013-08-09 00:32:30 -040014import os.path
15
16
Alex Gaynord3ce7032013-11-11 14:46:20 -080017def load_nist_vectors(vector_data):
Alex Gaynor521c42d2013-11-11 14:25:59 -080018 section = None
19 count = None
20 data = {}
Donald Stufft9e1a48b2013-08-09 00:32:30 -040021
22 for line in vector_data:
23 line = line.strip()
24
25 # Blank lines are ignored
26 if not line:
27 continue
28
29 # Lines starting with # are comments
30 if line.startswith("#"):
31 continue
32
33 # Look for section headers
34 if line.startswith("[") and line.endswith("]"):
35 section = line[1:-1]
Alex Gaynor521c42d2013-11-11 14:25:59 -080036 continue
37
Donald Stufft9e1a48b2013-08-09 00:32:30 -040038 # Build our data using a simple Key = Value format
39 name, value = line.split(" = ")
40
41 # COUNT is a special token that indicates a new block of data
42 if name.upper() == "COUNT":
43 count = value
Alex Gaynord3ce7032013-11-11 14:46:20 -080044 data[section, count] = {}
Donald Stufft9e1a48b2013-08-09 00:32:30 -040045 # For all other tokens we simply want the name, value stored in
46 # the dictionary
47 else:
Alex Gaynord3ce7032013-11-11 14:46:20 -080048 data[section, count][name.lower()] = value.encode("ascii")
Donald Stufft9e1a48b2013-08-09 00:32:30 -040049
Alex Gaynor1fe70b12013-10-16 11:59:17 -070050 # We want to test only for a particular operation, we sort them for the
51 # benefit of the tests of this function.
Alex Gaynor521c42d2013-11-11 14:25:59 -080052 return [v for k, v in sorted(data.items(), key=lambda kv: kv[0])]
Donald Stufft9e1a48b2013-08-09 00:32:30 -040053
54
Alex Gaynord3ce7032013-11-11 14:46:20 -080055def load_nist_vectors_from_file(filename):
Donald Stufft9e1a48b2013-08-09 00:32:30 -040056 base = os.path.join(
Paul Kehrer2b758672013-10-30 09:01:38 -050057 os.path.dirname(__file__), "hazmat", "primitives", "vectors",
Donald Stufft9e1a48b2013-08-09 00:32:30 -040058 )
59 with open(os.path.join(base, filename), "r") as vector_file:
Alex Gaynord3ce7032013-11-11 14:46:20 -080060 return load_nist_vectors(vector_file)
Paul Kehrer1951bf62013-09-15 12:05:43 -050061
62
63def load_cryptrec_vectors_from_file(filename):
64 base = os.path.join(
Donald Stufftf04317a2013-10-27 16:44:30 -040065 os.path.dirname(__file__),
Paul Kehrer2b758672013-10-30 09:01:38 -050066 "hazmat", "primitives", "vectors",
Paul Kehrer1951bf62013-09-15 12:05:43 -050067 )
68 with open(os.path.join(base, filename), "r") as vector_file:
69 return load_cryptrec_vectors(vector_file)
70
71
72def load_cryptrec_vectors(vector_data):
Paul Kehrere5805982013-09-27 11:26:01 -050073 cryptrec_list = []
Paul Kehrer1951bf62013-09-15 12:05:43 -050074
75 for line in vector_data:
76 line = line.strip()
77
78 # Blank lines and comments are ignored
79 if not line or line.startswith("#"):
80 continue
81
82 if line.startswith("K"):
Paul Kehrere5805982013-09-27 11:26:01 -050083 key = line.split(" : ")[1].replace(" ", "").encode("ascii")
Paul Kehrer1951bf62013-09-15 12:05:43 -050084 elif line.startswith("P"):
Paul Kehrere5805982013-09-27 11:26:01 -050085 pt = line.split(" : ")[1].replace(" ", "").encode("ascii")
Paul Kehrer1951bf62013-09-15 12:05:43 -050086 elif line.startswith("C"):
Paul Kehrere5805982013-09-27 11:26:01 -050087 ct = line.split(" : ")[1].replace(" ", "").encode("ascii")
88 # after a C is found the K+P+C tuple is complete
89 # there are many P+C pairs for each K
Alex Gaynor1fe70b12013-10-16 11:59:17 -070090 cryptrec_list.append({
91 "key": key,
92 "plaintext": pt,
93 "ciphertext": ct
94 })
Donald Stufft3359d7e2013-10-19 19:33:06 -040095 else:
96 raise ValueError("Invalid line in file '{}'".format(line))
Paul Kehrer1951bf62013-09-15 12:05:43 -050097 return cryptrec_list
98
99
Paul Kehrer6b99a1b2013-09-24 16:50:21 -0500100def load_openssl_vectors_from_file(filename):
Paul Kehrer1951bf62013-09-15 12:05:43 -0500101 base = os.path.join(
Donald Stufftf04317a2013-10-27 16:44:30 -0400102 os.path.dirname(__file__),
Paul Kehrer2b758672013-10-30 09:01:38 -0500103 "hazmat", "primitives", "vectors",
Paul Kehrer1951bf62013-09-15 12:05:43 -0500104 )
105 with open(os.path.join(base, filename), "r") as vector_file:
Paul Kehrer6b99a1b2013-09-24 16:50:21 -0500106 return load_openssl_vectors(vector_file)
Paul Kehrer1951bf62013-09-15 12:05:43 -0500107
108
Paul Kehrer6b99a1b2013-09-24 16:50:21 -0500109def load_openssl_vectors(vector_data):
110 vectors = []
Paul Kehrer1951bf62013-09-15 12:05:43 -0500111
112 for line in vector_data:
113 line = line.strip()
114
115 # Blank lines and comments are ignored
116 if not line or line.startswith("#"):
117 continue
118
119 vector = line.split(":")
Alex Gaynor016eed12013-10-16 14:16:04 -0700120 vectors.append({
121 "key": vector[1].encode("ascii"),
122 "iv": vector[2].encode("ascii"),
123 "plaintext": vector[3].encode("ascii"),
124 "ciphertext": vector[4].encode("ascii"),
125 })
Paul Kehrer6b99a1b2013-09-24 16:50:21 -0500126 return vectors
Paul Kehrer69e06522013-10-18 17:28:39 -0500127
128
129def load_hash_vectors(vector_data):
130 vectors = []
Paul Kehrer1bb8b712013-10-27 17:00:14 -0500131 key = None
132 msg = None
133 md = None
Paul Kehrer69e06522013-10-18 17:28:39 -0500134
135 for line in vector_data:
136 line = line.strip()
137
Paul Kehrer87cd0db2013-10-18 18:01:26 -0500138 if not line or line.startswith("#") or line.startswith("["):
Paul Kehrer69e06522013-10-18 17:28:39 -0500139 continue
140
141 if line.startswith("Len"):
142 length = int(line.split(" = ")[1])
Paul Kehrer0317b042013-10-28 17:34:27 -0500143 elif line.startswith("Key"):
144 """
145 HMAC vectors contain a key attribute. Hash vectors do not.
146 """
147 key = line.split(" = ")[1].encode("ascii")
Paul Kehrer69e06522013-10-18 17:28:39 -0500148 elif line.startswith("Msg"):
149 """
150 In the NIST vectors they have chosen to represent an empty
151 string as hex 00, which is of course not actually an empty
152 string. So we parse the provided length and catch this edge case.
153 """
154 msg = line.split(" = ")[1].encode("ascii") if length > 0 else b""
155 elif line.startswith("MD"):
156 md = line.split(" = ")[1]
Paul Kehrer0317b042013-10-28 17:34:27 -0500157 # after MD is found the Msg+MD (+ potential key) tuple is complete
Paul Kehrer00dd5092013-10-23 09:41:49 -0500158 if key is not None:
Paul Kehrer0317b042013-10-28 17:34:27 -0500159 vectors.append((msg, md, key))
Paul Kehrer1bb8b712013-10-27 17:00:14 -0500160 key = None
161 msg = None
162 md = None
Paul Kehrer00dd5092013-10-23 09:41:49 -0500163 else:
Paul Kehrer0317b042013-10-28 17:34:27 -0500164 vectors.append((msg, md))
Paul Kehrer1bb8b712013-10-27 17:00:14 -0500165 msg = None
166 md = None
Paul Kehrer69e06522013-10-18 17:28:39 -0500167 else:
168 raise ValueError("Unknown line in hash vector")
169 return vectors
170
171
172def load_hash_vectors_from_file(filename):
173 base = os.path.join(
Donald Stufftf04317a2013-10-27 16:44:30 -0400174 os.path.dirname(__file__), "hazmat", "primitives", "vectors"
Paul Kehrer69e06522013-10-18 17:28:39 -0500175 )
176 with open(os.path.join(base, filename), "r") as vector_file:
177 return load_hash_vectors(vector_file)