xref: /third_party/openssl/apps/lib/app_x509.c (revision e1051a39)
1/*
2 * Copyright 2020-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License").  You may not use
5 * this file except in compliance with the License.  You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <string.h>
11#include "apps.h"
12
13/*
14 * X509_ctrl_str() is sorely lacking in libcrypto, but is still needed to
15 * allow the application to process verification options in a manner similar
16 * to signature or other options that pass through EVP_PKEY_CTX_ctrl_str(),
17 * for uniformity.
18 *
19 * As soon as more stuff is added, the code will need serious rework.  For
20 * the moment, it only handles the FIPS 196 / SM2 distinguishing ID.
21 */
22#ifdef EVP_PKEY_CTRL_SET1_ID
23static ASN1_OCTET_STRING *mk_octet_string(void *value, size_t value_n)
24{
25    ASN1_OCTET_STRING *v = ASN1_OCTET_STRING_new();
26
27    if (v == NULL) {
28        BIO_printf(bio_err, "error: allocation failed\n");
29    } else if (!ASN1_OCTET_STRING_set(v, value, (int)value_n)) {
30        ASN1_OCTET_STRING_free(v);
31        v = NULL;
32    }
33    return v;
34}
35#endif
36
37static int x509_ctrl(void *object, int cmd, void *value, size_t value_n)
38{
39    switch (cmd) {
40#ifdef EVP_PKEY_CTRL_SET1_ID
41    case EVP_PKEY_CTRL_SET1_ID:
42        {
43            ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
44
45            if (v == NULL) {
46                BIO_printf(bio_err,
47                           "error: setting distinguishing ID in certificate failed\n");
48                return 0;
49            }
50
51            X509_set0_distinguishing_id(object, v);
52            return 1;
53        }
54#endif
55    default:
56        break;
57    }
58    return -2;     /* typical EVP_PKEY return for "unsupported" */
59}
60
61static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n)
62{
63    switch (cmd) {
64#ifdef EVP_PKEY_CTRL_SET1_ID
65    case EVP_PKEY_CTRL_SET1_ID:
66        {
67            ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
68
69            if (v == NULL) {
70                BIO_printf(bio_err,
71                           "error: setting distinguishing ID in certificate signing request failed\n");
72                return 0;
73            }
74
75            X509_REQ_set0_distinguishing_id(object, v);
76            return 1;
77        }
78#endif
79    default:
80        break;
81    }
82    return -2;     /* typical EVP_PKEY return for "unsupported" */
83}
84
85static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd,
86                                           void *value, size_t value_n),
87                               void *object, const char *value)
88{
89    int rv = 0;
90    char *stmp, *vtmp = NULL;
91    size_t vtmp_len = 0;
92    int cmd = 0; /* Will get command values that make sense somehow */
93
94    stmp = OPENSSL_strdup(value);
95    if (stmp == NULL)
96        return -1;
97    vtmp = strchr(stmp, ':');
98    if (vtmp != NULL) {
99        *vtmp = 0;
100        vtmp++;
101        vtmp_len = strlen(vtmp);
102    }
103
104    if (strcmp(stmp, "distid") == 0) {
105#ifdef EVP_PKEY_CTRL_SET1_ID
106        cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
107#endif
108    } else if (strcmp(stmp, "hexdistid") == 0) {
109        if (vtmp != NULL) {
110            void *hexid;
111            long hexid_len = 0;
112
113            hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len);
114            OPENSSL_free(stmp);
115            stmp = vtmp = hexid;
116            vtmp_len = (size_t)hexid_len;
117        }
118#ifdef EVP_PKEY_CTRL_SET1_ID
119        cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
120#endif
121    }
122
123    rv = ctrl(object, cmd, vtmp, vtmp_len);
124
125    OPENSSL_free(stmp);
126    return rv;
127}
128
129int x509_ctrl_string(X509 *x, const char *value)
130{
131    return do_x509_ctrl_string(x509_ctrl, x, value);
132}
133
134int x509_req_ctrl_string(X509_REQ *x, const char *value)
135{
136    return do_x509_ctrl_string(x509_req_ctrl, x, value);
137}
138