4 # certdata2pem.py - splits certdata.txt into multiple files
6 # Copyright (C) 2009 Philipp Kern <pkern@debian.org>
7 # Copyright (C) 2013 Kai Engert <kaie@redhat.com>
9 # This program is free software; you can redistribute it and/or modify
10 # it under the terms of the GNU General Public License as published by
11 # the Free Software Foundation; either version 2 of the License, or
12 # (at your option) any later version.
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 # GNU General Public License for more details.
19 # You should have received a copy of the GNU General Public License
20 # along with this program; if not, write to the Free Software
21 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
33 def printable_serial(obj
):
34 return ".".join(map(lambda x
:str(ord(x
)), obj
['CKA_SERIAL_NUMBER']))
37 in_data
, in_multiline
, in_obj
= False, False, False
38 field
, type, value
, obj
= None, None, None, dict()
39 for line
in open('certdata.txt', 'r'):
40 # Ignore the file header.
42 if line
.startswith('BEGINDATA'):
45 # Ignore comment lines.
46 if line
.startswith('#'):
48 # Empty lines are significant if we are inside an object.
49 if in_obj
and len(line
.strip()) == 0:
54 if len(line
.strip()) == 0:
57 if not line
.startswith('END'):
58 if type == 'MULTILINE_OCTAL':
60 for i
in re
.finditer(r
'\\([0-3][0-7][0-7])', line
):
61 value
+= chr(int(i
.group(1), 8))
68 if line
.startswith('CKA_CLASS'):
70 line_parts
= line
.strip().split(' ', 2)
71 if len(line_parts
) > 2:
72 field
, type = line_parts
[0:2]
73 value
= ' '.join(line_parts
[2:])
74 elif len(line_parts
) == 2:
75 field
, type = line_parts
78 raise NotImplementedError, 'line_parts < 2 not supported.\n' + line
79 if type == 'MULTILINE_OCTAL':
84 if len(obj
.items()) > 0:
87 # Build up trust database.
90 if obj
['CKA_CLASS'] != 'CKO_NSS_TRUST':
92 key
= obj
['CKA_LABEL'] + printable_serial(obj
)
94 print " added trust", key
96 # Build up cert database.
99 if obj
['CKA_CLASS'] != 'CKO_CERTIFICATE':
101 key
= obj
['CKA_LABEL'] + printable_serial(obj
)
103 print " added cert", key
105 def obj_to_filename(obj
):
106 label
= obj
['CKA_LABEL'][1:-1]
107 label
= label
.replace('/', '_')\
112 label
= re
.sub(r
'\\x[0-9a-fA-F]{2}', lambda m
:chr(int(m
.group(0)[2:], 16)), label
)
113 serial
= printable_serial(obj
)
114 return label
+ ":" + serial
117 "CKA_TRUST_DIGITAL_SIGNATURE": "digital-signature",
118 "CKA_TRUST_NON_REPUDIATION": "non-repudiation",
119 "CKA_TRUST_KEY_ENCIPHERMENT": "key-encipherment",
120 "CKA_TRUST_DATA_ENCIPHERMENT": "data-encipherment",
121 "CKA_TRUST_KEY_AGREEMENT": "key-agreement",
122 "CKA_TRUST_KEY_CERT_SIGN": "cert-sign",
123 "CKA_TRUST_CRL_SIGN": "crl-sign",
124 "CKA_TRUST_SERVER_AUTH": "server-auth",
125 "CKA_TRUST_CLIENT_AUTH": "client-auth",
126 "CKA_TRUST_CODE_SIGNING": "code-signing",
127 "CKA_TRUST_EMAIL_PROTECTION": "email-protection",
128 "CKA_TRUST_IPSEC_END_SYSTEM": "ipsec-end-system",
129 "CKA_TRUST_IPSEC_TUNNEL": "ipsec-tunnel",
130 "CKA_TRUST_IPSEC_USER": "ipsec-user",
131 "CKA_TRUST_TIME_STAMPING": "time-stamping",
132 "CKA_TRUST_STEP_UP_APPROVED": "step-up-approved",
135 legacy_trust_types
= {
136 "LEGACY_CKA_TRUST_SERVER_AUTH": "server-auth",
137 "LEGACY_CKA_TRUST_CODE_SIGNING": "code-signing",
138 "LEGACY_CKA_TRUST_EMAIL_PROTECTION": "email-protection",
141 legacy_to_real_trust_types
= {
142 "LEGACY_CKA_TRUST_SERVER_AUTH": "CKA_TRUST_SERVER_AUTH",
143 "LEGACY_CKA_TRUST_CODE_SIGNING": "CKA_TRUST_CODE_SIGNING",
144 "LEGACY_CKA_TRUST_EMAIL_PROTECTION": "CKA_TRUST_EMAIL_PROTECTION",
148 "CKA_TRUST_SERVER_AUTH": "serverAuth",
149 "CKA_TRUST_CLIENT_AUTH": "clientAuth",
150 "CKA_TRUST_CODE_SIGNING": "codeSigning",
151 "CKA_TRUST_EMAIL_PROTECTION": "emailProtection",
155 if tobj
['CKA_CLASS'] == 'CKO_NSS_TRUST':
156 key
= tobj
['CKA_LABEL'] + printable_serial(tobj
)
157 print "producing trust for " + key
160 openssl_trustflags
= []
161 openssl_distrustflags
= []
162 legacy_trustbits
= []
163 legacy_openssl_trustflags
= []
164 for t
in trust_types
.keys():
165 if tobj
.has_key(t
) and tobj
[t
] == 'CKT_NSS_TRUSTED_DELEGATOR':
167 if t
in openssl_trust
:
168 openssl_trustflags
.append(openssl_trust
[t
])
169 if tobj
.has_key(t
) and tobj
[t
] == 'CKT_NSS_NOT_TRUSTED':
170 distrustbits
.append(t
)
171 if t
in openssl_trust
:
172 openssl_distrustflags
.append(openssl_trust
[t
])
174 for t
in legacy_trust_types
.keys():
175 if tobj
.has_key(t
) and tobj
[t
] == 'CKT_NSS_TRUSTED_DELEGATOR':
176 real_t
= legacy_to_real_trust_types
[t
]
177 legacy_trustbits
.append(real_t
)
178 if real_t
in openssl_trust
:
179 legacy_openssl_trustflags
.append(openssl_trust
[real_t
])
180 if tobj
.has_key(t
) and tobj
[t
] == 'CKT_NSS_NOT_TRUSTED':
181 raise NotImplementedError, 'legacy distrust not supported.\n' + line
183 fname
= obj_to_filename(tobj
)
195 if tobj
.has_key('LEGACY_CKA_TRUST_SERVER_AUTH') or tobj
.has_key('LEGACY_CKA_TRUST_EMAIL_PROTECTION') or tobj
.has_key('LEGACY_CKA_TRUST_CODE_SIGNING'):
198 raise NotImplementedError, 'found legacy trust without certificate.\n' + line
199 legacy_fname
= "legacy-default/" + fname
200 f
= open(legacy_fname
, 'w')
201 f
.write("# alias=%s\n"%tobj
['CKA_LABEL'])
202 f
.write("# trust=" + " ".join(legacy_trustbits
) + "\n")
203 if legacy_openssl_trustflags
:
204 f
.write("# openssl-trust=" + " ".join(legacy_openssl_trustflags
) + "\n")
205 f
.write("-----BEGIN CERTIFICATE-----\n")
206 f
.write("\n".join(textwrap
.wrap(base64
.b64encode(obj
['CKA_VALUE']), 64)))
207 f
.write("\n-----END CERTIFICATE-----\n")
209 if tobj
.has_key('CKA_TRUST_SERVER_AUTH') or tobj
.has_key('CKA_TRUST_EMAIL_PROTECTION') or tobj
.has_key('CKA_TRUST_CODE_SIGNING'):
210 fname
= "legacy-disable/" + fname
216 f
.write("# alias=%s\n"%tobj
['CKA_LABEL'])
217 f
.write("# trust=" + " ".join(trustbits
) + "\n")
218 f
.write("# distrust=" + " ".join(distrustbits
) + "\n")
219 if openssl_trustflags
:
220 f
.write("# openssl-trust=" + " ".join(openssl_trustflags
) + "\n")
221 if openssl_distrustflags
:
222 f
.write("# openssl-distrust=" + " ".join(openssl_distrustflags
) + "\n")
223 f
.write("-----BEGIN CERTIFICATE-----\n")
224 f
.write("\n".join(textwrap
.wrap(base64
.b64encode(obj
['CKA_VALUE']), 64)))
225 f
.write("\n-----END CERTIFICATE-----\n")
227 f
.write("[p11-kit-object-v1]\n")
229 f
.write(tobj
['CKA_LABEL']);
231 f
.write("class: certificate\n")
232 f
.write("certificate-type: x-509\n")
233 f
.write("issuer: \"");
234 f
.write(urllib
.quote(tobj
['CKA_ISSUER']));
236 f
.write("serial-number: \"");
237 f
.write(urllib
.quote(tobj
['CKA_SERIAL_NUMBER']));
239 if (tobj
['CKA_TRUST_SERVER_AUTH'] == 'CKT_NSS_NOT_TRUSTED') or (tobj
['CKA_TRUST_EMAIL_PROTECTION'] == 'CKT_NSS_NOT_TRUSTED') or (tobj
['CKA_TRUST_CODE_SIGNING'] == 'CKT_NSS_NOT_TRUSTED'):
240 f
.write("x-distrusted: true\n")
243 print " -> written as '%s', trust = %s, openssl-trust = %s, distrust = %s, openssl-distrust = %s" % (fname
, trustbits
, openssl_trustflags
, distrustbits
, openssl_distrustflags
)