blob: f2c22948f20160968eb100a135d65a256846d858 [file] [log] [blame] [edit]
/*
* 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);
}