CVE-2021-36218 (C++, published 2021-09-27T14:15Z)
Description: value: An issue was discovered in SKALE sgxwallet 1.58.3. sgx_disp_ippsAES_GCMEncrypt allows an out-of-bounds write, resulting in a segfault and compromised enclave. This issue describes a buffer overflow, which was resolved prior to v1.77.0 and not reproducible in latest sgxwallet v1.77.0
Severity: MEDIUM (CVSS v3 base score: 7.5)
Weakness: CWE-787 \u2014 Out-of-bounds Write
The product writes data past the end, or before the beginning, of the intended buffer.
Repository: https://github.com/skalenetwork/sgxwallet
Files changed:
BLSCrypto.cpp
DKGCrypto.cpp
ECDSACrypto.cpp
SEKManager.cpp
SGXWalletServer.cpp
secure_enclave/AESUtils.c
secure_enclave/AESUtils.h
secure_enclave/secure_enclave.c
secure_enclave/secure_enclave.edl
testw.cpp
Commit message: SKALE-3205-restart


Vulnerable code:
    for (int j = 0; j < _len; j++) {
    int len = strnlen(_hex, 2 * _max_length + 1);
    for (int i = 0; i < len / 2; i++) {
    unsigned int encryptedLen = 0;
    uint32_t enc_len = 0;

    sgx_status_t status = trustedGenDkgSecretAES(eid, &errStatus, errMsg.data(), encrypted_dkg_secret.data(), &enc_len, _t);
        uint32_t decLen;
    uint32_t enc_bls_len = 0;
    uint32_t enc_len = 0;
    uint32_t enc_len;
    uint32_t l = 0;
    uint32_t enc_len = 0;
        if (public_keys.size() != n) {
int AES_encrypt(char *message, uint8_t *encr_message, uint64_t encrLen) {
    if (len + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE > encrLen ) {
    sgx_status_t status = sgx_rijndael128GCM_encrypt(&AES_key, (uint8_t*)message, strlen(message),
  return status;
}




int AES_encrypt_DH(char *message, uint8_t *encr_message, uint64_t encrLen) {

    if (!message) {
        LOG_ERROR("Null message in AES_encrypt_DH");
        return -1;
    }

    if (!encr_message) {
        LOG_ERROR("Null encr message in AES_encrypt_DH");
        return -2;
    }

    uint64_t len = strlen(message) + 1;

    if (len + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE > encrLen ) {
        LOG_ERROR("Output buffer too small");
        return -3;
    }

    sgx_read_rand(encr_message + SGX_AESGCM_MAC_SIZE, SGX_AESGCM_IV_SIZE);

    sgx_status_t status = sgx_rijndael128GCM_encrypt(&AES_DH_key, (uint8_t*)message, strlen(message),
                                                     encr_message + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE,
                                                     encr_message + SGX_AESGCM_MAC_SIZE, SGX_AESGCM_IV_SIZE,
                                                     NULL, 0,
                                                     (sgx_aes_gcm_128bit_tag_t *) encr_message);
    return status;
int AES_decrypt_DH(uint8_t *encr_message, uint64_t length, char *message, uint64_t msgLen) {
    if (!message) {
        LOG_ERROR("Null message in AES_encrypt_DH");
        return -1;
    }

    if (!encr_message) {
        LOG_ERROR("Null encr message in AES_encrypt_DH");
        return -2;
    }


    if (length < SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE) {
        LOG_ERROR("length < SGX_AESGCM_MAC_SIZE - SGX_AESGCM_IV_SIZE");
        return -1;
    }
    uint64_t len = length - SGX_AESGCM_MAC_SIZE - SGX_AESGCM_IV_SIZE;
    if (msgLen < len) {
        LOG_ERROR("Output buffer not large enough");
        return -2;
    }

    sgx_status_t status = sgx_rijndael128GCM_decrypt(&AES_DH_key,
                                                     encr_message + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE, len,
                                                     (unsigned char*) message,
                                                     encr_message + SGX_AESGCM_MAC_SIZE, SGX_AESGCM_IV_SIZE,
                                                     NULL, 0,
                                                     (sgx_aes_gcm_128bit_tag_t *)encr_message);

    return status;
}
int AES_encrypt(char *message, uint8_t *encr_message, uint64_t encrLen);
void trustedEnclaveInit(uint32_t _logLevel) {
                        uint8_t *encrypted_sek, uint32_t *enc_len, char *sek_hex) {
    uint32_t encrypt_text_length = sgx_get_encrypt_txt_len((const sgx_sealed_data_t *)encrypted_sek);
    uint32_t add_text_length = sgx_get_add_mac_txt_len((const sgx_sealed_data_t *)encrypted_sek);
                        uint8_t *encrypted_sek, uint32_t *enc_len, char *sek_hex) {
                          uint8_t *encrypted_sek, uint32_t *enc_len, const char *sek_hex) {
                                uint8_t *encryptedPrivateKey, uint32_t *enc_len, char *pub_key_x, char *pub_key_y) {
    SAFE_CHAR_BUF(skey_str, ECDSA_SKEY_LEN);SAFE_CHAR_BUF(arr_skey_str, mpz_sizeinbase(skey, ECDSA_SKEY_BASE) + 2);
    skey_str[ECDSA_SKEY_LEN - 1] = 0;
    int status = AES_encrypt((char *) skey_str, encryptedPrivateKey, BUF_LEN);
    *enc_len = strlen(skey_str) + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE;

    status = AES_decrypt(encryptedPrivateKey, *enc_len, skey_str, ECDSA_SKEY_LEN);
                                 uint8_t *encryptedPrivateKey, uint32_t enc_len, char *pub_key_x, char *pub_key_y) {
    SAFE_CHAR_BUF(skey, ECDSA_SKEY_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, ECDSA_SKEY_LEN);
void trustedEcdsaSignAES(int *errStatus, char *errString, uint8_t *encryptedPrivateKey, uint32_t enc_len,
    SAFE_CHAR_BUF(skey, ECDSA_SKEY_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, ECDSA_SKEY_LEN);
                          uint32_t enc_len, char *key) {
    int status = AES_decrypt_DH(encryptedPrivateKey, enc_len, key, 3072);
                          uint8_t *encryptedPrivateKey, uint32_t *enc_len) {
    int status = AES_encrypt_DH((char *)key, encryptedPrivateKey, BUF_LEN);
    *enc_len = strlen(key) + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE;

    status = AES_decrypt_DH(encryptedPrivateKey, *enc_len, decryptedKey, BUF_LEN);
                              uint32_t enc_len, char *_hashX,
trustedGenDkgSecretAES(int *errStatus, char *errString, uint8_t *encrypted_dkg_secret, uint32_t *enc_len, size_t _t) {
    status = AES_encrypt(dkg_secret, encrypted_dkg_secret, 3 * BUF_LEN);
    *enc_len = strlen(dkg_secret) + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE;
                           uint32_t enc_len,
void trustedSetEncryptedDkgPolyAES(int *errStatus, char *errString, uint8_t *encrypted_poly, uint32_t enc_len) {
void trustedGetEncryptedSecretShareAES(int *errStatus, char *errString, uint8_t *encrypted_skey, uint32_t *dec_len,
    uint32_t enc_len;
    SAFE_CHAR_BUF(skey, ECDSA_SKEY_LEN);
    status = AES_decrypt(encrypted_skey, enc_len, skey, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(common_key, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(s_share, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(cypher, ECDSA_SKEY_LEN);
void trustedGetPublicSharesAES(int *errStatus, char *errString, uint8_t *encrypted_dkg_secret, uint32_t enc_len,
    SAFE_CHAR_BUF(skey, ECDSA_SKEY_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(encr_sshare, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(common_key, ECDSA_SKEY_LEN);
    SAFE_CHAR_BUF(decr_sshare, ECDSA_SKEY_LEN);
                            uint32_t *enc_bls_key_len) {
    SAFE_CHAR_BUF(skey, ECDSA_SKEY_LEN);
    int status = AES_decrypt(encryptedPrivateKey, key_len, skey, ECDSA_SKEY_LEN);
    status = AES_encrypt(key_share, encr_bls_key, BUF_LEN);
    *enc_bls_key_len = strlen(key_share) + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE;

    SAFE_CHAR_BUF(skey_hex, ECDSA_SKEY_LEN);
    int status = AES_decrypt(encryptedPrivateKey, key_len, skey_hex, ECDSA_SKEY_LEN);
		public void trustedEnclaveInit(uint32_t _logLevel);
                                [out] uint32_t *enc_len,
                                [out] uint32_t *enc_len,
                                [out] uint32_t *enc_len,
                                uint32_t dec_len,
                                uint32_t enc_len,
                                [out] uint32_t *enc_len);
                                uint32_t enc_len,
                                [out] uint32_t * enc_len, size_t _t);
                                uint32_t enc_len,
                                uint32_t enc_len);
                                [out] uint32_t* dec_len,
                                uint32_t enc_len,
                                [out] uint32_t *enc_bls_key_len);
                                uint32_t enc_len,
    uint32_t encLen = 0;
    uint32_t encLen = 0;
    uint32_t encLen = 0;
    uint32_t encLen = 0;
    uint32_t encLen = 0;
    uint32_t encLen = 0;
    uint32_t encLen;

Fixed code:
    for (uint64_t j = 0; j < _len; j++) {
    uint64_t len = strnlen(_hex, 2 * _max_length + 1);
    for (uint64_t i = 0; i < len / 2; i++) {

    uint64_t encryptedLen = 0;
    uint64_t enc_len = 0;
    sgx_status_t status = trustedGenDkgSecretAES(
            eid, &errStatus,errMsg.data(), encrypted_dkg_secret.data(), &enc_len, _t);
        uint64_t decLen;
    uint64_t enc_bls_len = 0;
    uint64_t enc_len = 0;
    uint64_t enc_len;
    uint64_t l = 0;
    uint64_t enc_len = 0;
        if (public_keys.size() != (uint64_t)n) {


#define SAFE_CHAR_BUF(__X__, __Y__)  ;char __X__ [ __Y__ ]; memset(__X__, 0, __Y__);

int AES_encrypt(char *message, uint8_t *encr_message, uint64_t encrBufLen, unsigned  char type,
                unsigned char decryptable, uint64_t* resultLen) {



    if (!type) {
        LOG_ERROR("Null type in AES_encrypt");
        return -1;
    }
    if (2 + len + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE > encrBufLen ) {
    SAFE_CHAR_BUF(fullMessage, len + 2);

    fullMessage[0] = type;
    fullMessage[1] = decryptable;

    strncpy(fullMessage + 2, message, len );

    len = len + 2;
    message = fullMessage;

    sgx_status_t status = sgx_rijndael128GCM_encrypt(&AES_key, (uint8_t*)message, len,
    *resultLen = len + SGX_AESGCM_MAC_SIZE + SGX_AESGCM_IV_SIZE;

  for (int i = 2; i < strlen(message) + 1; i++) {
      message[i - 2 ] = message[i];
  }
  return status;
int AES_encrypt(char *message, uint8_t *encr_message, uint64_t encrLen,
                unsigned char type, unsigned char decryptable, uint64_t* resultLen);
#define ECDSA '1'
#define BLS '2'
#define DKG '3'

#define DECRYPTABLE '1'
#define NON_DECRYPTABLE '2'


void trustedEnclaveInit(uint64_t _logLevel) {
                        uint8_t *encrypted_sek, uint64_t *enc_len, char *sek_hex) {
    uint64_t encrypt_text_length = sgx_get_encrypt_txt_len((const sgx_sealed_data_t *)encrypted_sek);
    uint64_t add_text_length = sgx_get_add_mac_txt_len((const sgx_sealed_data_t *)encrypted_sek);
                        uint8_t *encrypted_sek, uint64_t *enc_len, char *sek_hex) {
                          uint8_t *encrypted_sek, uint64_t *enc_len, const char *sek_hex) {
                                uint8_t *encryptedPrivateKey, uint64_t *enc_len, char *pub_key_x, char *pub_key_y) {
    SAFE_CHAR_BUF(skey_str, BUF_LEN);
    SAFE_CHAR_BUF(arr_skey_str, mpz_sizeinbase(skey, ECDSA_SKEY_BASE) + 2);
    int status = AES_encrypt((char *) skey_str, encryptedPrivateKey, BUF_LEN,
                             ECDSA, NON_DECRYPTABLE, enc_len);
    status = AES_decrypt(encryptedPrivateKey, *enc_len, skey_str, BUF_LEN);
                                 uint8_t *encryptedPrivateKey, uint64_t enc_len, char *pub_key_x, char *pub_key_y) {
    SAFE_CHAR_BUF(skey, BUF_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, BUF_LEN);
void trustedEcdsaSignAES(int *errStatus, char *errString, uint8_t *encryptedPrivateKey, uint64_t enc_len,
    SAFE_CHAR_BUF(skey, BUF_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, BUF_LEN);
                          uint64_t enc_len, char *key) {
    int status = AES_decrypt(encryptedPrivateKey, enc_len, key, 3072);
                          uint8_t *encryptedPrivateKey, uint64_t *enc_len) {
    int status = AES_encrypt((char *)key, encryptedPrivateKey, BUF_LEN,
                             DKG, DECRYPTABLE, enc_len);
    status = AES_decrypt(encryptedPrivateKey, *enc_len, decryptedKey, BUF_LEN);
        LOG_ERROR(key);
        LOG_ERROR(decryptedKey);
                              uint64_t enc_len, char *_hashX,
trustedGenDkgSecretAES(int *errStatus, char *errString, uint8_t *encrypted_dkg_secret, uint64_t *enc_len, size_t _t) {
    status = AES_encrypt(dkg_secret, encrypted_dkg_secret, 3 * BUF_LEN,
                         DKG, DECRYPTABLE, enc_len);

                           uint64_t enc_len,
void trustedSetEncryptedDkgPolyAES(int *errStatus, char *errString, uint8_t *encrypted_poly, uint64_t enc_len) {
void trustedGetEncryptedSecretShareAES(int *errStatus, char *errString, uint8_t *encrypted_skey, uint64_t *dec_len,
    uint64_t enc_len;
    SAFE_CHAR_BUF(skey, BUF_LEN);
    status = AES_decrypt(encrypted_skey, enc_len, skey, BUF_LEN);
    SAFE_CHAR_BUF(common_key, BUF_LEN);
    SAFE_CHAR_BUF(s_share, BUF_LEN);
    SAFE_CHAR_BUF(cypher, BUF_LEN);
void trustedGetPublicSharesAES(int *errStatus, char *errString, uint8_t *encrypted_dkg_secret, uint64_t enc_len,
    SAFE_CHAR_BUF(skey,BUF_LEN);
    int status = AES_decrypt(encryptedPrivateKey, enc_len, skey, BUF_LEN);
    SAFE_CHAR_BUF(encr_sshare, BUF_LEN);
    SAFE_CHAR_BUF(common_key, BUF_LEN);
    SAFE_CHAR_BUF(decr_sshare, BUF_LEN);
                            uint64_t *enc_bls_key_len) {
    SAFE_CHAR_BUF(skey, BUF_LEN);
    int status = AES_decrypt(encryptedPrivateKey, key_len, skey, BUF_LEN);
    status = AES_encrypt(key_share, encr_bls_key, BUF_LEN, BLS, NON_DECRYPTABLE, enc_bls_key_len);
    SAFE_CHAR_BUF(skey_hex, BUF_LEN);
    int status = AES_decrypt(encryptedPrivateKey, key_len, skey_hex, BUF_LEN);
		public void trustedEnclaveInit(uint64_t _logLevel);
                                [out] uint64_t *enc_len,
                                [out] uint64_t *enc_len,
                                [out] uint64_t *enc_len,
                                uint64_t dec_len,
                                uint64_t enc_len,
                                [out] uint64_t *enc_len);
                                uint64_t enc_len,
                                [out] uint64_t * enc_len, size_t _t);
                                uint64_t enc_len,
                                uint64_t enc_len);
                                [out] uint64_t* dec_len,
                                uint64_t enc_len,
                                [out] uint64_t *enc_bls_key_len);
                                uint64_t enc_len,
    uint64_t encLen = 0;
    uint64_t encLen = 0;

    uint64_t encLen = 0;
    uint64_t encLen = 0;
    uint64_t encLen = 0;
    uint64_t encLen = 0;
    uint64_t encLen;