1 /*
2  * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License").
5  * You may not use this file except in compliance with the License.
6  * A copy of the License is located at
7  *
8  *  http://aws.amazon.com/apache2.0
9  *
10  * or in the "license" file accompanying this file. This file is distributed
11  * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12  * express or implied. See the License for the specific language governing
13  * permissions and limitations under the License.
14  */
15 
16 #include <errno.h>
17 #include <strings.h>
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include "error/s2n_errno.h"
22 
23 #include <s2n.h>
24 #include "utils/s2n_map.h"
25 #include "utils/s2n_safety.h"
26 
27 #if S2N_HAVE_EXECINFO
28 #   include <execinfo.h>
29 #endif
30 
31 __thread int s2n_errno;
32 __thread const char *s2n_debug_str;
33 
34 /**
35  * Returns the address of the thread-local `s2n_errno` variable
36  */
s2n_errno_location()37 int *s2n_errno_location()
38 {
39     return &s2n_errno;
40 }
41 
42 static const char *no_such_language = "Language is not supported for error translation";
43 static const char *no_such_error = "Internal s2n error";
44 
45 /*
46  * Define error entries with descriptions in this macro once
47  * to generate code in next 2 following functions.
48  */
49 /* clang-format off */
50 #define ERR_ENTRIES(ERR_ENTRY) \
51     ERR_ENTRY(S2N_ERR_OK, "no error") \
52     ERR_ENTRY(S2N_ERR_IO, "underlying I/O operation failed, check system errno") \
53     ERR_ENTRY(S2N_ERR_CLOSED, "connection is closed") \
54     ERR_ENTRY(S2N_ERR_IO_BLOCKED, "underlying I/O operation would block") \
55     ERR_ENTRY(S2N_ERR_ASYNC_BLOCKED, "blocked on external async function invocation") \
56     ERR_ENTRY(S2N_ERR_ALERT, "TLS alert received") \
57     ERR_ENTRY(S2N_ERR_ENCRYPT, "error encrypting data") \
58     ERR_ENTRY(S2N_ERR_DECRYPT, "error decrypting data") \
59     ERR_ENTRY(S2N_ERR_BAD_MESSAGE, "Bad message encountered") \
60     ERR_ENTRY(S2N_ERR_KEY_INIT, "error initializing encryption key") \
61     ERR_ENTRY(S2N_ERR_KEY_DESTROY, "error destroying encryption key") \
62     ERR_ENTRY(S2N_ERR_DH_SERIALIZING, "error serializing Diffie-Hellman parameters") \
63     ERR_ENTRY(S2N_ERR_DH_SHARED_SECRET, "error computing Diffie-Hellman shared secret") \
64     ERR_ENTRY(S2N_ERR_DH_WRITING_PUBLIC_KEY, "error writing Diffie-Hellman public key") \
65     ERR_ENTRY(S2N_ERR_DH_FAILED_SIGNING, "error signing Diffie-Hellman values") \
66     ERR_ENTRY(S2N_ERR_DH_COPYING_PARAMETERS, "error copying Diffie-Hellman parameters") \
67     ERR_ENTRY(S2N_ERR_DH_GENERATING_PARAMETERS, "error generating Diffie-Hellman parameters") \
68     ERR_ENTRY(S2N_ERR_CIPHER_NOT_SUPPORTED, "Cipher is not supported") \
69     ERR_ENTRY(S2N_ERR_NO_APPLICATION_PROTOCOL, "No supported application protocol to negotiate") \
70     ERR_ENTRY(S2N_ERR_FALLBACK_DETECTED, "TLS fallback detected") \
71     ERR_ENTRY(S2N_ERR_HASH_DIGEST_FAILED, "failed to create hash digest") \
72     ERR_ENTRY(S2N_ERR_HASH_INIT_FAILED, "error initializing hash") \
73     ERR_ENTRY(S2N_ERR_HASH_UPDATE_FAILED, "error updating hash") \
74     ERR_ENTRY(S2N_ERR_HASH_COPY_FAILED, "error copying hash") \
75     ERR_ENTRY(S2N_ERR_HASH_WIPE_FAILED, "error wiping hash") \
76     ERR_ENTRY(S2N_ERR_HASH_NOT_READY, "hash not in a valid state for the attempted operation") \
77     ERR_ENTRY(S2N_ERR_ALLOW_MD5_FOR_FIPS_FAILED, "error allowing MD5 to be used when in FIPS mode") \
78     ERR_ENTRY(S2N_ERR_DECODE_CERTIFICATE, "error decoding certificate") \
79     ERR_ENTRY(S2N_ERR_DECODE_PRIVATE_KEY, "error decoding private key") \
80     ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_ALGORITHM, "Invalid signature algorithm") \
81     ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_SCHEME, "Invalid signature scheme") \
82     ERR_ENTRY(S2N_ERR_CBC_VERIFY, "Failed CBC verification") \
83     ERR_ENTRY(S2N_ERR_DH_COPYING_PUBLIC_KEY, "error copying Diffie-Hellman public key") \
84     ERR_ENTRY(S2N_ERR_SIGN, "error signing data") \
85     ERR_ENTRY(S2N_ERR_VERIFY_SIGNATURE, "error verifying signature") \
86     ERR_ENTRY(S2N_ERR_ECDHE_GEN_KEY, "Failed to generate an ECDHE key") \
87     ERR_ENTRY(S2N_ERR_ECDHE_SHARED_SECRET, "Error computing ECDHE shared secret") \
88     ERR_ENTRY(S2N_ERR_ECDHE_UNSUPPORTED_CURVE, "Unsupported EC curve was presented during an ECDHE handshake") \
89     ERR_ENTRY(S2N_ERR_ECDSA_UNSUPPORTED_CURVE, "Unsupported EC curve was presented during an ECDSA SignatureScheme handshake") \
90     ERR_ENTRY(S2N_ERR_ECDHE_SERIALIZING, "Error serializing ECDHE public") \
91     ERR_ENTRY(S2N_ERR_KEM_UNSUPPORTED_PARAMS, "Unsupported KEM params was presented during a handshake that uses a KEM") \
92     ERR_ENTRY(S2N_ERR_SHUTDOWN_RECORD_TYPE, "Non alert record received during s2n_shutdown()") \
93     ERR_ENTRY(S2N_ERR_SHUTDOWN_CLOSED, "Peer closed before sending their close_notify") \
94     ERR_ENTRY(S2N_ERR_NON_EMPTY_RENEGOTIATION_INFO, "renegotiation_info should be empty") \
95     ERR_ENTRY(S2N_ERR_RECORD_LIMIT, "TLS record limit reached") \
96     ERR_ENTRY(S2N_ERR_CERT_UNTRUSTED, "Certificate is untrusted") \
97     ERR_ENTRY(S2N_ERR_CERT_TYPE_UNSUPPORTED, "Certificate Type is unsupported") \
98     ERR_ENTRY(S2N_ERR_INVALID_MAX_FRAG_LEN, "invalid Maximum Fragmentation Length encountered") \
99     ERR_ENTRY(S2N_ERR_MAX_FRAG_LEN_MISMATCH, "Negotiated Maximum Fragmentation Length from server does not match the requested length by client") \
100     ERR_ENTRY(S2N_ERR_PROTOCOL_VERSION_UNSUPPORTED, "TLS protocol version is not supported by configuration") \
101     ERR_ENTRY(S2N_ERR_BAD_KEY_SHARE, "Bad key share received") \
102     ERR_ENTRY(S2N_ERR_CANCELLED, "handshake was cancelled") \
103     ERR_ENTRY(S2N_ERR_PROTOCOL_DOWNGRADE_DETECTED, "Protocol downgrade detected by client") \
104     ERR_ENTRY(S2N_ERR_MADVISE, "error calling madvise") \
105     ERR_ENTRY(S2N_ERR_ALLOC, "error allocating memory") \
106     ERR_ENTRY(S2N_ERR_MLOCK, "error calling mlock (Did you run prlimit?)") \
107     ERR_ENTRY(S2N_ERR_MUNLOCK, "error calling munlock") \
108     ERR_ENTRY(S2N_ERR_FSTAT, "error calling fstat") \
109     ERR_ENTRY(S2N_ERR_OPEN, "error calling open") \
110     ERR_ENTRY(S2N_ERR_MMAP, "error calling mmap") \
111     ERR_ENTRY(S2N_ERR_ATEXIT, "error calling atexit") \
112     ERR_ENTRY(S2N_ERR_NOMEM, "no memory") \
113     ERR_ENTRY(S2N_ERR_NULL, "NULL pointer encountered") \
114     ERR_ENTRY(S2N_ERR_SAFETY, "a safety check failed") \
115     ERR_ENTRY(S2N_ERR_INITIALIZED, "s2n is initialized") \
116     ERR_ENTRY(S2N_ERR_NOT_INITIALIZED, "s2n not initialized") \
117     ERR_ENTRY(S2N_ERR_RANDOM_UNINITIALIZED, "s2n entropy not initialized") \
118     ERR_ENTRY(S2N_ERR_OPEN_RANDOM, "error opening urandom") \
119     ERR_ENTRY(S2N_ERR_RESIZE_STATIC_STUFFER, "cannot resize a static stuffer") \
120     ERR_ENTRY(S2N_ERR_RESIZE_TAINTED_STUFFER, "cannot resize a tainted stuffer") \
121     ERR_ENTRY(S2N_ERR_STUFFER_OUT_OF_DATA, "stuffer is out of data") \
122     ERR_ENTRY(S2N_ERR_STUFFER_IS_FULL, "stuffer is full") \
123     ERR_ENTRY(S2N_ERR_STUFFER_NOT_FOUND, "stuffer expected bytes were not found") \
124     ERR_ENTRY(S2N_ERR_STUFFER_HAS_UNPROCESSED_DATA, "stuffer has unprocessed data") \
125     ERR_ENTRY(S2N_ERR_HASH_INVALID_ALGORITHM, "invalid hash algorithm") \
126     ERR_ENTRY(S2N_ERR_PRF_INVALID_ALGORITHM, "invalid prf hash algorithm") \
127     ERR_ENTRY(S2N_ERR_PRF_INVALID_SEED, "invalid prf seeds provided") \
128     ERR_ENTRY(S2N_ERR_P_HASH_INVALID_ALGORITHM, "invalid p_hash algorithm") \
129     ERR_ENTRY(S2N_ERR_P_HASH_INIT_FAILED, "error initializing p_hash") \
130     ERR_ENTRY(S2N_ERR_P_HASH_UPDATE_FAILED, "error updating p_hash") \
131     ERR_ENTRY(S2N_ERR_P_HASH_FINAL_FAILED, "error creating p_hash digest") \
132     ERR_ENTRY(S2N_ERR_P_HASH_WIPE_FAILED, "error wiping p_hash") \
133     ERR_ENTRY(S2N_ERR_HMAC_INVALID_ALGORITHM, "invalid HMAC algorithm") \
134     ERR_ENTRY(S2N_ERR_HKDF_OUTPUT_SIZE, "invalid HKDF output size") \
135     ERR_ENTRY(S2N_ERR_ALERT_PRESENT, "TLS alert is already pending") \
136     ERR_ENTRY(S2N_ERR_HANDSHAKE_STATE, "Invalid handshake state encountered") \
137     ERR_ENTRY(S2N_ERR_SHUTDOWN_PAUSED, "s2n_shutdown() called while paused") \
138     ERR_ENTRY(S2N_ERR_SIZE_MISMATCH, "size mismatch") \
139     ERR_ENTRY(S2N_ERR_DRBG, "Error using Deterministic Random Bit Generator") \
140     ERR_ENTRY(S2N_ERR_DRBG_REQUEST_SIZE, "Request for too much entropy") \
141     ERR_ENTRY(S2N_ERR_KEY_CHECK, "Invalid key") \
142     ERR_ENTRY(S2N_ERR_CIPHER_TYPE, "Unknown cipher type used") \
143     ERR_ENTRY(S2N_ERR_MAP_DUPLICATE, "Duplicate map key inserted") \
144     ERR_ENTRY(S2N_ERR_MAP_IMMUTABLE, "Attempt to update an immutable map") \
145     ERR_ENTRY(S2N_ERR_MAP_MUTABLE, "Attempt to lookup a mutable map") \
146     ERR_ENTRY(S2N_ERR_MAP_INVALID_MAP_SIZE, "Attempt to create a map with 0 capacity") \
147     ERR_ENTRY(S2N_ERR_INITIAL_HMAC, "error calling EVP_CIPHER_CTX_ctrl for composite cbc cipher") \
148     ERR_ENTRY(S2N_ERR_INVALID_NONCE_TYPE, "Invalid AEAD nonce type") \
149     ERR_ENTRY(S2N_ERR_UNIMPLEMENTED, "Unimplemented feature") \
150     ERR_ENTRY(S2N_ERR_HANDSHAKE_UNREACHABLE, "Unreachable handshake state machine handler invoked") \
151     ERR_ENTRY(S2N_ERR_READ, "error calling read") \
152     ERR_ENTRY(S2N_ERR_WRITE, "error calling write") \
153     ERR_ENTRY(S2N_ERR_BAD_FD, "Invalid file descriptor") \
154     ERR_ENTRY(S2N_ERR_RDRAND_FAILED, "Error executing rdrand instruction") \
155     ERR_ENTRY(S2N_ERR_FAILED_CACHE_RETRIEVAL, "Failed cache retrieval") \
156     ERR_ENTRY(S2N_ERR_X509_TRUST_STORE, "Error initializing trust store") \
157     ERR_ENTRY(S2N_ERR_UNKNOWN_PROTOCOL_VERSION, "Error determining client protocol version") \
158     ERR_ENTRY(S2N_ERR_NULL_CN_NAME, "Error parsing CN names") \
159     ERR_ENTRY(S2N_ERR_NULL_SANS, "Error parsing SANS") \
160     ERR_ENTRY(S2N_ERR_CLIENT_HELLO_VERSION, "Could not get client hello version") \
161     ERR_ENTRY(S2N_ERR_CLIENT_PROTOCOL_VERSION, "Could not get client protocol version") \
162     ERR_ENTRY(S2N_ERR_SERVER_PROTOCOL_VERSION, "Could not get server protocol version") \
163     ERR_ENTRY(S2N_ERR_ACTUAL_PROTOCOL_VERSION, "Could not get actual protocol version") \
164     ERR_ENTRY(S2N_ERR_POLLING_FROM_SOCKET, "Error polling from socket") \
165     ERR_ENTRY(S2N_ERR_RECV_STUFFER_FROM_CONN, "Error receiving stuffer from connection") \
166     ERR_ENTRY(S2N_ERR_SEND_STUFFER_TO_CONN, "Error sending stuffer to connection") \
167     ERR_ENTRY(S2N_ERR_PRECONDITION_VIOLATION, "Precondition violation") \
168     ERR_ENTRY(S2N_ERR_POSTCONDITION_VIOLATION, "Postcondition violation") \
169     ERR_ENTRY(S2N_ERR_INTEGER_OVERFLOW, "Integer overflow violation") \
170     ERR_ENTRY(S2N_ERR_ARRAY_INDEX_OOB, "Array index out of bounds") \
171     ERR_ENTRY(S2N_ERR_FREE_STATIC_BLOB, "Cannot free a static blob") \
172     ERR_ENTRY(S2N_ERR_RESIZE_STATIC_BLOB, "Cannot resize a static blob") \
173     ERR_ENTRY(S2N_ERR_NO_SUPPORTED_LIBCRYPTO_API, "libcrypto does not support this API") \
174     ERR_ENTRY(S2N_ERR_RECORD_LENGTH_TOO_LARGE, "Record length exceeds protocol version maximum") \
175     ERR_ENTRY(S2N_ERR_SET_DUPLICATE_VALUE, "Set already contains the provided value") \
176     ERR_ENTRY(S2N_ERR_ASYNC_CALLBACK_FAILED, "Callback associated with async private keys function has failed") \
177     ERR_ENTRY(S2N_ERR_ASYNC_MORE_THAN_ONE, "Only one asynchronous operation can be in-progress at the same time") \
178     ERR_ENTRY(S2N_ERR_NO_ALERT, "No Alert present") \
179     ERR_ENTRY(S2N_ERR_SERVER_MODE, "Operation not allowed in server mode") \
180     ERR_ENTRY(S2N_ERR_CLIENT_MODE, "Operation not allowed in client mode") \
181     ERR_ENTRY(S2N_ERR_CLIENT_MODE_DISABLED, "client connections not allowed") \
182     ERR_ENTRY(S2N_ERR_TOO_MANY_CERTIFICATES, "only 1 certificate is supported in client mode") \
183     ERR_ENTRY(S2N_ERR_TOO_MANY_SIGNATURE_SCHEMES, "Max supported length of SignatureAlgorithms/SignatureSchemes list is 32") \
184     ERR_ENTRY(S2N_ERR_CLIENT_AUTH_NOT_SUPPORTED_IN_FIPS_MODE, "Client Auth is not supported when in FIPS mode") \
185     ERR_ENTRY(S2N_ERR_INVALID_BASE64, "invalid base64 encountered") \
186     ERR_ENTRY(S2N_ERR_INVALID_HEX, "invalid HEX encountered") \
187     ERR_ENTRY(S2N_ERR_INVALID_PEM, "invalid PEM encountered") \
188     ERR_ENTRY(S2N_ERR_DH_PARAMS_CREATE, "error creating Diffie-Hellman parameters") \
189     ERR_ENTRY(S2N_ERR_DH_TOO_SMALL, "Diffie-Hellman parameters are too small") \
190     ERR_ENTRY(S2N_ERR_DH_PARAMETER_CHECK, "Diffie-Hellman parameter check failed") \
191     ERR_ENTRY(S2N_ERR_INVALID_PKCS3, "invalid PKCS3 encountered") \
192     ERR_ENTRY(S2N_ERR_NO_CERTIFICATE_IN_PEM, "No certificate in PEM") \
193     ERR_ENTRY(S2N_ERR_SERVER_NAME_TOO_LONG, "server name is too long") \
194     ERR_ENTRY(S2N_ERR_NUM_DEFAULT_CERTIFICATES, "exceeded max default certificates or provided no default") \
195     ERR_ENTRY(S2N_ERR_MULTIPLE_DEFAULT_CERTIFICATES_PER_AUTH_TYPE, "setting multiple default certificates per auth type is not allowed") \
196     ERR_ENTRY(S2N_ERR_INVALID_CIPHER_PREFERENCES, "Invalid Cipher Preferences version") \
197     ERR_ENTRY(S2N_ERR_INVALID_APPLICATION_PROTOCOL, "The supplied application protocol name is invalid") \
198     ERR_ENTRY(S2N_ERR_KEY_MISMATCH, "public and private key do not match") \
199     ERR_ENTRY(S2N_ERR_SEND_SIZE, "Retried s2n_send() size is invalid") \
200     ERR_ENTRY(S2N_ERR_CORK_SET_ON_UNMANAGED, "Attempt to set connection cork management on unmanaged IO") \
201     ERR_ENTRY(S2N_ERR_UNRECOGNIZED_EXTENSION, "TLS extension not recognized") \
202     ERR_ENTRY(S2N_ERR_INVALID_SCT_LIST, "SCT list is invalid") \
203     ERR_ENTRY(S2N_ERR_INVALID_OCSP_RESPONSE, "OCSP response is invalid") \
204     ERR_ENTRY(S2N_ERR_UPDATING_EXTENSION, "Updating extension data failed") \
205     ERR_ENTRY(S2N_ERR_INVALID_SERIALIZED_SESSION_STATE, "Serialized session state is not in valid format") \
206     ERR_ENTRY(S2N_ERR_SERIALIZED_SESSION_STATE_TOO_LONG, "Serialized session state is too long") \
207     ERR_ENTRY(S2N_ERR_SESSION_ID_TOO_LONG, "Session id is too long") \
208     ERR_ENTRY(S2N_ERR_CLIENT_AUTH_NOT_SUPPORTED_IN_SESSION_RESUMPTION_MODE, "Client Auth is not supported in session resumption mode") \
209     ERR_ENTRY(S2N_ERR_INVALID_TICKET_KEY_LENGTH, "Session ticket key length cannot be zero") \
210     ERR_ENTRY(S2N_ERR_INVALID_TICKET_KEY_NAME_OR_NAME_LENGTH, "Session ticket key name should be unique and the name length cannot be zero") \
211     ERR_ENTRY(S2N_ERR_TICKET_KEY_NOT_UNIQUE, "Cannot add session ticket key because it was added before") \
212     ERR_ENTRY(S2N_ERR_TICKET_KEY_LIMIT, "Limit reached for unexpired session ticket keys") \
213     ERR_ENTRY(S2N_ERR_NO_TICKET_ENCRYPT_DECRYPT_KEY, "No key in encrypt-decrypt state is available to encrypt session ticket") \
214     ERR_ENTRY(S2N_ERR_ENCRYPT_DECRYPT_KEY_SELECTION_FAILED, "Failed to select a key from keys in encrypt-decrypt state") \
215     ERR_ENTRY(S2N_ERR_KEY_USED_IN_SESSION_TICKET_NOT_FOUND, "Key used in already assigned session ticket not found for decryption") \
216     ERR_ENTRY(S2N_ERR_SENDING_NST, "Error in session ticket status encountered before sending NST") \
217     ERR_ENTRY(S2N_ERR_INVALID_DYNAMIC_THRESHOLD, "invalid dynamic record threshold") \
218     ERR_ENTRY(S2N_ERR_INVALID_ARGUMENT, "invalid argument provided into a function call") \
219     ERR_ENTRY(S2N_ERR_NOT_IN_UNIT_TEST, "Illegal configuration, can only be used during unit tests") \
220     ERR_ENTRY(S2N_ERR_NOT_IN_TEST, "Illegal configuration, can only be used during unit or integration tests") \
221     ERR_ENTRY(S2N_ERR_UNSUPPORTED_CPU, "Unsupported CPU architecture") \
222     ERR_ENTRY(S2N_ERR_SESSION_ID_TOO_SHORT, "Session id is too short") \
223     ERR_ENTRY(S2N_ERR_CONNECTION_CACHING_DISALLOWED, "This connection is not allowed to be cached") \
224     ERR_ENTRY(S2N_ERR_SESSION_TICKET_NOT_SUPPORTED, "Session ticket not supported for this connection") \
225     ERR_ENTRY(S2N_ERR_OCSP_NOT_SUPPORTED, "OCSP stapling was requested, but is not supported") \
226     ERR_ENTRY(S2N_ERR_INVALID_SIGNATURE_ALGORITHMS_PREFERENCES, "Invalid signature algorithms preferences version") \
227     ERR_ENTRY(S2N_RSA_PSS_NOT_SUPPORTED, "RSA-PSS signing not supported by underlying libcrypto implementation") \
228     ERR_ENTRY(S2N_ERR_MAX_INNER_PLAINTEXT_SIZE, "Inner plaintext size exceeds limit") \
229     ERR_ENTRY(S2N_ERR_INVALID_ECC_PREFERENCES, "Invalid ecc curves preferences version") \
230     ERR_ENTRY(S2N_ERR_RECORD_STUFFER_SIZE, "Record stuffer out of space") \
231     ERR_ENTRY(S2N_ERR_FRAGMENT_LENGTH_TOO_SMALL, "Fragment length is too small") \
232     ERR_ENTRY(S2N_ERR_FRAGMENT_LENGTH_TOO_LARGE, "Fragment length is too large") \
233     ERR_ENTRY(S2N_ERR_RECORD_STUFFER_NEEDS_DRAINING, "Record stuffer needs to be drained first") \
234     ERR_ENTRY(S2N_ERR_UNSUPPORTED_EXTENSION, "Illegal use of a known, supported extension") \
235     ERR_ENTRY(S2N_ERR_MISSING_EXTENSION, "Mandatory extension not received") \
236     ERR_ENTRY(S2N_ERR_DUPLICATE_EXTENSION, "Extension block contains two or more extensions of the same type") \
237     ERR_ENTRY(S2N_ERR_INVALID_SECURITY_POLICY, "Invalid security policy") \
238     ERR_ENTRY(S2N_ERR_INVALID_KEM_PREFERENCES, "Invalid kem preferences version") \
239     ERR_ENTRY(S2N_ERR_INVALID_PARSED_EXTENSIONS, "Invalid parsed extension data") \
240     ERR_ENTRY(S2N_ERR_ASYNC_ALREADY_PERFORMED, "Async operation was already performed, cannot perfom it again") \
241     ERR_ENTRY(S2N_ERR_ASYNC_NOT_PERFORMED, "Async operation is not performed, cannot apply its result") \
242     ERR_ENTRY(S2N_ERR_ASYNC_WRONG_CONNECTION, "Async private key operation can only be consumed by connection which initiated it") \
243     ERR_ENTRY(S2N_ERR_ASYNC_APPLY_WHILE_INVOKING, "Async private key operation cannot consumed inside async pkey callback") \
244     ERR_ENTRY(S2N_ERR_ASYNC_ALREADY_APPLIED, "Async operation was already applied to connection, cannot apply it again") \
245     ERR_ENTRY(S2N_ERR_INVALID_HELLO_RETRY, "Invalid hello retry request") \
246     ERR_ENTRY(S2N_ERR_INVALID_STATE, "Invalid state, this is the result of invalid use of an API. Check the API documentation for the function that raised this error for more info") \
247     ERR_ENTRY(S2N_ERR_UNSUPPORTED_WITH_QUIC, "Functionality not supported when running with QUIC support enabled") \
248     ERR_ENTRY(S2N_ERR_PQ_CRYPTO, "An error occurred in a post-quantum crypto function") \
249     ERR_ENTRY(S2N_ERR_PQ_DISABLED, "Post-quantum crypto is disabled") \
250     ERR_ENTRY(S2N_ERR_DUPLICATE_PSK_IDENTITIES, "The list of pre-shared keys provided contains duplicate psk identities") \
251     ERR_ENTRY(S2N_ERR_OFFERED_PSKS_TOO_LONG, "The total pre-shared key data is too long to send over the wire") \
252     ERR_ENTRY(S2N_ERR_INVALID_SESSION_TICKET, "Session ticket data is not valid") \
253     ERR_ENTRY(S2N_ERR_REENTRANCY, "Original execution must complete before method can be called again") \
254     ERR_ENTRY(S2N_ERR_INVALID_CERT_STATE, "Certificate validation entered an invalid state and is not able to continue") \
255     ERR_ENTRY(S2N_ERR_INVALID_EARLY_DATA_STATE, "Early data in invalid state") \
256     ERR_ENTRY(S2N_ERR_EARLY_DATA_NOT_ALLOWED, "Early data is not allowed by the connection") \
257     ERR_ENTRY(S2N_ERR_NO_CERT_FOUND, "Certificate not found") \
258     ERR_ENTRY(S2N_ERR_NO_PRIVATE_KEY, "Certificate found, but no corresponding private key") \
259     ERR_ENTRY(S2N_ERR_CERT_NOT_VALIDATED, "Certificate not validated") \
260     ERR_ENTRY(S2N_ERR_MAX_EARLY_DATA_SIZE, "Maximum early data bytes exceeded") \
261     ERR_ENTRY(S2N_ERR_EARLY_DATA_BLOCKED, "Blocked on early data") \
262     ERR_ENTRY(S2N_ERR_PSK_MODE, "Mixing resumption and external PSKs is not supported") \
263     ERR_ENTRY(S2N_ERR_X509_EXTENSION_VALUE_NOT_FOUND, "X509 extension value not found") \
264     ERR_ENTRY(S2N_ERR_INVALID_X509_EXTENSION_TYPE, "Invalid X509 extension type") \
265     ERR_ENTRY(S2N_ERR_INSUFFICIENT_MEM_SIZE, "The provided buffer size is not large enough to contain the output data. Try increasing the allocation size.") \
266     ERR_ENTRY(S2N_ERR_KEYING_MATERIAL_EXPIRED, "The lifetime of the connection keying material has exceeded the limit. Perform a new full handshake.") \
267     ERR_ENTRY(S2N_ERR_EARLY_DATA_TRIAL_DECRYPT, "Unable to decrypt rejected early data") \
268 
269 /* clang-format on */
270 
271 #define ERR_STR_CASE(ERR, str) case ERR: return str;
272 #define ERR_NAME_CASE(ERR, str) case ERR: return #ERR;
273 
s2n_strerror(int error,const char * lang)274 const char *s2n_strerror(int error, const char *lang)
275 {
276     if (lang == NULL) {
277         lang = "EN";
278     }
279 
280     if (strcasecmp(lang, "EN")) {
281         return no_such_language;
282     }
283 
284     s2n_error err = error;
285     switch (err) {
286         ERR_ENTRIES(ERR_STR_CASE)
287 
288         /* Skip block ends */
289         case S2N_ERR_T_OK_END:
290         case S2N_ERR_T_IO_END:
291         case S2N_ERR_T_CLOSED_END:
292         case S2N_ERR_T_BLOCKED_END:
293         case S2N_ERR_T_ALERT_END:
294         case S2N_ERR_T_PROTO_END:
295         case S2N_ERR_T_INTERNAL_END:
296         case S2N_ERR_T_USAGE_END:
297             break;
298 
299         /* No default to make compiler fail on missing values */
300     }
301 
302     return no_such_error;
303 }
304 
s2n_strerror_name(int error)305 const char *s2n_strerror_name(int error)
306 {
307     s2n_error err = error;
308     switch (err) {
309         ERR_ENTRIES(ERR_NAME_CASE)
310 
311         /* Skip block ends */
312         case S2N_ERR_T_OK_END:
313         case S2N_ERR_T_IO_END:
314         case S2N_ERR_T_CLOSED_END:
315         case S2N_ERR_T_BLOCKED_END:
316         case S2N_ERR_T_ALERT_END:
317         case S2N_ERR_T_PROTO_END:
318         case S2N_ERR_T_INTERNAL_END:
319         case S2N_ERR_T_USAGE_END:
320             break;
321 
322         /* No default to make compiler fail on missing values */
323     }
324 
325     return no_such_error;
326 }
327 
s2n_strerror_debug(int error,const char * lang)328 const char *s2n_strerror_debug(int error, const char *lang)
329 {
330     if (lang == NULL) {
331         lang = "EN";
332     }
333 
334     if (strcasecmp(lang, "EN")) {
335         return no_such_language;
336     }
337 
338     /* No error, just return the no error string */
339     if (error == S2N_ERR_OK) {
340         return s2n_strerror(error, lang);
341     }
342 
343     return s2n_debug_str;
344 }
345 
s2n_error_get_type(int error)346 int s2n_error_get_type(int error)
347 {
348     return (error >> S2N_ERR_NUM_VALUE_BITS);
349 }
350 
351 
352 /* https://www.gnu.org/software/libc/manual/html_node/Backtraces.html */
353 static bool s_s2n_stack_traces_enabled = false;
354 
s2n_stack_traces_enabled()355 bool s2n_stack_traces_enabled()
356 {
357     return s_s2n_stack_traces_enabled;
358 }
359 
s2n_stack_traces_enabled_set(bool newval)360 int s2n_stack_traces_enabled_set(bool newval)
361 {
362     s_s2n_stack_traces_enabled = newval;
363     return S2N_SUCCESS;
364 }
365 
366 #ifdef S2N_HAVE_EXECINFO
367 
368 #define MAX_BACKTRACE_DEPTH 20
369 __thread struct s2n_stacktrace tl_stacktrace = {0};
370 
s2n_free_stacktrace(void)371 int s2n_free_stacktrace(void)
372 {
373     if (tl_stacktrace.trace != NULL) {
374         free(tl_stacktrace.trace);
375 	struct s2n_stacktrace zero_stacktrace = {0};
376 	tl_stacktrace = zero_stacktrace;
377     }
378     return S2N_SUCCESS;
379 }
380 
s2n_calculate_stacktrace(void)381 int s2n_calculate_stacktrace(void)
382 {
383     if (!s_s2n_stack_traces_enabled) {
384         return S2N_SUCCESS;
385     }
386 
387     int old_errno = errno;
388     POSIX_GUARD(s2n_free_stacktrace());
389     void *array[MAX_BACKTRACE_DEPTH];
390     tl_stacktrace.trace_size = backtrace(array, MAX_BACKTRACE_DEPTH);
391     tl_stacktrace.trace = backtrace_symbols(array, tl_stacktrace.trace_size);
392     errno = old_errno;
393     return S2N_SUCCESS;
394 }
395 
s2n_get_stacktrace(struct s2n_stacktrace * trace)396 int s2n_get_stacktrace(struct s2n_stacktrace *trace) {
397     *trace = tl_stacktrace;
398     return S2N_SUCCESS;
399 }
400 
s2n_print_stacktrace(FILE * fptr)401 int s2n_print_stacktrace(FILE *fptr)
402 {
403     if (!s_s2n_stack_traces_enabled) {
404       fprintf(fptr, "%s\n%s\n",
405 	      "NOTE: Some details are omitted, run with S2N_PRINT_STACKTRACE=1 for a verbose backtrace.",
406 	      "See https://github.com/awslabs/s2n/blob/main/docs/USAGE-GUIDE.md");
407         return S2N_SUCCESS;
408     }
409 
410     fprintf(fptr, "\nStacktrace is:\n");
411     for (int i = 0; i < tl_stacktrace.trace_size; ++i){
412         fprintf(fptr, "%s\n",  tl_stacktrace.trace[i]);
413     }
414     return S2N_SUCCESS;
415 }
416 
417 #else /* !S2N_HAVE_EXECINFO */
s2n_free_stacktrace(void)418 int s2n_free_stacktrace(void)
419 {
420     S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
421 }
422 
s2n_calculate_stacktrace(void)423 int s2n_calculate_stacktrace(void)
424 {
425     if (!s_s2n_stack_traces_enabled)
426     {
427         return S2N_SUCCESS;
428     }
429 
430     S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
431 }
432 
s2n_get_stacktrace(struct s2n_stacktrace * trace)433 int s2n_get_stacktrace(struct s2n_stacktrace *trace)
434 {
435     S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
436 }
437 
s2n_print_stacktrace(FILE * fptr)438 int s2n_print_stacktrace(FILE *fptr)
439 {
440     S2N_ERROR(S2N_ERR_UNIMPLEMENTED);
441 }
442 #endif /* S2N_HAVE_EXECINFO */
443