1# SPDX-License-Identifier: GPL-2.0+
2# Copyright 2022 Google LLC
3#
4"""Bintool implementation for openssl
5
6openssl provides a number of features useful for signing images
7
8Documentation is at https://www.coreboot.org/CBFS
9
10Source code is at https://www.openssl.org/
11"""
12
13import hashlib
14
15from binman import bintool
16from u_boot_pylib import tools
17
18class Bintoolopenssl(bintool.Bintool):
19    """openssl tool
20
21    This bintool supports creating new openssl certificates.
22
23    It also supports fetching a binary openssl
24
25    Documentation about openssl is at https://www.openssl.org/
26    """
27    def __init__(self, name):
28        super().__init__(
29            name, 'openssl cryptography toolkit',
30            version_regex=r'OpenSSL (.*) \(', version_args='version')
31
32    def x509_cert(self, cert_fname, input_fname, key_fname, cn, revision,
33                  config_fname):
34        """Create a certificate
35
36        Args:
37            cert_fname (str): Filename of certificate to create
38            input_fname (str): Filename containing data to sign
39            key_fname (str): Filename of .pem file
40            cn (str): Common name
41            revision (int): Revision number
42            config_fname (str): Filename to write fconfig into
43
44        Returns:
45            str: Tool output
46        """
47        indata = tools.read_file(input_fname)
48        hashval = hashlib.sha512(indata).hexdigest()
49        with open(config_fname, 'w', encoding='utf-8') as outf:
50            print(f'''[ req ]
51distinguished_name     = req_distinguished_name
52x509_extensions        = v3_ca
53prompt                 = no
54dirstring_type         = nobmp
55
56[ req_distinguished_name ]
57CN                     = {cert_fname}
58
59[ v3_ca ]
60basicConstraints       = CA:true
611.3.6.1.4.1.294.1.3    = ASN1:SEQUENCE:swrv
621.3.6.1.4.1.294.1.34   = ASN1:SEQUENCE:sysfw_image_integrity
63
64[ swrv ]
65swrv = INTEGER:{revision}
66
67[ sysfw_image_integrity ]
68shaType                = OID:2.16.840.1.101.3.4.2.3
69shaValue               = FORMAT:HEX,OCT:{hashval}
70imageSize              = INTEGER:{len(indata)}
71''', file=outf)
72        args = ['req', '-new', '-x509', '-key', key_fname, '-nodes',
73                '-outform', 'DER', '-out', cert_fname, '-config', config_fname,
74                '-sha512']
75        return self.run_cmd(*args)
76
77    def fetch(self, method):
78        """Fetch handler for openssl
79
80        This installs the openssl package using the apt utility.
81
82        Args:
83            method (FETCH_...): Method to use
84
85        Returns:
86            True if the file was fetched and now installed, None if a method
87            other than FETCH_BIN was requested
88
89        Raises:
90            Valuerror: Fetching could not be completed
91        """
92        if method != bintool.FETCH_BIN:
93            return None
94        return self.apt_install('openssl')
95