Exemplo n.º 1
0
def main(input_config_file=None,
         input_values_file=None,
         target_file_name_prefix=None,
         file_identifier=None,
         output_dir_path=None,
         part_size=None,
         input_version=None,
         input_is_keygen=None,
         input_is_encrypt=None,
         input_is_keyfile=None):
    try:
        if all(arg is None for arg in [
                input_config_file, input_values_file, target_file_name_prefix,
                file_identifier, output_dir_path
        ]):
            parser = argparse.ArgumentParser(
                prog='./mfg_gen.py',
                description=
                "Create binary files from input config and values file",
                formatter_class=argparse.RawDescriptionHelpFormatter)

            parser.add_argument('--conf',
                                dest='config_file',
                                help='the input configuration csv file',
                                default=None)

            parser.add_argument('--values',
                                dest='values_file',
                                help='the input values csv file',
                                default=None)

            parser.add_argument('--prefix',
                                dest='prefix',
                                help='the unique name as each filename prefix')

            parser.add_argument(
                '--fileid',
                dest='fileid',
                help='the unique file identifier(any key in values file) \
                                as each filename suffix (Default: numeric value(1,2,3...)'
            )

            parser.add_argument(
                '--outdir',
                dest='outdir',
                default=os.getcwd(),
                help='the output directory to store the files created\
                                (Default: current directory)')

            parser.add_argument(
                "--size",
                dest='part_size',
                help='Size of NVS Partition in bytes (must be multiple of 4096)'
            )

            parser.add_argument("--version",
                                dest="version",
                                help='Set version. Default: v2',
                                choices=['v1', 'v2'],
                                default='v2',
                                type=str.lower)

            parser.add_argument(
                "--keygen",
                dest="keygen",
                help='Generate keys for encryption. Default: false',
                choices=['true', 'false'],
                default='false',
                type=str.lower)

            parser.add_argument("--encrypt",
                                dest="encrypt",
                                help='Set encryption mode. Default: false',
                                choices=['true', 'false'],
                                default='false',
                                type=str.lower)

            parser.add_argument(
                "--keyfile",
                dest="keyfile",
                help=
                'File having key for encryption (Applicable only if encryption mode is true)',
                default=None)

            args = parser.parse_args()

            args.outdir = os.path.join(args.outdir, '')

            input_config_file = args.config_file
            input_values_file = args.values_file
            target_file_name_prefix = args.prefix
            output_dir_path = args.outdir
            part_size = args.part_size
            input_version = args.version
            input_is_keygen = args.keygen
            input_is_encrypt = args.encrypt
            input_is_keyfile = args.keyfile
            file_identifier = ''
            print_arg_str = "Invalid.\nTo generate binary --conf, --values, --prefix and --size arguments are mandatory.\
            \nTo generate encryption keys --keygen argument is mandatory."

            print_encrypt_arg_str = "Missing parameter. Enter --keygen or --keyfile."

            if args.fileid:
                file_identifier = args.fileid

            if input_config_file and input_is_encrypt.lower(
            ) == 'true' and input_is_keygen.lower(
            ) == 'true' and input_is_keyfile:
                sys.exit(
                    'Invalid. Cannot provide both --keygen and --keyfile argument together.'
                )

            nvs_partition_gen.check_input_args(
                input_config_file, input_values_file, part_size,
                input_is_keygen, input_is_encrypt, input_is_keyfile,
                input_version, print_arg_str, print_encrypt_arg_str,
                output_dir_path)

            if not input_config_file and input_is_keygen:
                if input_is_encrypt == 'true':
                    sys.exit(
                        "Invalid.\nOnly --keyfile and --outdir arguments allowed.\n"
                    )
                # Generate Key Only
                nvs_partition_gen.nvs_part_gen(
                    input_filename=input_config_file,
                    output_filename=input_values_file,
                    input_part_size=part_size,
                    is_key_gen=input_is_keygen,
                    encrypt_mode=input_is_encrypt,
                    key_file=input_is_keyfile,
                    version_no=input_version,
                    output_dir=output_dir_path)
                exit(0)

            if not (input_config_file and input_values_file
                    and target_file_name_prefix and part_size):
                sys.exit(print_arg_str)

        keys_in_values_file = []
        keys_in_config_file = []
        config_data_to_write = []
        key_value_data = []
        csv_file_list = []
        keys_repeat = []
        is_empty_line = False
        files_created = False
        file_identifier_value = '0'
        output_target_dir = ''
        target_values_file = None
        output_file_prefix = None

        # Verify config file is not empty
        if os.stat(input_config_file).st_size == 0:
            raise SystemExit("Oops...config file: %s is empty." %
                             input_config_file)

        # Verify values file is not empty
        if os.stat(input_values_file).st_size == 0:
            raise SystemExit("Oops...values file: %s is empty." %
                             input_values_file)

        # Verify config file does not have empty lines
        csv_config_file = open(input_config_file, 'r')
        try:
            config_file_reader = csv.reader(csv_config_file, delimiter=',')
            for config_data in config_file_reader:
                for data in config_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line:
                    raise SystemExit(
                        "Oops...config file: %s cannot have empty lines. " %
                        input_config_file)
                if not config_data:
                    raise SystemExit(
                        "Oops...config file: %s cannot have empty lines." %
                        input_config_file)

            csv_config_file.seek(0)

            # Extract keys from config file
            for config_data in config_file_reader:
                if 'namespace' not in config_data:
                    keys_in_config_file.append(config_data[0])
                if 'REPEAT' in config_data:
                    keys_repeat.append(config_data[0])

            csv_config_file.close()
        except Exception as e:
            print(e)
        finally:
            csv_config_file.close()

        is_empty_line = False
        # Verify values file does not have empty lines
        csv_values_file = open(input_values_file, 'r')
        try:
            values_file_reader = csv.reader(csv_values_file, delimiter=',')
            for values_data in values_file_reader:
                for data in values_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line:
                    raise SystemExit(
                        "Oops...values file: %s cannot have empty lines." %
                        input_values_file)
                if not values_data:
                    raise SystemExit(
                        "Oops...values file: %s cannot have empty lines." %
                        input_values_file)

            csv_values_file.seek(0)

            # Extract keys from values file
            keys_in_values_file = next(values_file_reader)

            csv_values_file.close()
        except Exception as e:
            print(e)
            exit(1)
        finally:
            csv_values_file.close()

        # Verify file identifier exists in values file
        if file_identifier:
            if file_identifier not in keys_in_values_file:
                raise SystemExit(
                    'Oops...target_file_identifier: %s does not exist in values file.\n'
                    % file_identifier)

        # Verify data in the input_config_file and input_values_file
        verify_data_in_file(input_config_file, input_values_file,
                            keys_in_config_file, keys_in_values_file,
                            keys_repeat)

        # Add config data per namespace to `config_data_to_write` list
        config_data_to_write = add_config_data_per_namespace(input_config_file)

        try:
            with open(input_values_file, 'r') as csv_values_file:
                values_file_reader = csv.reader(csv_values_file, delimiter=',')
                keys = next(values_file_reader)

            filename, file_ext = os.path.splitext(input_values_file)
            target_filename = filename + "_created" + file_ext
            if keys_repeat:
                target_values_file = set_repeat_value(keys_repeat, keys,
                                                      input_values_file,
                                                      target_filename)
            else:
                target_values_file = input_values_file

            csv_values_file = open(target_values_file, 'r')

            values_file_reader = csv.reader(csv_values_file, delimiter=',')
            next(values_file_reader)
            for values_data_line in values_file_reader:
                key_value_data = list(
                    zip_longest(keys_in_values_file, values_data_line))

                # Get file identifier value from values file
                file_identifier_value = get_fileid_val(
                    file_identifier, keys_in_config_file, keys_in_values_file,
                    values_data_line, key_value_data, file_identifier_value)

                key_value_pair = key_value_data[:]

                # Create new directory(if doesn't exist) to store csv file generated
                output_target_dir = create_dir("csv/", output_dir_path)

                # Verify if output csv file does not exist
                csv_filename = target_file_name_prefix + "-" + file_identifier_value + ".csv"
                csv_file_list.append(csv_filename)
                output_csv_file = output_target_dir + csv_filename
                if os.path.isfile(output_csv_file):
                    raise SystemExit("Target csv file: %s already exists.`" %
                                     output_csv_file)

                # Add values corresponding to each key to csv target file
                add_data_to_file(config_data_to_write, key_value_pair,
                                 output_csv_file)

                # Create new directory(if doesn't exist) to store bin file generated
                output_target_dir = create_dir("bin/", output_dir_path)

                # Verify if output bin file does not exist
                output_file_prefix = target_file_name_prefix + "-" + file_identifier_value
                output_bin_file = output_target_dir + output_file_prefix + ".bin"
                if os.path.isfile(output_bin_file):
                    raise SystemExit("Target csv file: %s already exists.`" %
                                     output_bin_file)

                # Create output csv and bin file
                if input_is_keygen.lower() == 'true' and input_is_keyfile:
                    input_is_keyfile = os.path.basename(input_is_keyfile)
                nvs_partition_gen.nvs_part_gen(
                    input_filename=output_csv_file,
                    output_filename=output_bin_file,
                    input_part_size=part_size,
                    is_key_gen=input_is_keygen,
                    encrypt_mode=input_is_encrypt,
                    key_file=input_is_keyfile,
                    version_no=input_version,
                    encr_key_prefix=output_file_prefix,
                    output_dir=output_dir_path)
                print("CSV Generated: ", str(output_csv_file))

                files_created = True

            csv_values_file.close()
        except Exception as e:
            print(e)
            exit(1)
        finally:
            csv_values_file.close()
        return csv_file_list, files_created, target_values_file

    except ValueError as err:
        print(err)
    except Exception:
        raise
