Skip to content

Commit

Permalink
Bug 1514999 - Add wycheproof Curve25519 testcases to nss, r=franziskus
Browse files Browse the repository at this point in the history
Differential Revision: https://phabricator.services.mozilla.com/D14843

--HG--
rename : gtests/common/chachapoly-vectors.h => gtests/common/testvectors/chachapoly-vectors.h
rename : gtests/common/gcm-vectors.h => gtests/common/testvectors/gcm-vectors.h
rename : gtests/common/wycheproof/header_bases/chachapoly-vectors.h => gtests/common/testvectors_base/chachapoly-vectors_base.h
rename : gtests/common/wycheproof/header_bases/gcm-vectors.h => gtests/common/testvectors_base/gcm-vectors_base.h
rename : gtests/common/wycheproof/testvectors/aes_gcm_test.json => gtests/common/wycheproof/source_vectors/aes_gcm_test.json
rename : gtests/common/wycheproof/testvectors/chacha20_poly1305_test.json => gtests/common/wycheproof/source_vectors/chacha20_poly1305_test.json
extra : amend_source : c6a4e9bc385e669347b13bbe1703eed65e385d6c
  • Loading branch information
Jonas Allmann committed Dec 19, 2018
1 parent 7bc70a3 commit 69203ee
Show file tree
Hide file tree
Showing 15 changed files with 2,944 additions and 78 deletions.
File renamed without changes.
1,819 changes: 1,819 additions & 0 deletions gtests/common/testvectors/curve25519-vectors.h

Large diffs are not rendered by default.

File renamed without changes.
75 changes: 75 additions & 0 deletions gtests/common/testvectors_base/curve25519-vectors_base.h
@@ -0,0 +1,75 @@
/* vim: set ts=2 et sw=2 tw=80: */
/* 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/. */

#ifndef curve25519_vectors_h__
#define curve25519_vectors_h__

#include <string>
#include <vector>

typedef struct curve25519_testvector_str {
std::vector<uint8_t> private_key;
std::vector<uint8_t> public_key;
std::vector<uint8_t> secret;
bool valid;
} curve25519_testvector;

const curve25519_testvector kCurve25519Vectors[] = {
{{0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda,
0x47, 0x0f, 0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20,
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72,
0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a, 0xa1, 0x23, 0x03, 0x21,
0x00, 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d,
0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a,
0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a},
{0x30, 0x39, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
0x03, 0x21, 0x00, 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3,
0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b,
0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f},
{0x4a, 0x5d, 0x9d, 0x5b, 0xa4, 0xce, 0x2d, 0xe1, 0x72, 0x8e, 0x3b,
0xf4, 0x80, 0x35, 0x0f, 0x25, 0xe0, 0x7e, 0x21, 0xc9, 0x47, 0xd1,
0x9e, 0x33, 0x76, 0xf0, 0x9b, 0x3c, 0x1e, 0x16, 0x17, 0x42},
true},

// A public key that's too short (31 bytes).
{{0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda,
0x47, 0x0f, 0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20,
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72,
0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a, 0xa1, 0x23, 0x03, 0x21,
0x00, 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d,
0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a,
0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a},
{0x30, 0x38, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
0x03, 0x20, 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3, 0x5b,
0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b, 0x78,
0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f},
{},
false},

// A public key that's too long (33 bytes).
{{0x30, 0x67, 0x02, 0x01, 0x00, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48,
0xce, 0x3d, 0x02, 0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda,
0x47, 0x0f, 0x01, 0x04, 0x4c, 0x30, 0x4a, 0x02, 0x01, 0x01, 0x04, 0x20,
0x77, 0x07, 0x6d, 0x0a, 0x73, 0x18, 0xa5, 0x7d, 0x3c, 0x16, 0xc1, 0x72,
0x51, 0xb2, 0x66, 0x45, 0xdf, 0x4c, 0x2f, 0x87, 0xeb, 0xc0, 0x99, 0x2a,
0xb1, 0x77, 0xfb, 0xa5, 0x1d, 0xb9, 0x2c, 0x2a, 0xa1, 0x23, 0x03, 0x21,
0x00, 0x85, 0x20, 0xf0, 0x09, 0x89, 0x30, 0xa7, 0x54, 0x74, 0x8b, 0x7d,
0xdc, 0xb4, 0x3e, 0xf7, 0x5a, 0x0d, 0xbf, 0x3a, 0x0d, 0x26, 0x38, 0x1a,
0xf4, 0xeb, 0xa4, 0xa9, 0x8e, 0xaa, 0x9b, 0x4e, 0x6a},
{0x30, 0x3a, 0x30, 0x14, 0x06, 0x07, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02,
0x01, 0x06, 0x09, 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01,
0x03, 0x22, 0x00, 0xde, 0x9e, 0xdb, 0x7d, 0x7b, 0x7d, 0xc1, 0xb4, 0xd3,
0x5b, 0x61, 0xc2, 0xec, 0xe4, 0x35, 0x37, 0x3f, 0x83, 0x43, 0xc8, 0x5b,
0x78, 0x67, 0x4d, 0xad, 0xfc, 0x7e, 0x14, 0x6f, 0x88, 0x2b, 0x4f, 0x34},
{},
false}};

#endif // curve25519_vectors_h__
87 changes: 74 additions & 13 deletions gtests/common/wycheproof/genTestVectors.py
Expand Up @@ -7,6 +7,7 @@

import json
import os
import subprocess

script_dir = os.path.dirname(os.path.abspath(__file__))

Expand Down Expand Up @@ -58,15 +59,46 @@ def format_testcase(self, testcase):

return result

