18 Commits

Author SHA1 Message Date
Michał Trojnara f3a590be69 Release 2.11
Signed-off-by: Michał Trojnara <Michal.Trojnara@stunnel.org>
2026-01-20 23:53:33 +01:00
Michał Trojnara 6631a5f10b Update trusted certificate list 2026-01-20 23:21:33 +01:00
Michał Trojnara 9924f0c085 Minor style improvements
- Reorder checks by corresponding RFC 5280 section numbers.
- Simplify comments.
2026-01-20 23:21:33 +01:00
olszomal 7d85ac5f04 Add GitHub issue and PR templates 2026-01-09 14:41:02 +01:00
olszomal feebbcd4d9 Print current CRL during certificate verification 2026-01-07 13:36:43 +01:00
olszomal d787541107 tests: add digitalSignature keyUsage to leaf certificate 2025-12-31 11:38:21 +01:00
olszomal 6390ae2746 Add keyUsage digitalSignature validation for signer certificate 2025-12-31 11:38:21 +01:00
Michał Trojnara a472d7fbff Comment returned CRL Content-Type 2025-12-22 19:26:21 +01:00
Chris Thibodeaux 27172a07ca Patch CRL fetch failure from expected file type
`application/octet-stream` response types caused CRL/TSA-CRL fetch failures
2025-12-22 19:22:01 +01:00
olszomal d77ddb9443 Disable keep-alive and remove the shutdown workaround.
Some RFC 3161 TSA servers (e.g. time.certum.pl) advertise
"Connection: close" but delay closing the connection,
when keep-alive was requested. The client waited for EOF and
attempted to work around this by explicitly shutting down the socket.
2025-12-19 15:11:12 +01:00
olszomal 988f72249b Simplify ASLR/PIE flags check for macOS 2025-12-16 06:42:01 +01:00
olszomal c23f92ca68 Improve PKCS#11 and CNG usage instructions in README 2025-09-22 11:16:29 +02:00
olszomal 842bd94aaf Remove duplicate certs from sorted X509 chain 2025-09-19 17:02:21 +02:00
olszomal 1d72c3da8c Improve key/cert loading logic and standardize usage file argument names 2025-09-19 17:02:21 +02:00
olszomal d792e8d0db Use bio_new_file() wrapper instead of BIO_new_file() for consistent file handling 2025-09-19 17:01:02 +02:00
olszomal bbdfc1d98a Avoid undefined behavior with BIO_get_fp by replacing BIO_new_file with fopen + BIO_new_fp 2025-09-19 17:01:02 +02:00
olszomal 5ac11e9f58 Fix -Wsign-conversion warning in x509_name_to_utf8() 2025-07-01 12:21:44 +02:00
Michał Trojnara 55541c6ace Initial 2.11-dev commit 2025-06-23 21:42:26 +02:00
18 changed files with 1855 additions and 761 deletions
+8
View File
@@ -0,0 +1,8 @@
<!--
Please use one of the available issue templates.
Bug reports without required information may be closed.
-->
If you are reporting a bug or crash, please use the appropriate issue template.
For questions or support, use please use [Discussions](<https://github.com/mtrojnar/osslsigncode/discussions>).
+74
View File
@@ -0,0 +1,74 @@
---
name: Crash report
about: Report a segmentation fault or other crash
labels: crash
---
<!--
Thank you for your crash report.
Note: Please search to see if an issue already exists for the bug you encountered.
-->
### Segmentation Fault / Crash Details
<!--
Provide exact, reproducible steps.
Include the complete command, exactly as executed.
-->
- Signal / exit code: <!-- SIGSEGV, SIGABRT -->
- Reproducibility: <!-- always / sometimes / once -->
- Affected command or operation: <!-- e.g. `osslsigncode sign`, `osslsigncode verify` -->
- First observed version:
- Last known working version (if any):
#### Backtrace
<!--
Provide a backtrace from gdb or lldb.
Build with debug symbols if possible. Use `bt full` if possible.
Crash reports without a backtrace may be closed without investigation.
-->
- `(gdb) bt`
#### Memory / Sanitizers
<!--
Attach relevant output if available.
-->
- [ ] Valgrind
- [ ] ASan / UBSan
- [ ] Other tools
#### Crash Context
<!--
Anything that may be relevant:
- OpenSSL provider / engine in use
- PKCS#11 modules
- Custom OpenSSL configuration
- Threading or concurrency
-->
### Environment
- Operating system and version (e.g. Ubuntu 24.04):
- Architecture (x86_64, arm64, etc.):
### Versions
<!--
Please verify that the issue is reproducible with the current upstream master.
-->
- osslsigncode built from:
- [ ] upstream master
- [ ] upstream release (tag):
- [ ] distribution package (name and version):
- `openssl version -a`
- `osslsigncode --version`
### Configuration / Settings
<!--
Anything that could affect signing or verification:
- Custom OpenSSL configuration
- Engine / provider settings
- Environment variables (OPENSSL_CONF, etc.)
-->
### Anything else
<!--
Links, references, related issues, workarounds or additional observations.
-->
@@ -0,0 +1,26 @@
---
name: Documentation
about: Report an error in (or missing) documentation
labels: documentation
---
<!--
Thank you for taking the time to report a documentation issue.
-->
### Documentation Location
<!--
Where is the problem located?
Provide a link, file path, or section name.
-->
### Issue Description
<!--
Describe what is wrong or missing.
-->
### Suggested Improvement (optional)
<!--
If you know how it should be fixed, describe it here.
Proposed wording or examples are especially helpful.
-->
@@ -0,0 +1,30 @@
---
name: Feature request
about: Suggest a new feature or improvement
labels: feature
---
<!--
Thank you for your feature request.
Please describe the use case and motivation as clearly as possible.
-->
### Use Case / Motivation
<!--
What problem are you trying to solve?
Why is this feature needed?
-->
### Proposed Change
<!--
Describe the feature or improvement you are proposing.
High-level description is sufficient.
-->
### Additional Notes (optional)
<!--
Anything else that may help:
- examples
- references
- related issues
-->
+17
View File
@@ -0,0 +1,17 @@
---
name: Questions / Support
about: Please use Q&A in Discussions instead
labels: question
---
### Questions and Support
Please do **not** use GitHub issues for general questions or support requests.
For:
- usage questions
- "how do I..." questions
please use [Q&A category in Discussions](<https://github.com/mtrojnar/osslsigncode/discussions/new?category=q-a>)
Bug reports and crashes should be reported using the appropriate issue templates.
+77
View File
@@ -0,0 +1,77 @@
---
name: Other bug report
about: Report a bug
labels: bug
---
<!--
Thank you for your bug report.
Note: Please search to see if an issue already exists for the bug you encountered.
-->
### Current Behavior
<!--
A concise description of what is happening.
Include error messages or incorrect results.
-->
### Expected Behavior
<!--
A concise description of what you expected to happen instead.
-->
### Steps To Reproduce & Observed Output
<!--
Provide exact, reproducible steps together with full stdout/stderr for each.
-->
1. Signing with osslsigncode
<!--
Full `osslsigncode sign` command and complete stdout/stderr output.
-->
2. Verification with osslsigncode
<!--
Full `osslsigncode verify` command and complete stdout/stderr output.
-->
3. Signing / verification with Windows signtool (if applicable)
<!--
Full signtool command (`signtool verify /pa /v`) and complete stdout/stderr output.
-->
### Environment
- Operating system and version (e.g. Ubuntu 24.04):
- Architecture (x86_64, arm64, etc.):
### Versions
<!--
Please verify that the issue is reproducible with the current upstream master.
-->
- osslsigncode built from:
- [ ] upstream master
- [ ] upstream release (tag):
- [ ] distribution package (name and version):
- `openssl version -a`
- `osslsigncode --version`
### Files
<!--
Attach files if possible, or mention that you will share them privately.
-->
- [ ] unsigned file
- [ ] file signed with osslsigncode
- [ ] file signed with signtool or the other tool (for comparison)
- [ ] certificate chain used for verification (PEM format)
### Configuration / Settings
<!--
Anything that could affect signing or verification:
- Custom OpenSSL configuration
- Engine / provider settings
- Environment variables (OPENSSL_CONF, etc.)
-->
### Anything else
<!--
Links, references, related issues, workarounds or additional observations.
-->
+65
View File
@@ -0,0 +1,65 @@
<!--
Thank you for your pull request.
Provide a concise summary of the changes in the PR title.
-->
### Pull Request Type
<!--
Limit this PR to a single type. If necessary, split changes into multiple PRs.
-->
- [ ] Bug fix
- [ ] New feature
- [ ] Code style / formatting / renaming
- [ ] Refactoring (no functional or API changes)
- [ ] Build / CI related changes
- [ ] Documentation
- [ ] Other (please describe):
### Related Issue
<!--
If this fixes a GitHub issue, make sure to have a line saying 'Fixes #XXXX' (without quotes) in the commit message.
-->
Issue number: N/A
### Current Behavior
<!--
Describe the current behavior or limitation this PR addresses.
Include error messages or crash symptoms if relevant.
-->
### New Behavior
<!--
Describe the new or changed behavior introduced by this PR.
-->
### Scope of Changes
<!--
Briefly describe what was changed and why.
Focus on relevant parts only.
-->
### Testing
<!--
Describe how the changes were tested.
Include commands, environments, or platforms if relevant.
-->
- [ ] Existing tests
- [ ] New tests added
- [ ] Manual testing
### Additional Notes
<!--
Any additional information relevant for reviewers:
- design decisions
- backward compatibility
- known limitations
-->
## License Declaration
<!--
All contributions to this project are licensed under the project's license.
By submitting this pull request, you confirm that you have the right to submit
the code and agree to license it accordingly.
-->
- [ ] I hereby agree to license my contribution under the project's license.
+1 -1
View File
@@ -7,7 +7,7 @@ on:
env:
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
BUILD_TYPE: Release
version: osslsigncode-2.10
version: osslsigncode-2.11
jobs:
build:
+1 -1
View File
@@ -10,7 +10,7 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
# configure basic project information
project(osslsigncode
VERSION 2.10
VERSION 2.11
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
LANGUAGES C)
+10
View File
@@ -1,5 +1,15 @@
# osslsigncode change log
### 2.11 (2026.01.20)
- added keyUsage validation for signer certificate
(thanks to Hanqing Zhao and Zi-Quan You for reporting the issue)
- added printing CRL details during signature verification
- implemented a workaround for CRL servers returning the HTTP Content-Type
header other than application/pkix-crl (thanks to Chris Thibodeaux)
- fixed HTTP keep-alive handling
- fixed macOS compiler and linker flags
- fixed undefined BIO_get_fp() behavior with BIO_FLAGS_UPLINK_INTERNAL
### 2.10 (2025.06.23)
- added JavaScript signing
+33 -16
View File
@@ -133,8 +133,9 @@ To sign a CAB file containing Java class files:
```
Only the 'low' parameter is currently supported.
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:
### Using the PKCS#11 Engine with osslsigncode
If you want to use a PKCS#11 token, specify the PKCS#11 engine and module.
Example usage with SoftHSM:
```
osslsigncode sign \
-engine /usr/lib64/engines-1.1/pkcs11.so \
@@ -144,8 +145,10 @@ An example of using osslsigncode with SoftHSM:
-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:
### Using the PKCS#11 Provider with osslsigncode (OpenSSL 3.x only)
OpenSSL 3.0 introduced a new provider-based architecture. To use a PKCS#11 token
with `osslsigncode`, specify the PKCS#11 provider and module.
Example usage with OpenSC:
```
osslsigncode sign \
-provider /usr/lib64/ossl-modules/pkcs11prov.so \
@@ -155,26 +158,40 @@ An example of using osslsigncode with OpenSC:
-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
### Using the CNG Engine with osslsigncode (Windows only)
The CNG engine allows using certificates and keys stored in the Windows
Certificate Store. It requires 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.
To ensure `osslsigncode` can locate and load the CNG engine module (`cng.dll`)
even when it is not installed in the default system engine directory, you can:
Below is an example of how to use osslsigncode with the CNG engine:
- Specify the full or relative path to `cng.dll`:
```
osslsigncode sign \
-engine cng \
-pkcs11cert osslsigncode_cert \
-key osslsigncode_cert \
-engineCtrl store_flags:0 \
-engineCtrl store_name:MY \
-engineCtrl PIN:yourpass \
osslsigncode sign -engine C:\my\engines\cng.dll ...
```
- Or set the `OPENSSL_ENGINES` environment variable to the directory containing
`cng.dll`, and refer to the engine by its ID:
```
set OPENSSL_ENGINES=C:\my\engines
osslsigncode sign -engine cng ...
```
Below is an example of how to use `osslsigncode` with the CNG engine on Windows:
```
set OPENSSL_ENGINES=C:\my\engines
osslsigncode sign ^
-engine 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
```
+4 -1
View File
@@ -2744,7 +2744,10 @@ static int get_current_position(BIO *bio, uint64_t *offset)
FILE *file = NULL;
int64_t pos;
BIO_get_fp(bio, &file);
if (BIO_get_fp(bio, &file) != 1 || file == NULL) {
fprintf(stderr, "BIO_get_fp() failed\n");
return 0; /* FAILED */
}
pos = ftello(file);
if (pos < 0) {
return 0; /* FAILED */
+4 -9
View File
@@ -96,16 +96,11 @@ function(add_compile_flags target)
message(WARNING "No stack protection supported")
endif(HAVE_STACK_PROTECTOR)
endif(HAVE_STACK_PROTECTOR_ALL)
# Support address space layout randomization (ASLR)
if(NOT (MINGW OR CYGWIN OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
OR ((CMAKE_SYSTEM_NAME MATCHES Darwin) AND (CMAKE_C_COMPILER_ID MATCHES Clang))))
# Support address space layout randomization (ASLR) / PIE
if(UNIX AND NOT APPLE)
target_compile_options(${target} PRIVATE -fPIE)
target_link_options(${target} PRIVATE -fPIE -pie)
target_link_options(${target} PRIVATE -Wl,-z,relro)
target_link_options(${target} PRIVATE -Wl,-z,now)
target_link_options(${target} PRIVATE -Wl,-z,noexecstack)
endif(NOT (MINGW OR CYGWIN OR CMAKE_C_COMPILER_ID STREQUAL "AppleClang"
OR ((CMAKE_SYSTEM_NAME MATCHES Darwin) AND (CMAKE_C_COMPILER_ID MATCHES Clang))))
target_link_options(${target} PRIVATE -fPIE -pie -Wl,-z,relro,-z,now,-z,noexecstack)
endif(UNIX AND NOT APPLE)
target_link_options(${target} PRIVATE -fstack-check)
add_compile_flag_to_targets(${target})
endif(MSVC)
+1341 -638
View File
File diff suppressed because it is too large Load Diff
+18 -7
View File
@@ -10,6 +10,7 @@ from csv import reader
from requests import get
from requests.exceptions import RequestException
from concurrent.futures import ThreadPoolExecutor
from re import search
def download_cert(hash):
for attempt in range(10):
@@ -17,23 +18,33 @@ def download_cert(hash):
sleep(10)
try:
creds = f'{attempt}{hash}:{attempt}{hash}'
resp = get(f'https://crt.sh/?d={hash}',
proxies=dict(https=f'socks5://{creds}@127.0.0.1:9050'))
proxies = dict(https=f'socks5://{creds}@127.0.0.1:9050')
url = f'https://crt.sh/?sha1={hash}&match=='
resp = get(url, proxies=proxies)
resp.raise_for_status()
m = search(r'\bid=(\d+)\b', resp.content.decode('ascii', 'replace'))
id = m.group(1)
url = f'https://crt.sh/?d={id}'
resp = get(url, proxies=proxies)
resp.raise_for_status()
print('.', file=stderr, end='')
stderr.flush()
return resp.content.decode('utf-8')
except RequestException as e:
print(f'\nAttempt {attempt}: {e}', file=stderr)
return resp.content.decode('utf-8', 'replace')
except Exception as e:
print(f'\n{url} attempt {attempt}: {e}', file=stderr)
print('\nGiving up on', hash, file=stderr)
resp = get('https://ccadb-public.secure.force.com/microsoft/IncludedCACertificateReportForMSFTCSV')
resp = get('https://ccadb.my.salesforce-sites.com/microsoft/IncludedCACertificateReportForMSFTCSV')
resp.raise_for_status()
lines = resp.content.decode('utf-8').splitlines()[1:]
hashes = [row[4] for row in reader(lines)
if row[0] != 'Disabled'
or row[4] == 'F38406E540D7A9D90CB4A9479299640FFB6DF9E224ECC7A01C0D9558D8DAD77D']
with ThreadPoolExecutor(max_workers=20) as executor:
with ThreadPoolExecutor(max_workers=10) as executor:
certs = executor.map(download_cert, hashes)
for cert in certs:
if cert is not None:
+33
View File
@@ -17,6 +17,7 @@ static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer);
static int X509_compare(const X509 *const *a, const X509 *const *b);
static void sk_X509_remove_duplicates(STACK_OF(X509) *chain);
/*
* Common functions
@@ -763,6 +764,9 @@ static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
}
/* sort certificate chain using the supplied comparison function */
sk_X509_sort(chain);
/* remove duplicates */
sk_X509_remove_duplicates(chain);
return chain;
}
@@ -814,6 +818,35 @@ static int X509_compare(const X509 *const *a, const X509 *const *b)
return ret;
}
/*
* Remove duplicate certificates from a sorted STACK_OF(X509).
*
* This function assumes the stack is sorted according to X.690-compliant
* certificate comparison, so duplicate certificates appear consecutively.
* It iterates through the stack and removes any duplicate certificates
* by comparing each element with its immediate predecessor.
* The stack is modified in place.
*/
static void sk_X509_remove_duplicates(STACK_OF(X509) *chain)
{
int i, n = sk_X509_num(chain);
if (n < 2)
return;
/* start from the second element */
for (i = 1; i < n; ) {
if (!X509_cmp(sk_X509_value(chain, i - 1), sk_X509_value(chain, i))) {
/* duplicate found: remove the certificate at index i */
(void)sk_X509_delete(chain, i);
n--; /* reduce stack size since one element was removed */
/* do not increment i, as next element shifts into index i */
} else {
i++; /* advance only if no removal was done */
}
}
}
/*
Local Variables:
c-basic-offset: 4
+101 -88
View File
@@ -244,6 +244,7 @@ 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 load_objects_from_store(const char *url, char *pass, EVP_PKEY **pkey, STACK_OF(X509) *certs, STACK_OF(X509_CRL) *crls);
static BIO *bio_new_file(const char *filename, const char *mode);
#ifndef OPENSSL_NO_ENGINE
static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg);
#endif /* OPENSSL_NO_ENGINE */
@@ -797,63 +798,37 @@ static int verify_callback(int ok, X509_STORE_CTX *ctx)
/*
* Read data from socket BIO
* [in] s_bio: socket BIO
* [in] rctx: open connection context
* [in] use_ssl: HTTPS request switch
* [returns] memory BIO
*/
static BIO *socket_bio_read(BIO *s_bio, OSSL_HTTP_REQ_CTX *rctx, int use_ssl)
static BIO *socket_bio_read(BIO *s_bio)
{
int retry = 1, ok = 0, written = 0, resp_len = 0;
int retry = 1, ok = 0;
char *buf = OPENSSL_malloc(OSSL_HTTP_DEFAULT_MAX_RESP_LEN);
BIO *resp = BIO_new(BIO_s_mem());
if (rctx) {
resp_len = (int)OSSL_HTTP_REQ_CTX_get_resp_len(rctx);
}
if (resp_len == 0) {
if (use_ssl)
BIO_ssl_shutdown(s_bio);
else {
int fd = (int)BIO_get_fd(s_bio, NULL);
if (fd >= 0) {
#ifdef WIN32
(void)shutdown(fd, SD_SEND);
#else /* WIN32 */
(void)shutdown(fd, SHUT_WR);
#endif /* WIN32 */
}
}
}
ERR_clear_error();
while (retry) {
int n;
errno = 0;
n = BIO_read(s_bio, buf, OSSL_HTTP_DEFAULT_MAX_RESP_LEN);
if (n > 0) {
written += BIO_write(resp, buf, n);
(void)BIO_write(resp, buf, n);
} else if (BIO_eof(s_bio) == 1) {
ok = 1;
retry = 0; /* EOF */
retry = 0; /* HTTP EOF */
} else if (BIO_should_retry(s_bio)) {
} else {
unsigned long err = ERR_get_error();
if (err == 0) {
ok = 1;
retry = 0; /* use_ssl EOF */
retry = 0; /* HTTPS EOF */
} else {
fprintf(stderr, "\nHTTP failure: error %ld: %s\n", err, ERR_reason_error_string(err));
retry = 0; /* FAILED */
}
}
if (resp_len > 0 && resp_len == written) {
ok = 1;
retry = 0; /* all response has been read */
}
}
OSSL_HTTP_close(rctx, ok);
OPENSSL_free(buf);
if (!ok) {
BIO_free_all(resp);
@@ -915,12 +890,10 @@ static void check_authenticode_timestamp(BIO **resp)
static BIO *bio_get_http(char *url, BIO *req, char *proxy, int rfc3161, char *cafile, char *crlfile)
{
BIO *tmp_bio = NULL, *s_bio = NULL, *resp = NULL;
OSSL_HTTP_REQ_CTX *rctx = NULL;
HTTP_TLS_Info info;
SSL_CTX *ssl_ctx = NULL;
char *server = NULL, *port = NULL, *path = NULL;
int timeout = -1; /* blocking mode, exactly one try, see BIO_do_connect_retry() */
int keep_alive = 1; /* prefer */
int use_ssl = 0;
if (!url) {
@@ -956,10 +929,16 @@ static BIO *bio_get_http(char *url, BIO *req, char *proxy, int rfc3161, char *ca
info.ssl_ctx = ssl_ctx;
if (!req) { /* GET */
const char *expected_content_type = "application/pkix-crl";
/*
* HTTP server implementations accessed via the URI SHOULD specify the
* media type application/pkix-crl in the Content-Type header field of
* the response (RFC 5280, section 4.2.1.13).
* In practice, some CRL distribution points return "application/octet-stream"
* instead. Therefore, do not enforce the Content-Type and rely on the CRL
* parser to validate the response content.
*/
s_bio = OSSL_HTTP_get(url, proxy, NULL, NULL, NULL, http_tls_cb, &info, 0,
NULL, expected_content_type, 0, 0, timeout);
NULL, NULL, 0, 0, timeout);
} else { /* POST */
const char *content_type = "application/timestamp-query"; /* RFC3161 Timestamp */
const char *expected_content_type = "application/timestamp-reply";
@@ -974,9 +953,9 @@ static BIO *bio_get_http(char *url, BIO *req, char *proxy, int rfc3161, char *ca
content_type = "application/octet-stream"; /* Authenticode Timestamp */
expected_content_type = "application/octet-stream";
}
s_bio = OSSL_HTTP_transfer(&rctx, server, port, path, use_ssl, proxy, NULL,
s_bio = OSSL_HTTP_transfer(NULL, server, port, path, use_ssl, proxy, NULL,
NULL, NULL, http_tls_cb, &info, 0, NULL, content_type, req,
expected_content_type, 0, 0, timeout, keep_alive);
expected_content_type, 0, 0, timeout, 0);
BIO_free(tmp_bio);
}
OPENSSL_free(server);
@@ -985,7 +964,7 @@ static BIO *bio_get_http(char *url, BIO *req, char *proxy, int rfc3161, char *ca
SSL_CTX_free(ssl_ctx);
if (s_bio) {
resp = socket_bio_read(s_bio, rctx, use_ssl);
resp = socket_bio_read(s_bio);
BIO_free_all(s_bio);
if (resp && req && !rfc3161)
check_authenticode_timestamp(&resp);
@@ -1277,7 +1256,7 @@ static int add_timestamp_builtin(PKCS7 *p7, FILE_FORMAT_CTX *ctx)
TS_RESP *response = NULL;
int i, res = 1;
btmp = BIO_new_file(ctx->options->tsa_certfile, "rb");
btmp = bio_new_file(ctx->options->tsa_certfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read Time-Stamp Authority certificate file: %s\n", ctx->options->tsa_certfile);
return 0; /* FAILED */
@@ -1285,7 +1264,7 @@ static int add_timestamp_builtin(PKCS7 *p7, FILE_FORMAT_CTX *ctx)
/* .pem certificate file */
chain = X509_chain_read_certs(btmp, NULL);
BIO_free(btmp);
btmp = BIO_new_file(ctx->options->tsa_keyfile, "rb");
btmp = bio_new_file(ctx->options->tsa_keyfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read private key file: %s\n", ctx->options->tsa_keyfile);
return 0; /* FAILED */
@@ -1766,7 +1745,7 @@ static char *x509_name_to_utf8(const X509_NAME *name)
flags = XN_FLAG_RFC2253 | ASN1_STRFLGS_UTF8_CONVERT |
ASN1_STRFLGS_ESC_CTRL;
flags &= ~ASN1_STRFLGS_ESC_MSB;
flags &= ~(unsigned long)ASN1_STRFLGS_ESC_MSB;
bio = BIO_new(BIO_s_mem());
if (!bio)
@@ -1922,11 +1901,22 @@ static int verify_ca_callback(int ok, X509_STORE_CTX *ctx)
static int verify_crl_callback(int ok, X509_STORE_CTX *ctx)
{
X509_CRL *crl;
int error = X509_STORE_CTX_get_error(ctx);
int depth = X509_STORE_CTX_get_error_depth(ctx);
X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
print_cert(current_cert, depth);
crl = X509_STORE_CTX_get0_current_crl(ctx);
if (crl) {
BIO *bio = BIO_new_fp(stdout, BIO_NOCLOSE);
X509_CRL_print(bio, crl);
BIO_free(bio);
printf("\n");
}
if (!ok) {
if (trusted_cert(current_cert, error)) {
return 1;
@@ -2534,9 +2524,14 @@ static int verify_authenticode(FILE_FORMAT_CTX *ctx, PKCS7 *p7, time_t time, X50
if (!crlok)
goto out;
}
/* check extended key usage flag XKU_CODE_SIGN */
/* keyUsage, if present, must permit digitalSignature (RFC 5280 section 4.2.1.3) */
if (!(X509_get_key_usage(signer) & X509v3_KU_DIGITAL_SIGNATURE)) {
fprintf(stderr, "Signer certificate rejected: keyUsage does not permit digitalSignature\n");
goto out;
}
/* extendedKeyUsage, if present, must permit codeSigning (RFC 5280 section 4.2.1.12) */
if (!(X509_get_extended_key_usage(signer) & XKU_CODE_SIGN)) {
fprintf(stderr, "Unsupported Signer's certificate purpose XKU_CODE_SIGN\n");
fprintf(stderr, "Signer certificate rejected: extendedKeyUsage does not permit codeSigning\n");
goto out;
}
@@ -3605,11 +3600,11 @@ static void usage(const char *argv0, const char *cmd)
printf("%1s[ --help ]\n\n", "");
}
if (on_list(cmd, cmds_sign)) {
printf("%1s[ sign ] -pkcs12 <pkcs12file> | ( [ -certs <certfile> | -spc <certfile> ]\n", "");
printf("%1s[ sign ] -pkcs12 <file> | ( [ -certs <file|URI> | -spc <file> ]\n", "");
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s( -key <keyfile> | ( -key <pkcs11 key URI> -pkcs11module <module> [ -pkcs11cert <pkcs11 cert URI> ] )\n", "");
printf("%12s( -key <file|URI> [ -pkcs11module <module> ] [ -pkcs11cert <pkcs11 cert URI> ] )\n", "");
#else /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
printf("%12s-key <keyfile> )\n", "");
printf("%12s-key <file|URI> )\n", "");
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s[ -provider <provider> | ", "");
@@ -3619,7 +3614,7 @@ static void usage(const char *argv0, const char *cmd)
#endif /* OPENSSL_NO_ENGINE */
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
#ifndef OPENSSL_NO_ENGINE
printf("%s( -engine <engine> [ -login ] [ -engineCtrl <command[:parameter]> ] ) ] ) )\n", "");
printf("%s( -engine <engine> [ -login ] [ -engineCtrl <command[:parameter]> ] ) ] )\n", "");
#endif /* OPENSSL_NO_ENGINE */
#if OPENSSL_VERSION_NUMBER>=0x30000000L
printf("%12s[ -nolegacy ]\n", "");
@@ -3630,73 +3625,73 @@ static void usage(const char *argv0, const char *cmd)
#endif /* PROVIDE_ASKPASS */
printf("%1s[ -readpass <file> ]\n", "");
printf("%12s(use \"-\" with readpass to read from stdin)\n", "");
printf("%12s[ -ac <crosscertfile> ]\n", "");
printf("%12s[ -ac <file> ]\n", "");
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
printf("%12s[ -n <desc> ] [ -i <url> ] [ -jp <level> ] [ -comm ]\n", "");
printf("%12s[ -ph ]\n", "");
printf("%12s[ -t <timestampurl> [ -t ... ] [ -p <proxy> ] [ -noverifypeer ]\n", "");
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
printf("%12s[ -TSA-certs <file> ] [ -TSA-key <file> ]\n", "");
printf("%12s[ -TSA-time <unix-time> ]\n", "");
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CAfile <file> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <file> ]\n", "");
printf("%12s[ -time <unix-time> ]\n", "");
printf("%12s[ -addUnauthenticatedBlob [ -blobFile <blobfile> ] ]\n", "");
printf("%12s[ -addUnauthenticatedBlob [ -blobFile <file> ] ]\n", "");
printf("%12s[ -nest ]\n", "");
printf("%12s[ -verbose ]\n", "");
printf("%12s[ -add-msi-dse ]\n", "");
printf("%12s[ -pem ]\n", "");
printf("%12s[ -in ] <infile> [-out ] <outfile>\n\n", "");
printf("%12s[ -in ] <file> [-out ] <file>\n\n", "");
}
if (on_list(cmd, cmds_extract_data)) {
printf("%1sextract-data [ -pem ]\n", "");
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
printf("%12s[ -ph ]\n", "");
printf("%12s[ -add-msi-dse ]\n", "");
printf("%12s[ -in ] <infile> [ -out ] <datafile>\n\n", "");
printf("%12s[ -in ] <file> [ -out ] <file>\n\n", "");
}
if (on_list(cmd, cmds_add)) {
printf("%1sadd [ -addUnauthenticatedBlob [ -blobFile <blobfile> ] ]\n", "");
printf("%1sadd [ -addUnauthenticatedBlob [ -blobFile <file> ] ]\n", "");
printf("%12s[ -t <timestampurl> [ -t ... ] [ -p <proxy> ] [ -noverifypeer ]\n", "");
printf("%12s[ -ts <timestampurl> [ -ts ... ] [ -p <proxy> ] [ -noverifypeer ] ]\n", "");
printf("%12s[ -TSA-certs <TSA-certfile> ] [ -TSA-key <TSA-keyfile> ]\n", "");
printf("%12s[ -TSA-certs <file> ] [ -TSA-key <file> ]\n", "");
printf("%12s[ -TSA-time <unix-time> ]\n", "");
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CAfile <file> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <file> ]\n", "");
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
printf("%12s[ -index <index> ]\n", "");
printf("%12s[ -verbose ]\n", "");
printf("%12s[ -add-msi-dse ]\n", "");
printf("%12s[ -in ] <infile> [ -out ] <outfile>\n\n", "");
printf("%12s[ -in ] <file> [ -out ] <file>\n\n", "");
}
if (on_list(cmd, cmds_attach)) {
printf("%1sattach-signature [ -sigin ] <sigfile>\n", "");
printf("%12s[ -CAfile <infile> ]\n", "");
printf("%12s[ -CRLfile <infile> ]\n", "");
printf("%12s[ -TSA-CAfile <infile> ]\n", "");
printf("%12s[ -TSA-CRLfile <infile> ]\n", "");
printf("%1sattach-signature [ -sigin ] <file>\n", "");
printf("%12s[ -CAfile <file> ]\n", "");
printf("%12s[ -CRLfile <file> ]\n", "");
printf("%12s[ -TSA-CAfile <file> ]\n", "");
printf("%12s[ -TSA-CRLfile <file> ]\n", "");
printf("%12s[ -time <unix-time> ]\n", "");
printf("%12s[ -h {md5,sha1,sha2(56),sha384,sha512} ]\n", "");
printf("%12s[ -require-leaf-hash {md5,sha1,sha2(56),sha384,sha512}:XXXXXXXXXXXX... ]\n", "");
printf("%12s[ -nest ]\n", "");
printf("%12s[ -add-msi-dse ]\n", "");
printf("%12s[ -in ] <infile> [ -out ] <outfile>\n\n", "");
printf("%12s[ -in ] <file> [ -out ] <file>\n\n", "");
}
if (on_list(cmd, cmds_extract)) {
printf("%1sextract-signature [ -pem ]\n", "");
printf("%12s[ -in ] <infile> [ -out ] <sigfile>\n\n", "");
printf("%12s[ -in ] <file> [ -out ] <file>\n\n", "");
}
if (on_list(cmd, cmds_remove))
printf("%1sremove-signature [ -in ] <infile> [ -out ] <outfile>\n\n", "");
printf("%1sremove-signature [ -in ] <file> [ -out ] <file>\n\n", "");
if (on_list(cmd, cmds_verify)) {
printf("%1sverify [ -in ] <infile>\n", "");
printf("%12s[ -c | -catalog <infile> ]\n", "");
printf("%12s[ -CAfile <infile> ]\n", "");
printf("%12s[ -CRLfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CAfile <infile> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <infile> ]\n", "");
printf("%12s[ -TSA-CAfile <infile> ]\n", "");
printf("%12s[ -TSA-CRLfile <infile> ]\n", "");
printf("%1sverify [ -in ] <file>\n", "");
printf("%12s[ -c | -catalog <file> ]\n", "");
printf("%12s[ -CAfile <file> ]\n", "");
printf("%12s[ -CRLfile <file> ]\n", "");
printf("%12s[ -HTTPS-CAfile <file> ]\n", "");
printf("%12s[ -HTTPS-CRLfile <file> ]\n", "");
printf("%12s[ -TSA-CAfile <file> ]\n", "");
printf("%12s[ -TSA-CRLfile <file> ]\n", "");
printf("%12s[ -p <proxy> ]\n", "");
printf("%12s[ -index <index> ]\n", "");
printf("%12s[ -ignore-timestamp ]\n", "");
@@ -3857,7 +3852,7 @@ static void help_for(const char *argv0, const char *cmd)
if (on_list(cmd, cmds_CAfile))
printf("%-24s= the file containing one or more trusted certificates in PEM format\n", "-CAfile");
if (on_list(cmd, cmds_certs))
printf("%-24s= the signing certificate to use\n", "-certs, -spc");
printf("%-24s= certificate chain (signing cert + intermediates)\n", "-certs, -spc");
if (on_list(cmd, cmds_comm))
printf("%-24s= set commercial purpose (default: individual purpose)\n", "-comm");
if (on_list(cmd, cmds_CRLfile))
@@ -3882,7 +3877,7 @@ static void help_for(const char *argv0, const char *cmd)
printf("%-24s= disable legacy mode and don't automatically load the legacy provider\n", "-nolegacy");
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
if (on_list(cmd, cmds_key))
printf("%-24s= the private key to use or PKCS#11 URI identifies a key in the token\n", "-key");
printf("%-24s= private key (optionally with signing cert) from file or URI\n", "-key");
if (on_list(cmd, cmds_n))
printf("%-24s= specifies a description of the signed content\n", "-n");
if (on_list(cmd, cmds_nest))
@@ -4104,7 +4099,7 @@ err:
*/
static int read_der_keyfile(GLOBAL_OPTIONS *options)
{
BIO *btmp = BIO_new_file(options->keyfile, "rb");
BIO *btmp = bio_new_file(options->keyfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read private key file: %s\n", options->keyfile);
@@ -4130,7 +4125,7 @@ static int read_der_keyfile(GLOBAL_OPTIONS *options)
static int read_pkcs7_certfile(GLOBAL_OPTIONS *options)
{
PKCS7 *p7;
BIO *btmp = BIO_new_file(options->certfile, "rb");
BIO *btmp = bio_new_file(options->certfile, "rb");
if (!btmp) {
fprintf(stderr, "Failed to read certificate from: %s\n",
@@ -4364,8 +4359,8 @@ static int read_crypto_params(GLOBAL_OPTIONS *options)
(void)provider_load(options->provider);
}
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
/* Load the private key ('-key' option) */
load_objects_from_store(options->keyfile, options->pass, &options->pkey, NULL, NULL);
/* Load the private key and the signing certificate ('-key' option) */
load_objects_from_store(options->keyfile, options->pass, &options->pkey, options->certs, NULL);
}
#if OPENSSL_VERSION_NUMBER<0x1010108f
/* Workaround for OpenSSL 1.1.1g and older, where the store API does not
@@ -4609,6 +4604,26 @@ static int file_exists(const char *filename)
return 0; /* File does not exist */
}
static BIO *bio_new_file(const char *filename, const char *mode)
{
FILE *file;
BIO *bio;
if (!filename)
return NULL;
file = fopen(filename, mode);
if (!file)
return NULL;
bio = BIO_new_fp(file, BIO_CLOSE);
if (!bio) {
fclose(file);
return NULL;
}
return bio;
}
/*
* [in] argc, argv
* [in, out] options: structure holds the input data
@@ -5122,14 +5137,12 @@ int main(int argc, char **argv)
#if defined(__GNUC__)
#pragma GCC diagnostic pop
#endif
/* Create outdata file */
outdata = BIO_new_file(options.outfile, "w+bx");
if (!outdata && errno != EEXIST)
outdata = BIO_new_file(options.outfile, "w+b");
/* Create output file — file existence already verified via file_exists() */
outdata = bio_new_file(options.outfile, "w+b");
if (!outdata) {
BIO_free_all(hash);
DO_EXIT_1("Failed to create file: %s\n", options.outfile);
}
}
}
ctx = file_format_script.ctx_new(&options, hash, outdata);
if (!ctx)
+12
View File
@@ -338,6 +338,17 @@ class LeafCertificate(X509Extensions):
authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
)
key_usage = KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=False,
data_encipherment=False,
key_agreement=False,
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
decipher_only=False
)
extended_key_usage = ExtendedKeyUsage(
[ExtendedKeyUsageOID.CODE_SIGNING]
)
@@ -352,6 +363,7 @@ class LeafCertificate(X509Extensions):
.add_extension(BasicConstraints(ca=False, path_length=None), critical=False)
.add_extension(SubjectKeyIdentifier.from_public_key(public_key), critical=False)
.add_extension(authority_key, critical=False)
.add_extension(key_usage, critical=False)
.add_extension(extended_key_usage, critical=False)
.add_extension(self.create_x509_crldp(), critical=False)
.sign(self.issuer_key, SHA256())