diff options
author | nagendra modadugu <ngm@google.com> | 2015-12-08 21:07:54 -0800 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-01-11 22:03:13 -0800 |
commit | 7a254e9851e37a5473efb8e61059d47b52bcee76 (patch) | |
tree | f37e151d293b26962f79234b6103d5245e4f4d0b /test | |
parent | 4368dcfb32942740dd11188de6a8658cdd448a5a (diff) | |
download | chrome-ec-7a254e9851e37a5473efb8e61059d47b52bcee76.tar.gz |
Initial RSA implementation.stabilize-7821.B
Includes support for encrypt / decrypt,
and sign / verify; padding schemes OAEP /
PKCS1; supporting bignum library.
RSA key sizes must be a multiple of 32-bits
(with the top bit set). Keying material,
input and output buffers are required to be
word-aligned.
BRANCH=none
TEST=added encrypt/decrypt sign/verify tests, compatibility with openssl tested
BUG=chrome-os-partner:43025,chrome-os-partner:47524
Change-Id: I6bc324c651e3178bb45bb75ab5935d9bc07efbce
Signed-off-by: nagendra modadugu <ngm@google.com>
Reviewed-on: https://chromium-review.googlesource.com/316942
Commit-Ready: Marius Schilder <mschilder@chromium.org>
Tested-by: Nagendra Modadugu <ngm@google.com>
Reviewed-by: Marius Schilder <mschilder@chromium.org>
Diffstat (limited to 'test')
-rw-r--r-- | test/tpm_test/rsa_test.py | 169 | ||||
-rw-r--r-- | test/tpm_test/subcmd.py | 1 | ||||
-rwxr-xr-x | test/tpm_test/tpmtest.py | 9 |
3 files changed, 177 insertions, 2 deletions
diff --git a/test/tpm_test/rsa_test.py b/test/tpm_test/rsa_test.py new file mode 100644 index 0000000000..c337c524cc --- /dev/null +++ b/test/tpm_test/rsa_test.py @@ -0,0 +1,169 @@ +#!/usr/bin/python +# Copyright 2015 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +"""Module for testing rsa functions using extended commands.""" + +import hashlib +import struct + +import subcmd +import utils + + +_RSA_OPCODES = { + 'ENCRYPT': 0x00, + 'DECRYPT': 0x01, + 'SIGN': 0x02, + 'VERIFY': 0x03, + 'KEYGEN': 0x04 +} + + +# TPM2 ALG codes. +_RSA_PADDING = { + 'PKCS1-SSA': 0x14, + 'PKCS1-ES': 0x15, + 'OAEP': 0x17 +} + + +# TPM2 ALG codes. +_HASH = { + 'NONE': 0x00, + 'SHA1': 0x04, + 'SHA256': 0x0B +} + + +# Command format. +# +# 0x00 OP +# 0x00 PADDING +# 0x00 HASHING +# 0x00 MSB KEY LEN +# 0x00 LSB KEY LEN +# 0x00 MSB IN LEN +# 0x00 LSB IN LEN +# .... IN +# 0x00 MSB DIGEST LEN +# 0x00 LSB DIGEST LEN +# .... DIGEST +# +_RSA_CMD_FORMAT = '{o:c}{p:c}{h:c}{kl:s}{ml:s}{msg}{dl:s}{dig}' + + +def _decrypt_cmd(padding, hashing, key_len, msg): + op = _RSA_OPCODES['DECRYPT'] + msg_len = len(msg) + return _RSA_CMD_FORMAT.format(o=op, p=padding, h=hashing, + kl=struct.pack('>H', key_len), + ml=struct.pack('>H', msg_len), msg=msg, + dl='', dig='') + + +def _encrypt_cmd(padding, hashing, key_len, msg): + op = _RSA_OPCODES['ENCRYPT'] + msg_len = len(msg) + return _RSA_CMD_FORMAT.format(o=op, p=padding, h=hashing, + kl=struct.pack('>H', key_len), + ml=struct.pack('>H', msg_len), msg=msg, + dl='', dig='') + + +def _sign_cmd(padding, hashing, key_len, msg): + op = _RSA_OPCODES['SIGN'] + digest = '' + if hashing == _HASH['SHA1']: + digest = hashlib.sha1(msg).digest() + elif hashing == _HASH['SHA256']: + digest = hashlib.sha256(msg).digest() + digest_len = len(digest) + return _RSA_CMD_FORMAT.format(o=op, p=padding, h=hashing, + kl=struct.pack('>H', key_len), + ml=struct.pack('>H', digest_len), msg=digest, + dl='', dig='') + + +def _verify_cmd(padding, hashing, key_len, sig, msg): + op = _RSA_OPCODES['VERIFY'] + sig_len = len(sig) + digest = '' + if hashing == _HASH['SHA1']: + digest = hashlib.sha1(msg).digest() + elif hashing == _HASH['SHA256']: + digest = hashlib.sha256(msg).digest() + digest_len = len(digest) + return _RSA_CMD_FORMAT.format(o=op, p=padding, h=hashing, + kl=struct.pack('>H', key_len), + ml=struct.pack('>H', sig_len), msg=sig, + dl=struct.pack('>H', digest_len), dig=digest) + + +# +# TEST VECTORS. +# +_ENCRYPT_INPUTS = ( + ('OAEP', 'SHA1', 768), + ('OAEP', 'SHA256', 768), + ('PKCS1-ES', 'NONE', 768), + ('PKCS1-ES', 'NONE', 2048), +) + + +_SIGN_INPUTS = ( + # TODO(ngm): add support for PSS. + ('PKCS1-SSA', 'SHA1', 768), + ('PKCS1-SSA', 'SHA256', 768), +) + + +class RSAError(Exception): + pass + + +def _encrypt_tests(tpm): + msg = 'Hello CR50!' + + for data in _ENCRYPT_INPUTS: + padding, hashing, key_len = data + test_name = 'RSA-ENC:%s:%s:%d' % data + cmd = _encrypt_cmd(_RSA_PADDING[padding], _HASH[hashing], key_len, msg) + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) + ciphertext = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) + + cmd = _decrypt_cmd(_RSA_PADDING[padding], _HASH[hashing], + key_len, ciphertext) + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) + plaintext = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) + if msg != plaintext: + raise RSAError('%s error:%s%s' % ( + test_name, utils.hex_dump(msg), utils.hex_dump(plaintext))) + print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) + + +def _sign_tests(tpm): + msg = 'Hello CR50!' + + for data in _SIGN_INPUTS: + padding, hashing, key_len = data + test_name = 'RSA-SIGN:%s:%s:%d' % data + cmd = _sign_cmd(_RSA_PADDING[padding], _HASH[hashing], key_len, msg) + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) + signature = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) + + cmd = _verify_cmd(_RSA_PADDING[padding], _HASH[hashing], + key_len, signature, msg) + wrapped_response = tpm.command(tpm.wrap_ext_command(subcmd.RSA, cmd)) + verified = tpm.unwrap_ext_response(subcmd.RSA, wrapped_response) + expected = '\x01' + if verified != expected: + raise RSAError('%s error:%s%s' % ( + test_name, utils.hex_dump(verified), utils.hex_dump(expected))) + print('%sSUCCESS: %s' % (utils.cursor_back(), test_name)) + + +def rsa_test(tpm): + _encrypt_tests(tpm) + _sign_tests(tpm) diff --git a/test/tpm_test/subcmd.py b/test/tpm_test/subcmd.py index dbfcadb1c5..f7bd8090a0 100644 --- a/test/tpm_test/subcmd.py +++ b/test/tpm_test/subcmd.py @@ -8,3 +8,4 @@ # Keep these codes in sync with include/extension.h. AES = 0 HASH = 1 +RSA = 2 diff --git a/test/tpm_test/tpmtest.py b/test/tpm_test/tpmtest.py index 571a4548d9..52d7205022 100755 --- a/test/tpm_test/tpmtest.py +++ b/test/tpm_test/tpmtest.py @@ -19,8 +19,11 @@ root_dir = os.path.dirname(os.path.abspath(sys.argv[0])) sys.path.append(os.path.join(root_dir, '..', '..', 'build', 'tpm_test')) import crypto_test -import hash_test import ftdi_spi_tpm +import hash_test +import rsa_test +import subcmd + # Extension command for dcypto testing EXT_CMD = 0xbaccd00a @@ -133,7 +136,9 @@ if __name__ == '__main__': crypto_test.crypto_tests(t, os.path.join(root_dir, 'crypto_test.xml')) hash_test.hash_test(t) - except (TpmError, crypto_test.CryptoError, hash_test.HashError) as e: + rsa_test.rsa_test(t) + except (TpmError, crypto_test.CryptoError, hash_test.HashError, + rsa_test.RSAError) as e: print() print('Error:', e) if debug_needed: |