1/*
2 *  Error message information
3 *
4 *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
5 *  SPDX-License-Identifier: Apache-2.0
6 *
7 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8 *  not use this file except in compliance with the License.
9 *  You may obtain a copy of the License at
10 *
11 *  http://www.apache.org/licenses/LICENSE-2.0
12 *
13 *  Unless required by applicable law or agreed to in writing, software
14 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 *  See the License for the specific language governing permissions and
17 *  limitations under the License.
18 *
19 *  This file is part of mbed TLS (https://tls.mbed.org)
20 */
21
22#if !defined(MBEDTLS_CONFIG_FILE)
23#include "mbedtls/config.h"
24#else
25#include MBEDTLS_CONFIG_FILE
26#endif
27
28#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY)
29#include "mbedtls/error.h"
30#include <string.h>
31#endif
32
33#if defined(MBEDTLS_PLATFORM_C)
34#include "mbedtls/platform.h"
35#else
36#define mbedtls_snprintf snprintf
37#define mbedtls_time_t   time_t
38#endif
39
40#if defined(MBEDTLS_ERROR_C)
41
42#include <stdio.h>
43
44HEADER_INCLUDED
45
46// Error code table type
47struct ssl_errs {
48    int16_t errnum;
49    const char *errstr;
50};
51
52// Table of high level error codes
53static const struct ssl_errs mbedtls_high_level_error_tab[] = {
54// BEGIN generated code
55HIGH_LEVEL_CODE_CHECKS
56// END generated code
57};
58
59static const struct ssl_errs mbedtls_low_level_error_tab[] = {
60// Low level error codes
61//
62// BEGIN generated code
63LOW_LEVEL_CODE_CHECKS
64// END generated code
65};
66
67static const char *mbedtls_err_prefix = "MBEDTLS_ERR_";
68#define MBEDTLS_ERR_PREFIX_LEN ( sizeof("MBEDTLS_ERR_")-1 )
69
70// copy error text into buffer, ensure null termination, return strlen of result
71static size_t mbedtls_err_to_str(int err, const struct ssl_errs tab[], int tab_len, char *buf, size_t buflen) {
72    if (buflen == 0) return 0;
73
74    // prefix for all error names
75    strncpy(buf, mbedtls_err_prefix, buflen);
76    if (buflen <= MBEDTLS_ERR_PREFIX_LEN+1) {
77        buf[buflen-1] = 0;
78        return buflen-1;
79    }
80
81    // append error name from table
82    for (int i = 0; i < tab_len; i++) {
83        if (tab[i].errnum == err) {
84            strncpy(buf+MBEDTLS_ERR_PREFIX_LEN, tab[i].errstr, buflen-MBEDTLS_ERR_PREFIX_LEN);
85            buf[buflen-1] = 0;
86            return strlen(buf);
87        }
88    }
89
90    mbedtls_snprintf(buf+MBEDTLS_ERR_PREFIX_LEN, buflen-MBEDTLS_ERR_PREFIX_LEN, "UNKNOWN (0x%04X)",
91            err);
92    return strlen(buf);
93}
94
95#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
96
97void mbedtls_strerror(int ret, char *buf, size_t buflen) {
98    int use_ret;
99
100    if (buflen == 0) return;
101
102    buf[buflen-1] = 0;
103
104    if (ret < 0) ret = -ret;
105
106    //
107    // High-level error codes
108    //
109    uint8_t got_hl = (ret & 0xFF80) != 0;
110    if (got_hl) {
111        use_ret = ret & 0xFF80;
112
113        // special case
114#if defined(MBEDTLS_SSL_TLS_C)
115        if (use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE)) {
116            strncpy(buf, "MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE", buflen);
117            buf[buflen-1] = 0;
118            return;
119        }
120#endif
121
122        size_t len = mbedtls_err_to_str(use_ret, mbedtls_high_level_error_tab,
123                ARRAY_SIZE(mbedtls_high_level_error_tab), buf, buflen);
124
125        buf += len;
126        buflen -= len;
127        if (buflen == 0) return;
128    }
129
130    //
131    // Low-level error codes
132    //
133    use_ret = ret & ~0xFF80;
134
135    if (use_ret == 0) return;
136
137    // If high level code is present, make a concatenation between both error strings.
138    if (got_hl) {
139        if (buflen < 2) return;
140        *buf++ = '+';
141        buflen--;
142    }
143
144    mbedtls_err_to_str(use_ret, mbedtls_low_level_error_tab,
145            ARRAY_SIZE(mbedtls_low_level_error_tab), buf, buflen);
146}
147
148#else /* MBEDTLS_ERROR_C */
149
150#if defined(MBEDTLS_ERROR_STRERROR_DUMMY)
151
152/*
153 * Provide an non-function in case MBEDTLS_ERROR_C is not defined
154 */
155void mbedtls_strerror( int ret, char *buf, size_t buflen )
156{
157    ((void) ret);
158
159    if( buflen > 0 )
160        buf[0] = '\0';
161}
162
163#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */
164
165#endif /* MBEDTLS_ERROR_C */
166