Repository: chipsalliance/caliptra-sw
Pull request #210 (2023-04-26 17:54:46)

[feat] Update The Certificate With Dates From Manifest Header
The FMC Alias Certificate was getting populated with default values for "not_before" and "not_after" fields. This PR will let the certificate date fields get populated using the values from manifest. 


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 78eab196..7fc6b928 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -13,6 +13,15 @@ dependencies = [
  "cpufeatures",
 ]
 
+[[package]]
+name = "android_system_properties"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "anyhow"
 version = "1.0.70"
@@ -100,6 +109,12 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "bumpalo"
+version = "3.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+
 [[package]]
 name = "byteorder"
 version = "1.4.3"
@@ -300,6 +315,7 @@ dependencies = [
  "caliptra-image-openssl",
  "caliptra-image-serde",
  "caliptra-image-types",
+ "chrono",
  "clap",
  "hex",
  "openssl",
@@ -553,8 +569,13 @@ version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
+ "iana-time-zone",
+ "js-sys",
  "num-integer",
  "num-traits",
+ "time",
+ "wasm-bindgen",
+ "winapi",
 ]
 
 [[package]]
@@ -588,6 +609,16 @@ dependencies = [
  "os_str_bytes",
 ]
 
+[[package]]
+name = "codespan-reporting"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e"
+dependencies = [
+ "termcolor",
+ "unicode-width",
+]
+
 [[package]]
 name = "compliance-test"
 version = "0.1.0"
@@ -614,6 +645,12 @@ dependencies = [
  "unicode-segmentation",
 ]
 
+[[package]]
+name = "core-foundation-sys"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa"
+
 [[package]]
 name = "cpufeatures"
 version = "0.2.5"
@@ -645,6 +682,50 @@ dependencies = [
  "typenum",
 ]
 
+[[package]]
+name = "cxx"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f61f1b6389c3fe1c316bf8a4dccc90a38208354b330925bce1f74a6c4756eb93"
+dependencies = [
+ "cc",
+ "cxxbridge-flags",
+ "cxxbridge-macro",
+ "link-cplusplus",
+]
+
+[[package]]
+name = "cxx-build"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "12cee708e8962df2aeb38f594aae5d827c022b6460ac71a7a3e2c3c2aae5a07b"
+dependencies = [
+ "cc",
+ "codespan-reporting",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "scratch",
+ "syn 2.0.5",
+]
+
+[[package]]
+name = "cxxbridge-flags"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7944172ae7e4068c533afbb984114a56c46e9ccddda550499caa222902c7f7bb"
+
+[[package]]
+name = "cxxbridge-macro"
+version = "1.0.94"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2345488264226bf682893e25de0769f3360aac9957980ec49361b083ddaa5bc5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.5",
+]
+
 [[package]]
 name = "der"
 version = "0.6.1"
@@ -778,7 +859,7 @@ checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi",
+ "wasi 0.11.0+wasi-snapshot-preview1",
 ]
 
 [[package]]
@@ -822,6 +903,30 @@ dependencies = [
  "digest",
 ]
 
+[[package]]
+name = "iana-time-zone"
+version = "0.1.56"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0722cd7114b7de04316e7ea5456a0bbb20e4adb46fd27a3697adb812cff0f37c"
+dependencies = [
+ "android_system_properties",
+ "core-foundation-sys",
+ "iana-time-zone-haiku",
+ "js-sys",
+ "wasm-bindgen",
+ "windows",
+]
+
+[[package]]
+name = "iana-time-zone-haiku"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0703ae284fc167426161c2e3f1da3ea71d94b21bedbcc9494e92b28e334e3dca"
+dependencies = [
+ "cxx",
+ "cxx-build",
+]
+
 [[package]]
 name = "indexmap"
 version = "1.9.2"
@@ -842,6 +947,15 @@ dependencies = [
  "generic-array",
 ]
 
+[[package]]
+name = "js-sys"
+version = "0.3.61"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+dependencies = [
+ "wasm-bindgen",
+]
+
 [[package]]
 name = "lazy_static"
 version = "1.4.0"
@@ -854,6 +968,15 @@ version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
 
+[[package]]
+name = "link-cplusplus"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ecd207c9c713c34f95a097a5b029ac2ce6010530c7b49d7fea24d977dede04f5"
+dependencies = [
+ "cc",
+]
+
 [[package]]
 name = "log"
 version = "0.4.17"
