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//! correspond Rust type will either be a
9//! [`CustomVars`](firmware_uefi_custom_vars::CustomVars) or a
10//! [`CustomVarsDelta`](firmware_uefi_custom_vars::delta::CustomVarsDelta).
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 a [`CustomVars`](firmware_uefi_custom_vars::CustomVars) 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 load_template_from_json(
42    data: &[u8],
43) -> Result<firmware_uefi_custom_vars::CustomVars, ParseJsonError> {
44    use firmware_uefi_custom_vars::CustomVars;
45    use firmware_uefi_custom_vars::Signature;
46    use firmware_uefi_custom_vars::Signatures;
47    use firmware_uefi_custom_vars::delta::CustomVarsDelta;
48    use firmware_uefi_custom_vars::delta::SignatureDelta;
49    use firmware_uefi_custom_vars::delta::SignatureDeltaVec;
50    use firmware_uefi_custom_vars::delta::SignaturesDelta;
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 CustomVarsDelta {
67        signatures,
68        custom_vars,
69    } = load_delta_from_json(data)?;
70
71    Ok(CustomVars {
72        signatures: Some(match signatures {
73            SignaturesDelta::Append(_) => panic!("hardcoded templates cannot use append"),
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        custom_vars,
92    })
93}
94
95/// Parse a [`CustomVarsDelta`](firmware_uefi_custom_vars::delta::CustomVarsDelta) from a user
96/// provided UEFI custom nvram variables JSON file.
97pub fn load_delta_from_json(
98    data: &[u8],
99) -> Result<firmware_uefi_custom_vars::delta::CustomVarsDelta, ParseJsonError> {
100    // syntax validation
101    let json: json::JsonRoot = serde_json::from_slice(data)?;
102    // semantic validation
103    let delta = convert::json_to_delta(json)?;
104    Ok(delta)
105}
106
107mod json {
108    use guid::Guid;
109    use serde::Deserialize;
110    use std::collections::BTreeMap;
111
112    #[derive(Debug, Deserialize)]
113    pub struct JsonRoot {
114        /// we don't actually care about the specific `type` field - all we care
115        /// about is that it passes `validate_root_type`
116        #[serde(rename = "type", deserialize_with = "parse::validate_root_type")]
117        pub _type: (),
118        #[serde(rename = "properties")]
119        pub properties: Properties,
120    }
121
122    #[derive(Debug, Deserialize)]
123    pub struct Properties {
124        #[serde(rename = "uefiSettings")]
125        pub uefi_settings: UefiSettings,
126    }
127
128    #[derive(Debug, Deserialize)]
129    #[serde(tag = "signatureMode", content = "signatures")]
130    pub enum Signatures {
131        #[serde(rename = "Append")]
132        Append(SignaturesAppend),
133        #[serde(rename = "Replace")]
134        Replace(SignaturesReplace),
135    }
136
137    #[derive(Debug, Deserialize)]
138    pub struct UefiSettings {
139        #[serde(flatten)]
140        pub signatures: Signatures,
141        #[serde(flatten)]
142        pub custom_vars: BTreeMap<String, CustomVar>,
143    }
144
145    #[derive(Debug, Deserialize)]
146    pub struct CustomVar {
147        #[serde(rename = "guid", deserialize_with = "parse::base64_guid")]
148        pub guid: Guid,
149        #[serde(rename = "attributes", deserialize_with = "parse::base64_u32")]
150        pub attr: u32,
151        #[serde(rename = "value", with = "serde_helpers::base64_vec")]
152        pub value: Vec<u8>,
153    }
154
155    #[derive(Debug, Deserialize)]
156    pub struct SignaturesAppend {
157        #[serde(rename = "KEK")]
158        pub kek: Option<Vec<Signature>>,
159        #[serde(rename = "db")]
160        pub db: Option<Vec<Signature>>,
161        #[serde(rename = "dbx")]
162        pub dbx: Option<Vec<Signature>>,
163        #[serde(rename = "MokList")]
164        pub moklist: Option<Vec<Signature>>,
165        #[serde(rename = "MokListX")]
166        pub moklistx: Option<Vec<Signature>>,
167    }
168
169    #[derive(Debug, Deserialize)]
170    pub struct SignaturesReplace {
171        #[serde(rename = "PK")]
172        pub pk: Signature,
173        #[serde(rename = "KEK")]
174        pub kek: Vec<Signature>,
175        #[serde(rename = "db")]
176        pub db: Vec<Signature>,
177        #[serde(rename = "dbx")]
178        pub dbx: Vec<Signature>,
179        #[serde(rename = "MokList")]
180        pub moklist: Option<Vec<Signature>>,
181        #[serde(rename = "MokListX")]
182        pub moklistx: Option<Vec<Signature>>,
183    }
184
185    #[derive(Debug, Deserialize)]
186    #[serde(tag = "type")]
187    pub enum Signature {
188        #[serde(rename = "x509")]
189        X509 { value: Vec<X509Cert> },
190        #[serde(rename = "sha256")]
191        Sha256 { value: Vec<Sha256Digest> },
192        /// "Default" will pull the value of the signature from the specified
193        /// hardcoded template (and fail if one wasn't specified)
194        ///
195        /// It shouldn't be used in the hardcoded templates
196        #[serde(rename = "Default")]
197        Default,
198    }
199
200    #[derive(Debug, Deserialize)]
201    #[serde(transparent)]
202    pub struct X509Cert {
203        #[serde(with = "serde_helpers::base64_vec")]
204        pub data: Vec<u8>,
205    }
206
207    #[derive(Debug, Deserialize)]
208    #[serde(transparent)]
209    pub struct Sha256Digest {
210        #[serde(deserialize_with = "parse::base64_u8_32")]
211        pub data: [u8; 32],
212    }
213
214    mod parse {
215        use base64::Engine;
216        use guid::Guid;
217        use serde::Deserialize;
218        use serde::Deserializer;
219        use zerocopy::FromBytes;
220
221        pub fn validate_root_type<'de, D: Deserializer<'de>>(d: D) -> Result<(), D::Error> {
222            let s: &str = Deserialize::deserialize(d)?;
223
224            if s != "Microsoft.Compute/disks" {
225                return Err(serde::de::Error::custom(
226                    r#"root "type" must be "Microsoft.Compute/disks""#,
227                ));
228            }
229
230            Ok(())
231        }
232
233        pub fn base64_u8_32<'de, D: Deserializer<'de>>(d: D) -> Result<[u8; 32], D::Error> {
234            let s: &str = Deserialize::deserialize(d)?;
235
236            let v = base64::engine::general_purpose::STANDARD
237                .decode(s)
238                .map_err(serde::de::Error::custom)?;
239            v.try_into().map_err(|v: Vec<_>| {
240                serde::de::Error::custom(format!("expected 32 bytes. found {} bytes", v.len()))
241            })
242        }
243
244        #[expect(clippy::many_single_char_names)]
245        pub fn base64_u32<'de, D: Deserializer<'de>>(d: D) -> Result<u32, D::Error> {
246            let s: &str = Deserialize::deserialize(d)?;
247
248            let v = base64::engine::general_purpose::STANDARD
249                .decode(s)
250                .map_err(serde::de::Error::custom)?;
251            let v: [u8; 4] = match v.as_slice() {
252                &[a] => [a, 0, 0, 0],
253                &[a, b] => [a, b, 0, 0],
254                &[a, b, c] => [a, b, c, 0],
255                &[a, b, c, d] => [a, b, c, d],
256                other => {
257                    return Err(serde::de::Error::custom(format!(
258                        "expected 4 bytes. found {} bytes",
259                        other.len()
260                    )));
261                }
262            };
263            Ok(u32::from_le_bytes(v))
264        }
265
266        pub fn base64_guid<'de, D: Deserializer<'de>>(d: D) -> Result<Guid, D::Error> {
267            let s: &str = Deserialize::deserialize(d)?;
268
269            let v = base64::engine::general_purpose::STANDARD
270                .decode(s)
271                .map_err(serde::de::Error::custom)?;
272            if v.len() != size_of::<Guid>() {
273                return Err(serde::de::Error::custom(format!(
274                    "expected {} bytes. found {} bytes",
275                    size_of::<Guid>(),
276                    v.len()
277                )));
278            }
279            Ok(Guid::read_from_prefix(v.as_slice()).unwrap().0) // TODO: zerocopy: use-rest-of-range (https://github.com/microsoft/openvmm/issues/759)
280        }
281    }
282}
283
284mod convert {
285    use super::json;
286    use firmware_uefi_custom_vars as base;
287    use firmware_uefi_custom_vars::delta;
288    use thiserror::Error;
289
290    #[derive(Debug, Error)]
291    pub enum JsonToDeltaError {
292        #[error("Default can only be used once per signature array")]
293        MultipleDefault,
294        #[error("Default cannot be used alongside any other vars in the signature array")]
295        DefaultWithOtherVars,
296        #[error("Default cannot be used alongside Append")]
297        DefaultWithAppend,
298    }
299
300    fn validate_default(
301        sigs: Vec<delta::SignatureDelta>,
302    ) -> Result<delta::SignatureDeltaVec, JsonToDeltaError> {
303        let num_sigs = sigs.len();
304        let num_defaults = sigs
305            .iter()
306            .filter(|s| matches!(s, delta::SignatureDelta::Default))
307            .count();
308
309        // `.collect::<Option<Vec<_>>>()` will collapse a vec with _any_
310        // Defaults into a `None`
311        let sigs = sigs
312            .into_iter()
313            .map(|s| match s {
314                delta::SignatureDelta::Default => None,
315                delta::SignatureDelta::Sig(sig) => Some(sig),
316            })
317            .collect::<Option<Vec<_>>>();
318
319        match sigs {
320            Some(sigs) => Ok(delta::SignatureDeltaVec::Sigs(sigs)),
321            None => {
322                if num_defaults != 1 {
323                    return Err(JsonToDeltaError::MultipleDefault);
324                }
325
326                if num_sigs != 1 {
327                    return Err(JsonToDeltaError::DefaultWithOtherVars);
328                }
329
330                Ok(delta::SignatureDeltaVec::Default)
331            }
332        }
333    }
334
335    fn deny_default(sig_delta: json::Signature) -> Result<base::Signature, JsonToDeltaError> {
336        let ret = match sig_delta {
337            json::Signature::X509 { value } => {
338                base::Signature::X509(value.into_iter().map(Into::into).collect())
339            }
340            json::Signature::Sha256 { value } => {
341                base::Signature::Sha256(value.into_iter().map(Into::into).collect())
342            }
343            json::Signature::Default => return Err(JsonToDeltaError::DefaultWithAppend),
344        };
345
346        Ok(ret)
347    }
348
349    fn json_to_base_sig_vec(
350        sigs: Vec<json::Signature>,
351    ) -> Result<Vec<base::Signature>, JsonToDeltaError> {
352        sigs.into_iter()
353            .map(deny_default)
354            .collect::<Result<Vec<_>, _>>()
355    }
356
357    fn json_to_delta_sig_vec(sigs: Vec<json::Signature>) -> Vec<delta::SignatureDelta> {
358        sigs.into_iter().map(Into::into).collect()
359    }
360
361    /// Convert the JSON-specific data types into the format agnostic
362    /// [`CustomVarsDelta`](delta::CustomVarsDelta) container.
363    pub(super) fn json_to_delta(
364        json: json::JsonRoot,
365    ) -> Result<delta::CustomVarsDelta, JsonToDeltaError> {
366        let custom_vars: Vec<(String, base::CustomVar)> = json
367            .properties
368            .uefi_settings
369            .custom_vars
370            .into_iter()
371            .map(|(k, v)| (k, v.into()))
372            .collect();
373
374        let ret = match json.properties.uefi_settings.signatures {
375            json::Signatures::Append(json::SignaturesAppend {
376                kek,
377                db,
378                dbx,
379                moklist,
380                moklistx,
381            }) => delta::CustomVarsDelta {
382                signatures: delta::SignaturesDelta::Append(delta::SignaturesAppend {
383                    kek: kek.map(json_to_base_sig_vec).transpose()?,
384                    db: db.map(json_to_base_sig_vec).transpose()?,
385                    dbx: dbx.map(json_to_base_sig_vec).transpose()?,
386                    moklist: moklist.map(json_to_base_sig_vec).transpose()?,
387                    moklistx: moklistx.map(json_to_base_sig_vec).transpose()?,
388                }),
389                custom_vars,
390            },
391            json::Signatures::Replace(json::SignaturesReplace {
392                pk,
393                kek,
394                db,
395                dbx,
396                moklist,
397                moklistx,
398            }) => delta::CustomVarsDelta {
399                signatures: delta::SignaturesDelta::Replace(delta::SignaturesReplace {
400                    pk: pk.into(),
401                    kek: validate_default(json_to_delta_sig_vec(kek))?,
402                    db: validate_default(json_to_delta_sig_vec(db))?,
403                    dbx: validate_default(json_to_delta_sig_vec(dbx))?,
404                    moklist: moklist
405                        .map(|sigs| validate_default(json_to_delta_sig_vec(sigs)))
406                        .transpose()?,
407                    moklistx: moklistx
408                        .map(|sigs| validate_default(json_to_delta_sig_vec(sigs)))
409                        .transpose()?,
410                }),
411                custom_vars,
412            },
413        };
414
415        Ok(ret)
416    }
417
418    impl From<json::CustomVar> for base::CustomVar {
419        fn from(json_custom_var: json::CustomVar) -> base::CustomVar {
420            base::CustomVar {
421                guid: json_custom_var.guid,
422                attr: json_custom_var.attr,
423                value: json_custom_var.value,
424            }
425        }
426    }
427
428    impl From<json::Signature> for delta::SignatureDelta {
429        fn from(json_signature: json::Signature) -> delta::SignatureDelta {
430            match json_signature {
431                json::Signature::X509 { value } => delta::SignatureDelta::Sig(
432                    base::Signature::X509(value.into_iter().map(Into::into).collect()),
433                ),
434                json::Signature::Sha256 { value } => delta::SignatureDelta::Sig(
435                    base::Signature::Sha256(value.into_iter().map(Into::into).collect()),
436                ),
437                json::Signature::Default => delta::SignatureDelta::Default,
438            }
439        }
440    }
441
442    impl From<json::Sha256Digest> for base::Sha256Digest {
443        fn from(json_digest: json::Sha256Digest) -> base::Sha256Digest {
444            base::Sha256Digest(json_digest.data)
445        }
446    }
447
448    impl From<json::X509Cert> for base::X509Cert {
449        fn from(json_cert: json::X509Cert) -> base::X509Cert {
450            base::X509Cert(json_cert.data)
451        }
452    }
453}
454
455#[cfg(test)]
456mod test {
457    use super::*;
458
459    const APPEND: &str = r#"
460    {
461        "type": "Microsoft.Compute/disks",
462
463        "properties": {
464            "uefiSettings" : {
465                "signatureMode": "Append",
466                "signatures": {
467                    "db": [{
468                        "type": "sha256",
469                        "value": ["i4HHnT7SW4zUdcQ7LyvOyfVOTr9BxCWWoP/W3lqGE0Q=",
470                                "ELLxN/fAUzttWO5WW3SOdJ4a99OAWy56o2ga46W1Efc="]
471                    }],
472                    "dbx": [{
473                        "type": "sha256",
474                        "value": ["Bkk5Ef7VzGk3M7FLY/MyHyl+ygAF1P8ju9HBSl53Cak=",
475                                "h6/eEfJXfmqGLZWr/ekVjhQAiG3OlGw6Yi4MAbBjpqc="]
476                    }]
477                }
478            }
479        }
480    }
481    "#;
482
483    #[test]
484    fn append() {
485        let data = serde_json::from_str::<json::JsonRoot>(APPEND);
486        let _ = data.unwrap();
487    }
488
489    const APPEND_DEFAULT: &str = r#"
490    {
491        "type": "Microsoft.Compute/disks",
492
493        "properties": {
494            "uefiSettings" : {
495                "signatureMode": "Append",
496                "signatures": {
497                    "db": [{
498                        "type": "Default",
499                    }]
500                }
501            }
502        }
503    }
504    "#;
505
506    #[test]
507    fn append_default() {
508        let data = serde_json::from_str::<json::JsonRoot>(APPEND_DEFAULT);
509        assert!(data.is_err())
510    }
511
512    const REPLACE_MALFORMED_DB: &str = r#"
513    {
514        "type": "Microsoft.Compute/disks",
515
516        "properties": {
517            "uefiSettings" : {
518                "signatureMode": "Replace",
519                "signatures": {
520                    "PK": {
521                        "type": "x509",
522                        "value": ["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"]
523                    },
524                    "KEK": [{
525                        "type": "x509",
526                        "value": ["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"]
527                    }],
528                    "db": [{
529                        "type": "x509",
530                        "value": ["InvalidKey"]
531                    }],
532                    "dbx": [{
533                        "type": "Default"
534                    }]
535                }
536            }
537        }
538    }
539    "#;
540
541    #[test]
542    fn replace_malformed_db() {
543        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MALFORMED_DB);
544        assert!(data.is_err())
545    }
546
547    const REPLACE_MISSING_SIGNATURE_MODE: &str = r#"
548    {
549        "type": "Microsoft.Compute/disks",
550
551        "properties": {
552            "uefiSettings" : {
553                "signatures": {
554                    "PK": {
555                        "type": "x509",
556                        "value": ["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"]
557                    },
558                    "KEK": [{
559                        "type": "x509",
560                        "value": ["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"]
561                    }],
562                    "dbx": [{
563                        "type": "Default"
564                    }]
565                }
566            }
567        }
568    }
569    "#;
570
571    #[test]
572    fn replace_missing_signature_mode() {
573        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MISSING_SIGNATURE_MODE);
574        assert!(data.is_err())
575    }
576
577    const REPLACE_MULTI_DEFAULT: &str = r#"
578    {
579        "type": "Microsoft.Compute/disks",
580
581        "properties": {
582            "uefiSettings" : {
583                "signatureMode": "Replace",
584                "signatures": {
585                    "PK": {
586                        "type": "x509",
587                        "value": ["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"]
588                    },
589                    "KEK": [{
590                        "type": "Default"
591                    }, {
592                        "type": "Default"
593                    }],
594                    "db": [{
595                        "type": "x509",
596                        "value": ["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"]
597                    }],
598                    "dbx": [{
599                        "type": "Default"
600                    }]
601                }
602            }
603        }
604    }
605    "#;
606
607    #[test]
608    fn replace_multi_default() {
609        // serde parses this fine
610        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MULTI_DEFAULT).unwrap();
611        // but semantic checks will fail
612        let data = convert::json_to_delta(data);
613        assert!(data.is_err())
614    }
615
616    const REPLACE_MIXED_DEFAULT: &str = r#"
617    {
618        "type": "Microsoft.Compute/disks",
619
620        "properties": {
621            "uefiSettings" : {
622                "signatureMode": "Replace",
623                "signatures": {
624                    "PK": {
625                        "type": "x509",
626                        "value": ["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"]
627                    },
628                    "KEK": [{
629                        "type": "Default"
630                    }, {
631                        "type": "x509",
632                        "value": ["Jw=="]
633                    }],
634                    "db": [{
635                        "type": "x509",
636                        "value": ["MIIF1zCCA7+gAwIBAgIKYQd2VgAAAAAACDANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTExMDE5MTg0MTQyWhcNMjYxMDE5MTg1MTQyWjCBhDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEuMCwGA1UEAxMlTWljcm9zb2Z0IFdpbmRvd3MgUHJvZHVjdGlvbiBQQ0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN0Mu6LkLgnj58X3lmm8ACG9aTMz760Ey1SA7gaDu8UghNn30ovzOLCrpK0tfGJ5Bf/jSj8ENSBw48Tna+CcwDZ16Yox3Y1w5dw3tXRGlihbh2AjLL/cR6Vn91EnnnLrB6bJuR47UzV85dPsJ7mHHP65ySMJb6hGkcFuljxB08ujP10Cak3saR8lKFw2//1DFQqU4Bm0z9/CEuLCWyfuJ3gwi1sqCWsiiVNgFizAaB1TuuxJ851hjIVoCXNEXX2iVCvdefcVzzVdbBwrXM68nCOLb261Jtk2E8NP1ieuuTI7QZIs4cfNd+iqVE73XAsEh2W0QxiosuBtGXfsWiT6SAMCAwEAAaOCAUMwggE/MBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSpKQI5jhbEl3jNkPmeT5rhfFWvUzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAFPx8cVGlecJusu85Prw8Ug9uKz8QE3P+qGjQSKY0TYqWBSbuMUaQYXnW/zguRWv0wOUouNodj4rbCdcax0wKNmZqjOwb1wSQqBgXpJu54kAyNnbEwVrGv+QEwOoW06zDaO9irN1UbFAwWKbrfP6Up06O9Ox8hnNXwlIhczRa86OKVsgE2gcJ7fiL4870fo6u8PYLigj7P8kdcn9TuOu+Y+DjPTFlsIHl8qzNFqSfPaixm8JC0JCEX1Qd/4nquh1HkG+wc05Bn0CfX+WhKrIRkXOKISjwzt5zOV8+q1xg7N8DEKjTCen09paFtn9RiGZHGY2isBI9gSpoBXe7kUxie7bBB8e6eoc0Aw5LYnqZ6cr8zko3yS2kV3wc/j3cuA9a+tbEswKFAjrqs9lu5GkhN96B0fZ1GQVn05NXXikbOcjuLeHN5EVzW9DSznqrFhmCRljQXp2Bs2evbDXyvOU/JOI1ogp1BvYYVpnUeCzRBRvr0IgBnaoQ8QXfun4sY7cGmyMhxPl4bOJYFwY2K5ESA8yk2fItuvmUnUDtGEXxzopcaz6rA9NwGCoKauBfR9HVYwoy8q/XNh8qcFrlQlkIcUtXun6DgfAhPPQcwcW5kJMOiEWThumxIJm+mMvFlaRdYtagYwggvXUQd30980W5n5efy1eAbzOpBM93pGIcWX4="]
637                    }],
638                    "dbx": [{
639                        "type": "Default"
640                    }]
641                }
642            }
643        }
644    }
645    "#;
646
647    #[test]
648    fn replace_mixed_default() {
649        // serde parses this fine
650        let data = serde_json::from_str::<json::JsonRoot>(REPLACE_MIXED_DEFAULT).unwrap();
651        // but semantic checks will fail
652        let data = convert::json_to_delta(data);
653        assert!(data.is_err())
654    }
655
656    const REPLACE: &str = r#"
657    {
658        "type": "Microsoft.Compute/disks",
659
660        "properties": {
661            "uefiSettings" : {
662                "signatureMode": "Replace",
663                "signatures": {
664                    "PK": {
665                        "type": "x509",
666                        "value": ["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"]
667                    },
668                    "KEK": [{
669                        "type": "x509",
670                        "value": ["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"]
671                    }],
672                    "db": [{
673                        "type": "x509",
674                        "value": ["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"]
675                    }],
676                    "dbx": [{
677                        "type": "Default"
678                    }]
679                }
680            }
681        }
682    }
683    "#;
684
685    #[test]
686    fn replace() {
687        let data = serde_json::from_str::<json::JsonRoot>(REPLACE);
688        let _ = data.unwrap();
689    }
690
691    // BAD_DB is a semantic test that requires performing signature validation
692    // (which isn't done as part of the basic JSON parsing + validation)
693
694    // const BAD_DB: &str = r#"
695    // {
696    //     "type": "Microsoft.Compute/disks",
697
698    //     "properties": {
699    //         "uefiSettings" : {
700    //             "signatureMode": "Replace",
701    //             "signatures": {
702    //                 "PK": {
703    //                     "type": "x509",
704    //                     "value": ["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"]
705    //                 },
706    //                 "KEK": [{
707    //                     "type": "x509",
708    //                     "value": ["MIIF6DCCA9CgAwIBAgIKYQrRiAAAAAAAAzANBgkqhkiG9w0BAQsFADCBkTELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjE7MDkGA1UEAxMyTWljcm9zb2Z0IENvcnBvcmF0aW9uIFRoaXJkIFBhcnR5IE1hcmtldHBsYWNlIFJvb3QwHhcNMTEwNjI0MjA0MTI5WhcNMjYwNjI0MjA1MTI5WjCBgDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEqMCgGA1UEAxMhTWljcm9zb2Z0IENvcnBvcmF0aW9uIEtFSyBDQSAyMDExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxOi1ir+tVyawJsPq5/tXekQCXQcN2krldCrmsA/sbevsf7njWmMyfBEXTw7jC6c4FZOOxvXghLGamyzn9beR1gnh4sAEqKwwHN9I8wZQmmSnUX/IhU+PIIbO/i/hn/+CwO3pzc70U2piOgtDueIl/f4F+dTEFKsR4iOJjXC3pB1N7K7lnPoWwtfBy9ToxC/lme4kiwPsjfKL6sNK+0MREgt+tUeSbNzmBInr9TME6xABKnHl+YMTPP8lCS9odkb/uk++3K1xKliq+w7SeT3km2U7zCkqn/xyWaLrrpLv9jUTgMYC7ORfzJ12ze9jksGveUCEeYd/41Ko6J17B2mPFQIDAQABo4IBTzCCAUswEAYJKwYBBAGCNxUBBAMCAQAwHQYDVR0OBBYEFGL8Q82gPqTLZxLSW9lVrHvMtopfMBkGCSsGAQQBgjcUAgQMHgoAUwB1AGIAQwBBMAsGA1UdDwQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEVmUkPhflgRv9ZOniNVCDs6ImqoMFwGA1UdHwRVMFMwUaBPoE2GS2h0dHA6Ly9jcmwubWljcm9zb2Z0LmNvbS9wa2kvY3JsL3Byb2R1Y3RzL01pY0NvclRoaVBhck1hclJvb18yMDEwLTEwLTA1LmNybDBgBggrBgEFBQcBAQRUMFIwUAYIKwYBBQUHMAKGRGh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2kvY2VydHMvTWljQ29yVGhpUGFyTWFyUm9vXzIwMTAtMTAtMDUuY3J0MA0GCSqGSIb3DQEBCwUAA4ICAQDUhIj1FJQYAsoqPPsqkhwM16DR8ehSZqjuorV1epAAqi2kdlrqebe5N2pRexBk9uFk8gJnvveoG3i9us6IWGQM1lfIGaNfBdbbxtBpzkhLMrfrXdIw9cD1uLp4B6Mr/pvbNFaE7ILKrkElcJxr6f6QD9eWH+XnlB+yKgyNS/8oKRB799d8pdF2uQXIee0PkJKcwv7fb35sD3vUwUXdNFGWOQ/lXlbYGAWW9AemQrOgd/0IGfJxVsyfhiOkh8um/Vh+1GlnFZF+gfJ/E+UNi4o8h4Tr4869Q+WtLYSTjmorWnxE+lKqgcgtHLvgUt8AEfiaPcFgsOEztaOI0WUZChrnrHykwYKHTjixLw3FFIdv/Y0uvDm25+bD4OTNJ4TvlELvKYuQRkE7gRtn2PlDWWXLDbz9AJJP9HU7p6kk/FBBQHngLU8Kaid2blLtlml7rw/3hwXQRcKtUxSBH/swBKo3NmHaSmkbNNho7dYCz2yUDNPPbCJ5rbHwvAOiRmCpxAfCIYLx/fLoeTJgv9ispSIUS8rB2EvrfT9XNbLmT3W0sGADIlOukXkd1ptBHxWGVHCy3g01D3ywNHK6l2A78HnrorIcXaIWuIfF6Rv2tZclbzif45H6inmYw2kOt6McIAWX+MoUrgDXxPPAFBB1azSgG7WZYPNcsMVXTjbSMoS/ng=="]
709    //                 }]
710    //             },
711
712    //             "db": {
713    //                 "guid":"y7IZ1zo9lkWjvNrQDmdlbw==",
714    //                 "attributes":"Jw==",
715    //                 "value":"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"
716    //             },
717
718    //             "dbx": {
719    //                 "guid":"y7IZ1zo9lkWjvNrQDmdlbw==",
720    //                 "attributes":"Jw==",
721    //                 "value":"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"
722    //             }
723    //         }
724    //     }
725    // }
726    // "#;
727
728    // #[test]
729    // fn bad_db() {
730    //     let data = serde_json::from_str::<json::JsonRoot>(BAD_DB);
731    //     let _ = data.unwrap();
732    // }
733
734    const PRIVATE_VARS: &str = r#"
735    {
736        "type": "Microsoft.Compute/disks",
737
738        "properties": {
739            "uefiSettings" : {
740                "signatureMode": "Replace",
741                "signatures": {
742                    "PK": {
743                        "type": "x509",
744                        "value": ["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"]
745                    },
746                    "KEK": [{
747                        "type": "x509",
748                        "value": ["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"]
749                    }],
750                    "db": [{
751                        "type": "x509",
752                        "value": ["MIIF1zCCA7+gAwIBAgIKYQd2VgAAAAAACDANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTAwHhcNMTExMDE5MTg0MTQyWhcNMjYxMDE5MTg1MTQyWjCBhDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEuMCwGA1UEAxMlTWljcm9zb2Z0IFdpbmRvd3MgUHJvZHVjdGlvbiBQQ0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN0Mu6LkLgnj58X3lmm8ACG9aTMz760Ey1SA7gaDu8UghNn30ovzOLCrpK0tfGJ5Bf/jSj8ENSBw48Tna+CcwDZ16Yox3Y1w5dw3tXRGlihbh2AjLL/cR6Vn91EnnnLrB6bJuR47UzV85dPsJ7mHHP65ySMJb6hGkcFuljxB08ujP10Cak3saR8lKFw2//1DFQqU4Bm0z9/CEuLCWyfuJ3gwi1sqCWsiiVNgFizAaB1TuuxJ851hjIVoCXNEXX2iVCvdefcVzzVdbBwrXM68nCOLb261Jtk2E8NP1ieuuTI7QZIs4cfNd+iqVE73XAsEh2W0QxiosuBtGXfsWiT6SAMCAwEAAaOCAUMwggE/MBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBSpKQI5jhbEl3jNkPmeT5rhfFWvUzAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3JsLm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAxMC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8vd3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAFPx8cVGlecJusu85Prw8Ug9uKz8QE3P+qGjQSKY0TYqWBSbuMUaQYXnW/zguRWv0wOUouNodj4rbCdcax0wKNmZqjOwb1wSQqBgXpJu54kAyNnbEwVrGv+QEwOoW06zDaO9irN1UbFAwWKbrfP6Up06O9Ox8hnNXwlIhczRa86OKVsgE2gcJ7fiL4870fo6u8PYLigj7P8kdcn9TuOu+Y+DjPTFlsIHl8qzNFqSfPaixm8JC0JCEX1Qd/4nquh1HkG+wc05Bn0CfX+WhKrIRkXOKISjwzt5zOV8+q1xg7N8DEKjTCen09paFtn9RiGZHGY2isBI9gSpoBXe7kUxie7bBB8e6eoc0Aw5LYnqZ6cr8zko3yS2kV3wc/j3cuA9a+tbEswKFAjrqs9lu5GkhN96B0fZ1GQVn05NXXikbOcjuLeHN5EVzW9DSznqrFhmCRljQXp2Bs2evbDXyvOU/JOI1ogp1BvYYVpnUeCzRBRvr0IgBnaoQ8QXfun4sY7cGmyMhxPl4bOJYFwY2K5ESA8yk2fItuvmUnUDtGEXxzopcaz6rA9NwGCoKauBfR9HVYwoy8q/XNh8qcFrlQlkIcUtXun6DgfAhPPQcwcW5kJMOiEWThumxIJm+mMvFlaRdYtagYwggvXUQd30980W5n5efy1eAbzOpBM93pGIcWX4="]
753                    }],
754                    "dbx": [{
755                        "type": "Default"
756                    }]
757                },
758
759                "Var1": {
760                    "guid":"Yd/ki8qT0hGqDQDgmAMrjA==",
761                    "attributes":"Bw==",
762                    "value":"VGVzdCBWYXJpYWJsZSAx"
763                },
764
765                "Var2": {
766                    "guid":"Yd/ki8qT0hGqDQDgmAMrjA==",
767                    "attributes":"Jw==",
768                    "value":"VGVzdCBWYXJpYWJsZSAy"
769                }
770            }
771        }
772    }
773    "#;
774
775    #[test]
776    fn private_vars() {
777        let data = serde_json::from_str::<json::JsonRoot>(PRIVATE_VARS);
778        let data = data.unwrap();
779        match data.properties.uefi_settings.custom_vars.get("Var1") {
780            Some(v) => assert_eq!(v.attr, 7),
781            None => panic!(),
782        }
783        match data.properties.uefi_settings.custom_vars.get("Var2") {
784            Some(v) => assert_eq!(v.attr, 39),
785            None => panic!(),
786        }
787    }
788}