Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add the "-engineCtrl" option to control hardware and CNG engines #405

Merged
merged 5 commits into from
Sep 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

### 2.10 (unreleased)

- added compatiblity with the CNG engine version 1.1 or later
- added the "-engineCtrl" option to control hardware and CNG engines
- improved unauthenticated blob support (thanks to Asger Hautop Drewsen)
- added the '-blobFile' option to specify a file containing the blob content

Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,29 @@ An example of using osslsigncode with SoftHSM:
-in yourapp.exe -out yourapp-signed.exe
```

You can use a certificate and key stored in the Windows Certificate Store with
the CNG engine version 1.1 or later. For more information, refer to

https://www.stunnel.org/cng-engine.html

A non-commercial edition of CNG engine is available for testing, personal,
educational, or research purposes.

To use the CNG engine with osslsigncode, ensure that the `cng.dll` library is
placed in the same directory as the `osslsigncode.exe` executable.

Below is an example of how to use osslsigncode with the CNG engine:
```
osslsigncode sign \
-pkcs11engine cng \
-pkcs11cert osslsigncode_cert \
-key osslsigncode_cert \
-engineCtrl store_flags:0 \
-engineCtrl store_name:MY \
-engineCtrl PIN:yourpass \
-in yourapp.exe -out yourapp-signed.exe
```

You can check that the signed file is correct by right-clicking
on it in Windows and choose Properties --> Digital Signatures,
and then choose the signature from the list, and click on
Expand Down
50 changes: 50 additions & 0 deletions osslsigncode.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,14 @@ ASN1_SEQUENCE(MsCtlContent) = {

IMPLEMENT_ASN1_FUNCTIONS(MsCtlContent)


ASN1_SEQUENCE(EngineControl) = {
ASN1_SIMPLE(EngineControl, cmd, ASN1_OCTET_STRING),
ASN1_SIMPLE(EngineControl, param, ASN1_OCTET_STRING)
} ASN1_SEQUENCE_END(EngineControl)

IMPLEMENT_ASN1_FUNCTIONS(EngineControl)

/* Prototypes */
static ASN1_INTEGER *create_nonce(int bits);
static char *clrdp_url_get_x509(X509 *cert);
Expand All @@ -224,6 +232,7 @@ static int PKCS7_compare(const PKCS7 *const *a, const PKCS7 *const *b);
static PKCS7 *pkcs7_get_sigfile(FILE_FORMAT_CTX *ctx);
static void print_cert(X509 *cert, int i);
static int x509_store_load_crlfile(X509_STORE *store, char *cafile, char *crlfile);
static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg);


/*
Expand Down Expand Up @@ -3433,6 +3442,7 @@ static void free_options(GLOBAL_OPTIONS *options)
options->xcerts = NULL;
sk_X509_CRL_pop_free(options->crls, X509_CRL_free);
options->crls = NULL;
sk_EngineControl_pop_free(options->engine_ctrls, EngineControl_free);
}

/*
Expand All @@ -3459,6 +3469,7 @@ static void usage(const char *argv0, const char *cmd)
printf("%1s[ sign ] ( -pkcs12 <pkcs12file>\n", "");
printf("%13s | ( -certs <certfile> | -spc <certfile> ) -key <keyfile>\n", "");
printf("%13s | [ -pkcs11engine <engine> ] [ -login ] -pkcs11module <module>\n", "");
printf("%13s | [ -engineCtrl <command[:parameter]> ]\n", "");
printf("%15s ( -pkcs11cert <pkcs11 cert id> | -certs <certfile> ) -key <pkcs11 key id> )\n", "");
#if OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s[ -nolegacy ]\n", "");
Expand Down Expand Up @@ -3596,6 +3607,7 @@ static void help_for(const char *argv0, const char *cmd)
const char *cmds_pkcs11cert[] = {"sign", NULL};
const char *cmds_pkcs11engine[] = {"sign", NULL};
const char *cmds_pkcs11module[] = {"sign", NULL};
const char *cmds_engineCtrl[] = {"sign", NULL};
const char *cmds_login[] = {"sign", NULL};
const char *cmds_pkcs12[] = {"sign", NULL};
const char *cmds_readpass[] = {"sign", NULL};
Expand Down Expand Up @@ -3734,6 +3746,8 @@ static void help_for(const char *argv0, const char *cmd)
printf("%-24s= PKCS#11 engine\n", "-pkcs11engine");
if (on_list(cmd, cmds_pkcs11module))
printf("%-24s= PKCS#11 module\n", "-pkcs11module");
if (on_list(cmd, cmds_engineCtrl))
printf("%-24s= control hardware engine\n", "-engineCtrl");
if (on_list(cmd, cmds_login))
printf("%-24s= force login to the token\n", "-login");
if (on_list(cmd, cmds_pkcs12))
Expand Down Expand Up @@ -4191,6 +4205,8 @@ static ENGINE *engine_pkcs11(void)
*/
static int read_token(GLOBAL_OPTIONS *options, ENGINE *engine)
{
int i;

if (options->p11module && !ENGINE_ctrl_cmd_string(engine, "MODULE_PATH", options->p11module, 0)) {
fprintf(stderr, "Failed to set pkcs11 engine MODULE_PATH to '%s'\n", options->p11module);
ENGINE_free(engine);
Expand All @@ -4211,6 +4227,20 @@ static int read_token(GLOBAL_OPTIONS *options, ENGINE *engine)
ENGINE_free(engine);
return 0; /* FAILED */
}
for (i = 0; i < sk_EngineControl_num(options->engine_ctrls); i++) {
EngineControl *engine_ctrl = sk_EngineControl_value(options->engine_ctrls, i);
const u_char *cmd = ASN1_STRING_get0_data(engine_ctrl->cmd);
const u_char *param = ASN1_STRING_get0_data(engine_ctrl->param);

if (param)
printf("Executing engine control command %s:%s\n", cmd, param);
else
printf("Executing engine control command %s\n", cmd);

if(!ENGINE_ctrl_cmd_string(engine, (const char *)cmd, (const char *)param, 0)) {
fprintf(stderr, "Failed to execute the engine control command\n");
}
}
/*
* ENGINE_init() returned a functional reference, so free the structural
* reference from ENGINE_by_id().
Expand Down Expand Up @@ -4479,6 +4509,7 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
/* Use legacy PKCS#12 container with RC2-40-CBC private key and certificate encryption algorithm */
options->legacy = 1;
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
options->engine_ctrls = sk_EngineControl_new_null();

if (cmd == CMD_HELP) {
return 0; /* FAILED */
Expand Down Expand Up @@ -4553,6 +4584,12 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
return 0; /* FAILED */
}
options->p11module = *(++argv);
} else if (!strcmp(*argv, "-engineCtrl")) {
if (--argc < 1) {
usage(argv0, "all");
return 0; /* FAILED */
}
engine_control_set(options, *(++argv));
} else if ((cmd == CMD_SIGN) && !strcmp(*argv, "-login")) {
options->login = 1;
#endif /* OPENSSL_NO_ENGINE */
Expand Down Expand Up @@ -4860,6 +4897,19 @@ static int main_configure(int argc, char **argv, GLOBAL_OPTIONS *options)
return 1; /* OK */
}

static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg)
{
EngineControl *engine_ctrl = EngineControl_new();
char *tmp_str=strchr(arg, ':');

if(tmp_str) {
*tmp_str++='\0';
ASN1_STRING_set(engine_ctrl->param, tmp_str, (int)strlen(tmp_str));
}
ASN1_STRING_set(engine_ctrl->cmd, arg, (int)strlen(arg));
sk_EngineControl_push(options->engine_ctrls, engine_ctrl);
}

int main(int argc, char **argv)
{
FILE_FORMAT_CTX *ctx = NULL;
Expand Down
9 changes: 9 additions & 0 deletions osslsigncode.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,14 @@ typedef enum {

typedef unsigned char u_char;

typedef struct {
ASN1_OCTET_STRING *cmd;
ASN1_OCTET_STRING *param;
} EngineControl;

DECLARE_ASN1_FUNCTIONS(EngineControl)
DEFINE_STACK_OF(EngineControl)

typedef struct {
char *infile;
char *outfile;
Expand Down Expand Up @@ -307,6 +315,7 @@ typedef struct {
char *tsa_keyfile;
time_t tsa_time;
int nested_number;
STACK_OF(EngineControl) *engine_ctrls;
} GLOBAL_OPTIONS;

/*
Expand Down
Loading