Beispiel #1
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)
		crts = self._read_certificates(self._args.crtfile)

		self._hd = HexDump()
		local_vars = {
			"x509sak":	x509sak,
			"derdec":	lambda data: pyasn1.codec.der.decoder.decode(data)[0],
			"derenc":	pyasn1.codec.der.encoder.encode,
			"berenc":	pyasn1.codec.ber.encoder.encode,
			"crts":		crts,
			"c":		crts[0] if (len(crts) > 0) else None,
			"a":		crts[0].asn1 if (len(crts) > 0) else None,
			"unpkcs1":	PaddingTools.unpad_pkcs1,
			"decrsa":	self._decrypt_selfsigned_rsa_signature,
			"md5":		lambda payload: hashlib.md5(payload).digest(),
			"sha1":		lambda payload: hashlib.sha1(payload).digest(),
			"sha256":	lambda payload: hashlib.sha256(payload).digest(),
			"sha384":	lambda payload: hashlib.sha384(payload).digest(),
			"sha512":	lambda payload: hashlib.sha512(payload).digest(),
			"hd":		self._hd.dump,
			"ap":		self._asn1parse,
			"write_py":	self._write_py,
			"safedec":	ASN1Tools.safe_decode,
		}

		console = DebugConsole(local_vars = local_vars)
		for command in self._args.execute:
			print(">>> %s" % (command))
			console.runcode(command)
		if len(self._args.execute) > 0:
			print()
		if not self._args.no_interact:
			console.interact()
Beispiel #2
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        camgr = CAManager(self._args.capath)
        camgr.create_crl(self._args.crl_filename,
                         validity_days=self._args.validity_days,
                         signing_hash=self._args.hashfnc)
Beispiel #3
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)

		self._pool = CertificatePool()
		self._pool.load_sources(self._args.crtsource)
		self._log.debug("Loaded a total of %d unique certificates in trust store.", self._pool.certificate_count)

		if self._args.format is not None:
			file_format = self._args.format
		else:
			file_format = os.path.splitext(self._args.outfile)[1].lstrip(".")

		self._active_substitutions = { name: getattr(self, "_substitute_" + name) for name in self.get_supported_substitutions() }
		self._get_cert_attributes = getattr(self, "_get_cert_attributes_" + self._args.color_scheme, None)
		if self._get_cert_attributes is None:
			raise LazyDeveloperException("Color scheme '%s' is unsupported. This is a bug." % (self._args.color_scheme))

		# Load color palettes
		self._palette_traffic = AdvancedColorPalette(JSONTools.load_internal("x509sak.data", "palettes.json")["traffic"])
		self._palette_flatui = AdvancedColorPalette(JSONTools.load_internal("x509sak.data", "palettes.json")["flatui"])

		if file_format == "dot":
			with open(self._args.outfile, "w") as dotfile:
				self._write_dotfile(dotfile)
		elif file_format in [ "ps", "png", "pdf" ]:
			with tempfile.NamedTemporaryFile("w", prefix = "graph_", suffix = ".dot") as dotfile, open(self._args.outfile, "wb") as outfile:
				self._write_dotfile(dotfile)
				cmd = [ "dot", "-T%s" % (file_format), dotfile.name ]
				subprocess.check_call(cmd, stdout = outfile)
		else:
			raise UnknownFormatException("Unknown file format: \"%s\"" % (file_format))
Beispiel #4
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)
        self._pool = CertificatePool()
        self._pool.load_sources(self._args.crtsource)
        self._log.debug(
            "Loaded a total of %d unique certificates in trust store.",
            self._pool.certificate_count)

        for cert in sorted(self._pool):
            if self._cert_matches(cert):
                cert.dump_pem()
