File: lccrypto_common.c

package info (click to toggle)
aws-crt-python 0.28.4%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 78,428 kB
  • sloc: ansic: 437,955; python: 27,657; makefile: 5,855; sh: 4,289; ruby: 208; java: 82; perl: 73; cpp: 25; xml: 11
file content (116 lines) | stat: -rw-r--r-- 4,402 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
/**
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0.
 */

#include <aws/cal/cal.h>
#include <aws/cal/private/opensslcrypto_common.h>

#define OPENSSL_SUPPRESS_DEPRECATED
#include <openssl/err.h>
#include <openssl/evp.h>

#if defined(OPENSSL_IS_OPENSSL)
/*Error defines were part of evp.h in 1.0.x and were moved to evperr.h in 1.1.0*/
#    if OPENSSL_VERSION_NUMBER >= 0x10100000L
#        include <openssl/evperr.h>
#    endif
#else
#    include <openssl/evp_errors.h>
#endif

/*
 * Transforms evp error code into crt error code and raises it as necessary.
 * All evp functions follow the same:
 * >= 1 for success
 * <= 0 for failure
 * -2 always indicates incorrect algo for operation
 */
int aws_reinterpret_lc_evp_error_as_crt(int evp_error, const char *function_name, enum aws_cal_log_subject subject) {
    if (evp_error > 0) {
        return AWS_OP_SUCCESS;
    }

    /* AWS-LC/BoringSSL error code is uint32_t, but OpenSSL uses unsigned long. */
#if defined(OPENSSL_IS_OPENSSL)
    uint32_t error = ERR_peek_error();
#else
    unsigned long error = ERR_peek_error();
#endif

    int crt_error = AWS_OP_ERR;
    const char *error_message = ERR_reason_error_string(error);

    if (evp_error == -2) {
        crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM;
        goto on_error;
    }

    if (ERR_GET_LIB(error) == ERR_LIB_EVP) {
        switch (ERR_GET_REASON(error)) {
            case EVP_R_BUFFER_TOO_SMALL: {
                crt_error = AWS_ERROR_SHORT_BUFFER;
                goto on_error;
            }
            case EVP_R_UNSUPPORTED_ALGORITHM: {
                crt_error = AWS_ERROR_CAL_UNSUPPORTED_ALGORITHM;
                goto on_error;
            }
        }
    }

    crt_error = AWS_ERROR_CAL_CRYPTO_OPERATION_FAILED;

on_error:
    AWS_LOGF_ERROR(
        subject,
        "%s() failed. returned: %d extended error:%lu(%s) aws_error:%s",
        function_name,
        evp_error,
        (unsigned long)error,
        error_message == NULL ? "" : error_message,
        aws_error_name(crt_error));

    return aws_raise_error(crt_error);
}

/* Validate at runtime that we're linked against the same libcrypto we compiled against. */
void aws_validate_libcrypto_linkage(void) {
    /* NOTE: the choice of stack buffer size is somewhat arbitrary. it's
     * possible, but unlikely, that libcrypto version strings may exceed this in
     * the future. we guard against buffer overflow by limiting write size in
     * snprintf with the size of the buffer itself. if libcrypto version strings
     * do eventually exceed the chosen size, this runtime check will fail and
     * will need to be addressed by increasing buffer size.*/
    char expected_version[64] = {0};
#if defined(OPENSSL_IS_AWSLC)
    /* get FIPS mode at runtime because headers don't give any indication of
     * AWS-LC's FIPSness at aws-c-cal compile time. version number can still be
     * captured at preprocess/compile time from AWSLC_VERSION_NUMBER_STRING.*/
    const char *mode = FIPS_mode() ? "AWS-LC FIPS" : "AWS-LC";
    snprintf(expected_version, sizeof(expected_version), "%s %s", mode, AWSLC_VERSION_NUMBER_STRING);
#elif defined(OPENSSL_IS_BORINGSSL)
    snprintf(expected_version, sizeof(expected_version), "BoringSSL");
#elif defined(OPENSSL_IS_OPENSSL)
    snprintf(expected_version, sizeof(expected_version), OPENSSL_VERSION_TEXT);
#elif !defined(BYO_CRYPTO)
#    error Unsupported libcrypto!
#endif
    const char *runtime_version = SSLeay_version(SSLEAY_VERSION);
    AWS_LOGF_DEBUG(
        AWS_LS_CAL_LIBCRYPTO_RESOLVE,
        "Compiled with libcrypto %s, linked to libcrypto %s",
        expected_version,
        runtime_version);
#if defined(OPENSSL_IS_OPENSSL)
    /* Validate that the string "AWS-LC" doesn't appear in OpenSSL version str. */
    AWS_FATAL_ASSERT(strstr("AWS-LC", expected_version) == NULL);
    AWS_FATAL_ASSERT(strstr("AWS-LC", runtime_version) == NULL);
    /* Validate both expected and runtime versions begin with OpenSSL's version str prefix. */
    const char *openssl_prefix = "OpenSSL ";
    AWS_FATAL_ASSERT(strncmp(openssl_prefix, expected_version, strlen(openssl_prefix)) == 0);
    AWS_FATAL_ASSERT(strncmp(openssl_prefix, runtime_version, strlen(openssl_prefix)) == 0);
#else
    AWS_FATAL_ASSERT(strcmp(expected_version, runtime_version) == 0 && "libcrypto mislink");
#endif
}