• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2#
3# Copyright (C) 2017 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""Outputs CSV data for NIST test cases.
18
19Reads in a selection of test cases in NIST response file format on standard
20input and outputs a CSV representation of them to standard output, with the
21NIST-recommended statement in a header at the top, prefixed by #
22characters.  The data is in one of the following formats:
23
24key,iv,plaintext,ciphertext
25key,iv,plaintext,ciphertext,tag,aad"""
26
27import argparse
28import binascii
29import sys
30
31
32def dequote(value):
33    if value[0] == '"' and value[-1] == '"':
34        value = binascii.hexlify(value[1:-1])
35    return value
36
37
38def format_records(record):
39    # There are a number of different input formats, depending on whether the
40    # particular operation includes an IV, single or multiple cipher operations,
41    # etc.  Just check for each possibility.
42    if 'key' in record and 'iv' in record and 'plaintext' in record and 'ciphertext' in record:
43        # A normal operation with an IV
44        return ["{key},{iv},{plaintext},{ciphertext}".format(**record)]
45    elif 'key' in record and 'nonce' in record and 'plaintext' in record and 'ciphertext' in record:
46        # A normal operation with nonce instead of IV
47        return ["{key},{nonce},{plaintext},{ciphertext}".format(**record)]
48    elif 'key' in record and 'plaintext' in record and 'ciphertext' in record:
49        # A normal operation without IV
50        return ["{key},,{plaintext},{ciphertext}".format(**record)]
51    elif 'keys' in record and 'iv' in record and 'plaintext' in record and 'ciphertext' in record:
52        # A single triple-DES operation where all keys are the same
53        return ["{keys}{keys}{keys},{iv},{plaintext},{ciphertext}".format(**record)]
54    elif 'keys' in record and 'plaintext' in record and 'ciphertext' in record:
55        # A single triple-DES operation where all keys are the same without IV
56        return ["{keys}{keys}{keys},,{plaintext},{ciphertext}".format(**record)]
57    elif ('key1' in record and 'key2' in record and 'key3' in record and 'iv' in record
58          and 'plaintext' in record and 'ciphertext' in record):
59        # A single triple-DES operation with different keys for each step
60        return ["{key1}{key2}{key3},{iv},{plaintext},{ciphertext}".format(**record)]
61    elif ('key' in record and 'iv' in record and 'pt' in record and 'aad' in record
62          and 'ct' in record and 'tag' in record):
63        # An AEAD operation
64        return ["{key},{iv},{pt},{ct},{tag},{aad}".format(**record)]
65    elif ('key' in record and 'nonce' in record and 'in' in record and 'ad' in record
66          and 'ct' in record and 'tag' in record):
67        # A BoringSSL AEAD operation
68        return ["{key},{nonce},{in},{ct},{tag},{ad}".format(**record)]
69    return []
70
71
72def main():
73    parser = argparse.ArgumentParser()
74    parser.add_argument("--noheader", action='store_true')
75    args = parser.parse_args()
76    if not args.noheader:
77        print """# This data was developed by employees of the National Institute
78# of Standards and Technology (NIST), an agency of the Federal
79# Government. Pursuant to title 17 United States Code Section 105, works
80# of NIST employees are not subject to copyright protection in the United
81# States and are considered to be in the public domain.
82#
83# The data is provided by NIST as a public service and is expressly
84# provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
85# OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
86# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
87# AND DATA ACCURACY. NIST does not warrant or make any representations
88# regarding the use of the data or the results thereof, including but
89# not limited to the correctness, accuracy, reliability or usefulness
90# of the data. NIST SHALL NOT BE LIABLE AND YOU HEREBY RELEASE NIST FROM
91# LIABILITY FOR ANY INDIRECT, CONSEQUENTIAL, SPECIAL, OR INCIDENTAL DAMAGES
92# (INCLUDING DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION,
93# LOSS OF BUSINESS INFORMATION, AND THE LIKE), WHETHER ARISING IN TORT,
94# CONTRACT, OR OTHERWISE, ARISING FROM OR RELATING TO THE DATA (OR THE USE
95# OF OR INABILITY TO USE THIS DATA), EVEN IF NIST HAS BEEN ADVISED OF THE
96# POSSIBILITY OF SUCH DAMAGES.
97#
98# To the extent that NIST may hold copyright in countries other than the
99# United States, you are hereby granted the non-exclusive irrevocable
100# and unconditional right to print, publish, prepare derivative works and
101# distribute the NIST data, in any medium, or authorize others to do so
102# on your behalf, on a royalty-free basis throughout the world.
103#
104# You may improve, modify, and create derivative works of the data or any
105# portion of the data, and you may copy and distribute such modifications
106# or works. Modified works should carry a notice stating that you changed
107# the data and should note the date and nature of any such change. Please
108# explicitly acknowledge the National Institute of Standards and Technology
109# as the source of the data: Data citation recommendations are provided
110# below.
111#
112# Permission to use this data is contingent upon your acceptance of
113# the terms of this agreement and upon your providing appropriate
114# acknowledgments of NIST's creation of the data.
115#"""
116    record = {}
117    output_lines = []
118    for line in sys.stdin.readlines():
119        line = line.strip()
120        if line == '':
121            output_lines.extend(format_records(record))
122            record = {}
123        if ' =' in line:
124            record[line[:line.index('=') - 1].lower()] = line[line.index('=') + 2:]
125        if ': ' in line:
126            record[line[:line.index(':')].lower()] = dequote(line[line.index(':') + 2:])
127        if line == 'FAIL':
128            record['fail'] = True
129    output_lines.extend(format_records(record))
130    if len(output_lines) > 0:
131        if output_lines[0].count(',') == 3:
132            print """# Data is in the format:
133# key,iv,plaintext,ciphertext"""
134        elif output_lines[0].count(',') == 5:
135            print """# Data is in the format:
136# key,iv,plaintext,ciphertext,tag,aad"""
137        for output_line in output_lines:
138            print output_line
139
140
141
142if __name__ == '__main__':
143    main()
144