Commit aa593979 authored by Sorin Jianu's avatar Sorin Jianu Committed by Commit Bot

Create a tagging script to allow tagging of signed metainstallers.

This tool is intended for developer use. It is not a production tool,
although it may be extended at some point to offer the functionality
of Omaha's ApplyTag.exe.

The script is a wrapper for certificate_tag.exe.

Since the tag format is not a simple concatenation of the magic
string start and the tag, but it requires a big-endian value be
inserted in between the strings, and certificate_tag.exe requires
the tag be provided as a hex-encoded string, then some command
wrapping is needed.

For now, the tooling assumes the tag is ASCII-encoded, but UTF-8
support can be provided later on.

To use the tool, invoke it like this:

python3 chrome\updater\tools\tag.py
--certificate_tag=out\Default\certificate_tag.exe
--in_file=out\Default\UpdaterSetup.signed.exe
--tag=appguid={8A69D345-D564-463c-AFF1-A69D9E530F96}

Bug: 1128751
Change-Id: I2dab1dfd4e7fff34c9982868625b995cff122d8a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2426765Reviewed-by: default avatarJoshua Pawlicki <waffles@chromium.org>
Commit-Queue: Sorin Jianu <sorin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#815609}
parent 0b0d9319
[style]
based_on_style = pep8
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Presubmit script for chrome/updater/tools/.
See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts
for more details about the presubmit API built into depot_tools.
"""
def CommonChecks(input_api, output_api):
return input_api.canned_checks.RunPylint(input_api, output_api)
def CheckChangeOnUpload(input_api, output_api):
return CommonChecks(input_api, output_api)
def CheckChangeOnCommit(input_api, output_api):
return CommonChecks(input_api, output_api)
#!/usr/bin/python3
# Copyright 2020 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""A tool for tagging an updater metainstaller.
For example:
python3 chrome/updater/tools/tag.py --certificate_tag=certificate_tag.exe
--in_file=UpdaterSetup.signed.exe --out_file=ChromeSetup.exe
--tag=appguid={8A69D345-D564-463c-AFF1-A69D9E530F96}
The script requires the presence of `certificate_tag.exe` and a signed
metainstaller. If the --out_file argument is not specified, then the output
goes to a file named `tagged_<in_file>`.
The tag is encoded as an ASCII string.
To run locally:
1. find the certificate_tag.exe. This file is usually in the build out dir.
2. use the signing/sign.py script to sign the updatersetup.exe target.
3. run this script as suggested above, using the correct paths for the args.
"""
import argparse
import binascii
import os.path
import struct
import subprocess
class TaggingError(Exception):
"""Module exception class."""
pass
class Tagger(object):
"""A container for a tagging operation."""
def __init__(self, tagging_exe):
"""Inits a tagger with the certificate tag tool."""
self._tagging_exe = tagging_exe
def _make_hex_tag(self, tag):
""" Builds the string which gets embedded in the metainstaller.
The tag contains a magic start, followed by a 2-byte big endian value
representing the length of the tag, followed by the tag bytes. The
entire tag is hex-encoded."""
if len(tag) > 0xFFFF:
raise TaggingError('Tag is too long.')
bin_tag = bytearray(binascii.hexlify('Gact2.0Omaha'.encode()))
bin_tag.extend(binascii.hexlify(struct.pack(">H", len(tag))))
bin_tag.extend(binascii.hexlify(tag.encode()))
return bin_tag.decode()
def _insert_tag(self, tag, in_file, out_file):
"""Inserts the tag. This overrides any tag previously present in
the metainstaller."""
subprocess.run([
self._tagging_exe,
'--set-superfluous-cert-tag=0x%s' % self._make_hex_tag(tag),
'--padded-length=8206',
'--out=%s' % out_file, in_file
],
check=True)
def tag_metainstaller(self, tag, in_file, out_file):
if not out_file:
out_file = os.path.join(os.path.dirname(in_file),
'tagged_' + os.path.basename(in_file))
return self._insert_tag(tag, in_file, out_file)
def main():
parser = argparse.ArgumentParser(
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('--certificate_tag',
required=True,
help='The path to the certificate_tag executable.')
parser.add_argument('--tag',
required=True,
help='The tag as an ASCII string.')
parser.add_argument('--in_file',
required=True,
help='The path to the signed metainstaller.')
parser.add_argument('--out_file',
required=False,
help='The path to save the tagged metainstaller to.'
' "tagged_" is prepended to in_file name if'
' the out_file is not specified.')
args = parser.parse_args()
Tagger(args.certificate_tag).tag_metainstaller(args.tag, args.in_file,
args.out_file)
if __name__ == '__main__':
main()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment