Browse Source

[Pal] Fix errors returned from mbedTLS crypto adapter

Most errors returned from mbedTLS functions were not converted to PAL errors.
This commit adds a separate PAL-error code block for crypto errors.
Rafał Wojdyła 4 years ago
parent
commit
a04e71c7fa

+ 8 - 4
LibOS/shim/src/shim_init.c

@@ -54,7 +54,11 @@ static void handle_failure (PAL_PTR event, PAL_NUM arg, PAL_CONTEXT * context)
 {
     __UNUSED(event);
     __UNUSED(context);
-    shim_get_tls()->pal_errno = (arg <= PAL_ERROR_BOUND) ? arg : 0;
+    if ((arg <= PAL_ERROR_NATIVE_COUNT) || (arg >= PAL_ERROR_CRYPTO_START &&
+        arg <= PAL_ERROR_CRYPTO_END))
+        shim_get_tls()->pal_errno = arg;
+    else
+        shim_get_tls()->pal_errno = PAL_ERROR_DENIED;
 }
 
 noreturn void __abort(void) {
@@ -75,7 +79,7 @@ void __stack_chk_fail (void)
 {
 }
 
-static int pal_errno_to_unix_errno [PAL_ERROR_BOUND + 1] = {
+static int pal_errno_to_unix_errno [PAL_ERROR_NATIVE_COUNT + 1] = {
         /* reserved                 */  0,
         /* PAL_ERROR_NOTIMPLEMENTED */  ENOSYS,
         /* PAL_ERROR_NOTDEFINED     */  ENOSYS,
@@ -106,8 +110,8 @@ static int pal_errno_to_unix_errno [PAL_ERROR_BOUND + 1] = {
 
 long convert_pal_errno (long err)
 {
-    return (err >= 0 && err <= PAL_ERROR_BOUND) ?
-           pal_errno_to_unix_errno[err] : 0;
+    return (err >= 0 && err <= PAL_ERROR_NATIVE_COUNT) ?
+           pal_errno_to_unix_errno[err] : EACCES;
 }
 
 /*!

+ 1 - 1
LibOS/shim/src/shim_object.c

@@ -8,7 +8,7 @@ int object_wait_with_retry(PAL_HANDLE handle) {
     } while (ret == NULL &&
              (PAL_NATIVE_ERRNO == PAL_ERROR_INTERRUPTED || PAL_NATIVE_ERRNO == PAL_ERROR_TRYAGAIN));
     if (ret == NULL) {
-        debug("waiting on %p resulted in error %s", handle, PAL_STRERROR(PAL_NATIVE_ERRNO));
+        debug("waiting on %p resulted in error %s", handle, pal_strerror(PAL_NATIVE_ERRNO));
         return -PAL_NATIVE_ERRNO;
     }
     assert(ret == handle);

+ 106 - 37
Pal/lib/crypto/adapters/mbedtls_adapter.c

@@ -24,10 +24,86 @@
 #include "pal_error.h"
 #include "pal_debug.h"
 #include "assert.h"
+#include "crypto/mbedtls/mbedtls/aes.h"
 #include "crypto/mbedtls/mbedtls/cmac.h"
 #include "crypto/mbedtls/mbedtls/sha256.h"
 #include "crypto/mbedtls/mbedtls/rsa.h"
 
+int mbedtls_to_pal_error(int error)
+{
+    switch(error) {
+        case 0:
+            return 0;
+
+        case MBEDTLS_ERR_AES_INVALID_KEY_LENGTH:
+            return -PAL_ERROR_CRYPTO_INVALID_KEY_LENGTH;
+
+        case MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH:
+        case MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED:
+            return -PAL_ERROR_CRYPTO_INVALID_INPUT_LENGTH;
+
+        case MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE:
+        case MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE:
+            return -PAL_ERROR_CRYPTO_FEATURE_UNAVAILABLE;
+
+        case MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_DHM_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_MD_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_MPI_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_RSA_BAD_INPUT_DATA:
+        case MBEDTLS_ERR_RSA_PUBLIC_FAILED: // see mbedtls_rsa_public()
+        case MBEDTLS_ERR_RSA_PRIVATE_FAILED: // see mbedtls_rsa_private()
+            return -PAL_ERROR_CRYPTO_BAD_INPUT_DATA;
+
+        case MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE:
+            return -PAL_ERROR_CRYPTO_INVALID_OUTPUT_LENGTH;
+
+        case MBEDTLS_ERR_CIPHER_ALLOC_FAILED:
+        case MBEDTLS_ERR_DHM_ALLOC_FAILED:
+        case MBEDTLS_ERR_MD_ALLOC_FAILED:
+            return -PAL_ERROR_NOMEM;
+
+        case MBEDTLS_ERR_CIPHER_INVALID_PADDING:
+        case MBEDTLS_ERR_RSA_INVALID_PADDING:
+            return -PAL_ERROR_CRYPTO_INVALID_PADDING;
+
+        case MBEDTLS_ERR_CIPHER_AUTH_FAILED:
+            return -PAL_ERROR_CRYPTO_AUTH_FAILED;
+
+        case MBEDTLS_ERR_CIPHER_INVALID_CONTEXT:
+            return -PAL_ERROR_CRYPTO_INVALID_CONTEXT;
+
+        case MBEDTLS_ERR_DHM_READ_PARAMS_FAILED:
+        case MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED:
+        case MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED:
+        case MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED:
+        case MBEDTLS_ERR_DHM_CALC_SECRET_FAILED:
+            return -PAL_ERROR_CRYPTO_INVALID_DH_STATE;
+
+        case MBEDTLS_ERR_DHM_INVALID_FORMAT:
+            return -PAL_ERROR_CRYPTO_INVALID_FORMAT;
+
+        case MBEDTLS_ERR_DHM_FILE_IO_ERROR:
+        case MBEDTLS_ERR_MD_FILE_IO_ERROR:
+            return -PAL_ERROR_CRYPTO_IO_ERROR;
+
+        case MBEDTLS_ERR_RSA_KEY_GEN_FAILED:
+            return -PAL_ERROR_CRYPTO_KEY_GEN_FAILED;
+
+        case MBEDTLS_ERR_RSA_KEY_CHECK_FAILED:
+            return -PAL_ERROR_CRYPTO_INVALID_KEY;
+
+        case MBEDTLS_ERR_RSA_VERIFY_FAILED:
+            return -PAL_ERROR_CRYPTO_VERIFY_FAILED;
+
+        case MBEDTLS_ERR_RSA_RNG_FAILED:
+            return -PAL_ERROR_CRYPTO_RNG_FAILED;
+
+        default:
+            return -PAL_ERROR_DENIED;
+    }
+}
+
 #define BITS_PER_BYTE 8
 
 /* This is declared in pal_internal.h, but that can't be included here. */
@@ -98,16 +174,13 @@ int lib_AESCMAC(const uint8_t *key, uint64_t key_len, const uint8_t *input,
         return -PAL_ERROR_INVAL;
     }
 
-    return mbedtls_cipher_cmac(cipher_info,
-                               key, key_len * BITS_PER_BYTE,
-                               input, input_len, mac);
+    int ret = mbedtls_cipher_cmac(cipher_info, key, key_len * BITS_PER_BYTE, input, input_len, mac);
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_AESCMACInit(LIB_AESCMAC_CONTEXT * context,
                     const uint8_t *key, uint64_t key_len)
 {
-    int ret;
-
     switch (key_len) {
     case 16:
         context->cipher = MBEDTLS_CIPHER_AES_128_ECB;
@@ -125,17 +198,19 @@ int lib_AESCMACInit(LIB_AESCMAC_CONTEXT * context,
     const mbedtls_cipher_info_t *cipher_info =
         mbedtls_cipher_info_from_type(context->cipher);
 
-    if ( ( ret = mbedtls_cipher_setup( &context->ctx, cipher_info ) ) != 0 )
-        return ret;
+    int ret = mbedtls_cipher_setup(&context->ctx, cipher_info);
+    if (ret != 0)
+        return mbedtls_to_pal_error(ret);
 
-    return mbedtls_cipher_cmac_starts( &context->ctx, key,
-                                       key_len * BITS_PER_BYTE );
+    ret = mbedtls_cipher_cmac_starts(&context->ctx, key, key_len * BITS_PER_BYTE);
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_AESCMACUpdate(LIB_AESCMAC_CONTEXT * context, const uint8_t * input,
                       uint64_t input_len)
 {
-    return mbedtls_cipher_cmac_update( &context->ctx, input, input_len );
+    int ret = mbedtls_cipher_cmac_update(&context->ctx, input, input_len);
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_AESCMACFinish(LIB_AESCMAC_CONTEXT * context, uint8_t * mac,
@@ -148,11 +223,12 @@ int lib_AESCMACFinish(LIB_AESCMAC_CONTEXT * context, uint8_t * mac,
     if (mac_len < cipher_info->block_size)
         goto exit;
 
-    ret = mbedtls_cipher_cmac_finish( &context->ctx, mac );
+    ret = mbedtls_cipher_cmac_finish(&context->ctx, mac);
+    ret = mbedtls_to_pal_error(ret);
 
 exit:
     mbedtls_cipher_free( &context->ctx );
-    return( ret );
+    return ret;
 }
 
 int lib_RSAInitKey(LIB_RSA_KEY *key)
@@ -171,31 +247,27 @@ int lib_RSAInitKey(LIB_RSA_KEY *key)
 
 int lib_RSAGenerateKey(LIB_RSA_KEY *key, uint64_t length_in_bits, uint64_t exponent)
 {
-    if (length_in_bits > UINT_MAX) {
+    if (length_in_bits > UINT_MAX)
         return -PAL_ERROR_INVAL;
-    }
-    if (exponent > UINT_MAX || (int) exponent < 0) {
+
+    if (exponent > UINT_MAX || (int) exponent < 0)
         return -PAL_ERROR_INVAL;
-    }
-    return mbedtls_rsa_gen_key(key, RandomWrapper, NULL, length_in_bits,
-                               exponent);
+
+    int ret = mbedtls_rsa_gen_key(key, RandomWrapper, NULL, length_in_bits, exponent);
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_RSAExportPublicKey(LIB_RSA_KEY *key, uint8_t *e, uint64_t *e_size,
                            uint8_t *n, uint64_t *n_size)
 {
-    int ret;
-
     /* Public exponent. */
-    if ((ret = mbedtls_mpi_write_binary(&key->E, e, *e_size)) != 0) {
-        return ret;
-    }
+    int ret = mbedtls_mpi_write_binary(&key->E, e, *e_size);
+    if (ret != 0)
+        return mbedtls_to_pal_error(ret);
 
     /* Modulus. */
-    if ((ret = mbedtls_mpi_write_binary(&key->N, n, *n_size)) != 0) {
-        return ret;
-    }
-    return 0;
+    ret = mbedtls_mpi_write_binary(&key->N, n, *n_size);
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_RSAImportPublicKey(LIB_RSA_KEY *key, const uint8_t *e, uint64_t e_size,
@@ -204,14 +276,14 @@ int lib_RSAImportPublicKey(LIB_RSA_KEY *key, const uint8_t *e, uint64_t e_size,
     int ret;
 
     /* Public exponent. */
-    if ((ret = mbedtls_mpi_read_binary(&key->E, e, e_size)) != 0) {
-        return ret;
-    }
+    ret = mbedtls_mpi_read_binary(&key->E, e, e_size);
+    if (ret != 0)
+        return mbedtls_to_pal_error(ret);
 
     /* Modulus. */
-    if ((ret = mbedtls_mpi_read_binary(&key->N, n, n_size)) != 0) {
-        return ret;
-    }
+    ret = mbedtls_mpi_read_binary(&key->N, n, n_size);
+    if (ret != 0)
+        return mbedtls_to_pal_error(ret);
 
     /* This length is in bytes. */
     key->len = (mbedtls_mpi_bitlen(&key->N) + 7) >> 3;
@@ -232,10 +304,7 @@ int lib_RSAVerifySHA256(LIB_RSA_KEY* key, const uint8_t* hash, uint64_t hash_len
     int ret = mbedtls_rsa_pkcs1_verify(key, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA256,
                                        hash_len, hash, signature);
 
-    if (ret < 0)
-        return -PAL_ERROR_DENIED;
-
-    return 0;
+    return mbedtls_to_pal_error(ret);
 }
 
 int lib_RSAFreeKey(LIB_RSA_KEY *key)

+ 6 - 0
Pal/lib/crypto/adapters/mbedtls_adapter.h

@@ -0,0 +1,6 @@
+#ifndef MBEDTLS_ADAPTER_H
+#define MBEDTLS_ADAPTER_H
+
+int mbedtls_to_pal_error(int error);
+
+#endif

+ 7 - 5
Pal/lib/crypto/adapters/mbedtls_dh.c

@@ -20,6 +20,7 @@
 
 #include "api.h"
 #include "assert.h"
+#include "mbedtls_adapter.h"
 #include "pal.h"
 #include "pal_crypto.h"
 #include "pal_debug.h"
@@ -49,13 +50,13 @@ int lib_DhInit(LIB_DH_CONTEXT* context) {
     ret = mbedtls_mpi_read_string(&context->P, 16 /* radix */, MBEDTLS_DHM_RFC3526_MODP_2048_P);
     if (ret != 0) {
         pal_printf("D-H initialization failed: %d\n", ret);
-        return ret;
+        return mbedtls_to_pal_error(ret);
     }
 
     ret = mbedtls_mpi_read_string(&context->G, 16 /* radix */, MBEDTLS_DHM_RFC3526_MODP_2048_G);
     if (ret != 0) {
         pal_printf("D-H initialization failed: %d\n", ret);
-        return ret;
+        return mbedtls_to_pal_error(ret);
     }
 
     context->len = mbedtls_mpi_size(&context->P);
@@ -72,7 +73,7 @@ int lib_DhCreatePublic(LIB_DH_CONTEXT* context, uint8_t* public, uint64_t* publi
     /* The RNG here is used to generate secret exponent X. */
     ret = mbedtls_dhm_make_public(context, context->len, public, *public_size, RandomWrapper, NULL);
     if (ret != 0)
-        return ret;
+        return mbedtls_to_pal_error(ret);
 
     /* mbedtls writes leading zeros in the big-endian output to pad to
      * public_size, so leave caller's public_size unchanged */
@@ -88,12 +89,13 @@ int lib_DhCalcSecret(LIB_DH_CONTEXT* context, uint8_t* peer, uint64_t peer_size,
 
     ret = mbedtls_dhm_read_public(context, peer, peer_size);
     if (ret != 0)
-        return ret;
+        return mbedtls_to_pal_error(ret);
 
     /* The RNG here is used for blinding against timing attacks if X is
      * reused and not used otherwise. mbedtls recommends always passing
      * in an RNG. */
-    return mbedtls_dhm_calc_secret(context, secret, *secret_size, secret_size, RandomWrapper, NULL);
+    ret = mbedtls_dhm_calc_secret(context, secret, *secret_size, secret_size, RandomWrapper, NULL);
+    return mbedtls_to_pal_error(ret);
 }
 
 void lib_DhFinal(LIB_DH_CONTEXT* context) {

+ 1 - 1
Pal/regression/normalize_path.c

@@ -59,7 +59,7 @@ static int run_test(void) {
         int ret     = func_to_test(cases[i][0], buf, &size);
 
         if (ret < 0) {
-            print_err(func_name, i, "failed with error: %s\n", PAL_STRERROR(ret));
+            print_err(func_name, i, "failed with error: %s\n", pal_strerror(ret));
             return 1;
         }
 

+ 1 - 1
Pal/src/Makefile

@@ -39,7 +39,7 @@ defs	= -DIN_PAL -DHOST_TYPE="$(PAL_HOST)" -D$(PAL_HOST_MACRO) -DPAL_DIR=$(PAL_DI
 	  -DRUNTIME_DIR=$(RUNTIME_DIR)
 CFLAGS += $(defs)
 objs	= $(addprefix db_,streams memory threading mutex events process \
-	    object main misc ipc exception rtld) slab printf
+	    object main misc ipc exception rtld) slab printf pal_error
 
 graphene_lib = $(LIB_DIR)/graphene-lib.a
 host_lib = $(HOST_DIR)/libpal-$(PAL_HOST).a

+ 1 - 1
Pal/src/db_main.c

@@ -420,7 +420,7 @@ noreturn void pal_main (
         }
 
         if (ret < 0)
-            INIT_FAIL(ret, PAL_STRERROR(ret));
+            INIT_FAIL(ret, pal_strerror(ret));
 
 #if PROFILING == 1
         pal_state.linking_time += _DkSystemTimeQuery() - before_load_exec;

+ 1 - 1
Pal/src/host/FreeBSD/db_main.c

@@ -248,7 +248,7 @@ void pal_bsd_main (void * args)
     char * path = (void *) file + HANDLE_SIZE(file);
     int ret = get_norm_path(argv[0], path, &len);
     if (ret < 0) {
-        printf("Could not normalize path (%s): %s\n", argv[0], PAL_STRERROR(ret));
+        printf("Could not normalize path (%s): %s\n", argv[0], pal_strerror(ret));
         goto done_init;
     }
     file->file.realpath = path;

+ 2 - 2
Pal/src/host/Linux-SGX/db_files.c

@@ -62,7 +62,7 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
     char* path       = (void*)hdl + HANDLE_SIZE(file);
     int ret;
     if ((ret = get_norm_path(uri, path, &len)) < 0) {
-        SGX_DBG(DBG_E, "Could not normalize path (%s): %s\n", uri, PAL_STRERROR(ret));
+        SGX_DBG(DBG_E, "Could not normalize path (%s): %s\n", uri, pal_strerror(ret));
         free(hdl);
         return ret;
     }
@@ -75,7 +75,7 @@ static int file_open(PAL_HANDLE* handle, const char* type, const char* uri, int
         SGX_DBG(DBG_E,
                 "Accessing file:%s is denied. (%s) "
                 "This file is not trusted or allowed.\n",
-                hdl->file.realpath, PAL_STRERROR(ret));
+                hdl->file.realpath, pal_strerror(ret));
         free(hdl);
         return ret;
     }

+ 1 - 1
Pal/src/host/Linux-SGX/db_main.c

@@ -109,7 +109,7 @@ static PAL_HANDLE setup_dummy_file_handle (const char * name)
     char * path = (void *) handle + HANDLE_SIZE(file);
     int ret = get_norm_path(name, path, &len);
     if (ret < 0) {
-        SGX_DBG(DBG_E, "Could not normalize path (%s): %s\n", name, PAL_STRERROR(ret));
+        SGX_DBG(DBG_E, "Could not normalize path (%s): %s\n", name, pal_strerror(ret));
         free(handle);
         return NULL;
     }

+ 2 - 2
Pal/src/host/Linux-SGX/enclave_framework.c

@@ -291,7 +291,7 @@ int load_trusted_file (PAL_HANDLE file, sgx_stub_t ** stubptr,
     size_t len = sizeof(normpath) - 5;
     ret = get_norm_path(uri + 5, normpath + 5, &len);
     if (ret < 0) {
-        SGX_DBG(DBG_E, "Path (%s) normalization failed: %s\n", uri + 5, PAL_STRERROR(ret));
+        SGX_DBG(DBG_E, "Path (%s) normalization failed: %s\n", uri + 5, pal_strerror(ret));
         return ret;
     }
     len += 5;
@@ -718,7 +718,7 @@ static int init_trusted_file (const char * key, const char * uri)
     size_t len = sizeof(normpath) - 5;
     ret = get_norm_path(uri + 5, normpath + 5, &len);
     if (ret < 0) {
-        SGX_DBG(DBG_E, "Path (%s) normalization failed: %s\n", uri + 5, PAL_STRERROR(ret));
+        SGX_DBG(DBG_E, "Path (%s) normalization failed: %s\n", uri + 5, pal_strerror(ret));
         return ret;
     }
 

+ 1 - 1
Pal/src/host/Linux/db_main.c

@@ -297,7 +297,7 @@ void pal_linux_main (void * args)
     char * path = (void *) file + HANDLE_SIZE(file);
     int ret = get_norm_path(argv[0], path, &len);
     if (ret < 0) {
-        printf("Could not normalize path (%s): %s\n", argv[0], PAL_STRERROR(ret));
+        printf("Could not normalize path (%s): %s\n", argv[0], pal_strerror(ret));
         goto done_init;
     }
     file->file.realpath = path;

+ 1 - 0
Pal/src/pal-symbols

@@ -48,3 +48,4 @@ DkDebugAttachBinary
 DkDebugDetachBinary
 pal_printf
 pal_control_addr
+pal_strerror

+ 77 - 0
Pal/src/pal_error.c

@@ -0,0 +1,77 @@
+/* Copyright (C) 2014 Stony Brook University
+   This file is part of Graphene Library OS.
+
+   Graphene Library OS is free software: you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public License
+   as published by the Free Software Foundation, either version 3 of the
+   License, or (at your option) any later version.
+
+   Graphene Library OS is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "pal_error.h"
+
+struct pal_error_description {
+    int         error;
+    const char* description;
+};
+
+static const struct pal_error_description pal_error_list[] = {
+    { PAL_ERROR_SUCCESS, "Success" },
+    { PAL_ERROR_NOTIMPLEMENTED, "Function not implemented" },
+    { PAL_ERROR_NOTDEFINED, "Symbol not defined" },
+    { PAL_ERROR_NOTSUPPORT, "Function not supported" },
+    { PAL_ERROR_INVAL, "Invalid argument" },
+    { PAL_ERROR_TOOLONG, "Name/path is too long" },
+    { PAL_ERROR_DENIED, "Operation denied" },
+    { PAL_ERROR_BADHANDLE, "Handle corrupted" },
+    { PAL_ERROR_STREAMEXIST, "Stream already exists" },
+    { PAL_ERROR_STREAMNOTEXIST, "Stream does not exist" },
+    { PAL_ERROR_STREAMISFILE, "Stream is a file" },
+    { PAL_ERROR_STREAMISDIR, "Stream is a directory" },
+    { PAL_ERROR_STREAMISDEVICE, "Stream is a device" },
+    { PAL_ERROR_INTERRUPTED, "Operation interrupted" },
+    { PAL_ERROR_OVERFLOW, "Buffer overflowed" },
+    { PAL_ERROR_BADADDR, "Invalid address" },
+    { PAL_ERROR_NOMEM, "Not enough memory" },
+    { PAL_ERROR_NOTKILLABLE, "Thread state unkillable" },
+    { PAL_ERROR_INCONSIST, "Inconsistent system state" },
+    { PAL_ERROR_TRYAGAIN, "Try again" },
+    { PAL_ERROR_ENDOFSTREAM, "End of stream" },
+    { PAL_ERROR_NOTSERVER, "Not a server" },
+    { PAL_ERROR_NOTCONNECTION, "Not a connection" },
+    { PAL_ERROR_ZEROSIZE, "Zero size" },
+    { PAL_ERROR_CONNFAILED, "Connection failed" },
+    { PAL_ERROR_ADDRNOTEXIST, "Resource address does not exist" },
+
+    { PAL_ERROR_CRYPTO_FEATURE_UNAVAILABLE, "[Crypto] Feature not available" },
+    { PAL_ERROR_CRYPTO_INVALID_CONTEXT, "[Crypto] Invalid context" },
+    { PAL_ERROR_CRYPTO_INVALID_KEY_LENGTH, "[Crypto] Invalid key length" },
+    { PAL_ERROR_CRYPTO_INVALID_INPUT_LENGTH, "[Crypto] Invalid input length" },
+    { PAL_ERROR_CRYPTO_INVALID_OUTPUT_LENGTH, "[Crypto] Invalid output length" },
+    { PAL_ERROR_CRYPTO_BAD_INPUT_DATA, "[Crypto] Bad input parameters" },
+    { PAL_ERROR_CRYPTO_INVALID_PADDING, "[Crypto] Invalid padding" },
+    { PAL_ERROR_CRYPTO_DATA_MISALIGNED, "[Crypto] Data misaligned" },
+    { PAL_ERROR_CRYPTO_INVALID_FORMAT, "[Crypto] Invalid data format" },
+    { PAL_ERROR_CRYPTO_AUTH_FAILED, "[Crypto] Authentication failed" },
+    { PAL_ERROR_CRYPTO_IO_ERROR, "[Crypto] I/O error" },
+    { PAL_ERROR_CRYPTO_KEY_GEN_FAILED, "[Crypto] Key generation failed" },
+    { PAL_ERROR_CRYPTO_INVALID_KEY, "[Crypto] Invalid key" },
+    { PAL_ERROR_CRYPTO_VERIFY_FAILED, "[Crypto] Verification failed" },
+    { PAL_ERROR_CRYPTO_RNG_FAILED, "[Crypto] RNG failed to generate data" },
+    { PAL_ERROR_CRYPTO_INVALID_DH_STATE, "[Crypto] Invalid DH state" },
+};
+
+#define PAL_ERROR_COUNT (sizeof(pal_error_list) / sizeof(pal_error_list[0]))
+
+const char* pal_strerror(int err) {
+    for (size_t i = 0; i < PAL_ERROR_COUNT; i++)
+        if (pal_error_list[i].error == err)
+            return pal_error_list[i].description;
+    return "Unknown error";
+}

+ 51 - 64
Pal/src/pal_error.h

@@ -23,72 +23,59 @@
 #ifndef PAL_ERROR_H
 #define PAL_ERROR_H
 
-#define PAL_ERROR_NOTIMPLEMENTED 1
-#define PAL_ERROR_NOTDEFINED     2
-#define PAL_ERROR_NOTSUPPORT     3
-#define PAL_ERROR_INVAL          4
-#define PAL_ERROR_TOOLONG        5
-#define PAL_ERROR_DENIED         6
-#define PAL_ERROR_BADHANDLE      7
-#define PAL_ERROR_STREAMEXIST    8
-#define PAL_ERROR_STREAMNOTEXIST 9
-#define PAL_ERROR_STREAMISFILE   10
-#define PAL_ERROR_STREAMISDIR    11
-#define PAL_ERROR_STREAMISDEVICE 12
-#define PAL_ERROR_INTERRUPTED    13
-#define PAL_ERROR_OVERFLOW       14
-#define PAL_ERROR_BADADDR        15
-#define PAL_ERROR_NOMEM          16
-#define PAL_ERROR_NOTKILLABLE    17
-#define PAL_ERROR_INCONSIST      18
-#define PAL_ERROR_TRYAGAIN       19
-#define PAL_ERROR_ENDOFSTREAM    20
-#define PAL_ERROR_NOTSERVER      21
-#define PAL_ERROR_NOTCONNECTION  22
-#define PAL_ERROR_ZEROSIZE       23
-#define PAL_ERROR_CONNFAILED     24
-#define PAL_ERROR_ADDRNOTEXIST   25
+#include <stddef.h>
 
-#define PAL_ERROR_BOUND 25
+typedef enum _pal_error_t {
+    PAL_ERROR_SUCCESS = 0,
+    PAL_ERROR_NOTIMPLEMENTED,
+    PAL_ERROR_NOTDEFINED,
+    PAL_ERROR_NOTSUPPORT,
+    PAL_ERROR_INVAL,
+    PAL_ERROR_TOOLONG,
+    PAL_ERROR_DENIED,
+    PAL_ERROR_BADHANDLE,
+    PAL_ERROR_STREAMEXIST,
+    PAL_ERROR_STREAMNOTEXIST,
+    PAL_ERROR_STREAMISFILE,
+    PAL_ERROR_STREAMISDIR,
+    PAL_ERROR_STREAMISDEVICE,
+    PAL_ERROR_INTERRUPTED,
+    PAL_ERROR_OVERFLOW,
+    PAL_ERROR_BADADDR,
+    PAL_ERROR_NOMEM,
+    PAL_ERROR_NOTKILLABLE,
+    PAL_ERROR_INCONSIST,
+    PAL_ERROR_TRYAGAIN,
+    PAL_ERROR_ENDOFSTREAM,
+    PAL_ERROR_NOTSERVER,
+    PAL_ERROR_NOTCONNECTION,
+    PAL_ERROR_ZEROSIZE,
+    PAL_ERROR_CONNFAILED,
+    PAL_ERROR_ADDRNOTEXIST,
 
-static const char* pal_errstring[]
-#ifdef __GNUC__
-    __attribute__((unused))
-#endif
-    = {
-        /*  0. */ "Success",
-        /*  1. */ "Function not implemented",
-        /*  2. */ "Symbol not defined",
-        /*  3. */ "Function not supported",
-        /*  4. */ "Invalid argument",
-        /*  5. */ "Name/Path is too long",
-        /*  6. */ "Operation Denied",
-        /*  7. */ "Handle Corrupted",
-        /*  8. */ "Stream already exists",
-        /*  9. */ "Stream does not exists",
-        /* 10. */ "Stream is File",
-        /* 11. */ "Stream is Directory",
-        /* 12. */ "Stream is Device",
-        /* 13. */ "Operation interrupted",
-        /* 14. */ "Buffer overflowed",
-        /* 15. */ "Invalid address",
-        /* 16. */ "Not enough memory",
-        /* 17. */ "Thread state unkillable",
-        /* 18. */ "Inconsistent system state",
-        /* 19. */ "Try again",
-        /* 20. */ "End of stream",
-        /* 21. */ "Not a server",
-        /* 22. */ "Not a connection",
-        /* 23. */ "Zero size",
-        /* 24. */ "Connection failed",
-        /* 25. */ "Resource address not exist",
-};
+#define PAL_ERROR_NATIVE_COUNT PAL_ERROR_ADDRNOTEXIST
+#define PAL_ERROR_CRYPTO_START PAL_ERROR_CRYPTO_FEATURE_UNAVAILABLE
+
+    /* Crypto error constants and their descriptions are adapted from mbedtls. */
+    PAL_ERROR_CRYPTO_FEATURE_UNAVAILABLE = 1000,
+    PAL_ERROR_CRYPTO_INVALID_CONTEXT,
+    PAL_ERROR_CRYPTO_INVALID_KEY_LENGTH,
+    PAL_ERROR_CRYPTO_INVALID_INPUT_LENGTH,
+    PAL_ERROR_CRYPTO_INVALID_OUTPUT_LENGTH,
+    PAL_ERROR_CRYPTO_BAD_INPUT_DATA,
+    PAL_ERROR_CRYPTO_INVALID_PADDING,
+    PAL_ERROR_CRYPTO_DATA_MISALIGNED,
+    PAL_ERROR_CRYPTO_INVALID_FORMAT,
+    PAL_ERROR_CRYPTO_AUTH_FAILED,
+    PAL_ERROR_CRYPTO_IO_ERROR,
+    PAL_ERROR_CRYPTO_KEY_GEN_FAILED,
+    PAL_ERROR_CRYPTO_INVALID_KEY,
+    PAL_ERROR_CRYPTO_VERIFY_FAILED,
+    PAL_ERROR_CRYPTO_RNG_FAILED,
+    PAL_ERROR_CRYPTO_INVALID_DH_STATE,
+#define PAL_ERROR_CRYPTO_END PAL_ERROR_CRYPTO_INVALID_DH_STATE
+} pal_error_t;
 
-static inline const char* PAL_STRERROR(int err) {
-    int _e = -err;
-    if (_e >= 0 && _e <= PAL_ERROR_BOUND)
-        return pal_errstring[_e];
-    return "Unknown error";
-}
+const char* pal_strerror(int err);
 
 #endif

+ 3 - 4
Pal/src/pal_internal.h

@@ -431,10 +431,9 @@ static inline void log_stream (const char * uri)
         write_log(2, uri, "\n");
 }
 
-/* errval is negative value. see PAL_STRERROR */
-static inline void print_error(const char * errstring, int errval)
-{
-    printf("%s (%s)\n", errstring, PAL_STRERROR(errval));
+/* errval is negative value, see pal_strerror */
+static inline void print_error(const char* errstring, int errval) {
+    printf("%s (%s)\n", errstring, pal_strerror(errval));
 }
 
 #endif

+ 1 - 1
Pal/test/Failure.c

@@ -7,7 +7,7 @@
 int handled = 0;
 
 void FailureHandler(PAL_PTR event, PAL_NUM arg, PAL_CONTEXT* context) {
-    pal_printf("Failure notified: %s\n", pal_errstring[(unsigned long)arg]);
+    pal_printf("Failure notified: %s\n", pal_strerror((unsigned long)arg));
 
     handled = 1;
     DkExceptionReturn(event);