@@ -1061,6 +1184,12 @@ dependencies = [
  "zeroize",
 ]
 
+[[package]]
+name = "scratch"
+version = "1.0.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
+
 [[package]]
 name = "sec1"
 version = "0.3.0"
@@ -1180,12 +1309,32 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "termcolor"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
+dependencies = [
+ "winapi-util",
+]
+
 [[package]]
 name = "textwrap"
 version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d"
 
+[[package]]
+name = "time"
+version = "0.1.45"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a"
+dependencies = [
+ "libc",
+ "wasi 0.10.0+wasi-snapshot-preview1",
+ "winapi",
+]
+
 [[package]]
 name = "tock-registers"
 version = "0.8.1"
@@ -1270,6 +1419,12 @@ version = "1.10.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
 
+[[package]]
+name = "unicode-width"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b"
+
 [[package]]
 name = "ureg"
 version = "0.1.0"
@@ -1307,12 +1462,169 @@ version = "0.9.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
+[[package]]
+name = "wasi"
+version = "0.10.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
+
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
+[[package]]
+name = "wasm-bindgen"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+dependencies = [
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 1.0.109",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.84"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+
+[[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
+name = "windows"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
 [[package]]
 name = "winnow"
 version = "0.3.6"
diff --git a/image/app/Cargo.toml b/image/app/Cargo.toml
index 8d4721ae..7a6c03ec 100644
--- a/image/app/Cargo.toml
+++ b/image/app/Cargo.toml
@@ -20,4 +20,4 @@ openssl = "0.10.48"
 zerocopy = "0.6.1"
 anyhow = "1.0.70"
 hex = "0.4.3"
-
+chrono = "0.4.24"
diff --git a/image/app/src/create/mod.rs b/image/app/src/create/mod.rs
index cfb8e4a9..6117d63c 100644
--- a/image/app/src/create/mod.rs
+++ b/image/app/src/create/mod.rs
@@ -14,6 +14,7 @@ Abstract:
 
 mod config;
 
+use anyhow::anyhow;
 use anyhow::Context;
 use caliptra_image_gen::*;
 use caliptra_image_openssl::ecc_priv_key_from_pem;
@@ -27,6 +28,46 @@ use std::path::PathBuf;
 use caliptra_image_elf::ElfExecutable;
 use config::{OwnerKeyConfig, VendorKeyConfig};
 
+use chrono::NaiveDate;
+
+///
+/// This function takes the string as the input
+/// and extracts year, month and day from the string
+/// and then performs some basic validity checks
+///
+fn check_date(from_date: &str, to_date: &str) -> anyhow::Result<bool> {
+    let time_fmt = "YYYYMMDDHHMMSS";
+
+    let current_date = chrono::Utc::now().date_naive();
+
+    if from_date.len() < time_fmt.len() || to_date.len() < time_fmt.len() {
+        return Err(anyhow!("Invalid Date Input Format"));
+    }
+
+    let from_date_str: &str = &from_date[0..8];
+    let to_date_str: &str = &to_date[0..8];
+
+    let from_date_in = match NaiveDate::parse_from_str(from_date_str, "%Y%m%d") {
+        Ok(d) => d,
+        Err(_) => return Err(anyhow!("Invalid From Date Input Format")),
+    };
+
+    let to_date_in = match NaiveDate::parse_from_str(to_date_str, "%Y%m%d") {
+        Ok(d) => d,
+        Err(_) => return Err(anyhow!("Invalid To Date Input Format")),
+    };
+
+    if from_date_in < current_date || to_date_in < current_date {
+        return Err(anyhow!("Invalid Input Date"));
+    }
+
+    if from_date_in > to_date_in {
+        return Err(anyhow!("From Date Is greater Than To Date"));
+    }
+
+    Ok(true)
+}
+
 /// Run the command
 pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> {
     let config_path: &PathBuf = args
@@ -73,6 +114,32 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> {
         .get_one::<PathBuf>("out")
         .with_context(|| "out arg not specified")?;
 
+    //YYYYMMDDHHMMSS - Zulu Time
+    let mut own_from_date: [u8; 15] = [0u8; 15];
+    let mut own_to_date: [u8; 15] = [0u8; 15];
+    if let Some(from_date) = args.get_one::<String>("own-from-date") {
+        if let Some(to_date) = args.get_one::<String>("own-to-date") {
+            check_date(from_date, to_date)?;
+            own_from_date[0..14].copy_from_slice(&from_date.as_bytes()[0..14]);
+            own_from_date[14] = b'Z';
+            own_to_date[0..14].copy_from_slice(&to_date.as_bytes()[0..14]);
+            own_to_date[14] = b'Z';
+        }
+    }
+
+    //YYYYMMDDHHMMSS - Zulu Time
+    let mut mfg_from_date: [u8; 15] = [0u8; 15];
+    let mut mfg_to_date: [u8; 15] = [0u8; 15];
+    if let Some(from_date) = args.get_one::<String>("mfg-from-date") {
+        if let Some(to_date) = args.get_one::<String>("mfg-to-date") {
+            check_date(from_date, to_date)?;
+            mfg_from_date[0..14].copy_from_slice(&from_date.as_bytes()[0..14]);
+            mfg_from_date[14] = b'Z';
+            mfg_to_date[0..14].clone_from_slice(&to_date.as_bytes()[0..14]);
+            mfg_to_date[14] = b'Z';
+        }
+    }
+
     let config = config::load_key_config(config_path)?;
 
     let fmc_rev = hex::decode(fmc_rev)?;
@@ -96,8 +163,14 @@ pub(crate) fn run_cmd(args: &ArgMatches) -> anyhow::Result<()> {
         .with_context(|| "Invalid parent path")?;
 
     let gen_config = ImageGeneratorConfig::<ElfExecutable> {
-        vendor_config: vendor_config(config_dir, &config.vendor, *ecc_key_idx)?,
-        owner_config: owner_config(config_dir, &config.owner)?,
+        vendor_config: vendor_config(
+            config_dir,
+            &config.vendor,
+            *ecc_key_idx,
+            mfg_from_date,
+            mfg_to_date,
+        )?,
+        owner_config: owner_config(config_dir, &config.owner, own_from_date, own_to_date)?,
         fmc,
         runtime,
     };
@@ -123,6 +196,8 @@ fn vendor_config(
     path: &Path,
     config: &VendorKeyConfig,
     ecc_key_idx: u32,
+    from_date: [u8; 15],
+    to_date: [u8; 15],
 ) -> anyhow::Result<ImageGeneratorVendorConfig> {
     let mut gen_config = ImageGeneratorVendorConfig::default();
     let ecc_pub_keys = &config.ecc_pub_keys;
@@ -150,6 +225,8 @@ fn vendor_config(
     }
 
     gen_config.ecc_key_idx = ecc_key_idx;
+    gen_config.not_before = from_date;
+    gen_config.not_after = to_date;
 
     Ok(gen_config)
 }
@@ -158,6 +235,8 @@ fn vendor_config(
 fn owner_config(
     path: &Path,
     config: &Option<OwnerKeyConfig>,
+    from_date: [u8; 15],
+    to_date: [u8; 15],
 ) -> anyhow::Result<Option<ImageGeneratorOwnerConfig>> {
     if let Some(config) = config {
         let mut gen_config = ImageGeneratorOwnerConfig::default();
@@ -172,6 +251,8 @@ fn owner_config(
             priv_keys.ecc_priv_key = ecc_priv_key_from_pem(&pub_key_path)?;
             gen_config.priv_keys = Some(priv_keys);
         }
+        gen_config.not_before = from_date;
+        gen_config.not_after = to_date;
 
         Ok(Some(gen_config))
     } else {
diff --git a/image/app/src/main.rs b/image/app/src/main.rs
index e54c27d4..d24cdadd 100644
--- a/image/app/src/main.rs
+++ b/image/app/src/main.rs
@@ -75,6 +75,26 @@ fn main() {
             arg!(--"out" <FILE> "Output file")
                 .required(true)
                 .value_parser(value_parser!(PathBuf)),
+        )
+        .arg(
+            arg!(--"own-from-date" <String> "Certificate Validity Start Date By Owner [YYYYMMDDHHMMSS - Zulu Time]")
+                .required(false)
+                .value_parser(value_parser!(String)),
+        )
+        .arg(
+            arg!(--"own-to-date" <String> "Certificate Validity End Date By Owner [YYYYMMDDHHMMSS - Zulu Time]")
+                .required(false)
+                .value_parser(value_parser!(String)),
+        )
+        .arg(
+            arg!(--"mfg-from-date" <String> "Certificate Validity Start Date By Manufacturer [YYYYMMDDHHMMSS - Zulu Time]")
+                .required(false)
+                .value_parser(value_parser!(String)),
+        )
+        .arg(
+            arg!(--"mfg-to-date" <String> "Certificate Validity End Date By Manufacturer [YYYYMMDDHHMMSS - Zulu Time]")
+                .required(false)
+                .value_parser(value_parser!(String)),
         )];
 
     let cmd = Command::new("caliptra-image-app")
diff --git a/image/fake-keys/src/lib.rs b/image/fake-keys/src/lib.rs
index 30fd69b4..94458850 100644
--- a/image/fake-keys/src/lib.rs
+++ b/image/fake-keys/src/lib.rs
@@ -125,6 +125,8 @@ pub const VENDOR_CONFIG_KEY_0: ImageGeneratorVendorConfig = ImageGeneratorVendor
     pub_keys: VENDOR_PUBLIC_KEYS,
     ecc_key_idx: 0,
     priv_keys: Some(VENDOR_PRIVATE_KEYS),
+    not_before: [0u8; 15],
+    not_after: [0u8; 15],
 };
 
 pub const VENDOR_CONFIG_KEY_1: ImageGeneratorVendorConfig = ImageGeneratorVendorConfig {
@@ -149,4 +151,6 @@ pub const OWNER_CONFIG: ImageGeneratorOwnerConfig = ImageGeneratorOwnerConfig {
     priv_keys: Some(ImageOwnerPrivKeys {
         ecc_priv_key: OWNER_KEY_PRIVATE,
     }),
+    not_before: [0u8; 15],
+    not_after: [0u8; 15],
 };
diff --git a/image/gen/src/generator.rs b/image/gen/src/generator.rs
index ec421b8d..d1483150 100644
--- a/image/gen/src/generator.rs
+++ b/image/gen/src/generator.rs
@@ -63,7 +63,7 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
 
         // Create Header
         let toc_digest = self.toc_digest(&fmc_toc, &runtime_toc)?;
-        let header = self.gen_header(ecc_key_idx, Self::DEFAULT_FLAGS, toc_digest)?;
+        let header = self.gen_header(config, ecc_key_idx, Self::DEFAULT_FLAGS, toc_digest)?;
 
         // Create Preamable
         let header_digest = self.header_digest(&header)?;
@@ -138,19 +138,32 @@ impl<Crypto: ImageGeneratorCrypto> ImageGenerator<Crypto> {
     }
 
     /// Generate header
-    fn gen_header(
+    fn gen_header<E>(
         &self,
+        config: &ImageGeneratorConfig<E>,
         ecc_key_idx: u32,
         flags: u32,
         digest: ImageDigest,
-    ) -> anyhow::Result<ImageHeader> {
-        let header = ImageHeader {
+    ) -> anyhow::Result<ImageHeader>
+    where
+        E: ImageGenratorExecutable,
+    {
+        let mut header = ImageHeader {
             vendor_ecc_pub_key_idx: ecc_key_idx,
             flags,
             toc_len: MAX_TOC_ENTRY_COUNT,
             toc_digest: digest,
             ..Default::default()
         };
+
+        header.vendor_not_before = config.vendor_config.not_before;
+        header.vendor_not_after = config.vendor_config.not_after;
+
+        if let Some(owner_config) = &config.owner_config {
+            header.owner_data.owner_not_before = owner_config.not_before;
+            header.owner_data.owner_not_after = owner_config.not_after;
+        }
+
         Ok(header)
     }
 
diff --git a/image/gen/src/lib.rs b/image/gen/src/lib.rs
index 9239da88..567a7056 100644
--- a/image/gen/src/lib.rs
+++ b/image/gen/src/lib.rs
@@ -64,6 +64,10 @@ pub struct ImageGeneratorVendorConfig {
     pub ecc_key_idx: u32,
 
     pub priv_keys: Option<ImageVendorPrivKeys>,
+
+    pub not_before: [u8; 15],
+
+    pub not_after: [u8; 15],
 }
 
 /// Image Generator Owner Configuration
@@ -72,6 +76,10 @@ pub struct ImageGeneratorOwnerConfig {
     pub pub_keys: ImageOwnerPubKeys,
 
     pub priv_keys: Option<ImageOwnerPrivKeys>,
+
+    pub not_before: [u8; 15],
+
+    pub not_after: [u8; 15],
 }
 
 /// Image Generator Configuration
diff --git a/image/types/src/lib.rs b/image/types/src/lib.rs
index 1fc42bde..148dae7f 100644
--- a/image/types/src/lib.rs
+++ b/image/types/src/lib.rs
@@ -213,6 +213,16 @@ pub struct ImagePreamble {
     pub _rsvd: [u32; 2],
 }
 
+#[repr(C)]
+#[derive(AsBytes, FromBytes, Default, Debug)]
+pub struct OwnerSignedData {
+    /// Owner Start Date [ASN1 Time Format] For LDEV-Id certificate: Takes Preference over vendor start date
+    pub owner_not_before: [u8; 15],
+
+    /// Owner End Date [ASN1 Time Format] For LDEV-Id certificate: Takes Preference over vendor end date
+    pub owner_not_after: [u8; 15],
+}
+
 /// Caliptra Image header
 #[repr(C)]
 #[derive(AsBytes, FromBytes, Default, Debug)]
@@ -231,6 +241,15 @@ pub struct ImageHeader {
 
     /// TOC Digest
     pub toc_digest: ImageDigest,
+
+    /// Vendor Start Date [ASN1 Time Format] For LDEV-Id certificate
+    pub vendor_not_before: [u8; 15],
+
+    /// Vendor End Date [ASN1 Time Format] For LDEV-Id certificate
+    pub vendor_not_after: [u8; 15],
+
+    /// The Signed owner data
+    pub owner_data: OwnerSignedData,
 }
 
 /// Caliptra table contents entry id
diff --git a/rom/dev/src/flow/cold_reset/fmc_alias.rs b/rom/dev/src/flow/cold_reset/fmc_alias.rs
index 7a591dc2..6ca200a2 100644
--- a/rom/dev/src/flow/cold_reset/fmc_alias.rs
+++ b/rom/dev/src/flow/cold_reset/fmc_alias.rs
@@ -28,7 +28,7 @@ use caliptra_drivers::{
 };
 use caliptra_image_types::{ImageManifest, IMAGE_BYTE_SIZE};
 use caliptra_image_verify::{ImageVerificationInfo, ImageVerifier};
-use caliptra_x509::{FmcAliasCertTbs, FmcAliasCertTbsParams};
+use caliptra_x509::{FmcAliasCertTbs, FmcAliasCertTbsParams, NotAfter, NotBefore};
 use zerocopy::{AsBytes, FromBytes};
 
 extern "C" {
@@ -52,12 +52,14 @@ impl DiceLayer for FmcAliasLayer {
     /// Perform derivations for the DICE layer
     fn derive(env: &RomEnv, input: &DiceInput) -> CaliptraResult<DiceOutput> {
         cprintln!("[afmc] ++");
-        cprintln!("[afmc] CDI.KEYID = {}", input.cdi as u8);
-        cprintln!("[afmc] SUBJECT.KEYID = {}", input.subj_priv_key as u8);
-        cprintln!(
-            "[afmc] AUTHORITY.KEYID = {}",
-            input.auth_key_pair.priv_key as u8
-        );
+
+        // To Do : Disabling the Prints Temporarily
+        //cprintln!("[afmc] CDI.KEYID = {}", input.cdi as u8);
+        //cprintln!("[afmc] SUBJECT.KEYID = {}", input.subj_priv_key as u8);
+        // cprintln!(
+        //     "[afmc] AUTHORITY.KEYID = {}",
+        //     input.auth_key_pair.priv_key as u8
+        // );
 
         // Download the image
         let mut txn = Self::download_image(env)?;
@@ -102,8 +104,30 @@ impl DiceLayer for FmcAliasLayer {
         // Generate the output for next layer
         let output = input.to_output(key_pair, subj_sn, subj_key_id);
 
+        // if there is a valid value in the manifest for the not_before and not_after
+        // we take it from there.
+
+        let mut nb = NotBefore::default();
+        let mut nf = NotAfter::default();
+        let null_time = [0u8; 15];
+
+        if manifest.header.vendor_not_after != null_time
+            && manifest.header.vendor_not_before != null_time
+        {
+            nf.not_after = manifest.header.vendor_not_after;
+            nb.not_before = manifest.header.vendor_not_before;
+        }
+
+        //The owner values takes preference
+        if manifest.header.owner_data.owner_not_after != null_time
+            && manifest.header.owner_data.owner_not_before != null_time
+        {
+            nf.not_after = manifest.header.owner_data.owner_not_after;
+            nb.not_before = manifest.header.owner_data.owner_not_before;
+        }
+
         // Generate Local Device ID Certificate
-        Self::generate_cert_sig(env, input, &output)?;
+        Self::generate_cert_sig(env, input, &output, &nb.not_before, &nf.not_after)?;
 
         cprintln!("[afmc] --");
 
@@ -358,6 +382,8 @@ impl FmcAliasLayer {
         env: &RomEnv,
         input: &DiceInput,
         output: &DiceOutput,
+        not_before: &[u8; FmcAliasCertTbsParams::NOT_BEFORE_LEN],
+        not_after: &[u8; FmcAliasCertTbsParams::NOT_AFTER_LEN],
     ) -> CaliptraResult<()> {
         let auth_priv_key = input.auth_key_pair.priv_key;
         let auth_pub_key = &input.auth_key_pair.pub_key;
@@ -374,6 +400,8 @@ impl FmcAliasLayer {
             public_key: &pub_key.to_der(),
             tcb_info_fmc_tci: &env.data_vault().map(|d| d.fmc_tci()).into(),
             tcb_info_owner_pk_hash: &env.data_vault().map(|d| d.owner_pk_hash()).into(),
+            not_before,
+            not_after,
         };
 
         // Generate the `To Be Signed` portion of the CSR
diff --git a/rom/dev/src/flow/cold_reset/ldev_id.rs b/rom/dev/src/flow/cold_reset/ldev_id.rs
index 090c918e..5a4a1f05 100644
--- a/rom/dev/src/flow/cold_reset/ldev_id.rs
+++ b/rom/dev/src/flow/cold_reset/ldev_id.rs
@@ -152,6 +152,8 @@ impl LocalDevIdLayer {
             authority_key_id: &input.auth_key_id,
             serial_number: &X509::cert_sn(env, pub_key)?,
             public_key: &pub_key.to_der(),
+            not_before: &NotBefore::default().not_before,
+            not_after: &NotAfter::default().not_after,
         };
 
         // Generate the `To Be Signed` portion of the CSR
@@ -165,7 +167,8 @@ impl LocalDevIdLayer {
         let sig = Crypto::ecdsa384_sign(env, auth_priv_key, tbs.tbs())?;
 
         // Clear the authority private key
-        cprintln!("[ldev] Erasing AUTHORITY.KEYID = {}", auth_priv_key as u8);
+        //To-Do : Disabling The Print Temporarily
+        //cprintln!("[ldev] Erasing AUTHORITY.KEYID = {}", auth_priv_key as u8);
         env.key_vault().map(|k| k.erase_key(auth_priv_key))?;
 
         // Verify the signature of the `To Be Signed` portion
diff --git a/x509/build/cert.rs b/x509/build/cert.rs
index 8462a130..2b20d61a 100644
--- a/x509/build/cert.rs
+++ b/x509/build/cert.rs
@@ -145,12 +145,25 @@ impl<Algo: SigningAlgorithm> CertTemplateBuilder<Algo> {
         self.builder.set_version(2).unwrap();
 
         // Set the valid from time
-        let valid_from = Asn1Time::from_str("20230101000000Z").unwrap();
+        let not_before = "20230101000000Z";
+        let valid_from = Asn1Time::from_str(not_before).unwrap();
         self.builder.set_not_before(&valid_from).unwrap();
+        let param = CertTemplateParam {
+            tbs_param: TbsParam::new("NOT_BEFORE", 0, not_before.len()),
+            needle: not_before.as_bytes().to_vec(),
+        };
+
+        self.params.push(param);
 
         // Set the valid to time
-        let valid_to = Asn1Time::from_str("99991231235959Z").unwrap();
+        let not_after = "99991231235959Z";
+        let valid_to = Asn1Time::from_str(not_after).unwrap();
         self.builder.set_not_after(&valid_to).unwrap();
+        let param = CertTemplateParam {
+            tbs_param: TbsParam::new("NOT_AFTER", 0, not_after.len()),
+            needle: not_after.as_bytes().to_vec(),
+        };
+        self.params.push(param);
 
         // Set the serial number
         let serial_number_bytes = [0x7Fu8; 20];
diff --git a/x509/src/fmc_alias_cert.rs b/x509/src/fmc_alias_cert.rs
index 436bac5f..a6506c8f 100644
--- a/x509/src/fmc_alias_cert.rs
+++ b/x509/src/fmc_alias_cert.rs
@@ -17,13 +17,13 @@ include!(concat!(env!("OUT_DIR"), "/fmc_alias_cert_tbs.rs"));
 
 #[cfg(all(test, target_family = "unix"))]
 mod tests {
+    use super::*;
+    use crate::test_util::tests::*;
+    use crate::{NotAfter, NotBefore};
     use openssl::ecdsa::EcdsaSig;
     use openssl::sha::Sha384;
     use openssl::x509::X509;
 
-    use super::*;
-    use crate::test_util::tests::*;
-
     #[test]
     fn test_cert_signing() {
         let subject_key = Ecc384AsymKey::default();
@@ -56,6 +56,8 @@ mod tests {
                 .unwrap(),
             tcb_info_owner_pk_hash: &[0xCDu8; FmcAliasCertTbsParams::TCB_INFO_OWNER_PK_HASH_LEN],
             tcb_info_fmc_tci: &[0xEFu8; FmcAliasCertTbsParams::TCB_INFO_FMC_TCI_LEN],
+            not_before: &NotBefore::default().not_before,
+            not_after: &NotAfter::default().not_after,
         };
 
         let cert = FmcAliasCertTbs::new(&params);
diff --git a/x509/src/ldevid_cert.rs b/x509/src/ldevid_cert.rs
index eec50504..164d13ee 100644
--- a/x509/src/ldevid_cert.rs
+++ b/x509/src/ldevid_cert.rs
@@ -23,6 +23,7 @@ mod tests {
 
     use super::*;
     use crate::test_util::tests::*;
+    use crate::{NotAfter, NotBefore};
 
     #[test]
     fn test_cert_signing() {
@@ -55,6 +56,8 @@ mod tests {
                     issuer_key.sha1(),
                 )
                 .unwrap(),
+            not_before: &NotBefore::default().not_before,
+            not_after: &NotAfter::default().not_after,
         };
 
         let cert = LocalDevIdCertTbs::new(&params);
diff --git a/x509/src/lib.rs b/x509/src/lib.rs
index 1e329a55..5023af6d 100644
--- a/x509/src/lib.rs
+++ b/x509/src/lib.rs
@@ -26,3 +26,35 @@ pub use fmc_alias_cert::{FmcAliasCertTbs, FmcAliasCertTbsParams};
 pub use idevid_csr::{InitDevIdCsrTbs, InitDevIdCsrTbsParams};
 pub use ldevid_cert::{LocalDevIdCertTbs, LocalDevIdCertTbsParams};
 pub use rt_alias_cert::{RtAliasCertTbs, RtAliasCertTbsParams};
+
+pub struct NotBefore {
+    pub not_before: [u8; 15],
+}
+
+impl Default for NotBefore {
+    fn default() -> Self {
+        let not_before = "20230101000000Z";
+        let mut nb: NotBefore = NotBefore {
+            not_before: [0u8; 15],
+        };
+
+        nb.not_before.copy_from_slice(not_before.as_bytes());
+        nb
+    }
+}
+
+pub struct NotAfter {
+    pub not_after: [u8; 15],
+}
+
+impl Default for NotAfter {
+    fn default() -> Self {
+        let not_after = "99991231235959Z";
+        let mut nb: NotAfter = NotAfter {
+            not_after: [0u8; 15],
+        };
+
+        nb.not_after.copy_from_slice(not_after.as_bytes());
+        nb
+    }
+}
diff --git a/x509/src/rt_alias_cert.rs b/x509/src/rt_alias_cert.rs
index fcf5451c..f6432c13 100644
--- a/x509/src/rt_alias_cert.rs
+++ b/x509/src/rt_alias_cert.rs
@@ -23,6 +23,7 @@ mod tests {
 
     use super::*;
     use crate::test_util::tests::*;
+    use crate::{NotAfter, NotBefore};
 
     #[test]
     fn test_cert_signing() {
@@ -54,6 +55,8 @@ mod tests {
             )
             .unwrap(),
             tcb_info_rt_tci: &[0xEFu8; RtAliasCertTbsParams::TCB_INFO_RT_TCI_LEN],
+            not_before: &NotBefore::default().not_before,
+            not_after: &NotAfter::default().not_after,
         };
 
         let cert = RtAliasCertTbs::new(&params);


Test patch:
diff --git a/rom/dev/tests/test_image_validation.rs b/rom/dev/tests/test_image_validation.rs
index 3d662af9..eece203c 100644
--- a/rom/dev/tests/test_image_validation.rs
+++ b/rom/dev/tests/test_image_validation.rs
@@ -1189,6 +1189,87 @@ fn test_runtime_svn_less_than_fuse_svn() {
     );
 }
 
+#[test]
+fn cert_test_with_custom_dates() {
+    pub const TEST_FMC_WITH_UART: FwId = FwId {
+        crate_name: "caliptra-rom-test-fmc",
+        bin_name: "caliptra-rom-test-fmc",
+        features: &["emu"],
+    };
+
+    let fuses = Fuses::default();
+    let rom = caliptra_builder::build_firmware_rom(&ROM_WITH_UART).unwrap();
+    let mut hw = caliptra_hw_model::new(BootParams {
+        init_params: InitParams {
+            rom: &rom,
+            security_state: SecurityState::from(fuses.life_cycle as u32),
+            ..Default::default()
+        },
+        fuses,
+        fw_image: None,
+    })
+    .unwrap();
+
+    let mut opts = ImageOptions::default();
+
+    opts.vendor_config
+        .not_before
+        .copy_from_slice("20250101000000Z".as_bytes());
+
+    opts.vendor_config
+        .not_after
+        .copy_from_slice("20260101000000Z".as_bytes());
+
+    let mut own_config = opts.owner_config.unwrap();
+
+    own_config
+        .not_before
+        .copy_from_slice("20270101000000Z".as_bytes());
+    own_config
+        .not_after
+        .copy_from_slice("20280101000000Z".as_bytes());
+
+    opts.owner_config = Some(own_config);
+
+    let image_bundle =
+        caliptra_builder::build_and_sign_image(&TEST_FMC_WITH_UART, &APP_WITH_UART, opts).unwrap();
+
+    let mut output = vec![];
+
+    // Set gen_idev_id_csr to generate CSR.
+    let flags = MfgFlags::GENERATE_IDEVID_CSR;
+    hw.soc_ifc()
+        .cptra_dbg_manuf_service_reg()
+        .write(|_| flags.bits());
+
+    #[cfg(feature = "verilator")]
+    {
+        // [TODO] Download the CSR from the mailbox and set the gen_idev_id_csr bit 0.
+    }
+
+    hw.step_until(|m| m.soc_ifc().cptra_flow_status().read().ready_for_fw());
+    hw.upload_firmware(&image_bundle.to_bytes().unwrap())
+        .unwrap();
+
+    let result = hw.copy_output_until_exit_success(&mut output);
+    assert!(result.is_ok());
+    let output = String::from_utf8_lossy(&output);
+
+    // Get the idevid cert.
+    let idevid_cert = idevid_cert(&output);
+
+    // Get the ldevid cert.
+    let ldevid_cert = ldevid_cert(&idevid_cert, &output);
+
+    let not_before: Asn1Time = Asn1Time::from_str("20270101000000Z").unwrap();
+    let not_after: Asn1Time = Asn1Time::from_str("20280101000000Z").unwrap();
+
+    // Get the fmclias cert.
+    let cert = fmcalias_cert(&ldevid_cert, &output);
+    assert!(cert.not_before() == not_before);
+    assert!(cert.not_after() == not_after);
+}
+
 #[test]
 fn cert_test() {
     pub const TEST_FMC_WITH_UART: FwId = FwId {
@@ -1486,7 +1567,7 @@ fn ldevid_cert(idevd_cert: &X509, output: &str) -> X509 {
     ldevid_cert
 }
 
-fn fmcalias_cert(ldevid_cert: &X509, output: &str) {
+fn fmcalias_cert(ldevid_cert: &X509, output: &str) -> X509 {
     // Get the ldevid cert
     let fmcalias_cert =
         X509::from_der(&hex::decode(get_data("[fmc] FMCALIAS cert = ", output)).unwrap()).unwrap();
@@ -1512,6 +1593,8 @@ fn fmcalias_cert(ldevid_cert: &X509, output: &str) {
     assert!(fmcalias_cert
         .verify(ldevid_cert.public_key().as_ref().unwrap())
         .unwrap());
+
+    fmcalias_cert
 }
 
 fn get_data(to_match: &str, haystack: &str) -> String {