Beispiel #5
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)

		certs = X509Certificate.read_pemfile(self._args.crt_filename)
		if not certs[0].is_selfsigned:
			raise InvalidInputException("First certificate in chain (%s) is not self-signed." % (certs[0]))
		for (cert_id, (issuer, subject)) in enumerate(zip(certs, certs[1:]), 1):
			if not subject.signed_by(issuer):
				raise InvalidInputException("Certificate %d in file (%s) is not issuer for certificate %d (%s)." % (cert_id, issuer, cert_id + 1, subject))

		self._log.debug("Chain of %d certificates to forge.", len(certs))
		self._forge_cert(0, certs[0], 0, certs[0])
		for (cert_subject_id, (issuer, subject)) in enumerate(zip(certs, certs[1:]), 1):
			self._forge_cert(cert_subject_id - 1, issuer, cert_subject_id, subject)
Beispiel #6
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if (not self._args.force) and os.path.exists(self._args.outfile):
            raise UnfulfilledPrerequisitesException(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.outfile))

        self._prime_db = PrimeDB(self._args.prime_db,
                                 generator_program=self._args.generator)
        q = self._prime_db.get(args.N_bits)
        if self._args.verbose >= 1:
            print("Chosen q = 0x%x" % (q))

        bit_diff = args.L_bits - q.bit_length()
        while True:
            r = NumberTheory.randint_bits(bit_diff, two_msb_set=True)
            p = (r * q) + 1
            if NumberTheory.is_probable_prime(p):
                break
        if self._args.verbose >= 1:
            print("Chosen p = 0x%x" % (p))

        assert (q.bit_length() == args.N_bits)
        assert (p.bit_length() == args.L_bits)
        assert ((p - 1) % q == 0)

        # Non-verifiable method of generating g, see A.2.1 of FIPS 186-4, pg. 41
        e = (p - 1) // q
        while True:
            h = random.randint(2, p - 2)
            g = pow(h, e, p)
            if g == 1:
                continue
            break

        if self._args.verbose >= 1:
            print("Chosen g = 0x%x" % (g))

        dsa_parameters = DSAParameters.create(p=p, q=q, g=g)
        dsa_parameters.write_pemfile(self._args.outfile)
Beispiel #7
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)

		# Plausibilize input parameters
		kwargs_checker = KwargsChecker(optional_arguments = set(self._DER_CLASSES.keys()))
		kwargs_checker.check(self._args.include_dertype, hint = "DER classes to be included")
		kwargs_checker.check(self._args.exclude_dertype, hint = "DER classes to be excluded")

		# Plausibilize output directory
		if os.path.exists(self._args.outdir) and (not self._args.force):
			raise Exception("Directory %s already exists. Remove it first or use --force." % (self._args.outdir))
		try:
			os.makedirs(self._args.outdir)
		except FileExistsError:
			pass

		# Determine active DERHandler classes
		if len(self._args.include_dertype) == 0:
			active_der_types = set(self._DER_CLASSES.keys())
		else:
			active_der_types = set(self._args.include_dertype)
		active_der_types -= set(self._args.exclude_dertype)
		self._active_der_types = [ self._DER_CLASSES[class_name] for class_name in active_der_types ]
		self._active_der_types.sort(key = lambda handler: (handler.precedence, handler.data_type))

		self._stats = ActionScrapeStats(self._args)
		self._stats.set_active_der_types([ handler_class.data_type for handler_class in self._active_der_types ])

		self._matches = Intervals()
		self._hashes = set()
		engine = ScrapeEngine(self._args.filename)
		if not self._args.no_pem:
			engine.search(self._find_pem, b"-----BEGIN ", min_length = 52, max_length = 32 * 1024)
		if (not self._args.no_der) and (len(self._active_der_types) > 0):
			self._log.debug("Looking for %d DER type(s): %s", len(self._active_der_types), ", ".join(handler.data_type for handler in self._active_der_types))
			engine.search(self._find_der, bytes.fromhex("30"), min_length = 2, max_length = 32 * 1024)
		end_offset = engine.commence(start_offset = self._args.seek_offset, length = self._args.analysis_length, progress_callback = self._progress_callback)
		self._stats.finish(end_offset)
		self._stats.dump()
		if self._args.write_json is not None:
			JSONTools.write_to_file(self._stats.as_dict(), self._args.write_json)
