gateway2/Tongsuo-8.4.0/apps/delecred.c
2026-07-11 13:40:57 +08:00

224 lines
6.3 KiB
C

/*
* Copyright 2022 The Tongsuo 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://github.com/Tongsuo-Project/Tongsuo/blob/master/LICENSE.txt
*/
#include <stdio.h>
#include <string.h>
#include "apps.h"
#include "progs.h"
#include <openssl/pem.h>
#include <openssl/err.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include "../ssl/ssl_local.h"
typedef enum OPTION_choice {
OPT_ERR = -1, OPT_EOF = 0, OPT_HELP,
OPT_IN, OPT_OUT,
OPT_NEW, OPT_DC_KEY,
OPT_EE_CERT, OPT_EE_KEY,
OPT_SEC, OPT_MD,
OPT_EXPECT_VERIFY_MD, OPT_CLIENT, OPT_SERVER,
OPT_TEXT, OPT_NOOUT
} OPTION_CHOICE;
const OPTIONS delecred_options[] = {
{"help", OPT_HELP, '-', "Display this summary"},
{"in", OPT_IN, '<', "input file"},
{"out", OPT_OUT, '>', "output file"},
{"new", OPT_NEW, '-', "generate a new delegated credential"},
{"dc_key", OPT_DC_KEY, 's', "private key of delegated credential"},
{"parent_cert", OPT_EE_CERT, 's', "end-entity certificate used to sign the dc"},
{"parent_key", OPT_EE_KEY, 's', "private key of the end-entity certificate"},
{"sec", OPT_SEC, 'p', "dc valid time, default is 604800 seconds(7 days)"},
{"expect_verify_md", OPT_EXPECT_VERIFY_MD, 's', "expected message digest of signature algorithm of dc key pair"},
{"", OPT_MD, '-', "Any supported digest"},
{"client", OPT_CLIENT, '-', "client DC"},
{"server", OPT_SERVER, '-', "server DC"},
{"text", OPT_TEXT, '-', "print the dc in text form"},
{"noout", OPT_NOOUT, '-', "no dc output"},
{NULL}
};
int delecred_main(int argc, char **argv)
{
int ret = 1;
int res;
char *prog;
size_t i;
OPTION_CHOICE o;
char *infile = NULL, *outfile = NULL;
BIO *in = NULL, *out = NULL;
int text = 0;
int noout = 0;
int new_flag = 0;
char *dc_key = NULL;
char *ee_cert_file = NULL, *ee_key_file = NULL;
char *expect_verify_hash = NULL;
EVP_MD *expect_verify_md = NULL;
EVP_MD *sign_md = NULL;
int is_server = 1;
int valid_time = 7 * 24 * 3600;
DELEGATED_CREDENTIAL *dc = NULL;
ENGINE *e = NULL;
EVP_PKEY *dc_pkey = NULL;
X509 *ee_cert = NULL;
EVP_PKEY *ee_pkey = NULL;
unsigned char *dc_raw = NULL;
unsigned long dc_raw_len = 0;
prog = opt_init(argc, argv, delecred_options);
while ((o = opt_next()) != OPT_EOF) {
switch (o) {
case OPT_EOF:
case OPT_ERR:
opthelp:
BIO_printf(bio_err, "%s: Use -help for summary.\n", prog);
goto end;
case OPT_HELP:
opt_help(delecred_options);
ret = 0;
goto end;
case OPT_IN:
infile = opt_arg();
break;
case OPT_OUT:
outfile = opt_arg();
break;
case OPT_NEW:
new_flag = 1;
break;
case OPT_DC_KEY:
dc_key = opt_arg();
break;
case OPT_EE_CERT:
ee_cert_file = opt_arg();
break;
case OPT_EE_KEY:
ee_key_file = opt_arg();
break;
case OPT_SEC:
opt_int(opt_arg(), &valid_time);
break;
case OPT_EXPECT_VERIFY_MD:
expect_verify_hash = opt_arg();
if (!opt_md(expect_verify_hash, &expect_verify_md))
goto opthelp;
break;
case OPT_MD:
if (!opt_md(opt_unknown(), &sign_md))
goto opthelp;
break;
case OPT_CLIENT:
is_server = 0;
break;
case OPT_SERVER:
is_server = 1;
break;
case OPT_TEXT:
text = 1;
break;
case OPT_NOOUT:
noout = 1;
break;
}
}
argc = opt_num_rest();
if (argc != 0)
goto opthelp;
if (infile) {
dc = DC_load_from_file_ex(infile, app_get0_libctx(), app_get0_propq());
if (dc == NULL) {
goto end;
}
if (text) {
if (!DC_print(bio_out, dc))
goto end;
}
} else if (new_flag) {
dc_pkey = load_key(dc_key, FORMAT_PEM, 1, NULL, e, "key");
if (dc_pkey == NULL) {
goto end;
}
ee_cert = load_cert(ee_cert_file, FORMAT_PEM, "end-entity cert");
if (ee_cert == NULL) {
goto end;
}
ee_pkey = load_key(ee_key_file, FORMAT_PEM, 1, NULL, e, "end-entity key");
if (ee_pkey == NULL) {
goto end;
}
dc = DC_new_ex(app_get0_libctx(), app_get0_propq());
if (dc == NULL) {
BIO_printf(bio_err, "failed to new DC\n");
goto end;
}
if (!DC_sign(dc, dc_pkey, valid_time, EVP_MD_type(expect_verify_md),
ee_cert, ee_pkey, sign_md, is_server)) {
BIO_printf(bio_err, "failed to sign DC\n");
goto end;
}
} else {
goto opthelp;
}
if (!noout) {
dc_raw = DC_get0_raw_byte(dc);
dc_raw_len = DC_get_raw_byte_len(dc);
if (dc_raw == NULL || dc_raw_len <= 0) {
BIO_printf(bio_err, "Invalid DC raw\n");
goto end;
}
if (outfile) {
out = BIO_new_file(outfile, "w");
if (out == NULL)
goto end;
} else {
out = dup_bio_out(FORMAT_TEXT);
}
for (i = 0; i < dc_raw_len; i++) {
res = BIO_printf(out, "%02x", dc_raw[i]);
if (res <= 0) {
BIO_printf(bio_out, "output dc error");
goto end;
}
}
}
ret = 0;
end:
if (ret != 0)
ERR_print_errors(bio_err);
EVP_MD_free(expect_verify_md);
EVP_MD_free(sign_md);
release_engine(e);
EVP_PKEY_free(ee_pkey);
X509_free(ee_cert);
EVP_PKEY_free(dc_pkey);
DC_free(dc);
BIO_free(out);
BIO_free(in);
return ret;
}