| #!/usr/bin/env python3 | |
| # Copyright lowRISC contributors. | |
| # Licensed under the Apache License, Version 2.0, see LICENSE for details. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| """ Generate parameters for the OTBN end-to-end tests. | |
| """ | |
| from Crypto.PublicKey import RSA, ECC | |
| import argparse | |
| import sys | |
| import secrets | |
| C_DATATYPE = "static const uint8_t" | |
| def print_array(varname: str, val: int, size_bytes: int): | |
| print("%s %s[%d] = {%s};" % (C_DATATYPE, varname, size_bytes, ', '.join(["0x%02x" % i for i in int(val).to_bytes(size_bytes, byteorder="little")]))) | |
| def print_string(varname: str, val: str, size_bytes: int): | |
| print("%s %s[%d] = {\"%s\"};" % (C_DATATYPE, varname, size_bytes, val)) | |
| def print_rsa_params(private_key_file: str, in_str: str) -> None: | |
| in_bytes = in_str.encode("utf-8") | |
| print("Using private key {}, and plaintext message {!r}".format(private_key_file, in_bytes)) | |
| print("") | |
| private_key = RSA.import_key(open(private_key_file).read()) | |
| data = int.from_bytes(in_bytes, byteorder="little", signed=False) | |
| print("// modulus (n)") | |
| print_array("kModulus", private_key.n, private_key.size_in_bytes()) | |
| print("") | |
| print("// private exponent (d)") | |
| print_array("kPrivateExponent", private_key.d, private_key.size_in_bytes()) | |
| print("") | |
| print("// decrypted/plaintext message") | |
| print_string("kIn", in_str, private_key.size_in_bytes()) | |
| print("") | |
| print("// encrypted message") | |
| encrypted = private_key._encrypt(data) | |
| print_array("kEncryptedExpected", encrypted, private_key.size_in_bytes()) | |
| print("") | |
| def print_ecc_params(private_key_file: str, in_str: str) -> None: | |
| in_bytes = in_str.encode("utf-8") | |
| print("Using private key {}, and plaintext message {!r}".format(private_key_file, in_bytes)) | |
| print("") | |
| key = ECC.import_key(open(private_key_file).read()) | |
| assert key.has_private() | |
| key_size_bytes = key.public_key().pointQ.size_in_bytes() | |
| data = int.from_bytes(in_bytes, byteorder="little", signed=False) | |
| k = int.from_bytes(secrets.token_bytes(key_size_bytes), byteorder="little", signed=False) | |
| # Sign the input data | |
| (r, s) = key._sign(data, k) | |
| print("// Parameters for ECC {}".format(key.curve)) | |
| print("// Message") | |
| print_string("kIn", in_str, key_size_bytes) | |
| print("") | |
| print("// Public key x-coordinate (Q.x)") | |
| print_array("kPublicKeyQx", key.public_key().pointQ.x, key_size_bytes) | |
| print("") | |
| print("// Public key y-coordinate (Q.y)") | |
| print_array("kPublicKeyQy", key.public_key().pointQ.y, key_size_bytes) | |
| print("") | |
| print("// Private key (d)") | |
| print_array("kPrivateKeyD", key.d, key_size_bytes) | |
| print("") | |
| print("// Secret random integer (k)") | |
| print_array("kSecretRandomIntK", k, key_size_bytes) | |
| print("") | |
| print("// Signature component r") | |
| print_array("kExpectedSignatureR", r, key_size_bytes) | |
| print("") | |
| print("// Signature component s") | |
| print_array("kExpectedSignatureS", s, key_size_bytes) | |
| print("") | |
| def main() -> int: | |
| parser = argparse.ArgumentParser() | |
| parser.add_argument('type', choices=('rsa', 'ecc')) | |
| parser.add_argument('private_key_pem_file') | |
| parser.add_argument('message', nargs='?', default="Hello OTBN.") | |
| args = parser.parse_args() | |
| if args.type == 'rsa': | |
| print_rsa_params(args.private_key_pem_file, args.message) | |
| elif args.type == 'ecc': | |
| print_ecc_params(args.private_key_pem_file, args.message) | |
| else: | |
| raise ValueError("Unknown type {!r}".format(args.type)) | |
| if __name__ == "__main__": | |
| sys.exit(main()) |