Beispiel #8
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if args.encoding == "hex":
            with open(args.filename) as f:
                data = bytes.fromhex(f.read().replace("\n", ""))
        elif args.encoding == "bin":
            with open(args.filename, "rb") as f:
                data = f.read()
        else:
            raise NotImplementedError(args.encoding)

        if self._args.verbose >= 1:
            hd = HexDump()
            hd.dump(data)

        self._pp = pprint.PrettyPrinter(width=180)
        decoder = TLSMessageDecoder(side=args.side)
        decoder.add_hook("alert", self._msg_alert)
        decoder.add_hook("handshake", self._msg_handshake)
        decoder.put(data)
Beispiel #9
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        structure = x509sak.estimate.JudgementStructure.create_judgement_structure(
            verbose=self._args.verbose >= 1)
        extended_enum_class = structure.create_extended_enum_class()
        if self._args.action == "list":
            codes = [enum_code.value for enum_code in extended_enum_class]
            for jc in sorted(codes):
                print(jc.name)
        elif self._args.action == "dump":
            structure.root.dump()
        elif self._args.action == "inherit":
            for (target_attribute, inherited_codes) in sorted(
                    extended_enum_class.inheritance.items()):
                print("%s:" % (target_attribute))
                for (base_name, codepoint) in sorted(inherited_codes.items()):
                    print("    %-60s  %s" % (base_name, codepoint.name))
                print()
        else:
            raise NotImplementedError(self._args.action)
Beispiel #10
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)
		if len(args.hash_alg) == 0:
			hash_fncs = self.get_default_hash_fncs()
		elif ("all" in args.hash_alg):
			hash_fncs = self.get_supported_hash_fncs()
		else:
			hash_fncs = set(args.hash_alg)

		with open(args.filename, "rb") as f:
			f.seek(args.seek_offset)
			self._data = f.read(args.analysis_length)

		if len(self._args.variable_hash_length) == 0:
			hash_lengths = self.get_default_variable_hash_lengths_bits()
		else:
			hash_lengths = self._args.variable_hash_length
		if any((value % 8) != 0 for value in hash_lengths):
			raise InvalidInputException("Not all hash lengths are evenly divisible by 8: %s" % (", ".join("%d" % (value) for value in hash_lengths)))
		if any((value < 8) for value in hash_lengths):
			raise InvalidInputException("Hash length must be at least 8 bit, not all are: %s" % (", ".join("%d" % (value) for value in hash_lengths)))

		valid_search_chars = set("abcdefABCDEF0123456789")
		if (self._args.search is not None) and (len(set(self._args.search) - valid_search_chars) > 0):
			raise InvalidInputException("Search pattern may only contain hexadecimal characters, but '%s' was given." % (self._args.search))

		self._search = (self._args.search or "").lower()

		t0 = time.time()
		hash_fncs_by_name = { hashfnc.name: hashfnc for hashfnc in self.get_all_supported_hash_fncs() }
		for hash_fnc_name in sorted(hash_fncs):
			hash_fnc = hash_fncs_by_name[hash_fnc_name]
			if not hash_fnc.variable_output_length:
				self._run_hash_function(hash_fnc_name)
			else:
				for hash_len_bits in hash_lengths:
					self._run_hash_function(hash_fnc_name, output_length_bits = hash_len_bits)

		t1 = time.time()
		self._log.debug("Hash search took %.1f secs.", t1 - t0)
Beispiel #11
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if os.path.exists(self._args.crt_filename) and (not self._args.force):
            raise Exception(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.crt_filename))

        camgr = CAManager(self._args.capath)
        custom_x509_extensions = {
            custom_x509_extension.key: custom_x509_extension.value
            for custom_x509_extension in self._args.extension
        }
        camgr.sign_csr(self._args.csr_filename,
                       self._args.crt_filename,
                       extension_template=self._args.template,
                       custom_x509_extensions=custom_x509_extensions,
                       subject_dn=self._args.subject_dn,
                       validity_days=self._args.validity_days,
                       signing_hash=self._args.hashfnc,
                       subject_alternative_dns_names=self._args.san_dns,
                       subject_alternative_ip_addresses=self._args.san_ip)
