summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authornagendra modadugu <ngm@google.com>2015-12-08 21:07:54 -0800
committerchrome-bot <chrome-bot@chromium.org>2016-01-11 22:03:13 -0800
commit7a254e9851e37a5473efb8e61059d47b52bcee76 (patch)
treef37e151d293b26962f79234b6103d5245e4f4d0b /test
parent4368dcfb32942740dd11188de6a8658cdd448a5a (diff)
downloadchrome-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.py169
-rw-r--r--test/tpm_test/subcmd.py1
-rwxr-xr-xtest/tpm_test/tpmtest.py9
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: