blob: 38316fbe12d0f927771cfcf63dac98ed6ecd4562 [file] [log] [blame]
#!/usr/bin/env python
# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""
Given a path to a XXX.pem file, re-generates a CERTIFICATE.
The .pem file is expected to contain comments that resemble:
#-----BEGIN XXX-----
<ascii-der values in here>
#-----END XXX-----
These are interpreted as substitutions to make inside of the Certificate
template (v3_certificate_template.txt)
"""
import sys
import os
import re
import base64
import subprocess
def read_file_to_string(path):
"""Reads a file entirely to a string"""
with open(path, 'r') as f:
return f.read()
def write_string_to_file(data, path):
"""Writes a string to a file"""
print "Writing file %s ..." % (path)
with open(path, "w") as f:
f.write(data)
def replace_string(original, start, end, replacement):
"""Replaces the specified range of |original| with |replacement|"""
return original[0:start] + replacement + original[end:]
def apply_substitution(template, name, value):
"""Finds a section named |name| in |template| and replaces it with |value|."""
# Find the section |name| in |template|.
regex = re.compile(r'#-----BEGIN %s-----(.*?)#-----END %s-----' %
(re.escape(name), re.escape(name)), re.DOTALL)
m = regex.search(template)
if not m:
print "Couldn't find a section named %s in the template" % (name)
sys.exit(1)
return replace_string(template, m.start(1), m.end(1), value)
def main():
if len(sys.argv) != 2:
print 'Usage: %s <PATH_TO_PEM>' % (sys.argv[0])
sys.exit(1)
pem_path = sys.argv[1]
orig = read_file_to_string(pem_path)
cert_ascii = read_file_to_string("v3_certificate_template.txt")
# Apply all substitutions described by comments in |orig|
regex = re.compile(r'#-----BEGIN ([\w ]+)-----(.*?)#-----END \1-----',
re.DOTALL)
num_matches = 0
for m in regex.finditer(orig):
num_matches += 1
cert_ascii = apply_substitution(cert_ascii, m.group(1), m.group(2))
if num_matches == 0:
print "Input did not contain any substitutions"
sys.exit(1)
# Convert the ascii-der to actual DER binary.
cert_der = None
try:
p = subprocess.Popen(['ascii2der'], stdout=subprocess.PIPE,
stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
cert_der = p.communicate(input=cert_ascii)[0]
except OSError as e:
print ('ERROR: Failed executing ascii2der.\n'
'Make sure this is in your path\n'
'Obtain it from https://github.com/google/der-ascii')
sys.exit(1)
# Replace the CERTIFICATE block with the newly generated one.
regex = re.compile(r'-----BEGIN CERTIFICATE-----\n(.*?)\n'
'-----END CERTIFICATE-----', re.DOTALL)
m = regex.search(orig)
if not m:
print "ERROR: Cannot find CERTIFICATE block in input"
sys.exit(1)
modified = replace_string(orig, m.start(1), m.end(1),
base64.b64encode(cert_der))
# Write back the .pem file.
write_string_to_file(modified, pem_path)
main()