1a8e1175bSopenharmony_ci#!/usr/bin/env python3
2a8e1175bSopenharmony_ci"""Generate server9-bad-saltlen.crt
3a8e1175bSopenharmony_ci
4a8e1175bSopenharmony_ciGenerate a certificate signed with RSA-PSS, with an incorrect salt length.
5a8e1175bSopenharmony_ci"""
6a8e1175bSopenharmony_ci
7a8e1175bSopenharmony_ci# Copyright The Mbed TLS Contributors
8a8e1175bSopenharmony_ci# SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9a8e1175bSopenharmony_ci
10a8e1175bSopenharmony_ciimport subprocess
11a8e1175bSopenharmony_ciimport argparse
12a8e1175bSopenharmony_cifrom asn1crypto import pem, x509, core #type: ignore #pylint: disable=import-error
13a8e1175bSopenharmony_ci
14a8e1175bSopenharmony_ciOPENSSL_RSA_PSS_CERT_COMMAND = r'''
15a8e1175bSopenharmony_ciopenssl x509 -req -CA {ca_name}.crt -CAkey {ca_name}.key -set_serial 24 {ca_password} \
16a8e1175bSopenharmony_ci    {openssl_extfile} -days 3650 -outform DER -in {csr}  \
17a8e1175bSopenharmony_ci    -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:{anounce_saltlen} \
18a8e1175bSopenharmony_ci    -sigopt rsa_mgf1_md:sha256
19a8e1175bSopenharmony_ci'''
20a8e1175bSopenharmony_ciSIG_OPT = \
21a8e1175bSopenharmony_ci    r'-sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:{saltlen} -sigopt rsa_mgf1_md:sha256'
22a8e1175bSopenharmony_ciOPENSSL_RSA_PSS_DGST_COMMAND = r'''openssl dgst -sign {ca_name}.key {ca_password} \
23a8e1175bSopenharmony_ci    -sigopt rsa_padding_mode:pss -sigopt rsa_pss_saltlen:{actual_saltlen} \
24a8e1175bSopenharmony_ci    -sigopt rsa_mgf1_md:sha256'''
25a8e1175bSopenharmony_ci
26a8e1175bSopenharmony_ci
27a8e1175bSopenharmony_cidef auto_int(x):
28a8e1175bSopenharmony_ci    return int(x, 0)
29a8e1175bSopenharmony_ci
30a8e1175bSopenharmony_ci
31a8e1175bSopenharmony_cidef build_argparser(parser):
32a8e1175bSopenharmony_ci    """Build argument parser"""
33a8e1175bSopenharmony_ci    parser.description = __doc__
34a8e1175bSopenharmony_ci    parser.add_argument('--ca-name', type=str, required=True,
35a8e1175bSopenharmony_ci                        help='Basename of CA files')
36a8e1175bSopenharmony_ci    parser.add_argument('--ca-password', type=str,
37a8e1175bSopenharmony_ci                        required=True, help='CA key file password')
38a8e1175bSopenharmony_ci    parser.add_argument('--csr', type=str, required=True,
39a8e1175bSopenharmony_ci                        help='CSR file for generating certificate')
40a8e1175bSopenharmony_ci    parser.add_argument('--openssl-extfile', type=str,
41a8e1175bSopenharmony_ci                        required=True, help='X905 v3 extension config file')
42a8e1175bSopenharmony_ci    parser.add_argument('--anounce_saltlen', type=auto_int,
43a8e1175bSopenharmony_ci                        required=True, help='Announced salt length')
44a8e1175bSopenharmony_ci    parser.add_argument('--actual_saltlen', type=auto_int,
45a8e1175bSopenharmony_ci                        required=True, help='Actual salt length')
46a8e1175bSopenharmony_ci    parser.add_argument('--output', type=str, required=True)
47a8e1175bSopenharmony_ci
48a8e1175bSopenharmony_ci
49a8e1175bSopenharmony_cidef main():
50a8e1175bSopenharmony_ci    parser = argparse.ArgumentParser()
51a8e1175bSopenharmony_ci    build_argparser(parser)
52a8e1175bSopenharmony_ci    args = parser.parse_args()
53a8e1175bSopenharmony_ci
54a8e1175bSopenharmony_ci    return generate(**vars(args))
55a8e1175bSopenharmony_ci
56a8e1175bSopenharmony_cidef generate(**kwargs):
57a8e1175bSopenharmony_ci    """Generate different salt length certificate file."""
58a8e1175bSopenharmony_ci    ca_password = kwargs.get('ca_password', '')
59a8e1175bSopenharmony_ci    if ca_password:
60a8e1175bSopenharmony_ci        kwargs['ca_password'] = r'-passin "pass:{ca_password}"'.format(
61a8e1175bSopenharmony_ci            **kwargs)
62a8e1175bSopenharmony_ci    else:
63a8e1175bSopenharmony_ci        kwargs['ca_password'] = ''
64a8e1175bSopenharmony_ci    extfile = kwargs.get('openssl_extfile', '')
65a8e1175bSopenharmony_ci    if extfile:
66a8e1175bSopenharmony_ci        kwargs['openssl_extfile'] = '-extfile {openssl_extfile}'.format(
67a8e1175bSopenharmony_ci            **kwargs)
68a8e1175bSopenharmony_ci    else:
69a8e1175bSopenharmony_ci        kwargs['openssl_extfile'] = ''
70a8e1175bSopenharmony_ci
71a8e1175bSopenharmony_ci    cmd = OPENSSL_RSA_PSS_CERT_COMMAND.format(**kwargs)
72a8e1175bSopenharmony_ci    der_bytes = subprocess.check_output(cmd, shell=True)
73a8e1175bSopenharmony_ci    target_certificate = x509.Certificate.load(der_bytes)
74a8e1175bSopenharmony_ci
75a8e1175bSopenharmony_ci    cmd = OPENSSL_RSA_PSS_DGST_COMMAND.format(**kwargs)
76a8e1175bSopenharmony_ci    #pylint: disable=unexpected-keyword-arg
77a8e1175bSopenharmony_ci    der_bytes = subprocess.check_output(cmd,
78a8e1175bSopenharmony_ci                                        input=target_certificate['tbs_certificate'].dump(),
79a8e1175bSopenharmony_ci                                        shell=True)
80a8e1175bSopenharmony_ci
81a8e1175bSopenharmony_ci    with open(kwargs.get('output'), 'wb') as f:
82a8e1175bSopenharmony_ci        target_certificate['signature_value'] = core.OctetBitString(der_bytes)
83a8e1175bSopenharmony_ci        f.write(pem.armor('CERTIFICATE', target_certificate.dump()))
84a8e1175bSopenharmony_ci
85a8e1175bSopenharmony_ci
86a8e1175bSopenharmony_ciif __name__ == '__main__':
87a8e1175bSopenharmony_ci    main()
88