# Writes one Curve25519 testvector into C-header format. (Not clang-format conform)
class Curve25519():
"""Class that provides the generator function for a single curve25519 test case."""

def generate_header(params):
# Static pkcs8 and skpi wrappers for the raw keys from Wycheproof.
# The public key section of the pkcs8 wrapper is filled up with 0's, which is
# not correct, but acceptable for the tests at this moment because
# validity of the public key is not checked.
# It's still necessary because of
# https://searchfox.org/nss/rev/7bc70a3317b800aac07bad83e74b6c79a9ec5bff/lib/pk11wrap/pk11pk12.c#171
pkcs8WrapperStart = "3067020100301406072a8648ce3d020106092b06010401da470f01044c304a0201010420"
pkcs8WrapperEnd = "a1230321000000000000000000000000000000000000000000000000000000000000000000"
spkiWrapper = "3039301406072a8648ce3d020106092b06010401da470f01032100"

def format_testcase(self, testcase):
result = '\n// Comment: {}'.format(testcase['comment'])
result += '\n{{{},\n'.format(string_to_hex_array(self.pkcs8WrapperStart + testcase['private'] + self.pkcs8WrapperEnd))
result += '{},\n'.format(string_to_hex_array(self.spkiWrapper + testcase['public']))
result += '{},\n'.format(string_to_hex_array(testcase['shared']))

# Flag 'acceptable' cases with secret == 0 as invalid for NSS.
# Flag 'acceptable' cases with forbidden public key values as invalid for NSS.
# Flag 'acceptable' cases with small public key (0 or 1) as invalid for NSS.
valid = testcase['result'] in ['valid', 'acceptable'] \
and not testcase['shared'] == "0000000000000000000000000000000000000000000000000000000000000000" \
and not testcase["public"] == "daffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" \
and not testcase["public"] == "dbffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff" \
and not 'Small public key' in testcase['flags']
result += '{}}},\n'.format(str(valid).lower())

return result

def generate_vectors_file(params):
"""
Generate and store a .h-file with test vectors for one test.
params -- Dictionary with parameters for test vector generation for the desired test.
"""

cases = import_testvector(os.path.join(script_dir, params['source']))
cases = import_testvector(os.path.join(script_dir, params['source_dir'] + params['source_file']))

with open(os.path.join(script_dir, params['base'])) as base:
header = base.read()
Expand Down Expand Up @@ -95,33 +127,62 @@ def generate_header(params):
# formatter -- the test case formatter class to be used for this test.
# crop_size_end -- number of characters removed from the end of the last generated test vector to close the array definiton.
# finish -- string to re-insert at the end and finish the file. (identical to chars cropped at the start)
# comment -- additional comments to add to the file just before defintion of the test vector array.
aes_gcm_params = {
'source': 'testvectors/aes_gcm_test.json',
'base': 'header_bases/gcm-vectors.h',
'target': '../gcm-vectors.h',
'source_dir': 'source_vectors/',
'source_file': 'aes_gcm_test.json',
'base': '../testvectors_base/gcm-vectors_base.h',
'target': '../testvectors/gcm-vectors.h',
'crop_size_start': -27,
'array_init': 'const gcm_kat_value kGcmWycheproofVectors[] = {\n',
'formatter' : AESGCM(),
'crop_size_end': -3,
'finish': '#endif // gcm_vectors_h__\n'
'finish': '#endif // gcm_vectors_h__\n',
'comment' : ''
}

chacha_poly_params = {
'source': 'testvectors/chacha20_poly1305_test.json',
'base': 'header_bases/chachapoly-vectors.h',
'target': '../chachapoly-vectors.h',
'source_dir': 'source_vectors/',
'source_file': 'chacha20_poly1305_test.json',
'base': '../testvectors_base/chachapoly-vectors_base.h',
'target': '../testvectors/chachapoly-vectors.h',
'crop_size_start': -35,
'array_init': 'const chacha_testvector kChaCha20WycheproofVectors[] = {\n',
'formatter' : ChaChaPoly(),
'crop_size_end': -2,
'finish': '#endif // chachapoly_vectors_h__\n'
'finish': '#endif // chachapoly_vectors_h__\n',
'comment' : ''
}

curve25519_params = {
'source_dir': 'source_vectors/',
'source_file': 'x25519_test.json',
'base': '../testvectors_base/curve25519-vectors_base.h',
'target': '../testvectors/curve25519-vectors.h',
'crop_size_start': -34,
'array_init': 'const curve25519_testvector kCurve25519WycheproofVectors[] = {\n',
'formatter' : Curve25519(),
'crop_size_end': -2,
'finish': '#endif // curve25519_vectors_h__\n',
'comment' : '// The public key section of the pkcs8 wrapped private key is\n\
// filled up with 0\'s, which is not correct, but acceptable for the\n\
// tests at this moment because validity of the public key is not checked.\n'
}

def update_tests(tests):

remote = "https://raw.githubusercontent.com/google/wycheproof/master/testvectors/"
for test in tests:
subprocess.check_call(['wget', remote+test['source_file'], '-O',
'gtests/common/wycheproof/source_vectors/' +test['source_file'],
'--no-check-certificate'])

def generate_test_vectors():
"""Generate C-header files for all supported tests."""
all_params = [aes_gcm_params, chacha_poly_params]
for param in all_params:
generate_header(param)
all_tests = [aes_gcm_params, chacha_poly_params, curve25519_params]
update_tests(all_tests)
for test in all_tests:
generate_vectors_file(test)

def main():
generate_test_vectors()
Expand Down

0 comments on commit 69203ee

Please sign in to comment.