File: s2n_openssl_x509.c

package info (click to toggle)
aws-crt-python 0.20.4%2Bdfsg-1~bpo12%2B1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-backports
  • size: 72,656 kB
  • sloc: ansic: 381,805; python: 23,008; makefile: 6,251; sh: 4,536; cpp: 699; ruby: 208; java: 77; perl: 73; javascript: 46; xml: 11
file content (118 lines) | stat: -rw-r--r-- 4,134 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
117
118
/*
 * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  http://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file is distributed
 * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

#include "crypto/s2n_openssl_x509.h"

#include "api/s2n.h"

S2N_CLEANUP_RESULT s2n_openssl_x509_stack_pop_free(STACK_OF(X509) **cert_chain)
{
    RESULT_ENSURE_REF(*cert_chain);
    sk_X509_pop_free(*cert_chain, X509_free);
    *cert_chain = NULL;
    return S2N_RESULT_OK;
}

S2N_CLEANUP_RESULT s2n_openssl_asn1_time_free_pointer(ASN1_GENERALIZEDTIME **time_ptr)
{
    /* The ANS1_*TIME structs are just typedef wrappers around ASN1_STRING
     *
     * The ASN1_TIME, ASN1_UTCTIME and ASN1_GENERALIZEDTIME structures are
     * represented as an ASN1_STRING internally and can be freed up using
     * ASN1_STRING_free().
     * https://www.openssl.org/docs/man1.1.1/man3/ASN1_TIME_to_tm.html
     */
    RESULT_ENSURE_REF(*time_ptr);
    ASN1_STRING_free((ASN1_STRING *) *time_ptr);
    *time_ptr = NULL;
    return S2N_RESULT_OK;
}

S2N_RESULT s2n_openssl_x509_parse_impl(struct s2n_blob *asn1der, X509 **cert_out, uint32_t *parsed_length)
{
    RESULT_ENSURE_REF(asn1der);
    RESULT_ENSURE_REF(asn1der->data);
    RESULT_ENSURE_REF(cert_out);
    RESULT_ENSURE_REF(parsed_length);

    uint8_t *cert_to_parse = asn1der->data;
    *cert_out = d2i_X509(NULL, (const unsigned char **) (void *) &cert_to_parse, asn1der->size);
    RESULT_ENSURE(*cert_out != NULL, S2N_ERR_DECODE_CERTIFICATE);

    /* If cert parsing is successful, d2i_X509 increments *cert_to_parse to the byte following the parsed data */
    *parsed_length = cert_to_parse - asn1der->data;

    return S2N_RESULT_OK;
}

S2N_RESULT s2n_openssl_x509_parse_without_length_validation(struct s2n_blob *asn1der, X509 **cert_out)
{
    RESULT_ENSURE_REF(asn1der);
    RESULT_ENSURE_REF(cert_out);

    uint32_t parsed_len = 0;
    RESULT_GUARD(s2n_openssl_x509_parse_impl(asn1der, cert_out, &parsed_len));

    return S2N_RESULT_OK;
}

S2N_RESULT s2n_openssl_x509_parse(struct s2n_blob *asn1der, X509 **cert_out)
{
    RESULT_ENSURE_REF(asn1der);
    RESULT_ENSURE_REF(cert_out);

    uint32_t parsed_len = 0;
    RESULT_GUARD(s2n_openssl_x509_parse_impl(asn1der, cert_out, &parsed_len));

    /* Some TLS clients in the wild send extra trailing bytes after the Certificate.
     * Allow this in s2n for backwards compatibility with existing clients. */
    uint32_t trailing_bytes = asn1der->size - parsed_len;
    RESULT_ENSURE(trailing_bytes <= S2N_MAX_ALLOWED_CERT_TRAILING_BYTES, S2N_ERR_DECODE_CERTIFICATE);

    return S2N_RESULT_OK;
}

S2N_RESULT s2n_openssl_x509_get_cert_info(X509 *cert, struct s2n_cert_info *info)
{
    RESULT_ENSURE_REF(cert);
    RESULT_ENSURE_REF(info);

    X509_NAME *issuer_name = X509_get_issuer_name(cert);
    RESULT_ENSURE_REF(issuer_name);

    X509_NAME *subject_name = X509_get_subject_name(cert);
    RESULT_ENSURE_REF(subject_name);

    if (X509_NAME_cmp(issuer_name, subject_name) == 0) {
        info->self_signed = true;
    } else {
        info->self_signed = false;
    }

#if defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x02070000f)
    RESULT_ENSURE_REF(cert->sig_alg);
    info->signature_nid = OBJ_obj2nid(cert->sig_alg->algorithm);
#else
    info->signature_nid = X509_get_signature_nid(cert);
#endif
    /* These is no method to directly retrieve that signature digest from the X509*
     * that is available in all libcryptos, so instead we use find_sigid_algs. For
     * a signature NID_ecdsa_with_SHA256 this will return NID_SHA256 
     */
    RESULT_GUARD_OSSL(OBJ_find_sigid_algs(info->signature_nid, &info->signature_digest_nid, NULL),
            S2N_ERR_CERT_TYPE_UNSUPPORTED);

    return S2N_RESULT_OK;
}