blob: d31028898d3bc27a193ecaaa5db1bc35e60732d7 [file] [log] [blame]
package caesar
# Check if an import is sealed with the Caesar capability type
is_sealed_caesar_capability(capability) {
capability.kind = "SealedObject"
capability.sealing_type.compartment = "caesar"
capability.sealing_type.key = "CaesarCapabilityType"
}
# Helpers for converting C integers to booleans.
# These fail if the input is not either 1 or 0
value_as_boolean(value) = output {
value = 1
output = true
}
value_as_boolean(value) = output {
value = 0
output = false
}
decode_caesar_capability(capability) = decoded {
# Fail if this is not sealed with the Caesar capability type
is_sealed_caesar_capability(capability)
some permitEncrypt, permitDecrypt, shift
# Extract the values. Each of these will fail if the value is not as expected.
# permitEncrypt is a (single-byte) boolean value at offset 0.
permitEncrypt = value_as_boolean(integer_from_hex_string(capability.contents, 0, 1))
# permitDecrypt is a (single-byte) boolean value at offset 1.
permitDecrypt = value_as_boolean(integer_from_hex_string(capability.contents, 1, 1))
# shift is a single-byte integer value at offset 2.
shift = integer_from_hex_string(capability.contents, 2, 1)
decoded = {
"permitEncrypt": permitEncrypt,
"permitDecrypt": permitDecrypt,
"shift": shift,
}
}
# Helper to extract all valid Caesar capabilities in the firmware image
all_valid_caesar_capabilities = [{"owner": owner, "capability": decode_caesar_capability(c)} | c = input.compartments[owner].imports[_]; is_sealed_caesar_capability(c)]
# Helper predicate to check that this is valid.
valid {
# Make sure that the RTOS configuration is valid.
data.rtos.valid
# There are two things sealed with the Caesar capability type
count([c | c = input.compartments[owner].imports[_]; is_sealed_caesar_capability(c)]) = 2
# Both of them are valid Caesar capabilities
count(all_valid_caesar_capabilities) = 2
# Extract the producer and consumer's capabilities
some producerCapability, consumerCapability
producerCapability = [c | c = all_valid_caesar_capabilities[_]; c.owner = "producer"][0].capability
consumerCapability = [c | c = all_valid_caesar_capabilities[_]; c.owner = "consumer"][0].capability
# Check permissions
producerCapability.permitEncrypt = true
producerCapability.permitDecrypt = false
consumerCapability.permitEncrypt = false
consumerCapability.permitDecrypt = true
# Make sure that the shift (encryption keys) are the same.
producerCapability.shift = consumerCapability.shift
# Make sure that only the producer and consumer compartments call the encrypt and decrypt functions
data.compartment.compartment_call_allow_list("caesar", "caesar_encrypt.*", {"producer"})
data.compartment.compartment_call_allow_list("caesar", "caesar_decrypt.*", {"consumer"})
# Make sure that only the entry compartment calls the produce and consume functions
data.compartment.compartment_call_allow_list("producer", "produce_message.*", {"entry"})
data.compartment.compartment_call_allow_list("consumer", "consume_message.*", {"entry"})
}