Home | History | Annotate | Line # | Download | only in lib
      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
     23 static 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 
     37 static 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         ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
     43 
     44         if (v == NULL) {
     45             BIO_printf(bio_err,
     46                 "error: setting distinguishing ID in certificate failed\n");
     47             return 0;
     48         }
     49 
     50         X509_set0_distinguishing_id(object, v);
     51         return 1;
     52     }
     53 #endif
     54     default:
     55         break;
     56     }
     57     return -2; /* typical EVP_PKEY return for "unsupported" */
     58 }
     59 
     60 static int x509_req_ctrl(void *object, int cmd, void *value, size_t value_n)
     61 {
     62     switch (cmd) {
     63 #ifdef EVP_PKEY_CTRL_SET1_ID
     64     case EVP_PKEY_CTRL_SET1_ID: {
     65         ASN1_OCTET_STRING *v = mk_octet_string(value, value_n);
     66 
     67         if (v == NULL) {
     68             BIO_printf(bio_err,
     69                 "error: setting distinguishing ID in certificate signing request failed\n");
     70             return 0;
     71         }
     72 
     73         X509_REQ_set0_distinguishing_id(object, v);
     74         return 1;
     75     }
     76 #endif
     77     default:
     78         break;
     79     }
     80     return -2; /* typical EVP_PKEY return for "unsupported" */
     81 }
     82 
     83 static int do_x509_ctrl_string(int (*ctrl)(void *object, int cmd,
     84                                    void *value, size_t value_n),
     85     void *object, const char *value)
     86 {
     87     int rv = 0;
     88     char *stmp, *vtmp = NULL;
     89     size_t vtmp_len = 0;
     90     int cmd = 0; /* Will get command values that make sense somehow */
     91 
     92     stmp = OPENSSL_strdup(value);
     93     if (stmp == NULL)
     94         return -1;
     95     vtmp = strchr(stmp, ':');
     96     if (vtmp != NULL) {
     97         *vtmp = 0;
     98         vtmp++;
     99         vtmp_len = strlen(vtmp);
    100     }
    101 
    102     if (strcmp(stmp, "distid") == 0) {
    103 #ifdef EVP_PKEY_CTRL_SET1_ID
    104         cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
    105 #endif
    106     } else if (strcmp(stmp, "hexdistid") == 0) {
    107         if (vtmp != NULL) {
    108             void *hexid;
    109             long hexid_len = 0;
    110 
    111             hexid = OPENSSL_hexstr2buf((const char *)vtmp, &hexid_len);
    112             OPENSSL_free(stmp);
    113             stmp = vtmp = hexid;
    114             vtmp_len = (size_t)hexid_len;
    115         }
    116 #ifdef EVP_PKEY_CTRL_SET1_ID
    117         cmd = EVP_PKEY_CTRL_SET1_ID; /* ... except we put it in X509 */
    118 #endif
    119     }
    120 
    121     rv = ctrl(object, cmd, vtmp, vtmp_len);
    122 
    123     OPENSSL_free(stmp);
    124     return rv;
    125 }
    126 
    127 int x509_ctrl_string(X509 *x, const char *value)
    128 {
    129     return do_x509_ctrl_string(x509_ctrl, x, value);
    130 }
    131 
    132 int x509_req_ctrl_string(X509_REQ *x, const char *value)
    133 {
    134     return do_x509_ctrl_string(x509_req_ctrl, x, value);
    135 }
    136