├── FEEDBACK.md ├── LICENSE.md ├── README.md └── fw └── psp_bl_uapps └── sev_uapp └── src ├── amd_cert.c ├── amd_cert.h ├── apicid.c ├── apicid.h ├── bignum.c ├── bignum.h ├── ccp_direct_cipher.c ├── ccp_direct_cipher.h ├── cipher.c ├── cipher.h ├── cipher_utest.c ├── cipher_utest.h ├── compression.h ├── cpuid_lookup.c ├── cpuid_lookup.h ├── crc.c ├── crc.h ├── df_regs.c ├── df_regs.h ├── df_regs_utest.c ├── df_regs_utest.h ├── digest.c ├── digest.h ├── digest_utest.c ├── digest_utest.h ├── ecc.c ├── ecc.h ├── ecc_utest.c ├── ecc_utest.h ├── ecdh.c ├── ecdh.h ├── ecdh_utest.c ├── ecdh_utest.h ├── ecdsa.c ├── ecdsa.h ├── ecdsa_utest.c ├── ecdsa_utest.h ├── encrypt_memory_utest.c ├── encrypt_memory_utest.h ├── end_data.s ├── header.inc ├── helper.c ├── helper.h ├── hmac.c ├── hmac.h ├── hmac_utest.c ├── hmac_utest.h ├── kdf.c ├── kdf.h ├── main.c ├── nist_kdf.c ├── nist_kdf.h ├── pool_u32.c ├── pool_u32.h ├── rom_rsmu.h ├── rsa.c ├── rsa.h ├── rsa_utest.c ├── rsa_utest.h ├── secure_ops.c ├── secure_ops.h ├── secure_ops_utest.c ├── secure_ops_utest.h ├── sev_cert.c ├── sev_cert.h ├── sev_cert_utest.c ├── sev_cert_utest.h ├── sev_channel.c ├── sev_channel.h ├── sev_dispatch.c ├── sev_dispatch.h ├── sev_errors.c ├── sev_errors.h ├── sev_es.c ├── sev_es.h ├── sev_extended_errors.h ├── sev_fw_image.h ├── sev_globals.c ├── sev_globals.h ├── sev_guest.c ├── sev_guest.h ├── sev_hal.c ├── sev_hal.h ├── sev_hal_interface.c ├── sev_hal_interface.h ├── sev_hal_iommu.c ├── sev_hal_iommu.h ├── sev_mcmd.c ├── sev_mcmd.h ├── sev_persistent.c ├── sev_persistent.h ├── sev_persistent_utest.c ├── sev_persistent_utest.h ├── sev_plat.c ├── sev_plat.h ├── sev_ring_buffer.c ├── sev_ring_buffer.h ├── sev_rmp.c ├── sev_rmp.h ├── sev_scmd.c ├── sev_scmd.h ├── sev_tmr.c ├── sev_tmr.h ├── sev_trace.h ├── sev_wrap.c ├── sev_wrap.h ├── startup.s ├── sw_hash.c ├── sw_hash.h ├── tmr_cache.c ├── tmr_cache.h ├── umc.c ├── umc.h ├── x86_copy.c └── x86_copy.h /FEEDBACK.md: -------------------------------------------------------------------------------- 1 | To report to AMD potential security vulnerabilities contact psirt@amd.com 2 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | AMD Secure Encrypted Virtualization (SEV) Firmware for 4th Generation AMD EPYC® Processors Secure Encrypted Virtualization (SEV) Firmware License 2 | 3 | Copyright © 2023 Advanced Micro Devices, Inc. 4 | 5 | In an effort to increase transparency in the security space, Advanced Micro Devices, Inc. (“AMD”) is making the source code for the AMD SEV firmware for 4th Generation AMD EPYC Processors (formerly codenamed “Genoa”) (the “Software”) available to you (either an individual or an entity) ("You") to assess; AMD is not accepting contributions to this Software. 6 | 7 | These license terms are an agreement (“Agreement”) between AMD and You, and the terms apply to the Software identified above. By installing, copying, or using the Software you agree to all the terms and conditions of this Agreement. If You do not or cannot agree to the terms of this Agreement, please do not download or use this Software. 8 | 9 | LICENSE GRANT: Subject to Your compliance with all of the terms and condition of this License, AMD grants You a non-exclusive, non-transferable, free of charge copyright license to use, copy, modify, and create derivatives for the purpose of evaluating the Software for use with AMD’s hardware only; and/or distribute the Software (including derivatives of the Software), for use with AMD hardware only. 10 | 11 | COPYRIGHT NOTICE: The above copyright notice shall be included in all copies or substantial portions of the Software. 12 | 13 | RESTRICTIONS: 14 | i. You may not combine, distribute, or otherwise use the Software in a way that would require any portion of the Software to be made available under any terms other than those of this Agreement. 15 | ii. You may not use the Software to: (a) develop inventions to seek patent protection; (b) assist in the analysis of Your patents and patent applications; or (c) modify Your existing patents or patent applications. 16 | 17 | OWNERSHIP: The Software as well as all intellectual property rights therein are and remain the sole and exclusive property of AMD. 18 | 19 | FEEDBACK AND CONTRIBUTIONS: AMD is not accepting contributions to the Software. You have no obligation to give AMD any suggestions, comments or other feedback (“Feedback”) relating to the Software. However, if You choose to provide AMD with any Feedback, AMD is free to use the Feedback however it chooses. You understand and agree that AMD is not required to make any use of any Feedback that You provide. You represent and warrant that You have sufficient rights in any Feedback that You provide to AMD, to grant AMD and its affiliates the rights described above. 20 | 21 | 22 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES, OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, STRICT LIABILITY OR TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AMD-ASPFW 2 | 3 | SEV FW source corresponds to Genoa SEV FW version 1.55.25 [hex 1.37.19] 4 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/amd_cert.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef AMD_CERT_H 4 | #define AMD_CERT_H 5 | 6 | #include "sev_cert.h" 7 | #include "sev_errors.h" 8 | 9 | #define AMD_CERT_VERSION (0x01) 10 | #define AMD_CERT_ID_SIZE_BYTES (16) 11 | 12 | enum amd_cert_key_bits 13 | { 14 | AMD_CERT_KEY_BITS_2K = 2048, 15 | AMD_CERT_KEY_BITS_4K = 4096, 16 | }; 17 | 18 | typedef struct amd_cert_fixed 19 | { 20 | uint32_t version; 21 | uint8_t key_id[AMD_CERT_ID_SIZE_BYTES]; 22 | uint8_t certifying_id[AMD_CERT_ID_SIZE_BYTES]; 23 | uint32_t key_usage; 24 | uint8_t reserved[AMD_CERT_ID_SIZE_BYTES]; 25 | uint32_t pubexp_size_bits; 26 | uint32_t modulus_size_bits; 27 | } amd_cert_fixed_t; 28 | 29 | #define AMD_CERT_MAX_LENGTH (sizeof(amd_cert_fixed_t) + \ 30 | 3*AMD_CERT_KEY_BITS_4K/(BITS_PER_BYTE)) 31 | #define AMD_CERT_MIN_LENGTH (sizeof(amd_cert_fixed_t) + \ 32 | 3*AMD_CERT_KEY_BITS_2K/(BITS_PER_BYTE)) 33 | typedef struct amd_cert_pubkey 34 | { 35 | uint32_t pubexp_size; 36 | uint32_t modulus_size; 37 | const uint8_t *pubexp; 38 | const uint8_t *modulus; 39 | } amd_cert_pubkey_t; 40 | 41 | typedef struct amd_cert 42 | { 43 | amd_cert_fixed_t fixed; 44 | amd_cert_pubkey_t pubkey; 45 | const uint8_t *signature; 46 | } amd_cert_t; 47 | 48 | /** 49 | * Initialize an amd_cert_t object. AMD certificates are far too large to store 50 | * on the stack, so the caller must first copy the certificate into a 51 | * sufficiently large buffer. 52 | * 53 | * Parameters: 54 | * cert [out] AMD certificate object, 55 | * buffer [in] buffer containing the raw AMD certificate, 56 | * size [in] size of the data in the buffer. 57 | */ 58 | sev_status_t amd_cert_init(amd_cert_t *cert, const uint8_t *buffer, 59 | size_t size); 60 | 61 | /** 62 | * Validate the AMD Root Key certificate. 63 | * 64 | * Parameters: 65 | * cert [in] ARK certificate object. 66 | */ 67 | sev_status_t amd_cert_validate_ark(const amd_cert_t *ark); 68 | 69 | /** 70 | * Validate the AMD SEV Signing Key certificate. 71 | * 72 | * Parameters: 73 | * ask [in] ASK certificate object, 74 | * ark [in] ARK certificate object, 75 | */ 76 | sev_status_t amd_cert_validate_ask(const amd_cert_t *ask, 77 | const amd_cert_t *ark); 78 | 79 | size_t amd_cert_get_size(const amd_cert_t *cert); 80 | sev_status_t amd_cert_export_pubkey(const amd_cert_t *cert, 81 | sev_cert_pubkey_t *pubkey); 82 | bool amd_cert_chain_length_is_valid(size_t length); 83 | 84 | #endif /* AMD_CERT_H */ 85 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/apicid.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2018-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef APICID_H 4 | #define APICID_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_plat.h" 10 | #include "sev_status.h" 11 | 12 | /* Apicid list count (numIDs) limit for apicid to ccx bitmask conversion. */ 13 | /* Each apicid entry is 4 bytes (32bits), and the maximum number of entries 14 | for a 4K page should be 1024 entries */ 15 | #define APIC_ID_LIST_MAX_CNT (1024) /* 4K memory - 1 page */ 16 | 17 | /** 18 | * Creates APIC ID look up table. 19 | */ 20 | sev_status_t create_apicid_table(sev_t *sev); 21 | 22 | /** 23 | * Sync up APIC ID lookup table between master and slave 24 | */ 25 | sev_status_t sync_apicid_tables(sev_t *sev); 26 | 27 | /** 28 | * Converts a list of APICIDs of uint32_t to the PHYSICAL ccx_bitmask 29 | */ 30 | sev_status_t apicid_to_ccx_bitmask(sev_t *sev, uint32_t *apicid_list, 31 | size_t listcnt, uint32_t *ccx_bitmask); 32 | 33 | /** 34 | * Get the APIC ID (physical params) 35 | */ 36 | sev_status_t get_apic_id(uint32_t socket_id, uint32_t ccd, uint32_t ccx, uint32_t core, uint32_t thread_id, uint32_t *apicid); 37 | /** 38 | * Get the APIC ID (logical params) 39 | */ 40 | uint32_t get_apic_id_logical(uint32_t socket_id, uint32_t ccd, uint32_t ccx, uint32_t core, uint32_t thread_id); 41 | 42 | /** 43 | * Helper function to get bits needed to represent given number of instances. 44 | */ 45 | uint32_t get_field_width(uint32_t num_instances); 46 | 47 | uint32_t get_num_cores_per_complex(void); 48 | 49 | uint32_t get_ccds_per_socket(void); 50 | 51 | uint32_t get_ccxs_per_ccd(void); 52 | 53 | uint32_t get_max_ccds(void); 54 | 55 | uint32_t get_physical_ccxs_per_ccd(void); 56 | 57 | #endif /* APICID_H */ 58 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/bignum.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2012-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef BIGNUM_H 4 | #define BIGNUM_H 5 | 6 | #include 7 | #include 8 | 9 | #include "common_utilities.h" 10 | 11 | /** 12 | * Error codes 13 | */ 14 | #define KC_OK 0x00000000 // Result OK 15 | #define KC_SUCCESS 0x00000000 // Result SUCCESS 16 | #define KCERR_GENERIC_ERROR 0x00008001 // Generic Error 17 | #define KCERR_BUFFER_OVERFLOW 0x00008002 // Not enough space for output 18 | #define KCERR_INVALID_PARAMETER 0x00008003 19 | #define KCERR_INCORRECT_DATA_LEN 0x00008004 20 | #define KCERR_NULL_PTR 0x00008005 21 | #define KCERR_FUNCTION_NOT_SUPPORTED 0x00008006 22 | 23 | #define KCERR_INVALID_SESSION 0x00008007 24 | #define KCERR_INVALID_OPERATION 0x00008008 25 | #define KCERR_INVALID_ROUNDS 0x00008009 // Invalid number of rounds 26 | #define KCERR_INVALID_OPERATION_TYPE 0x0000800A 27 | #define KCERR_FAIL_TESTVECTOR 0x0000800B // Algorithm failed test vectors 28 | #define KCERR_DATA_CORRUPTED 0x0000800C // Corrupted data buffer 29 | 30 | #define KCERR_BN_TOO_SMALL 0x0000800D // BigNumber too small for result value 31 | #define KCERR_BAD_BIGNUMBER 0x0000800E // Illegal BigNumber passed (probably NULL) 32 | #define KCERR_SCRATCH_TOO_SMALL 0x0000800F // Scratch area not big enough 33 | #define KCERR_PK_INVALID_SIZE 0x00008010 // Invalid size input for PK parameters 34 | #define KCERR_RSA_DECRYPTION_ERROR 0x00008011 // RSA decryption error 35 | #define KCERR_PK_INVALID_TYPE 0x00008012 // Invalid type of PK key 36 | 37 | #define KCERR_NOT_IMPLEMENTED 0x00008013 // Internal - Code not implemented 38 | #define KCERR_INTERNAL_ERROR 0x00008014 // Internal error 39 | #define KCERR_SIGNATURE_INCORRECT 0x00008015 // incorrect signature 40 | #define KCERR_BN_NO_INVERSE 0x00008016 // no inverse 41 | #define KCERR_BN_INVALID_SIZE 0x00008017 // invalid size of the operand 42 | #define KCERR_INCORRECT_UNIT_SIZE 0x00008018 // incorrect XTS unit size 43 | #define KCERR_DATA_LENGTH 0x00008019 // incorrect data length 44 | 45 | #define BN_BITS 28 46 | 47 | /** 48 | * The data size is set for 1024 bit big numbers where 49 | * the result of multiplication is 2048 bit. 50 | * 64 bytes + 16 bytes, where the 16 bytes is used for optimization. 51 | * The implementation is size-optimized for debug-unlock. 52 | */ 53 | #define MAX_BN_ELEMENTS 80 54 | 55 | // Big number structure 56 | typedef struct _KC_BIGNUM 57 | { 58 | uint32_t Used; // how many elements used 59 | uint32_t Sign; // 1 means negative value 60 | uint32_t Obfuscated; // whether bignum is obfuscated or not 61 | uint32_t Data[MAX_BN_ELEMENTS]; // 28-bit elements of big number 62 | } KC_BIGNUM; 63 | 64 | typedef struct _KC_BN_SCRATCH 65 | { 66 | KC_BIGNUM Barrett_u; // u value for Barrett modular reduction 67 | KC_BIGNUM BarrettTemp[3]; // temporary numbers for BNBarrettReduce function 68 | KC_BIGNUM Temp[6]; // temporary numbers for BNDiv() function 69 | } KC_BN_SCRATCH; 70 | 71 | // Set bignum to integer value (integer must not be bigger than 0x0FFFFFFF). 72 | #define BN_SET_INT( Bn, Integer ) \ 73 | { \ 74 | Bn.Used = 1; \ 75 | Bn.Sign = 0; \ 76 | Bn.Obfuscated = 0; \ 77 | Bn.Data[0] = Integer; \ 78 | \ 79 | } 80 | 81 | enum 82 | { 83 | BN_BIGGER = 1, 84 | BN_SMALLER = 2, 85 | BN_EQUAL = 3 86 | }; 87 | 88 | // Functions provided 89 | 90 | uint32_t BNLoad( KC_BIGNUM *pBn, const uint8_t *pData, uint32_t DataLen ); 91 | uint32_t BNStore( KC_BIGNUM *pBn, uint8_t *pData, uint32_t DataLen ); 92 | 93 | void BNCopy( KC_BIGNUM *pDest, KC_BIGNUM *pSrc ); 94 | void BNShiftDigR( KC_BIGNUM *pDest, KC_BIGNUM *pSrc, uint32_t Shift ); 95 | uint32_t BNShiftDigL( KC_BIGNUM *pDest, KC_BIGNUM *pSrc, uint32_t Shift ); 96 | uint32_t BNShiftBitsL( KC_BIGNUM *pDest, KC_BIGNUM *pSrc, uint32_t Shift ); 97 | void BNShiftBitsR( KC_BIGNUM *pDest, KC_BIGNUM *pSrc, uint32_t Shift ); 98 | uint32_t BNCompare( KC_BIGNUM *x, KC_BIGNUM *y ); 99 | uint32_t BNSecureCompare( KC_BIGNUM *x, KC_BIGNUM *y ); 100 | uint32_t BNMultiply( KC_BIGNUM *x, KC_BIGNUM *y, KC_BIGNUM *z, uint32_t Digits ); 101 | uint32_t BNMultiplyHighDigs( KC_BIGNUM *z, KC_BIGNUM *x, KC_BIGNUM *y, uint32_t Digits ); 102 | uint32_t BNAdd( KC_BIGNUM *z, KC_BIGNUM *x, KC_BIGNUM *y ); 103 | uint32_t BNSubtract( KC_BIGNUM *z, KC_BIGNUM *x, KC_BIGNUM *y ); 104 | void BNMod_2Pwr( KC_BIGNUM *z, KC_BIGNUM *x, uint32_t Exp ); 105 | uint32_t BNBitCount( KC_BIGNUM *pBn ); 106 | uint32_t BNDiv( KC_BN_SCRATCH *pScratch, KC_BIGNUM *z, KC_BIGNUM *a, KC_BIGNUM *b, KC_BIGNUM *r ); 107 | uint32_t BNSet2Pwr( KC_BIGNUM *pBn, uint32_t Pwr ); 108 | uint32_t BNBarrettSetup( KC_BN_SCRATCH *pScratch, KC_BIGNUM *m ); 109 | uint32_t BNBarrettReduce( KC_BN_SCRATCH *pScratch, KC_BIGNUM *r, KC_BIGNUM *x, KC_BIGNUM *m ); 110 | 111 | #endif /* BIGNUM_H */ 112 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ccp_direct_cipher.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2018-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef CCP_DIRECT_CIPHER_H 4 | #define CCP_DIRECT_CIPHER_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t aesctr_hmac256_encrypt(const uint8_t *pEncKey, size_t EncKeySize, 12 | const uint8_t *pMacKey, size_t MacKeySize, 13 | const uint8_t *pAAD, size_t AADSize, 14 | const uint8_t *pMsg, size_t MsgSize, 15 | uint8_t *pOut, uint8_t *pIV, 16 | uint8_t *pHmac); 17 | 18 | sev_status_t aesctr_hmac256_decrypt(const uint8_t *pEncKey, size_t EncKeySize, 19 | const uint8_t *pMacKey, size_t MacKeySize, 20 | const uint8_t *pAAD, size_t AADSize, 21 | const uint8_t *pMsg, size_t MsgSize, 22 | uint8_t *pOut, const uint8_t *pIv, 23 | const uint8_t *pHmac); 24 | 25 | sev_status_t aes256gcm_authenticated_encrypt(const uint8_t *pKey, size_t KeySize, 26 | const uint8_t *pAAD, size_t AADSize, 27 | const uint8_t *pMsg, size_t MsgSize, 28 | uint8_t *pOut, 29 | const uint8_t *pIV, size_t IVSize, 30 | uint8_t *pTag); // [out, 16 bytes] 31 | 32 | sev_status_t aes256gcm_authenticated_encrypt_x86addr(const uint8_t *pKey, size_t KeySize, 33 | const uint8_t *pAAD, size_t AADSize, 34 | const uint64_t MsgAddr, size_t MsgSize, 35 | const uint64_t OutAddr, 36 | const uint8_t *pIV, size_t IVSize, 37 | uint8_t *pTag, // [out, 16 bytes] 38 | uint32_t asid); 39 | 40 | sev_status_t aes256gcm_authenticated_decrypt(const uint8_t *pKey, size_t KeySize, 41 | const uint8_t *pAAD, size_t AADSize, 42 | const uint8_t *pMsg, size_t MsgSize, 43 | uint8_t *pOut, 44 | const uint8_t *pIV, size_t IVSize, 45 | const uint8_t *pTag); // [in, 16 bytes] 46 | 47 | sev_status_t aes256gcm_authenticated_decrypt_x86addr(const uint8_t *pKey, size_t KeySize, 48 | const uint8_t *pAAD, size_t AADSize, 49 | const uint64_t MsgAddr, size_t MsgSize, 50 | const uint64_t OutAddr, 51 | const uint8_t *pIV, size_t IVSize, 52 | const uint8_t *pTag, // [in, 16 bytes] 53 | uint32_t asid); 54 | 55 | // -- KAT ---------------------------------------------------------------- 56 | 57 | sev_status_t digest_utest_sha256_kat(const uint8_t *msg, size_t msg_size, 58 | const uint8_t *digest, int multipart); 59 | 60 | sev_status_t hmac_utest_hmac256_kat(const uint8_t *key, size_t key_size, 61 | const uint8_t *msg, size_t msg_size, 62 | const uint8_t *hmac); 63 | 64 | sev_status_t cipher_utest_aes256gcm_kat(const uint8_t *pKey, const uint8_t *pIV, 65 | size_t IV_size, const uint8_t *pAAD, 66 | size_t AADSize, const uint8_t *pMsg, 67 | size_t MsgSize, 68 | const uint8_t *pCiphertext, 69 | const uint8_t *pTag); 70 | 71 | #endif /* CCP_DIRECT_CIPHER_H */ 72 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/cipher.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "cipher.h" 6 | #include "helper.h" 7 | #include "secure_ops.h" 8 | #include "sev_hal.h" 9 | 10 | static bool mode_is_valid(cipher_aes_mode_t mode) 11 | { 12 | bool result = false; 13 | 14 | switch (mode) 15 | { 16 | case AES_MODE_DECRYPT: 17 | case AES_MODE_ENCRYPT: 18 | result = true; 19 | break; 20 | default: 21 | result = false; 22 | } 23 | 24 | return result; 25 | } 26 | 27 | /** 28 | * Implements AES-CTR init. 29 | * 30 | * 'ctx': output, pointer to a pointer of context provided by crypto layer. 31 | */ 32 | sev_status_t cipher_aes_ctr_init(cipher_aes_ctr_ctx_t *ctx, 33 | const cipher_aes_iv_t *counter, 34 | const cipher_aes_key_t *key, 35 | const cipher_aes_mode_t mode) 36 | { 37 | sev_status_t status = SEV_STATUS_SUCCESS; 38 | 39 | if (!ctx || !counter || !key || !mode_is_valid(mode)) 40 | { 41 | status = ERR_INVALID_PARAMS; 42 | goto end; 43 | } 44 | 45 | memset(ctx, 0, sizeof(*ctx)); 46 | memcpy(&ctx->counter, counter, sizeof(ctx->counter)); 47 | memcpy(&ctx->key, key, sizeof(ctx->key)); 48 | ctx->mode = mode; 49 | 50 | end: 51 | return status; 52 | } 53 | 54 | /** 55 | * Implements AES-CTR update. 56 | * 57 | * 'ctx': input/output of intermediate context IV 58 | * 'src_len': must be a multiple of 16 bytes (i.e. 128-bits) so there's no padding 59 | * 'src' and 'dest': the data must be 16 bytes aligned so there's no padding. 60 | * 61 | * support In Place operation (src==dest)!!! 62 | */ 63 | sev_status_t cipher_aes_ctr_update(cipher_aes_ctr_ctx_t *ctx, 64 | const uint8_t *src, uint32_t src_len, 65 | uint8_t *dest, uint32_t *dest_len) 66 | { 67 | sev_status_t status = SEV_STATUS_SUCCESS; 68 | sev_hal_aes_t aes_params; 69 | sev_hal_aes_mode_t aes_mode = CCP_HAL_AES_MODE_DECRYPT; 70 | 71 | if (!ctx || !src || src_len == 0 || !dest || !dest_len || *dest_len == 0 || 72 | src_len > *dest_len || !mode_is_valid(ctx->mode) || 73 | !IS_ALIGNED_TO_16_BYTES(src_len)) 74 | { 75 | status = ERR_INVALID_PARAMS; 76 | goto end; 77 | } 78 | 79 | // Call HAL layer to get result 80 | aes_params.iv = ctx->counter.iv; 81 | aes_params.iv_length = sizeof(ctx->counter.iv); 82 | aes_params.key = (const uint8_t *)ctx->key.key; 83 | aes_params.key_length = sizeof(ctx->key.key); 84 | aes_params.key_memtype = CCP_HAL_LOCAL; 85 | aes_params.src = src; 86 | aes_params.src_length = src_len; 87 | aes_params.src_memtype = CCP_HAL_LOCAL; /* Assume we are using SEV heap space for migration pipeline */ 88 | aes_params.dest = (const uint8_t *)dest; 89 | aes_params.dest_length = *dest_len; 90 | aes_params.dest_memtype = CCP_HAL_LOCAL; /* Assume we are using SEV heap space for migration pipeline */ 91 | aes_params.aes_alg = CCP_HAL_AES_ALG_CTR; /* AES CTR */ 92 | 93 | if (ctx->mode == AES_MODE_DECRYPT) 94 | aes_mode = CCP_HAL_AES_MODE_DECRYPT; 95 | else 96 | aes_mode = CCP_HAL_AES_MODE_ENCRYPT; 97 | aes_params.aes_mode = aes_mode; 98 | 99 | /* Intermediate IV will be updated in this call */ 100 | status = sev_hal_aes_generic(&aes_params); 101 | if (status != SEV_STATUS_SUCCESS) 102 | goto end; 103 | 104 | *dest_len = src_len; 105 | 106 | end: 107 | return status; 108 | } 109 | 110 | /** 111 | * Implements AES-CTR final. 112 | * 113 | * 'ctx': input of final IV, note: this final IV cannot be used as context IV if src_len is not aligned to 16. 114 | * 'src_len': could be 0, or anything. Does not have to be multiple of 16 bytes. 115 | * 'src' and 'dest': must be 16 bytes aligned. 116 | * 117 | * support In Place operation (src==dest)!!! 118 | */ 119 | sev_status_t cipher_aes_ctr_final(cipher_aes_ctr_ctx_t *ctx, 120 | const uint8_t *src, uint32_t src_len, 121 | uint8_t *dest, uint32_t *dest_len) 122 | { 123 | sev_status_t status = SEV_STATUS_SUCCESS; 124 | size_t dest_size = 0, bytes_written = 0; 125 | 126 | if (!ctx || !src || !dest || !dest_len || !mode_is_valid(ctx->mode)) 127 | { 128 | status = ERR_INVALID_PARAMS; 129 | goto end; 130 | } 131 | 132 | if (src_len == 0) /* Nothing to do */ 133 | goto end; 134 | 135 | /* Since src_len != 0, now we can do more check against src and dest */ 136 | dest_size = *dest_len; 137 | if (src_len > dest_size || dest_size == 0) 138 | { 139 | status = ERR_INVALID_PARAMS; 140 | goto end; 141 | } 142 | 143 | if (IS_ALIGNED_TO_16_BYTES(src_len)) 144 | { 145 | /* Aligned to 16, directly call update. It may have worked, so still 146 | * inc counters, but pass back error */ 147 | status = cipher_aes_ctr_update(ctx, src, src_len, dest, &dest_size); 148 | bytes_written += dest_size; 149 | } 150 | else 151 | { 152 | /* Not aligned to 16 */ 153 | size_t len = src_len & (~0x0000000F); 154 | size_t len_leftover = src_len - len; 155 | uint8_t padding[CIPHER_AES_BLOCK_SIZE_BYTES]; 156 | size_t padding_len = sizeof(padding); 157 | 158 | if (len != 0) 159 | { 160 | status = cipher_aes_ctr_update(ctx, src, len, dest, &dest_size); 161 | if (status != SEV_STATUS_SUCCESS) 162 | goto end; 163 | 164 | bytes_written += dest_size; 165 | } 166 | 167 | /* Pad to 16 bytes before processing */ 168 | memset(padding, 0, sizeof(padding)); 169 | memcpy(padding, src + len, len_leftover); 170 | 171 | /* In-place update for the padded 16 bytes */ 172 | status = cipher_aes_ctr_update(ctx, padding, padding_len, 173 | padding, &padding_len); 174 | if (status != SEV_STATUS_SUCCESS) 175 | goto end; 176 | 177 | /* Copy the data to dest buffer */ 178 | memcpy(dest + bytes_written, padding, len_leftover); 179 | bytes_written += len_leftover; 180 | 181 | /* Attention! cache operation may be required if dest buffer is in DRAM */ 182 | } 183 | 184 | *dest_len = bytes_written; 185 | 186 | end: 187 | if (ctx) 188 | { 189 | /* Clean up */ 190 | secure_memzero(ctx, sizeof(*ctx)); 191 | ctx->mode = AES_MODE_INVALID; 192 | } 193 | 194 | return status; 195 | } 196 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/cipher.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef CIPHER_H 4 | #define CIPHER_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | #define CIPHER_AES128_KEY_SIZE_BYTES 16 /* Existing SEV APIs */ 12 | #define CIPHER_AES_KEY_SIZE_BYTES 32 /* Genoa hardware - UMC keys, cnli */ 13 | #define CIPHER_AES_BLOCK_SIZE_BYTES 16 14 | #define CIPHER_AES_IV_SIZE_BYTES (CIPHER_AES_BLOCK_SIZE_BYTES) 15 | 16 | typedef struct cipher_aes_iv 17 | { 18 | uint8_t iv[CIPHER_AES_IV_SIZE_BYTES]; 19 | } cipher_aes_iv_t; 20 | 21 | typedef struct cipher_aes_key 22 | { 23 | uint8_t key[CIPHER_AES128_KEY_SIZE_BYTES]; 24 | } cipher_aes_key_t; 25 | 26 | typedef enum cipher_aes_mode 27 | { 28 | AES_MODE_DECRYPT = 0, 29 | AES_MODE_ENCRYPT = 1, 30 | AES_MODE_INVALID = 0xFF, 31 | } cipher_aes_mode_t; 32 | 33 | typedef struct cipher_aes_ctr_ctx 34 | { 35 | cipher_aes_iv_t counter; 36 | cipher_aes_key_t key; 37 | cipher_aes_mode_t mode; 38 | } cipher_aes_ctr_ctx_t; 39 | 40 | /** 41 | * Implements AES-CTR init. 42 | * 43 | * 'ctx': output, pointer to context provided by crypto layer. 44 | * 45 | */ 46 | sev_status_t cipher_aes_ctr_init(cipher_aes_ctr_ctx_t *ctx, 47 | const cipher_aes_iv_t *counter, 48 | const cipher_aes_key_t *key, 49 | const cipher_aes_mode_t mode); 50 | 51 | /** 52 | * Implements AES-CTR update. 53 | * 54 | * 'ctx' : input/output of intermediate context IV 55 | * 'src_len': must be multiple of 16 bytes, cannot be 0. 56 | * 57 | * support In Place operation (src==dest)!!! 58 | */ 59 | sev_status_t cipher_aes_ctr_update(cipher_aes_ctr_ctx_t *ctx, 60 | const uint8_t *src, uint32_t src_len, 61 | uint8_t *dest, uint32_t *dest_len); 62 | 63 | /** 64 | * Implements AES-CTR final. 65 | * 66 | * 'ctx' : input of final IV, note: this final IV cannot be used as context IV if 67 | * src_len is not aligned to 16. 68 | * 'src_len': could be 0, or any, do not have to be multiple of 16 bytes. 69 | * 70 | * support In Place operation (src==dest)!!! 71 | */ 72 | sev_status_t cipher_aes_ctr_final(cipher_aes_ctr_ctx_t *ctx, 73 | const uint8_t *src, uint32_t src_len, 74 | uint8_t *dest, uint32_t *dest_len); 75 | 76 | #endif /* CIPHER_H */ 77 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/cipher_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef CIPHER_UTEST_H 4 | #define CIPHER_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t cipher_utest(void); 12 | 13 | #endif /* CIPHER_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/compression.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef COMPRESSION_H 4 | #define COMPRESSION_H 5 | 6 | #include 7 | #include 8 | 9 | /** 10 | * Compress into a zlib stream. 11 | * 12 | * NOTE: This will need to be implemented in firmware. the CCP does 13 | * not implement the compression side of the zlib algorithm. 14 | */ 15 | int compression_zlib_compress(const uint8_t *src, size_t src_length, 16 | uint8_t *dst, size_t *dst_legnth); 17 | 18 | /** 19 | * Decompress a zlib stream. 20 | */ 21 | int compression_zlib_decompress(const uint8_t *src, size_t src_length, 22 | uint8_t *dst, size_t *dst_legnth); 23 | 24 | #endif /* COMPRESSION_H */ 25 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/crc.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "crc.h" 7 | 8 | #define CRC32C_POLY (0x1EDC6F41ull) 9 | #define INITIAL_POLY (0xFFFFFFFFull) 10 | 11 | /* Reverses (reflects) bits in a 32-bit dword. */ 12 | static uint32_t reverse_bits(uint32_t x) 13 | { 14 | x = ((x & 0x55555555) << 1) | ((x >> 1) & 0x55555555); 15 | x = ((x & 0x33333333) << 2) | ((x >> 2) & 0x33333333); 16 | x = ((x & 0x0F0F0F0F) << 4) | ((x >> 4) & 0x0F0F0F0F); 17 | x = (x << 24) | ((x & 0xFF00) << 8) | ((x >> 8) & 0xFF00) | (x >> 24); 18 | return x; 19 | } 20 | 21 | /** 22 | * This is the basic CRC algorithm with no optimizations. It follows the 23 | * logic circuit as closely as possible and uses the Castagnoli polynomial. 24 | */ 25 | static sev_status_t crc32c(uint8_t *buffer, size_t size, uint32_t *crc32) 26 | { 27 | size_t i = 0, j = 0; 28 | uint32_t crc = INITIAL_POLY; 29 | sev_status_t status = SEV_STATUS_SUCCESS; 30 | 31 | if (!buffer || size == 0 || !crc32) 32 | { 33 | status = ERR_INVALID_PARAMS; 34 | goto end; 35 | } 36 | 37 | for (i = 0; i < size; i++) 38 | { 39 | uint32_t byte = buffer[i]; 40 | byte = reverse_bits(byte); 41 | for (j = 0; j < 8; j++) 42 | { 43 | if ((int)(crc ^ byte) < 0) 44 | crc = (crc << 1) ^ CRC32C_POLY; 45 | else 46 | crc <<= 1; 47 | byte <<= 1; 48 | } 49 | } 50 | *crc32 = reverse_bits(~crc); 51 | 52 | end: 53 | return status; 54 | } 55 | 56 | #define FIRST_ORDER_OFFSET (0) 57 | #define SECOND_ORDER_OFFSET (8) 58 | #define THIRD_ORDER_OFFSET (16) 59 | #define CRC_SKIP (24) 60 | 61 | /** 62 | * For Genoa, the calculation of checksum for the VSMA block 63 | * is to calculate based on an offset, accumulate 8 byte chunks of CRC, 64 | * then combine the 3 different CRCs. The CRC calculation is 65 | * modeled based on the CRC32 instruction. 66 | * 67 | * CRC0 - calculates CRC of bytes of offset 0-7, 24-31, etc. 68 | * CRC1 - calculates CRC of bytes of offset 8-15, 32-39, etc. 69 | * CRC2 - calculates CRC of bytes offset 16-23, 40, 47, etc. 70 | * 71 | * Any remaining bytes not multiple of (24) or CRC_SKIP is accumulated into CRC2. 72 | */ 73 | static sev_status_t crc32c_offset(uint8_t *buffer, size_t size, size_t offset, uint32_t *crc32) 74 | { 75 | uint32_t i, j, k; 76 | uint32_t crc = INITIAL_POLY; 77 | sev_status_t status = SEV_STATUS_SUCCESS; 78 | uint32_t n_blocks = 0; 79 | uint32_t remainder = 0; 80 | uint32_t offset_index = 0; 81 | 82 | if (!buffer || size == 0 || !crc32) 83 | { 84 | status = ERR_INVALID_PARAMS; 85 | goto end; 86 | } 87 | 88 | /* Size must be multiple of 8 and at least CRC_SKIP (24) bytes */ 89 | if ((size & 0x7) || (size < CRC_SKIP)) 90 | { 91 | status = ERR_INVALID_PARAMS; 92 | goto end; 93 | } 94 | 95 | if (offset != FIRST_ORDER_OFFSET && offset != SECOND_ORDER_OFFSET && 96 | offset != THIRD_ORDER_OFFSET) 97 | { 98 | status = ERR_INVALID_PARAMS; 99 | goto end; 100 | } 101 | 102 | /* Find the number of blocks of CRC_SKIP (24 bytes) to process, rounding down */ 103 | n_blocks = size / CRC_SKIP; 104 | 105 | /* Calculate CRC up to the highest multiple of CRC_SKIP (24), starting from offset value */ 106 | for (i = 0; i < n_blocks; i++) 107 | { 108 | offset_index = (i * CRC_SKIP) + offset; 109 | 110 | /* Calculate CRC for 8 bytes at a time */ 111 | for (j = offset_index; j < offset_index + 8; j++) 112 | { 113 | uint32_t byte = buffer[j]; 114 | byte = reverse_bits(byte); 115 | for (k = 0; k < 8; k++) 116 | { 117 | if ((int)(crc ^ byte) < 0) 118 | crc = (crc << 1) ^ CRC32C_POLY; 119 | else 120 | crc <<= 1; 121 | byte <<= 1; 122 | } 123 | } 124 | } 125 | 126 | remainder = size - (n_blocks * CRC_SKIP); 127 | if (remainder != 0) 128 | { 129 | if (offset == THIRD_ORDER_OFFSET) 130 | { 131 | /* 132 | * The remainder of the values goes to the third 133 | * offset calculation in multiple of 8 bytes 134 | */ 135 | for (i = n_blocks * CRC_SKIP; i < size; i += 8) 136 | { 137 | /* Calculate CRC for 8 bytes at a time */ 138 | for (j = i; j < i + 8; j++) 139 | { 140 | uint32_t byte = buffer[j]; 141 | byte = reverse_bits(byte); 142 | for (k = 0; k < 8; k++) 143 | { 144 | if ((int)(crc ^ byte) < 0) 145 | crc = (crc << 1) ^ CRC32C_POLY; 146 | else 147 | crc <<= 1; 148 | byte <<= 1; 149 | } 150 | } 151 | } 152 | } 153 | } 154 | 155 | *crc32 = reverse_bits(~crc); 156 | 157 | end: 158 | return status; 159 | } 160 | 161 | /** 162 | * Calculates CRC64 of the VMSA block 163 | * - 3 CRC calculations up to the size of the block, with starting offsets at 0, 8, and 16 164 | * and accumulates every 8 bytes. The remainder of the bytes that is not multiple of 24 165 | * goes into the 3rd CRC 166 | * - The 3 CRC results are combined together to calculate the final CRC32 value. 167 | * 168 | * Final CRC64 is [CRC0 ^ CRC1 ^ CRC2][Combined CRC] 169 | */ 170 | sev_status_t crc64_vmsa(uint8_t *buffer, size_t size, uint64_t *crc64) 171 | { 172 | sev_status_t status = SEV_STATUS_SUCCESS; 173 | uint32_t temp_crc[3] = {0}; 174 | uint32_t crc0 = 0; 175 | uint32_t crc1 = 0; 176 | uint32_t crc2 = 0; 177 | uint32_t crc32 = 0; 178 | 179 | if (size == 0 || buffer == NULL || crc64 == NULL) 180 | { 181 | status = ERR_INVALID_PARAMS; 182 | goto end; 183 | } 184 | 185 | status = crc32c_offset(buffer, size, FIRST_ORDER_OFFSET, &crc0); 186 | if (status != SEV_STATUS_SUCCESS) 187 | goto end; 188 | temp_crc[0] = crc0; 189 | 190 | status = crc32c_offset(buffer, size, SECOND_ORDER_OFFSET, &crc1); 191 | if (status != SEV_STATUS_SUCCESS) 192 | goto end; 193 | temp_crc[1] = crc1; 194 | 195 | status = crc32c_offset(buffer, size, THIRD_ORDER_OFFSET, &crc2); 196 | if (status != SEV_STATUS_SUCCESS) 197 | goto end; 198 | temp_crc[2] = crc2; 199 | 200 | /* Calculate the combined CRC */ 201 | status = crc32c((uint8_t *)temp_crc, sizeof(temp_crc), &crc32); 202 | if (status != SEV_STATUS_SUCCESS) 203 | goto end; 204 | 205 | /* Get upper 32 bits, CRC0 ^ CRC1 ^ CRC2 */ 206 | *crc64 = (uint64_t)(crc0 ^ crc1 ^ crc2) << 32ULL; 207 | 208 | *crc64 |= (uint64_t)crc32; 209 | 210 | end: 211 | return status; 212 | } 213 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/crc.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_UAPP_CRC_H 4 | #define SEV_UAPP_CRC_H 5 | 6 | #include "sev_status.h" 7 | 8 | /** 9 | * Calculate the 64-bit CRC of the input buffer 10 | */ 11 | sev_status_t crc64_vmsa(uint8_t *buffer, size_t size, uint64_t *crc64); 12 | 13 | #endif /* SEV_UAPP_CRC_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/df_regs_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "df_regs.h" 7 | #include "df_regs_utest.h" 8 | 9 | /** 10 | * D18F0x040 [Fabric Block Instance Count] (DF::FabricBlockInstanceCount) 11 | * FabricBlockInstanceCount is a read-only register, so it's value 12 | * will never change from the reset value. 13 | */ 14 | #define FABRIC_BLOCK_INSTANCE_COUNT_FUNC (0) 15 | #define FABRIC_BLOCK_INSTANCE_COUNT_OFFSET (0x40) 16 | #define FABRIC_BLOCK_INSTANCE_COUNT (0x61) /* Reset value (Genoa only) */ 17 | #define FABRIC_BLOCK_INSTANCE_COUNT_MASK (0xFF) 18 | 19 | /** 20 | * D18F6x380...D18F6x3FC [Scratch Register Area] (DF::ScratchRegister) 21 | * A block of 32 scratch registers are implemented for use by BIOS, 22 | * x86 microcode, PSP or SMU. We will use these to safely test register writes. 23 | */ 24 | #define SCRATCH_REGISTER_AREA_FUNC (3) 25 | #define SCRATCH_REGISTER_AREA_OFFSET (0xE00) 26 | #define SCRATCH_REGISTER_VALUE (0xdeadbeef) 27 | 28 | bool df_test_read32(void) 29 | { 30 | uint32_t function = FABRIC_BLOCK_INSTANCE_COUNT_FUNC; 31 | uint32_t offset = FABRIC_BLOCK_INSTANCE_COUNT_OFFSET; 32 | uint32_t value = 0; 33 | 34 | read_df_reg32(PIE_INSTANCE_ID, function, offset, &value); 35 | 36 | return (value & FABRIC_BLOCK_INSTANCE_COUNT_MASK) == FABRIC_BLOCK_INSTANCE_COUNT; 37 | } 38 | 39 | bool df_test_read_bcast32(void) 40 | { 41 | uint32_t function = FABRIC_BLOCK_INSTANCE_COUNT_FUNC; 42 | uint32_t offset = FABRIC_BLOCK_INSTANCE_COUNT_OFFSET; 43 | uint32_t value = 0; 44 | 45 | read_df_reg_bcast32(function, offset, &value); 46 | 47 | return (value & FABRIC_BLOCK_INSTANCE_COUNT_MASK) == FABRIC_BLOCK_INSTANCE_COUNT; 48 | } 49 | 50 | bool df_test_write32(void) 51 | { 52 | /* 53 | * In case the register addressing code is incorrect, write to a register 54 | * in the middle of the bank. This way, if we write to the wrong register, 55 | * there is less likelihood that we will clobber something important. 56 | */ 57 | uint32_t offset = SCRATCH_REGISTER_AREA_OFFSET + 16*sizeof(uint32_t); 58 | uint32_t function = SCRATCH_REGISTER_AREA_FUNC; 59 | uint32_t value = SCRATCH_REGISTER_VALUE; 60 | 61 | write_df_reg32(PIE_INSTANCE_ID, function, offset, value); 62 | read_df_reg32(PIE_INSTANCE_ID, function, offset, &value); 63 | 64 | return value == SCRATCH_REGISTER_VALUE; 65 | } 66 | 67 | bool df_test_write_bcast32(void) 68 | { 69 | /* 70 | * In case the register addressing code is incorrect, write to a register 71 | * in the middle of the bank. This way, if we write to the wrong register, 72 | * there is less likelihood that we will clobber something important. 73 | */ 74 | uint32_t offset = SCRATCH_REGISTER_AREA_OFFSET + 16*sizeof(uint32_t); 75 | uint32_t function = SCRATCH_REGISTER_AREA_FUNC; 76 | uint32_t value = SCRATCH_REGISTER_VALUE; 77 | 78 | write_df_reg_bcast32(function, offset, value); 79 | read_df_reg_bcast32(function, offset, &value); 80 | 81 | return value == SCRATCH_REGISTER_VALUE; 82 | } 83 | 84 | static bool (* const test_table[])(void) = { 85 | [0] = df_test_read32, 86 | [1] = df_test_read_bcast32, 87 | [2] = df_test_write32, 88 | [3] = df_test_write_bcast32, 89 | }; 90 | 91 | void df_utest(size_t *nr_tests, size_t *nr_passed) 92 | { 93 | size_t i = 0; 94 | size_t passed = 0; 95 | size_t tests = sizeof(test_table)/sizeof(test_table[0]); 96 | sev_status_t status = SEV_STATUS_SUCCESS; 97 | 98 | if (!nr_tests || !nr_passed) 99 | goto end; 100 | 101 | status = df_access_lock(); 102 | if (status != SEV_STATUS_SUCCESS) 103 | goto end; 104 | 105 | for (i = 0; i < tests; i++) 106 | { 107 | /* Run the test */ 108 | passed += test_table[i](); 109 | } 110 | *nr_tests = tests; 111 | *nr_passed = passed; 112 | 113 | df_access_unlock(); 114 | 115 | end: 116 | return; 117 | } 118 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/df_regs_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef DF_REGS_UTEST_H 4 | #define DF_REGS_UTEST_H 5 | 6 | void df_utest(uint32_t *nr_tests, uint32_t *nr_passed); 7 | 8 | #endif /* DF_REGS_UTEST_H */ 9 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/digest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef DIGEST_H 4 | #define DIGEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "bl_syscall.h" 10 | #include "sev_errors.h" 11 | 12 | #define DIGEST_SHA256_SIZE_BYTES (32) 13 | #define SHA256_BLOCK_SIZE_BYTES (64) 14 | #define SHA256_HASH_WORDS (8) 15 | 16 | #define DIGEST_SHA384_SIZE_BYTES (48) 17 | #define SHA384_BLOCK_SIZE_BYTES (128) 18 | #define SHA384_HASH_WORDS (16) 19 | 20 | #define DIGEST_SHA512_SIZE_BYTES (64) 21 | #define SHA512_BLOCK_SIZE_BYTES (128) 22 | #define SHA512_HASH_WORDS (16) 23 | 24 | /* Set this to be the largest size of the SHA expected */ 25 | #define DIGEST_SHA_SIZE_BYTES (DIGEST_SHA384_SIZE_BYTES) 26 | #define SHA_BLOCK_SIZE_BYTES (SHA384_BLOCK_SIZE_BYTES) 27 | 28 | /* For SHA 384 the DIGEST has to be stored with 64 bytes */ 29 | #define DIGEST_STORAGE_BYTES (64) 30 | #define SHA_HASH_WORDS (DIGEST_STORAGE_BYTES / 4) 31 | 32 | typedef struct digest_sha 33 | { 34 | uint8_t digest[DIGEST_STORAGE_BYTES]; 35 | } digest_sha_t; 36 | 37 | typedef uint32_t digest_crc32_t; 38 | typedef uint32_t digest_crc32_ctx_t; 39 | 40 | /** 41 | * Note: If this structure is used in PSP reserved DRAM, msg_block[] minimum 42 | * alignment must be 16 bytes if used with CCP. Since the sizeof h[] is a 43 | * multiple of 16 bytes, aligning the structure is sufficient. Don't swap 44 | * msg_block[] and h[]: there is an order dependency. 45 | * If used in SRAM, 4 byte minimum alignment is sufficient, so the 16-byte 46 | * alignment is not imposed here. 47 | */ 48 | typedef struct digest_sha_ctx 49 | { 50 | union 51 | { 52 | digest_sha_t d; 53 | uint32_t words[SHA_HASH_WORDS]; 54 | } h; 55 | uint8_t msg_block[SHA_BLOCK_SIZE_BYTES]; 56 | size_t bytes_used; 57 | uint32_t length; 58 | SHA_TYPE sha_type; 59 | } digest_sha_ctx_t; 60 | 61 | /** 62 | * Initializes the digest context. 63 | * 64 | * Caller must be responsible for donating context memory! 65 | * 66 | * Interweaving call is supported! 67 | * 68 | * For each digest_* call, low-level crypto resource is allocated 69 | * and release upon completion as one-shot business! 70 | */ 71 | sev_status_t digest_sha_init(digest_sha_ctx_t *ctx, SHA_TYPE sha_type); 72 | 73 | /** 74 | * Updates the context with the given data. 75 | * 76 | * 'data' : data buffer to hash. 77 | * 'length': length of the input data. 78 | * 79 | */ 80 | sev_status_t digest_sha_update(digest_sha_ctx_t *ctx, const void *data, 81 | size_t length); 82 | 83 | /** 84 | * Updates the context with the padding and calculates the final digest. 85 | * 86 | * digest : output buffer for the final digest. 87 | * digest_len: length of the output buffer. 88 | */ 89 | sev_status_t digest_sha_final(digest_sha_ctx_t *ctx, digest_sha_t *digest, 90 | size_t *digest_len); 91 | 92 | /** 93 | * Calculate the complete SHA256 digest of the input message. 94 | * 95 | * msg : message buffer to hash. 96 | * msg_len : length of the input message. 97 | * digest : output buffer for the final digest. 98 | * digest_len: length of the output buffer. 99 | */ 100 | sev_status_t digest_sha(const void *msg, size_t msg_len, 101 | digest_sha_t *digest, size_t *digest_len, 102 | SHA_TYPE sha_type); 103 | 104 | /** 105 | * Retrieve the digest bytes from the context 106 | * Returns the h param in digest_sha_ctx_t 107 | */ 108 | static inline digest_sha_t *sha_ctx_to_digest(digest_sha_ctx_t *ctx) 109 | { 110 | return (digest_sha_t *)ctx; 111 | } 112 | 113 | #endif /* DIGEST_H */ 114 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/digest_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef DIGEST_UTEST_H 4 | #define DIGEST_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t digest_utest(void); 12 | 13 | #endif /* DIGEST_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecc.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_ECC_H 4 | #define SEV_ECC_H 5 | 6 | #include 7 | 8 | #include "sev_errors.h" 9 | #include "sev_svc.h" 10 | 11 | #define ECC_CURVE_SECP256R1_SIZE_BYTES 32 12 | #define ECC_CURVE_SECP256R1_SIZE_BITS 256 13 | #define ECC_CURVE_SECP384R1_SIZE_BYTES 48 14 | #define ECC_CURVE_SECP384R1_SIZE_BITS 384 15 | 16 | // SEV supported ECC curve size 17 | #define SEV_ECC_CURVE_SIZE_BYTES ECC_CURVE_SECP384R1_SIZE_BYTES 18 | 19 | /** 20 | * For ECC keys generated from extra bits, FIPS 180-4 requires that the 21 | * input contain an additional 64 bits (8 bytes) of random data. 22 | */ 23 | #define ECC_KEYGEN_EXTRA_BITS (64) 24 | #define ECC_KEYGEN_EXTRA_BYTES (8) 25 | 26 | // All ECC data must be in little-endian 27 | // CCP5.0 ECC engine support prime curves up to 521 bits, Binary curves up to 571 bits 28 | #define ECC_SCALAR_SIZE_BYTES 72 29 | 30 | typedef enum ecc_curve_name 31 | { 32 | ECC_CURVE_NAME_INVALID = 0, 33 | ECC_CURVE_NAME_SECP256K1 = 1, 34 | ECC_CURVE_NAME_SECP384R1 = 2, 35 | } ecc_curve_name_t; 36 | 37 | typedef uint8_t ecc_int_t[ECC_SCALAR_SIZE_BYTES]; 38 | 39 | /** 40 | * in the prime case, the domain parameters are (p,a,b,G,n,h); 41 | * in the binary case, they are (m,f,a,b,G,n,h). 42 | */ 43 | typedef struct ecc_curve 44 | { 45 | ecc_curve_name_t name; 46 | ecc_scalar_t p; /* Prime, the field is defined by p in the prime case. Field size q=p (odd prime), or q = 2^m for binary case */ 47 | ecc_scalar_t a; /* Curve coefficient (i.e. y^2 = x^3 + ax + b) */ 48 | ecc_scalar_t b; /* Curve coefficient (i.e. y^2 = x^3 + ax + b) */ 49 | ecc_point_t G; /* Base point */ 50 | ecc_scalar_t n; /* The order of base point */ 51 | ecc_scalar_t h; /* Cofactor */ 52 | } ecc_curve_t; 53 | 54 | typedef struct ecc_keypair 55 | { 56 | ecc_curve_name_t curve; 57 | ecc_point_t Q; /* Public key */ 58 | ecc_scalar_t d; /* Private key, Q=d*G */ 59 | } ecc_keypair_t; 60 | 61 | typedef struct ecc_pubkey 62 | { 63 | ecc_curve_name_t curve; 64 | ecc_point_t Q; 65 | } ecc_pubkey_t; 66 | 67 | const ecc_curve_t *ecc_get_curve(size_t id); 68 | sev_status_t ecc_get_pubkey(const ecc_keypair_t *keypair, ecc_pubkey_t *pubkey); 69 | bool ecc_pubkey_is_valid(const ecc_pubkey_t *pubkey); 70 | 71 | /** 72 | * Initialize the scalar using 'size' bytes copied from 'buffer'. The scalar 73 | * is formatted properly for use by the CCP. 74 | */ 75 | sev_status_t ecc_scalar_init(ecc_scalar_t *scalar, const uint8_t *buffer, 76 | size_t size); 77 | bool ecc_scalar_is_greater(const ecc_scalar_t *a, const ecc_scalar_t *b); 78 | bool ecc_scalar_is_zero(const ecc_scalar_t *rop); 79 | sev_status_t ecc_scalar_minus(ecc_scalar_t *rop, const ecc_scalar_t *op1, 80 | const ecc_scalar_t *op2); 81 | 82 | sev_status_t ecc_scalar_add(ecc_scalar_t *rop, const ecc_scalar_t *op1, 83 | const ecc_scalar_t *op2, const ecc_scalar_t *modulus); 84 | 85 | sev_status_t ecc_scalar_mod(ecc_scalar_t *rop, const ecc_scalar_t *op1, 86 | const ecc_scalar_t *modulus); 87 | sev_status_t ecc_scalar_reduce(ecc_scalar_t *rop, const ecc_scalar_t *op1, 88 | const ecc_scalar_t *modulus); 89 | 90 | sev_status_t ecc_scalar_mul(ecc_scalar_t *rop, const ecc_scalar_t *op1, 91 | const ecc_scalar_t *op2, const ecc_scalar_t *modulus); 92 | 93 | sev_status_t ecc_scalar_inv(ecc_scalar_t *rop, const ecc_scalar_t *op1, 94 | const ecc_scalar_t *modulus); 95 | 96 | sev_status_t ecc_point_add(ecc_point_t *rop, const ecc_point_t *op1, 97 | const ecc_point_t *op2, ecc_curve_name_t curve_id); 98 | 99 | sev_status_t ecc_point_double(ecc_point_t *rop, const ecc_point_t *op1, 100 | ecc_curve_name_t curve_id); 101 | 102 | sev_status_t ecc_point_scale(ecc_point_t *rop, const ecc_point_t *op1, 103 | const ecc_scalar_t *k, ecc_curve_name_t curve_id); 104 | 105 | sev_status_t ecc_point_linear(ecc_point_t *rop, const ecc_point_t *op1, 106 | const ecc_scalar_t *k, const ecc_point_t *op2, 107 | const ecc_scalar_t *h, ecc_curve_name_t curve_id); 108 | 109 | /** 110 | * Key pair generation following NIST-FIPS-186-4.pdf section B.4.2: 111 | * 112 | * Key pair generation by: 113 | * 1. extra random bits, 114 | * 2. testing candidates. 115 | */ 116 | sev_status_t ecc_keypair_generate_rdata(ecc_keypair_t *keypair, 117 | ecc_curve_name_t curve_id, 118 | const uint8_t *rdata, size_t length); 119 | 120 | sev_status_t ecc_keypair_from_extra_bits(ecc_keypair_t *keypair, 121 | ecc_curve_name_t curve_id, 122 | const uint8_t *rdata, size_t length); 123 | 124 | sev_status_t ecc_keypair_from_candidates(ecc_keypair_t *keypair, 125 | ecc_curve_name_t curve_id, 126 | const uint8_t *rdata, size_t length); 127 | 128 | #endif /* SEV_ECC_H */ 129 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecc_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "ecc.h" 9 | #include "ecc_utest.h" 10 | 11 | static bool ecc_scalar_subtract_utest(void) 12 | { 13 | bool result = true; 14 | ecc_scalar_t left; 15 | ecc_scalar_t right; 16 | ecc_scalar_t diff; 17 | ecc_scalar_t expected; 18 | sev_status_t status = SEV_STATUS_SUCCESS; 19 | 20 | memset(&left, 0, sizeof(left)); 21 | memset(&right, 0, sizeof(right)); 22 | memset(&diff, 0, sizeof(diff)); 23 | memset(&expected, 0, sizeof(expected)); 24 | 25 | /* left = 0x530003 */ 26 | left.s[0] = 0x03; 27 | left.s[1] = 0x00; 28 | left.s[2] = 0x53; 29 | 30 | /* right = 0x353535 */ 31 | right.s[0] = 0x35; 32 | right.s[1] = 0x35; 33 | right.s[2] = 0x35; 34 | 35 | /* expected = 0x1DCACE */ 36 | expected.s[0] = 0xCE; 37 | expected.s[1] = 0xCA; 38 | expected.s[2] = 0x1D; 39 | 40 | /* diff = left - right = 0x1DCACE */ 41 | status = ecc_scalar_minus(&diff, &left, &right); 42 | if (status != SEV_STATUS_SUCCESS || memcmp(&diff, &expected, sizeof(diff)) != 0) 43 | result = false; 44 | 45 | return result; 46 | } 47 | 48 | bool ecc_scalar_mul_utest(void) 49 | { 50 | sev_status_t status = SEV_STATUS_SUCCESS; 51 | ecc_scalar_t one; 52 | ecc_scalar_t product; 53 | const ecc_curve_t *curve = ecc_get_curve(ECC_CURVE_NAME_SECP384R1); 54 | 55 | memset(&product, 0, sizeof(product)); 56 | memset(&one, 0, sizeof(one)); 57 | one.s[0] = 1; 58 | 59 | status = ecc_scalar_mul(&product, &one, &curve->G.x, &curve->n); 60 | if (status != SEV_STATUS_SUCCESS) 61 | goto end; 62 | 63 | if (memcmp(&product, &curve->G.x, sizeof(product)) != 0) 64 | status = ERR_UNKNOWN; 65 | 66 | end: 67 | return status == SEV_STATUS_SUCCESS ? true : false; 68 | } 69 | 70 | sev_status_t ecc_utest(void) 71 | { 72 | bool result = true; 73 | 74 | result = ecc_scalar_subtract_utest(); 75 | if (!result) 76 | goto end; 77 | 78 | result = ecc_scalar_mul_utest(); 79 | 80 | end: 81 | return result ? SEV_STATUS_SUCCESS : ERR_UNKNOWN; 82 | } 83 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecc_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ECC_UTEST_H 4 | #define ECC_UTEST_H 5 | 6 | #include "sev_errors.h" 7 | 8 | sev_status_t ecc_utest(void); 9 | 10 | #endif /* ECC_UTEST_H */ 11 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdh.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ecc.h" 8 | #include "ecdh.h" 9 | #include "helper.h" 10 | #include "secure_ops.h" 11 | #include "sev_hal.h" 12 | 13 | sev_status_t ecdh_keypair_generate(ecc_keypair_t *keypair) 14 | { 15 | sev_status_t status = SEV_STATUS_SUCCESS; 16 | uint8_t random[SEV_ECC_CURVE_SIZE_BYTES]; // P384, 48 bytes. 17 | 18 | if (!keypair) 19 | { 20 | status = ERR_INVALID_PARAMS; 21 | goto end; 22 | } 23 | 24 | do 25 | { 26 | status = sev_hal_trng(random, sizeof(random)); 27 | if (status != SEV_STATUS_SUCCESS) 28 | { 29 | break; 30 | } 31 | 32 | status = ecc_keypair_generate_rdata(keypair, ECC_CURVE_NAME_SECP384R1, random, sizeof(random)); 33 | if (status == ERR_INVALID_PARAMS) 34 | { 35 | // re-pick the random 36 | continue; 37 | } 38 | else 39 | { 40 | break; 41 | } 42 | 43 | } while (1); 44 | 45 | end: 46 | secure_memzero(random, sizeof(random)); 47 | return status; 48 | } 49 | 50 | sev_status_t ecdh_key_agreement(const ecc_keypair_t *lkeypair, 51 | const ecc_pubkey_t *rpubkey, 52 | uint8_t *secret, size_t length) 53 | { 54 | sev_status_t status = SEV_STATUS_SUCCESS; 55 | ecc_point_t result; 56 | 57 | if (!lkeypair || !rpubkey || !secret || length < ECC_CURVE_SECP384R1_SIZE_BYTES) 58 | { 59 | status = ERR_INVALID_PARAMS; 60 | goto end; 61 | } 62 | 63 | /* Validate the pubkey (from x86) before using */ 64 | /* Make sure the pubkey and keypair both specify the same curve */ 65 | if (!ecc_pubkey_is_valid(rpubkey) || rpubkey->curve != lkeypair->curve) 66 | { 67 | status = SEV_STATUS_INVALID_CERTIFICATE; 68 | goto end; 69 | } 70 | 71 | /* Calculate h*d*Q, since h is always 1 for P384, we only need to calculate d*Q */ 72 | status = ecc_point_scale(&result, &rpubkey->Q, &lkeypair->d, lkeypair->curve); 73 | if (status != SEV_STATUS_SUCCESS) 74 | { 75 | /* Checking if the result is infinity point has been done implicitly by CCP; 76 | * if the Point at Infinity is an output, an error-code will be returned. */ 77 | goto end; 78 | } 79 | 80 | /* CCP output is big-endian, so we need to reverse the bytes */ 81 | status = reverse_bytes(result.x.s, ECC_CURVE_SECP384R1_SIZE_BYTES); 82 | if (status != SEV_STATUS_SUCCESS) 83 | goto end; 84 | 85 | memcpy(secret, result.x.s, ECC_CURVE_SECP384R1_SIZE_BYTES); 86 | 87 | end: 88 | return status; 89 | } 90 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdh.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ECDH_H 4 | #define ECDH_H 5 | 6 | #include 7 | #include 8 | 9 | #include "ecc.h" 10 | #include "sev_errors.h" 11 | 12 | /** 13 | * Generate a key pair with the RNG HAL. 14 | */ 15 | sev_status_t ecdh_keypair_generate(ecc_keypair_t *keypair); 16 | 17 | /** 18 | * Compute the shared secret with the ECDH key material. 19 | */ 20 | sev_status_t ecdh_key_agreement(const ecc_keypair_t *lkeypair, 21 | const ecc_pubkey_t *rpubkey, 22 | uint8_t *secret, size_t length); 23 | 24 | #endif /* ECDH_H */ 25 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdh_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ecc.h" 8 | #include "ecdh.h" 9 | #include "ecdh_utest.h" 10 | #include "sev_trace.h" 11 | 12 | sev_status_t ecdh_utest(void) 13 | { 14 | sev_status_t status = SEV_STATUS_SUCCESS; 15 | 16 | ecc_keypair_t lkeypair; 17 | ecc_keypair_t rkeypair; 18 | uint8_t lsecret[SEV_ECC_CURVE_SIZE_BYTES]; 19 | uint8_t rsecret[SEV_ECC_CURVE_SIZE_BYTES]; 20 | 21 | status = ecdh_keypair_generate(&lkeypair); 22 | if (status != SEV_STATUS_SUCCESS) 23 | { 24 | goto end; 25 | } 26 | 27 | status = ecdh_keypair_generate(&rkeypair); 28 | if (status != SEV_STATUS_SUCCESS) 29 | { 30 | goto end; 31 | } 32 | 33 | status = ecdh_key_agreement(&lkeypair, (ecc_pubkey_t *)&rkeypair, lsecret, sizeof(lsecret)); 34 | if (status != SEV_STATUS_SUCCESS) 35 | { 36 | goto end; 37 | } 38 | 39 | status = ecdh_key_agreement(&rkeypair, (ecc_pubkey_t *)&lkeypair, rsecret, sizeof(rsecret)); 40 | if (status != SEV_STATUS_SUCCESS) 41 | { 42 | goto end; 43 | } 44 | 45 | // validate the result 46 | if (memcmp(lsecret, rsecret, sizeof(lsecret)) != 0) 47 | { 48 | status = ERR_UNKNOWN; 49 | } 50 | 51 | end: 52 | if (status != SEV_STATUS_SUCCESS) 53 | { 54 | SEV_TRACE("ecdh_utest failed...\n"); 55 | SEV_TRACE_EX(status, 0, 0, 0); 56 | } 57 | else 58 | { 59 | SEV_TRACE("ecdh_utest succeed!\n"); 60 | } 61 | 62 | return status; 63 | } 64 | 65 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdh_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ECDH_UTEST_H 4 | #define ECDH_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t ecdh_utest(void); 12 | 13 | #endif /* ECDH_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdsa.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ECDSA_H 4 | #define ECDSA_H 5 | 6 | #include 7 | #include 8 | 9 | #include "ecc.h" 10 | #include "sev_errors.h" 11 | 12 | typedef struct ecdsa_sig 13 | { 14 | ecc_scalar_t r; 15 | ecc_scalar_t s; 16 | } ecdsa_sig_t; 17 | 18 | /** 19 | * Generates a new key pair using the RNG HAL. 20 | * 21 | * This function generate enough random data using the RNG and then 22 | * calls 'ecc_keypair_generate_rdata()'. 23 | * 24 | * \param [out] keypair generated keypair 25 | */ 26 | sev_status_t ecdsa_keypair_generate(ecc_keypair_t *keypair); 27 | 28 | /** 29 | * Copies the public key out of the 'keypair' object into the 'pubkey' 30 | * object. 31 | * 32 | * We do this so the higher level code never has to unwrap and access 33 | * the raw data of the keypair (and accidentally copying out the wrong 34 | * part of the keypair). 35 | */ 36 | sev_status_t ecdsa_export_pubkey(ecc_pubkey_t *pubkey, const ecc_keypair_t *keypair); 37 | 38 | /** 39 | Sign the digest of a message using the random data provided in 40 | 'rdata'. 41 | 42 | This function _does not_ calculate the hash of the message. It is 43 | up to the caller to calculate the digest. 44 | 45 | \warning Passing the actual message and not the digest into this 46 | function will result in an incorrect signature and will likely lead 47 | to vulnerabilities. 48 | 49 | The signing algorithm is specified by FIPS 186-4, section 50 | 6.4. However, very annoyingly, this section only refers to the ANSI 51 | X9.62 standard, which is not immediately available. Therefore, 52 | we'll assume that [RFC 6979][1] matches X9.62 exactly. 53 | 54 | [1]: https://tools.ietf.org/html/rfc6979 55 | 56 | The algorithm is reproduced here with edits. 57 | 58 | 'rdata' is transformed into an integer modulo 'n' using the 59 | 'bits2int' (see [RFC 6979][1] for further details) transform and an 60 | extra modular reduction: 61 | 62 | ~~~ 63 | h = bits2int(H(m)) mod q 64 | ~~~ 65 | 66 | A random value modulo 'n', dubbed 'k', is generated. That value shall 67 | not be '0'; hence, it lies in the ['1', 'q-1'] range. 68 | 69 | A value 'r' (modulo 'n') is computed from 'k' and the key 70 | parameters. The point 'kG' is computed; its X coordinate (a member 71 | of the field over which the curve is defined) is converted to an 72 | integer, which is reduced modulo 'n', yielding 'r'. 73 | 74 | If 'r' turns out to be zero, the function returns an error. This 75 | should _never_ happen with secure random data, but we must check in 76 | case we're running tests with degenerate data. 77 | 78 | The value 's' (modulo 'n') is computed: 79 | 80 | ~~~ 81 | s = (h+x*r) * (h^(-1)) mod q 82 | ~~~ 83 | 84 | The pair (r, s) is the signature. 85 | 86 | \param [in] keypair the signing key pair 87 | \param [out] sig the generated signature 88 | \param [in] digest the digest of the message 89 | \param [in] length the length of 'digest' in bytes 90 | \param [in] rdata secure random data 91 | \param [in] rlength length of 'rdata' in bytes 92 | */ 93 | sev_status_t ecdsa_sign_rdata(ecdsa_sig_t *sig, const ecc_keypair_t *keypair, 94 | const uint8_t *digest, size_t length, 95 | const uint8_t *rdata, size_t rlength); 96 | 97 | /** 98 | * Sign the digest of a message using RNG HAL. 99 | * 100 | * This function generate enough random data using the RNG and then 101 | * calls 'ecdsa_keypair_sign_rdata()'. 102 | * 103 | * \see 'ecdsa_keypair_sign_rdata()' 104 | * 105 | * \param [out] sig the generated signature 106 | * \param [in] keypair the signing key pair 107 | * \param [in] digest the digest of the message 108 | * \param [in] length the length of 'digest' in bytes 109 | */ 110 | sev_status_t ecdsa_sign(ecdsa_sig_t *sig, const ecc_keypair_t *keypair, 111 | const uint8_t *digest, size_t length); 112 | 113 | /** 114 | * Sign a message using ECC DSA. 115 | * 116 | * This function generates a random 'k' and then 117 | * calls 'ecdsa_keypair_sign_rdata()'. 118 | * 119 | * \see 'ecdsa_keypair_sign_rdata()' 120 | * 121 | * \param [out] sig the generated signature 122 | * \param [in] keypair the signing key pair 123 | * \param [in] msg the message 124 | * \param [in] length the length of 'msg' in bytes 125 | * \param [in] algo the algorithm type 126 | */ 127 | sev_status_t ecdsa_sign_msg(ecdsa_sig_t *sig, const ecc_keypair_t *keypair, 128 | const uint8_t *msg, size_t length, const uint32_t algo); 129 | 130 | /** 131 | * Verifies the signature on a digest. 132 | * 133 | * Note that this function does __not__ take the message itself 134 | * as a parameter. It is up to the caller to generate the correct 135 | * digest (probably SHA-256) and provide it. 136 | * 137 | */ 138 | sev_status_t ecdsa_verify(const ecdsa_sig_t *sig, const ecc_pubkey_t *pubkey, 139 | const uint8_t *digest, size_t length); 140 | 141 | /** 142 | * Verifies the signature on a digest. 143 | * 144 | * Note that this function does __not__ take the message itself 145 | * as a parameter. It is up to the caller to generate the correct 146 | * digest (probably SHA-256) and provide it. 147 | * 148 | */ 149 | sev_status_t ecdsa_verify_msg(const ecdsa_sig_t *sig, const ecc_pubkey_t *pubkey, 150 | const uint8_t *msg, size_t length, const uint32_t algo); 151 | 152 | #endif /* ECDSA_H */ 153 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdsa_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "ecc.h" 8 | #include "ecdsa.h" 9 | #include "ecdsa_utest.h" 10 | #include "sev_hal.h" 11 | #include "sev_trace.h" 12 | 13 | #define ECDSA_TEST_STRESS_COUNT 1000 14 | 15 | /* 16 | Reference: 17 | NIST FIPS-186-4: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf 18 | 19 | Test Vector Source: 20 | 21 | https://www.iad.gov/iad/library/ia-guidance/ia-solutions-for-classified/algorithm-guidance/suite-b-implementers-guide-to-fips-186-3-ecdsa.cfm 22 | Suite B Implementer's Guide to FIPS 186-3 (ECDSA), section: D.2 Example ECDSA Signature for P-384 23 | 24 | More test vectors can be found at: 25 | Source: http://csrc.nist.gov/groups/STM/cavp/digital-signatures.html 26 | http://csrc.nist.gov/groups/STM/cavp/documents/dss/186-3ecdsatestvectors.zip 27 | 28 | The private key d: 29 | d = c838b852 53ef8dc7 394fa580 8a518398 1c7deef5 a69ba8f4 30 | f2117ffe a39cfcd9 0e95f6cb c854abac ab701d50 c1f3cf24 31 | 32 | The public key Q = dG = (xQ, yQ): 33 | xQ = 1fbac8ee bd0cbf35 640b39ef e0808dd7 74debff2 0a2a329e 34 | 91713baf 7d7f3c3e 81546d88 3730bee7 e48678f8 57b02ca0 35 | 36 | yQ = eb213103 bd68ce34 3365a8a4 c3d4555f a385f533 0203bdd7 37 | 6ffad1f3 affb9575 1c132007 e1b24035 3cb0a4cf 1693bdf9 38 | 39 | k = dc6b4403 6989a196 e39d1cda c000812f 4bdd8b2d b41bb33a 40 | f5137258 5ebd1db6 3f0ce827 5aa1fd45 e2d2a735 f8749359 41 | 42 | Message M='This is only a test message. It is 48 bytes long'. H = Hash(M): 43 | 44 | H = b9210c9d 7e20897a b8659726 6a9d5077 e8db1b06 f7220ed6 45 | ee75bd8b 45db3789 1f8ba555 03040041 59f4453d c5b3f5a1 46 | 47 | r = a0c27ec8 93092dea 1e1bd2cc fed3cf94 5c8134ed 0c9f8131 48 | 1a0f4a05 942db8db ed8dd59f 267471d5 462aa14f e72de856 49 | 50 | s = 20ab3f45 b74f10b6 e11f96a2 c8eb694d 206b9dda 86d3c7e3 51 | 31c26b22 c987b753 77265776 67adadf1 68ebbe80 3794a402 52 | 53 | The signature on the message M is the pair (r, s). 54 | */ 55 | static ecc_keypair_t test_keypair = 56 | { 57 | .curve = ECC_CURVE_NAME_SECP384R1, 58 | 59 | .Q ={{{0xa0, 0x2c, 0xb0, 0x57, 0xf8, 0x78, 0x86, 0xe4, 0xe7, 0xbe, 0x30, 0x37, 0x88, 0x6d, 0x54, 0x81, 60 | 0x3e, 0x3c, 0x7f, 0x7d, 0xaf, 0x3b, 0x71, 0x91, 0x9e, 0x32, 0x2a, 0x0a, 0xf2, 0xbf, 0xde, 0x74, 61 | 0xd7, 0x8d, 0x80, 0xe0, 0xef, 0x39, 0x0b, 0x64, 0x35, 0xbf, 0x0c, 0xbd, 0xee, 0xc8, 0xba, 0x1f,}}, 62 | 63 | {{0xf9, 0xbd, 0x93, 0x16, 0xcf, 0xa4, 0xb0, 0x3c, 0x35, 0x40, 0xb2, 0xe1, 0x07, 0x20, 0x13, 0x1c, 64 | 0x75, 0x95, 0xfb, 0xaf, 0xf3, 0xd1, 0xfa, 0x6f, 0xd7, 0xbd, 0x03, 0x02, 0x33, 0xf5, 0x85, 0xa3, 65 | 0x5f, 0x55, 0xd4, 0xc3, 0xa4, 0xa8, 0x65, 0x33, 0x34, 0xce, 0x68, 0xbd, 0x03, 0x31, 0x21, 0xeb,}}}, 66 | 67 | .d ={{ 0x24, 0xCF, 0xF3, 0xC1, 0x50, 0x1D, 0x70, 0xAB, 0xAC, 0xAB, 0x54, 0xC8, 0xCB, 0xF6, 0x95, 0x0E, 68 | 0xD9, 0xFC, 0x9C, 0xA3, 0xFE, 0x7F, 0x11, 0xF2, 0xF4, 0xA8, 0x9B, 0xA6, 0xF5, 0xEE, 0x7D, 0x1C, 69 | 0x98, 0x83, 0x51, 0x8A, 0x80, 0xA5, 0x4F, 0x39, 0xC7, 0x8D, 0xEF, 0x53, 0x52, 0xB8, 0x38, 0xC8, }}, 70 | }; 71 | 72 | static uint8_t test_digest[48] = 73 | { 74 | 0xb9, 0x21, 0x0c, 0x9d, 0x7e, 0x20, 0x89, 0x7a, 0xb8, 0x65, 0x97, 0x26, 0x6a, 0x9d, 0x50, 0x77, 75 | 0xe8, 0xdb, 0x1b, 0x06, 0xf7, 0x22, 0x0e, 0xd6, 0xee, 0x75, 0xbd, 0x8b, 0x45, 0xdb, 0x37, 0x89, 76 | 0x1f, 0x8b, 0xa5, 0x55, 0x03, 0x04, 0x00, 0x41, 0x59, 0xf4, 0x45, 0x3d, 0xc5, 0xb3, 0xf5, 0xa1, 77 | }; 78 | 79 | static ecdsa_sig_t test_sig = 80 | { 81 | .r ={{ 0x56, 0xE8, 0x2D, 0xE7, 0x4F, 0xA1, 0x2A, 0x46, 0xD5, 0x71, 0x74, 0x26, 0x9F, 0xD5, 0x8D, 0xED, 82 | 0xDB, 0xB8, 0x2D, 0x94, 0x05, 0x4A, 0x0F, 0x1A, 0x31, 0x81, 0x9F, 0x0C, 0xED, 0x34, 0x81, 0x5C, 83 | 0x94, 0xCF, 0xD3, 0xFE, 0xCC, 0xD2, 0x1B, 0x1E, 0xEA, 0x2D, 0x09, 0x93, 0xC8, 0x7E, 0xC2, 0xA0, }}, 84 | 85 | .s ={{ 0x02, 0xA4, 0x94, 0x37, 0x80, 0xBE, 0xEB, 0x68, 0xF1, 0xAD, 0xAD, 0x67, 0x76, 0x57, 0x26, 0x77, 86 | 0x53, 0xB7, 0x87, 0xC9, 0x22, 0x6B, 0xC2, 0x31, 0xE3, 0xC7, 0xD3, 0x86, 0xDA, 0x9D, 0x6B, 0x20, 87 | 0x4D, 0x69, 0xEB, 0xC8, 0xA2, 0x96, 0x1F, 0xE1, 0xB6, 0x10, 0x4F, 0xB7, 0x45, 0x3F, 0xAB, 0x20, }}, 88 | }; 89 | 90 | static uint8_t test_random[48] = 91 | { 92 | 0x59, 0x93, 0x74, 0xF8, 0x35, 0xA7, 0xD2, 0xE2, 0x45, 0xFD, 0xA1, 0x5A, 0x27, 0xE8, 0x0C, 0x3F, 93 | 0xB6, 0x1D, 0xBD, 0x5E, 0x58, 0x72, 0x13, 0xF5, 0x3A, 0xB3, 0x1B, 0xB4, 0x2D, 0x8B, 0xDD, 0x4B, 94 | 0x2F, 0x81, 0x00, 0xC0, 0xDA, 0x1C, 0x9D, 0xE3, 0x96, 0xA1, 0x89, 0x69, 0x03, 0x44, 0x6B, 0xDC, 95 | }; 96 | 97 | sev_status_t ecdsa_utest(void) 98 | { 99 | sev_status_t status = SEV_STATUS_SUCCESS; 100 | ecdsa_sig_t sig; 101 | ecc_keypair_t keypair; 102 | ecc_pubkey_t *test_pubkey; 103 | uint32_t loop; 104 | 105 | test_pubkey = (ecc_pubkey_t *)&test_keypair; 106 | 107 | /* Negative test for zero-buffer signature */ 108 | memset(&sig, 0, sizeof(sig)); 109 | status = ecdsa_verify(&sig, test_pubkey, test_digest, sizeof(test_digest)); 110 | if (status == SEV_STATUS_SUCCESS) 111 | { 112 | status = ERR_INVAL; 113 | goto end; 114 | } 115 | 116 | /* Negative test for random signature, test for a good amount of times */ 117 | for (loop = 0; loop < ECDSA_TEST_STRESS_COUNT; loop++ ) 118 | { 119 | status = sev_hal_trng((uint8_t *)&sig.r, SEV_ECC_CURVE_SIZE_BYTES); 120 | if (status != SEV_STATUS_SUCCESS) 121 | { 122 | break; 123 | } 124 | 125 | status = sev_hal_trng((uint8_t *)&sig.s, SEV_ECC_CURVE_SIZE_BYTES); 126 | if (status != SEV_STATUS_SUCCESS) 127 | { 128 | break; 129 | } 130 | 131 | status = ecdsa_verify(&sig, test_pubkey, test_digest, sizeof(test_digest)); 132 | if (status == SEV_STATUS_SUCCESS) 133 | { 134 | status = ERR_INVAL; 135 | break; 136 | } 137 | } 138 | if (status != SEV_STATUS_BAD_SIGNATURE) 139 | { 140 | goto end; 141 | } 142 | 143 | /* Positive test against test vector */ 144 | status = ecdsa_verify(&test_sig, test_pubkey, test_digest, sizeof(test_digest)); 145 | if (status != SEV_STATUS_SUCCESS) 146 | { 147 | goto end; 148 | } 149 | 150 | status = ecdsa_sign_rdata(&sig, &test_keypair, test_digest, sizeof(test_digest), test_random, sizeof(test_random)); 151 | if (status != SEV_STATUS_SUCCESS) 152 | { 153 | goto end; 154 | } 155 | 156 | if (memcmp(&sig, &test_sig, sizeof(test_sig)) != 0) 157 | { 158 | status = SEV_STATUS_BAD_SIGNATURE; 159 | goto end; 160 | } 161 | 162 | /* Finally, generate a keypair at run time, and test against itself. test for a good amount of times */ 163 | for (loop = 0; loop < ECDSA_TEST_STRESS_COUNT; loop++ ) 164 | { 165 | status = ecdsa_keypair_generate(&keypair); 166 | if (status != SEV_STATUS_SUCCESS) 167 | { 168 | break; 169 | } 170 | 171 | test_pubkey = (ecc_pubkey_t *)&keypair; 172 | status = ecdsa_sign(&sig, &keypair, test_digest, sizeof(test_digest)); 173 | if (status != SEV_STATUS_SUCCESS) 174 | { 175 | break; 176 | } 177 | 178 | status = ecdsa_verify(&sig, test_pubkey, test_digest, sizeof(test_digest)); 179 | if (status != SEV_STATUS_SUCCESS) 180 | { 181 | break; 182 | } 183 | } 184 | if (status != SEV_STATUS_SUCCESS) 185 | { 186 | goto end; 187 | } 188 | 189 | end: 190 | if (status != SEV_STATUS_SUCCESS) 191 | { 192 | SEV_TRACE("ecdsa_utest failed...\n"); 193 | SEV_TRACE_EX(status, 0, 0, 0); 194 | } 195 | else 196 | { 197 | SEV_TRACE("ecdsa_utest succeed!\n"); 198 | } 199 | 200 | return status; 201 | } 202 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/ecdsa_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ECDSA_UTEST_H 4 | #define ECDSA_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t ecdsa_utest(void); 12 | 13 | #endif /* ECDSA_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/encrypt_memory_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "sev_globals.h" 8 | #include "x86_copy.h" 9 | 10 | #define TEST_X86_ADDR (0x130000000) 11 | 12 | sev_status_t encrypt_memory_utest(void) 13 | { 14 | char plaintext[] = "Jesse Rules!!!!"; /* 16 byte-aligned */ 15 | sev_status_t status = SEV_STATUS_SUCCESS; 16 | uint64_t x86_addr = TEST_X86_ADDR; 17 | size_t asid = 1; 18 | 19 | /* Copy the plaintext to the scratch buffer */ 20 | memcpy(gpSevScratchBuf, plaintext, sizeof(plaintext)); 21 | 22 | /* Copy the scratch buffer contents to x86 memory with the C-bit set */ 23 | status = copy_to_x86_encrypted(x86_addr, gpSevScratchBuf, sizeof(plaintext), asid); 24 | if (status != SEV_STATUS_SUCCESS) 25 | goto end; 26 | 27 | /* Decrypt the x86 memory and copy it to a neighboring location */ 28 | status = decrypt_memory(x86_addr, x86_addr + sizeof(plaintext), 29 | gpSevScratchBuf+sizeof(plaintext), 30 | sizeof(plaintext), asid); 31 | if (status != SEV_STATUS_SUCCESS) 32 | goto end; 33 | 34 | /* Copy the unencrypted bytes back to the scratch buffer */ 35 | status = copy_from_x86_encrypted(x86_addr, gpSevScratchBuf, sizeof(plaintext), asid); 36 | if (status != SEV_STATUS_SUCCESS) 37 | goto end; 38 | 39 | /* The unencrypted bytes should be identical to the plaintext */ 40 | if (memcmp(plaintext, gpSevScratchBuf, sizeof(plaintext)) != 0) 41 | status = ERR_UNKNOWN; 42 | 43 | end: 44 | return status; 45 | } 46 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/encrypt_memory_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef ENCRYPT_MEMORY_UTEST_H 4 | #define ENCRYPT_MEMORY_UTEST_H 5 | 6 | #include "sev_status.h" 7 | 8 | sev_status_t encrypt_memory_utest(void); 9 | 10 | #endif /* ENCRYPT_MEMORY_UTEST_H */ 11 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/end_data.s: -------------------------------------------------------------------------------- 1 | ; Copyright(C) 2014 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | 4 | EXPORT LastBytes 5 | 6 | AREA END_DATA, DATA, READONLY, ALIGN=6 ; name this block of code; align at 64 byte 7 | 8 | ; Note: this is used for determining the size of the binary. It is 64 byte aligned and 64 byte 9 | ; in size so that the binary size is multiple of 64 byte. 10 | ; 11 | 12 | LastBytes DCB 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99 13 | DCB 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99 14 | DCB 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99 15 | DCB 0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99,0x99 16 | 17 | END 18 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/header.inc: -------------------------------------------------------------------------------- 1 | ; Copyright(C) 2014-2022 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | IMPORT LastBytes 4 | IMPORT ||Image$$SEV_UAPP_CODE$$ZI$$Limit|| 5 | 6 | ; IMPORT ||Image$$APP_CODE_RO$$Base|| ; Linker symbol from scatter file 7 | 8 | ;-------------------------------------------------------------------------------------- 9 | ; 256 byte binary header 10 | ; 11 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; nonce 12 | DCB 0x24,0x50,0x53,0x31 ; cookie "$PS1" 13 | ; Note: we can't use ||Image$$APP_CODE_RO$$Base|| symbol here because of some linker 14 | ; limitation (error A1142E: Subtractive relocations not supported for ELF format output). 15 | ; If start address in scatter file is changed it should be changed here as well, 16 | ; otherwise there will be signature validation error. 17 | ; 18 | DCD LastBytes + 64 - 0x00029000 - 256 ; image size (SizeFwSigned - sizeof(header)) 19 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 20 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 21 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 22 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 23 | DCD PSP_SEV_UAPP_FW_SPL ; [0x4C] Security patch level 24 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; 25 | DCB 0x43,0x01 ; [0x58] SocFwID 0x0143 26 | DCB 0x01 ; [0x5A] Header version 1 27 | DCB 0x00,0x00,0x00,0x00,0x00 28 | ; Why a 1 in the MSB of Image version? Because early SEV UApps had 0.0.1.0... big endian. Or 1.0.0 litte-endian. 29 | ; So putting a 1 in the MSB prevents those "old" 0.0.1.0/0.1.0.0 binaries from being downloadable on top of 0.16.x 30 | ; Image version is interpreted by Boot Loader C code as a little-endian 32-bit integer 31 | ; The LS byte is build #. Then Minor API version. Then Major API version. Then the 0x01. 32 | DCD PSP_SEV_UAPP_FW_VERSION ; [0x60] Image Version 33 | DCB 0xFF,0xFF,0xFF,0xFF ; [0x64] APU Family ID 34 | DCB 0x00,0x01,0x00,0x00 ; [0x68] Load Address 35 | DCB 0x00,0x00,0x00,0x00 ; [0x6C] In-use in other FWs, shall not use due to compatibility 36 | DCB 0x00,0x00,0x00,0x00 ; [0x70] In-use in other FWs, shall not use due to compatibility 37 | DCD ||Image$$SEV_UAPP_CODE$$ZI$$Limit|| - EntryPoint ; [0x74] FW Executable size = (RW base - FW entry offset) 38 | DCB 0x00,0x00,0x00,0x00 ; [0x78] Reserved 39 | DCB 0x39 ; [0x7C] FwTypeLegacy 40 | DCB 0x00,0x00,0x00 41 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 42 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 43 | DCB 0x61,0x00,0x29,0x00 ; [0xA0] Required Bootloader Image Version 44 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 ; [0xA4-0xFF] Reserved 45 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 46 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 47 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 48 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 49 | DCB 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 50 | 51 | END 52 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/helper.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "commontypes.h" 7 | #include "helper.h" 8 | 9 | bool is_empty(const void *object, size_t size) 10 | { 11 | bool rc = true; 12 | size_t i = 0; 13 | const uint8_t *buffer = (const uint8_t *)object; 14 | 15 | if (!object) 16 | { 17 | rc = false; 18 | goto end; 19 | } 20 | 21 | for (i = 0; i < size; i++) 22 | { 23 | if (buffer[i] != 0) 24 | { 25 | rc = false; 26 | goto end; 27 | } 28 | } 29 | 30 | end: 31 | return rc; 32 | } 33 | 34 | sev_status_t reverse_bytes(uint8_t *bytes, size_t size) 35 | { 36 | sev_status_t status = SEV_STATUS_SUCCESS; 37 | uint8_t *start = bytes; 38 | uint8_t *end = bytes + size - 1; 39 | 40 | if (!bytes) 41 | { 42 | status = ERR_INVALID_PARAMS; 43 | goto end; 44 | } 45 | 46 | while (start < end) 47 | { 48 | uint8_t byte = *start; 49 | *start = *end; 50 | *end = byte; 51 | start++; 52 | end--; 53 | } 54 | 55 | end: 56 | return status; 57 | } 58 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/helper.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef HELPER_H 4 | #define HELPER_H 5 | 6 | #include 7 | #include 8 | #include 9 | #include "sev_errors.h" 10 | #include "sev_status.h" 11 | 12 | static inline uint64_t to_addr64(uint32_t lo, uint32_t hi) 13 | { 14 | return ((uint64_t)hi << 32) | (uint64_t)lo; 15 | } 16 | 17 | static inline bool flags_valid(uint32_t flags, uint32_t mbz_mask) 18 | { 19 | return (flags & mbz_mask) == 0; 20 | } 21 | 22 | static inline uint64_t read_reg64(void *addr) 23 | { 24 | return *(volatile uint64_t *)addr; 25 | } 26 | 27 | static inline void write_reg64(void *addr, uint64_t value) 28 | { 29 | *(volatile uint64_t *)addr = value; 30 | } 31 | 32 | /** 33 | * Test if an object is empty (i.e. all zeros). 34 | */ 35 | bool is_empty(const void *object, size_t size); 36 | 37 | /** 38 | * Reverse 'size' bytes from the byte string pointed to by 'bytes'. 39 | */ 40 | sev_status_t reverse_bytes(uint8_t *bytes, size_t size); 41 | 42 | #endif /* HELPER_H */ 43 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/hmac.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "common_utilities.h" 6 | #include "hmac.h" 7 | #include "secure_ops.h" 8 | 9 | #define HMAC_IPAD_VALUE (0x36) 10 | #define HMAC_OPAD_VALUE (0x5C) 11 | 12 | /** 13 | * Initializes the digest context. 14 | */ 15 | sev_status_t hmac_sha256_init(hmac_sha256_ctx_t *ctx, const void *key, size_t length) 16 | { 17 | sev_status_t status = SEV_STATUS_SUCCESS; 18 | uint8_t *k_ipad = NULL; // inner padding - key XORd with ipad 19 | uint32_t i = 0; 20 | uint8_t pad_data[HMAC_SHA256_BLOCK_SIZE_BYTES + 32]; 21 | 22 | if (!ctx || !key || length == 0) 23 | { 24 | status = ERR_INVALID_PARAMS; 25 | goto end; 26 | } 27 | 28 | /* 29 | * For key sizes bigger than HMAC block size, the HMAC specification 30 | * requires the key to be hashed prior to using it with i-pad and o-pad. 31 | * We don't support this mode here. 32 | */ 33 | if (length > HMAC_SHA256_KEY_SIZE_BYTES) 34 | { 35 | status = ERR_INVALID_PARAMS; 36 | goto end; 37 | } 38 | 39 | k_ipad = (uint8_t *)ALIGN_TO_32_BYTES(pad_data); /* Make it aligned cache line boundary */ 40 | 41 | memset(k_ipad, 0, HMAC_SHA256_BLOCK_SIZE_BYTES); 42 | memcpy(k_ipad, key, length); 43 | for (i = 0; i < HMAC_SHA256_BLOCK_SIZE_BYTES; i++) 44 | { 45 | k_ipad[i] ^= HMAC_IPAD_VALUE; 46 | } 47 | 48 | status = digest_sha_init(&ctx->digest_ctx, SHA_TYPE_256); 49 | if (status != SEV_STATUS_SUCCESS) 50 | goto end; 51 | 52 | status = digest_sha_update(&ctx->digest_ctx, k_ipad, 53 | HMAC_SHA256_BLOCK_SIZE_BYTES); 54 | if (status != SEV_STATUS_SUCCESS) 55 | goto end; 56 | 57 | // save the context 58 | ctx->key_len = length; 59 | memcpy(ctx->key, key, length); 60 | 61 | end: 62 | return status; 63 | } 64 | 65 | /** 66 | * Updates the context with the given data. 67 | * 68 | * data : data buffer 69 | * length: can be any length, even 0. 70 | */ 71 | sev_status_t hmac_sha256_update(hmac_sha256_ctx_t *ctx, const void *data, size_t length) 72 | { 73 | return digest_sha_update(&ctx->digest_ctx, data, length); 74 | } 75 | 76 | /** 77 | * Updates the context with the padding and outputs the digest. 78 | * 79 | * data : input data buffer. 80 | * length: can be of any size, could be 0. 81 | * hmac : doesn't have to be 16 byte aligned. 82 | */ 83 | sev_status_t hmac_sha256_final(hmac_sha256_ctx_t *ctx, hmac_sha256_t *hmac) 84 | { 85 | sev_status_t status = SEV_STATUS_SUCCESS; 86 | uint8_t *k_opad = NULL; // outer padding - key XORd with opad 87 | uint32_t i = 0; 88 | uint8_t pad_data[HMAC_SHA256_BLOCK_SIZE_BYTES + HMAC_SHA256_SIZE_BYTES + 32]; 89 | uint32_t digest_len = 0; 90 | digest_sha_t *digest = NULL; 91 | 92 | if (!ctx || !hmac) 93 | { 94 | status = ERR_INVALID_PARAMS; 95 | goto end; 96 | } 97 | 98 | k_opad = (uint8_t *)ALIGN_TO_32_BYTES(pad_data); /* Make it aligned cache line boundary */ 99 | 100 | memset(k_opad, 0, HMAC_SHA256_BLOCK_SIZE_BYTES); 101 | memcpy(k_opad, ctx->key, ctx->key_len); 102 | for (i = 0; i < HMAC_SHA256_BLOCK_SIZE_BYTES; i++) 103 | { 104 | k_opad[i] ^= HMAC_OPAD_VALUE; 105 | } 106 | 107 | /* Hash(ipad || Message) where "||" is concatenation 108 | * and Read the value of Hash(ipad || Message) from CCP. */ 109 | digest_len = HMAC_SHA256_BLOCK_SIZE_BYTES; 110 | digest = (digest_sha_t *)&k_opad[HMAC_SHA256_BLOCK_SIZE_BYTES]; 111 | status = digest_sha_final(&ctx->digest_ctx, digest, &digest_len); 112 | if (status != SEV_STATUS_SUCCESS) 113 | goto end; 114 | 115 | /* Hash(opad || Hash(ipad || Message)) where "||" is concatenation. 116 | * and read the final HMAC value from CCP. */ 117 | status = digest_sha_init(&ctx->digest_ctx, SHA_TYPE_256); 118 | if (status != SEV_STATUS_SUCCESS) 119 | goto end; 120 | 121 | status = digest_sha_update(&ctx->digest_ctx, k_opad, 122 | HMAC_SHA256_BLOCK_SIZE_BYTES + 123 | HMAC_SHA256_SIZE_BYTES); 124 | if (status != SEV_STATUS_SUCCESS) 125 | goto end; 126 | 127 | digest_len = sizeof(*hmac); 128 | digest = (digest_sha_t *)hmac; 129 | status = digest_sha_final(&ctx->digest_ctx, digest, &digest_len); 130 | 131 | end: 132 | return status; 133 | } 134 | 135 | sev_status_t hmac_sha256(const void *msg, size_t msg_len, 136 | const void *key, size_t key_len, 137 | hmac_sha256_t *hmac) 138 | { 139 | sev_status_t status = SEV_STATUS_SUCCESS; 140 | hmac_sha256_ctx_t ctx; 141 | 142 | if (!msg || msg_len == 0 || !hmac || !key || key_len == 0) 143 | { 144 | status = ERR_INVALID_PARAMS; 145 | goto end; 146 | } 147 | 148 | status = hmac_sha256_init(&ctx, key, key_len); 149 | if (status != SEV_STATUS_SUCCESS) 150 | goto end; 151 | 152 | status = hmac_sha256_update(&ctx, msg, msg_len); 153 | if (status != SEV_STATUS_SUCCESS) 154 | goto end; 155 | 156 | status = hmac_sha256_final(&ctx, hmac); 157 | 158 | end: 159 | return status; 160 | } 161 | 162 | sev_status_t hmac_sha256_verify(const hmac_sha256_t *hmac, 163 | const hmac_sha256_t *valid_hmac) 164 | { 165 | sev_status_t status = SEV_STATUS_SUCCESS; 166 | 167 | if (!hmac || !valid_hmac) 168 | { 169 | status = ERR_INVALID_PARAMS; 170 | goto end; 171 | } 172 | 173 | if (secure_compare(valid_hmac, hmac, sizeof(hmac_sha256_t)) != 0) 174 | status = SEV_STATUS_BAD_MEASUREMENT; 175 | 176 | end: 177 | return status; 178 | } 179 | 180 | sev_status_t hmac_sha256_verify_msg(const void *msg, size_t msg_len, 181 | const void *key, size_t key_len, 182 | const hmac_sha256_t *valid_hmac) 183 | { 184 | sev_status_t status = SEV_STATUS_SUCCESS; 185 | hmac_sha256_t hmac; 186 | 187 | if (!msg || msg_len == 0 || !valid_hmac || !key || key_len == 0) 188 | { 189 | status = ERR_INVALID_PARAMS; 190 | goto end; 191 | } 192 | 193 | memset(&hmac, 0, sizeof(hmac)); 194 | 195 | status = hmac_sha256(msg, msg_len, key, key_len, &hmac); 196 | if (status != SEV_STATUS_SUCCESS) 197 | goto end; 198 | 199 | if (secure_compare(&hmac, valid_hmac, sizeof(hmac)) != 0) 200 | status = SEV_STATUS_BAD_MEASUREMENT; 201 | 202 | end: 203 | return status; 204 | } 205 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/hmac.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef HMAC_H 4 | #define HMAC_H 5 | 6 | #include 7 | #include 8 | 9 | #include "digest.h" 10 | #include "sev_errors.h" 11 | 12 | #define HMAC_SHA256_SIZE_BYTES (DIGEST_SHA256_SIZE_BYTES) 13 | #define HMAC_SHA256_BLOCK_SIZE_BYTES 64 14 | #define HMAC_SHA256_KEY_SIZE_BYTES 64 15 | #define HMAC_SHA512_SIZE_BYTES (DIGEST_SHA512_SIZE_BYTES) 16 | #define HMAC_SHA512_BLOCK_SIZE_BYTES 128 17 | #define HMAC_SHA512_KEY_SIZE_BYTES 128 18 | 19 | typedef struct hmac_sha256 20 | { 21 | uint8_t hmac[HMAC_SHA256_SIZE_BYTES]; 22 | } hmac_sha256_t; 23 | 24 | typedef struct hmac_sha256_ctx 25 | { 26 | digest_sha_ctx_t digest_ctx; 27 | uint8_t key[HMAC_SHA256_KEY_SIZE_BYTES]; 28 | uint32_t key_len; 29 | } hmac_sha256_ctx_t; 30 | 31 | /** 32 | * Initializes the hmac-sha256 context. 33 | */ 34 | sev_status_t hmac_sha256_init(hmac_sha256_ctx_t *ctx, const void *key, size_t length); 35 | 36 | /** 37 | * Updates the context with the given data. 38 | * 39 | * data : Input buffer. 40 | * length : Input buffer length. 41 | */ 42 | sev_status_t hmac_sha256_update(hmac_sha256_ctx_t *ctx, const void *data, size_t length); 43 | 44 | /** 45 | * Updates the context with the padding and outputs the digest. 46 | * 47 | * hmac : Output buffer. 48 | */ 49 | sev_status_t hmac_sha256_final(hmac_sha256_ctx_t *ctx, hmac_sha256_t *hmac); 50 | 51 | /** 52 | * Calculates the HMAC of the 'msg' keyed with 'key'. 53 | * 54 | * msg : Message to verify. (in) 55 | * msg_len : Message length in bytes. (in) 56 | * key : Key used to calculate 'hmac'. (in) 57 | * key_len : Length of the key in bytes. (in) 58 | * hmac : HMAC result. (out) 59 | */ 60 | sev_status_t hmac_sha256(const void *msg, size_t msg_len, 61 | const void *key, size_t key_len, 62 | hmac_sha256_t *hmac); 63 | 64 | /** 65 | * Verifies that the input 'hmac' is the same as 'valid_hmac'. The comparison 66 | * is guaranteed to be constant-time regardless of input. 67 | * 68 | * hmac : HMAC to verify. (in) 69 | * valid_hmac : expected HMAC. (in) 70 | */ 71 | sev_status_t hmac_sha256_verify(const hmac_sha256_t *hmac, 72 | const hmac_sha256_t *valid_hmac); 73 | 74 | /** 75 | * Verifies that the HMAC of the 'msg' keyed with 'key' is the same as 'hmac'. 76 | * 77 | * msg : Message to verify. (in) 78 | * msg_len : Message length in bytes. (in) 79 | * key : Key used to calculate 'hmac'. (in) 80 | * key_len : Length of the key in bytes. (in) 81 | * hmac : HMAC to verify. (in) 82 | */ 83 | sev_status_t hmac_sha256_verify_msg(const void *msg, size_t msg_len, 84 | const void *key, size_t key_len, 85 | const hmac_sha256_t *valid_hmac); 86 | 87 | #endif /* HMAC_H */ 88 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/hmac_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "hmac.h" 6 | #include "hmac_utest.h" 7 | #include "sev_trace.h" 8 | // #include "ccp_direct_cipher.h" 9 | 10 | /* HMAC Test Vectors are: 11 | * 12 | * Copyright (C) The Internet Society (2005). This document is subject to the rights, 13 | * licenses and restrictions contained in BCP 78, and except as set forth therein, the 14 | * authors retain all their rights. This document and the information contained herein 15 | * are provided on an "AS IS" basis and THE CONTRIBUTOR, THE ORGANIZATION HE/SHE REPRESENTS 16 | * OR IS SPONSORED BY (IF ANY), THE INTERNET SOCIETY AND THE INTERNET ENGINEERING TASK 17 | * FORCE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY 18 | * WARRANTY THAT THE USE OF THE INFORMATION HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY 19 | * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 20 | */ 21 | 22 | /* HMAC test vectors ================================================================== */ 23 | typedef struct HMAC_VECTOR_T 24 | { 25 | unsigned char aucKey[32]; 26 | unsigned char aucMessage[64]; 27 | unsigned char aucHmac[HMAC_SHA256_SIZE_BYTES]; 28 | unsigned int uiKeyLen; 29 | unsigned int uiMessageLen; 30 | } HMAC_VECTOR; 31 | 32 | /** 33 | * These are subset of test vectors from RFC 4231 (https://tools.ietf.org/html/rfc4231). 34 | * Test cases 1, 2, 3 and 4 are taken (HMAC-SHA-256). Other cases are not supported by our implementation. 35 | */ 36 | static HMAC_VECTOR HmacVector[] = 37 | { 38 | { // test case 1 39 | { 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 40 | 0x0b, 0x0b, 0x0b, 0x0b, 41 | }, 42 | { 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65, 43 | }, 44 | { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 45 | 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7, 46 | }, 47 | 20, 48 | 8, 49 | }, 50 | 51 | { // test case 2 52 | { 0x4a, 0x65, 0x66, 0x65, 53 | }, 54 | { 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20, 0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20, 55 | 0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68, 0x69, 0x6e, 0x67, 0x3f, 56 | }, 57 | { 58 | 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 59 | 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43, 60 | }, 61 | 4, 62 | 28, 63 | }, 64 | 65 | { // test case 3 66 | { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 67 | 0xaa, 0xaa, 0xaa, 0xaa, 68 | }, 69 | { 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 70 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 71 | 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 72 | 0xdd, 0xdd, 73 | }, 74 | { 75 | 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 76 | 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe, 77 | }, 78 | 20, 79 | 50, 80 | }, 81 | 82 | { // test case 4 83 | { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 84 | 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 85 | }, 86 | { 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 87 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 88 | 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 89 | 0xcd, 0xcd, 90 | }, 91 | { 92 | 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 93 | 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b, 94 | }, 95 | 25, 96 | 50, 97 | }, 98 | 99 | }; 100 | 101 | /* End of HMAC test vectors ================================================================== */ 102 | 103 | 104 | sev_status_t hmac_utest(void) 105 | { 106 | sev_status_t status = SEV_STATUS_SUCCESS; 107 | hmac_sha256_ctx_t ctx; 108 | hmac_sha256_t hmac; 109 | size_t i, j; 110 | 111 | for (i = 0; i < sizeof(HmacVector)/sizeof(HmacVector[0]); i++) 112 | { 113 | memset(&hmac, 0, sizeof(hmac)); 114 | 115 | status = hmac_sha256_init(&ctx, HmacVector[i].aucKey, HmacVector[i].uiKeyLen); 116 | if (status != SEV_STATUS_SUCCESS) 117 | break; 118 | 119 | status = hmac_sha256_update(&ctx, HmacVector[i].aucMessage, HmacVector[i].uiMessageLen); 120 | if (status != SEV_STATUS_SUCCESS) 121 | break; 122 | 123 | status = hmac_sha256_final(&ctx, &hmac); 124 | if (status != SEV_STATUS_SUCCESS) 125 | break; 126 | 127 | for (j = 0; j < sizeof(hmac); j++) 128 | { 129 | if (HmacVector[i].aucHmac[j] != hmac.hmac[j]) 130 | { 131 | status = ERR_UNKNOWN; 132 | goto end; 133 | } 134 | } 135 | 136 | // Test HMAC using CCP Direct API 137 | /* blilient: Commented out because the input vectors are too small. 138 | Function wants a minimum of 64 bytes 139 | status = hmac_utest_hmac256_kat( 140 | HmacVector[i].aucKey, HmacVector[i].uiKeyLen, 141 | HmacVector[i].aucMessage, HmacVector[i].uiMessageLen, 142 | HmacVector[i].aucHmac); 143 | if (status != SEV_STATUS_SUCCESS) 144 | goto end; */ 145 | } 146 | 147 | end: 148 | if (status != SEV_STATUS_SUCCESS) 149 | { 150 | SEV_TRACE("hmac_utest failed...\n"); 151 | SEV_TRACE_EX(status, 0, 0, 0); 152 | } 153 | else 154 | { 155 | SEV_TRACE("hmac_utest succeed!\n"); 156 | } 157 | 158 | return status; 159 | } 160 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/hmac_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef HMAC_UTEST_H 4 | #define HMAC_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t hmac_utest(void); 12 | 13 | #endif /* HMAC_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/kdf.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include "kdf.h" 4 | #include "sev_hal.h" 5 | 6 | sev_status_t bl_kdf_derive( uint8_t *key_out, size_t key_out_length, 7 | const uint8_t *key_in, size_t key_in_length, 8 | const uint8_t *label, size_t label_length, 9 | const uint8_t *context, size_t context_length) 10 | { 11 | sev_status_t status = SEV_STATUS_SUCCESS; 12 | sev_hal_key_derive_t params; 13 | 14 | if (!key_out || key_out_length == 0 || !label || label_length == 0 || 15 | !context || context_length == 0) 16 | { 17 | status = ERR_INVALID_PARAMS; 18 | goto end; 19 | } 20 | 21 | params.key_out = key_out; 22 | params.key_out_length = key_out_length; 23 | params.key_in = key_in; 24 | params.key_in_length = key_in_length; 25 | params.label = label; 26 | params.label_length = label_length; 27 | params.context = context; 28 | params.context_length = context_length; 29 | 30 | status = sev_hal_key_derive(¶ms); 31 | 32 | end: 33 | return status; 34 | } 35 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/kdf.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef KDF_H 4 | #define KDF_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | /** 12 | * Implements the KDF in Counter Mode defined in section 5.1 of NIST 13 | * SP 800-108. 14 | * 15 | * 'context': a one-time use nonce or context value, can be zero 16 | * 17 | * 'key_in': may be NULL, if so, derive the key from PSP fused AES key; 18 | * 19 | * 'label': null terminated string describing key, no rules 20 | * 21 | * All other pointers must not be 'NULL'. 22 | * 23 | * The PRF used is the HMAC-SHA256 implementation in this firmware. 24 | */ 25 | sev_status_t bl_kdf_derive(uint8_t *key_out, size_t key_out_length, 26 | const uint8_t *key_in, size_t key_in_length, 27 | const uint8_t *label, size_t label_length, 28 | const uint8_t *context, size_t context_length); 29 | 30 | #endif /* KDF_H */ 31 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/nist_kdf.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "common_utilities.h" 8 | #include "hmac.h" 9 | #include "kdf.h" 10 | #include "nist_kdf.h" 11 | #include "secure_ops.h" 12 | 13 | /** 14 | * Number of bytes in the output of the PRF. 15 | */ 16 | #define NIST_KDF_H_BYTES (HMAC_SHA256_SIZE_BYTES) 17 | 18 | /** 19 | * Number of bits in the output of the PRF. 20 | */ 21 | #define NIST_KDF_H ((NIST_KDF_H_BYTES)*(BITS_PER_BYTE)) 22 | 23 | /** 24 | * Number of bits in the representation of the counter, i. 25 | */ 26 | #define NIST_KDF_R (sizeof(uint32_t)*(BITS_PER_BYTE)) 27 | 28 | typedef struct nist_kdf_prf_params 29 | { 30 | const uint8_t *key; 31 | size_t key_length; 32 | uint32_t i; 33 | const uint8_t *label; 34 | size_t label_length; 35 | const uint8_t *context; 36 | size_t context_length; 37 | uint32_t l; 38 | } nist_kdf_prf_params_t; 39 | 40 | static sev_status_t nist_kdf_prf(uint8_t *out, size_t out_length, 41 | const nist_kdf_prf_params_t *params) 42 | { 43 | sev_status_t status = SEV_STATUS_SUCCESS; 44 | hmac_sha256_t hmac; 45 | hmac_sha256_ctx_t ctx; 46 | uint8_t null_byte = '\0'; 47 | 48 | if (!out || out_length != NIST_KDF_H_BYTES || !params || 49 | !params->key || !params->label) 50 | { 51 | status = ERR_INVALID_PARAMS; 52 | goto end; 53 | } 54 | 55 | status = hmac_sha256_init(&ctx, params->key, params->key_length); 56 | if (status != SEV_STATUS_SUCCESS) 57 | { 58 | goto end; 59 | } 60 | 61 | /* The SVC call for SHA256 releases the LSB after each op, so there's no 62 | * resource leak here, even though we may not call hmac_sha256_final(). */ 63 | 64 | status = hmac_sha256_update(&ctx, (uint8_t *)¶ms->i, sizeof(params->i)); 65 | if (status != SEV_STATUS_SUCCESS) 66 | { 67 | goto end; 68 | } 69 | 70 | status = hmac_sha256_update(&ctx, params->label, params->label_length); 71 | if (status != SEV_STATUS_SUCCESS) 72 | { 73 | goto end; 74 | } 75 | 76 | status = hmac_sha256_update(&ctx, &null_byte, sizeof(null_byte)); 77 | if (status != SEV_STATUS_SUCCESS) 78 | { 79 | goto end; 80 | } 81 | 82 | if (params->context && params->context_length != 0) 83 | { 84 | status = hmac_sha256_update(&ctx, params->context, params->context_length); 85 | if (status != SEV_STATUS_SUCCESS) 86 | { 87 | goto end; 88 | } 89 | } 90 | 91 | status = hmac_sha256_update(&ctx, (uint8_t *)¶ms->l, sizeof(params->l)); 92 | if (status != SEV_STATUS_SUCCESS) 93 | { 94 | goto end; 95 | } 96 | 97 | status = hmac_sha256_final(&ctx, &hmac); 98 | if (status != SEV_STATUS_SUCCESS) 99 | { 100 | goto end; 101 | } 102 | 103 | memcpy(out, hmac.hmac, out_length); 104 | 105 | end: 106 | secure_memzero(&hmac, sizeof(hmac)); 107 | return status; 108 | } 109 | 110 | sev_status_t nist_kdf(uint8_t *key_out, size_t key_out_length, 111 | const uint8_t *key_in, size_t key_in_length, 112 | const uint8_t *label, size_t label_length, 113 | const uint8_t *context, size_t context_length) 114 | { 115 | sev_status_t status = SEV_STATUS_SUCCESS; 116 | uint32_t i = 0, offset = 0; 117 | 118 | /* Buffer to collect PRF output */ 119 | uint8_t prf_out[NIST_KDF_H_BYTES]; 120 | 121 | /* Length in bits of derived key */ 122 | uint32_t l = key_out_length * BITS_PER_BYTE; 123 | 124 | /* Number of iterations to produce enough derived key bits */ 125 | uint32_t n = ((l-1)/NIST_KDF_H) + 1; 126 | 127 | size_t bytes_left = key_out_length; 128 | 129 | if (!key_out) 130 | { 131 | status = ERR_INVALID_PARAMS; 132 | goto end; 133 | } 134 | 135 | for (i = 1; i <= n; i++) 136 | { 137 | nist_kdf_prf_params_t params; 138 | 139 | params.key = key_in; 140 | params.key_length = key_in_length; 141 | params.label = label; 142 | params.label_length = label_length; 143 | params.context = context; 144 | params.context_length = context_length; 145 | params.i = i; 146 | params.l = l; 147 | 148 | /* 149 | * Ensure that all of the memory operations above have completed before 150 | * we continue. 151 | */ 152 | ARMCC_DSB_ISB(); 153 | 154 | /* Calculate a chunk of random data from the PRF */ 155 | status = nist_kdf_prf(prf_out, NIST_KDF_H_BYTES, ¶ms); 156 | if (status != SEV_STATUS_SUCCESS) 157 | { 158 | goto end; 159 | } 160 | 161 | /* Write out the key bytes */ 162 | if (bytes_left <= NIST_KDF_H_BYTES) 163 | { 164 | memcpy(key_out + offset, prf_out, bytes_left); 165 | } 166 | else 167 | { 168 | memcpy(key_out + offset, prf_out, NIST_KDF_H_BYTES); 169 | offset += NIST_KDF_H_BYTES; 170 | bytes_left -= NIST_KDF_H_BYTES; 171 | } 172 | } 173 | 174 | end: 175 | secure_memzero(prf_out, sizeof(prf_out)); 176 | return status; 177 | } 178 | 179 | #if 1 180 | sev_status_t kdf_derive( uint8_t *key_out, size_t key_out_length, 181 | const uint8_t *key_in, size_t key_in_length, 182 | const uint8_t *label, size_t label_length, 183 | const uint8_t *context, size_t context_length) 184 | { 185 | return nist_kdf(key_out, key_out_length, key_in, key_in_length, label, 186 | label_length, context, context_length); 187 | } 188 | #endif 189 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/nist_kdf.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef KDF_H 4 | #define KDF_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | /** 12 | * Implements the KDF in Counter Mode defined in section 5.1 of NIST 13 | * SP 800-108. 14 | * 15 | * 'context': a one-time use nonce or context value, can be zero 16 | * 17 | * 'key_in': input key material 18 | * 19 | * 'label': null terminated string describing key, no rules 20 | * 21 | * All other pointers must not be 'NULL'. 22 | * 23 | * The PRF used is the HMAC-SHA256 implementation in this firmware. 24 | */ 25 | sev_status_t nist_kdf(uint8_t *key_out, size_t key_out_length, 26 | const uint8_t *key_in, size_t key_in_length, 27 | const uint8_t *label, size_t label_length, 28 | const uint8_t *context, size_t context_length); 29 | 30 | sev_status_t kdf_derive(uint8_t *key_out, size_t key_out_length, 31 | const uint8_t *key_in, size_t key_in_length, 32 | const uint8_t *label, size_t label_length, 33 | const uint8_t *context, size_t context_length); 34 | 35 | #endif /* KDF_H */ 36 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/pool_u32.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef POOL_U32_H 4 | #define POOL_U32_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "sev_errors.h" 11 | 12 | typedef struct es_vcpu 13 | { 14 | uint32_t next_index; 15 | } es_vcpu_t; 16 | 17 | typedef struct es_vcpu_crc 18 | { 19 | union { 20 | uint64_t CRC64; 21 | uint32_t CRC32; 22 | } u; 23 | } es_vcpu_crc_t; 24 | 25 | #define ES_VCPU_CRC_OFFSET (offsetof(es_vcpu_t, CRC)) 26 | 27 | #define CRC_BLOCK_SIZE (sizeof(es_vcpu_crc_t)) 28 | #define INDEX_BLOCK_SIZE (sizeof(es_vcpu_t)) 29 | #define INVALID_BLOCK (0xFFFFFFFF) 30 | 31 | /** 32 | * See CSF-395/CSF-396 (comments/attachments) for how/why this was implemented 33 | */ 34 | typedef struct pool_vcpu 35 | { 36 | uint64_t start_crc_addr; /* Start address of the memory region to manage */ 37 | uint64_t end_crc_addr; /* End address of the memory region to manage */ 38 | uint64_t start_pool_addr; 39 | uint64_t end_pool_addr; 40 | size_t nr_blocks; /* Number of blocks in the pool */ 41 | size_t free_head_idx; /* Free list head */ 42 | size_t free_tail_idx; /* Free list tail */ 43 | bool is_initialized; /* State variable */ 44 | } pool_vcpu_t; 45 | 46 | /** 47 | * Initialize the pool. 'start_addr' points to the memory to use for the 48 | * pool. 49 | */ 50 | sev_status_t pool_vcpu_init(pool_vcpu_t *pool, uint64_t start_addr_pool, 51 | uint64_t start_addr_crc, uint64_t size); 52 | 53 | /** 54 | * Destroy the pool and clear its contents. 55 | */ 56 | sev_status_t pool_vcpu_destroy(pool_vcpu_t *pool); 57 | 58 | /** 59 | * Allocate a VCPU block from the trusted memory region. Returns a 64-bit x86 60 | * address for both the block and the CRC location that needs to 61 | * be mapped with sev_hal_map_memory() before use. 62 | * 63 | * On error, returns 0. 64 | */ 65 | uint64_t pool_vcpu_alloc(pool_vcpu_t *pool, uint32_t *index, uint64_t *crc_block_paddr); 66 | 67 | /** 68 | * Free a trusted block back to the pool. 69 | */ 70 | void pool_vcpu_free(pool_vcpu_t *pool, uint64_t block); 71 | 72 | /** 73 | * Free a user "linked" list of vcpu entries back into the pool. 74 | */ 75 | sev_status_t pool_vcpu_free_list(pool_vcpu_t *pool, uint32_t start_index, 76 | uint32_t end_index, uint32_t expected_entries); 77 | 78 | /** 79 | * Map a VCPU Index to its 64 bit physical address 80 | */ 81 | uint64_t pool_vcpu_index_to_addr64(pool_vcpu_t *pool, size_t idx); 82 | 83 | /** 84 | * Find a CRC entry in a user list. Return true or false or error code. 85 | */ 86 | sev_status_t pool_vcpu_find_crc_in_list(pool_vcpu_t *pool, uint32_t start_index, 87 | uint32_t end_index, uint64_t crc, 88 | uint32_t expected_entries, bool *found); 89 | 90 | #endif /* POOL_U32_H */ 91 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/rsa.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "rsa.h" 7 | #include "sev_hal.h" 8 | 9 | bool rsa_pubkey_is_valid(const rsa_pubkey_t *pubkey) 10 | { 11 | bool is_valid = false; 12 | 13 | if (pubkey && pubkey->modulus_size_bits <= RSA_MOD_SIZE_BYTES*BITS_PER_BYTE) 14 | is_valid = true; 15 | 16 | return is_valid; 17 | } 18 | 19 | sev_status_t rsa_pss_verify(const uint8_t *hash, uint32_t hash_len, 20 | const uint8_t *modulus, uint32_t modulus_len, 21 | const uint8_t *exp, uint32_t exp_len, 22 | const uint8_t *sig) 23 | { 24 | sev_status_t status = SEV_STATUS_SUCCESS; 25 | sev_hal_rsapss_verify_t rsa_pss; 26 | 27 | if (!hash || !modulus || !exp || !sig || hash_len == 0 || modulus_len == 0 || 28 | exp_len == 0) 29 | { 30 | status = ERR_INVALID_PARAMS; 31 | goto end; 32 | } 33 | 34 | rsa_pss.hash = (uint8_t *)hash; 35 | rsa_pss.hash_len = hash_len; 36 | rsa_pss.modulus = (uint8_t *)modulus; 37 | rsa_pss.modulus_len = modulus_len; 38 | rsa_pss.exponent = (uint8_t *)exp; 39 | rsa_pss.exp_len = exp_len; 40 | rsa_pss.sig = (uint8_t *)sig; 41 | status = sev_hal_rsapss_verify(&rsa_pss); 42 | if (status != SEV_STATUS_SUCCESS) 43 | status = SEV_STATUS_BAD_SIGNATURE; 44 | 45 | end: 46 | return status; 47 | } 48 | 49 | sev_status_t rsa_pss_verify_msg(const uint8_t *msg, uint32_t msg_len, 50 | const uint8_t *modulus, uint32_t modulus_len, 51 | const uint8_t *exp, uint32_t exp_len, 52 | const uint8_t *sig, const uint32_t algo) 53 | { 54 | sev_status_t status = SEV_STATUS_SUCCESS; 55 | digest_sha_t sha; 56 | SHA_TYPE sha_type = SHA_TYPE_256; 57 | size_t sha_len = sizeof(sha); 58 | 59 | if (!msg || !modulus || !exp || !sig) 60 | { 61 | status = ERR_INVALID_PARAMS; 62 | goto end; 63 | } 64 | 65 | if (msg_len == 0 || modulus_len == 0 || exp_len == 0 || 66 | modulus_len > RSA_MOD_SIZE_BYTES || exp_len > RSA_MOD_SIZE_BYTES || 67 | modulus_len != exp_len) 68 | { 69 | status = SEV_STATUS_INVALID_LENGTH; 70 | goto end; 71 | } 72 | 73 | if (algo == SEV_CERT_ALGO_RSA_SHA256) 74 | sha_type = SHA_TYPE_256; 75 | else 76 | sha_type = SHA_TYPE_384; 77 | 78 | /* Calculate the digest of the input message */ 79 | status = digest_sha(msg, msg_len, &sha, &sha_len, sha_type); 80 | if (status != SEV_STATUS_SUCCESS) 81 | goto end; 82 | 83 | /* Verify the digest signature */ 84 | status = rsa_pss_verify(sha.digest, sha_len, modulus, modulus_len, exp, 85 | exp_len, sig); 86 | 87 | end: 88 | return status; 89 | } 90 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/rsa.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef RSA_H 4 | #define RSA_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | #define RSA_MOD_SIZE_BYTES (512) 12 | #define RSA_SIG_SIZE_BYTES (RSA_MOD_SIZE_BYTES) 13 | 14 | typedef struct rsa_keypair 15 | { 16 | uint32_t modulus_size_bits; 17 | uint8_t pub_exp[RSA_MOD_SIZE_BYTES]; 18 | uint8_t modulus[RSA_MOD_SIZE_BYTES]; 19 | } rsa_keypair_t; 20 | 21 | typedef struct rsa_pubkey 22 | { 23 | uint32_t modulus_size_bits; 24 | uint8_t pub_exp[RSA_MOD_SIZE_BYTES]; 25 | uint8_t modulus[RSA_MOD_SIZE_BYTES]; 26 | } rsa_pubkey_t; 27 | 28 | typedef struct rsa_sig 29 | { 30 | uint8_t s[RSA_SIG_SIZE_BYTES]; 31 | } rsa_sig_t; 32 | 33 | 34 | /** 35 | * Validate RSA public key 36 | * 37 | * - pubkey : RSA public key to validate. 38 | */ 39 | bool rsa_pubkey_is_valid(const rsa_pubkey_t *pubkey); 40 | 41 | /** 42 | * RSA PSS Verify Digest Signature 43 | * 44 | * - modulus and exponent : little-endian 45 | * - sig : little-endian 46 | */ 47 | sev_status_t rsa_pss_verify(const uint8_t *hash, uint32_t hash_len, 48 | const uint8_t *modulus, uint32_t modulus_len, 49 | const uint8_t *exp, uint32_t exp_len, 50 | const uint8_t *sig); 51 | 52 | /** 53 | * RSA PSS Verify Message 54 | * 55 | * - modulus and exponent : little-endian 56 | * - sig : little-endian 57 | */ 58 | sev_status_t rsa_pss_verify_msg(const uint8_t *msg, uint32_t msg_len, 59 | const uint8_t *modulus, uint32_t modulus_len, 60 | const uint8_t *exp, uint32_t exp_len, 61 | const uint8_t *sig, const uint32_t algo); 62 | 63 | #endif /* RSA_H */ 64 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/rsa_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "rsa.h" 8 | #include "rsa_utest.h" 9 | #include "sev_globals.h" 10 | #include "sev_trace.h" 11 | 12 | #define RSA_PSS_BUFFER_LEN 256 13 | #define RSA_PSS_EXP_LEN 4 14 | 15 | typedef struct _RSAPSSVECTOR 16 | { 17 | unsigned char Modulus[RSA_PSS_BUFFER_LEN]; 18 | unsigned char Exp[RSA_PSS_EXP_LEN]; 19 | unsigned char Signature[RSA_PSS_BUFFER_LEN]; 20 | unsigned char Hash[32]; 21 | unsigned int ModulusLen; 22 | unsigned int ExpLen; 23 | unsigned int SignatureLen; 24 | unsigned int HashLen; 25 | } RSAPSSVECTOR; 26 | 27 | static RSAPSSVECTOR RSAPSSVector[] = 28 | { 29 | /* RSA-PSS */ 30 | { 31 | { 32 | 0x11, 0x44, 0xd1, 0xd0, 0x91, 0xa8, 0x83, 0x67, 0x78, 0x1e, 0xd0, 0xec, 0x69, 0x1c, 0xd5, 0x6a, 33 | 0x7f, 0x3b, 0x04, 0x7c, 0x4a, 0x78, 0xc4, 0x21, 0x11, 0x93, 0x55, 0x30, 0xc5, 0x17, 0xc0, 0x97, 34 | 0xcf, 0x5d, 0xc7, 0x0e, 0x25, 0xcb, 0x9d, 0x87, 0x8e, 0x80, 0x2d, 0xae, 0xee, 0x0a, 0xa1, 0xfd, 35 | 0xd7, 0xc8, 0x9c, 0x82, 0x0b, 0xcd, 0x16, 0x4d, 0x95, 0x76, 0x17, 0x33, 0x6d, 0x54, 0x0b, 0x3c, 36 | 0x8e, 0x4a, 0xd1, 0xbe, 0xcc, 0xa8, 0xdc, 0x57, 0x69, 0xc6, 0xe9, 0x32, 0x13, 0x07, 0x5b, 0xf0, 37 | 0x46, 0x6d, 0x73, 0xb7, 0x3c, 0xcf, 0x05, 0x61, 0x1b, 0x25, 0x89, 0x30, 0x65, 0xc0, 0x25, 0x84, 38 | 0x04, 0xc7, 0x5d, 0xa2, 0xed, 0x5f, 0x9e, 0x8f, 0xd5, 0x8a, 0x72, 0x7e, 0x66, 0x53, 0xfd, 0x03, 39 | 0xde, 0xea, 0x17, 0x68, 0xff, 0xec, 0x52, 0x95, 0x35, 0x29, 0xa6, 0xc9, 0xba, 0x15, 0x3d, 0x4b, 40 | 0xfa, 0x6f, 0xa9, 0x71, 0xc4, 0x15, 0xa6, 0xc3, 0xe2, 0xaf, 0xfe, 0x40, 0xb1, 0x2c, 0xd6, 0xb4, 41 | 0xb3, 0x38, 0x9d, 0x55, 0xab, 0xa2, 0xde, 0xcc, 0x4d, 0x62, 0xc7, 0xed, 0x97, 0x05, 0x26, 0x77, 42 | 0x33, 0x6c, 0x60, 0x1d, 0x35, 0xba, 0xd0, 0x3f, 0x1c, 0x8e, 0x1e, 0xe4, 0xd1, 0x43, 0x5b, 0x90, 43 | 0xea, 0x43, 0x41, 0x17, 0x32, 0x92, 0x21, 0x59, 0x8c, 0x16, 0xe8, 0x4b, 0x5a, 0x89, 0xfd, 0x8c, 44 | 0xfd, 0xb8, 0xd3, 0x17, 0x41, 0x40, 0x43, 0x40, 0x0a, 0xcb, 0x0d, 0x40, 0x31, 0x2a, 0x34, 0xd7, 45 | 0x1f, 0xcc, 0x1d, 0x67, 0x52, 0xec, 0xfe, 0xdb, 0xce, 0x6e, 0x11, 0x1a, 0x60, 0x90, 0x38, 0xdb, 46 | 0x54, 0xd8, 0x16, 0xb1, 0xb2, 0xfe, 0x86, 0x12, 0xa3, 0xba, 0x87, 0x68, 0x9d, 0x24, 0xd6, 0x3f, 47 | 0xe3, 0xf8, 0x35, 0x51, 0xf4, 0x81, 0x84, 0xb1, 0x30, 0x46, 0xe0, 0xde, 0x55, 0x81, 0x54, 0xc7, 48 | }, 49 | { 50 | 0x01, 0x00, 0x01, 0x00, 51 | }, 52 | { 53 | 0x38, 0x3c, 0x11, 0x5f, 0xe3, 0x79, 0x72, 0x17, 0xed, 0xed, 0x2d, 0xdf, 0x33, 0x0b, 0x3e, 0xc6, 54 | 0x55, 0xa4, 0xee, 0x00, 0x29, 0x7a, 0x08, 0x20, 0xe8, 0xaa, 0xe5, 0xc3, 0x0d, 0x46, 0x29, 0x64, 55 | 0x42, 0x23, 0x9c, 0x02, 0x38, 0xc9, 0x51, 0x04, 0xe4, 0xa0, 0xcb, 0x82, 0x24, 0x48, 0xca, 0xa8, 56 | 0x12, 0x76, 0x00, 0x5d, 0xce, 0xff, 0xe4, 0x69, 0x1f, 0xca, 0xcf, 0x99, 0x69, 0xa5, 0x7e, 0xb3, 57 | 0x40, 0x4a, 0x38, 0xbf, 0x29, 0x05, 0x71, 0xb4, 0xeb, 0x29, 0xf1, 0x42, 0xb7, 0xf4, 0xe0, 0xeb, 58 | 0xf0, 0xd0, 0x07, 0xf3, 0x77, 0xb6, 0x79, 0xde, 0x71, 0xfa, 0xff, 0x9e, 0x2a, 0xb8, 0x7c, 0x37, 59 | 0xd7, 0xa4, 0x1a, 0x6a, 0x5b, 0xcd, 0x4b, 0x2c, 0x30, 0xf7, 0x88, 0xac, 0xc1, 0x9f, 0xd5, 0xf3, 60 | 0x7e, 0xda, 0x17, 0x0c, 0x11, 0x64, 0xe2, 0x78, 0x93, 0x1d, 0xd8, 0xe8, 0x19, 0x0d, 0xad, 0x3f, 61 | 0x02, 0xd9, 0x79, 0x1c, 0xc1, 0xb4, 0x5c, 0xa0, 0x8d, 0xd9, 0xb5, 0x1b, 0xda, 0x12, 0x3f, 0xb2, 62 | 0x09, 0x73, 0x3f, 0x0b, 0x16, 0xc9, 0x2c, 0x78, 0xf7, 0x18, 0x64, 0x44, 0xd5, 0x19, 0x9a, 0xfe, 63 | 0x41, 0xca, 0x27, 0xb3, 0x65, 0x58, 0x23, 0xc7, 0x6a, 0x2a, 0x7e, 0xa0, 0x21, 0x62, 0x90, 0x5e, 64 | 0x58, 0xad, 0xd9, 0x00, 0xc8, 0x23, 0xfb, 0x1f, 0x5c, 0x11, 0x7e, 0x53, 0x44, 0x19, 0x62, 0xe2, 65 | 0x25, 0x2d, 0xe5, 0x97, 0x15, 0x11, 0xe7, 0x29, 0xb4, 0xa2, 0xe1, 0xd3, 0xe6, 0x90, 0x34, 0x36, 66 | 0x7f, 0xce, 0x05, 0x71, 0x32, 0x07, 0x4d, 0x3a, 0x96, 0xc1, 0x45, 0x2c, 0x8d, 0xbc, 0x38, 0x02, 67 | 0x36, 0x9d, 0x7d, 0xd7, 0x42, 0xc7, 0x16, 0x37, 0xb7, 0x4c, 0xd2, 0x2d, 0xbe, 0x89, 0x31, 0xca, 68 | 0x46, 0x55, 0xc0, 0x05, 0x74, 0x36, 0x4f, 0xca, 0x2f, 0x51, 0x7b, 0xc7, 0x3d, 0xe9, 0x3a, 0x6a, 69 | }, 70 | { 71 | 0x9e, 0x6e, 0x79, 0x4b, 0x7c, 0xe1, 0xfc, 0x83, 0x33, 0x8b, 0x21, 0xfe, 0x87, 0xff, 0xd7, 0x84, 72 | 0x6f, 0x14, 0xd9, 0xec, 0xa2, 0x0b, 0xb7, 0xaf, 0x2e, 0xac, 0x54, 0x26, 0x4e, 0x2b, 0x1d, 0xaf, 73 | }, 74 | 256, 75 | 4, 76 | 256, 77 | 32, 78 | }, 79 | }; 80 | 81 | 82 | sev_status_t rsa_utest(void) 83 | { 84 | sev_status_t status = SEV_STATUS_SUCCESS; 85 | uint32_t index = 0; 86 | 87 | for (index = 0; index < ARRAY_LENGTH(RSAPSSVector); index++) 88 | { 89 | status = rsa_pss_verify(RSAPSSVector[index].Hash, 90 | RSAPSSVector[index].HashLen, 91 | RSAPSSVector[index].Modulus, 92 | RSAPSSVector[index].ModulusLen, 93 | RSAPSSVector[index].Exp, 94 | RSAPSSVector[index].ExpLen, 95 | RSAPSSVector[index].Signature); 96 | if (status != SEV_STATUS_SUCCESS) 97 | { 98 | break; 99 | } 100 | } 101 | 102 | if (status != SEV_STATUS_SUCCESS) 103 | { 104 | SEV_TRACE("rsa_utest failed...\n"); 105 | SEV_TRACE_EX(status, index, 0, 0); 106 | } 107 | else 108 | { 109 | SEV_TRACE("rsa_utest succeed!\n"); 110 | } 111 | 112 | return status; 113 | } 114 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/rsa_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef RSA_UTEST_H 4 | #define RSA_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t rsa_utest(void); 12 | 13 | #endif /* RSA_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/secure_ops.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "secure_ops.h" 8 | 9 | int secure_compare(const void *left, const void *right, size_t size) 10 | { 11 | int result = 0; 12 | const uint8_t *l = left, *r = right; 13 | size_t i = 0; 14 | 15 | if (!l || !r) 16 | { 17 | result = 0x200; /* (0x200 + 0xff >> 8) = 2 */ 18 | goto end; 19 | } 20 | 21 | for (i = 0; i < size; i++) 22 | { 23 | result |= l[i] ^ r[i]; 24 | } 25 | 26 | end: 27 | return (result + 0xff) >> 8; // 0=equal, 1=not-equal, 2=error 28 | } 29 | 30 | int secure_array_compare_le(const void *left, const void *right, size_t size) 31 | { 32 | uint8_t gt = 0; 33 | uint8_t eq = 1; 34 | const uint8_t *l = left, *r = right; 35 | size_t i = size; 36 | 37 | /* Compare the numbers */ 38 | while (i != 0) 39 | { 40 | i--; 41 | gt |= ((r[i] - l[i]) >> 8) & eq; 42 | eq &= ((r[i] ^ l[i]) - 1) >> 8; 43 | } 44 | 45 | return (2 - (gt + eq + eq)); // 0=equal, 1=left>right, 2=left 0) 51 | { 52 | // MEHDI: Statements below are true only when this function is declared inline. 53 | // You can safely use memset here without worrying from being optimized. 54 | // Optimization happens when memset done on a memory just before getting 55 | // freed or going out of scope. 56 | //#ifdef __STDC_LIB_EXT1__ 57 | // /* Use memset_s() from C11 which cannot be optimized away. */ 58 | // memset_s(buffer, 0, size); 59 | //#elif defined(__GNUC__) || defined(__clang__) 60 | // /* 61 | // * Define a memory clobber to prevent the memset() from being optimized 62 | // * away. 63 | // */ 64 | memset(buffer, 0, size); 65 | // __asm__ __volatile__("" : : "r" (buffer) : "memory"); 66 | //#else 67 | // /* Zero the data by accessing it through a volatile pointer */ 68 | // volatile char *p = buffer; 69 | // size_t len = size; 70 | // 71 | // while (len--) *p++ = 0; 72 | //#endif 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/secure_ops.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SECURE_OPS_H 4 | #define SECURE_OPS_H 5 | 6 | /** 7 | * Constant-time implementation of memcmp(). Use this to validate security- 8 | * sensitive data. 9 | * 10 | * Returns 0 if left == right, 1 if left != right, 2 if error. 11 | */ 12 | int secure_compare(const void *left, const void *right, size_t size); 13 | 14 | /** 15 | * Generic (and Little-Endian) implementation of BNSecureCompare. 16 | * Use this to validate security-sensitive data. 17 | * >> 8 because each element is uint8_t 18 | 19 | * Returns 0 if left == right, 1 if left > right, 2 if left < right. 20 | * 21 | * Example (returns 1 because the first element is larger): 22 | * const unsigned char b1[4] = {0, 51, 255, 200}; 23 | * const unsigned char b2[4] = {55, 99, 0, 200}; 24 | */ 25 | int secure_array_compare_le(const void *left, const void *right, size_t size); 26 | 27 | /** 28 | * Zero security-sensitive data buffers. This implementation is resistant to 29 | * dead store elimination by the compiler. 30 | */ 31 | void secure_memzero(void *buffer, size_t size); 32 | 33 | #endif /* SECURE_OPS_H */ 34 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/secure_ops_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "bignum.h" 6 | #include "secure_ops.h" 7 | #include "secure_ops_utest.h" 8 | #include "sev_trace.h" 9 | 10 | enum 11 | { 12 | SC_EQUAL = 0, 13 | SC_BIGGER = 1, 14 | SC_SMALLER = 2, 15 | }; 16 | 17 | static const uint8_t b01[4] = {50, 88, 1, 200}; 18 | static const uint8_t b02[4] = {50, 3, 1, 200}; 19 | 20 | static const uint8_t b11[4] = {50, 88, 1, 200}; 21 | static const uint8_t b12[4] = {50, 210, 1, 200}; 22 | 23 | static const uint8_t b21[4] = {50, 255, 0, 200}; 24 | static const uint8_t b22[4] = {50, 255, 0, 200}; 25 | 26 | static const uint8_t b31[4] = {0, 51, 100, 200}; 27 | static const uint8_t b32[4] = {55, 99, 50, 200}; 28 | 29 | static const uint8_t b41[4] = {0, 50, 100, 50}; 30 | static const uint8_t b42[4] = {50, 100, 50, 0}; 31 | 32 | static const uint8_t b51[4] = {0, 255, 100, 50}; 33 | static const uint8_t b52[4] = {255, 100, 50, 0}; 34 | 35 | static const uint8_t b61[4] = {0, 0, 0, 1}; 36 | static const uint8_t b62[4] = {0, 0, 0, 2}; 37 | static const uint8_t b63[4] = {0, 0, 0, 0}; 38 | 39 | sev_status_t secure_ops_utest(void) 40 | { 41 | sev_status_t status = SEV_STATUS_SUCCESS; 42 | 43 | if (secure_array_compare_le(b01, b02, 4) != SC_BIGGER || 44 | secure_array_compare_le(b11, b12, 4) != SC_SMALLER || 45 | secure_array_compare_le(b21, b22, 4) != SC_EQUAL || 46 | secure_array_compare_le(b31, b32, 4) != SC_BIGGER || 47 | secure_array_compare_le(b41, b42, 4) != SC_BIGGER || 48 | secure_array_compare_le(b51, b52, 4) != SC_BIGGER) 49 | { 50 | status = SEV_STATUS_INVALID_PARAM; 51 | goto end; 52 | } 53 | 54 | KC_BIGNUM x; 55 | KC_BIGNUM y; 56 | if (BNLoad(&x, b01, sizeof(b01)) != KC_OK || 57 | BNLoad(&y, b02, sizeof(b02)) != KC_OK || 58 | BNSecureCompare(&x, &y) != BN_BIGGER ) 59 | { 60 | status = SEV_STATUS_INVALID_PARAM; 61 | goto end; 62 | } 63 | 64 | if (BNLoad(&x, b11, sizeof(b11)) != KC_OK || 65 | BNLoad(&y, b12, sizeof(b12)) != KC_OK || 66 | BNSecureCompare(&x, &y) != BN_SMALLER) 67 | { 68 | status = SEV_STATUS_INVALID_PARAM; 69 | goto end; 70 | } 71 | 72 | if (BNLoad(&x, b21, sizeof(b21)) != KC_OK || 73 | BNLoad(&y, b22, sizeof(b22)) != KC_OK || 74 | BNSecureCompare(&x, &y) != BN_EQUAL) 75 | { 76 | status = SEV_STATUS_INVALID_PARAM; 77 | goto end; 78 | } 79 | 80 | if (BNLoad(&x, b31, sizeof(b31)) != KC_OK || 81 | BNLoad(&y, b32, sizeof(b32)) != KC_OK || 82 | BNSecureCompare(&x, &y) != BN_BIGGER) 83 | { 84 | status = SEV_STATUS_INVALID_PARAM; 85 | goto end; 86 | } 87 | 88 | if (BNLoad(&x, b41, sizeof(b41)) != KC_OK || 89 | BNLoad(&y, b42, sizeof(b42)) != KC_OK || 90 | BNSecureCompare(&x, &y) != BN_BIGGER) 91 | { 92 | status = SEV_STATUS_INVALID_PARAM; 93 | goto end; 94 | } 95 | 96 | if (BNLoad(&x, b51, sizeof(b51)) != KC_OK || 97 | BNLoad(&y, b52, sizeof(b52)) != KC_OK || 98 | BNSecureCompare(&x, &y) != BN_BIGGER) 99 | { 100 | status = SEV_STATUS_INVALID_PARAM; 101 | goto end; 102 | } 103 | 104 | if (BNLoad(&x, b61, sizeof(b61)) != KC_OK || /* x = 1 */ 105 | BNLoad(&y, b62, sizeof(b62)) != KC_OK || /* y = 2 */ 106 | BNSubtract(&x, &x, &y) != KC_OK || /* x = -1 */ 107 | BNLoad(&y, b61, sizeof(b61)) != KC_OK || /* y = 1 */ 108 | BNSecureCompare(&x, &y) != BN_EQUAL || /* ABS(-1) < ABS(1) */ 109 | BNSecureCompare(&y, &x) != BN_EQUAL || 110 | BNLoad(&y, b63, sizeof(b63)) != KC_OK || /* y = 0 */ 111 | BNSecureCompare(&x, &y) != BN_BIGGER || /* ABS(-1) < ABS(0) */ 112 | BNSecureCompare(&y, &x) != BN_SMALLER) 113 | { 114 | status = SEV_STATUS_INVALID_PARAM; 115 | goto end; 116 | } 117 | 118 | end: 119 | if (status != SEV_STATUS_SUCCESS) 120 | { 121 | SEV_TRACE("secure_ops_utest failed...\n"); 122 | SEV_TRACE_EX(status, 0, 0, 0); 123 | } 124 | else 125 | { 126 | SEV_TRACE("secure_ops_utest succeed!\n"); 127 | } 128 | 129 | return status; 130 | } 131 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/secure_ops_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SECURE_OPS_UTEST_H 4 | #define SECURE_OPS_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t secure_ops_utest(void); 12 | 13 | #endif /* SECURE_OPS_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_cert.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_CERT_H 4 | #define SEV_CERT_H 5 | 6 | #include 7 | #include 8 | 9 | #include "ecdsa.h" 10 | #include "rsa.h" 11 | #include "sev_status.h" 12 | 13 | enum sev_cert_usage 14 | { 15 | SEV_CERT_USAGE_ARK = 0x00, 16 | SEV_CERT_USAGE_ASK = 0x13, 17 | 18 | SEV_CERT_USAGE_INVALID = 0x1000, 19 | SEV_CERT_USAGE_OCA = 0x1001, 20 | SEV_CERT_USAGE_PEK = 0x1002, 21 | SEV_CERT_USAGE_PDH = 0x1003, 22 | SEV_CERT_USAGE_CEK = 0x1004, 23 | }; 24 | 25 | // every place uses this as a uint32_t because there's a circular reference 26 | // between this enum and sev_cert_sig in ecdsa.h/rsa.h. 27 | enum sev_cert_algo 28 | { 29 | SEV_CERT_ALGO_INVALID = 0x000, 30 | SEV_CERT_ALGO_RSA_SHA256 = 0x001, 31 | SEV_CERT_ALGO_ECDSA_SHA256 = 0x002, 32 | SEV_CERT_ALGO_ECDH_SHA256 = 0x003, 33 | 34 | SEV_CERT_ALGO_RSA_SHA384 = 0x101, 35 | SEV_CERT_ALGO_ECDSA_SHA384 = 0x102, 36 | SEV_CERT_ALGO_ECDH_SHA384 = 0x103, 37 | SEV_CERT_ALGO_LIMIT, 38 | }; 39 | 40 | typedef struct sev_cert_sig 41 | { 42 | uint32_t usage; 43 | uint32_t algo; 44 | union { 45 | rsa_sig_t rsa; 46 | ecdsa_sig_t ecdsa; 47 | } sig; 48 | } sev_cert_sig_t; 49 | 50 | typedef struct sev_cert_keypair 51 | { 52 | uint32_t usage; 53 | uint32_t algo; 54 | union { 55 | rsa_keypair_t rsa; 56 | ecc_keypair_t ecdsa; 57 | } keypair; 58 | } sev_cert_keypair_t; 59 | 60 | typedef struct sev_cert_pubkey 61 | { 62 | uint32_t usage; 63 | uint32_t algo; 64 | union { 65 | rsa_pubkey_t rsa; 66 | ecc_pubkey_t ecdsa; 67 | } key; 68 | } sev_cert_pubkey_t; 69 | 70 | typedef struct sev_cert_body 71 | { 72 | uint32_t version; 73 | uint8_t api_major; 74 | uint8_t api_minor; 75 | uint8_t reserved[2]; 76 | sev_cert_pubkey_t pubkey; 77 | } sev_cert_body_t; 78 | 79 | typedef struct sev_cert 80 | { 81 | sev_cert_body_t body; 82 | sev_cert_sig_t sig1; 83 | sev_cert_sig_t sig2; 84 | } sev_cert_t; 85 | 86 | /** 87 | * Check if a certificate has a valid public key. 88 | */ 89 | bool sev_cert_has_pubkey(const sev_cert_t *cert); 90 | 91 | /** 92 | * Validate the body metadata for the certificate. 93 | */ 94 | sev_status_t sev_cert_sanity_check(const sev_cert_t *cert, uint32_t expected_usage, 95 | uint32_t expected_algo); 96 | 97 | /** 98 | * Retrieve the public portion of the key pair. 99 | */ 100 | sev_status_t sev_cert_keypair_get_pubkey(const sev_cert_keypair_t *keypair, 101 | sev_cert_pubkey_t *pubkey); 102 | 103 | /** 104 | * Retrieve the public key of the certificate. 105 | */ 106 | sev_status_t sev_cert_get_pubkey(const sev_cert_t *cert, sev_cert_pubkey_t *pubkey); 107 | 108 | /** 109 | * Retrieve the signature of the certificate. 110 | */ 111 | sev_status_t sev_cert_get_sig1(const sev_cert_t *cert, sev_cert_sig_t *sig); 112 | sev_status_t sev_cert_get_sig2(const sev_cert_t *cert, sev_cert_sig_t *sig); 113 | 114 | /** 115 | * Set the public key of the certificate. 116 | */ 117 | sev_status_t sev_cert_set_pubkey(sev_cert_t *cert, const sev_cert_pubkey_t *pubkey); 118 | 119 | /** 120 | * Set the signature of the certificate. 121 | */ 122 | sev_status_t sev_cert_set_sig(sev_cert_t *cert, const sev_cert_sig_t *sig); 123 | 124 | /** 125 | * Add a signature to the cert using the given signing key. 126 | */ 127 | sev_status_t sev_cert_sign(sev_cert_t *cert, const sev_cert_keypair_t *key); 128 | 129 | /** 130 | * Initialize a sev_cert_t object. 131 | */ 132 | sev_status_t sev_cert_init(sev_cert_t *cert); 133 | 134 | /** 135 | * Generate and sign a certificate. 136 | */ 137 | sev_status_t sev_cert_create(sev_cert_t *cert, const sev_cert_pubkey_t *pubkey, 138 | const sev_cert_keypair_t *signing_key); 139 | 140 | /** 141 | * Validate the signature (XXX and possibly other things) on the 142 | * certificate. 143 | */ 144 | sev_status_t sev_cert_validate(const sev_cert_t *cert, 145 | const sev_cert_pubkey_t *signing_key); 146 | 147 | #endif /* SEV_CERT_H */ 148 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_cert_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "digest.h" 8 | #include "sev_cert.h" 9 | #include "sev_cert_utest.h" 10 | #include "sev_globals.h" 11 | #include "sev_plat.h" 12 | 13 | static sev_cert_t cert; 14 | static sev_cert_keypair_t keys; 15 | static sev_cert_pubkey_t pubkey; 16 | 17 | static sev_status_t generate_keypair(uint32_t usage, uint32_t algo, 18 | sev_cert_keypair_t *keys) 19 | { 20 | sev_status_t status = SEV_STATUS_SUCCESS; 21 | sev_cert_keypair_t kp; 22 | 23 | if (!keys /*|| !usage_is_valid(usage) || !algo_is_valid(algo)*/) 24 | { 25 | status = ERR_INVALID_PARAMS; 26 | goto end; 27 | } 28 | 29 | kp.usage = usage; 30 | kp.algo = algo; 31 | 32 | switch (algo) 33 | { 34 | case SEV_CERT_ALGO_RSA_SHA256: 35 | case SEV_CERT_ALGO_RSA_SHA384: 36 | status = ERR_UNIMPLEMENTED; 37 | goto end; 38 | case SEV_CERT_ALGO_ECDSA_SHA256: 39 | case SEV_CERT_ALGO_ECDH_SHA256: 40 | status = ecdsa_keypair_generate(&kp.keypair.ecdsa); 41 | break; 42 | default: 43 | status = SEV_STATUS_UNSUPPORTED; 44 | goto end; 45 | } 46 | 47 | if (status != SEV_STATUS_SUCCESS) 48 | goto end; 49 | 50 | memcpy(keys, &kp, sizeof(*keys)); 51 | 52 | end: 53 | return status; 54 | } 55 | 56 | static sev_status_t sev_cert_ecdsa_utest(void) 57 | { 58 | sev_status_t status = SEV_STATUS_SUCCESS; 59 | 60 | status = generate_keypair(SEV_CERT_USAGE_OCA, SEV_CERT_ALGO_ECDSA_SHA256, &keys); 61 | if (status != SEV_STATUS_SUCCESS) 62 | goto end; 63 | 64 | status = sev_cert_keypair_get_pubkey(&keys, &pubkey); 65 | if (status != SEV_STATUS_SUCCESS) 66 | goto end; 67 | 68 | status = sev_cert_create(&cert, &pubkey, &keys); 69 | if (status != SEV_STATUS_SUCCESS) 70 | goto end; 71 | 72 | status = sev_cert_validate(&cert, &pubkey); 73 | 74 | end: 75 | return status; 76 | } 77 | 78 | static sev_status_t oca_utest(sev_t *sev) 79 | { 80 | sev_status_t status = SEV_STATUS_SUCCESS; 81 | 82 | if (!sev) 83 | { 84 | status = ERR_INVALID_PARAMS; 85 | goto end; 86 | } 87 | 88 | status = sev_oca_generate(&sev->sev.identity); 89 | if (status != SEV_STATUS_SUCCESS) 90 | goto end; 91 | 92 | status = sev_cert_validate(&sev->sev.identity.persistent.oca_cert, 93 | &sev->sev.identity.persistent.oca_cert.body.pubkey); 94 | 95 | end: 96 | return status; 97 | } 98 | 99 | static sev_status_t pek_utest(sev_t *sev) 100 | { 101 | sev_status_t status = SEV_STATUS_SUCCESS; 102 | sev_cert_pubkey_t *cek_pubkey = &pubkey; 103 | 104 | if (!sev || !sev_cert_has_pubkey(&sev->sev.identity.persistent.oca_cert)) 105 | { 106 | status = ERR_INVALID_PARAMS; 107 | goto end; 108 | } 109 | 110 | status = sev_cek_derive(&sev->sev.identity); 111 | if (status != SEV_STATUS_SUCCESS) 112 | goto end; 113 | 114 | status = sev_pek_generate(&sev->sev.identity); 115 | if (status != SEV_STATUS_SUCCESS) 116 | goto end; 117 | 118 | status = sev_cert_keypair_get_pubkey(&sev->sev.identity.cek, cek_pubkey); 119 | if (status != SEV_STATUS_SUCCESS) 120 | goto end; 121 | 122 | status = sev_cert_validate(&sev->sev.identity.persistent.pek_cert, cek_pubkey); 123 | if (status != SEV_STATUS_SUCCESS) 124 | goto end; 125 | 126 | status = sev_cert_validate(&sev->sev.identity.persistent.pek_cert, 127 | &sev->sev.identity.persistent.oca_cert.body.pubkey); 128 | 129 | end: 130 | return status; 131 | } 132 | 133 | static sev_status_t pdh_utest(sev_t *sev) 134 | { 135 | sev_status_t status = SEV_STATUS_SUCCESS; 136 | 137 | if (!sev || !sev_cert_has_pubkey(&sev->sev.identity.persistent.pek_cert)) 138 | { 139 | status = ERR_INVALID_PARAMS; 140 | goto end; 141 | } 142 | 143 | status = sev_pdh_generate(&sev->sev.identity); 144 | if (status != SEV_STATUS_SUCCESS) 145 | goto end; 146 | 147 | status = sev_cert_validate(&sev->sev.identity.persistent.pdh_cert, 148 | &sev->sev.identity.persistent.pek_cert.body.pubkey); 149 | 150 | end: 151 | return status; 152 | } 153 | 154 | static sev_status_t oca_digest_utest(sev_t *sev) 155 | { 156 | sev_status_t status = SEV_STATUS_SUCCESS; 157 | static digest_sha_ctx_t ctx; /* Static to not waste stack space */ 158 | static digest_sha_t last, current; /* Static to not waste stack space */ 159 | size_t length = 0, i = 0; 160 | sev_cert_body_t *body = NULL; 161 | 162 | if (!sev) 163 | { 164 | status = ERR_INVALID_PARAMS; 165 | goto end; 166 | } 167 | 168 | status = sev_oca_generate(&sev->sev.identity); 169 | if (status != SEV_STATUS_SUCCESS) 170 | goto end; 171 | 172 | body = &sev->sev.identity.persistent.oca_cert.body; 173 | memset(¤t, 0, sizeof(current)); 174 | 175 | for (i = 0; i < 100; i++) 176 | { 177 | memcpy(&last, ¤t, sizeof(last)); 178 | 179 | status = digest_sha_init(&ctx, SHA_TYPE_256); 180 | if (status != SEV_STATUS_SUCCESS) 181 | goto end; 182 | 183 | status = digest_sha_update(&ctx, body, sizeof(*body)); 184 | if (status != SEV_STATUS_SUCCESS) 185 | goto end; 186 | 187 | status = digest_sha_final(&ctx, ¤t, &length); 188 | if (status != SEV_STATUS_SUCCESS) 189 | goto end; 190 | 191 | if (i > 0 && memcmp(&last, ¤t, sizeof(last)) != 0) 192 | { 193 | status = ERR_UNKNOWN; 194 | goto end; 195 | } 196 | } 197 | 198 | end: 199 | return status; 200 | } 201 | 202 | sev_status_t sev_cert_utest(void) 203 | { 204 | sev_status_t status = SEV_STATUS_SUCCESS; 205 | 206 | status = sev_cert_ecdsa_utest(); 207 | if (status != SEV_STATUS_SUCCESS) 208 | goto end; 209 | 210 | status = oca_digest_utest(&gSev); 211 | if (status != SEV_STATUS_SUCCESS) 212 | goto end; 213 | 214 | status = oca_utest(&gSev); 215 | if (status != SEV_STATUS_SUCCESS) 216 | goto end; 217 | 218 | status = pek_utest(&gSev); 219 | if (status != SEV_STATUS_SUCCESS) 220 | goto end; 221 | 222 | status = pdh_utest(&gSev); 223 | 224 | end: 225 | return status; 226 | } 227 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_cert_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_CERT_UTEST_H 4 | #define SEV_CERT_UTEST_H 5 | 6 | #include "sev_status.h" 7 | 8 | sev_status_t sev_cert_utest(void); 9 | 10 | #endif /* SEV_CERT_UTEST_H */ 11 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_channel.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_CHANNEL_H 4 | #define SEV_CHANNEL_H 5 | 6 | #include "cipher.h" 7 | #include "hmac.h" 8 | #include "sev_status.h" 9 | 10 | #define MASTER_SECRET_SIZE_BYTES (16) 11 | #define NONCE_SIZE_BYTES (16) 12 | 13 | #define SEV_TEK_SIZE_BYTES (CIPHER_AES128_KEY_SIZE_BYTES) 14 | #define SEV_TIK_SIZE_BYTES (SEV_TEK_SIZE_BYTES) 15 | #define SEV_TRANSPORT_KEYS_SIZE_BYTES ((SEV_TEK_SIZE_BYTES)+(SEV_TIK_SIZE_BYTES)) 16 | #define SEV_KEK_SIZE_BYTES (CIPHER_AES128_KEY_SIZE_BYTES) 17 | #define SEV_KIK_SIZE_BYTES (SEV_KEK_SIZE_BYTES) 18 | 19 | typedef struct sev_measurement 20 | { 21 | hmac_sha256_t measurement; 22 | uint8_t mnonce[NONCE_SIZE_BYTES]; 23 | } sev_measurement_t; 24 | 25 | typedef struct sev_trusted_channel 26 | { 27 | uint8_t master_secret[MASTER_SECRET_SIZE_BYTES]; 28 | cipher_aes_key_t tek; 29 | uint8_t tik[SEV_TIK_SIZE_BYTES]; 30 | uint8_t nonce[NONCE_SIZE_BYTES]; 31 | sev_measurement_t measurement; /* launch measure to launch secret */ 32 | } sev_trusted_channel_t; 33 | 34 | typedef struct sev_session 35 | { 36 | uint8_t nonce[NONCE_SIZE_BYTES]; 37 | uint8_t wrap_tk[SEV_TRANSPORT_KEYS_SIZE_BYTES]; 38 | cipher_aes_iv_t wrap_iv; 39 | hmac_sha256_t wrap_mac; 40 | hmac_sha256_t policy_mac; 41 | } sev_session_t; 42 | 43 | typedef struct sev_packet_header 44 | { 45 | uint32_t flags; 46 | cipher_aes_iv_t iv; 47 | hmac_sha256_t mac; 48 | } sev_packet_header_t; 49 | 50 | typedef enum sev_channel_ctx 51 | { 52 | SEV_CHANNEL_CTX_SECRET = 0x01, 53 | SEV_CHANNEL_CTX_DATA = 0x02, 54 | SEV_CHANNEL_CTX_VMSA = 0x03, 55 | SEV_CHANNEL_CTX_MEASURE = 0x04, 56 | } sev_channel_ctx_t; 57 | 58 | /** 59 | * Open the server end of the trusted channel (i.e. the receiver). 60 | * 61 | * Parameters: 62 | * keypair [in] server's DH keypair, 63 | * dh_cert [in] client's DH cert, 64 | * session [in] launch session object, 65 | * channel [out] stored channel parameters 66 | */ 67 | sev_status_t sev_channel_open_server(const sev_cert_keypair_t *keypair, 68 | const sev_cert_t *dh_cert, 69 | const sev_session_t *session, 70 | sev_trusted_channel_t *channel); 71 | 72 | /** 73 | * Open the client end of the trusted channel (i.e. the sender). 74 | * 75 | * Parameters: 76 | * policy [in] guest policy 77 | * keypair [in] client's DH keypair, 78 | * dh_cert_paddr [in] server's DH cert, 79 | * session [out] migrate session object, 80 | * channel [out] generated channel parameters 81 | */ 82 | sev_status_t sev_channel_open_client(uint32_t policy, 83 | const sev_cert_keypair_t *keypair, 84 | const sev_cert_t *dh_cert, 85 | sev_session_t *session, 86 | sev_trusted_channel_t *channel); 87 | 88 | /** 89 | * Close the trusted channel and delete all channel parameters. 90 | * 91 | * Parameters: 92 | * channel [in] channel parameters 93 | */ 94 | void sev_channel_close(sev_trusted_channel_t *channel); 95 | 96 | /** 97 | * Extract a secret from the trusted channel. The secret will be extracted to 98 | * 'buffer' in-place. 99 | * 100 | * Parameters: 101 | * buffer [in/out] input data/extracted secret, 102 | * size [in] buffer size, 103 | * uncompressed_size [in] size of uncompressed secret, 104 | * channel [in] SEV trusted channel parameters, 105 | * header [in] SEV packet header object. 106 | */ 107 | sev_status_t sev_channel_extract_secret(void *buffer, size_t size, 108 | size_t uncompressed_size, 109 | const sev_trusted_channel_t *channel, 110 | const sev_packet_header_t *header); 111 | 112 | #endif /* SEV_CHANNEL_H */ 113 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_dispatch.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_DISPATCH_H 4 | #define SEV_DISPATCH_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | #include "sev_mcmd.h" 11 | 12 | /** 13 | * Dispatches an SEV slave command. 14 | * 15 | * The 'sev_svc_slave()' function calls this function. 16 | */ 17 | sev_status_t sev_dispatch_slave(void *pCmd); 18 | 19 | /** 20 | * Dispatches an SEV API (aka master) command. 21 | * 22 | * The 'sev_svc_master()' function calls this function. Once called, 23 | * this function performs the following steps: 24 | * 25 | * 1. Reads the command ID from 'CmdResp' to determine which command 26 | * is being called. 27 | * 28 | * 2. Validates the pointer+length of the command buffer. 29 | * 30 | * 3. Copies the command buffer (but not any data that the command 31 | * buffer may point to) into private memory. 32 | * 33 | * 4. Passes the command buffer to the correct command handler. 34 | * 35 | * 5. Writes the returned status code into the CmdResp 36 | * register. (XXX Should this be done in the sev_svc.h functions 37 | * instead?) 38 | * 39 | * 6. Returns. 40 | */ 41 | sev_status_t sev_dispatch_master(sev_mcmd_id_t CmdId, uint32_t CmdBuf_Lo, uint32_t CmdBuf_Hi); 42 | 43 | /** 44 | * Function that wipes out the dispatch master table, except for 45 | * the command ID provided as a parameter. This is used by DLFW_EX_CONTINUED 46 | * in the awkward case where the new/current FW can't abide the system 47 | * configuration, but the Boot Loader can't restore the old FW (1.0.0.4 to 48 | * 1.0.0.6 boot loaders had a bug in the RESTORE subop for cache_new_image.) 49 | * Rather than add code to every command to check for the rare case, we 50 | * instead levarage the existing tests in sev_dispatch_master() to prevent 51 | * execution of any command except DLFW_EX, which will expect the committed 52 | * old FW to be restored by the HV. 53 | */ 54 | sev_status_t clear_dispatch_master(sev_mcmd_id_t CmdId); 55 | 56 | #endif /* SEV_DISPATCH_H */ 57 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_errors.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include "sev_errors.h" 4 | #include "sev_trace.h" 5 | 6 | void sev_fatal_error(const char *filename, const char *function, int line) 7 | { 8 | SEV_TRACE("SEV ASSERT!!!"); 9 | SEV_TRACE(filename); 10 | SEV_TRACE(function); 11 | SEV_TRACE_EX(line, 0, 0, 0); 12 | 13 | /* Soft hang here */ 14 | while (1); 15 | } 16 | 17 | #ifdef DBG_ASSERT 18 | void sev_assert(bool condition) 19 | { 20 | if (!condition) 21 | { 22 | sev_fatal_error(__FILE__, __FUNCTION__, __LINE__); 23 | } 24 | } 25 | #endif /* DBG_ASSERT */ 26 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_errors.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_ERRORS_H 4 | #define SEV_ERRORS_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "sev_status.h" 11 | 12 | #define is_external_status(e) ((e) < SEV_STATUS_LIMIT) 13 | #define is_internal_error(e) ((e) >= ERR_UNKNOWN) 14 | #define is_hardware_error(e) ((e) >= ERR_HAL_SLAVE_DIE) 15 | 16 | // Note: To catch a programmer's coding mistakes, debug assertion would be more appropriate 17 | void sev_fatal_error(const char *filename, const char *function, int line); 18 | 19 | #ifdef DBG_ASSERT 20 | void sev_assert(bool condition); 21 | #else 22 | #define sev_assert(condition) ((void)0) 23 | #endif 24 | 25 | #define sev_panic() sev_fatal_error(__FILE__, __FUNCTION__, __LINE__) 26 | 27 | inline void wait_for_debugger(void) 28 | { 29 | volatile bool wait = true; 30 | 31 | while (wait); 32 | } 33 | 34 | #endif /* SEV_ERRORS_H */ 35 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_es.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_ES_H 4 | #define SEV_ES_H 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include "pool_u32.h" 11 | #include "sev_status.h" 12 | 13 | /** 14 | * http://twiki.amd.com/twiki/bin/view/ZPArch/VMSAVMEncryptedSaveArea 15 | * Offsets in the 4K vmsa page 16 | */ 17 | #define VMSA_RIP (0x178) /* For VMSA tweak */ 18 | #define VMSA_RSP (0x1D8) /* For VMSA tweak */ 19 | #define VMSA_RAX (0x1F8) /* For VMSA tweak */ 20 | #define VMSA_GUEST_TSC_SCALE (0x2F0) 21 | #define VMSA_GUEST_TSC_OFFSET (0x2F8) 22 | #define VMSA_REG_PROT_NONCE (0x300) 23 | #define VMSA_RCX (0x308) /* For VMSA tweak */ 24 | #define VMSA_RDX (0x310) /* For VMSA tweak */ 25 | #define VMSA_RBX (0x318) /* For VMSA tweak */ 26 | #define VMSA_RBP (0x328) /* For VMSA tweak */ 27 | #define VMSA_RSI (0x330) /* For VMSA tweak */ 28 | #define VMSA_RDI (0x338) /* For VMSA tweak */ 29 | #define VMSA_R8 (0x340) /* For VMSA tweak */ 30 | #define VMSA_R9 (0x348) /* For VMSA tweak */ 31 | #define VMSA_R10 (0x350) /* For VMSA tweak */ 32 | #define VMSA_R11 (0x358) /* For VMSA tweak */ 33 | #define VMSA_R12 (0x360) /* For VMSA tweak */ 34 | #define VMSA_R13 (0x368) /* For VMSA tweak */ 35 | #define VMSA_R14 (0x370) /* For VMSA tweak */ 36 | #define VMSA_R15 (0x378) /* For VMSA tweak */ 37 | #define VMSA_SEV_FEATURES (0x3B0) 38 | #define VMSA_FPREG_X87 (0x420) /* For VMSA tweak */ 39 | #define VMSA_FPREG_XMM (0x470) /* For VMSA tweak */ 40 | #define VMSA_FPREG_YMM (0x570) /* For VMSA tweak */ 41 | #define VMSA_FPREG_KI (0x980) /* For VMSA tweak */ 42 | #define VMSA_FPREG_ZMMHI (0x9C0) /* For VMSA tweak */ 43 | #define VMSA_FPREG_HIZMM (0xBC0) /* For VMSA tweak */ 44 | 45 | #define VMSA_OPAQUE_SIZE (0x380) 46 | #define VMSA_CRC_SIZE (0xFC0) /* Must match uCode, CRC doesn't apply to whole page because 'history' */ 47 | #define VMSA_SIZE (PAGE_SIZE_4K) 48 | 49 | #define VMSA_TWEAK_BITMAP_SIZE (VMSA_SIZE/(sizeof(uint64_t)*BITS_PER_BYTE)) /* 64 */ 50 | 51 | /* http://twiki.amd.com/twiki/bin/view/ZPArch/SEV_FEATURES */ 52 | #define VMSA_SEV_FEATURES_SECURE_TSC (1ULL << 9) /* Secure TSC feature is enabled for this guest */ 53 | #define VMSA_SEV_FEATURES_VMSA_REG_PROT (1ULL << 14) /* VMSA Register Protection is enabled for this guest */ 54 | #define VMSA_SEV_FEATURES_SECURE_TSC_ENABLED(vmsa) ((*(uint64_t *)((uint8_t *)vmsa + VMSA_SEV_FEATURES)) & VMSA_SEV_FEATURES_SECURE_TSC) 55 | #define VMSA_SEV_FEATURES_VMSA_REG_PROT_ENABLED(vmsa) ((*(uint64_t *)((uint8_t *)vmsa + VMSA_SEV_FEATURES)) & VMSA_SEV_FEATURES_VMSA_REG_PROT) 56 | 57 | /* 58 | * Use forward declarations here to avoid circular dependencies on 59 | * sev_plat.h/sev_guest.h 60 | */ 61 | typedef struct sev_guest sev_guest_t; 62 | typedef struct sev sev_t; 63 | 64 | typedef struct sev_es_platform 65 | { 66 | pool_vcpu_t crc32_pool; 67 | uint64_t tmr_addr_start; 68 | uint64_t tmr_addr_size; 69 | uint64_t start_pool_addr; 70 | uint64_t start_crc_addr; 71 | uint32_t pool_block_size; 72 | uint32_t crc_block_size; 73 | bool enable_crc64; 74 | uint64_t reserved_tmr_base; /* TMR is reserved but not initialized */ 75 | uint64_t reserved_tmr_end; 76 | } sev_es_platform_t; 77 | 78 | typedef struct sev_es_guest 79 | { 80 | size_t num_vcpus; 81 | uint32_t head_index; 82 | uint32_t tail_index; 83 | } sev_es_guest_t; 84 | 85 | static inline bool sev_es_is_initialized(sev_es_platform_t *es) 86 | { 87 | return es != NULL ? es->crc32_pool.is_initialized : false; 88 | } 89 | 90 | /** 91 | * Setup a VMSA for use in a guest. 92 | * 93 | * A VMSA is the VMCB register save state area. 94 | * 95 | * This function takes the following steps: 96 | * 97 | * 1. Allocates a 32bit block from the CRC32 pool. 98 | * 99 | * 2. Writes the _system physical address_ of the allocated 32bit 100 | * word into the VCPU. 101 | * 102 | * 3. Calculates the CRC32 checksum of the VCPU and saves it to the 103 | * allocated 32bit block. 104 | * 105 | * Parameters: 106 | * es : [in/out] SEV-ES platform object, 107 | * guest : [in/out] SEV guest object, 108 | * psp_addr : [in/out] PSP-local buffer containing the VMSA, 109 | * length : [in] Length of the VMSA buffer. 110 | */ 111 | sev_status_t sev_es_setup_vmsa(sev_es_platform_t *es, sev_guest_t *guest, 112 | uint8_t *psp_addr, size_t length); 113 | 114 | /** 115 | * Validate VMSA in guest. 116 | * 117 | * A VMSA is the VMCB register save state area. 118 | * 119 | * This function takes the following steps: 120 | * 121 | * 1. Allocates a 32bit block from the CRC32 pool. 122 | * 123 | * 2. Writes the _system physical address_ of the allocated 32bit 124 | * word into the VCPU. 125 | * 126 | * 3. Calculates the CRC32 checksum of the VCPU and saves it to the 127 | * allocated 32bit block. 128 | * 129 | * Parameters: 130 | * es : [in/out] SEV-ES platform object, 131 | * guest : [in/out] SEV guest object, 132 | * psp_addr : [in/out] PSP-local buffer containing the VMSA, 133 | * length : [in] Length of the VMSA buffer. 134 | */ 135 | sev_status_t sev_es_validate_vmsa(sev_es_platform_t *es, sev_guest_t *guest, 136 | uint8_t *psp_addr, uint32_t length); 137 | 138 | /** 139 | * Returns false if SEV-ES is disabled for the platform and true if enabled. 140 | */ 141 | bool sev_es_platform_enabled(const sev_t *sev); 142 | 143 | /** 144 | * Returns false if SEV-ES is disabled for the guest and true if enabled. 145 | */ 146 | bool sev_es_guest_enabled(const sev_guest_t *guest); 147 | 148 | /** 149 | * Returns false if SEV-ES pool allocation is disabled for the guest and true if enabled. 150 | */ 151 | bool sev_es_allocation_guest_enabled(const sev_guest_t *guest); 152 | 153 | /** 154 | * Checks if an ASID is valid for use with SEV-ES 155 | * 156 | * Returns INVALID_ASID if the ASID is not in the proper range. 157 | */ 158 | sev_status_t sev_es_validate_asid(sev_guest_t *guest, size_t asid); 159 | 160 | /** 161 | * Reserve a Trusted Memory Region (TMR) 162 | */ 163 | sev_status_t sev_es_reserve_trusted_region(sev_es_platform_t *es, uint64_t base, size_t size); 164 | 165 | /** 166 | * Initialize a reserved Trusted Memory Region (TMR). The TMR must have 167 | * already been reserved with sev_es_reserve_trusted_region(). 168 | * 169 | * If the TMR has not been reserved, returns ERR_OUT_OF_RESOURCES. 170 | */ 171 | sev_status_t sev_es_init_trusted_region(sev_es_platform_t *es); 172 | 173 | /** 174 | * Free a Trusted Memory Region (TMR) 175 | */ 176 | sev_status_t sev_es_release_trusted_region(sev_es_platform_t *es); 177 | 178 | /** 179 | * Generate the bitmap to which the VMSA tweak will be applied. The kth bit of 180 | * the bitmap indicates that the kth quadword of the VMSA is tweaked 181 | */ 182 | void sev_es_create_vmsa_bitmap(uint8_t *bitmap); 183 | 184 | /** 185 | * Apply the XOR tweak to the VMSA 186 | */ 187 | void sev_es_apply_vmsa_bitmap(uint8_t *vmsa, uint8_t *bitmap); 188 | 189 | /** 190 | * Create the XOR tweak and apply it to the VMSA 191 | */ 192 | sev_status_t sev_es_vmsa_xor_tweak(uint8_t *vmsa, uint8_t *bitmap); 193 | 194 | #endif /* SEV_ES_H */ 195 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_extended_errors.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2023 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | /* Extended error codes used throughout SEV FW. 4 | * Each error code is unique, but arbitrary. 5 | * These values need to be documented elsewhere. 6 | * All we do here in this file is track allocation. 7 | */ 8 | 9 | #include "sev_status.h" 10 | 11 | extern uint64_t sev_error_stack; 12 | extern sev_status_t sev_error(sev_status_t status, uint16_t error_id); 13 | #define SEV_ERROR(status, error_id) sev_error(status, error_id) 14 | 15 | #define EXT_ERR_001 1 16 | #define EXT_ERR_002 2 17 | #define EXT_ERR_003 3 18 | #define EXT_ERR_004 4 19 | #define EXT_ERR_005 5 20 | #define EXT_ERR_006 6 21 | #define EXT_ERR_007 7 22 | #define EXT_ERR_008 8 23 | #define EXT_ERR_009 9 24 | #define EXT_ERR_010 10 25 | #define EXT_ERR_011 11 26 | #define EXT_ERR_012 12 27 | #define EXT_ERR_013 13 28 | #define EXT_ERR_014 14 29 | #define EXT_ERR_015 15 30 | #define EXT_ERR_016 16 31 | #define EXT_ERR_017 17 32 | #define EXT_ERR_018 18 33 | #define EXT_ERR_019 19 34 | #define EXT_ERR_020 20 35 | #define EXT_ERR_021 21 36 | #define EXT_ERR_022 22 37 | #define EXT_ERR_023 23 38 | #define EXT_ERR_024 24 39 | #define EXT_ERR_025 25 40 | #define EXT_ERR_026 26 41 | #define EXT_ERR_027 27 42 | #define EXT_ERR_028 28 43 | #define EXT_ERR_029 29 44 | #define EXT_ERR_030 30 45 | #define EXT_ERR_031 31 46 | #define EXT_ERR_032 32 47 | #define EXT_ERR_033 33 48 | #define EXT_ERR_034 34 49 | #define EXT_ERR_035 35 50 | #define EXT_ERR_036 36 51 | #define EXT_ERR_037 37 52 | #define EXT_ERR_038 38 53 | #define EXT_ERR_039 39 54 | #define EXT_ERR_040 40 55 | #define EXT_ERR_041 41 56 | #define EXT_ERR_042 42 57 | #define EXT_ERR_043 43 58 | #define EXT_ERR_044 44 59 | #define EXT_ERR_045 45 60 | #define EXT_ERR_046 46 61 | #define EXT_ERR_047 47 62 | #define EXT_ERR_048 48 63 | #define EXT_ERR_049 49 64 | #define EXT_ERR_050 50 65 | #define EXT_ERR_051 51 66 | #define EXT_ERR_052 52 67 | #define EXT_ERR_053 53 68 | #define EXT_ERR_054 54 69 | #define EXT_ERR_055 55 70 | #define EXT_ERR_056 56 71 | #define EXT_ERR_057 57 72 | #define EXT_ERR_058 58 73 | #define EXT_ERR_059 59 74 | #define EXT_ERR_060 60 75 | #define EXT_ERR_061 61 76 | #define EXT_ERR_062 62 77 | #define EXT_ERR_063 63 78 | #define EXT_ERR_064 64 79 | #define EXT_ERR_065 65 80 | #define EXT_ERR_066 66 81 | #define EXT_ERR_067 67 82 | #define EXT_ERR_068 68 83 | #define EXT_ERR_069 69 84 | #define EXT_ERR_070 70 85 | #define EXT_ERR_071 71 86 | #define EXT_ERR_072 72 87 | #define EXT_ERR_073 73 88 | #define EXT_ERR_074 74 89 | #define EXT_ERR_075 75 90 | #define EXT_ERR_076 76 91 | #define EXT_ERR_077 77 92 | #define EXT_ERR_078 78 93 | #define EXT_ERR_079 79 94 | #define EXT_ERR_080 80 95 | #define EXT_ERR_081 81 96 | #define EXT_ERR_082 82 97 | #define EXT_ERR_083 83 98 | #define EXT_ERR_084 84 99 | #define EXT_ERR_085 85 100 | #define EXT_ERR_086 86 101 | #define EXT_ERR_087 87 102 | #define EXT_ERR_088 88 103 | #define EXT_ERR_089 89 104 | #define EXT_ERR_090 90 105 | #define EXT_ERR_091 91 106 | #define EXT_ERR_092 92 107 | #define EXT_ERR_093 93 108 | #define EXT_ERR_094 94 109 | #define EXT_ERR_095 95 110 | #define EXT_ERR_096 96 111 | #define EXT_ERR_097 97 112 | #define EXT_ERR_098 98 113 | #define EXT_ERR_099 99 114 | #define EXT_ERR_100 100 115 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_fw_image.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2022 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_FW_IMAGE_H 4 | #define SEV_FW_IMAGE_H 5 | 6 | // ----------------------------------------------------------------------------- 7 | // SEV FW Image Header Format 8 | // ----------------------------------------------------------------------------- 9 | typedef struct SEV_FW_IMAGE_HEADER_T 10 | { 11 | uint8_t Nonce[16]; // [0x00] Unique image id 12 | uint32_t Cookie; // [0x10] Cookie for sanity checks 13 | uint32_t SizeFWSigned; // [0x14] Size of the FW to be included in signature in bytes 14 | uint32_t EncOption; // [0x18] 0 - Not encrypted, 1 - encrypted 15 | uint8_t IkekType; // [0x1C] 0 - iKEK-AMD is be used, non-zero - iKEK-OEM is used 16 | uint8_t Reserved0[3]; // [0x1D] *** RESERVED *** 17 | uint8_t EncParameters[16]; // [0x20] Encryption Parameters 18 | uint32_t SigOption; // [0x30] 0 - not signed, 1 - signed 19 | uint32_t SigAlgID; // [0x34] Signature algorithm ID 20 | uint8_t SigParameters[16]; // [0x38] Signature parameter 21 | uint32_t CompOption; // [0x48] 0 - Not compressed, 1 - compressed 22 | uint32_t SecPatchLevel; // [0x4C] Security patch level 23 | uint32_t UnCompImageSize; // [0x50] Uncompressed Image Size (only valid when comp enabled) 24 | uint32_t CompImageSize; // [0x54] Compressed Image Size (only valid when comp enabled) 25 | uint16_t FwType; // [0x58] SOC FW ID 26 | uint8_t HeaderVersion; // [0x5A] Header version 27 | uint8_t MeasurementOption; // [0x5B] Measurement Flag. 0 - not available, 1 - available 28 | uint8_t Reserved[4]; // [0x5C] Reserved. Must be 0 29 | uint32_t FWVersion; // [0x60] Off Chip Firmware Version 30 | uint32_t APUFamilyID; // [0x64] APU Family ID or SoC ID 31 | uint32_t FirmwareLoadAddr; // [0x68] Firmware Load address (default 0) 32 | uint32_t SizeImage; // [0x6C] Size of entire signed image including key tokens 33 | uint32_t SizeFWUnSigned; // [0x70] Size of Un-signed portion of the FW (usually 0) 34 | uint32_t FirmwareSplitAddr; // [0x74] Joining point of combined FWs (e.g. Nwd/Swd split address) 35 | uint32_t SigFlags; // [0x78] Flags for FW signing options, app permissions etc. 36 | uint8_t FwTypeLegacy; // [0x7C] Module Fw Type. Must match Directory Table Entry Type 37 | uint8_t FwSubType; // [0x7D] FwSubType (must match the value in Unified FW table for specific FW) 38 | uint8_t SubProgram; // [0x7E] indicates sub-program for which FW is applied 39 | uint8_t SigLevel; // [0x7F] signature level (0 - level 0 (normal) header, 1 - level 1 etc.) 40 | uint8_t EncKey[16]; // [0x80] Encryption Key (Wrapped MEK) 41 | uint8_t SigningInfo[16]; // [0x90] Signing tool specific information 42 | uint32_t BlFirmwareVersion; // [0xA0] Required BL Firmware Version 43 | uint8_t FwSpecificData[28]; // [0xA4-0xBF] (rest of) FW specific information 44 | uint8_t DebugEncKey[16]; // [0xC0] MEK wrapped with tKEK 45 | uint8_t Measurement[32]; // [0xD0] SHA256 of FW binary (without header and signature) 46 | uint8_t Reserved2[16]; // [0xF0] *** RESERVED *** 47 | } SEV_FW_IMAGE_HEADER; 48 | 49 | #endif /* SEV_FW_IMAGE_H */ 50 | 51 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_globals.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2018 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | 6 | #include "sev_globals.h" 7 | 8 | /* Included from /fw/common/ to access AMD root public key */ 9 | #include "psp_key_image.h" 10 | #include "dram_map.h" 11 | 12 | /* Note that gSev and gPersistent are completely unique to each socket and data 13 | is only shared between sockets through gpDram */ 14 | uint32_t gTotalDieNum = 0; 15 | uint32_t gCurrentDieID = 0xFFFFFFFF; 16 | sev_persistent_globals_t gPersistent; 17 | 18 | /* Note: moved from .bss to zero_init once section. */ 19 | sev_t gSev __attribute__((section ("init_once"), zero_init)); 20 | 21 | sev_rsvd_dram_t *gpDram __attribute__((section ("init_once"), zero_init)); 22 | 23 | /** 24 | * SEV_UAPP_SCRATCH_AREA can be used as a static buffer. 25 | * SEV user app scratch buffer, can be used as intermediate buffer for 26 | * compression, AES, SHA, etc. 27 | * 28 | * This buffer is NOT persistent. 29 | */ 30 | uint8_t gSevScratchBuf[SEV_SCRATCH_BUF_LEN] __attribute__((section ("scratch_space"), zero_init)); 31 | uint8_t *gpSevScratchBuf = gSevScratchBuf; 32 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_globals.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2018 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_GLOBALS_H 4 | #define SEV_GLOBALS_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_plat.h" 10 | 11 | extern uint32_t Image$$SEV_UAPP_STACK$$ZI$$Base; 12 | extern uint32_t Image$$SEV_UAPP_STACK$$ZI$$Limit; 13 | extern uint32_t Image$$SEV_UAPP_DATA$$ZI$$Base; 14 | extern uint32_t Image$$SEV_UAPP_DATA$$ZI$$Length; 15 | 16 | extern uint32_t gTotalDieNum; 17 | extern uint32_t gCurrentDieID; 18 | 19 | extern sev_persistent_globals_t gPersistent; 20 | extern sev_t gSev; 21 | 22 | /* There's a 20KB scratch area */ 23 | #define SEV_SCRATCH_BUF_LEN 0x5000 24 | extern uint8_t *gpSevScratchBuf; 25 | 26 | extern sev_rsvd_dram_t *gpDram; 27 | 28 | #endif /* SEV_GLOBALS_H */ 29 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_hal_interface.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_HAL_INTERFACE_H 4 | #define SEV_HAL_INTERFACE_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_status.h" 10 | 11 | #define MAX_CCDS (16) 12 | #define MAX_CCDS_RSDN (8) // FW_SUPPORTED_MAX_NUM_CCDS. Needs to stay power of 2 13 | #define MAX_CCDS_RS (16) // FW_SUPPORTED_MAX_NUM_CCDS. Needs to stay power of 2 14 | #define MAX_CCD_BITMASK ((1 << MAX_CCDS) - 1) /* 0xFFFF */ 15 | #define THREADS_PER_CORE (2) 16 | #define MAX_COMPLEXES (1) 17 | #define CCXS_PER_CCD_RS (1) 18 | #define CCXS_PER_CCD_RSDN (2) 19 | 20 | #define MAX_CCX_PER_SOCKET_SHIFT (16) // Maximum bits required to represent all the CCXs per socket. 21 | 22 | #define CCXS_ON_P0(ccxs) ((ccxs >> 0) & MAX_CCD_BITMASK) /* CCD Bit Mask on Socket 0. */ 23 | #define CCXS_ON_P1(ccxs) ((ccxs >> MAX_CCDS) & MAX_CCD_BITMASK) /* CCD Bit Mask on Socket 1. */ 24 | 25 | #define INVALID_ASID_BITS_PER_REG (32) 26 | #define INVALID_ASID_REG_SIZE (4) /* INVALID_ASID register size in bytes */ 27 | 28 | /** 29 | * Reports if a core is available on a specific die/socket 30 | */ 31 | bool is_core_enabled(uint32_t ccd, uint32_t coreid, uint32_t complex, uint32_t die); 32 | 33 | /** 34 | * Calculate the mask for the ASID register 35 | */ 36 | uint32_t asid_to_reg_mask(uint32_t asid, uint32_t *reg); 37 | 38 | /** 39 | * Mark an ASID valid on all cores on this die. 40 | */ 41 | sev_status_t mark_asid_valid(uint32_t asid, uint32_t ccd_mask); 42 | 43 | /** 44 | * Mark an ASID invalid on all cores on this die. 45 | */ 46 | sev_status_t mark_asid_invalid(uint32_t asid, uint32_t ccd_mask); 47 | 48 | /** 49 | * Mark all ASIDs valid on all cores on this die. 50 | */ 51 | sev_status_t mark_all_asids_valid(void); 52 | 53 | /** 54 | * Mark all ASIDs invalid on all cores on this die. 55 | */ 56 | sev_status_t mark_all_asids_invalid(void); 57 | 58 | /** 59 | * Writes the VmgSts register on all cores on this die. 60 | */ 61 | sev_status_t write_all_vmg_status_regs(uint32_t flags); 62 | 63 | /** 64 | * Clear the WBINVD_DONE bits on the specified CCD. 65 | */ 66 | sev_status_t clear_wbinvd_done(uint32_t ccd_mask); 67 | 68 | /** 69 | * Test if SME is enabled across all cores 70 | */ 71 | bool sme_is_enabled_all_cores(void); 72 | 73 | /** 74 | * Test if SMKE is enabled across all cores 75 | */ 76 | bool smke_is_enabled_all_cores(void); 77 | 78 | /** 79 | * Test if VMPL is enabled across all cores 80 | */ 81 | bool vmpl_is_enabled_all_cores(void); 82 | 83 | /** 84 | * Test if VM_HSAVE_PA is 0 across all cores 85 | */ 86 | bool vm_hsave_pa_cleared_all_cores(void); 87 | 88 | /** 89 | * Test if wbinvd has been issued on all dies/cores. 90 | */ 91 | sev_status_t is_wbinvd_done(bool *is_done, uint32_t *ccds_done); 92 | 93 | /** 94 | * Retrieve microcode patch level 95 | */ 96 | uint32_t retrieve_microcode_patch_level(void); 97 | 98 | /** 99 | * Retrieve RMP BASE and END 100 | */ 101 | sev_status_t get_rmp_base_end(uint64_t *rmp_base, uint64_t *rmp_end); 102 | 103 | /** 104 | * This function writes SEV-ES TMR address to the CPU TMR for all cores 105 | */ 106 | sev_status_t write_sev_es_tmr_address_to_all_cores(uint64_t value); 107 | 108 | #endif /* SEV_HAL_INTERFACE_H */ 109 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_hal_iommu.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_HAL_IOMMU_H 4 | #define SEV_HAL_IOMMU_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_es.h" 10 | #include "sev_rmp.h" 11 | #include "sev_status.h" 12 | 13 | /* Genoa has 2 physical NBIOs, but each has 2 IOHUBs. So logically, 14 | it was "4 NBIOs" in the way SNP is addressing the registers */ 15 | #define MAX_NBIO (2 * 2) 16 | #define MAX_IOMMU_TABLE_STATES (5*MAX_NBIO*MAX_SOCKET_NUM) /* 5 tables in set_iommu_table_state() */ 17 | 18 | sev_status_t enable_snp_iommu(void); 19 | sev_status_t validate_snp_iommu(void); 20 | sev_status_t disable_snp_iommu(void); 21 | sev_status_t check_iommu_event_logs(void); 22 | sev_status_t set_iommu_table_state(snp_page_state_t page_state); 23 | 24 | #endif /* SEV_HAL_IOMMU_H */ 25 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_persistent.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_PERSISTENT_H 4 | #define SEV_PERSISTENT_H 5 | 6 | #include 7 | #include 8 | 9 | #include "common_utilities.h" // COMMON_COMPILE_TIME_ASSERT 10 | #include "sev_errors.h" 11 | 12 | #define SEV_PERSISTENT_NR_BLOCKS (8) 13 | #define SEV_PERSISTENT_BLOCK_SIZE (4*1024) 14 | #define SEV_PERSISTENT_STORE_MAX_SIZE ((SEV_PERSISTENT_NR_BLOCKS)*(SEV_PERSISTENT_BLOCK_SIZE)) 15 | 16 | /** 17 | * "Device address" of 0 means use SPI storage. Otherwise, 18 | * it is the physical address of system memory. Ref: INIT EX command. 19 | */ 20 | #define SEV_PERSISTENT_SPI_DEV (0ULL) 21 | 22 | typedef struct sev_persistent_store 23 | { 24 | uint8_t cdata[sizeof(sev_persistent_t)]; // ciphertext for SEV persistent data 25 | hmac_sha256_t hmac; // plaintext 26 | cipher_aes_iv_t iv; // plaintext. stored at end for backwards compatibility 27 | } sev_persistent_store_t; 28 | COMMON_COMPILE_TIME_ASSERT(sizeof(sev_persistent_store_t) <= SEV_PERSISTENT_STORE_MAX_SIZE, sev_persistent_h); 29 | 30 | /** 31 | * Init the interface 32 | */ 33 | sev_status_t sev_persistent_store_init(void); 34 | 35 | /** 36 | * De-init the interface 37 | */ 38 | sev_status_t sev_persistent_store_deinit(void); 39 | 40 | /** 41 | * Retrieve the persistent data 42 | */ 43 | sev_status_t sev_persistent_store_retrieve(uint64_t dev_addr, 44 | sev_persistent_t *persistent); 45 | 46 | /** 47 | * Save the persistent data 48 | */ 49 | sev_status_t sev_persistent_store_save(uint64_t dev_addr, 50 | const sev_persistent_t *persistent); 51 | 52 | /** 53 | * Delete the persistent data 54 | */ 55 | sev_status_t sev_persistent_store_delete(uint64_t dev_addr); 56 | 57 | #endif /* SEV_PERSISTENT_H */ 58 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_persistent_utest.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "sev_globals.h" 6 | #include "sev_hal.h" 7 | #include "sev_persistent.h" 8 | #include "sev_persistent_utest.h" 9 | #include "sev_plat.h" 10 | #include "sev_trace.h" 11 | 12 | sev_status_t sev_persistent_store_utest(void) 13 | { 14 | sev_status_t status = SEV_STATUS_SUCCESS; 15 | sev_persistent_t *persistent = NULL; 16 | size_t i = 0; 17 | uint8_t random = 0; 18 | uint8_t *buf = NULL; 19 | 20 | persistent = (sev_persistent_t *)gpSevScratchBuf; 21 | 22 | status = sev_persistent_store_delete(SEV_PERSISTENT_SPI_DEV); /* use SPI */ 23 | if (status != SEV_STATUS_SUCCESS) 24 | { 25 | goto end; 26 | } 27 | 28 | // Generate random data for testing 29 | status = sev_hal_trng(&random, sizeof(random)); 30 | if (status != SEV_STATUS_SUCCESS) 31 | { 32 | goto end; 33 | } 34 | 35 | memset(persistent, random, sizeof(*persistent)); 36 | status = sev_persistent_store_save(SEV_PERSISTENT_SPI_DEV, persistent); 37 | if (status != SEV_STATUS_SUCCESS) 38 | { 39 | goto end; 40 | } 41 | 42 | memset(persistent, 0, sizeof(*persistent)); 43 | status = sev_persistent_store_retrieve(SEV_PERSISTENT_SPI_DEV, persistent); 44 | if (status != SEV_STATUS_SUCCESS) 45 | { 46 | goto end; 47 | } 48 | 49 | // Check the result 50 | buf = (uint8_t *)persistent; 51 | for (i = 0; i < sizeof(*persistent); i++) 52 | { 53 | if (buf[i] != random) 54 | { 55 | status = ERR_SECURE_DATA_VALIDATION; 56 | (void)sev_persistent_store_delete(SEV_PERSISTENT_SPI_DEV); /* use SPI */ 57 | goto end; 58 | } 59 | } 60 | 61 | status = sev_persistent_store_delete(SEV_PERSISTENT_SPI_DEV); /* use SPI */ 62 | if (status != SEV_STATUS_SUCCESS) 63 | { 64 | goto end; 65 | } 66 | 67 | end: 68 | if (status != SEV_STATUS_SUCCESS) 69 | { 70 | SEV_TRACE("sev_persistent_store_utest failed...\n"); 71 | SEV_TRACE_EX(status, 0, 0, 0); 72 | } 73 | else 74 | { 75 | SEV_TRACE("sev_persistent_store_utest succeed!\n"); 76 | } 77 | 78 | return status; 79 | } 80 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_persistent_utest.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_PERSISTENT_UTEST_H 4 | #define SEV_PERSISTENT_UTEST_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | sev_status_t sev_persistent_store_utest(void); 12 | 13 | #endif /* SEV_PERSISTENT_UTEST_H */ 14 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_ring_buffer.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_RING_BUFFER_H 4 | #define SEV_RING_BUFFER_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_status.h" 10 | 11 | /* cmd_flags */ 12 | #define SEV_RB_CMD_FLAG_INT_COMPLETE (1 << 0) /* Interrupt when command completes */ 13 | #define SEV_RB_CMD_FLAG_CONT_ON_ERROR (1 << 1) /* Continue or pause queue on error */ 14 | 15 | #define SEV_MAILBOX_INTERRUPT 0x01u /* Mailbox interrupt ID*/ 16 | typedef enum 17 | { 18 | HIGH_PRIORITY = 0, 19 | LOW_PRIORITY = 1 20 | } sev_rb_queue_type; 21 | 22 | typedef struct sev_rb_cmd_ptr_entry 23 | { 24 | uint16_t cmd_id; 25 | uint16_t cmd_flags; 26 | uint32_t software_data; /* Reserved for x86 */ 27 | uint64_t cmd_buffer_ptr; 28 | } __attribute__((packed))sev_rb_cmd_ptr_entry_t; 29 | 30 | typedef struct sev_rb_status_entry /* StatVal entry */ 31 | { 32 | uint16_t status; 33 | uint16_t reserved; 34 | uint32_t reserved2; 35 | uint64_t error_stack; 36 | } __attribute__((packed))sev_rb_cmd_status_entry_t; 37 | 38 | typedef struct sev_rb_control_register_bits /* RBCtl */ 39 | { 40 | uint32_t lo_queue_empty_int : 1; /* Enable Lo priority queue near empty interrupt */ 41 | uint32_t hi_queue_empty_int : 1; /* Enable Hi priority queue near empty interrupt */ 42 | uint32_t reserved : 6; 43 | uint32_t resume_lo_queue : 1; /* Resume Lo priority queue (Part of queue error recovery) */ 44 | uint32_t resume_hi_queue : 1; /* Resume Hi priority queue (Part of queue error recovery) */ 45 | uint32_t reserved2 :19; 46 | uint32_t clear_int_bits : 1; /* Clear Interrupt Status bits in RBHead register */ 47 | uint32_t rb_mode_active : 1; /* Indicates Ring Buffer mode active */ 48 | uint32_t x86_control : 1; /* Indicates x86 controls the register */ 49 | } __attribute__((packed))sev_rb_control_register_bits_t; 50 | 51 | typedef struct sev_rb_control_register 52 | { 53 | union 54 | { 55 | sev_rb_control_register_bits_t field; 56 | uint32_t val; 57 | } __attribute__((packed)) u; 58 | } __attribute__((packed)) sev_rb_control_register_t; 59 | 60 | typedef struct sev_rb_tail_bits 61 | { 62 | uint8_t lo_q_index; /* Lo priority Queue CmdPtr Tail index */ 63 | uint8_t reserved1; 64 | uint8_t hi_q_index; /* Hi priority Queue CmdPtr Tail index */ 65 | uint8_t reserved2; 66 | } __attribute__((packed)) sev_rb_bits_t; 67 | 68 | typedef struct sev_rb_tail 69 | { 70 | union 71 | { 72 | sev_rb_bits_t field; 73 | uint32_t val; 74 | } __attribute__((packed)) u; 75 | } __attribute__((packed)) sev_rb_tail_t; 76 | 77 | typedef struct sev_rb_head_bits 78 | { 79 | uint32_t lo_q_index : 8; /* Lo priority Queue CmdPtr Head index */ 80 | uint32_t reserved1 : 3; 81 | uint32_t lo_queue_running : 1; /* Lo priority Queue is running */ 82 | uint32_t reserved2 : 4; 83 | uint32_t hi_q_index : 8; /* Hi priority Queue CmdPtr Head index */ 84 | uint32_t reserved : 3; 85 | uint32_t hi_queue_running : 1; /* Hi priority Queue is running */ 86 | uint32_t all_queue_empty_int_stat : 1; /* All queues are empty */ 87 | uint32_t cmd_done_int_stat : 1; /* A command with InterruptOnCompletion set completed */ 88 | uint32_t q_paused_int_stat : 1; /* A command without ContinueOnError set did not return SUCCESS */ 89 | uint32_t q_free_int_stat : 1; /* A queue is near empty */ 90 | } __attribute__((packed)) sev_rb_head_bits_t; 91 | 92 | typedef struct sev_rb_head 93 | { 94 | union 95 | { 96 | sev_rb_head_bits_t field; 97 | uint32_t val; 98 | } __attribute__((packed)) u; 99 | } __attribute__((packed)) sev_rb_head_t; 100 | 101 | /** 102 | * Processing State 103 | * - Interrupt trackers exist because some interrupts trigger on each command 104 | * and some are only once 105 | */ 106 | typedef struct sev_rb_process_state /* Internal structure */ 107 | { 108 | sev_rb_queue_type queue_in_process; 109 | uint32_t queue_index; 110 | uint16_t cmd_flags; 111 | uint8_t generate_queue_empty_int; /* Int tracker for rb_head.all_queue_empty_int_stat */ 112 | uint8_t generate_cmd_done_int; /* Int tracker for rb_head.cmd_done_int_stat */ 113 | uint8_t generate_q_pause_int; /* Int tracker for rb_head.q_paused_int_stat */ 114 | uint8_t generate_q_free_int; /* Int tracker for rb_head.q_free_int_stat */ 115 | } sev_rb_process_state_t; 116 | 117 | typedef struct sev_rb_state 118 | { 119 | sev_rb_control_register_t x86_control; /* CmdResp -> rb_ctl */ 120 | sev_rb_tail_t x86_tail; /* CmdBufAddr_Hi -> rb_tail */ 121 | sev_rb_head_t sev_head; /* CmdBufAddr_Lo -> rb_head */ 122 | sev_rb_process_state_t process_state; 123 | } sev_rb_state_t; 124 | 125 | typedef struct sev_rb_config 126 | { 127 | bool rb_enable; 128 | bool int_on_empty; 129 | uint64_t cmd_ptr_low_priority_addr; 130 | uint64_t cmd_ptr_high_priority_addr; 131 | uint64_t status_ptr_low_priority_addr; 132 | uint64_t status_ptr_high_priority_addr; 133 | uint64_t status_ptr_low_priority_reclaim; 134 | uint64_t status_ptr_high_priority_reclaim; 135 | uint16_t low_queue_threshold; 136 | uint16_t high_queue_threshold; 137 | sev_rb_state_t state; 138 | uint8_t low_priority_queue_size; 139 | uint8_t high_priority_queue_size; 140 | } sev_rb_config_t; 141 | 142 | #define SEV_RB_CMD_BUFFER_MAX_SIZE (PAGE_SIZE_4K / sizeof(sev_rb_cmd_ptr_entry_t)) 143 | 144 | sev_status_t sev_rb_pre_cmd_process(sev_rb_state_t *state, uint32_t *cmd, 145 | uint32_t *cmd_low, uint32_t *cmd_high, 146 | bool *valid_cmd); 147 | sev_status_t sev_rb_generate_interrupt(sev_rb_state_t *state); 148 | sev_status_t sev_rb_post_cmd_process(sev_rb_state_t *state, sev_status_t status_save); 149 | void sev_rb_copy_mailbox(sev_rb_state_t *state); 150 | 151 | #endif /* SEV_RING_BUFFER_H */ 152 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_scmd.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "secure_ops.h" 8 | #include "sev_globals.h" 9 | #include "sev_hal.h" 10 | #include "sev_plat.h" 11 | #include "sev_scmd.h" 12 | #include "pspsmc.h" 13 | 14 | sev_status_t sev_scmd_df_flush(sev_scmd_t *ignored) 15 | { 16 | return sev_hal_df_write_flush(); 17 | } 18 | 19 | sev_status_t sev_scmd_set_tmr(sev_scmd_t *cmd) 20 | { 21 | uint64_t tmr_size = 0; 22 | if (cmd == NULL) 23 | { 24 | return ERR_INVALID_PARAMS; 25 | } 26 | 27 | tmr_size = (uint64_t)(cmd->scmd.set_tmr.size); 28 | tmr_size <<= TMR_X86_PHYS_ADDR_SHIFT; 29 | 30 | /* Setup the TMR on this die */ 31 | return sev_hal_set_tmr(cmd->scmd.set_tmr.tmr_nr, cmd->scmd.set_tmr.base, 32 | tmr_size, cmd->scmd.set_tmr.trust_level, 33 | cmd->scmd.set_tmr.flags); 34 | } 35 | 36 | sev_status_t sev_scmd_reset_tmr(sev_scmd_t *cmd) 37 | { 38 | return cmd != NULL ? sev_hal_reset_tmr(cmd->scmd.reset_tmr.tmr_nr) 39 | : ERR_INVALID_PARAMS; 40 | } 41 | 42 | sev_status_t sev_scmd_enable_tmr(sev_scmd_t *cmd) 43 | { 44 | return cmd != NULL ? sev_hal_enable_tmr(cmd->scmd.enable_tmr.tmr_nr) 45 | : ERR_INVALID_PARAMS; 46 | } 47 | 48 | sev_status_t sev_scmd_get_cuk(sev_scmd_t *ignored) 49 | { 50 | sev_status_t status = SEV_STATUS_SUCCESS; 51 | uint8_t cuk[2*CUK_SIZE]; 52 | uint8_t *pCukAligned = NULL; 53 | size_t cuk_size = CUK_SIZE; 54 | 55 | do { 56 | pCukAligned = (uint8_t *)ALIGN_TO_32_BYTES(cuk); 57 | status = sev_hal_get_chip_unique_key(pCukAligned, &cuk_size); 58 | if (status != SEV_STATUS_SUCCESS) 59 | break; 60 | memcpy(gpDram->p1_info.p1cuk, pCukAligned, cuk_size); 61 | sev_hal_clean_dcache((uint32_t)gpDram->p1_info.p1cuk, sizeof(gpDram->p1_info.p1cuk)); 62 | } while (0); 63 | 64 | /* Clean up */ 65 | secure_memzero(pCukAligned, cuk_size); 66 | 67 | return status; 68 | } 69 | 70 | sev_status_t sev_scmd_get_apicid(sev_scmd_t *ignored) 71 | { 72 | sev_status_t status = SEV_STATUS_SUCCESS; 73 | 74 | if (gCurrentDieID != SEV_SLAVE_SOCKET_MASTER_DIE) 75 | return status; 76 | 77 | do { 78 | gpDram->p1_info.activate_ex_enable = gSev.activate_ex_enable; 79 | memcpy(gpDram->p1_info.apic_ids, gSev.apic_ids, 80 | sizeof(gpDram->p1_info.apic_ids)); 81 | sev_hal_clean_dcache((uint32_t)&gpDram->p1_info, sizeof(gpDram->p1_info)); 82 | } while (0); 83 | 84 | return status; 85 | } 86 | 87 | sev_status_t sev_scmd_modify_tmr_flags(sev_scmd_t *cmd) 88 | { 89 | if (cmd == NULL) 90 | { 91 | return ERR_INVALID_PARAMS; 92 | } 93 | 94 | return sev_hal_modify_tmr_flags(cmd->scmd.modify_tmr.tmr_nr, cmd->scmd.modify_tmr.flags, 95 | cmd->scmd.modify_tmr.set); 96 | } 97 | 98 | sev_status_t sev_scmd_tlb_flush(sev_scmd_t *ignored) 99 | { 100 | return sev_hal_flush_tlb(); 101 | } 102 | 103 | sev_status_t sev_scmd_rd_sz_wrbkinvd(sev_scmd_t *cmd) 104 | { 105 | return sev_hal_set_misc_read_sized_wrbkinvd(cmd->scmd.sz_wrbkinvd.enable); 106 | } 107 | 108 | sev_status_t sev_scmd_df_acquire(sev_scmd_t *ignored) 109 | { 110 | return sev_hal_df_acquire(); 111 | } 112 | 113 | sev_status_t sev_scmd_df_release(sev_scmd_t *ignored) 114 | { 115 | return sev_hal_df_release(); 116 | } 117 | 118 | sev_status_t sev_scmd_get_mcm_info(sev_scmd_t *ignored) 119 | { 120 | sev_status_t status = SEV_STATUS_SUCCESS; 121 | 122 | if (gCurrentDieID != SEV_SLAVE_SOCKET_MASTER_DIE) 123 | return status; 124 | 125 | do { 126 | /* Get the data from BL for this socket */ 127 | status = sev_hal_get_mcm_info(&gPersistent); 128 | if (status != SEV_STATUS_SUCCESS) 129 | break; 130 | 131 | /* Copy the data to the shared DRAM so P0 can see it */ 132 | gpDram->p1_info.socket_info = gPersistent.socket_info[gCurrentDieID]; 133 | 134 | sev_hal_clean_dcache((uint32_t)&gpDram->p1_info, sizeof(gpDram->p1_info)); 135 | } while (0); 136 | 137 | return status; 138 | } 139 | 140 | sev_status_t sev_scmd_check_msrs(sev_scmd_t *ignored) 141 | { 142 | sev_status_t status = SEV_STATUS_SUCCESS; 143 | 144 | do { 145 | status = sev_hal_check_msrs(gpDram->p1_info.msrs); 146 | if (status != SEV_STATUS_SUCCESS) 147 | break; 148 | 149 | } while (0); 150 | 151 | /* Always flush the msrs informatio cache */ 152 | sev_hal_clean_dcache((uint32_t)gpDram->p1_info.msrs, sizeof(gpDram->p1_info.msrs)); 153 | 154 | return status; 155 | } 156 | 157 | sev_status_t sev_scmd_set_msr(sev_scmd_t *cmd) 158 | { 159 | if (Svc_SendPspSmuMsg(PSPSMC_MSG_UpdateC001MSR, cmd->scmd.set_msr.val, NULL, 0) != BL_OK) 160 | return SEV_STATUS_HARDWARE_PLATFORM; 161 | 162 | return SEV_STATUS_SUCCESS; 163 | } 164 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_scmd.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2019 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_SCMD_H 4 | #define SEV_SCMD_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | /** 12 | * How to use this file: 13 | * The slaves commands are called by the master using sev_hal_master_to_slave 14 | * to either get data from the slaves, or pass data to the slaves. Add your 15 | * command in sev_scmd.* and in sev_dispatch.* (the translation table that 16 | * turns the cmd.id param into (and calls) the corresponding function in 17 | * sev_scmd.c) 18 | */ 19 | typedef enum sev_scmd_id 20 | { 21 | SEV_SCMD_ID_DF_FLUSH = 0x0001, 22 | SEV_SCMD_ID_SET_TMR = 0x0002, 23 | SEV_SCMD_ID_RESET_TMR = 0x0003, 24 | SEV_SCMD_ID_ENABLE_TMR = 0x0004, 25 | SEV_SCMD_ID_GET_CUK = 0x0005, 26 | SEV_SCMD_ID_GET_APICID = 0x0006, 27 | SEV_SCMD_ID_MODIFY_TMR_FLAGS = 0x0007, 28 | SEV_SCMD_ID_TLB_FLUSH = 0x0008, 29 | SEV_SCMD_ID_RD_SZ_WRBKINVD = 0x000B, 30 | SEV_SCMD_ID_DF_ACQUIRE = 0x000C, 31 | SEV_SCMD_ID_DF_RELEASE = 0x000D, 32 | SEV_SCMD_GET_MCM_INFO = 0x000E, 33 | SEV_SCMD_CHECK_MSRS = 0x000F, 34 | SEV_SCMD_SET_MSR = 0x0010, 35 | /** XXX more to be added **/ 36 | 37 | SEV_SCMD_ID_LIMIT, 38 | } sev_scmd_id_t; 39 | 40 | typedef struct sev_scmd_set_tmr 41 | { 42 | uint64_t base; 43 | size_t size; 44 | uint8_t tmr_nr; 45 | uint8_t trust_level; 46 | uint32_t flags; 47 | } sev_scmd_set_tmr_t; 48 | 49 | typedef struct sev_scmd_tmr_ops 50 | { 51 | uint8_t tmr_nr; 52 | uint32_t flags; 53 | bool set; 54 | } sev_scmd_tmr_ops_t; 55 | 56 | typedef struct sev_scmd_df_ccm_privilege 57 | { 58 | uint8_t ccd; 59 | } sev_scmd_df_ccm_privilege_t; 60 | 61 | typedef struct sev_scmd_rd_sz_wrbkinvd 62 | { 63 | bool enable; 64 | } sev_scmd_rd_sz_wrbkinvd_t; 65 | 66 | typedef struct sev_scmd_set_msr 67 | { 68 | uint32_t val; 69 | } sev_scmd_set_msr_t; 70 | 71 | /** 72 | * NOTE: This structure must be small enough to fit into the P2P message 73 | * buffer, which is currently 32 bytes! 74 | */ 75 | typedef struct sev_scmd 76 | { 77 | sev_scmd_id_t id; 78 | uint8_t die; 79 | 80 | union 81 | { 82 | sev_scmd_set_tmr_t set_tmr; 83 | sev_scmd_tmr_ops_t reset_tmr; 84 | sev_scmd_tmr_ops_t enable_tmr; 85 | sev_scmd_tmr_ops_t modify_tmr; 86 | sev_scmd_rd_sz_wrbkinvd_t sz_wrbkinvd; 87 | sev_scmd_set_msr_t set_msr; 88 | } scmd; 89 | } sev_scmd_t; 90 | 91 | sev_status_t sev_scmd_df_flush(sev_scmd_t *ignored); 92 | sev_status_t sev_scmd_set_tmr(sev_scmd_t *cmd); 93 | sev_status_t sev_scmd_reset_tmr(sev_scmd_t *cmd); 94 | sev_status_t sev_scmd_enable_tmr(sev_scmd_t *cmd); 95 | sev_status_t sev_scmd_get_cuk(sev_scmd_t *ignored); 96 | sev_status_t sev_scmd_get_apicid(sev_scmd_t *ignored); 97 | sev_status_t sev_scmd_modify_tmr_flags(sev_scmd_t *cmd); 98 | sev_status_t sev_scmd_tlb_flush(sev_scmd_t *cmd); 99 | sev_status_t sev_scmd_rd_sz_wrbkinvd(sev_scmd_t *cmd); 100 | sev_status_t sev_scmd_df_acquire(sev_scmd_t *ignored); 101 | sev_status_t sev_scmd_df_release(sev_scmd_t *ignored); 102 | sev_status_t sev_scmd_get_mcm_info(sev_scmd_t *ignored); 103 | sev_status_t sev_scmd_check_msrs(sev_scmd_t *ignored); 104 | sev_status_t sev_scmd_set_msr(sev_scmd_t *cmd); 105 | 106 | #endif /* SEV_SCMD_H */ 107 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_tmr.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2021 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "sev_globals.h" 9 | #include "sev_hal.h" 10 | #include "sev_scmd.h" 11 | 12 | /** 13 | * Levels for TMR calls 14 | * x -> sev_tmr.c -> sev_hal.c -> tmr_cache.c -> df_regs.c 15 | */ 16 | 17 | /* Note that this function takes a base address and length/size, not base and end addresses */ 18 | sev_status_t enable_tmr(uint8_t tmr_num, uint64_t base, uint64_t size, uint32_t flags) 19 | { 20 | sev_status_t status = SEV_STATUS_SUCCESS; 21 | uint32_t trust_level = 0; /* Don't care about trust level, not used */ 22 | 23 | /* Setup the TMR on this die */ 24 | status = sev_hal_set_tmr(tmr_num, base, (size - 1), trust_level, flags); 25 | if (status != SEV_STATUS_SUCCESS) 26 | goto end; 27 | 28 | /* Only send slave commands if this is the master die */ 29 | if (gCurrentDieID == SEV_GLOBAL_MASTER_DIE_ID) 30 | { 31 | /* Setup the TMR on slave dies as well */ 32 | sev_scmd_t cmd; 33 | memset(&cmd, 0, sizeof(cmd)); 34 | cmd.id = SEV_SCMD_ID_SET_TMR; 35 | cmd.scmd.set_tmr.tmr_nr = tmr_num; 36 | cmd.scmd.set_tmr.base = base; 37 | cmd.scmd.set_tmr.size = (uint32_t)((size - 1ULL) >> TMR_X86_PHYS_ADDR_SHIFT); 38 | cmd.scmd.set_tmr.trust_level = trust_level; 39 | cmd.scmd.set_tmr.flags = flags; 40 | status = sev_hal_master_to_slave(1, &cmd, sizeof(cmd)); 41 | if (status != SEV_STATUS_SUCCESS) 42 | goto end; 43 | } 44 | 45 | end: 46 | return status; 47 | } 48 | 49 | sev_status_t modify_tmr_flags(uint8_t tmr_num, uint32_t flags, bool set) 50 | { 51 | sev_status_t status = SEV_STATUS_SUCCESS; 52 | sev_scmd_t cmd; 53 | 54 | /* This function is designed to read-modify-write the TmrCtl register without 55 | disabling it first. It will set/clear the flag bits */ 56 | status = sev_hal_modify_tmr_flags(tmr_num, flags, set); 57 | if (status != SEV_STATUS_SUCCESS) 58 | goto end; 59 | 60 | /* Only send slave commands if this is the master die */ 61 | if (gCurrentDieID == SEV_GLOBAL_MASTER_DIE_ID) 62 | { 63 | /* Setup the TMR on slave dies as well */ 64 | memset(&cmd, 0, sizeof(cmd)); 65 | cmd.id = SEV_SCMD_ID_MODIFY_TMR_FLAGS; 66 | cmd.scmd.modify_tmr.tmr_nr = tmr_num; 67 | cmd.scmd.modify_tmr.flags = flags; 68 | cmd.scmd.modify_tmr.set = set; 69 | 70 | status = sev_hal_master_to_slave(1, &cmd, sizeof(cmd)); 71 | if (status != SEV_STATUS_SUCCESS) 72 | goto end; 73 | } 74 | 75 | end: 76 | return status; 77 | } 78 | 79 | sev_status_t disable_tmr(uint8_t tmr_num) 80 | { 81 | sev_status_t status = SEV_STATUS_SUCCESS; 82 | 83 | sev_scmd_t cmd; 84 | 85 | /* Release the TMR on this die */ 86 | status = sev_hal_reset_tmr(tmr_num); 87 | if (status != SEV_STATUS_SUCCESS) 88 | goto end; 89 | 90 | /* Release the TMR on slave dies */ 91 | memset(&cmd, 0, sizeof(cmd)); 92 | cmd.id = SEV_SCMD_ID_RESET_TMR; 93 | cmd.scmd.reset_tmr.tmr_nr = tmr_num; 94 | 95 | status = sev_hal_master_to_slave(1, &cmd, sizeof(cmd)); 96 | if (status != SEV_STATUS_SUCCESS) 97 | goto end; 98 | 99 | end: 100 | return status; 101 | } 102 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_tmr.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2019-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_TMR_H 4 | #define SEV_TMR_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | /** 12 | * Create and enable a generic, non-SEV-ES, TMR region 13 | * Input: tmr_num - Which TMR to enable 14 | * base - 64 bit start address 15 | * size - 64 bit end address 16 | * flags - TMR flags for protection 17 | */ 18 | sev_status_t enable_tmr(uint8_t tmr_num, uint64_t base, uint64_t size, uint32_t flags); 19 | 20 | /** 21 | * Modify the TMR_CTRL flags on an enabled TMR 22 | */ 23 | sev_status_t modify_tmr_flags(uint8_t tmr_num, uint32_t flags, bool set); 24 | 25 | /** 26 | * Release and disable the TMR region for RMP table. 27 | */ 28 | sev_status_t disable_tmr(uint8_t tmr_num); 29 | 30 | #endif /* SEV_TMR_H */ 31 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_trace.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_TRACE_H 4 | #define SEV_TRACE_H 5 | 6 | #include 7 | #include 8 | 9 | // TRACE switch for overall SEV_UAPP 10 | // Turn ON by compile switch "SEV_UAPP_TRACE_ENABLE=1" 11 | // Only work for master die, debug print cannot be enabled on slave Dies. 12 | #ifdef SEV_UAPP_TRACE_ENABLE 13 | #define SEV_MCMD_TRACE_EN // TRACE switch for module: sev_mcmd 14 | #define SEV_PLAT_TRACE_EN // TRACE switch for module: sev_plat 15 | #define SEV_GUEST_TRACE_EN // TRACE switch for module: sev_guest 16 | #define SEV_HAL_TRACE_EN // TRACE switch for module: sev_hal 17 | #endif 18 | 19 | 20 | #ifdef SEV_UAPP_TRACE_ENABLE 21 | #define SEV_TRACE( str ) Svc_DebugPrint( str ) 22 | #define SEV_TRACE_EX( ... ) Svc_DebugPrintEx ( __VA_ARGS__ ) 23 | #else 24 | #define SEV_TRACE( str ) 25 | #define SEV_TRACE_EX( ... ) 26 | #endif 27 | 28 | #ifdef SEV_MCMD_TRACE_EN 29 | #define SEV_MCMD_TRACE( str ) Svc_DebugPrint( str ) 30 | #define SEV_MCMD_TRACE_EX( ... ) Svc_DebugPrintEx ( __VA_ARGS__ ) 31 | #else 32 | #define SEV_MCMD_TRACE( str ) 33 | #define SEV_MCMD_TRACE_EX( ... ) 34 | #endif 35 | 36 | #ifdef SEV_PLAT_TRACE_EN 37 | #define SEV_PLAT_TRACE( str ) Svc_DebugPrint( str ) 38 | #define SEV_PLAT_TRACE_EX( ... ) Svc_DebugPrintEx ( __VA_ARGS__ ) 39 | #else 40 | #define SEV_PLAT_TRACE( str ) 41 | #define SEV_PLAT_TRACE_EX( ... ) 42 | #endif 43 | 44 | #ifdef SEV_GUEST_TRACE_EN 45 | #define SEV_GUEST_TRACE( str ) Svc_DebugPrint( str ) 46 | #define SEV_GUEST_TRACE_EX( ... ) Svc_DebugPrintEx ( __VA_ARGS__ ) 47 | #else 48 | #define SEV_GUEST_TRACE( str ) 49 | #define SEV_GUEST_TRACE_EX( ... ) 50 | #endif 51 | 52 | #ifdef SEV_HAL_TRACE_EN 53 | #define SEV_HAL_TRACE( str ) Svc_DebugPrint( str ) 54 | #define SEV_HAL_TRACE_EX( ... ) Svc_DebugPrintEx ( __VA_ARGS__ ) 55 | #else 56 | #define SEV_HAL_TRACE( str ) 57 | #define SEV_HAL_TRACE_EX( ... ) 58 | #endif 59 | 60 | #endif /* SEV_TRACE_H */ 61 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_wrap.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "secure_ops.h" 6 | #include "sev_hal.h" 7 | #include "sev_wrap.h" 8 | 9 | /** 10 | * Wrap the data 11 | * 12 | * algorithm: secure data is encrypted and HMAC'd as following. 13 | * IV is the initial AES counter, 14 | * KE is the encryption key, 15 | * KI is the integrity key, 16 | * M is the plaintext data, then we'd produce C: 17 | * 18 | * C = { IV, AES-CTR(M; KE, IV), HMAC(AES-CTR(M; KE, IV); KI) } 19 | * 20 | * support In Place operation 21 | */ 22 | sev_status_t sev_secure_data_wrap(const cipher_aes_key_t *aes_key, 23 | uint8_t *hmac_key, size_t hmac_key_len, 24 | uint8_t *src, size_t src_len, 25 | uint8_t *dest, size_t *dest_len, 26 | hmac_sha256_t *hmac) 27 | { 28 | sev_status_t status = SEV_STATUS_SUCCESS; 29 | cipher_aes_iv_t iv; 30 | cipher_aes_ctr_ctx_t aes_ctx; 31 | size_t len = 0; 32 | hmac_sha256_ctx_t sha_ctx; 33 | const uint32_t empty = 0xFFFFFFFF; 34 | 35 | if (!aes_key || !hmac_key || hmac_key_len == 0 || !src || 36 | src_len == 0 || !dest || !dest_len || *dest_len == 0 || 37 | *dest_len < src_len + HMAC_SHA256_SIZE_BYTES + sizeof(iv) || !hmac ) 38 | { 39 | status = ERR_INVALID_PARAMS; 40 | goto end; 41 | } 42 | 43 | /* Generate a new random iv that's not all F's, so it will pass the 44 | backwards-compatibility check in unwrap */ 45 | do { 46 | status = sev_hal_trng((uint8_t *)&iv, sizeof(iv)); 47 | if (status != SEV_STATUS_SUCCESS) 48 | goto end; 49 | } while (memcmp(&iv, &empty, sizeof(empty)) == 0); 50 | 51 | status = cipher_aes_ctr_init(&aes_ctx, &iv, aes_key, AES_MODE_ENCRYPT); 52 | if (status != SEV_STATUS_SUCCESS) 53 | goto end; 54 | 55 | len = src_len; 56 | status = cipher_aes_ctr_final(&aes_ctx, src, src_len, dest, &len); 57 | if (status != SEV_STATUS_SUCCESS) 58 | goto end; 59 | 60 | status = hmac_sha256_init(&sha_ctx, hmac_key, hmac_key_len); 61 | if (status != SEV_STATUS_SUCCESS) 62 | goto end; 63 | 64 | status = hmac_sha256_update(&sha_ctx, dest, len); 65 | if (status != SEV_STATUS_SUCCESS) 66 | goto end; 67 | 68 | status = hmac_sha256_update(&sha_ctx, &iv, sizeof(iv)); 69 | if (status != SEV_STATUS_SUCCESS) 70 | goto end; 71 | 72 | status = hmac_sha256_final(&sha_ctx, hmac); 73 | if (status != SEV_STATUS_SUCCESS) 74 | goto end; 75 | 76 | /* Finally, copy the HMAC to dest buffer to make it a completed datablob as a whole */ 77 | memcpy(dest+len, hmac, sizeof(*hmac)); 78 | 79 | /* Finally finally, store the random IV */ 80 | memcpy(dest+len+sizeof(*hmac), &iv, sizeof(iv)); 81 | 82 | end: 83 | return status; 84 | } 85 | 86 | /** 87 | * Unwrap the data 88 | * 89 | * support In Place operation 90 | */ 91 | sev_status_t sev_secure_data_unwrap(const cipher_aes_key_t *aes_key, 92 | uint8_t *hmac_key, size_t hmac_key_len, 93 | uint8_t *src, size_t src_len, 94 | uint8_t *dest, size_t *dest_len) 95 | { 96 | sev_status_t status = SEV_STATUS_SUCCESS; 97 | cipher_aes_iv_t *iv = NULL; 98 | cipher_aes_ctr_ctx_t aes_ctx; 99 | hmac_sha256_t hmac; 100 | size_t len = src_len - sizeof(hmac) - sizeof(*iv); 101 | hmac_sha256_ctx_t sha_ctx; 102 | const uint32_t empty = 0xFFFFFFFF; 103 | 104 | if (!aes_key || !hmac_key || hmac_key_len == 0 || !src || 105 | src_len == 0 || !dest || !dest_len || *dest_len == 0 || 106 | *dest_len < src_len - HMAC_SHA256_SIZE_BYTES - sizeof(*iv)) 107 | { 108 | status = ERR_INVALID_PARAMS; 109 | goto end; 110 | } 111 | 112 | iv = (cipher_aes_iv_t *)(src + len + sizeof(hmac)); 113 | 114 | status = hmac_sha256_init(&sha_ctx, hmac_key, hmac_key_len); 115 | if (status != SEV_STATUS_SUCCESS) 116 | goto end; 117 | 118 | status = hmac_sha256_update(&sha_ctx, src, len); 119 | if (status != SEV_STATUS_SUCCESS) 120 | goto end; 121 | 122 | if (memcmp(iv, &empty, sizeof(empty)) != 0) /* New method, IV is used */ 123 | { 124 | status = hmac_sha256_update(&sha_ctx, iv, sizeof(*iv)); 125 | if (status != SEV_STATUS_SUCCESS) 126 | goto end; 127 | } 128 | else /* Backwards compatibility - old IV was all 0's */ 129 | { 130 | memset(iv, 0, sizeof(cipher_aes_iv_t)); 131 | } 132 | 133 | status = hmac_sha256_final(&sha_ctx, &hmac); 134 | if (status != SEV_STATUS_SUCCESS) 135 | goto end; 136 | 137 | if (secure_compare(src + len, &hmac, sizeof(hmac)) != 0) 138 | { 139 | /* Failed validation */ 140 | status = SEV_STATUS_SECURE_DATA_INVALID; 141 | goto end; 142 | } 143 | 144 | status = cipher_aes_ctr_init(&aes_ctx, iv, aes_key, AES_MODE_DECRYPT); 145 | if (status != SEV_STATUS_SUCCESS) 146 | goto end; 147 | 148 | status = cipher_aes_ctr_final(&aes_ctx, src, len, dest, dest_len); 149 | if (status != SEV_STATUS_SUCCESS) 150 | goto end; 151 | 152 | end: 153 | return status; 154 | } 155 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sev_wrap.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_WRAP_H 4 | #define SEV_WRAP_H 5 | 6 | #include 7 | #include 8 | 9 | #include "cipher.h" 10 | #include "hmac.h" 11 | #include "sev_errors.h" 12 | 13 | /** 14 | * Wrap the data 15 | * 16 | * algorithm: secure data is encrypted and HMAC'd as following. 17 | * IV is the initial AES counter, 18 | * KE is the encryption key, 19 | * KI is the integrity key, 20 | * M is the plaintext data, then we'd produce C: 21 | * 22 | * C = { IV, AES-CTR(M; KE, IV), HMAC(AES-CTR(M; KE, IV); KI) } 23 | * 24 | * 'src': must be 16 bytes aligned. 25 | * 'dest': must be 16 bytes aligned. 26 | * 27 | * support In Place operation 28 | */ 29 | sev_status_t sev_secure_data_wrap(const cipher_aes_key_t *aes_key, 30 | uint8_t *hmac_key, size_t hmac_key_len, 31 | uint8_t *src, size_t src_len, 32 | uint8_t *dest, size_t *dest_len, 33 | hmac_sha256_t *hmac); 34 | 35 | /** 36 | * Unwrap the data 37 | * 38 | * 'src': must be 16 bytes aligned. 39 | * 'dest': must be 16 bytes aligned. 40 | * 41 | * support In Place operation 42 | */ 43 | sev_status_t sev_secure_data_unwrap(const cipher_aes_key_t *aes_key, 44 | uint8_t *hmac_key, size_t hmac_key_len, 45 | uint8_t *src, size_t src_len, 46 | uint8_t *dest, size_t *dest_len); 47 | 48 | #endif /* SEV_WRAP_H */ 49 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/startup.s: -------------------------------------------------------------------------------- 1 | ; Copyright(C) 2014 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | 4 | IMPORT sev_uapp_entry 5 | IMPORT allocate_stack 6 | 7 | ; Linker symbols from scatter file 8 | IMPORT ||Image$$SEV_UAPP_TEMP_STACK$$ZI$$Base|| 9 | IMPORT ||Image$$SEV_UAPP_TEMP_STACK$$ZI$$Limit|| 10 | IMPORT ||Image$$SEV_UAPP_STACK$$ZI$$Base|| 11 | IMPORT ||Image$$SEV_UAPP_STACK$$ZI$$Limit|| 12 | IMPORT ||Image$$SEV_UAPP_INIT_ONCE$$ZI$$Base|| 13 | IMPORT ||Image$$SEV_UAPP_INIT_ONCE$$ZI$$Limit|| 14 | 15 | PRESERVE8 16 | AREA STARTUP_DATA, DATA, READWRITE ; name this block of code 17 | ENTRY 18 | 19 | AREA STARTUP_CODE, CODE, READONLY ; name this block of code 20 | 21 | ;============================================================================== 22 | ; First 256 bytes of the binary image contain the header. 23 | ; Executable code starts from offset 0x100. 24 | ;============================================================================== 25 | INCLUDE header.inc 26 | 27 | 28 | ;============================================================================== 29 | ; This is entry poit to the binary which is called by main Boot Loader. 30 | ;============================================================================== 31 | 32 | EXPORT EntryPoint 33 | 34 | EntryPoint 35 | 36 | mov r4, r0 ; Save r0-r3 (input parameters) 37 | mov r5, r1 38 | mov r6, r2 39 | mov r7, r3 40 | ; Create the zero-initialized memory areas 41 | mov r3, #0 42 | cmp r7, #1 ; Clear "init_once" area only on first entry 43 | bne AllocateStack 44 | ; In SEV model, BSS is only initialized once. 45 | ldr r1, =||Image$$SEV_UAPP_INIT_ONCE$$ZI$$Base|| 46 | ldr r2, =||Image$$SEV_UAPP_INIT_ONCE$$ZI$$Limit|| 47 | bl zi_init 48 | 49 | ; Map SEV UAPP stack to separate Virtual Address so that stack overflow cause 50 | ; exception instead of data corruption. 51 | ; 52 | AllocateStack 53 | ldr sp, =||Image$$SEV_UAPP_TEMP_STACK$$ZI$$Limit|| ; temporary stack pointer 54 | ldr r2, =allocate_stack 55 | blx r2 56 | ; Return value contains Virtual Address of mapped stack 57 | ; 58 | mov sp, r0 ; set sev user app stack pointer 59 | ldr lr, =ShouldNotBeReached ; return address 60 | ldr r12, =sev_uapp_entry ; pass control to sev user app main function 61 | mov r0, r4 ; Restore r0-r3 input parameters 62 | mov r1, r5 63 | mov r2, r6 64 | mov r3, r7 65 | blx r12 66 | 67 | ; This point should not be reached. The sev_uapp_entry() function should return 68 | ; to main BL using Svc_Exit(). 69 | ; 70 | ShouldNotBeReached 71 | b . 72 | 73 | ;============================================================================== 74 | ; zi_init is a subroutine which initializes a region, starting at the 75 | ; address in r1, to a value held in r3. The address of the word beyond 76 | ; the end of this region is held in r2 77 | ;============================================================================== 78 | 79 | zi_init 80 | 81 | cmp r1, r2 82 | strcc r3, [r1], #4 83 | bcc zi_init 84 | bx lr ; return to caller 85 | 86 | END 87 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/sw_hash.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // Copyright 2021 Advanced Micro Devices, Inc. All rights reserved. 3 | // 4 | // This document contains proprietary, confidential information that 5 | // may be used, copied and/or disclosed only as authorized by a 6 | // valid licensing agreement with ATI Technologies Inc. This copyright 7 | // notice must be retained on all authorized copies. 8 | // 9 | // This code is provided "as is". AMD Inc. makes, and 10 | // the end user receives, no warranties or conditions, express, 11 | // implied, statutory or otherwise, and ATI Technologies Inc. 12 | // specifically disclaims any implied warranties of merchantability, 13 | // non-infringement, or fitness for a particular purpose. 14 | // 15 | //----------------------------------------------------------------------------- 16 | 17 | #ifndef SW_HASH_H_ 18 | #define SW_HASH_H_ 19 | 20 | #include "commontypes.h" 21 | #include "sev_status.h" 22 | 23 | // Used for SHA-1 and SHA-256 24 | typedef struct SW_SHA_CONTEXT 25 | { 26 | uint32_t State[8]; // hash state 27 | uint8_t Msg[64]; // currently processed block of the message 28 | uint32_t Mlen; // Length of the current block 29 | uint64_t MsgLen; // total length of the message 30 | 31 | } SW_SHA_CONTEXT; 32 | 33 | #if 0 34 | // Used for SHA-384 and SHA-512 35 | typedef struct SW_SHA2_CONTEXT 36 | { 37 | uint64_t State[8]; // hash state 38 | uint8_t Msg[128]; // currently processed block of the message 39 | uint32_t Mlen; // Length of the current block 40 | uint64_t MsgLen; // total length of the message 41 | 42 | } SW_SHA2_CONTEXT; 43 | 44 | // Function prototypes 45 | // 46 | uint32_t SW_SHA1_Init( SW_SHA_CONTEXT* pOp ); 47 | 48 | uint32_t SW_SHA1_Process( SW_SHA_CONTEXT* pOp, 49 | const uint8_t* pMsg, 50 | uint32_t MsgLen ); 51 | 52 | uint32_t SW_SHA1_Final( SW_SHA_CONTEXT* pOp, 53 | uint8_t* pHash, 54 | uint32_t HashLen ); 55 | 56 | uint32_t SW_SHA224_Init( SW_SHA_CONTEXT* pOp ); 57 | 58 | uint32_t SW_SHA224_Process( SW_SHA_CONTEXT* pOp, 59 | const uint8_t* pMsg, 60 | uint32_t MsgLen ); 61 | 62 | uint32_t SW_SHA224_Final( SW_SHA_CONTEXT* pOp, 63 | uint8_t* pHash, 64 | uint32_t HashLen ); 65 | #endif 66 | 67 | sev_status_t SW_SHA256_Init( SW_SHA_CONTEXT* pOp ); 68 | 69 | sev_status_t SW_SHA256_Process( SW_SHA_CONTEXT* pOp, 70 | const uint8_t* pMsg, 71 | uint32_t MsgLen ); 72 | 73 | sev_status_t SW_SHA256_Final( SW_SHA_CONTEXT* pOp, 74 | uint8_t* pHash, 75 | uint32_t HashLen ); 76 | 77 | #if 0 78 | uint32_t SW_SHA384_Init( SW_SHA2_CONTEXT* pOp ); 79 | 80 | uint32_t SW_SHA384_Process( SW_SHA2_CONTEXT* pOp, 81 | const uint8_t* pMsg, 82 | uint32_t MsgLen ); 83 | 84 | uint32_t SW_SHA384_Final( SW_SHA2_CONTEXT* pOp, 85 | uint8_t* pHash, 86 | uint32_t HashLen ); 87 | 88 | uint32_t SW_SHA512_Init( SW_SHA2_CONTEXT* pOp ); 89 | 90 | uint32_t SW_SHA512_Process( SW_SHA2_CONTEXT* pOp, 91 | const uint8_t* pMsg, 92 | uint32_t MsgLen ); 93 | 94 | uint32_t SW_SHA512_Final( SW_SHA2_CONTEXT* pOp, 95 | uint8_t* pHash, 96 | uint32_t HashLen ); 97 | 98 | #endif 99 | 100 | #endif // SW_HASH_H_ 101 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/tmr_cache.c: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #include 4 | 5 | #include "df_regs.h" 6 | #include "sev_globals.h" 7 | #include "tmr_cache.h" 8 | 9 | static tmr_cache_t *tmr_cache = &gPersistent.tmr_cache; 10 | 11 | bool tmr_cache_is_present(size_t tmr) 12 | { 13 | return tmr <= TMR_NR_MAX ? tmr_cache->present_mask & (1ul << tmr) : false; 14 | } 15 | 16 | void tmr_cache_init(void) 17 | { 18 | memset(tmr_cache, 0, sizeof(*tmr_cache)); 19 | } 20 | 21 | sev_status_t tmr_cache_invalidate(size_t tmr_nr) 22 | { 23 | sev_status_t status = SEV_STATUS_SUCCESS; 24 | tmr_t *cache = &tmr_cache->tmr[tmr_nr]; 25 | 26 | if (tmr_nr > TMR_NR_MAX) 27 | { 28 | status = ERR_INVALID_PARAMS; 29 | goto end; 30 | } 31 | 32 | memset(cache, 0, sizeof(*cache)); 33 | tmr_cache->present_mask &= ~(1ul << tmr_nr); 34 | 35 | end: 36 | return status; 37 | } 38 | 39 | sev_status_t tmr_cache_read(size_t tmr_nr, uint64_t *base, uint64_t *limit, 40 | uint32_t *control, uint32_t *trust_lvl) 41 | { 42 | sev_status_t status = SEV_STATUS_SUCCESS; 43 | tmr_t *cache = &tmr_cache->tmr[tmr_nr]; 44 | 45 | if (tmr_nr > TMR_NR_MAX) 46 | { 47 | status = ERR_INVALID_PARAMS; 48 | goto end; 49 | } 50 | 51 | if (!tmr_cache_is_present(tmr_nr)) 52 | { 53 | /* Call to disable DF C State, required to access TMR */ 54 | status = df_access_lock(); 55 | if (status != SEV_STATUS_SUCCESS) 56 | goto end; 57 | status = get_tmr_info(tmr_nr, &cache->base, &cache->limit, 58 | &cache->trust_lvl, &cache->control); 59 | /* Enable Df C State, preserve the status */ 60 | df_access_unlock(); 61 | if (status != SEV_STATUS_SUCCESS) 62 | goto end; 63 | 64 | tmr_cache->present_mask |= 1ul << tmr_nr; 65 | } 66 | 67 | if (base) 68 | *base = cache->base; 69 | if (limit) 70 | *limit = cache->limit; 71 | if (control) 72 | *control = cache->control; 73 | if (trust_lvl) 74 | *trust_lvl = cache->trust_lvl; 75 | 76 | end: 77 | return status; 78 | } 79 | 80 | sev_status_t tmr_cache_write(size_t tmr_nr, uint64_t base, uint64_t limit, 81 | uint32_t control, uint32_t trust_lvl) 82 | { 83 | sev_status_t status = SEV_STATUS_HARDWARE_PLATFORM; 84 | tmr_t *cache = &tmr_cache->tmr[tmr_nr]; 85 | 86 | if (tmr_nr > TMR_NR_MAX) 87 | { 88 | status = ERR_INVALID_PARAMS; 89 | goto end; 90 | } 91 | 92 | status = set_tmr(tmr_nr, base, limit, control, trust_lvl); 93 | if (status != SEV_STATUS_SUCCESS) 94 | { 95 | /* 96 | * We can't be sure which registers were written before the failure, 97 | * so invalidate this TMR. Future reads will re-populate the cache 98 | * from the fabric. 99 | */ 100 | (void)tmr_cache_invalidate(tmr_nr); 101 | goto end; 102 | } 103 | 104 | cache->base = base; 105 | cache->limit = limit; 106 | cache->control = control; 107 | cache->trust_lvl = trust_lvl; 108 | tmr_cache->present_mask |= 1ul << tmr_nr; 109 | 110 | end: 111 | return status; 112 | } 113 | 114 | sev_status_t tmr_cache_modify_flags(size_t tmr_nr, uint32_t flags, bool set) 115 | { 116 | sev_status_t status = SEV_STATUS_HARDWARE_PLATFORM; 117 | tmr_t *cache = &tmr_cache->tmr[tmr_nr]; 118 | 119 | if (tmr_nr > TMR_NR_MAX) 120 | { 121 | status = ERR_INVALID_PARAMS; 122 | goto end; 123 | } 124 | 125 | status = set_tmr_modify_flags(tmr_nr, flags, set); 126 | if (status != SEV_STATUS_SUCCESS) 127 | { 128 | /* 129 | * We can't be sure which registers were written before the failure, 130 | * so invalidate this TMR. Future reads will re-populate the cache 131 | * from the fabric. 132 | */ 133 | (void)tmr_cache_invalidate(tmr_nr); 134 | goto end; 135 | } 136 | 137 | /* Update the tmr cache info */ 138 | status = get_tmr_info(tmr_nr, &cache->base, &cache->limit, 139 | &cache->trust_lvl, &cache->control); 140 | if (status != SEV_STATUS_SUCCESS) 141 | goto end; 142 | 143 | tmr_cache->present_mask |= 1ul << tmr_nr; 144 | 145 | end: 146 | return status; 147 | } 148 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/tmr_cache.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2017-2018 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef TMR_CACHE_H 4 | #define TMR_CACHE_H 5 | 6 | #include 7 | #include 8 | 9 | #include "df_regs.h" 10 | #include "sev_errors.h" 11 | 12 | typedef struct tmr 13 | { 14 | uint64_t base; 15 | uint64_t limit; 16 | uint32_t control; 17 | uint32_t trust_lvl; 18 | } tmr_t; 19 | 20 | typedef struct tmr_cache 21 | { 22 | uint32_t present_mask; 23 | tmr_t tmr[TMR_NR_MAX+1]; 24 | } tmr_cache_t; 25 | 26 | 27 | /** 28 | * Initialize the TMR cache. 29 | */ 30 | void tmr_cache_init(void); 31 | 32 | /** 33 | * Clear the cached register values for the given TMR. Future reads/writes will 34 | * re-populate the cache. 35 | * 36 | * Parameters: 37 | * tmr : [in] TMR number (0-7) 38 | */ 39 | sev_status_t tmr_cache_invalidate(size_t tmr_nr); 40 | 41 | /** 42 | * Read the cached values of TMR registers. If the given TMR has not been 43 | * cached, read directly from the data fabric and cache the results. 44 | * 45 | * Parameters: 46 | * tmr : [in] TMR number (0-7) 47 | * base : [out] base address of trusted region 48 | * limit : [out] limit address of trusted region 49 | * control : [out] control flags 50 | * trust_lvl : [out] bit mask of entities allowed to access this trusted region 51 | * 52 | */ 53 | sev_status_t tmr_cache_read(size_t tmr_nr, uint64_t *base, uint64_t *limit, 54 | uint32_t *control, uint32_t *trust_lvl); 55 | 56 | /** 57 | * Write directly to the data fabric and update the values in the cache. 58 | * 59 | * Parameters: 60 | * tmr : [in] TMR number (0-7) 61 | * base : [in] base address of trusted region 62 | * limit : [in] limit address of trusted region 63 | * control : [in] control flags 64 | * trust_lvl : [in] bit mask of entities allowed to access this trusted region 65 | */ 66 | sev_status_t tmr_cache_write(size_t tmr_nr, uint64_t base, uint64_t limit, 67 | uint32_t control, uint32_t trust_lvl); 68 | 69 | /** 70 | * Read modify write the control register to set/clear bits. Update the tmr 71 | * cache afterwards. 72 | * 73 | * Parameters: 74 | * tmr : [in] TMR number (0-7) 75 | * flags : [in] TMR CTRL bits to set/clear 76 | * set : [in] to set or clear the bits/flags 77 | */ 78 | sev_status_t tmr_cache_modify_flags(size_t tmr_nr, uint32_t flags, bool set); 79 | 80 | #endif /* TMR_CACHE_H */ 81 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/umc.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef SEV_UAPP_UMC_H 4 | #define SEV_UAPP_UMC_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_status.h" 10 | 11 | /** 12 | * Copies 'size' bytes from 'key' into the key slot for 'asid' in all UMCs on 13 | * each die. 14 | */ 15 | sev_status_t set_umc_key(uint32_t asid, const uint8_t *seed, size_t size); 16 | 17 | /** 18 | * Checks the state of the memory encryption bits in the UMC configuration 19 | * registers. Returns true if memory encryption is enabled in the UMC, and 20 | * false otherwise. 21 | */ 22 | bool umc_encryption_enabled(void); 23 | 24 | #endif /* SEV_UAPP_UMC_H */ 25 | -------------------------------------------------------------------------------- /fw/psp_bl_uapps/sev_uapp/src/x86_copy.h: -------------------------------------------------------------------------------- 1 | // Copyright(C) 2016-2020 Advanced Micro Devices, Inc. All rights reserved. 2 | 3 | #ifndef X86_COPY_H 4 | #define X86_COPY_H 5 | 6 | #include 7 | #include 8 | 9 | #include "sev_errors.h" 10 | 11 | /* MASK for multiple of 2mb */ 12 | #define X86_2MB_SIZE (2*1024*1024ull) 13 | #define X86_2MB_MASK ~(X86_2MB_SIZE - 1ull) 14 | 15 | /* MASK for multiple 64 mb */ 16 | #define X86_64MB_SIZE (64*1024*1024ull) 17 | #define X86_64MB_MASK ~(X86_64MB_SIZE - 1ull) 18 | 19 | /* CBIT is located on bit 51 */ 20 | #define SEV_CBIT_SHIFT (51) 21 | #define SEV_CBIT_MASK (1ull << (SEV_CBIT_SHIFT)) 22 | 23 | /* CBIT_IS_SET - True if C-bit is set. False otherwise. */ 24 | /* CLEAR_CBIT - Takes in a x86_address to remove the C-bit */ 25 | /* SET_CBIT - Takes in a x86_address to set the C-bit */ 26 | #define CBIT_IS_SET(x86_addr) ((bool)((x86_addr) & SEV_CBIT_MASK)) 27 | #define CLEAR_CBIT(p) ((p) &= ~SEV_CBIT_MASK) 28 | #define SET_CBIT(p) ((p) |= SEV_CBIT_MASK) 29 | 30 | typedef enum x86_copy_op 31 | { 32 | COPY_PLAINTEXT_IN = 0, 33 | COPY_PLAINTEXT_OUT = 1, 34 | COPY_PLAINTEXT_IN_OUT = 2, 35 | COPY_CIPHERTEXT_IN = 3, 36 | COPY_CIPHERTEXT_OUT = 4, 37 | COPY_CIPHERTEXT_IN_OUT = 5, 38 | INFLATE_PLAINTEXT_OUT = 6, 39 | INFLATE_CIPHERTEXT_OUT = 7, 40 | } x86_copy_op_t; 41 | 42 | /** 43 | * Checks for overlap between two addresses and ignores the c-bit 44 | * 45 | * Parameters: 46 | * When using this function, please pass in exclusive comparisons. 47 | * Note the difference in end values in the example memories below 48 | * Ex: inclusive is 0x0:0x500 - 0x500:0x1000 49 | * Ex: exclusive is 0x0:0x4FF - 0x500:0x0FFF 50 | * 51 | * Return value: 52 | * true: ranges overlap, false: ranges don't overlap 53 | */ 54 | bool ranges_overlap(uint64_t start1, uint64_t end1, 55 | uint64_t start2, uint64_t end2); 56 | 57 | /** 58 | * Convert X86 address to data fabric address for SME 59 | * 60 | * Parameters: 61 | * x86_addr : pointer to x86 address and will be overwritten 62 | * with data fabric address for SME if enabled 63 | * 64 | * Return value: 65 | * SEV_STATUS_SUCCESS on success. 66 | * ERR_INVALID_PARAMS on invalid x86_addr pointer 67 | */ 68 | sev_status_t convert_x86_address(uint64_t *x86_addr); 69 | 70 | /** 71 | * Manage the way validate_address_range() checks 72 | * When doing 'internal' work, we need to avoid RMP 73 | * overlap checks. E.g., during rmp state lookups. 74 | */ 75 | void skip_rmp_addr_check(bool flag); 76 | 77 | /** 78 | * Ensure each command starts with RMP addr checks enforced 79 | */ 80 | void reset_rmp_addr_check(void); 81 | 82 | /** 83 | * Indicate whether to enforce CPU TMR address check or not 84 | * 85 | */ 86 | void skip_cpu_tmr_addr_check(bool flag); 87 | 88 | /** 89 | * Ensure each commmand starts with cpu TMR checks enforced 90 | */ 91 | void reset_cpu_tmr_addr_check(void); 92 | 93 | /** 94 | * Validate an address range from the x86. 95 | * 96 | * Parameters: 97 | * start : Starting address of the range to validate. (in) 98 | * size : Size of the range. (in) 99 | * 100 | * Return value: 101 | * SEV_STATUS_SUCCESS on success, 102 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 103 | * ERR_OUT_OF_RESOURCES if register mapping failed. 104 | */ 105 | sev_status_t validate_address_range(uint64_t start, uint64_t size); 106 | 107 | /** 108 | * Set the asid of an x86 address 109 | * 110 | * Parameters: 111 | * op : Operating being used. In certain cases, may use c-bit asid 112 | * instead of asid param 113 | * addr : x86 physical address 114 | * asid : ASID to append to addr 115 | * 116 | * Return value: 117 | * The value of addr with the asid appended 118 | */ 119 | uint64_t set_asid(x86_copy_op_t op, uint64_t addr, uint64_t asid); 120 | 121 | /** 122 | * Copy unencrypted data to/from x86 memory only if the address range is valid. 123 | * 124 | * Parameters: 125 | * x86_addr : Address to copy to/from. (in/out) 126 | * psp_addr : Address of a buffer in PSP private memory. (in/out) 127 | * size : Size of the region to copy. (in) 128 | * 129 | * Return value: 130 | * SEV_STATUS_SUCCESS on success, 131 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 132 | * ERR_OUT_OF_RESOURCES if register mapping failed. 133 | */ 134 | sev_status_t copy_to_x86(uint64_t x86_addr, void *psp_addr, uint64_t size); 135 | sev_status_t copy_from_x86(uint64_t x86_addr, void *psp_addr, uint64_t size); 136 | 137 | /** 138 | * Copy/move non asid-encrypted data from x86 memory to non asid-encrypted x86 139 | * memory only if the address ranges are valid. Source and destination may overlap. 140 | * 141 | * Parameters: 142 | * x86_src : Address to copy from. (in) 143 | * x86_dest : Address to copy to. (out) 144 | * size : Size of the region to copy. (in) 145 | * 146 | * Return value: 147 | * SEV_STATUS_SUCCESS on success, 148 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 149 | * ERR_OUT_OF_RESOURCES if register mapping failed. 150 | */ 151 | sev_status_t copy_to_x86_from_x86(uint64_t x86_dest, uint64_t x86_src, uint64_t size); 152 | 153 | /** 154 | * Copy encrypted data to/from x86 memory only if the address range is valid. 155 | * 156 | * Parameters: 157 | * x86_addr : Address to copy to/from. (in/out) 158 | * psp_addr : Address of a buffer in PSP private memory. (in/out) 159 | * size : Size of the region to copy. (in) 160 | * asid : ASID to use when accessing the memory. (in) 161 | * 162 | * Return value: 163 | * SEV_STATUS_SUCCESS on success, 164 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 165 | * ERR_OUT_OF_RESOURCES if register mapping failed. 166 | */ 167 | sev_status_t copy_to_x86_encrypted(uint64_t x86_addr, void *psp_addr, 168 | uint64_t size, uint32_t asid); 169 | sev_status_t copy_from_x86_encrypted(uint64_t x86_addr, void *psp_addr, 170 | uint64_t size, uint32_t asid); 171 | 172 | /** 173 | * Copy/move encrypted data from x86 memory to encrypted x86 memory only if 174 | * the address ranges are valid. Source and destination may overlap. 175 | * 176 | * Parameters: 177 | * x86_src : Address to copy from. (in) 178 | * x86_dest : Address to copy to. (out) 179 | * size : Size of the region to copy. (in) 180 | * asid : ASID to use when accessing the memory. (in) 181 | * 182 | * Return value: 183 | * SEV_STATUS_SUCCESS on success, 184 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 185 | * ERR_OUT_OF_RESOURCES if register mapping failed. 186 | */ 187 | sev_status_t copy_to_x86_encrypted_from_x86_encrypted(uint64_t x86_dest, uint64_t x86_src, 188 | uint64_t size, uint32_t asid); 189 | 190 | /** 191 | * Encrypt/Decrypt a memory region using the UMC. 192 | * 193 | * Parameters: 194 | * x86_src : Address to copy from. (in) 195 | * x86_dest : Address to copy to. (out) 196 | * psp_addr : Address of an intermediate buffer in PSP private memory. (in/out) 197 | * size : Size of the region to copy. (in) 198 | * asid : ASID to use when accessing the memory. (in) 199 | * 200 | * Return value: 201 | * SEV_STATUS_SUCCESS on success, 202 | * SEV_STATUS_INVALID_ADDRESS if the address fails a check, 203 | * ERR_OUT_OF_RESOURCES if register mapping failed. 204 | */ 205 | sev_status_t encrypt_memory(uint64_t x86_src, uint64_t x86_dest, 206 | void *psp_addr, uint32_t size, uint32_t asid); 207 | sev_status_t decrypt_memory(uint64_t x86_src, uint64_t x86_dest, 208 | void *psp_addr, uint32_t size, uint32_t asid); 209 | 210 | #endif /* X86_COPY_H */ 211 | --------------------------------------------------------------------------------