version 1.35, 2023/11/21 17:56:19 |
version 1.36, 2024/01/12 11:24:03 |
|
|
|
|
static int callb(int ok, X509_STORE_CTX *ctx); |
static int callb(int ok, X509_STORE_CTX *ctx); |
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, |
static int sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, |
const EVP_MD *digest, CONF *conf, char *section); |
const EVP_MD *digest, CONF *conf, char *section, X509_NAME *issuer); |
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, |
static int x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, |
X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, |
X509 *x, X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, |
char *serial, int create, int days, int clrext, CONF *conf, char *section, |
char *serial, int create, int days, int clrext, CONF *conf, char *section, |
ASN1_INTEGER *sno); |
ASN1_INTEGER *sno, X509_NAME *issuer); |
static int purpose_print(BIO *bio, X509 *cert, const X509_PURPOSE *pt); |
static int purpose_print(BIO *bio, X509 *cert, const X509_PURPOSE *pt); |
|
|
static struct { |
static struct { |
|
|
unsigned long certflag; |
unsigned long certflag; |
int checkend; |
int checkend; |
int checkoffset; |
int checkoffset; |
|
unsigned long chtype; |
int clrext; |
int clrext; |
int clrreject; |
int clrreject; |
int clrtrust; |
int clrtrust; |
|
|
char *extfile; |
char *extfile; |
char *extsect; |
char *extsect; |
int fingerprint; |
int fingerprint; |
|
char *force_pubkey; |
char *infile; |
char *infile; |
int informat; |
int informat; |
int issuer; |
int issuer; |
|
|
int keyformat; |
int keyformat; |
const EVP_MD *md_alg; |
const EVP_MD *md_alg; |
int modulus; |
int modulus; |
|
int multirdn; |
int next_serial; |
int next_serial; |
unsigned long nmflag; |
unsigned long nmflag; |
int noout; |
int noout; |
|
|
STACK_OF(ASN1_OBJECT) *reject; |
STACK_OF(ASN1_OBJECT) *reject; |
int reqfile; |
int reqfile; |
int serial; |
int serial; |
|
char *set_issuer; |
|
char *set_subject; |
int sign_flag; |
int sign_flag; |
STACK_OF(OPENSSL_STRING) *sigopts; |
STACK_OF(OPENSSL_STRING) *sigopts; |
ASN1_INTEGER *sno; |
ASN1_INTEGER *sno; |
|
|
return (0); |
return (0); |
} |
} |
|
|
|
static int |
|
x509_opt_utf8(void) |
|
{ |
|
cfg.chtype = MBSTRING_UTF8; |
|
return (0); |
|
} |
|
|
static const struct option x509_options[] = { |
static const struct option x509_options[] = { |
{ |
{ |
.name = "C", |
.name = "C", |
|
|
.order = &cfg.num, |
.order = &cfg.num, |
}, |
}, |
{ |
{ |
|
.name = "force_pubkey", |
|
.argname = "key", |
|
.desc = "Force the public key to be put in the certificate", |
|
.type = OPTION_ARG, |
|
.opt.arg = &cfg.force_pubkey, |
|
}, |
|
{ |
.name = "hash", |
.name = "hash", |
.desc = "Synonym for -subject_hash", |
.desc = "Synonym for -subject_hash", |
.type = OPTION_ORDER, |
.type = OPTION_ORDER, |
|
|
.order = &cfg.num, |
.order = &cfg.num, |
}, |
}, |
{ |
{ |
|
.name = "multivalue-rdn", |
|
.desc = "Enable support for multivalued RDNs", |
|
.type = OPTION_FLAG, |
|
.opt.flag = &cfg.multirdn, |
|
}, |
|
{ |
.name = "nameopt", |
.name = "nameopt", |
.argname = "option", |
.argname = "option", |
.desc = "Various certificate name options", |
.desc = "Various certificate name options", |
|
|
.order = &cfg.num, |
.order = &cfg.num, |
}, |
}, |
{ |
{ |
|
.name = "set_issuer", |
|
.argname = "name", |
|
.desc = "Set the issuer name", |
|
.type = OPTION_ARG, |
|
.opt.arg = &cfg.set_issuer, |
|
}, |
|
{ |
.name = "set_serial", |
.name = "set_serial", |
.argname = "n", |
.argname = "n", |
.desc = "Serial number to use", |
.desc = "Serial number to use", |
|
|
.opt.argfunc = x509_opt_set_serial, |
.opt.argfunc = x509_opt_set_serial, |
}, |
}, |
{ |
{ |
|
.name = "set_subject", |
|
.argname = "name", |
|
.desc = "Set the subject name", |
|
.type = OPTION_ARG, |
|
.opt.arg = &cfg.set_subject, |
|
}, |
|
{ |
.name = "setalias", |
.name = "setalias", |
.argname = "arg", |
.argname = "arg", |
.desc = "Set certificate alias", |
.desc = "Set certificate alias", |
|
|
.order = &cfg.num, |
.order = &cfg.num, |
}, |
}, |
{ |
{ |
|
.name = "subj", |
|
.type = OPTION_ARG, |
|
.opt.arg = &cfg.set_subject, |
|
}, |
|
{ |
.name = "subject", |
.name = "subject", |
.desc = "Print subject name", |
.desc = "Print subject name", |
.type = OPTION_ORDER, |
.type = OPTION_ORDER, |
|
|
.opt.flag = &cfg.trustout, |
.opt.flag = &cfg.trustout, |
}, |
}, |
{ |
{ |
|
.name = "utf8", |
|
.desc = "Input characters are in UTF-8 (default ASCII)", |
|
.type = OPTION_FUNC, |
|
.opt.func = x509_opt_utf8, |
|
}, |
|
{ |
.name = "x509toreq", |
.name = "x509toreq", |
.desc = "Output a certification request object", |
.desc = "Output a certification request object", |
.type = OPTION_ORDER, |
.type = OPTION_ORDER, |
|
|
" [-CAkeyform der | pem] [-CAserial file] [-certopt option]\n" |
" [-CAkeyform der | pem] [-CAserial file] [-certopt option]\n" |
" [-checkend arg] [-clrext] [-clrreject] [-clrtrust] [-dates]\n" |
" [-checkend arg] [-clrext] [-clrreject] [-clrtrust] [-dates]\n" |
" [-days arg] [-email] [-enddate] [-extensions section]\n" |
" [-days arg] [-email] [-enddate] [-extensions section]\n" |
" [-extfile file] [-fingerprint] [-hash] [-in file]\n" |
" [-extfile file] [-fingerprint] [-force_pubkey key] [-hash]\n" |
" [-inform der | net | pem] [-issuer] [-issuer_hash]\n" |
" [-in file] [-inform der | net | pem] [-issuer]\n" |
" [-issuer_hash_old] [-keyform der | pem] [-md5 | -sha1]\n" |
" [-issuer_hash] [-issuer_hash_old] [-keyform der | pem]\n" |
" [-modulus] [-nameopt option] [-next_serial] [-noout]\n" |
" [-md5 | -sha1] [-modulus] [-multivalue-rdn]\n" |
" [-ocsp_uri] [-ocspid] [-out file]\n" |
" [-nameopt option] [-next_serial] [-noout] [-ocsp_uri]\n" |
" [-outform der | net | pem] [-passin arg] [-pubkey]\n" |
" [-ocspid] [-out file] [-outform der | net | pem]\n" |
" [-purpose] [-req] [-serial] [-set_serial n] [-setalias arg]\n" |
" [-passin arg] [-pubkey] [-purpose] [-req] [-serial]\n" |
" [-signkey file] [-sigopt nm:v] [-startdate] [-subject]\n" |
" [-set_issuer name] [-set_serial n] [-set_subject name]\n" |
" [-subject_hash] [-subject_hash_old] [-text] [-trustout]\n" |
" [-setalias arg] [-signkey file] [-sigopt nm:v] [-startdate]\n" |
" [-x509toreq]\n"); |
" [-subject] [-subject_hash] [-subject_hash_old] [-text]\n" |
|
" [-trustout] [-utf8] [-x509toreq]\n"); |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
options_usage(x509_options); |
options_usage(x509_options); |
fprintf(stderr, "\n"); |
fprintf(stderr, "\n"); |
|
|
int ret = 1; |
int ret = 1; |
X509_REQ *req = NULL; |
X509_REQ *req = NULL; |
X509 *x = NULL, *xca = NULL; |
X509 *x = NULL, *xca = NULL; |
EVP_PKEY *Upkey = NULL, *CApkey = NULL; |
X509_NAME *iname = NULL, *sname = NULL; |
|
EVP_PKEY *Fpkey = NULL, *Upkey = NULL, *CApkey = NULL; |
int i; |
int i; |
BIO *out = NULL; |
BIO *out = NULL; |
BIO *STDout = NULL; |
BIO *STDout = NULL; |
|
|
} |
} |
|
|
memset(&cfg, 0, sizeof(cfg)); |
memset(&cfg, 0, sizeof(cfg)); |
|
cfg.chtype = MBSTRING_ASC; |
cfg.days = DEF_DAYS; |
cfg.days = DEF_DAYS; |
cfg.informat = FORMAT_PEM; |
cfg.informat = FORMAT_PEM; |
cfg.outformat = FORMAT_PEM; |
cfg.outformat = FORMAT_PEM; |
|
|
goto end; |
goto end; |
} |
} |
} |
} |
|
if (cfg.force_pubkey != NULL) { |
|
if ((Fpkey = load_pubkey(bio_err, cfg.force_pubkey, |
|
cfg.keyformat, 0, NULL, "Forced key")) == NULL) |
|
goto end; |
|
} |
if (cfg.reqfile) { |
if (cfg.reqfile) { |
EVP_PKEY *pkey; |
EVP_PKEY *pkey; |
BIO *in; |
BIO *in; |
|
|
} else if (!X509_set_serialNumber(x, cfg.sno)) |
} else if (!X509_set_serialNumber(x, cfg.sno)) |
goto end; |
goto end; |
|
|
if (!X509_set_issuer_name(x, X509_REQ_get_subject_name(req))) |
if (cfg.set_issuer != NULL) { |
|
iname = parse_name(cfg.set_issuer, cfg.chtype, |
|
cfg.multirdn); |
|
if (iname == NULL) |
|
goto end; |
|
} |
|
|
|
if (cfg.set_subject != NULL) |
|
sname = parse_name(cfg.set_subject, cfg.chtype, |
|
cfg.multirdn); |
|
else |
|
sname = X509_NAME_dup(X509_REQ_get_subject_name(req)); |
|
if (sname == NULL) |
goto end; |
goto end; |
if (!X509_set_subject_name(x, X509_REQ_get_subject_name(req))) |
if (!X509_set_subject_name(x, sname)) |
goto end; |
goto end; |
|
|
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) |
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) |
|
|
NULL) == NULL) |
NULL) == NULL) |
goto end; |
goto end; |
|
|
if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) |
if ((pkey = Fpkey) == NULL) |
|
pkey = X509_REQ_get0_pubkey(req); |
|
if (pkey == NULL) |
goto end; |
goto end; |
if (!X509_set_pubkey(x, pkey)) |
if (!X509_set_pubkey(x, pkey)) |
goto end; |
goto end; |
|
|
} |
} |
if (!sign(x, Upkey, cfg.days, |
if (!sign(x, Upkey, cfg.days, |
cfg.clrext, cfg.digest, |
cfg.clrext, cfg.digest, |
extconf, cfg.extsect)) |
extconf, cfg.extsect, iname)) |
goto end; |
goto end; |
} else if (cfg.CA_flag == i) { |
} else if (cfg.CA_flag == i) { |
BIO_printf(bio_err, "Getting CA Private Key\n"); |
BIO_printf(bio_err, "Getting CA Private Key\n"); |
|
|
if (!x509_certify(ctx, cfg.CAfile, cfg.digest, |
if (!x509_certify(ctx, cfg.CAfile, cfg.digest, |
x, xca, CApkey, cfg.sigopts, cfg.CAserial, |
x, xca, CApkey, cfg.sigopts, cfg.CAserial, |
cfg.CA_createserial, cfg.days, cfg.clrext, |
cfg.CA_createserial, cfg.days, cfg.clrext, |
extconf, cfg.extsect, cfg.sno)) |
extconf, cfg.extsect, cfg.sno, iname)) |
goto end; |
goto end; |
} else if (cfg.x509req == i) { |
} else if (cfg.x509req == i) { |
EVP_PKEY *pk; |
EVP_PKEY *pk; |
|
|
NCONF_free(extconf); |
NCONF_free(extconf); |
BIO_free_all(out); |
BIO_free_all(out); |
BIO_free_all(STDout); |
BIO_free_all(STDout); |
|
X509_NAME_free(iname); |
|
X509_NAME_free(sname); |
X509_STORE_free(ctx); |
X509_STORE_free(ctx); |
X509_REQ_free(req); |
X509_REQ_free(req); |
X509_free(x); |
X509_free(x); |
X509_free(xca); |
X509_free(xca); |
|
EVP_PKEY_free(Fpkey); |
EVP_PKEY_free(Upkey); |
EVP_PKEY_free(Upkey); |
EVP_PKEY_free(CApkey); |
EVP_PKEY_free(CApkey); |
sk_OPENSSL_STRING_free(cfg.sigopts); |
sk_OPENSSL_STRING_free(cfg.sigopts); |
|
|
x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, |
x509_certify(X509_STORE *ctx, char *CAfile, const EVP_MD *digest, X509 *x, |
X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, |
X509 *xca, EVP_PKEY *pkey, STACK_OF(OPENSSL_STRING) *sigopts, |
char *serialfile, int create, int days, int clrext, CONF *conf, |
char *serialfile, int create, int days, int clrext, CONF *conf, |
char *section, ASN1_INTEGER *sno) |
char *section, ASN1_INTEGER *sno, X509_NAME *issuer) |
{ |
{ |
int ret = 0; |
int ret = 0; |
ASN1_INTEGER *bs = NULL; |
ASN1_INTEGER *bs = NULL; |
|
|
"CA certificate and CA private key do not match\n"); |
"CA certificate and CA private key do not match\n"); |
goto end; |
goto end; |
} |
} |
if (!X509_set_issuer_name(x, X509_get_subject_name(xca))) |
|
|
if (issuer == NULL) |
|
issuer = X509_get_subject_name(xca); |
|
if (issuer == NULL) |
goto end; |
goto end; |
|
if (!X509_set_issuer_name(x, issuer)) |
|
goto end; |
|
|
if (!X509_set_serialNumber(x, bs)) |
if (!X509_set_serialNumber(x, bs)) |
goto end; |
goto end; |
|
|
|
|
/* self sign */ |
/* self sign */ |
static int |
static int |
sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, |
sign(X509 *x, EVP_PKEY *pkey, int days, int clrext, const EVP_MD *digest, |
CONF *conf, char *section) |
CONF *conf, char *section, X509_NAME *issuer) |
{ |
{ |
EVP_PKEY *pktmp; |
EVP_PKEY *pktmp; |
|
|
|
|
EVP_PKEY_copy_parameters(pktmp, pkey); |
EVP_PKEY_copy_parameters(pktmp, pkey); |
EVP_PKEY_save_parameters(pktmp, 1); |
EVP_PKEY_save_parameters(pktmp, 1); |
|
|
if (!X509_set_issuer_name(x, X509_get_subject_name(x))) |
if (issuer == NULL) |
|
issuer = X509_get_subject_name(x); |
|
if (issuer == NULL) |
|
goto err; |
|
if (!X509_set_issuer_name(x, issuer)) |
goto err; |
goto err; |
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) |
if (X509_gmtime_adj(X509_get_notBefore(x), 0) == NULL) |
goto err; |
goto err; |