Beispiel #12
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        tls_version = TLSVersion.ProtocolTLSv1_2
        self._conn = TLSClientConnection.tcp_connect(
            tls_version=tls_version,
            servername=args.servername,
            port=args.port)
        if self._args.starttls is None:
            pass
        elif self._args.starttls == "smtp":
            self._starttls_smtp(self._conn.transport)
        else:
            raise NotImplementedError(self._args.starttls)
        self._conn.decoder.add_hook("handshake", self._recv_handshake)
        self._conn.decoder.add_hook("record_layer", self._recv_record_layer)

        chh = ClientHelloHelper()
        client_hello = chh.create(server_name=args.servername)
        frame = ClientHelloPkt.pack(client_hello)
        self._conn.send_handshake(frame)
        self._conn.receive()
Beispiel #13
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        sys.setrecursionlimit(10000)
        self._cg = CertGenerator.instantiate(self._args.tcname + ".ader")
        if self._args.list_parameters:
            for (name, values) in sorted(self._cg.parameters):
                print("%-30s %s" % (name, ", ".join(sorted(values))))
            sys.exit(0)

        template_parameters = {}
        for parameter in self._args.parameter:
            (key, value) = parameter.split("=", maxsplit=1)
            if value == "*":
                template_parameters[key] = self._cg.get_choices(key)
            else:
                template_parameters[key] = [value]

        for (name, values) in self._cg.parameters:
            if name not in template_parameters:
                template_parameters[name] = values

        with contextlib.suppress(FileExistsError):
            os.makedirs(self._args.output_dir)

        template_parameters = list(template_parameters.items())
        keys = [key for (key, values) in template_parameters]
        values = [values for (key, values) in template_parameters]
        self._tcs = []
        for concrete_values in itertools.product(*values):
            concrete_values = dict(zip(keys, concrete_values))
            try:
                self._render(concrete_values)
            except subprocess.CalledProcessError as e:
                print("Failed: %s (%s)" % (str(concrete_values), str(e)))

        self._tcs.sort()
        self._print_tcs()
