mirror of
https://github.com/mtrojnar/osslsigncode
synced 2026-06-08 16:13:39 +00:00
Compare commits
32 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 97a9ade6ec | |||
| f2f33bb131 | |||
| 202b2c2866 | |||
| 2a5409b7c4 | |||
| 87bce8e372 | |||
| f7ace57c81 | |||
| 92f8761b47 | |||
| 09d3312fd9 | |||
| 9d02a20aec | |||
| f190ec5d87 | |||
| 4b30d6be28 | |||
| fac8164622 | |||
| cbee1e723c | |||
| f90327df09 | |||
| f3a590be69 | |||
| 6631a5f10b | |||
| 9924f0c085 | |||
| 7d85ac5f04 | |||
| feebbcd4d9 | |||
| d787541107 | |||
| 6390ae2746 | |||
| a472d7fbff | |||
| 27172a07ca | |||
| d77ddb9443 | |||
| 988f72249b | |||
| c23f92ca68 | |||
| 842bd94aaf | |||
| 1d72c3da8c | |||
| d792e8d0db | |||
| bbdfc1d98a | |||
| 5ac11e9f58 | |||
| 55541c6ace |
@@ -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>).
|
||||
@@ -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
|
||||
-->
|
||||
@@ -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.
|
||||
@@ -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.
|
||||
-->
|
||||
@@ -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.
|
||||
@@ -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.13
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
||||
|
||||
# configure basic project information
|
||||
project(osslsigncode
|
||||
VERSION 2.10
|
||||
VERSION 2.13
|
||||
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
|
||||
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
||||
LANGUAGES C)
|
||||
|
||||
@@ -1,5 +1,43 @@
|
||||
# osslsigncode change log
|
||||
|
||||
### 2.13 (2026.02.10)
|
||||
|
||||
**MULTIPLE SECURITY VULNERABILITIES**
|
||||
|
||||
This release includes important security fixes. Users are strongly encouraged
|
||||
to upgrade, as the issues below may be exploitable when processing untrusted
|
||||
files.
|
||||
|
||||
- fixed integer overflows when processing APPX compressed data streams
|
||||
(by Małgorzata Olszówka)
|
||||
- fixed double-free vulnerabilities in APPX file processing
|
||||
(by Małgorzata Olszówka)
|
||||
- fixed multiple memory corruption issues in PE page hash computation
|
||||
(by Antoni Klajn (Opera) and Małgorzata Olszówka)
|
||||
|
||||
### 2.12 (2026.02.02)
|
||||
|
||||
**CRITICAL SECURITY VULNERABILITY**
|
||||
|
||||
This release fixes a critical memory corruption vulnerability. A malicious
|
||||
attacker could create a signed file, which, when verified with osslsigncode,
|
||||
triggers arbitrary code execution. Any previous version of osslsigncode should
|
||||
be immediately upgraded if the tool is used for verification of untrusted
|
||||
files.
|
||||
|
||||
- fixed a buffer overflow while extracting message digests
|
||||
(reported and fixed by Antoni Klajn, Opera)
|
||||
|
||||
### 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
|
||||
|
||||
@@ -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
|
||||
```
|
||||
|
||||
|
||||
@@ -1503,6 +1503,7 @@ static int zipAppendSignatureFile(BIO *bio, ZIP_FILE *zip, uint8_t *data, uint64
|
||||
if (!get_current_position(bio, &offset)) {
|
||||
fprintf(stderr, "Unable to get offset\n");
|
||||
OPENSSL_free(header.fileName);
|
||||
header.fileName = NULL;
|
||||
OPENSSL_free(dataToWrite);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
@@ -1513,6 +1514,7 @@ static int zipAppendSignatureFile(BIO *bio, ZIP_FILE *zip, uint8_t *data, uint64
|
||||
if (!BIO_write_ex(bio, dataToWrite + written, toWrite, &check)
|
||||
|| check != toWrite) {
|
||||
OPENSSL_free(header.fileName);
|
||||
header.fileName = NULL;
|
||||
OPENSSL_free(dataToWrite);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
@@ -1685,6 +1687,8 @@ static int zipRewriteData(ZIP_FILE *zip, ZIP_CENTRAL_DIRECTORY_ENTRY *entry, BIO
|
||||
out:
|
||||
OPENSSL_free(header.fileName);
|
||||
OPENSSL_free(header.extraField);
|
||||
header.fileName = NULL;
|
||||
header.extraField = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1852,6 +1856,11 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
|
||||
}
|
||||
if (entry->overrideData) {
|
||||
compressedSize = entry->overrideData->compressedSize;
|
||||
/* Validate sizes for safe allocation */
|
||||
if (compressedSize > (uint64_t)(SIZE_MAX - 1)) {
|
||||
fprintf(stderr, "Corrupted compressedSize : %" PRIu64"\n", compressedSize);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
uncompressedSize = entry->overrideData->uncompressedSize;
|
||||
compressedData = OPENSSL_zalloc(compressedSize + 1);
|
||||
memcpy(compressedData, entry->overrideData->data, compressedSize);
|
||||
@@ -1863,6 +1872,8 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
|
||||
if (!zipReadLocalHeader(&header, zip, compressedSize)) {
|
||||
OPENSSL_free(header.fileName);
|
||||
OPENSSL_free(header.extraField);
|
||||
header.fileName = NULL;
|
||||
header.extraField = NULL;
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
if (header.fileNameLen != entry->fileNameLen
|
||||
@@ -1873,14 +1884,20 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
|
||||
fprintf(stderr, "Local header does not match central directory entry\n");
|
||||
OPENSSL_free(header.fileName);
|
||||
OPENSSL_free(header.extraField);
|
||||
header.fileName = NULL;
|
||||
header.extraField = NULL;
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
/* we don't really need those */
|
||||
OPENSSL_free(header.fileName);
|
||||
OPENSSL_free(header.extraField);
|
||||
header.fileName = NULL;
|
||||
header.extraField = NULL;
|
||||
|
||||
if (compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
||||
fprintf(stderr, "Corrupted compressedSize : 0x%08" PRIX64 "\n", entry->compressedSize);
|
||||
/* Validate sizes for safe allocation */
|
||||
if (compressedSize > (uint64_t)(SIZE_MAX - 1)
|
||||
|| compressedSize > (uint64_t)zip->fileSize - entry->offsetOfLocalHeader) {
|
||||
fprintf(stderr, "Corrupted compressedSize : %" PRIu64"\n", compressedSize);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
compressedData = OPENSSL_zalloc(compressedSize + 1);
|
||||
@@ -1899,11 +1916,24 @@ static size_t zipReadFileData(ZIP_FILE *zip, uint8_t **pData, ZIP_CENTRAL_DIRECT
|
||||
*pData = compressedData;
|
||||
dataSize = compressedSize;
|
||||
} else if (entry->compression == COMPRESSION_DEFLATE) {
|
||||
uint8_t *uncompressedData = OPENSSL_zalloc(uncompressedSize + 1);
|
||||
uint64_t destLen = uncompressedSize;
|
||||
uint64_t sourceLen = compressedSize;
|
||||
uint8_t *uncompressedData;
|
||||
uint64_t destLen, sourceLen;
|
||||
int ret;
|
||||
|
||||
/* Validate sizes for safe allocation */
|
||||
if (uncompressedSize > (uint64_t)(SIZE_MAX - 1)) {
|
||||
fprintf(stderr, "Corrupted uncompressedSize : %" PRIu64"\n", uncompressedSize);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
/* Detect suspicious compression ratio (zip bomb protection) */
|
||||
if (uncompressedSize > 1024 * 1024 && uncompressedSize / 100 >= compressedSize) {
|
||||
fprintf(stderr, "Error: suspicious compression ratio\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
uncompressedData = OPENSSL_zalloc(uncompressedSize + 1);
|
||||
destLen = uncompressedSize;
|
||||
sourceLen = compressedSize;
|
||||
|
||||
ret = zipInflate(uncompressedData, &destLen, compressedData, (uLong *)&sourceLen);
|
||||
OPENSSL_free(compressedData);
|
||||
|
||||
@@ -1970,6 +2000,8 @@ static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t
|
||||
header->extraFieldLen = fileGetU16(file);
|
||||
/* file name (variable size) */
|
||||
if (header->fileNameLen > 0) {
|
||||
/* fileNameLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so fileNameLen + 1 cannot overflow size_t */
|
||||
header->fileName = OPENSSL_zalloc(header->fileNameLen + 1);
|
||||
size = fread(header->fileName, 1, header->fileNameLen, file);
|
||||
if (size != header->fileNameLen) {
|
||||
@@ -1981,6 +2013,8 @@ static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t
|
||||
}
|
||||
/* extra field (variable size) */
|
||||
if (header->extraFieldLen > 0) {
|
||||
/* extraFieldLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so extraFieldLen + 1 cannot overflow size_t */
|
||||
header->extraField = OPENSSL_zalloc(header->extraFieldLen + 1);
|
||||
size = fread(header->extraField, 1, header->extraFieldLen, file);
|
||||
if (size != header->extraFieldLen) {
|
||||
@@ -2011,6 +2045,8 @@ static int zipReadLocalHeader(ZIP_LOCAL_HEADER *header, ZIP_FILE *zip, uint64_t
|
||||
fprintf(stderr, "The input file is not a valid zip file - flags indicate data descriptor, but data descriptor signature does not match\n");
|
||||
OPENSSL_free(header->fileName);
|
||||
OPENSSL_free(header->extraField);
|
||||
header->fileName = NULL;
|
||||
header->extraField = NULL;
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
header->crc32 = fileGetU32(file);
|
||||
@@ -2477,6 +2513,8 @@ static ZIP_CENTRAL_DIRECTORY_ENTRY *zipReadNextCentralDirectoryEntry(FILE *file)
|
||||
entry->offsetOfLocalHeader = fileGetU32(file);
|
||||
/* file name (variable size) */
|
||||
if (entry->fileNameLen > 0) {
|
||||
/* fileNameLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so fileNameLen + 1 cannot overflow size_t */
|
||||
entry->fileName = OPENSSL_zalloc(entry->fileNameLen + 1);
|
||||
size = fread(entry->fileName, 1, entry->fileNameLen, file);
|
||||
if (size != entry->fileNameLen) {
|
||||
@@ -2487,6 +2525,8 @@ static ZIP_CENTRAL_DIRECTORY_ENTRY *zipReadNextCentralDirectoryEntry(FILE *file)
|
||||
}
|
||||
/* extra field (variable size) */
|
||||
if (entry->extraFieldLen > 0) {
|
||||
/* extraFieldLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so extraFieldLen + 1 cannot overflow size_t */
|
||||
entry->extraField = OPENSSL_zalloc(entry->extraFieldLen + 1);
|
||||
size = fread(entry->extraField, 1, entry->extraFieldLen, file);
|
||||
if (size != entry->extraFieldLen) {
|
||||
@@ -2497,6 +2537,8 @@ static ZIP_CENTRAL_DIRECTORY_ENTRY *zipReadNextCentralDirectoryEntry(FILE *file)
|
||||
}
|
||||
/* file comment (variable size) */
|
||||
if (entry->fileCommentLen > 0) {
|
||||
/* fileCommentLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so fileCommentLen + 1 cannot overflow size_t */
|
||||
entry->fileComment = OPENSSL_zalloc(entry->fileCommentLen + 1);
|
||||
size = fread(entry->fileComment, 1, entry->fileCommentLen, file);
|
||||
if (size != entry->fileCommentLen) {
|
||||
@@ -2635,6 +2677,8 @@ static int readZipEOCDR(ZIP_EOCDR *eocdr, FILE *file)
|
||||
}
|
||||
#endif
|
||||
if (eocdr->commentLen > 0) {
|
||||
/* ZIP_EOCDR commentLen is uint16_t (ZIP spec, 2-byte field),
|
||||
* so fileCommentLen + 1 cannot overflow size_t */
|
||||
eocdr->comment = OPENSSL_zalloc(eocdr->commentLen + 1);
|
||||
size = fread(eocdr->comment, 1, eocdr->commentLen, file);
|
||||
if (size != eocdr->commentLen) {
|
||||
@@ -2744,7 +2788,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 */
|
||||
|
||||
@@ -342,9 +342,10 @@ static int cab_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
const u_char *p = content_val->data;
|
||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||
if (idc) {
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
}
|
||||
|
||||
@@ -390,16 +390,12 @@ static int cat_print_content_member_digest(ASN1_TYPE *content)
|
||||
idc = d2i_SpcIndirectDataContent(NULL, &data, ASN1_STRING_length(value));
|
||||
if (!idc)
|
||||
return 0; /* FAILED */
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
/* get a digest algorithm a message digest of the file from the content */
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
if (mdtype == -1) {
|
||||
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
printf("\tHash algorithm: %s\n", OBJ_nid2sn(mdtype));
|
||||
print_hash("\tMessage digest", "", mdbuf, EVP_MD_size(EVP_get_digestbynid(mdtype)));
|
||||
return 1; /* OK */
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+18
-7
@@ -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:
|
||||
|
||||
@@ -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
|
||||
@@ -562,6 +563,37 @@ int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype)
|
||||
return mdok;
|
||||
}
|
||||
|
||||
/*
|
||||
* Safely extract digest from SpcIndirectDataContent with bounds checking.
|
||||
* This function validates that the digest length from the ASN.1 structure
|
||||
* does not exceed the destination buffer size, preventing buffer overflows
|
||||
* from maliciously crafted signatures.
|
||||
* [in] idc: parsed SpcIndirectDataContent structure
|
||||
* [out] mdbuf: output buffer (must be at least EVP_MAX_MD_SIZE bytes)
|
||||
* [out] mdtype: digest algorithm NID
|
||||
* [returns] digest length on success, -1 on error
|
||||
*/
|
||||
int spc_indirect_data_content_get_digest(SpcIndirectDataContent *idc, u_char *mdbuf, int *mdtype)
|
||||
{
|
||||
int digest_len;
|
||||
|
||||
if (!idc || !idc->messageDigest || !idc->messageDigest->digest ||
|
||||
!idc->messageDigest->digestAlgorithm) {
|
||||
return -1; /* FAILED */
|
||||
}
|
||||
digest_len = idc->messageDigest->digest->length;
|
||||
|
||||
/* Validate digest length to prevent buffer overflow */
|
||||
if (digest_len <= 0 || digest_len > EVP_MAX_MD_SIZE) {
|
||||
fprintf(stderr, "Invalid digest length in signature: %d (expected 1-%d)\n",
|
||||
digest_len, EVP_MAX_MD_SIZE);
|
||||
return -1; /* FAILED */
|
||||
}
|
||||
*mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)digest_len);
|
||||
return digest_len; /* OK */
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper functions
|
||||
*/
|
||||
@@ -617,6 +649,10 @@ static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT
|
||||
idc->data->value->type = V_ASN1_SEQUENCE;
|
||||
idc->data->value->value.sequence = ASN1_STRING_new();
|
||||
idc->data->type = ctx->format->data_blob_get(&p, &l, ctx);
|
||||
if (!idc->data->type) {
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
idc->data->value->value.sequence->data = p;
|
||||
idc->data->value->value.sequence->length = l;
|
||||
idc->messageDigest->digestAlgorithm->algorithm = OBJ_nid2obj(mdtype);
|
||||
@@ -763,6 +799,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 +853,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
|
||||
|
||||
@@ -25,6 +25,7 @@ MsCtlContent *ms_ctl_content_get(PKCS7 *p7);
|
||||
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute);
|
||||
SpcLink *spc_link_obsolete_get(void);
|
||||
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype);
|
||||
int spc_indirect_data_content_get_digest(SpcIndirectDataContent *idc, u_char *mdbuf, int *mdtype);
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
|
||||
@@ -419,9 +419,10 @@ static int msi_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
const u_char *p = content_val->data;
|
||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||
if (idc) {
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
}
|
||||
|
||||
+133
-114
@@ -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;
|
||||
}
|
||||
|
||||
@@ -3087,13 +3082,8 @@ static int verify_content_member_digest(FILE_FORMAT_CTX *ctx, ASN1_TYPE *content
|
||||
fprintf(stderr, "Failed to extract SpcIndirectDataContent data\n");
|
||||
return 1; /* FAILED */
|
||||
}
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
/* get a digest algorithm a message digest of the file from the content */
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
}
|
||||
if (mdtype == -1) {
|
||||
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 1; /* FAILED */
|
||||
}
|
||||
@@ -3605,11 +3595,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 +3609,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 +3620,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 +3847,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 +3872,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 +4094,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 +4120,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 +4354,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 +4599,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
|
||||
@@ -5068,7 +5078,7 @@ static void engine_control_set(GLOBAL_OPTIONS *options, const char *arg)
|
||||
}
|
||||
#endif /* OPENSSL_NO_ENGINE */
|
||||
|
||||
int main(int argc, char **argv)
|
||||
static int main_execute(int argc, char **argv)
|
||||
{
|
||||
FILE_FORMAT_CTX *ctx = NULL;
|
||||
GLOBAL_OPTIONS options;
|
||||
@@ -5080,24 +5090,6 @@ int main(int argc, char **argv)
|
||||
/* reset options */
|
||||
memset(&options, 0, sizeof(GLOBAL_OPTIONS));
|
||||
|
||||
/* Set up OpenSSL */
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
| OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CONFIG, NULL))
|
||||
DO_EXIT_0("Failed to init crypto\n");
|
||||
|
||||
/* create some MS Authenticode OIDS we need later on */
|
||||
if (!OBJ_create(SPC_STATEMENT_TYPE_OBJID, NULL, NULL)
|
||||
/* PKCS9_COUNTER_SIGNATURE exists as OpenSSL OBJ_pkcs9_countersignature */
|
||||
|| !OBJ_create(MS_JAVA_SOMETHING, NULL, NULL)
|
||||
|| !OBJ_create(SPC_SP_OPUS_INFO_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_NESTED_SIGNATURE_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_UNAUTHENTICATED_DATA_BLOB_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_RFC3161_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(PKCS9_SEQUENCE_NUMBER, NULL, NULL))
|
||||
DO_EXIT_0("Failed to create objects\n");
|
||||
|
||||
/* commands and options initialization */
|
||||
if (!main_configure(argc, argv, &options))
|
||||
goto err_cleanup;
|
||||
@@ -5122,14 +5114,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)
|
||||
@@ -5347,6 +5337,35 @@ err_cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret = -1;
|
||||
|
||||
/* one-time OpenSSL initialization */
|
||||
if (!OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS
|
||||
| OPENSSL_INIT_ADD_ALL_CIPHERS
|
||||
| OPENSSL_INIT_ADD_ALL_DIGESTS
|
||||
| OPENSSL_INIT_LOAD_CONFIG, NULL))
|
||||
DO_EXIT_0("Failed to init crypto\n");
|
||||
|
||||
/* create some MS Authenticode OIDS we need later on */
|
||||
if (!OBJ_create(SPC_STATEMENT_TYPE_OBJID, NULL, NULL)
|
||||
/* PKCS9_COUNTER_SIGNATURE exists as OpenSSL OBJ_pkcs9_countersignature */
|
||||
|| !OBJ_create(MS_JAVA_SOMETHING, NULL, NULL)
|
||||
|| !OBJ_create(SPC_SP_OPUS_INFO_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_NESTED_SIGNATURE_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_UNAUTHENTICATED_DATA_BLOB_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(SPC_RFC3161_OBJID, NULL, NULL)
|
||||
|| !OBJ_create(PKCS9_SEQUENCE_NUMBER, NULL, NULL))
|
||||
DO_EXIT_0("Failed to create objects\n");
|
||||
|
||||
/* perform the requested operation */
|
||||
ret = main_execute(argc, argv);
|
||||
|
||||
err_cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
Local Variables:
|
||||
c-basic-offset: 4
|
||||
|
||||
@@ -163,8 +163,10 @@ static ASN1_OBJECT *pe_spc_image_data_get(u_char **p, int *plen, FILE_FORMAT_CTX
|
||||
if (EVP_MD_size(ctx->options->md) > EVP_MD_size(EVP_sha1()))
|
||||
phtype = NID_sha256;
|
||||
link = pe_page_hash_link_get(ctx, phtype);
|
||||
if (!link)
|
||||
if (!link) {
|
||||
SpcPeImageData_free(pid);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
pid->file = link;
|
||||
} else {
|
||||
pid->file = spc_link_obsolete_get();
|
||||
@@ -255,9 +257,11 @@ static int pe_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
OPENSSL_free(ph);
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
}
|
||||
@@ -402,6 +406,7 @@ static PKCS7 *pe_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||
content = spc_indirect_data_content_get(hash, ctx);
|
||||
if (!content) {
|
||||
fprintf(stderr, "Failed to get spcIndirectDataContent\n");
|
||||
PKCS7_free(p7);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||
@@ -914,12 +919,25 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
uint16_t nsections, opthdr_size;
|
||||
uint32_t alignment, pagesize, hdrsize;
|
||||
uint32_t rs, ro, l, lastpos = 0;
|
||||
int pphlen, phlen, i, pi = 1;
|
||||
size_t written;
|
||||
u_char *res, *zeroes;
|
||||
int mdlen, pphlen, phlen, i, pi = 1;
|
||||
size_t written, off, sect_off, sect_tbl, need;
|
||||
u_char *res = NULL, *zeroes = NULL;
|
||||
char *sections;
|
||||
const EVP_MD *md = EVP_get_digestbynid(phtype);
|
||||
BIO *bhash;
|
||||
BIO *bhash = NULL;
|
||||
uint32_t filebound;
|
||||
size_t pphlen_sz, sections_factor;
|
||||
|
||||
if (rphlen == NULL || ctx == NULL || ctx->options == NULL || ctx->pe_ctx == NULL
|
||||
|| ctx->options->indata == NULL)
|
||||
return NULL;
|
||||
|
||||
if (md == NULL)
|
||||
return NULL;
|
||||
|
||||
mdlen = EVP_MD_size(md);
|
||||
if (mdlen <= 0)
|
||||
return NULL;
|
||||
|
||||
/* NumberOfSections indicates the size of the section table,
|
||||
* which immediately follows the headers, can be up to 65535 under Vista and later */
|
||||
@@ -961,10 +979,46 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
fprintf(stderr, "Corrupted optional header size: 0x%08X\n", opthdr_size);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
pphlen = 4 + EVP_MD_size(md);
|
||||
phlen = pphlen * (3 + (int)nsections + (int)(ctx->pe_ctx->fileend / pagesize));
|
||||
/* Validate that pagesize >= hdrsize to prevent integer underflow */
|
||||
if (pagesize < hdrsize) {
|
||||
fprintf(stderr, "Page size (0x%08X) is smaller than header size (0x%08X)\n",
|
||||
pagesize, hdrsize);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
pphlen = 4 + mdlen;
|
||||
|
||||
/* Compute an upper bound for result size and guard overflow */
|
||||
pphlen_sz = (size_t)pphlen;
|
||||
sections_factor = 3 + (size_t)nsections + ((size_t)ctx->pe_ctx->fileend / pagesize);
|
||||
if (sections_factor > SIZE_MAX / pphlen_sz) {
|
||||
fprintf(stderr, "Page hash allocation size would overflow\n");
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
phlen = (int)(pphlen_sz * sections_factor);
|
||||
/* Sanity limit - page hash shouldn't exceed reasonable size (16 MB) */
|
||||
if (phlen < 0 || (size_t)phlen > SIZE_16M) {
|
||||
fprintf(stderr, "Page hash size exceeds limit: %d\n", phlen);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
|
||||
/* Determine the file boundary for section data validation */
|
||||
filebound = ctx->pe_ctx->sigpos ? ctx->pe_ctx->sigpos : ctx->pe_ctx->fileend;
|
||||
|
||||
/* Validate section table bounds before reading section headers */
|
||||
sect_off = (size_t)ctx->pe_ctx->header_size + 24u + (size_t)opthdr_size;
|
||||
sect_tbl = (size_t)nsections * 40u;
|
||||
|
||||
if (sect_off > (size_t)filebound || sect_tbl > (size_t)filebound - sect_off) {
|
||||
fprintf(stderr, "Section table out of bounds: off=%zu size=%zu filebound=%u\n",
|
||||
sect_off, sect_tbl, filebound);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
sections = (char *)ctx->options->indata + sect_off;
|
||||
|
||||
bhash = BIO_new(BIO_f_md());
|
||||
if (bhash == NULL)
|
||||
return NULL;
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
@@ -977,7 +1031,10 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
BIO_push(bhash, BIO_new(BIO_s_null()));
|
||||
if (BIO_push(bhash, BIO_new(BIO_s_null())) == NULL) {
|
||||
BIO_free_all(bhash);
|
||||
return NULL;
|
||||
}
|
||||
if (!BIO_write_ex(bhash, ctx->options->indata, ctx->pe_ctx->header_size + 88, &written)
|
||||
|| written != ctx->pe_ctx->header_size + 88) {
|
||||
BIO_free_all(bhash);
|
||||
@@ -989,36 +1046,84 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
BIO_free_all(bhash);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
if (!BIO_write_ex(bhash,
|
||||
ctx->options->indata + ctx->pe_ctx->header_size + 160 + ctx->pe_ctx->pe32plus*16,
|
||||
hdrsize - (ctx->pe_ctx->header_size + 160 + ctx->pe_ctx->pe32plus*16), &written)
|
||||
|| written != hdrsize - (ctx->pe_ctx->header_size + 160 + ctx->pe_ctx->pe32plus*16)) {
|
||||
off = ctx->pe_ctx->header_size + 160 + (size_t)ctx->pe_ctx->pe32plus * 16;
|
||||
if (hdrsize < off || hdrsize > filebound) {
|
||||
BIO_free_all(bhash);
|
||||
return NULL; /* FAILED: header too small */
|
||||
}
|
||||
if (!BIO_write_ex(bhash, ctx->options->indata + off, (size_t)hdrsize - off, &written)
|
||||
|| written != hdrsize - off) {
|
||||
BIO_free_all(bhash);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
if (pagesize < hdrsize) {
|
||||
BIO_free_all(bhash);
|
||||
return NULL; /* FAILED: header larger than page */
|
||||
}
|
||||
zeroes = OPENSSL_zalloc((size_t)pagesize);
|
||||
if (!BIO_write_ex(bhash, zeroes, pagesize - hdrsize, &written)
|
||||
|| written != pagesize - hdrsize) {
|
||||
if (zeroes == NULL) {
|
||||
BIO_free_all(bhash);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
if (!BIO_write_ex(bhash, zeroes, (size_t)pagesize - (size_t)hdrsize, &written)
|
||||
|| written != (size_t)pagesize - (size_t)hdrsize) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
res = OPENSSL_malloc((size_t)phlen);
|
||||
if (res == NULL) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
memset(res, 0, 4);
|
||||
BIO_gets(bhash, (char*)res + 4, EVP_MD_size(md));
|
||||
if (BIO_gets(bhash, (char *)res + 4, mdlen) != mdlen) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
BIO_free_all(bhash);
|
||||
sections = ctx->options->indata + ctx->pe_ctx->header_size + 24 + opthdr_size;
|
||||
for (i=0; i<nsections; i++) {
|
||||
/* Resource Table address and size */
|
||||
bhash = NULL;
|
||||
|
||||
for (i = 0; i < (int)nsections; i++) {
|
||||
/* SizeOfRawData and PointerToRawData from section header */
|
||||
rs = GET_UINT32_LE(sections + 16);
|
||||
ro = GET_UINT32_LE(sections + 20);
|
||||
if (rs == 0 || rs >= UINT32_MAX) {
|
||||
if (rs == 0) {
|
||||
sections += 40;
|
||||
continue;
|
||||
}
|
||||
for (l=0; l<rs; l+=pagesize, pi++) {
|
||||
PUT_UINT32_LE(ro + l, res + pi*pphlen);
|
||||
/* Validate section bounds against file size to prevent OOB read */
|
||||
if (ro >= filebound || rs > filebound - ro) {
|
||||
fprintf(stderr, "Section %d has invalid bounds: offset=0x%08X, size=0x%08X, fileend=0x%08X\n",
|
||||
i, ro, rs, filebound);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
for (l = 0; l < rs; l += pagesize, pi++) {
|
||||
need = (size_t)(pi + 1) * (size_t)pphlen;
|
||||
|
||||
/* Prevent OOB write into res if pi grows beyond allocated factor */
|
||||
if (need > (size_t)phlen) {
|
||||
fprintf(stderr, "Page hash buffer overflow prevented: pi=%d need=%zu phlen=%d\n",
|
||||
pi, need, phlen);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
|
||||
PUT_UINT32_LE(ro + l, res + (size_t)pi * (size_t)pphlen);
|
||||
|
||||
bhash = BIO_new(BIO_f_md());
|
||||
if (bhash == NULL) {
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||
@@ -1033,17 +1138,24 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
#if defined(__GNUC__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
BIO_push(bhash, BIO_new(BIO_s_null()));
|
||||
if (rs - l < pagesize) {
|
||||
if (!BIO_write_ex(bhash, ctx->options->indata + ro + l, rs - l, &written)
|
||||
|| written != rs - l) {
|
||||
if (BIO_push(bhash, BIO_new(BIO_s_null())) == NULL) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL;
|
||||
}
|
||||
if (l < rs && rs - l < pagesize) {
|
||||
size_t tail = (size_t)(rs - l);
|
||||
|
||||
if (!BIO_write_ex(bhash, ctx->options->indata + ro + l, tail, &written)
|
||||
|| written != tail) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
if (!BIO_write_ex(bhash, zeroes, pagesize - (rs - l), &written)
|
||||
|| written != pagesize - (rs - l)) {
|
||||
if (!BIO_write_ex(bhash, zeroes, pagesize - tail, &written)
|
||||
|| written != pagesize - tail) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
@@ -1058,17 +1170,35 @@ static u_char *pe_page_hash_calc(int *rphlen, FILE_FORMAT_CTX *ctx, int phtype)
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
}
|
||||
BIO_gets(bhash, (char*)res + pi*pphlen + 4, EVP_MD_size(md));
|
||||
if (BIO_gets(bhash, (char *)res + (size_t)pi * (size_t)pphlen + 4, mdlen) != mdlen) {
|
||||
BIO_free_all(bhash);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
BIO_free_all(bhash);
|
||||
bhash = NULL;
|
||||
}
|
||||
lastpos = ro + rs;
|
||||
sections += 40;
|
||||
}
|
||||
PUT_UINT32_LE(lastpos, res + pi*pphlen);
|
||||
memset(res + pi*pphlen + 4, 0, (size_t)EVP_MD_size(md));
|
||||
/* Final entry */
|
||||
need = (size_t)(pi + 1) * (size_t)pphlen;
|
||||
|
||||
if (need > (size_t)phlen) {
|
||||
fprintf(stderr, "Page hash buffer overflow prevented at final entry: pi=%d need=%zu phlen=%d\n",
|
||||
pi, need, phlen);
|
||||
OPENSSL_free(zeroes);
|
||||
OPENSSL_free(res);
|
||||
return NULL; /* FAILED */
|
||||
}
|
||||
|
||||
PUT_UINT32_LE(lastpos, res + (size_t)pi * (size_t)pphlen);
|
||||
memset(res + (size_t)pi * (size_t)pphlen + 4, 0, (size_t)mdlen);
|
||||
pi++;
|
||||
|
||||
OPENSSL_free(zeroes);
|
||||
*rphlen = pi*pphlen;
|
||||
*rphlen = pi * pphlen;
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -1088,6 +1218,10 @@ static int pe_verify_page_hash(FILE_FORMAT_CTX *ctx, u_char *ph, int phlen, int
|
||||
if (!ph)
|
||||
return 1; /* OK */
|
||||
cph = pe_page_hash_calc(&cphlen, ctx, phtype);
|
||||
if (!cph) {
|
||||
fprintf(stderr, "Page hash verification failed: could not calculate page hash\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
mdok = (phlen == cphlen) && !memcmp(ph, cph, (size_t)phlen);
|
||||
printf("Page hash algorithm : %s\n", OBJ_nid2sn(phtype));
|
||||
if (ctx->options->verbose) {
|
||||
@@ -1190,7 +1324,8 @@ static int pe_check_file(FILE_FORMAT_CTX *ctx)
|
||||
{
|
||||
uint32_t real_pe_checksum, sum = 0;
|
||||
|
||||
if (!ctx) {
|
||||
if (ctx == NULL || ctx->pe_ctx == NULL || ctx->options == NULL
|
||||
|| ctx->options->indata == NULL) {
|
||||
fprintf(stderr, "Init error\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
@@ -1202,25 +1337,52 @@ static int pe_check_file(FILE_FORMAT_CTX *ctx)
|
||||
printf("Calculated PE checksum: %08X\n", real_pe_checksum);
|
||||
printf("Warning: invalid PE checksum\n");
|
||||
}
|
||||
/* Signature directory bounds */
|
||||
if (ctx->pe_ctx->sigpos == 0 || ctx->pe_ctx->siglen == 0
|
||||
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend) {
|
||||
|| ctx->pe_ctx->sigpos > ctx->pe_ctx->fileend
|
||||
|| ctx->pe_ctx->siglen > ctx->pe_ctx->fileend - ctx->pe_ctx->sigpos) {
|
||||
fprintf(stderr, "No signature found\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
/*
|
||||
* Validate WIN_CERTIFICATE chain.
|
||||
* If the sum of the rounded dwLength values does not equal the Size value,
|
||||
* then either the attribute certificate table or the Size field is corrupted.
|
||||
*/
|
||||
while (sum < ctx->pe_ctx->siglen) {
|
||||
uint32_t len = GET_UINT32_LE(ctx->options->indata + ctx->pe_ctx->sigpos + sum);
|
||||
if (ctx->pe_ctx->siglen - len > 8) {
|
||||
uint32_t len, off;
|
||||
|
||||
/* Prevent overflow in sigpos + sum */
|
||||
if (sum > UINT32_MAX - ctx->pe_ctx->sigpos) {
|
||||
fprintf(stderr, "Corrupted attribute certificate table\n");
|
||||
fprintf(stderr, "Attribute certificate table size : %08X\n", ctx->pe_ctx->siglen);
|
||||
fprintf(stderr, "Attribute certificate entry length: %08X\n\n", len);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
/* quadword align data */
|
||||
len += len % 8 ? 8 - len % 8 : 0;
|
||||
off = ctx->pe_ctx->sigpos + sum;
|
||||
|
||||
/* Need at least 4 bytes to read dwLength */
|
||||
if (off > ctx->pe_ctx->fileend || ctx->pe_ctx->fileend - off < 4) {
|
||||
fprintf(stderr, "Corrupted attribute certificate table\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
len = GET_UINT32_LE(ctx->options->indata + off);
|
||||
|
||||
/* dwLength must include the 8-byte WIN_CERTIFICATE header */
|
||||
if (len < 8 || len > ctx->pe_ctx->siglen - sum || len > ctx->pe_ctx->fileend - off) {
|
||||
fprintf(stderr, "Corrupted attribute certificate table\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
|
||||
/* Quadword align data */
|
||||
if (len % 8) {
|
||||
uint32_t pad = 8 - (len % 8);
|
||||
|
||||
/* Ensure quadword alignment does not overflow or exceed remaining table size */
|
||||
if (pad > ctx->pe_ctx->siglen - sum - len) {
|
||||
fprintf(stderr, "Corrupted attribute certificate table\n");
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
len += pad;
|
||||
}
|
||||
sum += len;
|
||||
}
|
||||
if (sum != ctx->pe_ctx->siglen) {
|
||||
|
||||
@@ -294,9 +294,10 @@ static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||
const u_char *p = content_val->data;
|
||||
SpcIndirectDataContent *idc = d2i_SpcIndirectDataContent(NULL, &p, content_val->length);
|
||||
if (idc) {
|
||||
if (idc->messageDigest && idc->messageDigest->digest && idc->messageDigest->digestAlgorithm) {
|
||||
mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||
memcpy(mdbuf, idc->messageDigest->digest->data, (size_t)idc->messageDigest->digest->length);
|
||||
if (spc_indirect_data_content_get_digest(idc, mdbuf, &mdtype) < 0) {
|
||||
fprintf(stderr, "Failed to extract message digest from signature\n\n");
|
||||
SpcIndirectDataContent_free(idc);
|
||||
return 0; /* FAILED */
|
||||
}
|
||||
SpcIndirectDataContent_free(idc);
|
||||
}
|
||||
|
||||
@@ -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())
|
||||
|
||||
Reference in New Issue
Block a user