summaryrefslogtreecommitdiffstats
path: root/apps/lib/app_x509.c
blob: f2c22948f20160968eb100a135d65a256846d858 (plain)
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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include <string.h>
#include "apps.h"

/*
 * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to
 * allow the application to process verification options in a manner similar
 * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(),
 * for uniformity.
 *
 * As soon as more stuff is added, the code will need serious rework.  For
 * the moment, it only handles the FIPS 196 / SM2 distinguishing ID.
 */
#ifdef EVP_PKEY_CTRL_SET1_ID
static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n)
{
    ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new();

    if (v == NULL) {
        BIO_printf(bio_err, "error: allocation failed\n");
    } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) {
        ASN1_OCTET_STRING_free(v);
        v = NULL;
    }
    return v;
}
#endif

static int x509_ctrl(void *object, int cmd, void *value, size_t value_n)
{
    switch (cmd) {
#ifdef EVP_PKEY_CTRL_SET1_ID
    case EVP_PKEY_CTRL_SET1_ID:
        {
            ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);

            if (v == NULL) {
                BIO_printf(bio_err,
                           "error: setting distinguishing ID in certificate failed\n");
                return 0;
            }

            X509_set0_distinguishing_id(object, v);
            return 1;
        }
#endif
    default:
        break;
    }
    return -2;     /* typical EVP_PKEY return for "unsupported" */
}

static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n)
{
    switch (cmd) {
#ifdef EVP_PKEY_CTRL_SET1_ID
    case EVP_PKEY_CTRL_SET1_ID:
        {
            ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);

            if (v == NULL) {
                BIO_printf(bio_err,
                           "error: setting distinguishing ID in certificate signing request failed\n");
                return 0;
            }

            X509_REQ_set0_distinguishing_id(object, v);
            return 1;
        }
#endif
    default:
        break;
    }
    return -2;     /* typical EVP_PKEY return for "unsupported" */
}

static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd,
                                           void *value, size_t value_n),
                               void *object, const char *value)
{
    int rv = 0;
    char *stmp, *vtmp = NULL;
    size_t vtmp_len = 0;
    int cmd = 0; /* Will get command values that make sense somehow */

    stmp = OPENSSL_strdup(value);
    if (stmp == NULL)
        return -1;
    vtmp = strchr(stmp, ':');
    if (vtmp != NULL) {
        *vtmp = 0;
        vtmp++;
        vtmp_len = strlen(vtmp);
    }

    if (strcmp(stmp, "distid") == 0) {
#ifdef EVP_PKEY_CTRL_SET1_ID
        cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
#endif
    } else if (strcmp(stmp, "hexdistid") == 0) {
        if (vtmp != NULL) {
            void *hexid;
            long hexid_len = 0;

            hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len);
            OPENSSL_free(stmp);
            stmp = vtmp = hexid;
            vtmp_len = (size_t)hexid_len;
        }
#ifdef EVP_PKEY_CTRL_SET1_ID
        cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
#endif
    }

    rv = ctrl(object, cmd, vtmp, vtmp_len);

    OPENSSL_free(stmp);
    return rv;
}

int x509_ctrl_string(X509 *x, const char *value)
{
    return do_x509_ctrl_string(x509_ctrl, x, value);
}

int x509_req_ctrl_string(X509_REQ *x, const char *value)
{
    return do_x509_ctrl_string(x509_req_ctrl, x, value);
}