Exemplo n.º 2
0
def main():
    try:
        parser = argparse.ArgumentParser(prog='./factory_nvs_gen.py',\
        description="Factory NVS Generator",\
        formatter_class=argparse.RawDescriptionHelpFormatter)
        factory_nvs_part_gen_group = parser.add_argument_group('To generate Factory NVS partition')
        factory_nvs_part_gen_group.add_argument('setup_code',\
        help='the input setup code without hyphens Eg.: 11122333 ')
        factory_nvs_part_gen_group.add_argument('setup_id',\
        help='the input setup identifer Eg.: ES32')
        factory_nvs_part_gen_group.add_argument('--infile',dest='infile',\
        help='the input csv file with extension(full path) to add HomeKit data generated to this file Eg.: fan_data.csv')
        factory_nvs_part_gen_group.add_argument('outfile',\
        help='the output csv and bin filename without extension Eg.: fan_factory')
        factory_nvs_part_gen_group.add_argument('--size', \
        help='Size of NVS Partition in bytes (must be multiple of 4096)', \
        default='0x4000')
        factory_nvs_part_gen_group.add_argument('--version', \
        help='Set version. Default: v2',choices=['v1','v2'], \
        default='v2',type=str.lower)
        factory_nvs_part_gen_group.add_argument("--keygen", \
        help='Generate keys for encryption. Creates an `encryption_keys.bin` file. Default: false', \
        choices=['true','false'],default= 'false',type=str.lower)
        factory_nvs_part_gen_group.add_argument("--encrypt", \
        help='Set encryption mode. Default: false', \
        choices=['true','false'],default='false',type=str.lower)
        factory_nvs_part_gen_group.add_argument("--keyfile", \
        help='File having key for encryption (Applicable only if encryption mode is true)',
        default = None)
        factory_nvs_part_gen_group.add_argument('--outdir', dest='outdir', \
        help='the output directory to store the files created(Default: current directory)', default=os.getcwd())
        factory_nvs_part_gen_group.add_argument('--salt', \
        help='Predefined salt if any', \
        default=None)

        args = parser.parse_args()
        part_size = args.size
        is_key_gen = args.keygen
        encrypt_mode = args.encrypt
        version_no = args.version
        key_file = args.keyfile
        output_dir_path = args.outdir
        salt_input = args.salt

        # Check if the setup code has valid format
        setup_code = args.setup_code
        if (len(setup_code) != 8) or (not setup_code.isdigit()):
            print("Setup code should be 8 numbers without any '-' in between. Eg. 11122333")
            sys.exit (1)

        # Add the hyphen (-) in the PIN for salt-verifier generation. So, 11122333 will become 111-22-333
        setup_code = setup_code[:3] + '-' + setup_code[3:5] + '-' + setup_code[5:]
        setup_id = args.setup_id
        file_prefix = args.outfile

        if not args.infile:
            csv_file = file_prefix + ".csv"
        else:
            if not os.path.isfile(args.infile):
                sys.exit("Oops...file: `" + args.infile + "` does not exist...")
            else:
                csv_file = file_prefix + ".csv"
        bin_file = file_prefix + ".bin"
        # Consider enabling RFC5054 compatibility for interoperation with non srp SRP-6a implementations
        #srp.rfc5054_enable()

        # The Modulus, N, and Generator, g, as specified by the 3072-bit group of RFC5054. This is required since the standard srp script does not support this
        n_3072 = "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6BF12FFA06D98A0864D87602733EC86A64521F2B18177B200CBBE117577A615D6C770988C0BAD946E208E24FA074E5AB3143DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF"
        g_3072 = "5"

        # Generate the Salt and Verifier for the given PIN
        salt, vkey = srp.create_salted_verification_key( 'Pair-Setup', setup_code, srp.SHA512, srp.NG_CUSTOM, n_3072, g_3072, salt_len=16 , salt=salt_input)

        # Create the CSV file with appropriate data
        f = open(csv_file, 'w')
        if not args.infile:
            f.write("key,type,encoding,value\n")
        else:
            in_f = open(args.infile, 'r')
            data = in_f.read()
            f.write(data)
            in_f.close()

        f.close()

        hap_setup_found = False

        f = open(csv_file,'a+')
        f.seek(0)
        f_reader = csv.reader(f, delimiter='\n')
        for data in f_reader:
            if 'hap_setup,namespace,,' in data:
                hap_setup_found = True
                break

        if not hap_setup_found:
            f.write("hap_setup,namespace,,\n")

        f.write("setup_id,data,binary," + setup_id + "\n")
        f.write("setup_salt,data,hex2bin," + binascii.b2a_hex(salt).zfill(32).decode("utf-8") + "\n")
        f.write("setup_verifier,data,hex2bin," + binascii.b2a_hex(vkey).zfill(768).decode("utf-8"))
        f.close()

        print("CSV Generated: " + csv_file)

        print_arg_str = "Invalid.\nTo generate nvs partition binary --input, --output and --size arguments are mandatory.\nTo generate encryption keys --keygen argument is mandatory."
        print_encrypt_arg_str = "Missing parameter. Enter --keyfile or --keygen."

        nvs_partition_gen.check_input_args(csv_file, bin_file, part_size, is_key_gen,\
                                            encrypt_mode, key_file, version_no, print_arg_str, print_encrypt_arg_str, output_dir_path)

        nvs_partition_gen.nvs_part_gen(input_filename=csv_file, output_filename=bin_file,\
                                        input_part_size=part_size, is_key_gen=is_key_gen,\
                                        encrypt_mode=encrypt_mode, key_file=key_file,\
                                        encr_key_prefix=None, version_no=version_no, output_dir=output_dir_path)

        print("NVS Flash Binary Generated: " + bin_file)

    except Exception as e:
        sys.exit(e)
