Skip to content

Commit 5527190

Browse files
committed
[crypto] Cryptolib versioning
This commit adds a versioning concept to the cryptolib. cryptolib_build_info_t contains: - released - is the CL version released or not? - version - pinned version of the CL - scm_revision_low/high - truncated commit hash of sw/device/lib/crypto Signed-off-by: Pascal Nasahl <[email protected]>
1 parent 1a1b939 commit 5527190

File tree

12 files changed

+327
-0
lines changed

12 files changed

+327
-0
lines changed

rules/autogen.bzl

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,73 @@ def autogen_build_info(name):
207207
alwayslink = True,
208208
)
209209

210+
def _cryptolib_build_info_src(ctx):
211+
stamp_args = []
212+
stamp_files = []
213+
if stamping_enabled(ctx):
214+
stamp_files = [ctx.version_file]
215+
stamp_args.append("--ot_version_file")
216+
stamp_args.append(ctx.version_file.path)
217+
else:
218+
print("NOTE: stamping is disabled, the build_info section will use a fixed version string")
219+
stamp_args.append("--default_version")
220+
221+
# The script expects a 20-character long hash: "OpenTitanOpenTitanOT"
222+
stamp_args.append("4f70656e546974616e4f70656e546974616e4f54")
223+
224+
out_source = ctx.actions.declare_file("cryptolib_build_info.c")
225+
ctx.actions.run(
226+
outputs = [
227+
out_source,
228+
],
229+
inputs = [
230+
ctx.executable._tool,
231+
] + stamp_files,
232+
arguments = [
233+
"-o",
234+
out_source.dirname,
235+
] + stamp_args,
236+
executable = ctx.executable._tool,
237+
)
238+
239+
return [
240+
DefaultInfo(files = depset([out_source])),
241+
]
242+
243+
autogen_cryptolib_build_info_src = rule(
244+
implementation = _cryptolib_build_info_src,
245+
attrs = {
246+
"_tool": attr.label(
247+
default = "//util:cryptolib_build_info",
248+
executable = True,
249+
cfg = "exec",
250+
),
251+
} | stamp_attr(-1, "//rules:stamp_flag"),
252+
)
253+
254+
def autogen_cryptolib_build_info(name):
255+
"""Generates a cc_library named `name` that defines the cryptolib ID."""
256+
257+
# Generate a C source file that defines the build ID struct. This is an
258+
# implementation detail and should not be depended on externally.
259+
cryptolib_build_info_src_target = name + "_gen_src"
260+
autogen_cryptolib_build_info_src(name = cryptolib_build_info_src_target)
261+
262+
# Package up the generated source file with its corresponding header file
263+
# and dependencies. Any target that wants access to the build ID should
264+
# depend on this.
265+
native.cc_library(
266+
name = name,
267+
srcs = [cryptolib_build_info_src_target],
268+
hdrs = ["//sw/device/lib/crypto/drivers:cryptolib_build_info.h"],
269+
deps = [
270+
"//sw/device/lib/crypto/include:datatypes",
271+
],
272+
# Make sure to participate in linking so that the symbol is not discarded
273+
# (since it is not meant to be directly used).
274+
alwayslink = True,
275+
)
276+
210277
def _cryptotest_hjson_external(ctx):
211278
"""
212279
Implementation of the Bazel rule for parsing externally-sourced test vectors.

sw/device/lib/crypto/drivers/BUILD

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
package(default_visibility = ["//visibility:public"])
66

7+
load("//rules:autogen.bzl", "autogen_cryptolib_build_info")
78
load("//rules/opentitan:defs.bzl", "OPENTITAN_CPU")
89
load(
910
"//rules:cross_platform.bzl",
@@ -25,6 +26,8 @@ load(
2526
"dicts",
2627
)
2728

29+
autogen_cryptolib_build_info(name = "cryptolib_build_info")
30+
2831
cc_library(
2932
name = "aes",
3033
srcs = ["aes.c"],
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_CRYPTOLIB_BUILD_INFO_H_
6+
#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_CRYPTOLIB_BUILD_INFO_H_
7+
8+
#include <stdint.h>
9+
10+
#include "sw/device/lib/crypto/include/datatypes.h"
11+
12+
/**
13+
* A truncated commit hash from the sw/device/lib/crypto directory from
14+
* the open-source OpenTitan repo that can be used to reproduce the
15+
* cryptolib binary.
16+
*/
17+
typedef struct cryptolib_build_info_scm_revision {
18+
/**
19+
* Least significant word of the truncated commit hash.
20+
*/
21+
uint32_t scm_revision_low;
22+
/**
23+
* Most significant word of the truncated commit hash.
24+
*/
25+
uint32_t scm_revision_high;
26+
} cryptolib_build_info_scm_revision_t;
27+
28+
typedef struct cryptolib_build_info {
29+
/**
30+
* Truncated commit hash.
31+
*/
32+
cryptolib_build_info_scm_revision_t scm_revision;
33+
/**
34+
* Cryptolib version.
35+
*/
36+
uint32_t version;
37+
/**
38+
* Cryptolib released.
39+
*/
40+
bool released;
41+
} cryptolib_build_info_t;
42+
43+
enum {
44+
/**
45+
* Cryptolib version.
46+
* Currently the CL is in development, so this version is not
47+
* frozen.
48+
*/
49+
kCryptoLibVersion = kOtcryptoLibVersion1,
50+
/**
51+
* Indicates whether the cryptolib is released or not.
52+
*/
53+
kCryptoLibReleased = false,
54+
};
55+
56+
/**
57+
* The build information.
58+
*/
59+
extern const cryptolib_build_info_t kCryptoLibBuildInfo;
60+
61+
#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_DRIVERS_CRYPTOLIB_BUILD_INFO_H_

sw/device/lib/crypto/impl/BUILD

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@ cc_library(
4646
],
4747
)
4848

49+
cc_library(
50+
name = "cryptolib_build_info",
51+
srcs = ["cryptolib_build_info.c"],
52+
hdrs = ["//sw/device/lib/crypto/include:cryptolib_build_info.h"],
53+
deps = [
54+
":status",
55+
"//sw/device/lib/crypto/drivers:cryptolib_build_info",
56+
"//sw/device/lib/crypto/include:datatypes",
57+
],
58+
)
59+
4960
cc_library(
5061
name = "drbg",
5162
srcs = ["drbg.c"],
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#include "sw/device/lib/crypto/include/cryptolib_build_info.h"
6+
7+
#include "sw/device/lib/crypto/drivers/cryptolib_build_info.h"
8+
#include "sw/device/lib/crypto/impl/status.h"
9+
#include "sw/device/lib/crypto/include/datatypes.h"
10+
11+
// Module ID for status codes.
12+
#define MODULE_ID MAKE_MODULE_ID('c', 'b', 'i')
13+
14+
otcrypto_status_t otcrypto_build_info(uint32_t *version, bool *released,
15+
uint32_t *build_hash_low,
16+
uint32_t *build_hash_high) {
17+
*version = kCryptoLibBuildInfo.version;
18+
*released = kCryptoLibBuildInfo.released;
19+
*build_hash_low = kCryptoLibBuildInfo.scm_revision.scm_revision_low;
20+
*build_hash_high = kCryptoLibBuildInfo.scm_revision.scm_revision_high;
21+
22+
return OTCRYPTO_OK;
23+
}

sw/device/lib/crypto/include/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ cc_library(
2525
hdrs = [
2626
"aes.h",
2727
"aes_gcm.h",
28+
"cryptolib_build_info.h",
2829
"datatypes.h",
2930
"drbg.h",
3031
"ecc_p256.h",
@@ -57,6 +58,7 @@ cc_library(
5758
hdrs = [
5859
"aes.h",
5960
"aes_gcm.h",
61+
"cryptolib_build_info.h",
6062
"datatypes.h",
6163
"drbg.h",
6264
"ecc_p256.h",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// Copyright lowRISC contributors (OpenTitan project).
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
5+
#ifndef OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CRYPTOLIB_BUILD_INFO_H_
6+
#define OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CRYPTOLIB_BUILD_INFO_H_
7+
8+
#include "datatypes.h"
9+
10+
/**
11+
* @file
12+
* @brief Cryptolib build information.
13+
*
14+
* Returns the version of the cryptolib as well as the git hash.
15+
*/
16+
17+
#ifdef __cplusplus
18+
extern "C" {
19+
#endif // __cplusplus
20+
21+
/**
22+
* Read the cryptolib build information.
23+
*
24+
* Returns the current version of the cryptolib as well as the
25+
* latest git commit hash of the `sw/device/lib/crypto` directory.
26+
*
27+
* @param ctx Pointer to the generic HMAC context struct.
28+
* @param[out] version The current version of the cryptolib.
29+
* @param[out] build_hash_low The low portion of the git commit hash of
30+
* `sw/device/lib/crypto`.
31+
* @param[out] build_hash_high The high portion of the git commit hash of
32+
* `sw/device/lib/crypto`.
33+
* @return Result of the HMAC final operation.
34+
*/
35+
otcrypto_status_t otcrypto_build_info(uint32_t *version, bool *released,
36+
uint32_t *build_hash_low,
37+
uint32_t *build_hash_high);
38+
39+
#ifdef __cplusplus
40+
} // extern "C"
41+
#endif // __cplusplus
42+
43+
#endif // OPENTITAN_SW_DEVICE_LIB_CRYPTO_INCLUDE_CRYPTOLIB_BUILD_INFO_H_

sw/device/lib/crypto/include/otcrypto.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
#include "aes.h"
99
#include "aes_gcm.h"
10+
#include "cryptolib_build_info.h"
1011
#include "datatypes.h"
1112
#include "drbg.h"
1213
#include "ecc_p256.h"

util/BUILD

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ py_test(
3333
],
3434
)
3535

36+
py_binary(
37+
name = "cryptolib_build_info",
38+
srcs = ["cryptolib_build_info.py"],
39+
)
40+
3641
py_binary(
3742
name = "regtool",
3843
srcs = ["regtool.py"],

util/cryptolib_build_info.py

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
#!/usr/bin/env python3
2+
# Copyright lowRISC contributors (OpenTitan project).
3+
# Licensed under the Apache License, Version 2.0, see LICENSE for details.
4+
# SPDX-License-Identifier: Apache-2.0
5+
"""Generates cryptolib_build_info.c for cryptolib build."""
6+
7+
import argparse
8+
import logging as log
9+
from pathlib import Path
10+
11+
import version_file
12+
13+
14+
def generate_build_info_c_source(scm_revision: int) -> str:
15+
"""Return the contents of a C source file that defines `kCryptoLibBuildInfo`.
16+
17+
Args:
18+
scm_revision: SHA1 sum identifying the current SCM revision.
19+
"""
20+
SHA1_BYTE_CNT = 20
21+
assert 0 < scm_revision < 2**(SHA1_BYTE_CNT * 8)
22+
scm_rev_byte_be = scm_revision.to_bytes(SHA1_BYTE_CNT, "big")
23+
scm_revision_high = int.from_bytes(scm_rev_byte_be[0:4], "big")
24+
scm_revision_low = int.from_bytes(scm_rev_byte_be[4:8], "big")
25+
26+
return f"""
27+
// Copyright lowRISC contributors (OpenTitan project).
28+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
29+
// SPDX-License-Identifier: Apache-2.0
30+
//
31+
// --------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! ---------//
32+
33+
#include "sw/device/lib/crypto/drivers/cryptolib_build_info.h"
34+
35+
#include "sw/device/lib/crypto/include/datatypes.h"
36+
37+
OT_USED
38+
const cryptolib_build_info_t kCryptoLibBuildInfo = {{
39+
.scm_revision = (cryptolib_build_info_scm_revision_t){{
40+
.scm_revision_low = {scm_revision_low:#010x},
41+
.scm_revision_high = {scm_revision_high:#010x},
42+
}},
43+
.version = (uint32_t)kCryptoLibVersion,
44+
.released = (bool)kCryptoLibReleased,
45+
}};
46+
"""
47+
48+
49+
def read_version_file(version_info_path, default_version) -> int:
50+
"""
51+
Search for the scm revision variable and interprets
52+
the contents as a big-endian hex literal. Return an error
53+
if the revision cannot be found.
54+
"""
55+
56+
version_info = version_file.VersionInformation(version_info_path)
57+
version = version_info.cryptolib_scm_revision(default_version)
58+
return int(version, base=16)
59+
60+
61+
def write_source_file(outdir: Path, contents: str) -> Path:
62+
"""Creates cryptolib_build_info.c in `outdir`. Returns the path to the new file."""
63+
64+
source_out_path = outdir / "cryptolib_build_info.c"
65+
66+
outdir.mkdir(parents=True, exist_ok=True)
67+
with source_out_path.open(mode='w', encoding='utf-8') as fout:
68+
fout.write(contents)
69+
70+
return source_out_path
71+
72+
73+
def main():
74+
log.basicConfig(format="%(levelname)s: %(message)s")
75+
76+
parser = argparse.ArgumentParser(prog="cryptolib_build_info")
77+
parser.add_argument('--outdir',
78+
'-o',
79+
required=True,
80+
type=Path,
81+
help='Output Directory')
82+
parser.add_argument('--ot_version_file',
83+
type=Path,
84+
help='Path to a file with the OpenTitan Version')
85+
parser.add_argument('--default_version',
86+
type=str,
87+
help='Version to use if the version file does not indicate a version')
88+
89+
args = parser.parse_args()
90+
91+
# Extract version stamp from file
92+
version = read_version_file(args.ot_version_file, args.default_version)
93+
log.info("Version: %x" % (version, ))
94+
95+
generated_source = generate_build_info_c_source(version)
96+
out_path = write_source_file(args.outdir, generated_source)
97+
log.info("Generated new source file: %s" % (out_path))
98+
99+
100+
if __name__ == "__main__":
101+
main()

0 commit comments

Comments
 (0)