Skip to content
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
7 changes: 7 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,15 @@ set(PACKAGE_BUGREPORT "Michal.Trojnara@stunnel.org")
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

if(WIN32)
add_definitions(-DUSE_WIN32)
endif()

# load CMake library modules
include(FindOpenSSL)
if(OPENSSL_VERSION VERSION_LESS "1.1.1")
message(FATAL_ERROR "OpenSSL version must be at least 1.1.1")
endif()
if(OPENSSL_VERSION VERSION_LESS "3.0.0")
include(FindCURL)
endif(OPENSSL_VERSION VERSION_LESS "3.0.0")
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- 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
- added PKCS#11 provider support (requires OpenSSL 3.0)

### 2.9 (2024.06.29)

Expand Down
17 changes: 14 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -131,17 +131,28 @@ To sign a CAB file containing java class files:
```
Only the 'low' parameter is currently supported.

If you want to use PKCS11 token, you should indicate PKCS11 engine and module.
If you want to use a PKCS#11 token, you should specify the PKCS#11 engine and module.
An example of using osslsigncode with SoftHSM:
```
osslsigncode sign \
-pkcs11engine /usr/lib64/engines-1.1/pkcs11.so \
-engine /usr/lib64/engines-1.1/pkcs11.so \
-pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \
-pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \
-key 'pkcs11:token=softhsm-token;object=key' \
-in yourapp.exe -out yourapp-signed.exe
```

Since OpenSSL 3.0, you can use a PKCS#11 token with the PKCS#11 provider.
An example of using osslsigncode with OpenSC:
```
osslsigncode sign \
-provider /usr/lib64/ossl-modules/pkcs11prov.so \
-pkcs11module /usr/lib64/opensc-pkcs11.so \
-pkcs11cert 'pkcs11:token=my-token;object=cert' \
-key 'pkcs11:token=my-token;object=key' \
-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

Expand All @@ -156,7 +167,7 @@ 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 \
-engine cng \
-pkcs11cert osslsigncode_cert \
-key osslsigncode_cert \
-engineCtrl store_flags:0 \
Expand Down
80 changes: 39 additions & 41 deletions helpers.c
Original file line number Diff line number Diff line change
Expand Up @@ -165,73 +165,76 @@ int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
{
int i, signer = -1;
PKCS7 *p7;
PKCS7_SIGNER_INFO *si = NULL;
STACK_OF(X509) *chain = NULL;
PKCS7 *p7 = PKCS7_new();

if (!p7)
return NULL;

p7 = PKCS7_new();
PKCS7_set_type(p7, NID_pkcs7_signed);
PKCS7_content_new(p7, NID_pkcs7_data);
if (ctx->options->cert != NULL) {
/*
* the private key and corresponding certificate are parsed from the PKCS12
* structure or loaded from the security token, so we may omit to check
* the consistency of a private key with the public key in an X509 certificate
*/
si = PKCS7_add_signature(p7, ctx->options->cert, ctx->options->pkey,
ctx->options->md);
if (si == NULL)
return NULL; /* FAILED */
} else {
/* find the signer's certificate located somewhere in the whole certificate chain */
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
X509 *signcert = sk_X509_value(ctx->options->certs, i);
if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
signer = i;
break;
}
}
if (si == NULL) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
ctx->options->certfile);
return NULL; /* FAILED */

/* find the signer's certificate located somewhere in the whole certificate chain */
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
X509 *signcert = sk_X509_value(ctx->options->certs, i);

if (X509_check_private_key(signcert, ctx->options->pkey)) {
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
signer = i;
if (signer > 0)
printf("Warning: For optimal performance, consider placing the signer certificate at the beginning of the certificate chain.\n");
break;
}
}
if (!si) {
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
ctx->options->keyfile);
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
ctx->options->certfile ? ctx->options->certfile : ctx->options->p11cert);
#else
ctx->options->certfile);
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
goto err;
}

if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
return NULL; /* FAILED */
goto err;
}
if (!pkcs7_signer_info_add_purpose(si, ctx)) {
return NULL; /* FAILED */
goto err;
}
if ((ctx->options->desc || ctx->options->url) &&
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
fprintf(stderr, "Couldn't allocate memory for opus info\n");
return NULL; /* FAILED */
goto err;
}
if ((ctx->options->nested_number >= 0) &&
!pkcs7_signer_info_add_sequence_number(si, ctx)) {
return NULL; /* FAILED */
goto err;
}
/* create X509 chain sorted in ascending order by their DER encoding */
chain = X509_chain_get_sorted(ctx, signer);
if (chain == NULL) {
if (!chain) {
fprintf(stderr, "Failed to create a sorted certificate chain\n");
return NULL; /* FAILED */
goto err;
}
/* add sorted certificate chain */
for (i=0; i<sk_X509_num(chain); i++) {
PKCS7_add_certificate(p7, sk_X509_value(chain, i));
(void)PKCS7_add_certificate(p7, sk_X509_value(chain, i));
}
/* add crls */
if (ctx->options->crls) {
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
(void)PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
}
sk_X509_free(chain);
return p7; /* OK */

err:
PKCS7_free(p7);
return NULL; /* FAILED */
}

/*
Expand Down Expand Up @@ -732,11 +735,6 @@ static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
int i;
STACK_OF(X509) *chain = sk_X509_new(X509_compare);

/* add the signer's certificate */
if (ctx->options->cert != NULL && !sk_X509_push(chain, ctx->options->cert)) {
sk_X509_free(chain);
return NULL;
}
if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) {
sk_X509_free(chain);
return NULL;
Expand Down
Loading