Exemplo n.º 3
0
def main():
    try:
        filename = os.path.join('.', 'hk_mfg_gen.py')
        parser = argparse.ArgumentParser(
            prog=filename,
            description=
            "Generate HomeKit specific data and create binaries and HomeKit setup info",
            formatter_class=argparse.RawDescriptionHelpFormatter)

        parser.add_argument('--conf',
                            dest='config_file',
                            help='the input configuration csv file')

        parser.add_argument(
            '--values',
            dest='values_file',
            help='the input values csv file (the number of accessories \
                            to create HomeKit data for is equal to the data entries \
                            in this file)',
            default=None)

        parser.add_argument('--prefix',
                            dest='prefix',
                            help='the accessory name as each filename prefix',
                            default=None)

        parser.add_argument(
            '--fileid',
            dest='fileid',
            help='the unique file identifier(any key in values file) as \
                            each filename suffix (Default: setup_code)',
            default=None)

        curr_dir = os.path.join('.', '')
        parser.add_argument(
            '--outdir',
            dest='outdir',
            default=curr_dir,
            help='the output directory to store the files created \
                            (Default: current directory)')

        parser.add_argument('--cid',
                            dest='cid',
                            type=int,
                            help='the accessory category identifier',
                            default=None)

        parser.add_argument(
            '--count',
            dest='count',
            type=int,
            help='the number of accessories to create HomeKit data for,\
                            applicable only if --values is not given',
            default=None)

        parser.add_argument(
            "--size",
            dest='part_size',
            help='Size of NVS Partition in bytes (must be multiple of 4096)',
            default=None)

        parser.add_argument("--version",
                            dest="version",
                            help='Set version. Default: v2',
                            choices=['v1', 'v2'],
                            default='v2',
                            type=str.lower)

        parser.add_argument(
            "--keygen",
            dest="keygen",
            help='Generate keys for encryption. Default: False',
            choices=['true', 'false'],
            default='false',
            type=str.lower)

        parser.add_argument("--encrypt",
                            dest="encrypt",
                            help='Set encryption mode. Default: False',
                            choices=['true', 'false'],
                            default='false',
                            type=str.lower)

        parser.add_argument(
            "--keyfile",
            dest="keyfile",
            help=
            'File having key for encryption (Applicable only if encryption mode is true)',
            default=None)

        args = parser.parse_args()
        input_config_file = args.config_file
        input_values_file = args.values_file
        input_prefix = args.prefix
        input_fileid = args.fileid
        input_outdir = args.outdir
        input_cid = args.cid
        input_count = args.count
        part_size = args.part_size
        version = args.version
        input_is_keygen = args.keygen
        input_is_encrypt = args.encrypt
        input_is_keyfile = args.keyfile
        GENERATE_KEY_ONLY = False
        print_arg_str = "\nTo generate nvs partition binary with custom data --conf, --values, --prefix --cid, and --size arguments are mandatory.\
        \nTo generate nvs partition binary without any custom data --count, --prefix --cid, and --size arguments are mandatory.\
        \nTo generate encryption keys --keygen argument is mandatory."

        print_encrypt_arg_str = "Missing parameter. Enter --keyfile."

        if not part_size and input_is_keygen.lower() == 'true':
            if input_is_encrypt == 'true':
                sys.exit(
                    "Invalid.\nOnly --keyfile and --outdir arguments allowed.\n"
                )
            GENERATE_KEY_ONLY = True

            nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen,\
                                               input_is_encrypt, input_is_keyfile, version, print_arg_str,
                                               print_encrypt_arg_str, input_outdir)

            nvs_partition_gen.nvs_part_gen(input_filename = input_config_file, output_filename = input_values_file,\
                                           input_part_size=part_size, is_key_gen=input_is_keygen,\
                                           encrypt_mode=input_is_encrypt, key_file=input_is_keyfile,\
                                           version_no=version, output_dir=input_outdir)
            sys.exit(0)

        # Verify that --cid argument and --prefix arguments are given
        if not input_cid or not input_prefix:
            parser.error(print_arg_str)

        # Verify that --values argument and --count argument are not given together
        if input_values_file and input_count:
            parser.error('--values and --count cannot be given together')

        # Verify if --fileid argument is given then --values argument should also be given
        if input_fileid and not input_values_file:
            parser.error('--values is needed as --fileid given')

        # Verify --count argument is given if --values file is not given
        if not input_config_file:
            if not input_values_file and not input_count:
                parser.error('--count or --values is needed')
        else:
            # Verify that --conf argument and --count argument are not given together
            if input_count:
                parser.error('--conf and --count cannot be given together')

            # Verify if --conf argument is given then --values argument should also be given
            if not input_values_file:
                parser.error('--values is needed as --conf given')

        # Add backslash to outdir if it is not present
        backslash = ['/', '\\']
        if not any(ch in input_outdir for ch in backslash):
            input_outdir = os.path.join(args.outdir, '')

        # Set default value for fileid if --fileid argument is not given
        if not input_fileid:
            input_fileid = 'setup_code'

        if input_is_encrypt.lower() == 'true':
            if input_is_keygen.lower() == 'true' and input_is_keyfile:
                parser.error(
                    'Invalid. Cannot provide --keygen and --keyfile with --encrypt argument.'
                )
            #else:
            #    parser.error('Invalid. --keyfile needed as --encrypt is True.')
            elif not (input_is_keygen.lower() == 'true' or input_is_keyfile):
                parser.error(
                    'Invalid. Must provide --keygen or --keyfile with --encrypt argument.'
                )

        if input_count:
            nvs_partition_gen.check_input_args("None", "None", part_size, input_is_keygen,\
                input_is_encrypt, input_is_keyfile, version, print_arg_str, print_encrypt_arg_str, input_outdir)
        else:
            nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen,\
                input_is_encrypt, input_is_keyfile, version, print_arg_str, print_encrypt_arg_str, input_outdir)

        setup_id_created = []
        setup_code_created = []
        salt_created = []
        vkey_created = []
        keys_in_values_file = []
        keys_in_config_file = []
        values_file_keys = []
        homekit_data = []
        data_in_values_file = []
        csv_output_filenames = []
        setup_payload = b''
        setup_code = b''
        is_empty_line = False
        files_created = False
        total_value_count = 1
        hk_setup_info_dir = os.path.join('homekit_setup_info', '')

        if input_config_file:
            # Verify config file is not empty
            if os.stat(input_config_file).st_size == 0:
                raise SystemExit("Oops...config file: %s is empty..." %
                                 input_config_file)

            # Verify config file does not have empty lines
            config_file = open(input_config_file, 'r')
            config_file_reader = csv.reader(config_file, delimiter=',')
            for config_data in config_file_reader:
                for data in config_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line:
                    raise SystemExit(
                        "Oops...config file: %s cannot have empty lines..." %
                        input_config_file)
                if not config_data:
                    raise SystemExit(
                        "Oops...config file: %s cannot have empty lines..." %
                        str(input_config_file))
            config_file.close()

            # Extract keys from config file
            config_file = open(input_config_file, 'r')
            config_file_reader = csv.reader(config_file, delimiter=',')
            for config_data in config_file_reader:
                if not 'namespace' in config_data:
                    keys_in_config_file.append(config_data[0])
            config_file.close()

            # Verify data in the input config file
            verify_data_in_file(input_config_file=input_config_file)

        is_empty_line = False

        if input_values_file:
            # Verify values file is not empty
            if os.stat(input_values_file).st_size == 0:
                raise SystemExit("Oops...values file: %s is empty..." %
                                 input_values_file)

            # Verify values file does not have empty lines
            csv_values_file = open(input_values_file, 'r')
            values_file_reader = csv.reader(csv_values_file, delimiter=',')
            for values_data in values_file_reader:
                for data in values_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line is True:
                    raise SystemExit(
                        "Oops...values file: %s cannot have empty lines..." %
                        input_values_file)
                if not values_data:
                    raise SystemExit(
                        "Oops...values file: %s cannot have empty lines..." %
                        str(input_values_file))
            csv_values_file.close()

            # Extract keys from values file
            values_file = open(input_values_file, 'r')
            values_file_reader = csv.reader(values_file, delimiter=',')
            keys_in_values_file = next(values_file_reader)
            values_file.close()

            values_file = open(input_values_file, 'r')
            values_file_reader = csv.reader(values_file, delimiter=',')
            next(values_file_reader)

            # Verify file identifier exists in values file
            if 'setup_code' not in input_fileid:
                if input_fileid not in keys_in_values_file:
                    raise SystemExit(
                        'Oops...target_file_id: %s does not exist in values file...\n'
                        % input_fileid)

            # Verify data in the input values_file
            verify_data_in_file(input_values_file=input_values_file,
                                keys_in_values_file=keys_in_values_file)

            # Add data in values file to list
            for values in values_file_reader:
                data_in_values_file.append(values)

            # Get number of rows from values file which is equal to\
            # the number of accessories to create HomeKit data for
            total_value_count = len(data_in_values_file)

            values_file.close()

        if input_config_file and input_values_file:
            # Get keys from values file present in config files
            values_file_keys = get_keys(keys_in_values_file,
                                        keys_in_config_file)

            # Verify data in the input values_file
            verify_data_in_file(input_config_file=input_config_file,
                                keys_in_values_file=values_file_keys)

        if input_values_file:
            keys_in_values_file.extend([
                'setup_id', 'setup_code', 'setup_salt', 'setup_verifier',
                'setup_payload'
            ])
        else:
            keys_in_values_file = [
                'setup_id', 'setup_code', 'setup_salt', 'setup_verifier',
                'setup_payload'
            ]

        # Generate homekit data
        if input_count:
            setup_id_created, setup_code_created, salt_created, vkey_created = homekit_data_gen(
                no_of_accessories=input_count)
        else:
            setup_id_created, setup_code_created, salt_created, vkey_created = homekit_data_gen(
                no_of_accessories=total_value_count)

        # Verify Accessory Category Identifier (cid)
        setup_info_gen.verify_cid(input_cid)

        # Generate setup payload and add it alongwith the homekit data generated to config and values file(if exist)\
        # if input config and input values file do not exist then new files are created
        if data_in_values_file:
            for (values, setup_id, setup_code, salt, vkey) in \
            list(zip_longest(data_in_values_file,setup_id_created,setup_code_created,\
            salt_created, vkey_created)):
                setup_payload,setup_code = setup_info_gen.setup_payload_create(input_cid,\
                setup_code=setup_code,setup_id=setup_id)
                values.extend(
                    [setup_id, setup_code, salt, vkey, setup_payload])
                homekit_data.append(values)
        else:
            for (setup_id, setup_code, salt, vkey) in \
            list(zip_longest(setup_id_created,setup_code_created,\
            salt_created, vkey_created)):
                setup_payload,setup_code = setup_info_gen.setup_payload_create(input_cid,\
                setup_code=setup_code,setup_id=setup_id)
                homekit_data.append(
                    [setup_id, setup_code, salt, vkey, setup_payload])


        target_config_file,target_values_file = add_homekit_data_to_file(input_config_file, \
        input_values_file, keys_in_values_file, homekit_data, input_outdir)

        # Generate csv and bin file
        csv_output_filenames, files_created, target_values_file = mfg_gen.main(input_config_file=target_config_file, input_values_file=target_values_file,\
                                                           target_file_name_prefix=input_prefix, file_identifier=input_fileid,\
                                                           output_dir_path=input_outdir, part_size=part_size,\
                                                           input_version=version, input_is_keygen=input_is_keygen,\
                                                           input_is_encrypt=input_is_encrypt ,input_is_keyfile=input_is_keyfile)

        print("HomeKit config data generated is added to file: ",
              target_config_file)
        print("HomeKit values data generated is added to file: ",
              target_values_file)

        if not files_created:
            raise SystemExit(
                "Oops...csv,bin,setup info files could not be created...Please check your input files..."
            )

        # Create new directory(if doesn't exist) to store homekit setup info generated
        output_target_dir = input_outdir + hk_setup_info_dir
        if not os.path.isdir(output_target_dir):
            distutils.dir_util.mkpath(output_target_dir)

        # Write homekit setup info generated to output_target_file
        write_homekit_setup_info(target_values_file, output_target_dir,
                                 csv_output_filenames)

    except Exception as std_err:
        print(std_err)
    except:
        raise
