Skip to main content

hyperv_uefi_custom_vars_json/
lib.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4//! Parsing and validation logic for Hyper-V UEFI custom nvram variables JSON
5//! files.
6//!
7//! Depending on the type of JSON (template vs. user-defined custom vars), the
8//! corresponding Rust type will either be a
9//! [`BaseTemplateVars`](firmware_uefi_custom_vars::BaseTemplateVars) or a
10//! [`UefiVarsDelta`](firmware_uefi_custom_vars::delta::UefiVarsDelta).
11
12#![expect(missing_docs)]
13#![forbid(unsafe_code)]
14
15use thiserror::Error;
16
17#[derive(Debug, Error)]
18pub enum ParseJsonError {
19    #[error("malformed JSON: {0}")]
20    Json(#[from] serde_json::Error),
21    #[error("semantic error when parsing delta: {0}")]
22    SemanticDelta(#[from] convert::JsonToDeltaError),
23    #[error("semantic error when parsing template: {0}")]
24    SemanticTemplate(#[from] JsonToTemplateError),
25}
26
27#[derive(Debug, Error)]
28pub enum JsonToTemplateError {
29    #[error("template cannot use \"Default\" variable type")]
30    CannotUseDefault,
31    #[error("template cannot use \"append\" operations")]
32    CannotUseAppend,
33}
34
35/// Parse [`BaseTemplateVars`](firmware_uefi_custom_vars::BaseTemplateVars) from a
36/// _fully-defined_ template UEFI custom nvram variables JSON file.
37///
38/// In this context, _fully-defined_ means that the JSON files cannot include
39/// any "fallback" entries, nor can it encode any "append" operations to
40/// existing variables.
41pub fn parse_template_json(
42    data: &[u8],
43) -> Result<firmware_uefi_custom_vars::BaseTemplateVars, ParseJsonError> {
44    use firmware_uefi_custom_vars::Signature;
45    use firmware_uefi_custom_vars::Signatures;
46    use firmware_uefi_custom_vars::UefiVars;
47    use firmware_uefi_custom_vars::delta::SignatureDelta;
48    use firmware_uefi_custom_vars::delta::SignatureDeltaVec;
49    use firmware_uefi_custom_vars::delta::SignaturesDelta;
50    use firmware_uefi_custom_vars::delta::UefiVarsDelta;
51
52    fn deny_default(sig: SignatureDelta) -> Result<Signature, JsonToTemplateError> {
53        match sig {
54            SignatureDelta::Sig(sig) => Ok(sig),
55            SignatureDelta::Default => Err(JsonToTemplateError::CannotUseDefault),
56        }
57    }
58
59    fn deny_default_vec(sigs: SignatureDeltaVec) -> Result<Vec<Signature>, JsonToTemplateError> {
60        match sigs {
61            SignatureDeltaVec::Sigs(sig) => Ok(sig),
62            SignatureDeltaVec::Default => Err(JsonToTemplateError::CannotUseDefault),
63        }
64    }
65
66    let UefiVarsDelta {
67        signatures,
68        non_signature_vars,
69    } = parse_delta_json(data)?;
70
71    Ok(UefiVars {
72        signatures: Some(match signatures {
73            SignaturesDelta::Append(_) => return Err(JsonToTemplateError::CannotUseAppend.into()),
74            SignaturesDelta::Replace(signatures) => Signatures {
75                pk: deny_default(signatures.pk)?,
76                kek: deny_default_vec(signatures.kek)?,
77                db: deny_default_vec(signatures.db)?,
78                dbx: deny_default_vec(signatures.dbx)?,
79                moklist: signatures
80                    .moklist
81                    .map(deny_default_vec)
82                    .transpose()?
83                    .unwrap_or_default(),
84                moklistx: signatures
85                    .moklistx
86                    .map(deny_default_vec)
87                    .transpose()?
88                    .unwrap_or_default(),
89            },
90        }),
91        non_signature_vars,
92    }
93    .into())
94}
95
96/// Parse a [`UefiVarsDelta`](firmware_uefi_custom_vars::delta::UefiVarsDelta) from a user
97/// provided UEFI custom nvram variables JSON file.
98pub fn parse_delta_json(
99    data: &[u8],
100) -> Result<firmware_uefi_custom_vars::delta::UefiVarsDelta, ParseJsonError> {
101    // syntax validation
102    let json: json::JsonRoot = serde_json::from_slice(data)?;
103    // semantic validation
104    let delta = convert::json_to_delta(json)?;
105    Ok(delta)
106}
107
108mod json {
109    use guid::Guid;
110    use serde::Deserialize;
111    use std::collections::BTreeMap;
112
113    #[derive(Debug, Deserialize)]
114    pub struct JsonRoot {
115        /// we don't actually care about the specific `type` field - all we care
116        /// about is that it passes `validate_root_type`
117        #[serde(rename = "type", deserialize_with = "parse::validate_root_type")]
118        pub _type: (),
119        #[serde(rename = "properties")]
120        pub properties: Properties,
121    }
122
123    #[derive(Debug, Deserialize)]
124    pub struct Properties {
125        #[serde(rename = "uefiSettings")]
126        pub uefi_settings: UefiSettings,
127    }
128
129    #[derive(Debug, Deserialize)]
130    #[serde(tag = "signatureMode", content = "signatures")]
131    pub enum Signatures {
132        #[serde(rename = "Append")]
133        Append(SignaturesAppend),
134        #[serde(rename = "Replace")]
135        Replace(SignaturesReplace),
136    }
137
138    #[derive(Debug, Deserialize)]
139    pub struct UefiSettings {
140        #[serde(flatten)]
141        pub signatures: Signatures,
142        #[serde(flatten)]
143        pub custom_vars: BTreeMap<String, CustomVar>,
144    }
145
146    #[derive(Debug, Deserialize)]
147    pub struct CustomVar {
148        #[serde(rename = "guid", deserialize_with = "parse::base64_guid")]
149        pub guid: Guid,
150        #[serde(rename = "attributes", deserialize_with = "parse::base64_u32")]
151        pub attr: u32,
152        #[serde(rename = "value", with = "serde_helpers::base64_vec")]
153        pub value: Vec<u8>,
154    }
155
156    #[derive(Debug, Deserialize)]
157    pub struct SignaturesAppend {
158        #[serde(rename = "KEK")]
159        pub kek: Option<Vec<Signature>>,
160        #[serde(rename = "db")]
161        pub db: Option<Vec<Signature>>,
162        #[serde(rename = "dbx")]
163        pub dbx: Option<Vec<Signature>>,
164        #[serde(rename = "MokList")]
165        pub moklist: Option<Vec<Signature>>,
166        #[serde(rename = "MokListX")]
167        pub moklistx: Option<Vec<Signature>>,
168    }
169
170    #[derive(Debug, Deserialize)]
171    pub struct SignaturesReplace {
172        #[serde(rename = "PK")]
173        pub pk: Signature,
174        #[serde(rename = "KEK")]
175        pub kek: Vec<Signature>,
176        #[serde(rename = "db")]
177        pub db: Vec<Signature>,
178        #[serde(default, rename = "dbx")]
179        pub dbx: Vec<Signature>,
180        #[serde(rename = "MokList")]
181        pub moklist: Option<Vec<Signature>>,
182        #[serde(rename = "MokListX")]
183        pub moklistx: Option<Vec<Signature>>,
184    }
185
186    #[derive(Debug, Deserialize)]
187    #[serde(tag = "type")]
188    pub enum Signature {
189        #[serde(rename = "x509")]
190        X509 { value: Vec<X509Cert> },
191        #[serde(rename = "sha256")]
192        Sha256 { value: Vec<Sha256Digest> },
193        /// "Default" will pull the value of the signature from the specified
194        /// hardcoded template (and fail if one wasn't specified)
195        ///
196        /// It shouldn't be used in the hardcoded templates
197        #[serde(rename = "Default")]
198        Default,
199    }
200
201    #[derive(Debug, Deserialize)]
202    #[serde(transparent)]
203    pub struct X509Cert {
204        #[serde(with = "serde_helpers::base64_vec")]
205        pub data: Vec<u8>,
206    }
207
208    #[derive(Debug, Deserialize)]
209    #[serde(transparent)]
210    pub struct Sha256Digest {
211        #[serde(deserialize_with = "parse::base64_u8_32")]
212        pub data: [u8; 32],
213    }
214
215    mod parse {
216        use base64::Engine;
217        use guid::Guid;
218        use serde::Deserialize;
219        use serde::Deserializer;
220        use zerocopy::FromBytes;
221
222        pub fn validate_root_type<'de, D: Deserializer<'de>>(d: D) -> Result<(), D::Error> {
223            let s: &str = Deserialize::deserialize(d)?;
224
225            if s != "Microsoft.Compute/disks" {
226                return Err(serde::de::Error::custom(
227                    r#"root "type" must be "Microsoft.Compute/disks""#,
228                ));
229            }
230
231            Ok(())
232        }
233
234        pub fn base64_u8_32<'de, D: Deserializer<'de>>(d: D) -> Result<[u8; 32], D::Error> {
235            let s: &str = Deserialize::deserialize(d)?;
236
237            let v = base64::engine::general_purpose::STANDARD
238                .decode(s)
239                .map_err(serde::de::Error::custom)?;
240            v.try_into().map_err(|v: Vec<_>| {
241                serde::de::Error::custom(format!("expected 32 bytes. found {} bytes", v.len()))
242            })
243        }
244
245        #[expect(clippy::many_single_char_names)]
246        pub fn base64_u32<'de, D: Deserializer<'de>>(d: D) -> Result<u32, D::Error> {
247            let s: &str = Deserialize::deserialize(d)?;
248
249            let v = base64::engine::general_purpose::STANDARD
250                .decode(s)
251                .map_err(serde::de::Error::custom)?;
252            let v: [u8; 4] = match v.as_slice() {
253                &[a] => [a, 0, 0, 0],
254                &[a, b] => [a, b, 0, 0],
255                &[a, b, c] => [a, b, c, 0],
256                &[a, b, c, d] => [a, b, c, d],
257                other => {
258                    return Err(serde::de::Error::custom(format!(
259                        "expected 4 bytes. found {} bytes",
260                        other.len()
261                    )));
262                }
263            };
264            Ok(u32::from_le_bytes(v))
265        }
266
267        pub fn base64_guid<'de, D: Deserializer<'de>>(d: D) -> Result<Guid, D::Error> {
268            let s: &str = Deserialize::deserialize(d)?;
269
270            let v = base64::engine::general_purpose::STANDARD
271                .decode(s)
272                .map_err(serde::de::Error::custom)?;
273            if v.len() != size_of::<Guid>() {
274                return Err(serde::de::Error::custom(format!(
275                    "expected {} bytes. found {} bytes",
276                    size_of::<Guid>(),
277                    v.len()
278                )));
279            }
280            Ok(Guid::read_from_prefix(v.as_slice()).unwrap().0) // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
281        }
282    }
283}
284
285mod convert {
286    use super::json;
287    use firmware_uefi_custom_vars as base;
288    use firmware_uefi_custom_vars::delta;
289    use thiserror::Error;
290
291    #[derive(Debug, Error)]
292    pub enum JsonToDeltaError {
293        #[error("Default can only be used once per signature array")]
294        MultipleDefault,
295        #[error("Default cannot be used alongside any other vars in the signature array")]
296        DefaultWithOtherVars,
297        #[error("Default cannot be used alongside Append")]
298        DefaultWithAppend,
299    }
300
301    fn validate_default(
302        sigs: Vec<delta::SignatureDelta>,
303    ) -> Result<delta::SignatureDeltaVec, JsonToDeltaError> {
304        let num_sigs = sigs.len();
305        let num_defaults = sigs
306            .iter()
307            .filter(|s| matches!(s, delta::SignatureDelta::Default))
308            .count();
309
310        // `.collect::<Option<Vec<_>>>()` will collapse a vec with _any_
311        // Defaults into a `None`
312        let sigs = sigs
313            .into_iter()
314            .map(|s| match s {
315                delta::SignatureDelta::Default => None,
316                delta::SignatureDelta::Sig(sig) => Some(sig),
317            })
318            .collect::<Option<Vec<_>>>();
319
320        match sigs {
321            Some(sigs) => Ok(delta::SignatureDeltaVec::Sigs(sigs)),
322            None => {
323                if num_defaults != 1 {
324                    return Err(JsonToDeltaError::MultipleDefault);
325                }
326
327                if num_sigs != 1 {
328                    return Err(JsonToDeltaError::DefaultWithOtherVars);
329                }
330
331                Ok(delta::SignatureDeltaVec::Default)
332            }
333        }
334    }
335
336    fn deny_default(sig_delta: json::Signature) -> Result<base::Signature, JsonToDeltaError> {
337        let ret = match sig_delta {
338            json::Signature::X509 { value } => {
339                base::Signature::X509(value.into_iter().map(Into::into).collect())
340            }
341            json::Signature::Sha256 { value } => {
342                base::Signature::Sha256(value.into_iter().map(Into::into).collect())
343            }
344            json::Signature::Default => return Err(JsonToDeltaError::DefaultWithAppend),
345        };
346
347        Ok(ret)
348    }
349
350    fn json_to_base_sig_vec(
351        sigs: Vec<json::Signature>,
352    ) -> Result<Vec<base::Signature>, JsonToDeltaError> {
353        sigs.into_iter()
354            .map(deny_default)
355            .collect::<Result<Vec<_>, _>>()
356    }
357
358    fn json_to_delta_sig_vec(sigs: Vec<json::Signature>) -> Vec<delta::SignatureDelta> {
359        sigs.into_iter().map(Into::into).collect()
360    }
361
362    /// Convert the JSON-specific data types into the format agnostic
363    /// [`UefiVarsDelta`](delta::UefiVarsDelta) container.
364    pub(super) fn json_to_delta(
365        json: json::JsonRoot,
366    ) -> Result<delta::UefiVarsDelta, JsonToDeltaError> {
367        let non_signature_vars: Vec<(String, base::UefiVar)> = json
368            .properties
369            .uefi_settings
370            .custom_vars
371            .into_iter()
372            .map(|(k, v)| (k, v.into()))
373            .collect();
374
375        let ret = match json.properties.uefi_settings.signatures {
376            json::Signatures::Append(json::SignaturesAppend {
377                kek,
378                db,
379                dbx,
380                moklist,
381                moklistx,
382            }) => delta::UefiVarsDelta {
383                signatures: delta::SignaturesDelta::Append(delta::SignaturesAppend {
384                    kek: kek.map(json_to_base_sig_vec).transpose()?,
385                    db: db.map(json_to_base_sig_vec).transpose()?,
386                    dbx: dbx.map(json_to_base_sig_vec).transpose()?,
387                    moklist: moklist.map(json_to_base_sig_vec).transpose()?,
388                    moklistx: moklistx.map(json_to_base_sig_vec).transpose()?,
389                }),
390                non_signature_vars,
391            },
392            json::Signatures::Replace(json::SignaturesReplace {
393                pk,
394                kek,
395                db,
396                dbx,
397                moklist,
398                moklistx,
399            }) => delta::UefiVarsDelta {
400                signatures: delta::SignaturesDelta::Replace(delta::SignaturesReplace {
401                    pk: pk.into(),
402                    kek: validate_default(json_to_delta_sig_vec(kek))?,
403                    db: validate_default(json_to_delta_sig_vec(db))?,
404                    dbx: validate_default(json_to_delta_sig_vec(dbx))?,
405                    moklist: moklist
406                        .map(|sigs| validate_default(json_to_delta_sig_vec(sigs)))
407                        .transpose()?,
408                    moklistx: moklistx
409                        .map(|sigs| validate_default(json_to_delta_sig_vec(sigs)))
410                        .transpose()?,
411                }),
412                non_signature_vars,
413            },
414        };
415
416        Ok(ret)
417    }
418
419    impl From<json::CustomVar> for base::UefiVar {
420        fn from(json_custom_var: json::CustomVar) -> base::UefiVar {
421            base::UefiVar {
422                guid: json_custom_var.guid,
423                attr: json_custom_var.attr,
424                value: json_custom_var.value,
425            }
426        }
427    }
428
429    impl From<json::Signature> for delta::SignatureDelta {
430        fn from(json_signature: json::Signature) -> delta::SignatureDelta {
431            match json_signature {
432                json::Signature::X509 { value } => delta::SignatureDelta::Sig(
433                    base::Signature::X509(value.into_iter().map(Into::into).collect()),
434                ),
435                json::Signature::Sha256 { value } => delta::SignatureDelta::Sig(
436                    base::Signature::Sha256(value.into_iter().map(Into::into).collect()),
437                ),
438                json::Signature::Default => delta::SignatureDelta::Default,
439            }
440        }
441    }
442
443    impl From<json::Sha256Digest> for base::Sha256Digest {
444        fn from(json_digest: json::Sha256Digest) -> base::Sha256Digest {
445            base::Sha256Digest(json_digest.data)
446        }
447    }
448
449    impl From<json::X509Cert> for base::X509Cert {
450        fn from(json_cert: json::X509Cert) -> base::X509Cert {
451            base::X509Cert(json_cert.data)
452        }
453    }
454}
455
456#[cfg(test)]
457mod test {
458    use super::*;
459
460    const APPEND: &str = r#"
461    {
462        "type": "Microsoft.Compute/disks",
463
464        "properties": {
465            "uefiSettings" : {
466                "signatureMode": "Append",
467                "signatures": {
468                    "db": [{
469                        "type": "sha256",
470                        "value": ["i4HHnT7SW4zUdcQ7LyvOyfVOTr9BxCWWoP/W3lqGE0Q=",
471                                "ELLxN/fAUzttWO5WW3SOdJ4a99OAWy56o2ga46W1Efc="]
472                    }],
473                    "dbx": [{
474                        "type": "sha256",
475                        "value": ["Bkk5Ef7VzGk3M7FLY/MyHyl+ygAF1P8ju9HBSl53Cak=",
476                                "h6/eEfJXfmqGLZWr/ekVjhQAiG3OlGw6Yi4MAbBjpqc="]
477                    }]
478                }
479            }
480        }
481    }
482    "#;
483
484    #[test]
485    fn append() {
486        let data = serde_json::from_str::<json::JsonRoot>(APPEND);
487        let _ = data.unwrap();
488    }
489
490    const APPEND_DEFAULT: &str = r#"
491    {
492        "type": "Microsoft.Compute/disks",
493
494        "properties": {
495            "uefiSettings" : {
496                "signatureMode": "Append",
497                "signatures": {
498                    "db": [{
499                        "type": "Default",
500                    }]
501                }
502            }
503        }
504    }
505    "#;
506
507    #[test]
508    fn append_default() {
509        let data = serde_json::from_str::<json::JsonRoot>(APPEND_DEFAULT);
510        assert!(data.is_err())
511    }
512
513    const REPLACE_MALFORMED_DB: &str = r#"
514    {
515        "type": "Microsoft.Compute/disks",
516
517        "properties": {
518            "uefiSettings" : {
519                "signatureMode": "Replace",
520                "signatures": {
521                    "PK": {
522                        "type": "x509",
523                        "value": ["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"]
524                    },
525                    "KEK": [{
526                        "type": "x509",
527                        "value": ["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"]
528                    }],
529                    "db": [{
530                        "type": "x509",
531                        "value": ["InvalidKey"]
532                    }],
533                    "dbx": [{
534                        "type": "Default"
535                    }]
536                }
537            }
538        }
539    }
540    "#;
541
542    #[test]
543    fn replace_malformed_db() {
544        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MALFORMED_DB);
545        assert!(data.is_err())
546    }
547
548    const REPLACE_MISSING_SIGNATURE_MODE: &str = r#"
549    {
550        "type": "Microsoft.Compute/disks",
551
552        "properties": {
553            "uefiSettings" : {
554                "signatures": {
555                    "PK": {
556                        "type": "x509",
557                        "value": ["MIIHFjCCBP6gAwIBAgITMwAAACDxXiUkn6t10AAAAAAAIDANBgkqhkiG9w0BAQsFADCBkDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE6MDgGA1UEAxMxTWljcm9zb2Z0IENvcnBvcmF0aW9uIFRoaXJkIFBhcnR5IE1hcmtldHBsYWNlIFBDQTAeFw0xMzAxMjQyMjAyNDBaFw0xNDA0MjQyMjAyNDBaMHwxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jvc29mdCBIeXBlci1WIEZpcm13YXJlIFBLMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAx+U8Ti27qO+TAIhy9goO+UPD7TSEPfB8kjYpY8FPaKSP3mngCInzaRaEOj26L05uo/XydIDHHxn078nTthGmyBbPUe1Vm8GjvFODiE3s7rzebPhFo+qKLjuZ35gjyx+5dyRmUqQ73/wLGz3GvGIpNMO+3KAdSWRUC804IIsdZvtJPZYh0102A4pOMa+FaOzbe0js/b4SsHnHYt6ede0qvyRbuwSeJHliFYDH7qNpTv0sWCbn5P9z8vLgLCxjPTKOyN+F/08SuxtqO+oiwU8ph6ngmlWfHYWStX60iRFD2zPG2kTpckXooMQ5oKvMZo2SxHo6Oxa2KCaK73C8w/de0Rgwx1Uh6o+rIdnmNjUDNDGE+QYEvyU1azebL6TZ8sGOuU9B/e2SMQhLJdrStBGeMWfUkpy/3hZRA+1cCu1XMNw1v8plZCVe91taCA9mjP70RSxZQv8XM5PxyYG/aBTfCCLV97f11nGAG75cpyi52snGZpIw1K2+12Gm/lx71TDt++jHfcWiJNA69YUaKWaK0eqMRjubpNEfJH63k8dXKcNV2kBETM061kIlX3hkyi1zUIvF8jA0ShDnSmalf03diwDgxym4KSa/0CrWcsZTydXGJXSrELeo0EMu7DzIFrSzVeL/ToKJZ8/+CKvng089a0OIv/gw5cC5Ags1TVNk9DUCAwEAAaOCAXowggF2MBQGA1UdJQQNMAsGCSsGAQQBgjdPATAdBgNVHQ4EFgQUF74uaaCCLODudjIsHHpKBsEUbnowUAYDVR0RBEkwR6RFMEMxDDAKBgNVBAsTA0FPQzEzMDEGA1UEBRMqMzI1NjkrMGNlN2UxZTYtYzNlMi00ODNhLWJhOGMtYWRiMTBjZjhhNGEyMB8GA1UdIwQYMBaAFK6R5GCfmMAL3xoLa/BWMydHrMfHMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY0NvclRoaVBhck1hclBDQV8yMDEwLTEwLTA1LmNybDBgBggrBgEFBQcBAQRUMFIwUAYIKwYBBQUHMAKGRGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljQ29yVGhpUGFyTWFyUENBXzIwMTAtMTAtMDUuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIBAJA2zvE3bakPTtiW1bLOAj9MUno5/v41xpp5gcoW3PMTjwIeA2p1J89GfCcCKmGT0q2iuL38s0HXOPOooRxxBl0VupzXygxNiTt0gvoOGS+ajQPZxWnhpbWeuo4/izV4WO4sq8JwkNexTy2IK0m6S3Z5mA03bDBht8BDRM5AL3/6b1gzcMi5fAK7DYloHMckUlmArl9/itUZk0p3CpZOZT1sXaK/1WOCRijnBo5ibldfsO7zBXAY+DN4Hdec5yXhstdvvGSjMGoQyCwgzU65b+y5KQOkSo2L2xzTBRrcccj+dqSWi2itoOJjsTNjCtxsgZDAjQzvnN4/bm25OP+T/bIxdYLgKCdCRgNckWUlo90ooOiS//xFMBXfFE1zwEbYdICbrDUEBcjjr8NzZClJew1Ll5VTQK+stgj/RHW3SHzzpAjmOvT23f/Q0vY/0uw9KRlpW/+cQT6pKTJXOhDUPEzkuYJBzBQaAnUC3hvmZzkEk44cBGan4C72/x12VDL3Sg2Mxf2qe3II13F3jlsWCVnLtJleI2B0ibIyiLh9n5C6yMh54DIUqAjt4fa9Ds2ljs9Hvqa4AiffGgK8wKmXAZYcB4X0UCuShbRTQKCJNOr9GDnQGaHQWU6FbcL6Mo0rKCNqaBlEde37FyMa0qRT73NDpJsSSO2XiYSSw91KFgM9"]
558                    },
559                    "KEK": [{
560                        "type": "x509",
561                        "value": ["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"]
562                    }],
563                    "dbx": [{
564                        "type": "Default"
565                    }]
566                }
567            }
568        }
569    }
570    "#;
571
572    #[test]
573    fn replace_missing_signature_mode() {
574        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MISSING_SIGNATURE_MODE);
575        assert!(data.is_err())
576    }
577
578    const REPLACE_MULTI_DEFAULT: &str = r#"
579    {
580        "type": "Microsoft.Compute/disks",
581
582        "properties": {
583            "uefiSettings" : {
584                "signatureMode": "Replace",
585                "signatures": {
586                    "PK": {
587                        "type": "x509",
588                        "value": ["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"]
589                    },
590                    "KEK": [{
591                        "type": "Default"
592                    }, {
593                        "type": "Default"
594                    }],
595                    "db": [{
596                        "type": "x509",
597                        "value": ["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"]
598                    }],
599                    "dbx": [{
600                        "type": "Default"
601                    }]
602                }
603            }
604        }
605    }
606    "#;
607
608    #[test]
609    fn replace_multi_default() {
610        // serde parses this fine
611        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MULTI_DEFAULT).unwrap();
612        // but semantic checks will fail
613        let data = convert::json_to_delta(data);
614        assert!(data.is_err())
615    }
616
617    const REPLACE_MIXED_DEFAULT: &str = r#"
618    {
619        "type": "Microsoft.Compute/disks",
620
621        "properties": {
622            "uefiSettings" : {
623                "signatureMode": "Replace",
624                "signatures": {
625                    "PK": {
626                        "type": "x509",
627                        "value": ["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"]
628                    },
629                    "KEK": [{
630                        "type": "Default"
631                    }, {
632                        "type": "x509",
633                        "value": ["Jw=="]
634                    }],
635                    "db": [{
636                        "type": "x509",
637                        "value": ["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"]
638                    }],
639                    "dbx": [{
640                        "type": "Default"
641                    }]
642                }
643            }
644        }
645    }
646    "#;
647
648    #[test]
649    fn replace_mixed_default() {
650        // serde parses this fine
651        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MIXED_DEFAULT).unwrap();
652        // but semantic checks will fail
653        let data = convert::json_to_delta(data);
654        assert!(data.is_err())
655    }
656
657    const REPLACE: &str = r#"
658    {
659        "type": "Microsoft.Compute/disks",
660
661        "properties": {
662            "uefiSettings" : {
663                "signatureMode": "Replace",
664                "signatures": {
665                    "PK": {
666                        "type": "x509",
667                        "value": ["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"]
668                    },
669                    "KEK": [{
670                        "type": "x509",
671                        "value": ["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"]
672                    }],
673                    "db": [{
674                        "type": "x509",
675                        "value": ["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"]
676                    }],
677                    "dbx": [{
678                        "type": "Default"
679                    }]
680                }
681            }
682        }
683    }
684    "#;
685
686    #[test]
687    fn replace() {
688        let data = serde_json::from_str::<json::JsonRoot>(REPLACE);
689        let _ = data.unwrap();
690    }
691
692    #[test]
693    fn replace_without_dbx() {
694        let data = r#"
695        {
696            "type": "Microsoft.Compute/disks",
697            "properties": {
698                "uefiSettings": {
699                    "signatureMode": "Replace",
700                    "signatures": {
701                        "PK": {
702                            "type": "x509",
703                            "value": ["Jw=="]
704                        },
705                        "KEK": [],
706                        "db": []
707                    }
708                }
709            }
710        }
711        "#;
712
713        let delta = parse_delta_json(data.as_bytes()).unwrap();
714        let firmware_uefi_custom_vars::delta::SignaturesDelta::Replace(signatures) =
715            delta.signatures
716        else {
717            panic!("expected replace signatures");
718        };
719        assert!(matches!(
720            signatures.dbx,
721            firmware_uefi_custom_vars::delta::SignatureDeltaVec::Sigs(dbx) if dbx.is_empty()
722        ));
723    }
724
725    #[test]
726    fn replace_with_null_dbx_is_invalid() {
727        let data = r#"
728        {
729            "type": "Microsoft.Compute/disks",
730            "properties": {
731                "uefiSettings": {
732                    "signatureMode": "Replace",
733                    "signatures": {
734                        "PK": {
735                            "type": "x509",
736                            "value": ["Jw=="]
737                        },
738                        "KEK": [],
739                        "db": [],
740                        "dbx": null
741                    }
742                }
743            }
744        }
745        "#;
746
747        assert!(parse_delta_json(data.as_bytes()).is_err());
748    }
749
750    // BAD_DB is a semantic test that requires performing signature validation
751    // (which isn't done as part of the basic JSON parsing + validation)
752
753    // const BAD_DB: &str = r#"
754    // {
755    //     "type": "Microsoft.Compute/disks",
756
757    //     "properties": {
758    //         "uefiSettings" : {
759    //             "signatureMode": "Replace",
760    //             "signatures": {
761    //                 "PK": {
762    //                     "type": "x509",
763    //                     "value": ["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"]
764    //                 },
765    //                 "KEK": [{
766    //                     "type": "x509",
767    //                     "value": ["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"]
768    //                 }]
769    //             },
770
771    //             "db": {
772    //                 "guid":"y7IZ1zo9lkWjvNrQDmdlbw==",
773    //                 "attributes":"Jw==",
774    //                 "value":"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"
775    //             },
776
777    //             "dbx": {
778    //                 "guid":"y7IZ1zo9lkWjvNrQDmdlbw==",
779    //                 "attributes":"Jw==",
780    //                 "value":"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"
781    //             }
782    //         }
783    //     }
784    // }
785    // "#;
786
787    // #[test]
788    // fn bad_db() {
789    //     let data = serde_json::from_str::<json::JsonRoot>(BAD_DB);
790    //     let _ = data.unwrap();
791    // }
792
793    const PRIVATE_VARS: &str = r#"
794    {
795        "type": "Microsoft.Compute/disks",
796
797        "properties": {
798            "uefiSettings" : {
799                "signatureMode": "Replace",
800                "signatures": {
801                    "PK": {
802                        "type": "x509",
803                        "value": ["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"]
804                    },
805                    "KEK": [{
806                        "type": "x509",
807                        "value": ["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"]
808                    }],
809                    "db": [{
810                        "type": "x509",
811                        "value": ["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"]
812                    }],
813                    "dbx": [{
814                        "type": "Default"
815                    }]
816                },
817
818                "Var1": {
819                    "guid":"Yd/ki8qT0hGqDQDgmAMrjA==",
820                    "attributes":"Bw==",
821                    "value":"VGVzdCBWYXJpYWJsZSAx"
822                },
823
824                "Var2": {
825                    "guid":"Yd/ki8qT0hGqDQDgmAMrjA==",
826                    "attributes":"Jw==",
827                    "value":"VGVzdCBWYXJpYWJsZSAy"
828                }
829            }
830        }
831    }
832    "#;
833
834    #[test]
835    fn private_vars() {
836        let data = serde_json::from_str::<json::JsonRoot>(PRIVATE_VARS);
837        let data = data.unwrap();
838        match data.properties.uefi_settings.custom_vars.get("Var1") {
839            Some(v) => assert_eq!(v.attr, 7),
840            None => panic!(),
841        }
842        match data.properties.uefi_settings.custom_vars.get("Var2") {
843            Some(v) => assert_eq!(v.attr, 39),
844            None => panic!(),
845        }
846    }
847}