summaryrefslogtreecommitdiffstats
path: root/images/gen_key_migration_script/certs_data.py
blob: f76d24e3633bd5ef37365cdc545143bf5441e107 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#!/usr/bin/env python3
# Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <https://www.gnu.org/licenses/>.

class ReplicantCertsData(object):
    def __init__(self):
        self.data = {
            # '<filename>' : [
            #     {
            #         'release' : '<release|None>',
            #         'key' : '<key>',
            #         'format' : 'PEM-pubkey|DER-cert',
            #         'generation' : 'old|new',
            #     },
            # ],
        }

    def fixup_name(self, name):
        #  Replicant 4.2 and Replicant 6.0 both have media.x509.pem,
        #  platform.x509.pem, and shared.x509.pem, however Replicant 4.2 has
        #  system.x509.pem while Replicant 6.0 has releasekey.x509.pem instead.
        if name == 'system.x509.pem':
            return 'releasekey.x509.pem'
        else:
            return name

    def add_key(self, name, generation, release, format, key):

        assert (format in ['PEM-pubkey', 'DER-cert'])
        assert (generation in ['old', 'new'])

        name = self.fixup_name(name)

        # Avoid duplicates
        if len(self.get_keys(name, generation, release, format)) > 0:
            assert(False)

        # We have only one entry per format per 'new' certificate
        if format == 'new' and len(self.get_new_keys(name, format)) > 0:
            assert(False)

        elm = {
            'generation' : generation,
            'release' : release,
            'key' : key,
            'format' : format,
        }

        if name not in self.data.keys():
            self.data[name] = []

        self.data[name].append(elm)

    def get_keys(self, name, generation, release, format):
        results = []
        for elm in self.data.get(name, []):
            if elm['release'] != release:
                continue
            elif ['format'] != format:
                continue
            elif elm['generation'] != generation:
                continue
            else:
                results.append(elm)
        return results

    def get_new_keys(self, name, format):
        results = []
        for elm in self.data.get(name, []):
            if elm['format'] != format:
                continue
            elif elm['generation'] != 'new':
                continue
            else:
                results.append(elm)
        return results

    def check_consistency(self):
        for name, certs in self.data.items():
            new_der = 0
            new_pem = 0
            old_certs = {
                # '<release>' : {
                #     'PEM-pubkey' : '<nr>'
                #     'DER-cert' : '<nr>'
                # }
            }
            for cert in certs:
                # Only 1 PEM and 1 DER for new certificates
                if cert['generation'] == 'new' and cert['format'] == 'DER-cert':
                    new_der += 1
                if cert['generation'] == 'new' and \
                   cert['format'] == 'PEM-pubkey':
                    new_pem +=1
                # Only 1 PEM and 1 DER per release for old certificates
                if cert['generation'] == 'old':
                    release = cert['release']
                    format = cert['format']
                    if release not in old_certs.keys():
                        old_certs[release] = {}
                    if format not in old_certs[release]:
                        old_certs[release][format] = 1
                    else:
                        old_certs[release][format] += 1

            assert(new_der == 1)
            assert(new_pem == 1)

            for release, release_data in old_certs.items():
                assert(release_data['DER-cert'] == 1)
                assert(release_data['PEM-pubkey'] == 1)