Exemplo n.º 4
0
def main(input_config_file=None,input_values_file=None,target_file_name_prefix=None,
         file_identifier=None,output_dir_path=None,part_size=None,input_version=None,
         input_is_keygen=None,input_is_encrypt=None,input_is_keyfile=None):
    try:
        if all(arg is None for arg in [input_config_file,input_values_file,target_file_name_prefix,
                                       file_identifier,output_dir_path]):
            parser = argparse.ArgumentParser(prog='./mfg_gen.py',
                                             description="Create binary files from input config and values file",
                                             formatter_class=argparse.RawDescriptionHelpFormatter)

            parser.add_argument('--conf',
                                dest='config_file',
                                help='the input configuration csv file',
                                default=None)

            parser.add_argument('--values',
                                dest='values_file',
                                help='the input values csv file',
                                default=None)

            parser.add_argument('--prefix',
                                dest='prefix',
                                help='the unique name as each filename prefix')

            parser.add_argument('--fileid',
                                dest='fileid',
                                help='the unique file identifier(any key in values file) \
                                as each filename suffix (Default: numeric value(1,2,3...)')

            parser.add_argument('--outdir',
                                dest='outdir',
                                default=os.getcwd(),
                                help='the output directory to store the files created\
                                (Default: current directory)')

            parser.add_argument("--size",
                                dest='part_size',
                                help='Size of NVS Partition in bytes (must be multiple of 4096)')

            parser.add_argument("--version",
                                dest="version",
                                help='Set version. Default: v2',
                                choices=['v1','v2'],
                                default='v2',
                                type=str.lower)

            parser.add_argument("--keygen",
                                dest="keygen",
                                help='Generate keys for encryption. Default: false',
                                choices=['true','false'],
                                default='false',
                                type=str.lower)

            parser.add_argument("--encrypt",
                                dest="encrypt",
                                help='Set encryption mode. Default: false',
                                choices=['true','false'],
                                default='false',
                                type=str.lower)

            parser.add_argument("--keyfile",
                                dest="keyfile",
                                help='File having key for encryption (Applicable only if encryption mode is true)',
                                default=None)

            args = parser.parse_args()

            args.outdir = os.path.join(args.outdir, '')

            input_config_file = args.config_file
            input_values_file = args.values_file
            target_file_name_prefix = args.prefix
            output_dir_path = args.outdir
            part_size = args.part_size
            input_version = args.version
            input_is_keygen = args.keygen
            input_is_encrypt = args.encrypt
            input_is_keyfile = args.keyfile
            file_identifier = ''
            print_arg_str = "Invalid.\nTo generate binary --conf, --values, --prefix and --size arguments are mandatory.\
            \nTo generate encryption keys --keygen argument is mandatory."
            print_encrypt_arg_str = "Missing parameter. Enter --keygen or --keyfile."

            if args.fileid:
                file_identifier = args.fileid

            if input_config_file and input_is_encrypt.lower() == 'true' and input_is_keygen.lower() == 'true' and input_is_keyfile:
                sys.exit('Invalid. Cannot provide both --keygen and --keyfile argument together.')

            nvs_partition_gen.check_input_args(input_config_file, input_values_file, part_size, input_is_keygen,
                                               input_is_encrypt, input_is_keyfile, input_version, print_arg_str,
                                               print_encrypt_arg_str, output_dir_path)

            if not input_config_file and input_is_keygen:
                if input_is_encrypt == 'true':
                    sys.exit("Invalid.\nOnly --keyfile and --outdir arguments allowed.\n")
                # Generate Key Only
                nvs_partition_gen.nvs_part_gen(input_filename=input_config_file, output_filename=input_values_file,
                                               input_part_size=part_size, is_key_gen=input_is_keygen,
                                               encrypt_mode=input_is_encrypt, key_file=input_is_keyfile,
                                               version_no=input_version, output_dir=output_dir_path)
                exit(0)

            if not (input_config_file and input_values_file and target_file_name_prefix and part_size):
                sys.exit(print_arg_str)

        keys_in_values_file = []
        keys_in_config_file = []
        config_data_to_write = []
        key_value_data = []
        csv_file_list = []
        keys_repeat = []
        is_empty_line = False
        files_created = False
        file_identifier_value = '0'
        output_target_dir = ''
        target_values_file = None
        output_file_prefix = None

        # Verify config file is not empty
        if os.stat(input_config_file).st_size == 0:
            raise SystemExit("Oops...config file: %s is empty." % input_config_file)

        # Verify values file is not empty
        if os.stat(input_values_file).st_size == 0:
            raise SystemExit("Oops...values file: %s is empty." % input_values_file)

        # Verify config file does not have empty lines
        csv_config_file = open(input_config_file,'r')
        try:
            config_file_reader = csv.reader(csv_config_file, delimiter=',')
            for config_data in config_file_reader:
                for data in config_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line:
                    raise SystemExit("Oops...config file: %s cannot have empty lines. " % input_config_file)
                if not config_data:
                    raise SystemExit("Oops...config file: %s cannot have empty lines." % input_config_file)

            csv_config_file.seek(0)

            # Extract keys from config file
            for config_data in config_file_reader:
                if 'namespace' not in config_data:
                    keys_in_config_file.append(config_data[0])
                if 'REPEAT' in config_data:
                    keys_repeat.append(config_data[0])

            csv_config_file.close()
        except Exception as e:
            print(e)
        finally:
            csv_config_file.close()

        is_empty_line = False
        # Verify values file does not have empty lines
        csv_values_file = open(input_values_file, 'r')
        try:
            values_file_reader = csv.reader(csv_values_file, delimiter=',')
            for values_data in values_file_reader:
                for data in values_data:
                    empty_line = data.strip()
                    if empty_line is '':
                        is_empty_line = True
                    else:
                        is_empty_line = False
                        break
                if is_empty_line:
                    raise SystemExit("Oops...values file: %s cannot have empty lines." % input_values_file)
                if not values_data:
                    raise SystemExit("Oops...values file: %s cannot have empty lines." % input_values_file)

            csv_values_file.seek(0)

            # Extract keys from values file
            keys_in_values_file = next(values_file_reader)

            csv_values_file.close()
        except Exception as e:
            print(e)
            exit(1)
        finally:
            csv_values_file.close()

        # Verify file identifier exists in values file
        if file_identifier:
            if file_identifier not in keys_in_values_file:
                raise SystemExit('Oops...target_file_identifier: %s does not exist in values file.\n' % file_identifier)

        # Verify data in the input_config_file and input_values_file
        verify_data_in_file(input_config_file, input_values_file, keys_in_config_file,
                            keys_in_values_file, keys_repeat)

        # Add config data per namespace to `config_data_to_write` list
        config_data_to_write = add_config_data_per_namespace(input_config_file)

        try:
            with open(input_values_file, 'r') as csv_values_file:
                values_file_reader = csv.reader(csv_values_file, delimiter=',')
                keys = next(values_file_reader)

            filename, file_ext = os.path.splitext(input_values_file)
            target_filename = filename + "_created" + file_ext
            if keys_repeat:
                target_values_file = set_repeat_value(keys_repeat, keys, input_values_file, target_filename)
            else:
                target_values_file = input_values_file

            csv_values_file = open(target_values_file, 'r')

            values_file_reader = csv.reader(csv_values_file, delimiter=',')
            next(values_file_reader)
            for values_data_line in values_file_reader:
                key_value_data = list(zip_longest(keys_in_values_file,values_data_line))

                # Get file identifier value from values file
                file_identifier_value = get_fileid_val(file_identifier, keys_in_config_file,
                                                       keys_in_values_file, values_data_line, key_value_data, file_identifier_value)

                key_value_pair = key_value_data[:]

                # Create new directory(if doesn't exist) to store csv file generated
                output_target_dir = create_dir("csv/", output_dir_path)

                # Verify if output csv file does not exist
                csv_filename = target_file_name_prefix + "-" + file_identifier_value + ".csv"
                csv_file_list.append(csv_filename)
                output_csv_file = output_target_dir + csv_filename
                if os.path.isfile(output_csv_file):
                    raise SystemExit("Target csv file: %s already exists.`" % output_csv_file)

                # Add values corresponding to each key to csv target file
                add_data_to_file(config_data_to_write, key_value_pair, output_csv_file)

                # Create new directory(if doesn't exist) to store bin file generated
                output_target_dir = create_dir("bin/", output_dir_path)

                # Verify if output bin file does not exist
                # todo for keys
                output_file_prefix = target_file_name_prefix + "-" + file_identifier_value
                output_bin_file = output_target_dir + output_file_prefix + ".bin"
                if os.path.isfile(output_bin_file):
                    raise SystemExit("Target csv file: %s already exists.`" % output_bin_file)

                # Create output csv and bin file
                if input_is_keygen.lower() == 'true' and input_is_keyfile:
                    input_is_keyfile = os.path.basename(input_is_keyfile)
                nvs_partition_gen.nvs_part_gen(input_filename=output_csv_file, output_filename=output_bin_file,
                                               input_part_size=part_size, is_key_gen=input_is_keygen,
                                               encrypt_mode=input_is_encrypt, key_file=input_is_keyfile,
                                               version_no=input_version, encr_key_prefix=output_file_prefix, output_dir=output_dir_path)
                print("CSV Generated: ", str(output_csv_file))

                files_created = True

            csv_values_file.close()
        except Exception as e:
            print(e)
            exit(1)
        finally:
            csv_values_file.close()
        return csv_file_list, files_created, target_values_file

    except ValueError as err:
        print(err)
    except Exception:
        raise