Skip to content

Commit

Permalink
generate_cryptodriver: Add useful versioning to shared crypto binaries (
Browse files Browse the repository at this point in the history
#105)

## Description

Updates the ver section to reflect version info available depending on
the build type.

1. Removes hardcoded "1.0" in FFS Version string
2. Uses the EDK2 crypto version (binary compat) version for all builds.
3. Uses the EDK2 crypto version + Major.Minor.Patch for pipeline
(release) builds.

- Local Build: `"{EDK2_CRYPTO_VER}"`
- CI Build: `"{EDK2_CRYPTO_VER}.{MAJOR}.{MINOR}.{PATCH}"`

- [ ] Impacts functionality?
- [ ] Impacts security?
- [ ] Breaking change?
- [ ] Includes tests?
- [ ] Includes documentation?

## How This Was Tested

- Generate crypto driver
- Local build and bundle
- Integrate into platform and check VER section in FFS

## Integration Instructions

N/A - VER in Shared Crypto FFS will no longer be hardcoded to `1.0`

Signed-off-by: Michael Kubacki <[email protected]>
  • Loading branch information
makubacki authored Sep 21, 2024
1 parent 8303fd2 commit 0588021
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 10 deletions.
12 changes: 10 additions & 2 deletions .azuredevops/pipelines/template-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,14 @@ jobs:
scriptPath: MultiFlavorBuild.py
arguments: --update TOOL_CHAIN_TAG=${{ item.Value.ToolChain }}

- task: PythonScript@0
displayName: Generate Updated Packaging Files
env:
PUBLISH_VERSION: ${{ parameters.publish_version }}
inputs:
scriptSource: 'filePath'
scriptPath: CryptoBinPkg/Driver/Packaging/generate_cryptodriver.py

- task: PythonScript@0
displayName: 'Build Crypto Drivers'
inputs:
Expand Down Expand Up @@ -172,14 +180,14 @@ jobs:
dest_folder = os.environ['OUT_DIR']
src_folder = os.environ['ARTIFACT_DIR']
if not os.path.exists(dest_folder):
os.makedirs(dest_folder)
for content in Path(src_folder).iterdir():
print(content)
shutil.copytree(content, dest_folder, dirs_exist_ok=True)
- task: CopyFiles@2
displayName: Copy License
inputs:
Expand Down
Binary file added CryptoBinPkg/Driver/Images/ffs_ver.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
41 changes: 33 additions & 8 deletions CryptoBinPkg/Driver/Packaging/generate_cryptodriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
# Copyright (c) Microsoft Corporation
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import os
import glob
import shutil
import argparse
import datetime
import glob
import os
import re
import shutil
from enum import Enum

SCRIPT_DIR = os.path.dirname(__file__)
Expand All @@ -33,6 +34,8 @@ def main():
options = ParseCommandLineOptions()
# Read in all the functions from the Crypto and Tls headers
crypto_functions = read_basecryptlib_and_tlslib(options)
h_file_path = os.path.join(options.out_dir, "temp_Crypto.h")

# generate the requested files
if options.c_file:
get_crypto_c(options, crypto_functions)
Expand All @@ -43,8 +46,6 @@ def main():
if options.h_file:
get_crypto_h(options, crypto_functions)
if options.copy:
# TODO: define this somewhere globally
h_file_path = os.path.join(options.out_dir, "temp_Crypto.h")
shutil.copyfile(h_file_path, os.path.join(ROOT_DIR, "MU_BASECORE", "CryptoPkg", "Include", "Protocol", "Crypto.h"))
if options.p_file:
get_crypto_pcds(options, crypto_functions)
Expand All @@ -59,11 +60,23 @@ def main():
c_lib_file_path = os.path.join(options.out_dir, "temp_CryptLib.c")
shutil.copyfile(c_lib_file_path, os.path.join(ROOT_DIR, "MU_BASECORE", "CryptoPkg", "Library", "BaseCryptLibOnProtocolPpi", "CryptLib.c"))

generate_platform_files() # TODO: Refactor. Copied from separate script.
generate_platform_files(_get_edk2_crypto_version(h_file_path)) # TODO: Refactor. Copied from separate script.

print("Success. Thanks for playing :)")


def _get_edk2_crypto_version(crypto_header_path: str) -> str:
with open(crypto_header_path, 'r') as crypt_header_file:
for line in crypt_header_file:
if 'define EDKII_CRYPTO_VERSION' in line:
match = re.search(r'\bdefine EDKII_CRYPTO_VERSION\s+(\d+)', line)
if match:
ver = int(match.group(1))
print(f"EDK2 Crypto Version Found: {ver}")
return str(ver)
return "0"


def ParseCommandLineOptions():
''' parse arguments '''
def validate_abs_path(path_arg: str):
Expand Down Expand Up @@ -674,7 +687,7 @@ def get_crypto_inf(options, functions):
generate_file_replacement(lines, None, "temp_crypto_pcd.inc.inf", options, "#")


def generate_platform_files():
def generate_platform_files(edk2_crypto_ver: str = "1.0"):
class options():
out_dir = DEFAULT_OUTPUT_DIR
verbose = False
Expand Down Expand Up @@ -743,13 +756,23 @@ class options():
if len(guid) != len(original_guid):
raise ValueError(
f"{guid} is not long enough. {len(guid)} vs {len(original_guid)}")
# Get more detailed version info from the pipeline build if running in a
# pipeline with the version variables available.
#
# Final FFS Ver section value will be:
# - Local Build: "{EDK2_CRYPTO_VER}"
# - CI Build: "{EDK2_CRYPTO_VER}.{MAJOR}.{MINOR}.{PATCH}"
inf_ver_string = edk2_crypto_ver
if "PUBLISH_VERSION" in os.environ:
inf_ver_string += f".{os.environ['PUBLISH_VERSION']}"

inf_lines.extend(["[Defines]",
" INF_VERSION = 0x0001001B",
f" BASE_NAME = BaseCryptoDriver{phase}{arch}",
" MODULE_UNI_FILE = Crypto.uni",
f" FILE_GUID = {guid}",
f" MODULE_TYPE = {mod_type}",
" VERSION_STRING = 1.0",
f" VERSION_STRING = {inf_ver_string}",
" PI_SPECIFICATION_VERSION = 0x00010032",
f" ENTRY_POINT = Crypto{phase}Entry"])
inf_lines.append(f"\n[Binaries.{arch}]")
Expand All @@ -774,6 +797,8 @@ class options():
generate_file_replacement(
inf_lines, None, inf_filename, options(), comment="#")

print(f"Final Crypto Binary Version: {inf_ver_string}")

# now we generate the CI DSC include
generate_file_replacement(
dsc_ci_lines, None, "CryptoPkg.ci.inc.dsc", options(), comment="#")
Expand Down
37 changes: 37 additions & 0 deletions CryptoBinPkg/Driver/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,40 @@ the process.
[`CryptoPkg/Include/Protocol/Crypto.h`](https://github.com/microsoft/mu_basecore/blob/HEAD/CryptoPkg/Include/Protocol/Crypto.h).
The version should match in the `MU_BASECORE` submodule of the `mu_crypto_release` repository and the version in
your repo. If it does not, you may need to use a different shared crypto release.

## Finding the Version of a Shared Crypto Binary

Version information is placed into the `VERSION_STRING` of the .inf files that are made available in Shared Crypto
releases. For example, this is the `[DEFINES]` section for a `Driver/Bin/CryptoDriverBin_STANDARD_Dxe_DEBUG_X64.inf`
file.

```
[Defines]
INF_VERSION = 0x0001001B
BASE_NAME = BaseCryptoDriverDxeX64
MODULE_UNI_FILE = Crypto.uni
FILE_GUID = bdee011f-87f2-4a7f-bc5e-44b6b61f2D20
MODULE_TYPE = DXE_DRIVER
VERSION_STRING = 18.2023.12.3
PI_SPECIFICATION_VERSION = 0x00010032
ENTRY_POINT = CryptoDxeEntry
```
When Shared Crypto is used by platform, this informs the build system that the `VERSION_STRING` value should be added
to a version section in the FFS file created for the binary.
This means that given a firmware image that uses shared crypto, you can view the version for the crypto binaries in
that firmware by looking at the version section.
This is possible using a tool like [UefiTool](https://github.com/LongSoft/UEFITool) which can open UEFI ROMs and
firmware volumes. Find the shared crypto binary and go to the `Version section`. The tool will decode the
`Version string` in the information panel on the right.
An example:
![FFS Version Section](Images/ffs_ver.jpg "FFS Version Section")
Currently, this indicates:
- The "EDK2 Crypto Version" is `18`. This is the version of the crypto protocol interface.
- The Shared Crypto build version is `2023.12.3`

0 comments on commit 0588021

Please sign in to comment.