blob: 9eb530de3d1bfd915de07e54781f6f08fca01942 [file] [log] [blame]
#!/usr/bin/python
#
# Copyright (c) 2022 Project CHIP Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# Script that was used to fetch CHIP Development Product Attestation Authority (PAA)
# certificates from DCL.
# The script expects the path to the dcld tool binary as an input argument.
#
# Usage example when the script is run from the CHIP SDK root directory:
# python ./credentials/development/fetch-development-paa-certs-from-dcl.py /path/to/dcld
#
# The result will be stored in:
# credentials/development/paa-root-certs
#
import os
import sys
import subprocess
import copy
import re
from cryptography.hazmat.primitives import serialization
from cryptography import x509
def parse_paa_root_certs(cmdpipe, paa_list):
"""
example output of a query to all x509 root certs in DCL:
certs:
- subject: MCExHzAdBgNVBAMMFk1hdHRlciBEZXZlbG9wbWVudCBQQUE=
subjectKeyId: FA:92:CF:09:5E:FA:42:E1:14:30:65:16:32:FE:FE:1B:2C:77:A7:C8
- subject: MDAxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQTEUMBIGCisGAQQBgqJ8AgEMBDEyNUQ=
subjectKeyId: E2:90:8D:36:9C:3C:A3:C1:13:BB:09:E2:4D:C1:CC:C5:A6:66:91:D4
- subject: MEsxCzAJBgNVBAYTAlVTMQ8wDQYDVQQKDAZHb29nbGUxFTATBgNVBAMMDE1hdHRlciBQQUEgMTEUMBIGCisGAQQBgqJ8AgEMBDYwMDY=
subjectKeyId: B0:00:56:81:B8:88:62:89:62:80:E1:21:18:A1:A8:BE:09:DE:93:21
- subject: MFUxCzAJBgNVBAYTAlVTMRcwFQYDVQQKEw5EaWdpQ2VydCwgSW5jLjEtMCsGA1UEAxMkRGlnaUNlcnQgVEVTVCBSb290IENBIGZvciBNQVRURVIgUEtJ
subjectKeyId: C0:E0:64:15:00:EC:67:E2:7C:AF:7C:6E:2D:49:94:C7:73:DE:B7:BA
- subject: MDAxLjAsBgNVBAMMJU5vbiBQcm9kdWN0aW9uIE9OTFkgLSBYRk4gUEFBIENsYXNzIDM=
subjectKeyId: F8:99:A9:D5:AD:71:71:E4:C3:81:7F:14:10:7F:78:F0:D9:F7:62:E9
- subject: MEIxGDAWBgNVBAMMD01hdHRlciBUZXN0IFBBQTEQMA4GA1UECgwHU2Ftc3VuZzEUMBIGCisGAQQBgqJ8AgEMBDEwRTE=
subjectKeyId: CF:9E:0A:16:78:8B:40:30:EC:DD:AB:34:B9:C2:EC:7B:E5:34:55:C0
Brief:
This method will search for the first line that contains ': ' char sequence.
From there, it assumes every 2 lines contain subject and subject key id info of
a valid PAA root certificate.
The paa_list parameter will contain a list of all valid PAA Root certificates
from DCL.
"""
result = {}
while True:
line = cmdpipe.stdout.readline()
if not line:
break
else:
if b': ' in line:
key, value = line.split(b': ')
result[key.strip(b' -')] = value.strip()
parse_paa_root_certs.counter += 1
if parse_paa_root_certs.counter % 2 == 0:
paa_list.append(copy.deepcopy(result))
def write_paa_root_cert(cmdpipe, subject):
pem_read = False
subject_as_text_read = False
filename = 'paa-root-certs/dcld_mirror_' + \
re.sub('[^a-zA-Z0-9_-]', '', re.sub('[=, ]', '_', subject))
with open(filename + '.pem', 'wb+') as outfile:
while True:
line = cmdpipe.stdout.readline()
if not line:
break
else:
if b'pemCert: |' in line:
while True:
line = cmdpipe.stdout.readline()
outfile.write(line.strip(b' \t'))
if b'-----END CERTIFICATE-----' in line:
pem_read = True
break
if b'subjectAsText:' in line:
new_subject = line.split(b': ')[1].strip().decode("utf-8")
new_filename = 'paa-root-certs/dcld_mirror_' + \
re.sub('[=,\\\\ ]', '_', new_subject)
subject_as_text_read = True
break
# if successfully obtained all mandatory fields from the root certificate
if pem_read == True and subject_as_text_read == True:
os.rename(filename + '.pem', new_filename + '.pem')
# convert pem file to der
with open(new_filename + '.pem', 'rb') as infile:
pem_certificate = x509.load_pem_x509_certificate(infile.read())
with open(new_filename + '.der', 'wb+') as outfile:
der_certificate = pem_certificate.public_bytes(
serialization.Encoding.DER)
outfile.write(der_certificate)
def main():
if len(sys.argv) == 2:
dcld = sys.argv[1]
else:
sys.exit(
"Error: Please specify exactly one input argument; the path to the dcld tool binary")
previous_dir = os.getcwd()
abspath = os.path.dirname(sys.argv[0])
os.chdir(abspath)
os.makedirs('paa-root-certs', exist_ok=True)
cmdpipe = subprocess.Popen([dcld, 'query', 'pki', 'all-x509-root-certs'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
paa_list = []
parse_paa_root_certs.counter = 0
parse_paa_root_certs(cmdpipe, paa_list)
for paa in paa_list:
cmdpipe = subprocess.Popen(
[dcld, 'query', 'pki', 'x509-cert', '-u',
paa[b'subject'].decode("utf-8"), '-k', paa[b'subjectKeyId'].decode("utf-8")],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
write_paa_root_cert(cmdpipe, paa[b'subject'].decode("utf-8"))
os.chdir(previous_dir)
if __name__ == "__main__":
main()