Beispiel #14
0
	def __init__(self, cmdname, args):
		BaseAction.__init__(self, cmdname, args)
		if self._args.parent_certificate is None:
			parent_ca_cert = None
		else:
			if self._args.in_format == "dercrt":
				# CA cert in DER form if host certificate is also in DER form
				crt = X509Certificate.read_derfile(self._args.parent_certificate)
			else:
				# CA cert in PEM form for all other cases
				crt = X509Certificate.read_pemfile(self._args.parent_certificate)[0]
			parent_ca_cert = CertificateAnalyzer.CertSource(source = self._args.parent_certificate, source_type = "pemcrt" if (self._args.in_format != "dercrt") else "dercrt", crts = [ crt ])

		if self._args.in_format in [ "pemcrt", "dercrt", "host" ]:
			crt_sources = self._load_certificates()

			analysis_params = {
				"include_raw_data":	self._args.include_raw_data,
				"fast_rsa":			self._args.fast_rsa,
				"purposes":			self._args.purpose,
				"entity_name":		self._args.server_name,
			}
			if (len(analysis_params["purposes"]) == 0) and (self._args.in_format == "host") and (not self._args.no_automatic_host_check):
				analysis_params["purposes"].append("tls-server")
			if (analysis_params["entity_name"] is None) and (self._args.in_format == "host") and (not self._args.no_automatic_host_check):
				hostname = crt_sources[0].source.split(":")[0]
				analysis_params["entity_name"] = hostname
			crt_analyzer = CertificateAnalyzer(**analysis_params)

			analysis = crt_analyzer.analyze(crt_sources, parent_ca_cert)
		elif self._args.in_format == "json":
			analysis = self._read_json()
		else:
			raise NotImplementedError(self._args.in_format)

		output = self._args.output or "-"
		with FileWriter(output, "w") as f:
			self._show_analysis(f, analysis)
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        if (not self._args.force) and os.path.exists(self._args.outfile):
            raise UnfulfilledPrerequisitesException(
                "File/directory %s already exists. Remove it first or use --force."
                % (self._args.outfile))

        if not self._args.gcd_n_phi_n:
            self._primetype = "2msb"
            self._p_bitlen = self._args.bitlen // 2
            self._q_bitlen = self._args.bitlen - self._p_bitlen
        else:
            self._primetype = "3msb"
            self._p_bitlen = self._args.bitlen // 3
            self._q_bitlen = self._args.bitlen - (2 * self._p_bitlen) - 1

        if (self._args.close_q) and (self._p_bitlen != self._q_bitlen):
            raise UnfulfilledPrerequisitesException(
                "Generating a close-q keypair with a %d modulus does't work, because p would have to be %d bit and q %d bit. Choose an even modulus bitlength."
                % (self._args.bitlen, self._p_bitlen, self._q_bitlen))

        if self._args.q_stepping < 1:
            raise InvalidInputException(
                "q-stepping value must be greater or equal to 1, was %d." %
                (self._args.q_stepping))

        self._log.debug("Selecting %s primes with p = %d bit and q = %d bit.",
                        self._primetype, self._p_bitlen, self._q_bitlen)

        self._prime_db = PrimeDB(self._args.prime_db,
                                 generator_program=self._args.generator)
        p = None
        q = None
        while True:
            if p is None:
                p = self._prime_db.get(bitlen=self._p_bitlen,
                                       primetype=self._primetype)
                q_generator = self._select_q(p)
            if q is None:
                q = next(q_generator)
            if self._args.gcd_n_phi_n:
                # q = (2 * r * p) + 1
                r = q
                q = 2 * r * p + 1
                if not NumberTheory.is_probable_prime(q):
                    q = None
                    continue

            # Always make p the smaller factor
            if p > q:
                (p, q) = (q, p)

            n = p * q
            if self._args.public_exponent == -1:
                e = random.randint(2, n - 1)
            else:
                e = self._args.public_exponent

            if self._args.carmichael_totient:
                totient = NumberTheory.lcm(p - 1, q - 1)
            else:
                totient = (p - 1) * (q - 1)
            gcd = NumberTheory.gcd(totient, e)
            if self._args.accept_unusable_key or (gcd == 1):
                break
            else:
                # Pair (phi(n), e) wasn't acceptable.
                self._log.debug("gcd(totient, e) was %d, retrying.", gcd)
                if self._args.public_exponent != -1:
                    # Public exponent e is fixed, need to choose another q.
                    if p.bit_length() == q.bit_length():
                        # Can re-use q as next p
                        (p, q) = (q, None)
                        q_generator = self._select_q(p)
                    else:
                        # When they differ in length, need to re-choose both values
                        (p, q) = (None, None)

        rsa_keypair = RSAPrivateKey.create(
            p=p,
            q=q,
            e=e,
            swap_e_d=self._args.switch_e_d,
            valid_only=not self._args.accept_unusable_key,
            carmichael_totient=self._args.carmichael_totient)
        rsa_keypair.write_pemfile(self._args.outfile)
        if self._args.verbose >= 1:
            diff = q - p
            print("Generated %d bit RSA key:" % (rsa_keypair.n.bit_length()))
            print("p = 0x%x" % (rsa_keypair.p))
            if not self._args.gcd_n_phi_n:
                print("q = 0x%x" % (rsa_keypair.q))
            else:
                print("q = 2 * r * p + 1 = 0x%x" % (rsa_keypair.q))
                print("r = 0x%x" % (r))

            print("phi(n) = 0x%x" % (rsa_keypair.phi_n))
            print("lambda(n) = 0x%x" % (rsa_keypair.lambda_n))
            print("phi(n) / lambda(n) = gcd(p - 1, q - 1) = %d" %
                  (rsa_keypair.phi_n // rsa_keypair.lambda_n))
            gcd_n_phin = NumberTheory.gcd(rsa_keypair.n, rsa_keypair.phi_n)
            if gcd_n_phin == rsa_keypair.p:
                print("gcd(n, phi(n)) = p")
            else:
                print("gcd(n, phi(n)) = 0x%x" % (gcd_n_phin))
            if self._args.close_q:
                print("q - p = %d (%d bit)" % (diff, diff.bit_length()))
            print("n = 0x%x" % (rsa_keypair.n))
            print("d = 0x%x" % (rsa_keypair.d))
            print("e = 0x%x" % (rsa_keypair.e))
Beispiel #16
0
 def __init__(self, cmdname, args):
     BaseAction.__init__(self, cmdname, args)
     if self._args.public_key:
         key = PublicKey.read_pemfile(self._args.key_filename)[0]
         if key.pk_alg.value.cryptosystem == Cryptosystems.RSA:
             print("# %d bit RSA public key (ID %s)" %
                   (key.n.bit_length(), key.keyid().hex()))
             print("n = 0x%x" % (key.n))
             print("e = 0x%x" % (key.e))
         elif key.pk_alg.value.cryptosystem == Cryptosystems.ECC_ECDSA:
             print("# ECC public key on %s (key ID %s)" %
                   (key.curve.name, key.keyid().hex()))
             print("curve_name = \"%s\"" % (key.curve.name))
             print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y))
         elif key.pk_alg.value.cryptosystem == Cryptosystems.ECC_EdDSA:
             print(
                 "# ECC public key on Twisted Edwards curve %s %s prehashing (key ID %s)"
                 % (key.curve.name, "with" if key.prehash else "without",
                    key.keyid().hex()))
             print("curve_name = \"%s\"" % (key.curve.name))
             print("prehash = %s" % (key.prehash))
             print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y))
         else:
             raise NotImplementedError(key.pk_alg.value.cryptosystem)
     else:
         if self._args.key_type == "rsa":
             key = RSAPrivateKey.read_pemfile(self._args.key_filename)[0]
             print("# %d bit RSA private key (ID %s)" %
                   (key.n.bit_length(), key.pubkey.keyid().hex()))
             print("p = 0x%x" % (key.p))
             print("q = 0x%x" % (key.q))
             print("n = p * q")
             print("e = 0x%x" % (key.e))
             print("d = 0x%x" % (key.d))
         elif self._args.key_type == "ecc":
             key = ECPrivateKey.read_pemfile(self._args.key_filename)[0]
             print("# ECC private key on %s (key ID %s)" %
                   (key.curve.name, key.pubkey.keyid().hex()))
             print("curve_name = \"%s\"" % (key.curve.name))
             print("d = 0x%x" % (key.d))
             print("(x, y) = (0x%x, 0x%x)" % (key.x, key.y))
         elif self._args.key_type == "eddsa":
             key = EDPrivateKey.read_pemfile(self._args.key_filename)[0]
             pubkey = key.pubkey
             print(
                 "# ECC private key on Twisted Edwards curve %s %s prehashing (key ID %s)"
                 % (key.curve.name, "with" if key.prehash else "without",
                    pubkey.keyid().hex()))
             print("curve_name = \"%s\"" % (key.curve.name))
             print("prehash = %s" % (key.prehash))
             print("priv = bytes.fromhex(\"%s\")" % (key.priv.hex()))
             print("hashfnc = hashlib.new(\"%s\")" %
                   (key.curve.expand_hashfnc))
             print(
                 "(expand_bitwise_and, expand_bitwise_or) = (0x%x, 0x%x)" %
                 (key.curve.expand_bitwise_and,
                  key.curve.expand_bitwise_or))
             print("a = 0x%x" % (key.scalar))
             print("(x, y) = (0x%x, 0x%x)" % (pubkey.x, pubkey.y))
         else:
             raise NotImplementedError(self._args.key_type)
