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)
|