2 * Copyright (c) 2016-2020 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>
29 #include <openssl/pkcs12.h>
30 #include <openssl/dsa.h>
32 #include <yaca_error.h>
38 // TODO any better idea than to use __thread?
39 static __thread yaca_error_cb error_cb = NULL;
40 static bool error_strings_loaded = false;
41 static const int GENERIC_REASON_MAX = 99;
43 API void yaca_debug_set_error_cb(yaca_error_cb fn)
48 #define ERRORDESCRIBE(name) case name: return #name
49 API const char *yaca_debug_translate_error(yaca_error_e err)
52 ERRORDESCRIBE(YACA_ERROR_NONE);
53 ERRORDESCRIBE(YACA_ERROR_INVALID_PARAMETER);
54 ERRORDESCRIBE(YACA_ERROR_OUT_OF_MEMORY);
55 ERRORDESCRIBE(YACA_ERROR_INTERNAL);
56 ERRORDESCRIBE(YACA_ERROR_DATA_MISMATCH);
57 ERRORDESCRIBE(YACA_ERROR_INVALID_PASSWORD);
58 default: return "Error not defined";
63 void error_dump(const char *file, int line, const char *function, int code)
65 if (error_cb == NULL) {
70 static const size_t BUF_SIZE = 512;
71 static const char ELLIPSIS[] = "...\n";
72 static const size_t ELLIPSIS_SIZE = sizeof(ELLIPSIS) / sizeof(ELLIPSIS[0]);
76 const char *err_str = yaca_debug_translate_error(code);
77 const char *sign = "";
84 written = snprintf(buf, BUF_SIZE, "%s:%d %s() API error: %s0x%02X (%s)\n", file,
85 line, function, sign, code, err_str);
87 while ((err = ERR_get_error()) != 0 && written < BUF_SIZE - 1) {
88 if (!error_strings_loaded) {
90 * This function is thread-safe as long as static locks are
91 * installed according to doc so calling it twice won't break
92 * anything and I don't want to use synchronization mechanisms
95 ERR_load_crypto_strings();
96 error_strings_loaded = true;
99 ERR_error_string_n(err, buf + written, BUF_SIZE - written);
100 written = strlen(buf); /* I trust you, openssl */
101 if (written < BUF_SIZE - 1) {
107 /* In case the while broke early due to the BUF_SIZE, write
108 * ellipsis and clear remaining errors that might have not been
109 * read by ERR_get_error() */
110 if (written >= BUF_SIZE - 1) {
111 strncpy(buf + BUF_SIZE - ELLIPSIS_SIZE, ELLIPSIS, ELLIPSIS_SIZE);
112 written = BUF_SIZE - 1;
120 int error_handle(const char *file, int line, const char *function)
122 int ret = YACA_ERROR_NONE;
123 unsigned long err = ERR_peek_error();
126 return YACA_ERROR_INTERNAL;
130 case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN):
131 case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_GREATER_THAN_MOD_LEN):
132 case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PRIVATE_DECRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS):
133 case ERR_PACK(ERR_LIB_RSA, RSA_F_RSA_OSSL_PUBLIC_DECRYPT, RSA_R_DATA_TOO_LARGE_FOR_MODULUS):
134 case ERR_PACK(ERR_LIB_PEM, PEM_F_GET_NAME, PEM_R_NO_START_LINE):
135 case ERR_PACK(ERR_LIB_PEM, PEM_F_GET_HEADER_AND_DATA, PEM_R_BAD_END_LINE):
136 case ERR_PACK(ERR_LIB_RSA, RSA_F_PKEY_RSA_CTRL, RSA_R_KEY_SIZE_TOO_SMALL):
137 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_CTX_CTRL, EVP_R_COMMAND_NOT_SUPPORTED):
138 case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO, PEM_R_NO_START_LINE):
139 case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_D2I_READ_BIO, ASN1_R_NOT_ENOUGH_DATA):
140 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_ENCRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH):
141 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_DATA_NOT_MULTIPLE_OF_BLOCK_LENGTH):
142 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_WRONG_FINAL_BLOCK_LENGTH):
143 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_PKEY_DERIVE_SET_PEER, EVP_R_DIFFERENT_PARAMETERS):
144 case ERR_PACK(ERR_LIB_EC, EC_F_PKEY_EC_CTRL, EC_R_INVALID_DIGEST_TYPE):
145 case ERR_PACK(ERR_LIB_DSA, DSA_F_PKEY_DSA_CTRL, DSA_R_INVALID_DIGEST_TYPE):
146 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_SET_KEY_LENGTH, EVP_R_INVALID_KEY_LENGTH):
147 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_CIPHER_CTX_CTRL, EVP_R_CTRL_OPERATION_NOT_IMPLEMENTED):
148 ret = YACA_ERROR_INVALID_PARAMETER;
150 case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_TOO_LONG):
151 case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_GET_OBJECT, ASN1_R_HEADER_TOO_LONG):
152 case ERR_PACK(ERR_LIB_ASN1, ASN1_F_ASN1_CHECK_TLEN, ASN1_R_WRONG_TAG):
154 bool found_crypto_error = false;
156 while ((err = ERR_get_error()) != 0)
157 if (err == ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_ITEM_DECRYPT_D2I, PKCS12_R_DECODE_ERROR) ||
158 err == ERR_PACK(ERR_LIB_PKCS12, PKCS12_F_PKCS12_PBE_CRYPT, PKCS12_R_PKCS12_CIPHERFINAL_ERROR) ||
159 err == ERR_PACK(ERR_LIB_DSA, DSA_F_OLD_DSA_PRIV_DECODE, ERR_R_DSA_LIB) ||
160 err == ERR_PACK(ERR_LIB_RSA, RSA_F_OLD_RSA_PRIV_DECODE, ERR_R_RSA_LIB)) {
161 found_crypto_error = true;
165 if (found_crypto_error)
166 ret = YACA_ERROR_INVALID_PASSWORD;
168 ret = YACA_ERROR_INVALID_PARAMETER;
172 case ERR_PACK(ERR_LIB_EVP, EVP_F_EVP_DECRYPTFINAL_EX, EVP_R_BAD_DECRYPT):
173 case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_DECRYPT):
174 case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_DO_HEADER, PEM_R_BAD_PASSWORD_READ):
175 case ERR_PACK(ERR_LIB_PEM, PEM_F_PEM_READ_BIO_PRIVATEKEY, PEM_R_BAD_PASSWORD_READ):
176 case ERR_PACK(ERR_LIB_PEM, PEM_F_D2I_PKCS8PRIVATEKEY_BIO, PEM_R_BAD_PASSWORD_READ):
177 ret = YACA_ERROR_INVALID_PASSWORD;
181 /* known rsa padding errors */
182 if (ret == YACA_ERROR_NONE && ERR_GET_LIB(err) == ERR_LIB_RSA) {
183 switch (ERR_GET_FUNC(err)) {
184 case RSA_F_CHECK_PADDING_MD:
185 case RSA_F_RSA_PADDING_CHECK_NONE:
186 case RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP:
187 case RSA_F_RSA_PADDING_CHECK_PKCS1_OAEP_MGF1:
188 case RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_1:
189 case RSA_F_RSA_PADDING_CHECK_PKCS1_TYPE_2:
190 case RSA_F_RSA_PADDING_CHECK_SSLV23:
191 case RSA_F_RSA_PADDING_CHECK_X931:
192 case RSA_F_RSA_PADDING_ADD_NONE:
193 case RSA_F_RSA_PADDING_ADD_PKCS1_OAEP:
194 case RSA_F_RSA_PADDING_ADD_PKCS1_OAEP_MGF1:
195 case RSA_F_RSA_PADDING_ADD_PKCS1_PSS:
196 case RSA_F_RSA_PADDING_ADD_PKCS1_PSS_MGF1:
197 case RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_1:
198 case RSA_F_RSA_PADDING_ADD_PKCS1_TYPE_2:
199 case RSA_F_RSA_PADDING_ADD_SSLV23:
200 case RSA_F_RSA_PADDING_ADD_X931:
201 ret = YACA_ERROR_INVALID_PARAMETER;
207 int reason = ERR_GET_REASON(err);
208 if (ret == YACA_ERROR_NONE && reason <= GENERIC_REASON_MAX && (err & ERR_R_FATAL) > 0) {
210 case ERR_R_MALLOC_FAILURE:
211 ret = YACA_ERROR_OUT_OF_MEMORY;
213 case ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED:
214 case ERR_R_PASSED_NULL_PARAMETER:
215 ret = YACA_ERROR_INVALID_PARAMETER;
217 case ERR_R_INTERNAL_ERROR:
219 ret = YACA_ERROR_INTERNAL;
224 /* neither known nor fatal, unknown */
225 if (ret == YACA_ERROR_NONE) {
226 error_dump(file, line, function, YACA_ERROR_INTERNAL);
227 ret = YACA_ERROR_INTERNAL;
230 /* remove all errors from queue */