Beispiel #17
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)
        if (self._args.private_key
                is not None) and (self._args.outform != "pkcs12"):
            raise InvalidUsageException(
                "A private key will only be exported with a PKCS#12 output file."
            )
        if self._args.outform != "pkcs12":
            if self._args.pkcs12_legacy_crypto:
                raise InvalidUsageException(
                    "Specifying PKCS#12 legacy crypto while not using PKCS#12 output format has no effect."
                )
            if self._args.pkcs12_no_passphrase:
                raise InvalidUsageException(
                    "Specifying no PKCS#12 passphrase while not using PKCS#12 output format has no effect."
                )
            if self._args.pkcs12_passphrase_file is not None:
                raise InvalidUsageException(
                    "Specifying a PKCS#12 passphrase while not using PKCS#12 output format has no effect."
                )
        else:
            if (self._args.pkcs12_legacy_crypto
                    or self._args.pkcs12_no_passphrase
                    or self._args.pkcs12_passphrase_file
                    is not None) and (self._args.private_key is None):
                raise InvalidUsageException(
                    "Specifying any PKCS#12 passphrase/crypto options when not including a private key makes no sense."
                )

        self._pool = CertificatePool()
        self._load_truststore()
        if self._args.inform == "pem":
            certs = X509Certificate.read_pemfile(self._args.crtfile)
            if not self._args.dont_trust_crtfile:
                self._pool.add_certificates(certs)
            cert = certs[0]
        elif self._args.inform == "der":
            cert = X509Certificate.read_derfile(self._args.crtfile)
        else:
            raise NotImplementedError("inform", self._args.inform)
        chain = self._pool.find_chain(cert)
        if (chain.root is None) and (not self._args.allow_partial_chain):
            raise InvalidUsageException(
                "Could not build full chain for certificate %s and partial chain matches are disallowed."
                % (self._args.crtfile))

        if self._args.outform == "rootonly":
            if chain.root is None:
                print("Root certificate output requested, but none found.",
                      file=sys.stderr)
                sys.exit(1)
            certs = [chain.root]
        elif self._args.outform == "intermediates":
            certs = list(chain.chain)
        elif self._args.outform in ["fullchain", "multifile", "pkcs12"]:
            certs = list(chain.full_chain)
        elif self._args.outform == "all-except-root":
            certs = list(chain.full_chain)
            if chain.root is not None:
                certs = certs[:-1]
        else:
            raise NotImplementedError("outform", self._args.outform)

        if not self._args.order_leaf_to_root:
            certs = certs[::-1]

        for (cid, cert) in enumerate(certs):
            self._log.debug("Cert %d: %s", cid, cert)

        if self._args.outform == "multifile":
            for (cid, cert) in enumerate(certs):
                filename = self._args.outfile % (cid)
                with open(filename, "w") as f:
                    print(cert.to_pem_data(), file=f)
        elif self._args.outform == "pkcs12":
            if self._args.private_key is not None:
                if self._args.pkcs12_no_passphrase:
                    passphrase = None
                else:
                    if self._args.pkcs12_passphrase_file is not None:
                        with open(self._args.pkcs12_passphrase_file) as f:
                            passphrase = f.readline()
                    else:
                        passphrase = PassphraseGenerator.non_ambiguous(
                        ).gen_passphrase(80)
                        print("Passphrase: %s" % (passphrase), file=sys.stderr)
            else:
                passphrase = None
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename=self._args.private_key) if (self._args.private_key
                                                     is not None) else None
            pkcs12 = OpenSSLTools.create_pkcs12(
                certificates=certs,
                private_key_storage=private_key_storage,
                modern_crypto=not self._args.pkcs12_legacy_crypto,
                passphrase=passphrase)
            if self._args.outfile is None:
                # Write to stdout
                sys.stdout.buffer.write(pkcs12)
            else:
                # Write to file, binary
                with open(self._args.outfile, "wb") as f:
                    f.write(pkcs12)
        else:
            if self._args.outfile is not None:
                with open(self._args.outfile, "w") as f:
                    self._print_certs(f, certs)
            else:
                self._print_certs(sys.stdout, certs)
