|  | #include <compartment-macros-asm.S> | 
|  | #include <cheri-builtins.h> | 
|  | #include "../allocator/token.h" | 
|  |  | 
|  | .include "assembly-helpers.s" | 
|  |  | 
|  | .hidden __sealingkey_either | 
|  | .type   __sealingkey_either,@object | 
|  | .section    .sealing_key1,"aw",@progbits | 
|  | .globl  __sealingkey_either | 
|  | .p2align    3 | 
|  | __sealingkey_either: | 
|  | .chericap   0 | 
|  | .size   __sealingkey_either, 8 | 
|  |  | 
|  | .hidden __sealingkey_static | 
|  | .type   __sealingkey_static,@object | 
|  | .section    .sealing_key2,"aw",@progbits | 
|  | .globl  __sealingkey_static | 
|  | .p2align    3 | 
|  | __sealingkey_static: | 
|  | .chericap   0 | 
|  | .size   __sealingkey_static, 8 | 
|  |  | 
|  | .hidden __sealingkey_dynamic | 
|  | .type   __sealingkey_dynamic,@object | 
|  | .section    .sealing_key3,"aw",@progbits | 
|  | .globl  __sealingkey_dynamic | 
|  | .p2align    3 | 
|  | __sealingkey_dynamic: | 
|  | .chericap   0 | 
|  | .size   __sealingkey_dynamic, 8 | 
|  |  | 
|  | .section .text,"ax",@progbits | 
|  |  | 
|  | .p2align 1 | 
|  |  | 
|  | /** | 
|  | * The core of unsealing: | 
|  | * | 
|  | *   void *token_unseal_internal( | 
|  | *     struct SKeyStruct *, struct SObjStruct *, void *); | 
|  | */ | 
|  | .Ltoken_unseal_internal: | 
|  | /* | 
|  | * Register allocation: | 
|  | * | 
|  | *  - ca0 holds the user's sealing key, and is replaced with the unsealed | 
|  | *    value or NULL | 
|  | * | 
|  | *  - ca1 holds the user's sealed object pointer | 
|  | * | 
|  | *  - ca2 holds the unsealing authority and is clobbered on failure | 
|  | *    explicitly and on success with a scalar (the sealed payload's length) | 
|  | * | 
|  | *  - a3 is used within each local computation and never holds secrets | 
|  | */ | 
|  |  | 
|  | /* Verify key tag */ | 
|  | cgettag a3, ca0 | 
|  | beqz    a3, .Lexit_failure | 
|  |  | 
|  | /* Verify key address == base and len > 0 */ | 
|  | cgetbase a3, ca0 | 
|  | bne      a0, a3, .Lexit_failure // as-integer access to ca0 gives address | 
|  | cgetlen  a3, ca0 | 
|  | beqz     a3, .Lexit_failure | 
|  |  | 
|  | /* Verify key has unseal permission */ | 
|  | cgetperm a3, ca0 | 
|  | andi     a3, a3, CHERI_PERM_UNSEAL | 
|  | beqz     a3, .Lexit_failure | 
|  |  | 
|  | /* Unseal, clobbering authority */ | 
|  | cunseal ca2, ca1, ca2 | 
|  |  | 
|  | /* Verify tag of unsealed form */ | 
|  | cgettag a3, ca2 | 
|  | beqz    a3, .Lexit_failure | 
|  |  | 
|  | /* | 
|  | * Load software type tag.  This will not trap, thanks to above tag check and | 
|  | * because IRQs are deferred (see our export entry below) | 
|  | */ | 
|  | clw a3, TokenSObj_offset_type(ca2) | 
|  |  | 
|  | /* Verify that the loaded value matches the address of the key. */ | 
|  | bne a0, a3, .Lexit_failure | 
|  |  | 
|  | /* Subset bounds to ->data */ | 
|  | // Get the top into a3 | 
|  | cgettop         a3, ca2 | 
|  | // Move the address to the start of the data, clobber the user's sealing key | 
|  | cincoffset      ca0, ca2, TokenSObj_offset_data | 
|  | // Subtract the address of the (to-be-returned-unsealed) data from the top to | 
|  | // give the length, clobbering our unsealing key. | 
|  | sub             a2, a3, a0 | 
|  | // Set the new bounds, using an exact setting so that any errors in the | 
|  | // allocator's alignment turn into an untagged capability here. | 
|  | csetboundsexact ca0, ca0, a2 | 
|  |  | 
|  | /* And that's an unwrap. */ | 
|  | cret | 
|  |  | 
|  | .Lexit_failure: | 
|  | /* Failure; clobber potential sensitive state in ca2 and return null */ | 
|  | zeroOne a2 | 
|  | zeroOne a0 | 
|  | cret | 
|  |  | 
|  | /** | 
|  | * An in-assembler implementation of | 
|  | * | 
|  | * [[cheri::interrupt_state(disabled)]] void *__cheri_libcall | 
|  | * token_obj_unseal(struct SKeyStruct *, struct SObjStruct *); | 
|  | * | 
|  | * The name has been manually mangled as per the C++ rules. | 
|  | */ | 
|  | .hidden _Z16token_obj_unsealP10SKeyStructP10SObjStruct | 
|  | .globl  _Z16token_obj_unsealP10SKeyStructP10SObjStruct | 
|  | _Z16token_obj_unsealP10SKeyStructP10SObjStruct: | 
|  | LoadCapPCC ca2, __sealingkey_either | 
|  |  | 
|  | /* | 
|  | * Backwards compatibility with CUnseal that requires address match. | 
|  | * This can (and should) be removed once everyone's caught up with | 
|  | * https://github.com/CHERIoT-Platform/cheriot-sail/pull/87 . | 
|  | */ | 
|  | cgettype   a3, ca1 | 
|  | csetaddr   ca2, ca2, a3 | 
|  |  | 
|  | j        .Ltoken_unseal_internal | 
|  |  | 
|  | /** | 
|  | * An in-assembler implementation of | 
|  | * | 
|  | * [[cheri::interrupt_state(disabled)]] void *__cheri_libcall | 
|  | * token_obj_unseal_static(struct SKeyStruct *, struct SObjStruct *); | 
|  | * | 
|  | * The name has been manually mangled as per the C++ rules. | 
|  | */ | 
|  | .hidden  _Z23token_obj_unseal_staticP10SKeyStructP10SObjStruct | 
|  | .globl   _Z23token_obj_unseal_staticP10SKeyStructP10SObjStruct | 
|  | _Z23token_obj_unseal_staticP10SKeyStructP10SObjStruct: | 
|  | LoadCapPCC ca2, __sealingkey_static | 
|  | j          .Ltoken_unseal_internal | 
|  |  | 
|  | /** | 
|  | * An in-assembler implementation of | 
|  | * | 
|  | * [[cheri::interrupt_state(disabled)]] void *__cheri_libcall | 
|  | * token_obj_unseal_dynamic(struct SKeyStruct *, struct SObjStruct *); | 
|  | * | 
|  | * The name has been manually mangled as per the C++ rules. | 
|  | */ | 
|  | .hidden  _Z24token_obj_unseal_dynamicP10SKeyStructP10SObjStruct | 
|  | .globl   _Z24token_obj_unseal_dynamicP10SKeyStructP10SObjStruct | 
|  | _Z24token_obj_unseal_dynamicP10SKeyStructP10SObjStruct: | 
|  | LoadCapPCC ca2, __sealingkey_dynamic | 
|  | j          .Ltoken_unseal_internal | 
|  |  | 
|  | /* TODO: Eventually this goes away, when the assembler can generate it for us */ | 
|  | CHERIOT_EXPORT_LIBCALL \ | 
|  | _Z16token_obj_unsealP10SKeyStructP10SObjStruct, \ | 
|  | 0 /* No stack usage */, \ | 
|  | 0b00010010 /* IRQs deferred, zero two registers */ | 
|  |  | 
|  | CHERIOT_EXPORT_LIBCALL \ | 
|  | _Z23token_obj_unseal_staticP10SKeyStructP10SObjStruct, \ | 
|  | 0 /* No stack usage */, \ | 
|  | 0b00010010 /* IRQs deferred, zero two registers */ | 
|  |  | 
|  | CHERIOT_EXPORT_LIBCALL \ | 
|  | _Z24token_obj_unseal_dynamicP10SKeyStructP10SObjStruct, \ | 
|  | 0 /* No stack usage */, \ | 
|  | 0b00010010 /* IRQs deferred, zero two registers */ |