liboqs/scripts/update_cbom.py
Pravek Sharma e520ec1c38
Integrate Kyber from libjade (#1745)
* Add copy_from_libjade.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Modify copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Add patches for libjade Kyber code

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update alg_support.cmake templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM famiy templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Correct copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Modify copy_from_upstream.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM family templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix KEM family templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix KEM family templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update templates for build system files

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update build system files

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix add_enable_by_alg_conditional.libjade

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Run copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM family templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update copy_from_upstream.yml with libjade implementation info

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Edit KEM templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Run copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix KEM temlates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Run copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Add libjade_shim

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Add jasmin/libjade namespaces to test_binary.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update testing

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Allow manually triggering CI tests

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Change container for upstreamcheck in unix.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Edit unix.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Edit unix.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Restrict copying of code from libjade repo to relevant files

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Remove irrelevant libjade code

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Remove redundant KEM templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update KEM template to accomodate new dir structure

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Debug: tweak unix.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Re-build libjade with jasmin version used in CI

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Debug: undo unix.yml tweak

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Allow MSVC to ignore libjade_shims

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Simplify name scheme for libjade code

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update alg docs, libjade code name scheme, and license

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update copy_from_upstream documentation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix copy_from_upstream.py and simply libjade code name scheme

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update alg docs and CBOM

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Correct alg doc generation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Generate CBOM with unique bom-ref

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Cleanup unix.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix patches to include api.c; fix kem templates

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix kyber patch

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* turn off weekly constant time tests for libjade implementations

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* update documentation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* change upstream to stable libjade release

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix kyber documentation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix kyber documentation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix kem template again

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix weekly.yml and unix.yml to test libjade code

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* rename libjade asm files from *.s to *.S

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* end libjade_kyber*/api.c files with newline

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix kem template to prevent duplicate symbols in object files

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix indentation in weekly.yml

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* skip testing libjade on macos-14 in CI

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* use release tag/branch with libjade upstream url instead of commit

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix build error when OQS_ENABLE_LIBJADE_KEM_ALG=OFF

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* initialize LIBJADE_RANDOMBYTES when OQS_LIBJADE_BUILD=OFF

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* remove redundant comment

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix comment typo

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* make string explicit when comparing with variable in cmake

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* add libjade kyber licensing to README.md

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* remove reference to oldpqclean_kyber* code from libjade if branchin kem_kyber_*.c

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update CMakeLists.txt

Co-authored-by: Spencer Wilson <spencer.wilson@uwaterloo.ca>
Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* track jasminc version in copy_from_libjade.yml; check jasminc version in copy_from_upstream.py

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* add OQS_LIBJADE_BUILD to build flags output

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* remove link from CONFIGURE.md

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Update libjade to dual license

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Patch gcc version for MacOS CI runs

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix doc generation

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* Fix libjade docs

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* fix license info in README.md

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

* update libjade_randombytes spdx-license

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>

---------

Signed-off-by: Pravek Sharma <sharmapravek@gmail.com>
Co-authored-by: Spencer Wilson <spencer.wilson@uwaterloo.ca>
2024-08-18 12:02:37 -04:00

228 lines
8.3 KiB
Python

# SPDX-License-Identifier: MIT
# This script generates a Cryptography Bill of Material (CBOM)
# according to https://github.com/IBM/CBOM/blob/main/bom-1.4-cbom-1.0.schema.json
# apt-get install npm python3-git
import argparse
import glob
import yaml
import os
import json
import git
import uuid
from datetime import datetime
import copy
cbom_json_file = "cbom.json"
def load_yaml(filename, encoding='utf-8'):
with open(filename, mode='r', encoding=encoding) as fh:
return yaml.safe_load(fh.read())
def file_get_contents(filename, encoding=None):
with open(filename, mode='r', encoding=encoding) as fh:
return fh.read()
def out_write(out, str):
out.write(str)
kem_yamls = []
sig_yamls = []
cbom_components = []
bom_algs_bomrefs = []
bom_algs_use_dependencies = {}
## Common crypto components: aes, sha3
common_crypto_component_aes = {
"type": "crypto-asset",
"bom-ref": "alg:aes",
"name": "aes",
"cryptoProperties": {
"assetType": "algorithm",
"algorithmProperties": {
"variant": "aes",
"primitive": "blockcipher",
"implementationLevel": "softwarePlainRam"
}
}
}
common_crypto_component_sha3 = {
"type": "crypto-asset",
"bom-ref": "alg:sha3",
"name": "sha3",
"cryptoProperties": {
"assetType": "algorithm",
"algorithmProperties": {
"variant": "sha3",
"primitive": "hash",
"implementationLevel": "softwarePlainRam"
}
}
}
def add_cbom_component(out, kem_yaml, parameter_set):
primitive = kem_yaml['type']
component = {}
component['type'] = "crypto-asset"
component['bom-ref'] = "alg:" + parameter_set['name']
component['name'] = kem_yaml['name']
algorithmProperties = {}
algorithmProperties['variant'] = parameter_set['name']
algorithmProperties['primitive'] = primitive
algorithmProperties['implementationLevel'] = "softwarePlainRam"
if primitive == 'kem':
algorithmProperties['cryptoFunctions'] = ["keygen", "encapsulate", "decapsulate"]
elif primitive == 'signature':
algorithmProperties['cryptoFunctions'] = ["keygen", "sign", "verify"]
cryptoProperties = {}
cryptoProperties['assetType'] = "algorithm"
cryptoProperties['algorithmProperties'] = algorithmProperties
cryptoProperties['nistQuantumSecurityLevel'] = parameter_set['claimed-nist-level']
component['cryptoProperties'] = cryptoProperties
for impl in parameter_set['implementations']:
dic = {
"all": "generic",
"x86_64": "x86_64",
"ARM64_V8": "armv8-a"
}
dep = []
if 'common-crypto' in impl:
for a in impl['common-crypto']:
if "SHA3" in a:
dep.append(common_crypto_component_sha3['bom-ref'])
elif "AES" in a:
dep.append(common_crypto_component_aes['bom-ref'])
if impl['supported-platforms'] == "all":
algorithmProperties['implementationPlatform'] = dic[impl['supported-platforms']]
component_cpy = copy.deepcopy(component)
component_cpy['bom-ref'] += ":" + algorithmProperties['implementationPlatform']
cbom_components.append(component_cpy)
bom_algs_bomrefs.append(component_cpy['bom-ref'])
if (dep):
bom_algs_use_dependencies.update({
component_cpy['bom-ref'] : dep
})
else:
for plat in impl['supported-platforms']:
if plat['architecture'] in dic.keys():
algorithmProperties['implementationPlatform'] = dic[plat['architecture']]
component_cpy = copy.deepcopy(component)
if 'upstream' in impl and impl['upstream'] == 'libjade':
tag = ":jasmin:"
if any('required_flags' in i for i in impl['supported-platforms']):
tag += impl['upstream-id'] + ':'
component_cpy['bom-ref'] += tag + algorithmProperties['implementationPlatform']
else:
component_cpy['bom-ref'] += ":" + algorithmProperties['implementationPlatform']
cbom_components.append(component_cpy)
bom_algs_bomrefs.append(component_cpy['bom-ref'])
if dep:
bom_algs_use_dependencies.update({
component_cpy['bom-ref'] : dep
})
def build_cbom(liboqs_root, liboqs_version):
## Add KEM components
for kem_yaml_path in sorted(glob.glob(os.path.join(liboqs_root, 'docs', 'algorithms', 'kem', '*.yml'))):
kem_yaml = load_yaml(kem_yaml_path)
kem_yamls.append(kem_yaml)
kem_name = os.path.splitext(os.path.basename(kem_yaml_path))[0]
name = kem_yaml['name']
for parameter_set in kem_yaml['parameter-sets']:
add_cbom_component(None, kem_yaml, parameter_set)
## Add Sig components
for sig_yaml_path in sorted(glob.glob(os.path.join(liboqs_root, 'docs', 'algorithms', 'sig', '*.yml'))):
sig_yaml = load_yaml(sig_yaml_path)
sig_yamls.append(sig_yaml)
sig_name = os.path.splitext(os.path.basename(sig_yaml_path))[0]
for parameter_set in sig_yaml['parameter-sets']:
add_cbom_component(None, sig_yaml, parameter_set)
## liboqs component
liboqs_component = {}
version = liboqs_version
if version == "git":
repo = git.Repo(search_parent_directories=True, odbt=git.GitDB)
version = repo.head.object.hexsha
liboqs_component['type'] = "library"
liboqs_component['bom-ref'] = "pkg:github/open-quantum-safe/liboqs@" + version
liboqs_component['name'] = "liboqs"
liboqs_component['version'] = version
cbom_components.insert(0, liboqs_component)
metadata = {}
metadata['timestamp'] = datetime.now().isoformat()
metadata['component'] = liboqs_component
## Dependencies
dependencies = []
dependencies.append({
"ref": liboqs_component['bom-ref'],
"dependsOn": bom_algs_bomrefs,
"dependencyType": "implements"
})
for usedep in bom_algs_use_dependencies.keys():
dependencies.append({
"ref": usedep,
"dependsOn": bom_algs_use_dependencies[usedep],
"dependencyType": "uses"
})
## CBOM
cbom = {}
cbom['bomFormat'] = "CBOM"
cbom['specVersion'] = "1.4-cbom-1.0"
cbom['serialNumber'] = "urn:uuid:" + str(uuid.uuid4())
cbom['version'] = 1
cbom['metadata'] = metadata
cbom['components'] = cbom_components + [common_crypto_component_aes, common_crypto_component_sha3]
cbom['dependencies'] = dependencies
return cbom
def algorithms_changed(cbom, cbom_path):
if os.path.isfile(cbom_path):
with open(cbom_path, mode='r', encoding='utf-8') as c:
existing_cbom = json.load(c)
existing_cbom['serialNumber'] = cbom['serialNumber']
existing_cbom['metadata']['timestamp'] = cbom['metadata']['timestamp']
existing_cbom['metadata']['component']['bom-ref'] = cbom['metadata']['component']['bom-ref']
existing_cbom['metadata']['component']['version'] = cbom['metadata']['component']['version']
existing_cbom['components'][0]['bom-ref'] = cbom['components'][0]['bom-ref']
existing_cbom['components'][0]['version'] = cbom['components'][0]['version']
existing_cbom['dependencies'][0]['ref'] = cbom['dependencies'][0]['ref']
update_cbom = existing_cbom != cbom
c.close()
return update_cbom
else:
return True
def update_cbom_if_algs_not_changed(liboqs_root, liboqs_version):
cbom_path = os.path.join(liboqs_root, 'docs', cbom_json_file)
cbom = build_cbom(liboqs_root, liboqs_version)
if algorithms_changed(cbom, cbom_path):
with open(cbom_path, mode='w', encoding='utf-8') as out_md:
out_md.write(json.dumps(cbom, indent=2))
out_md.close()
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--liboqs-root", default=".")
parser.add_argument("--liboqs-version", default="git")
args = parser.parse_args()
update_cbom_if_algs_not_changed(args.liboqs_root, args.liboqs_version)