2 * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
4 * Contact: Krzysztof Jackiewicz <k.jackiewicz@samsung.com>
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License
27 #include <openssl/err.h>
28 #include <openssl/pem.h>
30 #include <yaca_error.h>
35 // TODO any better idea than to use __thread?
36 static __thread yaca_error_cb error_cb = NULL;
37 static bool error_strings_loaded = false;
39 API void yaca_debug_set_error_cb(yaca_error_cb fn)
44 char *error_translate(yaca_error_e err)
48 return "YACA_ERROR_NONE";
49 case YACA_ERROR_INVALID_ARGUMENT:
50 return "YACA_ERROR_INVALID_ARGUMENT";
51 case YACA_ERROR_OUT_OF_MEMORY:
52 return "YACA_ERROR_OUT_OF_MEMORY";
53 case YACA_ERROR_INTERNAL:
54 return "YACA_ERROR_INTERNAL";
55 case YACA_ERROR_DATA_MISMATCH:
56 return "YACA_ERROR_DATA_MISMATCH";
57 case YACA_ERROR_PASSWORD_INVALID:
58 return "YACA_ERROR_PASSWORD_INVALID";
64 void error_dump(const char *file, int line, const char *function, int code)
66 if (error_cb == NULL) {
71 static const size_t BUF_SIZE = 512;
72 static const char ELLIPSIS[] = "...\n";
73 static const size_t ELLIPSIS_SIZE = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]);
77 const char *err_str = error_translate(code);
79 written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: ", file, line, function);
81 written += snprintf(buf + written, BUF_SIZE - written, "%s\n", err_str);
83 written += snprintf(buf + written, BUF_SIZE - written, "0x%X\n", code);
85 while ((err = ERR_get_error()) != 0 && written < BUF_SIZE - 1) {
86 if (!error_strings_loaded) {
88 * This function is thread-safe as long as static locks are
89 * installed according to doc so calling it twice won't break
90 * anything and I don't want to use synchronization mechanisms
93 ERR_load_crypto_strings();
94 error_strings_loaded = true;
97 ERR_error_string_n(err, buf + written, BUF_SIZE - written);
98 written = strlen(buf); /* I trust you, openssl */
99 if (written < BUF_SIZE - 1) {
105 if (written >= BUF_SIZE - 1) {
106 strncpy(buf + BUF_SIZE - ELLIPSIS_SIZE, ELLIPSIS, ELLIPSIS_SIZE);
107 written = BUF_SIZE - 1;
115 int error_handle(const char *file, int line, const char *function)
118 unsigned long err = ERR_peek_error();
121 if (ERR_FATAL_ERROR(err) > 0) {
122 switch (ERR_GET_REASON(err)) {
123 case ERR_R_MALLOC_FAILURE:
124 ret = YACA_ERROR_OUT_OF_MEMORY;
126 case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
127 case ERR_R_PASSED_NULL_PARAMETER:
128 ret = YACA_ERROR_INVALID_ARGUMENT;
130 case ERR_R_INTERNAL_ERROR:
133 ret = YACA_ERROR_INTERNAL;
138 case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_INVALID_KEYBITS):
139 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED):
140 ret = YACA_ERROR_INVALID_ARGUMENT;
142 case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT):
143 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT):
144 ret = YACA_ERROR_PASSWORD_INVALID;
147 error_dump(file, line, function, YACA_ERROR_INTERNAL);
148 ret = YACA_ERROR_INTERNAL;
152 /* remove all errors from queue */