Beispiel #18
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)
        if self._args.force:
            try:
                os.unlink(self._args.capath)
            except (IsADirectoryError, FileNotFoundError):
                pass
            try:
                shutil.rmtree(self._args.capath)
            except FileNotFoundError:
                pass
        else:
            if os.path.exists(self._args.capath):
                raise UnfulfilledPrerequisitesException(
                    "File/directory %s already exists. Remove it first or use --force."
                    % (self._args.capath))

        os.makedirs(self._args.capath)
        os.chmod(self._args.capath, 0o700)

        camgr = CAManager(self._args.capath)
        custom_x509_extensions = {
            custom_x509_extension.key: custom_x509_extension.value
            for custom_x509_extension in self._args.extension
        }
        if (self._args.gen_keyspec
                is not None) or ((self._args.gen_keyspec is None) and
                                 (self._args.hardware_key is None)):
            # We need to generate a key.
            if self._args.gen_keyspec is not None:
                keyspec = self._args.gen_keyspec
            else:
                # Cannot default to this in argparse because it's part of a
                # mutually exclusive group with hardware_key
                keyspec = KeySpecification.from_cmdline_str("ecc:secp384r1")
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.PEM_FILE,
                filename="CA.key",
                search_path=camgr.capath)
            OpenSSLTools.create_private_key(private_key_storage,
                                            keyspec=keyspec)
        else:
            # The key is stored in hardware.
            private_key_storage = PrivateKeyStorage(
                PrivateKeyStorageForm.HARDWARE_TOKEN,
                pkcs11uri=self._args.hardware_key,
                so_search_path=self._args.pkcs11_so_search,
                module_so=self._args.pkcs11_module)

        signing_hash = self._args.hashfnc
        if private_key_storage.is_file_based:
            privkey = private_key_storage.load_private_key()
            if isinstance(privkey, EDPrivateKey):
                # We cannot specify a hash function for EdDSA because this
                # causes OpenSSL to fail with "elliptic curve
                # routines:pkey_ecd_ctrl:invalid digest type" -- for EdDSA, the
                # hash algorithms are implied
                signing_hash = None

        camgr.create_ca_structure(
            private_key_storage=private_key_storage,
            unique_subject=not self._args.allow_duplicate_subjects)
        if self._args.parent_ca is None:
            # Self-signed root CA
            camgr.create_selfsigned_ca_cert(
                subject_dn=self._args.subject_dn,
                validity_days=self._args.validity_days,
                custom_x509_extensions=custom_x509_extensions,
                signing_hash=signing_hash,
                serial=self._args.serial)

            # Create certificate chain file that only consists of our
            # self-signed certificate
            shutil.copy(self._args.capath + "/CA.crt",
                        self._args.capath + "/chain.crt")
        else:
            # Intermediate CA
            if self._args.serial is not None:
                raise InvalidUsageException(
                    "Can only specify certificate serial number when creating self-signed root CA certificate."
                )
            with tempfile.NamedTemporaryFile("w", prefix="ca_",
                                             suffix=".csr") as csr:
                camgr.create_ca_csr(csr_filename=csr.name,
                                    subject_dn=self._args.subject_dn)
                parent_ca = CAManager(self._args.parent_ca)
                parent_ca.sign_csr(
                    csr.name,
                    camgr.root_crt_filename,
                    subject_dn=self._args.subject_dn,
                    validity_days=self._args.validity_days,
                    custom_x509_extensions=custom_x509_extensions,
                    extension_template="ca",
                    signing_hash=signing_hash)

            # Create a certificate chain by appending the parent chain to our certificate
            if os.path.isfile(self._args.parent_ca + "/chain.crt"):
                with open(self._args.parent_ca +
                          "/chain.crt") as parent_chainfile:
                    parent_chain = parent_chainfile.read()
                with open(self._args.capath +
                          "/CA.crt") as new_certificate_file:
                    new_certificate = new_certificate_file.read()
                with open(self._args.capath + "/chain.crt",
                          "w") as intermediate_chainfile:
                    intermediate_chainfile.write(parent_chain)
                    intermediate_chainfile.write(new_certificate)
Beispiel #19
0
    def __init__(self, cmdname, args):
        BaseAction.__init__(self, cmdname, args)

        camgr = CAManager(self._args.capath)
        camgr.revoke_crt(self._args.crt_filename)