blob: c17823b7373740c585941b624d0d648f38df2bcb [file] [log] [blame]
#!/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())