mirror of
https://github.com/mtrojnar/osslsigncode
synced 2026-06-08 16:13:39 +00:00
Compare commits
347 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bf209e0fc8 | |||
| 68a6826cd1 | |||
| ea5d15862d | |||
| bdde95635f | |||
| d0ef178a9a | |||
| e126ab3e4a | |||
| a1fb6600fb | |||
| 8227c68ceb | |||
| c988b48063 | |||
| 6cf70b4af2 | |||
| 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 | |||
| 8329a14f8b | |||
| 343b0af1fe | |||
| d440f32780 | |||
| fb082942d2 | |||
| 025e808c01 | |||
| 23b6d7782c | |||
| 4c3a1e887c | |||
| 97ee163e31 | |||
| dfc3e46a77 | |||
| ff9a6d3593 | |||
| e81b08e02d | |||
| 0c85d54800 | |||
| 772bc22c94 | |||
| d65a2b5286 | |||
| a3fcf41e1a | |||
| e00caac3db | |||
| dd9b81281f | |||
| 6b56aef073 | |||
| 52bfff5756 | |||
| 4d52e9cc4b | |||
| 3292b02650 | |||
| 50c23daa4c | |||
| 9b7dae4572 | |||
| 62438908cb | |||
| 829e770250 | |||
| a6c7c25dae | |||
| 10ca3a06ea | |||
| 9ea7e85468 | |||
| 68e8845ef1 | |||
| 475ea95ba3 | |||
| d352dcc1a5 | |||
| 7734382436 | |||
| d425d8bf25 | |||
| 4568c890cc | |||
| 4bd167a8be | |||
| e7405fa839 | |||
| 776e2ec7b6 | |||
| 838aaaee8d | |||
| e8f19a6efe | |||
| 3a8e25e5bb | |||
| 7d1b460dfe | |||
| bc3e9e2172 | |||
| 21bce757ef | |||
| 6a43f62835 | |||
| 8780e6f8e4 | |||
| 78a23caa54 | |||
| d92927aff4 | |||
| 4f412b5989 | |||
| e6f3ff631d | |||
| 09135aabb8 | |||
| de983e680f | |||
| dc827b94e5 | |||
| 40ce811701 | |||
| db5b4c4dc0 | |||
| 4ee429792d | |||
| 27686c0b0c | |||
| 21133f9c3b | |||
| 64305d6415 | |||
| 4dd836bab1 | |||
| f57c213207 | |||
| 76ee550c9d | |||
| 2b3228d549 | |||
| bad6e96e0f | |||
| 3c8c74a8c3 | |||
| 771014a41e | |||
| 476168e09e | |||
| be4f010535 | |||
| 2c27e2e37d | |||
| b829e7a802 | |||
| d0ae214cb4 | |||
| 9b1a6c9fb8 | |||
| 41b662a8fe | |||
| 5232734071 | |||
| 996cf20fa9 | |||
| 825c9dad7c | |||
| 6e5bef14e9 | |||
| a53bd2bdb3 | |||
| e4d471b885 | |||
| bcb9737dda | |||
| 7a5389b719 | |||
| d9f0a8dade | |||
| aa8c8dd720 | |||
| 16c5e5aa4a | |||
| ded1f7aa67 | |||
| 6ad2679f17 | |||
| 4776f43f04 | |||
| d9db038c65 | |||
| e8ef027776 | |||
| 0a0761746f | |||
| f51e2a4869 | |||
| 093ed12c66 | |||
| 71a046a2d0 | |||
| c73f82b558 | |||
| b294f5d18f | |||
| e07bb7d6b2 | |||
| 699bc85d0a | |||
| 192e7a732b | |||
| 656051676f | |||
| 3998bcabb2 | |||
| fa40c57f80 | |||
| 0b93a94ffa | |||
| 105fd3af4a | |||
| 86a594b087 | |||
| 1dea73b038 | |||
| b661ed08ed | |||
| ead0584611 | |||
| bd7751147e | |||
| 1bc7fc36b8 | |||
| 42e9733916 | |||
| b2024cee9d | |||
| 9d152b8477 | |||
| 7a02d51a83 | |||
| dac68a3a4d | |||
| bd1ab77f44 | |||
| 5ee859db2c | |||
| ee3c51f6d5 | |||
| cedb8b5798 | |||
| dcf58a00e7 | |||
| 4576895718 | |||
| 1bdcad619e | |||
| 31b046cf98 | |||
| f3ac2c0c6f | |||
| f22c83514c | |||
| 44ca1f38e6 | |||
| 0985c47990 | |||
| aa158e40ec | |||
| 5da62de5ef | |||
| 4d08fbb2c1 | |||
| 98b004edda | |||
| 34bf3bc525 | |||
| 64e1bba96b | |||
| 46bcaa9d88 | |||
| 867e0d446d | |||
| 7285778cb0 | |||
| c909ba82d7 | |||
| 7b60d6447d | |||
| 588a1a0b5f | |||
| 8a9b275494 | |||
| 0db17be606 | |||
| f9ad19d4a2 | |||
| b9ca24d423 | |||
| 8d2b562244 | |||
| 6f4e9ab597 | |||
| 6d6270094e | |||
| 57563716d1 | |||
| 8ab8a133f7 | |||
| ef5047038e | |||
| e290e03341 | |||
| 900ffed596 | |||
| 33253afb5e | |||
| 3aba55e5e0 | |||
| 898a53b2a7 | |||
| 75ce1dadf5 | |||
| 4166476030 | |||
| a5690f2d19 | |||
| cdb75578e9 | |||
| e2ab4a152d | |||
| b8e690f3bd | |||
| c89d6b43aa | |||
| 9faed39931 | |||
| ecb17709fc | |||
| 9ebd79ad18 | |||
| 1700455533 | |||
| a6f767f5a3 | |||
| 4c5b329bc4 | |||
| 5626482e82 | |||
| 2d21a2121c | |||
| 5d2bf2c80f | |||
| 5b8376ce32 | |||
| 1fc2c937f2 | |||
| 2ed54490a6 | |||
| a096aa8a33 | |||
| aa08566a63 | |||
| c04b229ce2 | |||
| adcfd9a33f | |||
| f2f3a8891c | |||
| 29eedf9059 | |||
| d6f94d71f7 | |||
| a509a66c65 | |||
| 7bf4c92d83 | |||
| 0a0fdfe96a | |||
| 199f2b4586 | |||
| a92c4a5522 | |||
| dc44ed5f5b | |||
| c6990878c2 | |||
| abbbfabdc7 | |||
| 2a4b75842a | |||
| 56e7a72e8a | |||
| b61bcaac2e | |||
| 924af9e783 | |||
| cb80c7d188 | |||
| 76bb06bf7e | |||
| 4b6027a4f7 | |||
| de6a65cc67 | |||
| c90166ba8d | |||
| b00ceee310 | |||
| 54e61cb76a | |||
| fb731f2b5e | |||
| eec5a0755d | |||
| 41d98c3917 | |||
| 7fa0b21ddd | |||
| e0eb331baf | |||
| 7bb21c3539 | |||
| edcb18d63f | |||
| 3d7b8d2a21 | |||
| 7bfe3b5db9 | |||
| dd365d68c4 | |||
| 09555e8c05 | |||
| e4aa06f0c0 | |||
| 46e9ee447f | |||
| 3e7247d9dc | |||
| d2f1b9c035 | |||
| 4199310cdf | |||
| 0204d04a25 | |||
| 246f0abbfc | |||
| 0f51a06b8f | |||
| 44a6768089 | |||
| 93f5f800d6 | |||
| 4db6ed0cad | |||
| 32b65659be | |||
| 8e74a05b40 | |||
| 83e47e0252 | |||
| 41e6042c26 | |||
| 33c1fdaa85 | |||
| 11eb76d4f3 | |||
| b0391244a6 | |||
| 83f6ceeaea | |||
| b96a7a2232 | |||
| ff8034af2e | |||
| bde67ec1e2 | |||
| c5ad70d31a | |||
| 27a2a2bfa3 | |||
| 827f167f8b | |||
| 4098a5efc7 | |||
| e88bc1ca14 | |||
| dd2aaf0804 | |||
| 08113a08cb | |||
| 29843ccf40 | |||
| 5fef4faf47 | |||
| 5981c740c9 | |||
| f3af509973 | |||
| c29e14e697 | |||
| 4da5526c05 | |||
| 4ec23dbaa5 | |||
| d9979c4bc6 | |||
| 695892b8bf | |||
| 192ff59916 | |||
| 506daf84ac | |||
| bb6322e378 | |||
| b0eaa96d45 | |||
| fade782e58 | |||
| 199a852c12 | |||
| 95a8a9d9c1 | |||
| c197d7727c | |||
| efbe570f27 | |||
| fef65536f6 | |||
| 1155a9c338 | |||
| f67ca8aac5 | |||
| d59601f2b9 | |||
| 7f87f930f7 | |||
| dadca2516d | |||
| a862378280 | |||
| c4ec6debe5 | |||
| 08c205a02f | |||
| acfece2c26 | |||
| 61cf89f26f | |||
| 07a927f34a | |||
| 257cb1fb08 | |||
| c48a6cdef0 | |||
| 8bba4496c0 | |||
| dfc13c9bf8 | |||
| f57b469c29 | |||
| c718882ffb | |||
| 3109bdf0ab | |||
| 7aca21b481 | |||
| 8c113b3a86 | |||
| f3a5ecce9c | |||
| 1c678bf926 | |||
| 454e15326d | |||
| db556d0a2d | |||
| 8bdd22c183 | |||
| cc4e5a5076 | |||
| b8cb44fa47 | |||
| 36cdea56de | |||
| 77e63fa0cb | |||
| 225ce9bbd6 | |||
| a5011a00c5 | |||
| f9006f099a | |||
| b9664394a5 | |||
| 68c4163332 | |||
| c143eff68f | |||
| cbdbd9dbd0 | |||
| 20bfc0ffeb | |||
| 8e075d625d | |||
| 4eeaee4c16 | |||
| 6da29943ea | |||
| 431d6ab1bd | |||
| 5d51f0e2c7 | |||
| 4d476213d4 | |||
| 21c196342f | |||
| b8d83bb15e | |||
| abf5aa68f8 | |||
| 762dd8a21b | |||
| 86e4eb9252 | |||
| 7510e3c553 |
@@ -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.
|
||||||
+157
-57
@@ -1,4 +1,4 @@
|
|||||||
name: CI
|
name: Continuous Integration
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
@@ -7,6 +7,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||||
BUILD_TYPE: Release
|
BUILD_TYPE: Release
|
||||||
|
version: osslsigncode-2.14-dev
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
@@ -14,88 +15,173 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
- triplet: x64-linux
|
- id: ubuntu-24.04
|
||||||
os: ubuntu-latest
|
triplet: x64-linux
|
||||||
vcpkg_root: /usr/local/share/vcpkg
|
compiler: gcc
|
||||||
- triplet: x64-osx
|
os: ubuntu-24.04
|
||||||
|
generator: Unix Makefiles
|
||||||
|
vcpkg_root:
|
||||||
|
- id: ubuntu-22.04
|
||||||
|
triplet: x64-linux
|
||||||
|
compiler: gcc
|
||||||
|
os: ubuntu-22.04
|
||||||
|
generator: Unix Makefiles
|
||||||
|
vcpkg_root:
|
||||||
|
- id: macOS
|
||||||
|
triplet: arm64-osx
|
||||||
|
compiler: clang
|
||||||
os: macOS-latest
|
os: macOS-latest
|
||||||
|
generator: Unix Makefiles
|
||||||
vcpkg_root: /usr/local/share/vcpkg
|
vcpkg_root: /usr/local/share/vcpkg
|
||||||
cache: /Users/runner/.cache/vcpkg/archives
|
cache: /Users/runner/.cache/vcpkg/archives
|
||||||
- triplet: x64-windows
|
- id: windows-x64-vs
|
||||||
|
triplet: x64-windows
|
||||||
|
compiler: vs
|
||||||
arch: x64
|
arch: x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
- triplet: x86-windows
|
- id: windows-x86-vs
|
||||||
|
triplet: x86-windows
|
||||||
|
compiler: vs
|
||||||
arch: x86
|
arch: x86
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
- triplet: x64-windows-static
|
- id: windows-x64-static-vs
|
||||||
|
triplet: x64-windows-static
|
||||||
|
compiler: vs
|
||||||
arch: x64
|
arch: x64
|
||||||
os: windows-latest
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
|
vcpkg_root: C:/vcpkg
|
||||||
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
|
- id: windows-x64-mingw
|
||||||
|
triplet: x64-windows
|
||||||
|
compiler: mingw
|
||||||
|
os: windows-latest
|
||||||
|
generator: Ninja
|
||||||
vcpkg_root: C:/vcpkg
|
vcpkg_root: C:/vcpkg
|
||||||
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
cache: C:/Users/runneradmin/AppData/Local/vcpkg/archives
|
||||||
|
|
||||||
runs-on: ${{matrix.os}}
|
runs-on: ${{matrix.os}}
|
||||||
|
|
||||||
|
env:
|
||||||
|
VCPKG_ROOT: ${{matrix.vcpkg_root}}
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cache the vcpkg archives
|
- name: Cache the vcpkg archives
|
||||||
if: matrix.os != 'ubuntu-latest'
|
if: matrix.cache != ''
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ${{matrix.cache}}
|
path: ${{matrix.cache}}
|
||||||
key: ${{matrix.triplet}}-${{hashFiles('vcpkg.json')}}
|
key: ${{matrix.id}}-${{hashFiles('vcpkg.json')}}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{matrix.triplet}}-${{hashFiles('vcpkg.json')}}
|
${{matrix.id}}-${{hashFiles('vcpkg.json')}}
|
||||||
${{matrix.triplet}}-
|
${{matrix.id}}-
|
||||||
|
|
||||||
- name: Configure VS Toolchain (Windows)
|
- name: Configure Visual Studio
|
||||||
if: matrix.os == 'windows-latest'
|
if: matrix.compiler == 'vs'
|
||||||
uses: ilammy/msvc-dev-cmd@v1
|
uses: ilammy/msvc-dev-cmd@v1
|
||||||
with:
|
with:
|
||||||
arch: ${{matrix.arch}}
|
arch: ${{matrix.arch}}
|
||||||
|
|
||||||
- name: Install apt dependencies (Linux)
|
- name: Install MSYS2
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: matrix.compiler == 'mingw'
|
||||||
run: sudo apt-get install -y libssl-dev libcurl4-openssl-dev faketime
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
update: true
|
||||||
|
install: mingw-w64-x86_64-ninja
|
||||||
|
|
||||||
|
- name: Put MSYS2_MinGW64 on PATH
|
||||||
|
if: matrix.compiler == 'mingw'
|
||||||
|
run: echo "D:/a/_temp/msys64/mingw64/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||||
|
|
||||||
|
- name: Set up Python (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: actions/setup-python@v4
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
update-environment: false
|
||||||
|
architecture: 'arm64'
|
||||||
|
|
||||||
|
- name: Set up Python virtual environment (Linux/macOS)
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
run: |
|
||||||
|
python -m venv --system-site-packages --copies venv
|
||||||
|
|
||||||
|
- name: Set up Python virtual environment (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
python.exe -m venv --system-site-packages --copies venv
|
||||||
|
|
||||||
|
- name: Install Xcode (macOS)
|
||||||
|
if: runner.os == 'macOS'
|
||||||
|
uses: maxim-lobanov/setup-xcode@v1
|
||||||
|
with:
|
||||||
|
xcode-version: latest-stable
|
||||||
|
|
||||||
- name: Setup the oldest supported version of cmake (macOS)
|
- name: Setup the oldest supported version of cmake (macOS)
|
||||||
if: matrix.os == 'macOS-latest'
|
if: runner.os == 'macOS'
|
||||||
uses: jwlawson/actions-setup-cmake@v1.12
|
uses: jwlawson/actions-setup-cmake@v2.0
|
||||||
with:
|
|
||||||
cmake-version: '3.17.0'
|
|
||||||
|
|
||||||
- name: Configure CMake (Linux)
|
- name: Install python3 cryptography module (Linux)
|
||||||
if: matrix.os == 'ubuntu-latest'
|
if: runner.os == 'Linux'
|
||||||
run: cmake
|
run: |
|
||||||
-S ${{github.workspace}}
|
source venv/bin/activate
|
||||||
-B ${{github.workspace}}/build
|
python -m pip install --upgrade pip
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
python -m pip install --upgrade cryptography
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
python -c "import sys; print(sys.executable)"
|
||||||
|
python --version
|
||||||
|
python -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
|
||||||
|
|
||||||
- name: Configure CMake (macOS)
|
- name: Install python3 cryptography module (macOS)
|
||||||
if: matrix.os == 'macOS-latest'
|
if: runner.os == 'macOS'
|
||||||
run: cmake
|
run: |
|
||||||
-S ${{github.workspace}}
|
source venv/bin/activate
|
||||||
-B ${{github.workspace}}/build
|
python -m pip install --upgrade pip
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
ARCHFLAGS="-arch arm64" python -m pip install --upgrade cryptography
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
python -c "import sys; print(sys.executable)"
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{matrix.vcpkg_root}}/scripts/buildsystems/vcpkg.cmake
|
python --version
|
||||||
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}}
|
python -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
|
||||||
|
|
||||||
|
- name: Install python3 cryptography module (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
run: |
|
||||||
|
.\venv\Scripts\Activate.ps1
|
||||||
|
python.exe -m ensurepip
|
||||||
|
python.exe -m pip install --upgrade pip
|
||||||
|
python.exe -m pip install cryptography
|
||||||
|
python.exe -c "import sys; print(sys.executable)"
|
||||||
|
python.exe --version
|
||||||
|
python.exe -c "import cryptography; print(f'Python3 cryptography version {cryptography.__version__}')"
|
||||||
|
|
||||||
|
- name: Configure CMake (Linux/macOS)
|
||||||
|
if: runner.os != 'Windows'
|
||||||
|
run: |
|
||||||
|
source venv/bin/activate
|
||||||
|
cmake \
|
||||||
|
-G "${{matrix.generator}}" \
|
||||||
|
-S "${{github.workspace}}" \
|
||||||
|
-B "${{github.workspace}}/build" \
|
||||||
|
-DCMAKE_OSX_ARCHITECTURES=arm64 \
|
||||||
|
-DCMAKE_BUILD_TYPE="${{env.BUILD_TYPE}}" \
|
||||||
|
-DCMAKE_INSTALL_PREFIX="${{github.workspace}}/dist"
|
||||||
|
|
||||||
- name: Configure CMake (Windows)
|
- name: Configure CMake (Windows)
|
||||||
if: matrix.os == 'windows-latest'
|
if: runner.os == 'Windows'
|
||||||
run: cmake
|
run: |
|
||||||
-G Ninja
|
.\venv\Scripts\Activate.ps1
|
||||||
-S ${{github.workspace}}
|
cmake `
|
||||||
-B ${{github.workspace}}/build
|
-G "${{matrix.generator}}" `
|
||||||
-DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}}
|
-S "${{github.workspace}}" `
|
||||||
-DCMAKE_INSTALL_PREFIX=${{github.workspace}}/dist
|
-B "${{github.workspace}}/build" `
|
||||||
-DCMAKE_TOOLCHAIN_FILE=${{matrix.vcpkg_root}}/scripts/buildsystems/vcpkg.cmake
|
-DCMAKE_BUILD_TYPE="${{env.BUILD_TYPE}}" `
|
||||||
-DVCPKG_TARGET_TRIPLET=${{matrix.triplet}}
|
-DCMAKE_INSTALL_PREFIX="${{github.workspace}}/dist"
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake
|
run: cmake
|
||||||
@@ -103,29 +189,43 @@ jobs:
|
|||||||
--config ${{env.BUILD_TYPE}}
|
--config ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
- name: List files (Linux/macOS)
|
- name: List files (Linux/macOS)
|
||||||
if: matrix.os != 'windows-latest'
|
if: runner.os != 'Windows'
|
||||||
run: find .. -ls
|
run: find .. -ls
|
||||||
|
|
||||||
- name: List files (Windows)
|
- name: List files (Windows)
|
||||||
if: matrix.os == 'windows-latest'
|
if: runner.os == 'Windows'
|
||||||
run: Get-ChildItem -Recurse -Name ..
|
run: Get-ChildItem -Recurse -Name ..
|
||||||
|
|
||||||
- name: Test
|
- name: Test (Linux/macOS)
|
||||||
|
if: runner.os != 'Windows'
|
||||||
working-directory: ${{github.workspace}}/build
|
working-directory: ${{github.workspace}}/build
|
||||||
run: ctest -C ${{env.BUILD_TYPE}}
|
run: |
|
||||||
|
source ../venv/bin/activate
|
||||||
|
ctest -C ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
|
- name: Test (Windows)
|
||||||
|
if: runner.os == 'Windows'
|
||||||
|
working-directory: ${{github.workspace}}/build
|
||||||
|
run: |
|
||||||
|
..\venv\Scripts\Activate.ps1
|
||||||
|
ctest -C ${{env.BUILD_TYPE}}
|
||||||
|
|
||||||
- name: Upload the errors
|
- name: Upload the errors
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
if: failure()
|
if: failure()
|
||||||
with:
|
with:
|
||||||
name: errors-${{matrix.triplet}}
|
name: errors-${{matrix.id}}
|
||||||
path: ${{github.workspace}}/build/Testing/Temporary/LastTest.log
|
path: |
|
||||||
|
${{github.workspace}}/build/Testing/Temporary/LastTest.log
|
||||||
|
${{github.workspace}}/build/Testing/conf/makecerts.log
|
||||||
|
${{github.workspace}}/build/Testing/logs/server.log
|
||||||
|
${{github.workspace}}/build/Testing/logs/port.log
|
||||||
|
|
||||||
- name: Install
|
- name: Install
|
||||||
run: cmake --install ${{github.workspace}}/build
|
run: cmake --install ${{github.workspace}}/build
|
||||||
|
|
||||||
- name: Upload the executables
|
- name: Upload the executables
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: osslsigncode-${{matrix.triplet}}
|
name: ${{env.version}}-${{matrix.id}}
|
||||||
path: ${{github.workspace}}/dist
|
path: ${{github.workspace}}/dist
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
name: "CodeQL"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [ "master" ]
|
||||||
|
pull_request:
|
||||||
|
# The branches below must be a subset of the branches above
|
||||||
|
branches: [ "master" ]
|
||||||
|
schedule:
|
||||||
|
- cron: '45 1 * * 2'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: [ 'cpp' ]
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v3
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
|
||||||
|
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||||
|
# By default, queries listed here will override any specified in a config file.
|
||||||
|
# Prefix the list here with "+" to use these queries and those in the config file.
|
||||||
|
|
||||||
|
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
|
||||||
|
# queries: security-extended,security-and-quality
|
||||||
|
|
||||||
|
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||||
|
# If this step fails, then you should remove it and run the build manually (see below)
|
||||||
|
- name: Autobuild
|
||||||
|
uses: github/codeql-action/autobuild@v3
|
||||||
|
|
||||||
|
# ℹ️ Command-line programs to run using the OS shell.
|
||||||
|
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||||
|
|
||||||
|
# If the Autobuild fails above, remove it and uncomment the following three lines.
|
||||||
|
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
|
||||||
|
|
||||||
|
# - run: |
|
||||||
|
# echo "Run, Build Application using script"
|
||||||
|
# ./location_of_script_within_repo/buildscript.sh
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v3
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
name: Codespell
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
codespell:
|
||||||
|
name: Check for spelling errors
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: codespell-project/actions-codespell@master
|
||||||
|
with:
|
||||||
|
skip: '*.pem'
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
name: Coverity Scan
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
coverity:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
token: ${{secrets.COVERITY_SCAN_TOKEN}}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
if: env.token
|
||||||
|
- name: Get ready for scanning
|
||||||
|
if: env.token
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get install -y libssl-dev libcurl4-openssl-dev
|
||||||
|
cmake -S ${{github.workspace}} -B ${{github.workspace}}/build
|
||||||
|
- uses: vapier/coverity-scan-action@v1
|
||||||
|
if: env.token
|
||||||
|
with:
|
||||||
|
email: ${{secrets.COVERITY_SCAN_EMAIL}}
|
||||||
|
token: ${{secrets.COVERITY_SCAN_TOKEN}}
|
||||||
|
command: make -C ${{github.workspace}}/build
|
||||||
@@ -12,7 +12,6 @@ CPackSourceConfig.cmake
|
|||||||
CTestTestfile.cmake
|
CTestTestfile.cmake
|
||||||
install_manifest.txt
|
install_manifest.txt
|
||||||
Makefile
|
Makefile
|
||||||
missing
|
|
||||||
osslsigncode
|
osslsigncode
|
||||||
osslsigncode.exe
|
osslsigncode.exe
|
||||||
stamp-h1
|
stamp-h1
|
||||||
|
|||||||
+80
-33
@@ -3,21 +3,20 @@ cmake_minimum_required(VERSION 3.17)
|
|||||||
|
|
||||||
# autodetect vcpkg CMAKE_TOOLCHAIN_FILE if VCPKG_ROOT is defined
|
# autodetect vcpkg CMAKE_TOOLCHAIN_FILE if VCPKG_ROOT is defined
|
||||||
# this needs to be configured before the project() directive
|
# this needs to be configured before the project() directive
|
||||||
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
if((CMAKE_GENERATOR MATCHES "Ninja") AND DEFINED ENV{VCPKG_ROOT} AND NOT $ENV{VCPKG_ROOT} STREQUAL "" AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||||
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
|
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" CACHE STRING "")
|
||||||
CACHE STRING "")
|
endif((CMAKE_GENERATOR MATCHES "Ninja") AND DEFINED ENV{VCPKG_ROOT} AND NOT $ENV{VCPKG_ROOT} STREQUAL "" AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
||||||
endif(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
|
|
||||||
set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
set(BUILTIN_SOCKET ON CACHE BOOL "") # for static Python
|
||||||
|
|
||||||
# configure basic project information
|
# configure basic project information
|
||||||
project(osslsigncode
|
project(osslsigncode
|
||||||
VERSION 2.4
|
VERSION 2.14
|
||||||
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files"
|
DESCRIPTION "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files"
|
||||||
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
HOMEPAGE_URL "https://github.com/mtrojnar/osslsigncode"
|
||||||
LANGUAGES C)
|
LANGUAGES C)
|
||||||
|
|
||||||
# force nonstandard version format for development packages
|
# force nonstandard version format for development packages
|
||||||
set(DEV "")
|
set(DEV "-dev")
|
||||||
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}${DEV}")
|
set(PROJECT_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}${DEV}")
|
||||||
|
|
||||||
# version and contact information
|
# version and contact information
|
||||||
@@ -30,7 +29,13 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
|
|||||||
|
|
||||||
# load CMake library modules
|
# load CMake library modules
|
||||||
include(FindOpenSSL)
|
include(FindOpenSSL)
|
||||||
include(FindCURL)
|
if(OPENSSL_VERSION VERSION_LESS "1.1.1")
|
||||||
|
message(FATAL_ERROR "OpenSSL version must be at least 1.1.1")
|
||||||
|
endif()
|
||||||
|
if(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
|
include(FindCURL)
|
||||||
|
endif(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
|
include(FindZLIB)
|
||||||
|
|
||||||
# load CMake project modules
|
# load CMake project modules
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${PROJECT_SOURCE_DIR}/cmake")
|
||||||
@@ -48,30 +53,43 @@ configure_file(Config.h.in config.h)
|
|||||||
target_compile_definitions(osslsigncode PRIVATE HAVE_CONFIG_H=1)
|
target_compile_definitions(osslsigncode PRIVATE HAVE_CONFIG_H=1)
|
||||||
|
|
||||||
# set sources
|
# set sources
|
||||||
target_sources(osslsigncode PRIVATE osslsigncode.c msi.c)
|
target_sources(osslsigncode PRIVATE osslsigncode.c helpers.c utf.c msi.c pe.c cab.c cat.c appx.c script.c)
|
||||||
if(WIN32)
|
if(NOT UNIX)
|
||||||
target_sources(osslsigncode PRIVATE applink.c)
|
target_sources(osslsigncode PRIVATE applink.c)
|
||||||
endif(WIN32)
|
endif(NOT UNIX)
|
||||||
|
|
||||||
# set include directories
|
# set include directories
|
||||||
target_include_directories(osslsigncode PRIVATE "${PROJECT_BINARY_DIR}")
|
target_include_directories(osslsigncode PRIVATE "${PROJECT_BINARY_DIR}")
|
||||||
|
|
||||||
# set OpenSSL includes/libraries
|
# set OpenSSL includes/libraries
|
||||||
if(NOT OPENSSL_FOUND)
|
if(NOT OPENSSL_FOUND)
|
||||||
message(FATAL_ERROR "OpenSSL library not found")
|
message(FATAL_ERROR "OpenSSL library not found")
|
||||||
endif(NOT OPENSSL_FOUND)
|
endif(NOT OPENSSL_FOUND)
|
||||||
target_include_directories(osslsigncode PRIVATE ${OPENSSL_INCLUDE_DIR})
|
target_include_directories(osslsigncode PRIVATE ${OPENSSL_INCLUDE_DIR})
|
||||||
target_link_libraries(osslsigncode PRIVATE ${OPENSSL_LIBRARIES})
|
target_link_libraries(osslsigncode PRIVATE ${OPENSSL_LIBRARIES})
|
||||||
|
|
||||||
# set cURL includes/libraries
|
# set cURL includes/libraries
|
||||||
|
if(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
if(CURL_FOUND)
|
if(CURL_FOUND)
|
||||||
target_compile_definitions(osslsigncode PRIVATE ENABLE_CURL=1)
|
target_compile_definitions(osslsigncode PRIVATE ENABLE_CURL=1)
|
||||||
target_include_directories(osslsigncode PRIVATE ${CURL_INCLUDE_DIRS})
|
target_include_directories(osslsigncode PRIVATE ${CURL_INCLUDE_DIRS})
|
||||||
target_link_libraries(osslsigncode PRIVATE ${CURL_LIBRARIES})
|
target_link_libraries(osslsigncode PRIVATE ${CURL_LIBRARIES})
|
||||||
message(STATUS "cURL support enabled")
|
message(STATUS "cURL support enabled")
|
||||||
else(CURL_FOUND)
|
else(CURL_FOUND)
|
||||||
message(STATUS "cURL support disabled (library not found)")
|
message(STATUS "cURL support disabled (library not found)")
|
||||||
endif(CURL_FOUND)
|
endif(CURL_FOUND)
|
||||||
|
endif(OPENSSL_VERSION VERSION_LESS "3.0.0")
|
||||||
|
|
||||||
|
if(NOT ZLIB_FOUND)
|
||||||
|
message(FATAL_ERROR "Zlib library not found")
|
||||||
|
endif(NOT ZLIB_FOUND)
|
||||||
|
target_include_directories(osslsigncode PRIVATE ${ZLIB_INCLUDE_DIR})
|
||||||
|
target_link_libraries(osslsigncode PRIVATE ${ZLIB_LIBRARIES})
|
||||||
|
|
||||||
|
if(NOT UNIX)
|
||||||
|
# https://learn.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-shutdown
|
||||||
|
target_link_libraries(osslsigncode PRIVATE ws2_32.lib crypt32.lib)
|
||||||
|
endif(NOT UNIX)
|
||||||
|
|
||||||
# add paths to linker search and installed rpath
|
# add paths to linker search and installed rpath
|
||||||
set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
@@ -79,17 +97,46 @@ set_target_properties(osslsigncode PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
|
|||||||
# testing with CTest
|
# testing with CTest
|
||||||
include(CMakeTest)
|
include(CMakeTest)
|
||||||
|
|
||||||
|
# documentation with Pandoc
|
||||||
|
include(CMakeDoc)
|
||||||
|
|
||||||
# installation rules for a project
|
# installation rules for a project
|
||||||
install(TARGETS osslsigncode RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX})
|
include(GNUInstallDirs)
|
||||||
if(WIN32)
|
|
||||||
install(
|
install(TARGETS osslsigncode RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||||
DIRECTORY ${PROJECT_BINARY_DIR}/ DESTINATION ${CMAKE_INSTALL_PREFIX}
|
|
||||||
FILES_MATCHING
|
install(FILES
|
||||||
PATTERN "*.dll"
|
"${PROJECT_SOURCE_DIR}/README.md"
|
||||||
PATTERN "vcpkg_installed" EXCLUDE
|
"${PROJECT_SOURCE_DIR}/NEWS.md"
|
||||||
PATTERN "CMakeFiles" EXCLUDE
|
DESTINATION "${CMAKE_INSTALL_DOCDIR}")
|
||||||
PATTERN "Testing" EXCLUDE
|
|
||||||
)
|
if(UNIX)
|
||||||
else(WIN32)
|
include(CMakeDist)
|
||||||
include(CMakeDist)
|
else(UNIX)
|
||||||
endif(WIN32)
|
install(
|
||||||
|
DIRECTORY ${PROJECT_BINARY_DIR}/
|
||||||
|
DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
FILES_MATCHING
|
||||||
|
PATTERN "*.dll"
|
||||||
|
PATTERN "vcpkg_installed" EXCLUDE
|
||||||
|
PATTERN "CMakeFiles" EXCLUDE
|
||||||
|
PATTERN "Testing" EXCLUDE)
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
|
# uninstall target
|
||||||
|
configure_file(
|
||||||
|
"${PROJECT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
|
||||||
|
"${PROJECT_BINARY_DIR}/cmake_uninstall.cmake"
|
||||||
|
IMMEDIATE @ONLY)
|
||||||
|
|
||||||
|
add_custom_target(uninstall
|
||||||
|
COMMAND ${CMAKE_COMMAND} -P "${PROJECT_BINARY_DIR}/cmake_uninstall.cmake")
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
@@ -3,10 +3,8 @@
|
|||||||
#define VERSION_MINOR "@osslsigncode_VERSION_MINOR@"
|
#define VERSION_MINOR "@osslsigncode_VERSION_MINOR@"
|
||||||
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
#cmakedefine PACKAGE_STRING "@PACKAGE_STRING@"
|
||||||
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
#cmakedefine PACKAGE_BUGREPORT "@PACKAGE_BUGREPORT@"
|
||||||
#cmakedefine ENABLE_CURL
|
|
||||||
#cmakedefine HAVE_TERMIOS_H
|
#cmakedefine HAVE_TERMIOS_H
|
||||||
#cmakedefine HAVE_GETPASS
|
#cmakedefine HAVE_GETPASS
|
||||||
#cmakedefine HAVE_SYS_MMAN_H
|
#cmakedefine HAVE_SYS_MMAN_H
|
||||||
#cmakedefine HAVE_MMAP
|
#cmakedefine HAVE_MMAP
|
||||||
#cmakedefine HAVE_MAPVIEWOFFILE
|
#cmakedefine HAVE_MAPVIEWOFFILE
|
||||||
#cmakedefine _WIN32
|
|
||||||
|
|||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
# Stage 1: Build osslsigncode on Alpine
|
||||||
|
FROM alpine:latest AS builder
|
||||||
|
|
||||||
|
# Install build dependencies
|
||||||
|
RUN apk add --no-cache build-base cmake openssl-dev zlib-dev
|
||||||
|
|
||||||
|
# Copy osslsigncode source code into the image
|
||||||
|
COPY . /source
|
||||||
|
|
||||||
|
# Build osslsigncode
|
||||||
|
RUN cd /source && \
|
||||||
|
mkdir -p build && \
|
||||||
|
cd build && \
|
||||||
|
rm -f CMakeCache.txt && \
|
||||||
|
cmake -S .. && \
|
||||||
|
cmake --build . && \
|
||||||
|
cmake --install .
|
||||||
|
|
||||||
|
# Stage 2: Create final image without build environment
|
||||||
|
FROM alpine:latest
|
||||||
|
|
||||||
|
# Copy compiled binary from builder stage
|
||||||
|
COPY --from=builder /usr/local/bin/osslsigncode /usr/local/bin/osslsigncode
|
||||||
|
|
||||||
|
# Install necessary runtime libraries (latest version)
|
||||||
|
RUN apk add --no-cache libcrypto3
|
||||||
|
|
||||||
|
# Set working directory
|
||||||
|
WORKDIR /workdir
|
||||||
|
|
||||||
|
# Declare volume to mount files
|
||||||
|
VOLUME [ "/workdir" ]
|
||||||
+30
-56
@@ -3,50 +3,40 @@
|
|||||||
### Building osslsigncode source with MSYS2 MinGW 64-bit and MSYS2 packages:
|
### Building osslsigncode source with MSYS2 MinGW 64-bit and MSYS2 packages:
|
||||||
|
|
||||||
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
||||||
Once up and running install even mingw-w64-x86_64-gcc, mingw-w64-x86_64-curl.
|
Once up and running install the following packages:
|
||||||
```
|
```
|
||||||
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-curl
|
pacman -S make mingw-w64-x86_64-gcc mingw-w64-x86_64-cmake mingw-w64-x86_64-openssl mingw-w64-x86_64-python-cryptography
|
||||||
```
|
```
|
||||||
mingw-w64-x86_64-openssl and mingw-w64-x86_64-zlib packages are installed with dependencies.
|
mingw-w64-x86_64-zlib package is installed with dependencies.
|
||||||
|
|
||||||
2) Run "MSYS2 MinGW 64-bit" and build 64-bit Windows executables.
|
2) Run "MSYS2 MinGW 64-bit" and build 64-bit Windows executables.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
cd osslsigncode-folder
|
||||||
x86_64-w64-mingw32-gcc osslsigncode.c msi.c -o osslsigncode.exe \
|
mkdir build && cd build && cmake -S .. -DCMAKE_BUILD_TYPE=Release -G "MSYS Makefiles"
|
||||||
-lcrypto -lssl -lcurl \
|
cmake --build . --verbose
|
||||||
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
|
||||||
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
|
||||||
-D ENABLE_CURL
|
|
||||||
```
|
```
|
||||||
|
|
||||||
3) Run "Command prompt" and include "c:\msys64\mingw64\bin" folder as part of the path.
|
3) Make tests.
|
||||||
|
```
|
||||||
|
ctest
|
||||||
|
```
|
||||||
|
|
||||||
|
4) Run "Command prompt" and include "c:\msys64\mingw64\bin" folder as part of the path.
|
||||||
```
|
```
|
||||||
path=%path%;c:\msys64\mingw64\bin
|
path=%path%;c:\msys64\mingw64\bin
|
||||||
cd osslsigncode-folder
|
|
||||||
osslsigncode.exe -v
|
osslsigncode.exe -v
|
||||||
osslsigncode 2.4, using:
|
osslsigncode 2.8, using:
|
||||||
OpenSSL 1.1.1g 21 Apr 2020 (Library: OpenSSL 1.1.1g 21 Apr 2020)
|
OpenSSL 3.2.0 23 Nov 2023 (Library: OpenSSL 3.2.0 23 Nov 2023)
|
||||||
libcurl/7.70.0 OpenSSL/1.1.1g (Schannel) zlib/1.2.11 brotli/1.0.7 libidn2/2.3.0
|
No default -CAfile location detected
|
||||||
libpsl/0.21.0 (+libidn2/2.3.0) libssh2/1.9.0 nghttp2/1.40.0
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Building OpenSSL and osslsigncode sources with MSYS2 MinGW 64-bit:
|
||||||
### Building OpenSSL, Curl and osslsigncode sources with MSYS2 MinGW 64-bit:
|
|
||||||
|
|
||||||
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
1) Download and install MSYS2 from https://msys2.github.io/ and follow installation instructions.
|
||||||
Once up and running install even: perl make autoconf automake libtool pkg-config.
|
Once up and running install even: perl make autoconf automake libtool pkg-config.
|
||||||
```
|
```
|
||||||
pacman -S perl make autoconf automake libtool pkg-config
|
pacman -S perl make autoconf automake libtool pkg-config
|
||||||
```
|
```
|
||||||
Make sure there are no curl, brotli, libpsl, libidn2 and nghttp2 packages installed:
|
|
||||||
```
|
|
||||||
pacman -R mingw-w64-x86_64-curl \
|
|
||||||
mingw-w64-x86_64-brotli \
|
|
||||||
mingw-w64-x86_64-libpsl \
|
|
||||||
mingw-w64-x86_64-libidn2 \
|
|
||||||
mingw-w64-x86_64-nghttp2
|
|
||||||
```
|
|
||||||
|
|
||||||
Run "MSYS2 MinGW 64-bit" in the administrator mode.
|
Run "MSYS2 MinGW 64-bit" in the administrator mode.
|
||||||
|
|
||||||
2) Build and install OpenSSL.
|
2) Build and install OpenSSL.
|
||||||
@@ -55,46 +45,30 @@
|
|||||||
./config --prefix='C:/OpenSSL' --openssldir='C:/OpenSSL'
|
./config --prefix='C:/OpenSSL' --openssldir='C:/OpenSSL'
|
||||||
make && make install
|
make && make install
|
||||||
```
|
```
|
||||||
3) Build and install curl.
|
|
||||||
```
|
|
||||||
cd curl-(version)
|
|
||||||
./buildconf
|
|
||||||
./configure --prefix='C:/curl' --with-ssl='C:/OpenSSL' \
|
|
||||||
--disable-ftp --disable-tftp --disable-file --disable-dict \
|
|
||||||
--disable-telnet --disable-imap --disable-smb --disable-smtp \
|
|
||||||
--disable-gopher --disable-pop --disable-pop3 --disable-rtsp \
|
|
||||||
--disable-ldap --disable-ldaps --disable-unix-sockets \
|
|
||||||
--disable-pthreads --without-zstd --without-zlib
|
|
||||||
make && make install
|
|
||||||
```
|
|
||||||
|
|
||||||
3) Build 64-bit Windows executables.
|
3) Configure a CMake project.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
mkdir build && cd build && cmake -S .. -DCMAKE_BUILD_TYPE=Release -G "MSYS Makefiles" -DCMAKE_PREFIX_PATH="C:\OpenSSL"
|
||||||
x86_64-w64-mingw32-gcc osslsigncode.c msi.c -o osslsigncode.exe \
|
|
||||||
-L 'C:/OpenSSL/lib/' -lcrypto -lssl \
|
|
||||||
-I 'C:/OpenSSL/include/' \
|
|
||||||
-L 'C:/curl/lib' -lcurl \
|
|
||||||
-I 'C:/curl/include' \
|
|
||||||
-D 'PACKAGE_STRING="osslsigncode x.y"' \
|
|
||||||
-D 'PACKAGE_BUGREPORT="Your.Email@example.com"' \
|
|
||||||
-D ENABLE_CURL
|
|
||||||
```
|
```
|
||||||
|
|
||||||
4) Run "Command prompt" and copy required libraries.
|
4) Run "Command prompt" and copy required libraries.
|
||||||
```
|
```
|
||||||
cd osslsigncode-folder
|
cd osslsigncode-folder
|
||||||
copy C:\OpenSSL\bin\libssl-1_1-x64.dll
|
copy C:\OpenSSL\bin\libssl-3-x64.dll
|
||||||
copy C:\OpenSSL\bin\libcrypto-1_1-x64.dll
|
copy C:\OpenSSL\bin\libcrypto-3-x64.dll
|
||||||
copy C:\curl\bin\libcurl-4.dll
|
|
||||||
|
|
||||||
osslsigncode.exe -v
|
|
||||||
osslsigncode 2.4, using:
|
|
||||||
OpenSSL 1.1.1k 25 Mar 2021 (Library: OpenSSL 1.1.1k 25 Mar 2021)
|
|
||||||
libcurl/7.78.0 OpenSSL/1.1.1k
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Building OpenSSL, Curl and osslsigncode sources with Microsoft Visual Studio:
|
5) Build 64-bit Windows executables.
|
||||||
|
```
|
||||||
|
cmake --build . --verbose
|
||||||
|
```
|
||||||
|
|
||||||
|
6) Make tests.
|
||||||
|
```
|
||||||
|
ctest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building OpenSSL and osslsigncode sources with Microsoft Visual Studio:
|
||||||
|
|
||||||
1) Install and integrate vcpkg: https://vcpkg.io/en/getting-started.html
|
1) Install and integrate vcpkg: https://vcpkg.io/en/getting-started.html
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
OpenSSL based Authenticode signing for PE/MSI/Java CAB files.
|
OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files.
|
||||||
|
|
||||||
Copyright (C) 2005-2014 Per Allansson <pallansson@gmail.com>
|
Copyright (C) 2005-2014 Per Allansson <pallansson@gmail.com>
|
||||||
Copyright (C) 2018-2022 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
Copyright (C) 2018-2022 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
|||||||
@@ -1,5 +1,125 @@
|
|||||||
# osslsigncode change log
|
# osslsigncode change log
|
||||||
|
|
||||||
|
### 2.14 (unreleased)
|
||||||
|
|
||||||
|
- attach-signature now uses digest-only verification instead of full signature
|
||||||
|
validation; output file is not kept if digest verification fails
|
||||||
|
|
||||||
|
### 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
|
||||||
|
- added PKCS#11 provider support (requires OpenSSL 3.0+)
|
||||||
|
- added support for providers without specifying "-pkcs11module" option
|
||||||
|
(OpenSSL 3.0+, e.g., for the upcoming CNG provider)
|
||||||
|
- added compatibility with the CNG engine version 1.1 or later
|
||||||
|
- added the "-engineCtrl" option to control hardware and CNG engines
|
||||||
|
- added the '-blobFile' option to specify a file containing the blob content
|
||||||
|
- improved unauthenticated blob support (thanks to Asger Hautop Drewsen)
|
||||||
|
- improved UTF-8 handling for certificate subjects and issuers
|
||||||
|
- fixed support for multiple signerInfo contentType OIDs (CTL and Authenticode)
|
||||||
|
- fixed tests for python-cryptography >= 43.0.0
|
||||||
|
|
||||||
|
### 2.9 (2024.06.29)
|
||||||
|
|
||||||
|
- added a 64 bit long pseudo-random NONCE in the TSA request
|
||||||
|
- missing NID_pkcs9_signingTime is no longer an error
|
||||||
|
- added support for PEM-encoded CRLs
|
||||||
|
- fixed the APPX central directory sorting order
|
||||||
|
- added a special "-" file name to read the passphrase from stdin
|
||||||
|
(by Steve McIntyre)
|
||||||
|
- used native HTTP client with OpenSSL 3.x, removing libcurl dependency
|
||||||
|
- added '-login' option to force a login to PKCS11 engines
|
||||||
|
(by Brad Hughes)
|
||||||
|
- added the "-ignore-crl" option to disable fetching and verifying
|
||||||
|
CRL Distribution Points
|
||||||
|
- changed error output to stderr instead of stdout
|
||||||
|
- various testing framework improvements
|
||||||
|
- various memory corruption fixes
|
||||||
|
|
||||||
|
### 2.8 (2024.03.03)
|
||||||
|
|
||||||
|
- Microsoft PowerShell signing sponsored by Cisco Systems, Inc.
|
||||||
|
- fixed setting unauthenticated attributes (Countersignature, Unauthenticated
|
||||||
|
Data Blob) in a nested signature
|
||||||
|
- added the "-index" option to verify a specific signature or modify its
|
||||||
|
unauthenticated attributes
|
||||||
|
- added CAT file verification
|
||||||
|
- added listing the contents of a CAT file with the "-verbose" option
|
||||||
|
- added the new "extract-data" command to extract a PKCS#7 data content to be
|
||||||
|
signed with "sign" and attached with "attach-signature"
|
||||||
|
- added PKCS9_SEQUENCE_NUMBER authenticated attribute support
|
||||||
|
- added the "-ignore-cdp" option to disable CRL Distribution Points (CDP)
|
||||||
|
online verification
|
||||||
|
- unsuccessful CRL retrieval and verification changed into a critical error
|
||||||
|
- the "-p" option modified to also use to configured proxy to connect CRL
|
||||||
|
Distribution Points
|
||||||
|
- added implicit allowlisting of the Microsoft Root Authority serial number
|
||||||
|
00C1008B3C3C8811D13EF663ECDF40
|
||||||
|
- added listing of certificate chain retrieved from the signature in case of
|
||||||
|
verification failure
|
||||||
|
|
||||||
|
### 2.7 (2023.09.19)
|
||||||
|
|
||||||
|
- fixed signing CAB files (by Michael Brown)
|
||||||
|
- fixed handling of unsupported commands (by Maxim Bagryantsev)
|
||||||
|
- fixed writing DIFAT sectors
|
||||||
|
- added APPX support (by Maciej Panek and Małgorzata Olszówka)
|
||||||
|
- added a built-in TSA response generation (-TSA-certs, -TSA-key
|
||||||
|
and -TSA-time options)
|
||||||
|
|
||||||
|
### 2.6 (2023.05.29)
|
||||||
|
|
||||||
|
- modular architecture implemented to simplify adding file formats
|
||||||
|
- added verification of CRLs specified in the signing certificate
|
||||||
|
- added MSI DIFAT sectors support (by Max Bagryantsev)
|
||||||
|
- added legacy provider support for OpenSSL 3.0.0 and later
|
||||||
|
- fixed numerous bugs
|
||||||
|
|
||||||
|
### 2.5 (2022.08.12)
|
||||||
|
|
||||||
|
- fixed the Unix executable install path
|
||||||
|
- fixed the hardcoded "pkcs11" engine id
|
||||||
|
- fixed building with MinGW
|
||||||
|
- fixed testing with the python3 distributed with Ubuntu 18.04
|
||||||
|
|
||||||
### 2.4 (2022.08.02)
|
### 2.4 (2022.08.02)
|
||||||
|
|
||||||
- migrated the build system from GNU Autoconf to CMake
|
- migrated the build system from GNU Autoconf to CMake
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ machine every time I need to sign a binary - I can compile and build
|
|||||||
the binaries using Wine on my Linux machine, but I can't sign them
|
the binaries using Wine on my Linux machine, but I can't sign them
|
||||||
since the signtool.exe makes good use of the CryptoAPI in Windows, and
|
since the signtool.exe makes good use of the CryptoAPI in Windows, and
|
||||||
these APIs aren't (yet?) fully implemented in Wine, so the signtool.exe
|
these APIs aren't (yet?) fully implemented in Wine, so the signtool.exe
|
||||||
tool would fail. And, so, osslsigncode was born.
|
tool would fail. And, so, osslsigncode was born.
|
||||||
|
|
||||||
## WHAT CAN IT DO?
|
## WHAT CAN IT DO?
|
||||||
|
|
||||||
It can sign and timestamp PE (EXE/SYS/DLL/etc), CAB, CAT and MSI files.
|
It can sign and timestamp PE (EXE/SYS/DLL/etc), CAB, CAT, MSI and APPX files,
|
||||||
|
as well as script files with extensions `.ps1`, `.ps1xml`, `.psc1`, `.psd1`,
|
||||||
|
`.psm1`, `.cdxml`, `.mof`, and `.js`.
|
||||||
It supports the equivalent of signtool.exe's "-j javasign.dll -jp low",
|
It supports the equivalent of signtool.exe's "-j javasign.dll -jp low",
|
||||||
i.e. add a valid signature for a CAB file containing Java files.
|
i.e. add a valid signature for a CAB file containing Java files.
|
||||||
It supports getting the timestamp through a proxy as well. It also
|
It supports getting the timestamp through a proxy as well. It also
|
||||||
@@ -39,25 +41,29 @@ We highly recommend downloading a [release tarball](https://github.com/mtrojnar/
|
|||||||
|
|
||||||
* Install prerequisites on a Debian-based distributions, such as Ubuntu:
|
* Install prerequisites on a Debian-based distributions, such as Ubuntu:
|
||||||
```
|
```
|
||||||
sudo apt update && sudo apt install cmake libssl-dev libcurl4-openssl-dev
|
sudo apt update && sudo apt install cmake libssl-dev libcurl4-openssl-dev zlib1g-dev python3
|
||||||
```
|
```
|
||||||
* Install prerequisites on macOS with Homebrew:
|
* Install prerequisites on macOS with Homebrew:
|
||||||
```
|
```
|
||||||
brew install cmake pkg-config openssl@1.1
|
brew install cmake pkg-config openssl@1.1
|
||||||
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"
|
export PKG_CONFIG_PATH="/usr/local/opt/openssl@1.1/lib/pkgconfig"
|
||||||
```
|
```
|
||||||
**NOTE:** osslsigncode requires CMake 3.6 or newer.
|
**NOTE:** osslsigncode requires CMake 3.17 or newer.
|
||||||
|
|
||||||
You may need to use `cmake3` instead of `cmake` to complete the following steps on your system.
|
You may need to use `cmake3` instead of `cmake` to complete the following steps on your system.
|
||||||
* Navigate to the build directory and run CMake to configure the osslsigncode project
|
* Navigate to the build directory and run CMake to configure the osslsigncode project
|
||||||
and generate a native build system:
|
and generate a native build system:
|
||||||
```
|
```
|
||||||
mkdir build && cd build && cmake ..
|
mkdir build && cd build && cmake -S ..
|
||||||
```
|
```
|
||||||
with specific compile options:
|
optional CMake parameters:
|
||||||
```
|
```
|
||||||
-Denable-strict=ON
|
-DCMAKE_BUILD_TYPE=Debug
|
||||||
-Denable-pedantic=ON
|
-DCMAKE_C_COMPILER=clang
|
||||||
|
-DCMAKE_PREFIX_PATH=[openssl directory];[curl directory]
|
||||||
|
-DCMAKE_INSTALL_PREFIX=[installation directory]
|
||||||
|
-DBASH_COMPLETION_USER_DIR=[bash completion installation directory]
|
||||||
|
|
||||||
```
|
```
|
||||||
* Then call that build system to actually compile/link the osslsigncode project (alias `make`):
|
* Then call that build system to actually compile/link the osslsigncode project (alias `make`):
|
||||||
```
|
```
|
||||||
@@ -69,7 +75,7 @@ You may need to use `cmake3` instead of `cmake` to complete the following steps
|
|||||||
```
|
```
|
||||||
* Make install:
|
* Make install:
|
||||||
```
|
```
|
||||||
sudo cmake --install . --prefix "/home/myuser/installdir"
|
sudo cmake --install .
|
||||||
```
|
```
|
||||||
* Make tarball (simulate autotools' `make dist`):
|
* Make tarball (simulate autotools' `make dist`):
|
||||||
```
|
```
|
||||||
@@ -118,7 +124,7 @@ You can use a certificate and key stored in a PKCS#12 container:
|
|||||||
-n "Your Application" -i http://www.yourwebsite.com/ \
|
-n "Your Application" -i http://www.yourwebsite.com/ \
|
||||||
-in yourapp.exe -out yourapp-signed.exe
|
-in yourapp.exe -out yourapp-signed.exe
|
||||||
```
|
```
|
||||||
To sign a CAB file containing java class files:
|
To sign a CAB file containing Java class files:
|
||||||
```
|
```
|
||||||
osslsigncode sign -certs <cert-file> -key <key-file> \
|
osslsigncode sign -certs <cert-file> -key <key-file> \
|
||||||
-n "Your Application" -i http://www.yourwebsite.com/ \
|
-n "Your Application" -i http://www.yourwebsite.com/ \
|
||||||
@@ -127,17 +133,68 @@ To sign a CAB file containing java class files:
|
|||||||
```
|
```
|
||||||
Only the 'low' parameter is currently supported.
|
Only the 'low' parameter is currently supported.
|
||||||
|
|
||||||
If you want to use PKCS11 token, you should indicate PKCS11 engine and module.
|
### Using the PKCS#11 Engine with osslsigncode
|
||||||
An example of using osslsigncode with SoftHSM:
|
If you want to use a PKCS#11 token, specify the PKCS#11 engine and module.
|
||||||
|
Example usage with SoftHSM:
|
||||||
```
|
```
|
||||||
osslsigncode sign \
|
osslsigncode sign \
|
||||||
-pkcs11engine /usr/lib64/engines-1.1/pkcs11.so \
|
-engine /usr/lib64/engines-1.1/pkcs11.so \
|
||||||
-pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \
|
-pkcs11module /usr/lib64/pkcs11/libsofthsm2.so \
|
||||||
-pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \
|
-pkcs11cert 'pkcs11:token=softhsm-token;object=cert' \
|
||||||
-key 'pkcs11:token=softhsm-token;object=key' \
|
-key 'pkcs11:token=softhsm-token;object=key' \
|
||||||
-in yourapp.exe -out yourapp-signed.exe
|
-in yourapp.exe -out yourapp-signed.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 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 \
|
||||||
|
-pkcs11module /usr/lib64/opensc-pkcs11.so \
|
||||||
|
-pkcs11cert 'pkcs11:token=my-token;object=cert' \
|
||||||
|
-key 'pkcs11:token=my-token;object=key' \
|
||||||
|
-in yourapp.exe -out yourapp-signed.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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 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:
|
||||||
|
|
||||||
|
- Specify the full or relative path to `cng.dll`:
|
||||||
|
```
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
You can check that the signed file is correct by right-clicking
|
You can check that the signed file is correct by right-clicking
|
||||||
on it in Windows and choose Properties --> Digital Signatures,
|
on it in Windows and choose Properties --> Digital Signatures,
|
||||||
and then choose the signature from the list, and click on
|
and then choose the signature from the list, and click on
|
||||||
@@ -175,15 +232,13 @@ osslsigncode.exe add -addUnauthenticatedBlob -in your_signed_file.exe -out out.e
|
|||||||
This feature allows for doing dumb things. Be very careful with what you put
|
This feature allows for doing dumb things. Be very careful with what you put
|
||||||
in the unauthenticated blob, as an attacker could modify this. Do NOT, under
|
in the unauthenticated blob, as an attacker could modify this. Do NOT, under
|
||||||
any circumstances, put a URL here that you will use to download an additional
|
any circumstances, put a URL here that you will use to download an additional
|
||||||
file. If you do do that, you would need to check the newly downloaded file is
|
file. If you do that, you would need to check the newly downloaded file is
|
||||||
code signed AND that it has been signed with your cert AND that it is the
|
code signed AND that it has been signed with your cert AND that it is the
|
||||||
version you expect. You should consider using asymmetrical encryption for the
|
version you expect.
|
||||||
data you put in the blob, such that the executable contains the public key to
|
|
||||||
decrypt the data. Basically, be VERY careful.
|
|
||||||
|
|
||||||
## BUGS, QUESTIONS etc.
|
## BUGS, QUESTIONS etc.
|
||||||
|
|
||||||
Check whether your your question or suspected bug was already
|
Check whether your question or suspected bug was already
|
||||||
discussed on https://github.com/mtrojnar/osslsigncode/issues.
|
discussed on https://github.com/mtrojnar/osslsigncode/issues.
|
||||||
Otherwise, open a new issue.
|
Otherwise, open a new issue.
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
- signature extraction/removal/verificaton on MSI/CAB files
|
- signature extraction/removal/verification on MSI/CAB files
|
||||||
- clean up / untangle code
|
- clean up / untangle code
|
||||||
- separate timestamping
|
- separate timestamping
|
||||||
- remove mmap usage to increase portability
|
- remove mmap usage to increase portability
|
||||||
|
|||||||
@@ -0,0 +1,512 @@
|
|||||||
|
/*
|
||||||
|
* CAT file support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*
|
||||||
|
* Catalog files are a bit odd, in that they are only a PKCS7 blob.
|
||||||
|
* CAT files do not support nesting (multiple signature)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_BMPSTRING *tag;
|
||||||
|
ASN1_INTEGER *flags;
|
||||||
|
ASN1_OCTET_STRING *value;
|
||||||
|
} CatNameValueContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatNameValueContent)
|
||||||
|
|
||||||
|
ASN1_SEQUENCE(CatNameValueContent) = {
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, tag, ASN1_BMPSTRING),
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, flags, ASN1_INTEGER),
|
||||||
|
ASN1_SIMPLE(CatNameValueContent, value, ASN1_OCTET_STRING)
|
||||||
|
} ASN1_SEQUENCE_END(CatNameValueContent)
|
||||||
|
|
||||||
|
IMPLEMENT_ASN1_FUNCTIONS(CatNameValueContent)
|
||||||
|
|
||||||
|
struct cat_ctx_st {
|
||||||
|
uint32_t sigpos;
|
||||||
|
uint32_t siglen;
|
||||||
|
uint32_t fileend;
|
||||||
|
PKCS7 *p7;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* FILE_FORMAT method prototypes */
|
||||||
|
static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
|
static int cat_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
static void cat_bio_free(BIO *hash, BIO *outdata);
|
||||||
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
FILE_FORMAT file_format_cat = {
|
||||||
|
.ctx_new = cat_ctx_new,
|
||||||
|
.verify_digests = cat_verify_digests,
|
||||||
|
.pkcs7_extract = cat_pkcs7_extract,
|
||||||
|
.pkcs7_signature_new = cat_pkcs7_signature_new,
|
||||||
|
.append_pkcs7 = cat_append_pkcs7,
|
||||||
|
.bio_free = cat_bio_free,
|
||||||
|
.ctx_cleanup = cat_ctx_cleanup,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize);
|
||||||
|
static int cat_add_content_type(PKCS7 *p7, PKCS7 *cursig);
|
||||||
|
static int cat_sign_content(PKCS7 *p7, PKCS7 *contents);
|
||||||
|
static int cat_list_content(PKCS7 *p7);
|
||||||
|
static int cat_print_content_member_digest(ASN1_TYPE *content);
|
||||||
|
static int cat_print_content_member_name(ASN1_TYPE *content);
|
||||||
|
static void cat_print_base64(ASN1_OCTET_STRING *value);
|
||||||
|
static void cat_print_utf16_as_ascii(ASN1_OCTET_STRING *value);
|
||||||
|
static int cat_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FILE_FORMAT method definitions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a CAT file format context.
|
||||||
|
* [in, out] options: structure holds the input data
|
||||||
|
* [out] hash: message digest BIO (unused)
|
||||||
|
* [in] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] pointer to CAT file format context
|
||||||
|
*/
|
||||||
|
static FILE_FORMAT_CTX *cat_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
FILE_FORMAT_CTX *ctx;
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
uint32_t filesize;
|
||||||
|
|
||||||
|
if (options->cmd == CMD_REMOVE || options->cmd==CMD_ATTACH || options->cmd == CMD_EXTRACT_DATA) {
|
||||||
|
fprintf(stderr, "Unsupported command\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
filesize = get_file_size(options->infile);
|
||||||
|
if (filesize == 0)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
|
||||||
|
options->indata = map_file(options->infile, filesize);
|
||||||
|
if (!options->indata) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
cat_ctx = cat_ctx_get(options->indata, filesize);
|
||||||
|
if (!cat_ctx) {
|
||||||
|
unmap_file(options->indata, filesize);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
|
ctx->format = &file_format_cat;
|
||||||
|
ctx->options = options;
|
||||||
|
ctx->cat_ctx = cat_ctx;
|
||||||
|
|
||||||
|
/* Push hash on outdata, if hash is NULL the function does nothing */
|
||||||
|
BIO_push(hash, outdata);
|
||||||
|
|
||||||
|
if (options->cmd == CMD_VERIFY)
|
||||||
|
printf("Warning: Use -catalog option to verify that a file, listed in catalog file, is signed\n");
|
||||||
|
if (options->jp >= 0)
|
||||||
|
printf("Warning: -jp option is only valid for CAB files\n");
|
||||||
|
if (options->pagehash == 1)
|
||||||
|
printf("Warning: -ph option is only valid for PE files\n");
|
||||||
|
if (options->add_msi_dse == 1)
|
||||||
|
printf("Warning: -add-msi-dse option is only valid for MSI files\n");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ContentInfo value is the inner content of pkcs7-signedData.
|
||||||
|
* An extra verification is not necessary when a content type data
|
||||||
|
* is the inner content of the signed-data type.
|
||||||
|
*/
|
||||||
|
static int cat_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)ctx;
|
||||||
|
(void)p7;
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *cat_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (!cat_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return PKCS7_dup(ctx->cat_ctx->p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new PKCS#7 signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO (unused)
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *cat_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
|
||||||
|
/* squash unused parameter warnings */
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
p7 = pkcs7_create(ctx);
|
||||||
|
if (!p7) {
|
||||||
|
fprintf(stderr, "Creating a new signature failed\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!ctx->cat_ctx->p7 || !ctx->cat_ctx->p7->d.sign || !ctx->cat_ctx->p7->d.sign->contents) {
|
||||||
|
fprintf(stderr, "Failed to get content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!cat_add_content_type(p7, ctx->cat_ctx->p7)) {
|
||||||
|
fprintf(stderr, "Adding content type failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!cat_sign_content(p7, ctx->cat_ctx->p7->d.sign->contents)) {
|
||||||
|
fprintf(stderr, "Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return p7; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append signature to the outfile.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int cat_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
return data_write_pkcs7(ctx, outdata, p7);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free up an entire message digest BIO chain.
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_bio_free(BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)outdata;
|
||||||
|
BIO_free_all(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate a FILE_FORMAT_CTX structure and CAT format specific structure,
|
||||||
|
* unmap indata file.
|
||||||
|
* [in, out] ctx: structure holds all input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [in] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
unmap_file(ctx->options->indata, ctx->cat_ctx->fileend);
|
||||||
|
PKCS7_free(ctx->cat_ctx->p7);
|
||||||
|
OPENSSL_free(ctx->cat_ctx);
|
||||||
|
OPENSSL_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CAT helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Verify mapped PKCS#7 (CAT) file and create CAT format specific structure.
|
||||||
|
* [in] indata: mapped file
|
||||||
|
* [in] filesize: size of file
|
||||||
|
* [returns] pointer to CAT format specific structure
|
||||||
|
*/
|
||||||
|
static CAT_CTX *cat_ctx_get(char *indata, uint32_t filesize)
|
||||||
|
{
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
PKCS7 *p7;
|
||||||
|
|
||||||
|
p7 = pkcs7_read_data(indata, filesize);
|
||||||
|
if (!p7)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
if (!PKCS7_type_is_signed(p7)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
cat_ctx = OPENSSL_zalloc(sizeof(CAT_CTX));
|
||||||
|
cat_ctx->p7 = p7;
|
||||||
|
cat_ctx->sigpos = 0;
|
||||||
|
cat_ctx->siglen = filesize;
|
||||||
|
cat_ctx->fileend = filesize;
|
||||||
|
return cat_ctx; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a content type OID to the PKCS#7 signature structure.
|
||||||
|
* The content type can be:
|
||||||
|
* - "1.3.6.1.4.1.311.10.1" (MS_CTL_OBJID) for Certificate Trust Lists (CTL),
|
||||||
|
* - "1.3.6.1.4.1.311.2.1.4" (SPC_INDIRECT_DATA_OBJID) for Authenticode data.
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] cursig: current PKCS#7 signature to determine content type
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_add_content_type(PKCS7 *p7, PKCS7 *cursig)
|
||||||
|
{
|
||||||
|
const char *content_type;
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
if (is_content_type(cursig, SPC_INDIRECT_DATA_OBJID)) {
|
||||||
|
/* Authenticode content */
|
||||||
|
content_type = SPC_INDIRECT_DATA_OBJID;
|
||||||
|
} else if (is_content_type(cursig, MS_CTL_OBJID)) {
|
||||||
|
/* Certificate Trust List (CTL) */
|
||||||
|
content_type = MS_CTL_OBJID;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Unsupported content type\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
signer_info = PKCS7_get_signer_info(p7);
|
||||||
|
if (!signer_info)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
||||||
|
V_ASN1_OBJECT, OBJ_txt2obj(content_type, 1)))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sign the MS CTL blob.
|
||||||
|
* Certificate Trust List (CTL) is a list of file names or thumbprints.
|
||||||
|
* All the items in this list are authenticated (approved) by the signing entity.
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] contents: Certificate Trust List (CTL)
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_sign_content(PKCS7 *p7, PKCS7 *contents)
|
||||||
|
{
|
||||||
|
const unsigned char *sequence_data;
|
||||||
|
const unsigned char *content;
|
||||||
|
ASN1_STRING *sequence;
|
||||||
|
int seqhdrlen, sequence_len, content_length;
|
||||||
|
|
||||||
|
if (!contents->d.other || !contents->d.other->value.sequence) {
|
||||||
|
fprintf(stderr, "Failed to get content value\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
sequence = contents->d.other->value.sequence;
|
||||||
|
sequence_data = ASN1_STRING_get0_data(sequence);
|
||||||
|
sequence_len = ASN1_STRING_length(sequence);
|
||||||
|
|
||||||
|
if (!sequence_data) {
|
||||||
|
fprintf(stderr, "Failed to get content value\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
seqhdrlen = asn1_simple_hdr_len(sequence_data, sequence_len);
|
||||||
|
content = (const unsigned char *)sequence_data + seqhdrlen;
|
||||||
|
content_length = sequence_len - seqhdrlen;
|
||||||
|
|
||||||
|
if (!pkcs7_sign_content(p7, content, content_length)) {
|
||||||
|
fprintf(stderr, "Failed to sign content\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PKCS7_set_content(p7, PKCS7_dup(contents))) {
|
||||||
|
fprintf(stderr, "PKCS7_set_content failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print each member of the CAT file by using the "-verbose" option.
|
||||||
|
* [in, out] p7: catalog file to verify
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int cat_list_content(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
MsCtlContent *ctlc;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ctlc = ms_ctl_content_get(p7);
|
||||||
|
if (!ctlc) {
|
||||||
|
fprintf(stderr, "Failed to extract MS_CTL_OBJID data\n");
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
printf("\nCatalog members:\n");
|
||||||
|
for (i = 0; i < sk_CatalogInfo_num(ctlc->header_attributes); i++) {
|
||||||
|
int j, found = 0;
|
||||||
|
CatalogInfo *header_attr = sk_CatalogInfo_value(ctlc->header_attributes, i);
|
||||||
|
if (header_attr == NULL)
|
||||||
|
continue;
|
||||||
|
for (j = 0; j < sk_CatalogAuthAttr_num(header_attr->attributes); j++) {
|
||||||
|
char object_txt[128];
|
||||||
|
CatalogAuthAttr *attribute;
|
||||||
|
ASN1_TYPE *content;
|
||||||
|
|
||||||
|
attribute = sk_CatalogAuthAttr_value(header_attr->attributes, j);
|
||||||
|
if (!attribute)
|
||||||
|
continue;
|
||||||
|
content = catalog_content_get(attribute);
|
||||||
|
if (!content)
|
||||||
|
continue;
|
||||||
|
object_txt[0] = 0x00;
|
||||||
|
OBJ_obj2txt(object_txt, sizeof object_txt, attribute->type, 1);
|
||||||
|
if (!strcmp(object_txt, CAT_NAMEVALUE_OBJID)) {
|
||||||
|
/* CAT_NAMEVALUE_OBJID OID: 1.3.6.1.4.1.311.12.2.1 */
|
||||||
|
found |= cat_print_content_member_name(content);
|
||||||
|
} else if (!strcmp(object_txt, SPC_INDIRECT_DATA_OBJID)) {
|
||||||
|
/* SPC_INDIRECT_DATA_OBJID OID: 1.3.6.1.4.1.311.2.1.4 */
|
||||||
|
found |= cat_print_content_member_digest(content);
|
||||||
|
}
|
||||||
|
ASN1_TYPE_free(content);
|
||||||
|
}
|
||||||
|
if (found)
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
MsCtlContent_free(ctlc);
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
return 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a hash algorithm and a message digest from the SPC_INDIRECT_DATA_OBJID attribute.
|
||||||
|
* [in] content: catalog file content
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_print_content_member_digest(ASN1_TYPE *content)
|
||||||
|
{
|
||||||
|
SpcIndirectDataContent *idc;
|
||||||
|
u_char mdbuf[EVP_MAX_MD_SIZE];
|
||||||
|
int mdtype = -1;
|
||||||
|
|
||||||
|
idc = asn1_type_get_indirect_data_content(content);
|
||||||
|
if (!idc)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a file name from the CAT_NAMEVALUE_OBJID attribute.
|
||||||
|
* [in] content: catalog file content
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_print_content_member_name(ASN1_TYPE *content)
|
||||||
|
{
|
||||||
|
CatNameValueContent *nvc;
|
||||||
|
const u_char *data = NULL;
|
||||||
|
ASN1_STRING *value;
|
||||||
|
|
||||||
|
value = content->value.sequence;
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
nvc = d2i_CatNameValueContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
|
if (!nvc) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
printf("\tFile name: ");
|
||||||
|
if (ASN1_INTEGER_get(nvc->flags) & 0x00020000) {
|
||||||
|
cat_print_base64(nvc->value);
|
||||||
|
} else {
|
||||||
|
cat_print_utf16_as_ascii(nvc->value);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
CatNameValueContent_free(nvc);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a CAT_NAMEVALUE_OBJID attribute represented in base-64 encoding.
|
||||||
|
* [in] value: catalog member file name
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_print_base64(ASN1_OCTET_STRING *value)
|
||||||
|
{
|
||||||
|
BIO *stdbio, *b64;
|
||||||
|
stdbio = BIO_new_fp(stdout, BIO_NOCLOSE);
|
||||||
|
b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
stdbio = BIO_push(b64, stdbio);
|
||||||
|
ASN1_STRING_print_ex(stdbio, value, 0);
|
||||||
|
BIO_free_all(stdbio);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Print a CAT_NAMEVALUE_OBJID attribute represented in plaintext.
|
||||||
|
* [in] value: catalog member file name
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void cat_print_utf16_as_ascii(ASN1_OCTET_STRING *value)
|
||||||
|
{
|
||||||
|
const u_char *data;
|
||||||
|
int len, i;
|
||||||
|
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
len = ASN1_STRING_length(value);
|
||||||
|
for (i = 0; i < len && (data[i] || data[i+1]); i+=2)
|
||||||
|
putchar(isprint(data[i]) && !data[i+1] ? data[i] : '.');
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int cat_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "Init error\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
signer_info = PKCS7_get_signer_info(ctx->cat_ctx->p7);
|
||||||
|
if (!signer_info) {
|
||||||
|
fprintf(stderr, "Failed catalog file\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si) {
|
||||||
|
fprintf(stderr, "No signature found\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->options->verbose) {
|
||||||
|
(void)cat_list_content(ctx->cat_ctx->p7);
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
||||||
+10
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
set(CPACK_PACKAGE_NAME ${PROJECT_NAME})
|
||||||
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
set(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
|
||||||
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenSSL based Authenticode signing for PE, CAB, CAT and MSI files")
|
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "OpenSSL based Authenticode signing for PE, CAB, CAT, MSI, APPX and script files")
|
||||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
set(CPACK_PACKAGE_INSTALL_DIRECTORY ${CPACK_PACKAGE_NAME})
|
||||||
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
|
||||||
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.txt")
|
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING.txt")
|
||||||
@@ -25,3 +25,12 @@ list(APPEND CPACK_SOURCE_IGNORE_FILES "/build/")
|
|||||||
|
|
||||||
include(CPack)
|
include(CPack)
|
||||||
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
# documentation with Pandoc
|
||||||
|
# cmake --build .
|
||||||
|
|
||||||
|
find_program(PANDOC pandoc)
|
||||||
|
|
||||||
|
if(NOT PANDOC)
|
||||||
|
message(WARNING "CMakeDoc: pandoc not found, documentation disabled")
|
||||||
|
return()
|
||||||
|
endif(NOT PANDOC)
|
||||||
|
|
||||||
|
set(DOC_MD "${PROJECT_SOURCE_DIR}/osslsigncode.md")
|
||||||
|
|
||||||
|
if(NOT EXISTS "${DOC_MD}")
|
||||||
|
message(WARNING "CMakeDoc: markdown source not found: ${DOC_MD}")
|
||||||
|
return()
|
||||||
|
endif(NOT EXISTS "${DOC_MD}")
|
||||||
|
|
||||||
|
set(MAN_PAGE "${PROJECT_BINARY_DIR}/osslsigncode.1")
|
||||||
|
set(HTML_PAGE "${PROJECT_BINARY_DIR}/osslsigncode.html")
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${MAN_PAGE}"
|
||||||
|
COMMAND "${PANDOC}" -s "${DOC_MD}" -t man -o "${MAN_PAGE}"
|
||||||
|
DEPENDS "${DOC_MD}"
|
||||||
|
COMMENT "CMakeDoc: generating man page"
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT "${HTML_PAGE}"
|
||||||
|
COMMAND "${PANDOC}" -s --toc --toc-depth=2 "${DOC_MD}" -t html -o "${HTML_PAGE}"
|
||||||
|
DEPENDS "${DOC_MD}"
|
||||||
|
COMMENT "CMakeDoc: generating HTML documentation"
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_target(docs ALL DEPENDS "${MAN_PAGE}" "${HTML_PAGE}")
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
+601
-286
@@ -1,298 +1,613 @@
|
|||||||
# make test
|
# make test
|
||||||
# ctest -C Release
|
# ctest -C Release
|
||||||
|
|
||||||
|
########## Configure ##########
|
||||||
|
|
||||||
include(FindPython3)
|
include(FindPython3)
|
||||||
enable_testing()
|
|
||||||
|
|
||||||
set(FILES "${PROJECT_BINARY_DIR}/Testing/files")
|
|
||||||
set(CERTS "${PROJECT_BINARY_DIR}/Testing/certs")
|
|
||||||
set(CONF "${PROJECT_BINARY_DIR}/Testing/conf")
|
|
||||||
|
|
||||||
file(COPY
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/files"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/conf"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/tsa_server.py"
|
|
||||||
DESTINATION "${PROJECT_BINARY_DIR}/Testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
file(COPY
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/tests/certs/ca-bundle.crt"
|
|
||||||
DESTINATION "${CONF}"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(priv_p12 "-pkcs12" "${CERTS}/cert.p12" "-readpass" "${CERTS}/password.txt")
|
|
||||||
set(priv_spc "-certs" "${CERTS}/cert.spc" "-key" "${CERTS}/key.pvk" "-pass" "passme")
|
|
||||||
set(priv_der "-certs" "${CERTS}/cert.pem" "-key" "${CERTS}/key.der" "-pass" "passme")
|
|
||||||
set(priv_pkey "-certs" "${CERTS}/cert.pem" "-key" "${CERTS}/keyp.pem" "-pass" "passme")
|
|
||||||
set(sign_opt "-time" "1556708400"
|
|
||||||
"-add-msi-dse" "-comm" "-ph" "-jp" "low"
|
|
||||||
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
|
||||||
"-n" "osslsigncode" "-ac" "${CERTS}/crosscert.pem"
|
|
||||||
)
|
|
||||||
|
|
||||||
if(NOT CMAKE_HOST_WIN32)
|
|
||||||
execute_process(
|
|
||||||
COMMAND "${CONF}/makecerts.sh"
|
|
||||||
WORKING_DIRECTORY ${CONF}
|
|
||||||
OUTPUT_VARIABLE makecerts_output
|
|
||||||
RESULT_VARIABLE makecerts_result
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
set(makecerts_result 1)
|
|
||||||
endif()
|
|
||||||
if(makecerts_result)
|
|
||||||
message(STATUS "makecerts.sh failed")
|
|
||||||
if(makecerts_output)
|
|
||||||
message(STATUS "${makecerts_output}")
|
|
||||||
endif()
|
|
||||||
file(COPY "${CMAKE_CURRENT_SOURCE_DIR}/tests/certs"
|
|
||||||
DESTINATION "${PROJECT_BINARY_DIR}/Testing"
|
|
||||||
)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
execute_process(
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E sha256sum "${CERTS}/cert.der"
|
|
||||||
OUTPUT_VARIABLE sha256sum
|
|
||||||
)
|
|
||||||
string(SUBSTRING ${sha256sum} 0 64 leafhash)
|
|
||||||
set(verify_opt "-CAfile" "${CERTS}/CACert.pem"
|
|
||||||
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
|
||||||
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
|
||||||
)
|
|
||||||
set(extensions_4 "exe" "ex_" "msi" "cat")
|
|
||||||
set(extensions_3 "exe" "ex_" "msi")
|
|
||||||
set(files_4 "signed" "nested" "added")
|
|
||||||
set(files_3 "removed" "attached_pem" "attached_der")
|
|
||||||
set(sign_formats "pem" "der")
|
|
||||||
set(pem_certs "cert" "expired" "revoked")
|
|
||||||
set(failed_certs "expired" "revoked")
|
|
||||||
|
|
||||||
add_test(
|
|
||||||
NAME version
|
|
||||||
COMMAND osslsigncode --version
|
|
||||||
)
|
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
# Signing time: May 1 00:00:00 2019 GMT
|
|
||||||
set(sign_${ext} )
|
|
||||||
add_test(
|
|
||||||
NAME signed_${ext}
|
|
||||||
COMMAND osslsigncode "sign" ${sign_opt} ${priv_p12}
|
|
||||||
"-in" "${FILES}/unsigned.${ext}" "-out" "${FILES}/signed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
add_test(
|
|
||||||
NAME removed_${ext}
|
|
||||||
COMMAND osslsigncode "remove-signature"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/removed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
add_test(
|
|
||||||
NAME extract_pem_${ext}
|
|
||||||
COMMAND osslsigncode "extract-signature" "-pem"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/${ext}.pem"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
add_test(
|
|
||||||
NAME extract_der_${ext}
|
|
||||||
COMMAND osslsigncode "extract-signature"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/${ext}.der"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
set_tests_properties(removed_${ext} extract_pem_${ext} extract_der_${ext}
|
|
||||||
PROPERTIES DEPENDS sign_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
foreach(format ${sign_formats})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
add_test(
|
|
||||||
NAME attached_${format}_${ext}
|
|
||||||
COMMAND osslsigncode "attach-signature" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
|
||||||
"-add-msi-dse" "-h" "sha512" "-nest"
|
|
||||||
"-sigin" "${FILES}/${ext}.${format}"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/attached_${format}.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(attached_${format}_${ext} PROPERTIES
|
|
||||||
DEPENDS extract_pem_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
|
||||||
REQUIRED_FILES "${FILES}/${ext}.${format}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
add_test(
|
|
||||||
NAME added_${ext}
|
|
||||||
COMMAND osslsigncode "add"
|
|
||||||
"-addUnauthenticatedBlob" "-add-msi-dse" "-h" "sha512"
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/added.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(added_${ext} PROPERTIES
|
|
||||||
DEPENDS sign_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
add_test(
|
|
||||||
NAME nested_${ext}
|
|
||||||
COMMAND osslsigncode "sign" "-nest" ${sign_opt} ${priv_der}
|
|
||||||
"-in" "${FILES}/signed.${ext}" "-out" "${FILES}/nested.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(nested_${ext} PROPERTIES
|
|
||||||
DEPENDS sign_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/signed.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
|
|
||||||
foreach(file ${files_4})
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
add_test(
|
|
||||||
NAME verify_${file}_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
|
||||||
"-in" "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_${file}_${ext} PROPERTIES
|
|
||||||
DEPENDS ${file}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(file ${files_3})
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
|
||||||
add_test(
|
|
||||||
NAME verify_${file}_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-require-leaf-hash" "SHA256:${leafhash}"
|
|
||||||
"-in" "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_${file}_${ext} PROPERTIES
|
|
||||||
DEPENDS ${file}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/${file}.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_3})
|
|
||||||
set_tests_properties(verify_removed_${ext} PROPERTIES
|
|
||||||
WILL_FAIL TRUE
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
|
|
||||||
if(Python3_FOUND)
|
if(Python3_FOUND)
|
||||||
foreach(ext ${extensions_4})
|
execute_process(
|
||||||
foreach(cert ${pem_certs})
|
COMMAND ${Python3_EXECUTABLE} "check_cryptography.py"
|
||||||
add_test(
|
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/tests"
|
||||||
NAME sign_ts_${cert}_${ext}
|
OUTPUT_VARIABLE cryptography_output
|
||||||
COMMAND ${Python3_EXECUTABLE} "${PROJECT_BINARY_DIR}/Testing/tsa_server.py"
|
RESULT_VARIABLE cryptography_error)
|
||||||
"--certs" "${CERTS}/${cert}.pem" "--key" "${CERTS}/key.pem"
|
|
||||||
"--input" "${FILES}/unsigned.${ext}" "--output" "${FILES}/ts_${cert}.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
if(NOT cryptography_error)
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
message(STATUS "Using python3-cryptography version ${cryptography_output}")
|
||||||
add_test(
|
option(STOP_SERVER "Stop HTTP server after tests" ON)
|
||||||
NAME verify_ts_cert_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_ts_cert_${ext} PROPERTIES
|
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
# Remove http proxy configuration that may change behavior
|
||||||
foreach(ext ${extensions_4})
|
unset(ENV{HTTP_PROXY})
|
||||||
add_test(
|
unset(ENV{http_proxy})
|
||||||
NAME verify_ts_future_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "2051222400"
|
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_ts_future_${ext} PROPERTIES
|
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
set(TEST_DIR "${PROJECT_BINARY_DIR}/Testing")
|
||||||
# enabled "-ignore-timestamp" option
|
if(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
foreach(ext ${extensions_4})
|
set(OSSLSIGNCODE "${PROJECT_BINARY_DIR}/${CMAKE_BUILD_TYPE}/osslsigncode")
|
||||||
add_test(
|
else(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
NAME verify_ts_ignore_${ext}
|
set(OSSLSIGNCODE "${PROJECT_BINARY_DIR}/osslsigncode")
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
endif(CMAKE_GENERATOR STREQUAL "Ninja Multi-Config")
|
||||||
"-time" "2051222400"
|
set(EXEC "${TEST_DIR}/exec.py")
|
||||||
"-ignore-timestamp"
|
set(FILES "${TEST_DIR}/files")
|
||||||
"-in" "${FILES}/ts_cert.${ext}"
|
set(CERTS "${TEST_DIR}/certs")
|
||||||
)
|
set(CONF "${TEST_DIR}/conf")
|
||||||
set_tests_properties(verify_ts_ignore_${ext} PROPERTIES
|
set(LOGS "${TEST_DIR}/logs")
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/ts_cert.${ext}"
|
|
||||||
WILL_FAIL TRUE
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
file(MAKE_DIRECTORY "${LOGS}")
|
||||||
# Certificate has expired or revoked
|
|
||||||
foreach(ext ${extensions_4})
|
|
||||||
foreach(cert ${failed_certs})
|
|
||||||
add_test(
|
|
||||||
NAME verify_ts_${cert}_${ext}
|
|
||||||
COMMAND osslsigncode "verify" ${verify_opt}
|
|
||||||
"-time" "1567296000"
|
|
||||||
"-in" "${FILES}/ts_${cert}.${ext}"
|
|
||||||
)
|
|
||||||
set_tests_properties(verify_ts_${cert}_${ext} PROPERTIES
|
|
||||||
DEPENDS sign_ts_${cert}_${ext}
|
|
||||||
REQUIRED_FILES "${FILES}/ts_${cert}.${ext}"
|
|
||||||
WILL_FAIL TRUE
|
|
||||||
)
|
|
||||||
endforeach()
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
else()
|
file(COPY
|
||||||
message(STATUS "Python3 was not found, skip timestamping tests")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/certs/ca-bundle.crt"
|
||||||
endif()
|
DESTINATION "${CONF}")
|
||||||
|
|
||||||
foreach(ext ${extensions_4})
|
file(COPY
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/files"
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/nested.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/conf"
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/removed.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/client_http.py"
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/added.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/make_certificates.py"
|
||||||
foreach(cert ${pem_certs})
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/start_server.py"
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/ts_${cert}.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/exec.py"
|
||||||
endforeach()
|
DESTINATION "${TEST_DIR}/")
|
||||||
foreach(format ${sign_formats})
|
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
if(UNIX)
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
file(COPY
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_${format}.${ext}")
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/server_http.py"
|
||||||
endforeach()
|
DESTINATION "${TEST_DIR}/")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jreq.tsq")
|
set(SERVER_HTTP "${TEST_DIR}/server_http.py")
|
||||||
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jresp.tsr")
|
set(Python3w_EXECUTABLE ${Python3_EXECUTABLE})
|
||||||
endforeach()
|
else(UNIX)
|
||||||
add_test(NAME remove_files COMMAND ${CMAKE_COMMAND} -E rm -f ${OUTPUT_FILES})
|
file(COPY
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/tests/server_http.pyw"
|
||||||
|
DESTINATION "${TEST_DIR}/")
|
||||||
|
set(SERVER_HTTP "${TEST_DIR}/server_http.pyw")
|
||||||
|
get_filename_component(PYTHON_DIRECTORY ${Python3_EXECUTABLE} DIRECTORY)
|
||||||
|
set(Python3w_EXECUTABLE "${PYTHON_DIRECTORY}/pythonw.exe")
|
||||||
|
endif(UNIX)
|
||||||
|
|
||||||
|
if(EXISTS "${LOGS}/url.log")
|
||||||
|
# Stop HTTP server if running
|
||||||
|
message(STATUS "Try to kill HTTP server")
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/client_http.py"
|
||||||
|
OUTPUT_VARIABLE client_output
|
||||||
|
RESULT_VARIABLE client_result)
|
||||||
|
if(NOT client_result)
|
||||||
|
# Successfully closed
|
||||||
|
message(STATUS "${client_output}")
|
||||||
|
endif(NOT client_result)
|
||||||
|
endif(EXISTS "${LOGS}/url.log")
|
||||||
|
|
||||||
|
set(extensions_all "exe" "ex_" "msi" "256appx" "512appx" "cat" "ps1" "psc1" "mof" "js")
|
||||||
|
set(extensions_nocat "exe" "ex_" "msi" "256appx" "512appx" "ps1" "psc1" "mof" "js")
|
||||||
|
set(extensions_nocatappx "exe" "ex_" "msi" "ps1" "psc1" "mof" "js")
|
||||||
|
set(formats "pem" "der")
|
||||||
|
|
||||||
|
else(NOT cryptography_error)
|
||||||
|
message(STATUS "CTest skips tests: ${cryptography_output}")
|
||||||
|
endif(NOT cryptography_error)
|
||||||
|
|
||||||
|
else(Python3_FOUND)
|
||||||
|
message(STATUS "CTest skips tests: Python3 not found")
|
||||||
|
endif(Python3_FOUND)
|
||||||
|
|
||||||
|
|
||||||
|
########## Testing ##########
|
||||||
|
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
### osslsigncode version ###
|
||||||
|
if(Python3_FOUND AND NOT cryptography_error)
|
||||||
|
|
||||||
|
### Start ###
|
||||||
|
add_test(NAME "version"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE}
|
||||||
|
"--version")
|
||||||
|
|
||||||
|
add_test(NAME "start_server"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/start_server.py"
|
||||||
|
"--exe" ${Python3w_EXECUTABLE}
|
||||||
|
"--script" ${SERVER_HTTP})
|
||||||
|
set_tests_properties("start_server" PROPERTIES
|
||||||
|
TIMEOUT 60)
|
||||||
|
set(ALL_TESTS "version" "start_server")
|
||||||
|
|
||||||
|
### Sign ###
|
||||||
|
|
||||||
|
# Sign with PKCS#12 container with private key and certificate encryption algorithm
|
||||||
|
# Signing time: May 1 00:00:00 2019 GMT (1556668800)
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "signed_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/signed.${ext}")
|
||||||
|
set_tests_properties("signed_${ext}" PROPERTIES
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "signed_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Sign with revoked certificate
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "revoked_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-certs" "${CERTS}/revoked.pem"
|
||||||
|
"-key" "${CERTS}/keyp.pem"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha512" "-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/revoked.${ext}")
|
||||||
|
set_tests_properties("revoked_${ext}" PROPERTIES
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "revoked_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Remove signature
|
||||||
|
# Unsupported command for CAT files
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
add_test(NAME "removed_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "remove-signature"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/removed.${ext}")
|
||||||
|
set_tests_properties("removed_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "removed_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
|
# Extract PKCS#7 signature in PEM format
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "extract_pem_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-signature"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/${ext}.pem")
|
||||||
|
set_tests_properties("extract_pem_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "extract_pem_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Extract PKCS#7 signature in default DER format
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "extract_der_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-signature"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/${ext}.der")
|
||||||
|
set_tests_properties("extract_der_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "extract_der_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Attach a nested signature in PEM or DER format
|
||||||
|
# Unsupported command for CAT files
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
foreach(format ${formats})
|
||||||
|
add_test(NAME "attached_${format}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "attach-signature"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-h" "sha512"
|
||||||
|
"-nest"
|
||||||
|
"-sigin" "${FILES}/${ext}.${format}"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/attached_${format}.${ext}")
|
||||||
|
set_tests_properties("attached_${format}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext};extract_pem_${ext};extract_der_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "attached_${format}_${ext}")
|
||||||
|
endforeach(format ${formats})
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
|
# Add an unauthenticated blob to a previously-signed file
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "added_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "add"
|
||||||
|
"-addUnauthenticatedBlob"
|
||||||
|
"-blobFile" "${FILES}/unsigned.exe"
|
||||||
|
"-add-msi-dse" "-h" "sha512"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/added.${ext}")
|
||||||
|
set_tests_properties("added_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "added_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Add the new nested signature instead of replacing the first one
|
||||||
|
# APPX files do not support nesting (multiple signature)
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "nested_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-nest"
|
||||||
|
"-certs" "${CERTS}/cert.pem"
|
||||||
|
"-key" "${CERTS}/key.der"
|
||||||
|
"-pass" "passme"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556755200" # Signing time: May 2 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha512"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/signed.${ext}"
|
||||||
|
"-out" "${FILES}/nested.${ext}")
|
||||||
|
set_tests_properties("nested_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "nested_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
|
### Verify signature ###
|
||||||
|
|
||||||
|
# Verify PE/MSI/CAB files signed in the catalog file
|
||||||
|
# CAT and APPX files do not support detached PKCS#7 signature
|
||||||
|
foreach(ext ${extensions_nocatappx})
|
||||||
|
add_test(NAME "verify_catalog_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-catalog" "${FILES}/signed.cat" # catalog file
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-require-leaf-hash" "FILE ${CERTS}/leafhash.txt"
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}")
|
||||||
|
set_tests_properties("verify_catalog_${ext}" PROPERTIES
|
||||||
|
DEPENDS "signed_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_catalog_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocatappx})
|
||||||
|
|
||||||
|
# Verify signature
|
||||||
|
set(files "signed" "nested" "added" "revoked")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# "revoked" tests are expected to fail
|
||||||
|
set(files "revoked")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# Verify removed signature
|
||||||
|
# "removed" tests are expected to fail
|
||||||
|
# "remove-signature" command is unsupported for CAT files
|
||||||
|
set(files "removed")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
# Verify attached signature
|
||||||
|
# "attach-signature" command is unsupported for CAT files
|
||||||
|
set(files "attached_pem" "attached_der")
|
||||||
|
foreach(file ${files})
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
add_test(NAME "verify_${file}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-in" "${FILES}/${file}.${ext}")
|
||||||
|
set_tests_properties("verify_${file}_${ext}" PROPERTIES
|
||||||
|
DEPENDS "${file}_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_${file}_${ext}")
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
endforeach(file ${files})
|
||||||
|
|
||||||
|
|
||||||
|
### Extract a data content to be signed ###
|
||||||
|
|
||||||
|
# Unsupported command "extract-data" for CAT files
|
||||||
|
foreach(ext ${extensions_nocat})
|
||||||
|
# Extract PKCS#7 with data content, output in PEM format
|
||||||
|
add_test(NAME "data_${ext}_pem"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-data"
|
||||||
|
"-ph"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/data_${ext}.pem")
|
||||||
|
|
||||||
|
# Extract PKCS#7 with data content, output in default DER format
|
||||||
|
add_test(NAME "data_${ext}_der"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "extract-data"
|
||||||
|
"-ph"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/data_${ext}.der")
|
||||||
|
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
set_tests_properties("data_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "data_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Sign a data content, output in DER format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
add_test(NAME "signed_data_${ext}_${data_format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-in" "${FILES}/data_${ext}.${data_format}"
|
||||||
|
"-out" "${FILES}/signed_data_${ext}_${data_format}.der")
|
||||||
|
set_tests_properties("signed_data_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "data_${ext}_pem;data_${ext}_der")
|
||||||
|
list(APPEND ALL_TESTS "signed_data_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Sign a data content, output in PEM format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
add_test(NAME "signed_data_pem_${ext}_${data_format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-pkcs12" "${CERTS}/cert.p12"
|
||||||
|
"-readpass" "${CERTS}/password.txt"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-pem" # PEM format
|
||||||
|
"-in" "${FILES}/data_${ext}.${data_format}"
|
||||||
|
"-out" "${FILES}/signed_data_${ext}_${data_format}.pem")
|
||||||
|
set_tests_properties("signed_data_pem_${ext}_${data_format}" PROPERTIES
|
||||||
|
DEPENDS "data_${ext}_${data_format}")
|
||||||
|
list(APPEND ALL_TESTS "signed_data_pem_${ext}_${data_format}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
|
||||||
|
# Attach signature in PEM or DER format
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
foreach(format ${formats})
|
||||||
|
add_test(NAME "attached_data_${ext}_${data_format}_${format}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "attach-signature"
|
||||||
|
"-add-msi-dse"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-sigin" "${FILES}/signed_data_${ext}_${data_format}.${format}"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/attached_data_${data_format}_${format}.${ext}")
|
||||||
|
set_tests_properties("attached_data_${ext}_${data_format}_${format}" PROPERTIES
|
||||||
|
DEPENDS "signed_data_${ext}_${data_format};signed_data_pem_${ext}_${data_format}")
|
||||||
|
list(APPEND ALL_TESTS "attached_data_${ext}_${data_format}_${format}")
|
||||||
|
endforeach(format ${formats})
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
endforeach(ext ${extensions_nocat})
|
||||||
|
|
||||||
|
|
||||||
|
if(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
|
||||||
|
### Sign with Time-Stamp Authority ###
|
||||||
|
|
||||||
|
# Sign with the RFC3161 Time-Stamp Authority
|
||||||
|
set(pem_certs "cert" "expired" "revoked")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
foreach(cert ${pem_certs})
|
||||||
|
add_test(NAME "sign_ts_${cert}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "sign"
|
||||||
|
"-certs" "${CERTS}/${cert}.pem"
|
||||||
|
"-key" "${CERTS}/key.pem"
|
||||||
|
"-ac" "${CERTS}/CAcross.pem"
|
||||||
|
"-comm"
|
||||||
|
"-ph"
|
||||||
|
"-jp" "low"
|
||||||
|
"-h" "sha384"
|
||||||
|
"-i" "https://www.osslsigncode.com/"
|
||||||
|
"-n" "osslsigncode"
|
||||||
|
"-time" "1556668800" # Signing time: May 1 00:00:00 2019 GMT
|
||||||
|
"-ts" "FILE ${LOGS}/url.log"
|
||||||
|
"-in" "${FILES}/unsigned.${ext}"
|
||||||
|
"-out" "${FILES}/ts_${cert}.${ext}")
|
||||||
|
set_tests_properties("sign_ts_${cert}_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy="
|
||||||
|
DEPENDS "start_server")
|
||||||
|
list(APPEND ALL_TESTS "sign_ts_${cert}_${ext}")
|
||||||
|
endforeach(cert ${pem_certs})
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
|
### Verify Time-Stamp Authority ###
|
||||||
|
|
||||||
|
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_cert_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
|
set_tests_properties("verify_ts_cert_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_cert_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_future_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "2051222400" # Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
|
set_tests_properties("verify_ts_future_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_future_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Verify with ignored timestamp
|
||||||
|
# This tests are expected to fail
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_ignore_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "2051222400" # Signature verification time: Jan 1 00:00:00 2035 GMT
|
||||||
|
"-ignore-timestamp"
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
|
set_tests_properties("verify_ts_ignore_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_cert_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_ignore_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
|
||||||
|
### Verify CRL Distribution Points ###
|
||||||
|
|
||||||
|
# Verify file signed with X509v3 CRL Distribution Points extension
|
||||||
|
# Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_cert_crldp_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_cert.${ext}")
|
||||||
|
set_tests_properties("verify_ts_cert_crldp_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_cert_${ext}")
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_cert_crldp_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Verify with expired or revoked certificate, ignore X509v3 CRL Distribution Points extension
|
||||||
|
# This tests are expected to fail
|
||||||
|
set(failed_certs "expired" "revoked")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
foreach(cert ${failed_certs})
|
||||||
|
add_test(NAME "verify_ts_${cert}_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-CRLfile" "${CERTS}/CACertCRL.pem"
|
||||||
|
"-ignore-cdp"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_${cert}.${ext}")
|
||||||
|
set_tests_properties("verify_ts_${cert}_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_${cert}_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_${cert}_${ext}")
|
||||||
|
endforeach(cert ${failed_certs})
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
# Verify with revoked certificate contains X509v3 CRL Distribution Points extension
|
||||||
|
# Check X509v3 CRL Distribution Points extension, don't use "-CRLfile" and "-TSA-CRLfile" options
|
||||||
|
# This test is expected to fail
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
add_test(NAME "verify_ts_revoked_crldp_${ext}"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} ${EXEC} ${OSSLSIGNCODE} "verify"
|
||||||
|
"-time" "1567296000" # Signature verification time: Sep 1 00:00:00 2019 GMT
|
||||||
|
"-CAfile" "${CERTS}/CACert.pem"
|
||||||
|
"-TSA-CAfile" "${CERTS}/TSACA.pem"
|
||||||
|
"-in" "${FILES}/ts_revoked.${ext}")
|
||||||
|
set_tests_properties("verify_ts_revoked_crldp_${ext}" PROPERTIES
|
||||||
|
ENVIRONMENT "HTTP_PROXY=;http_proxy=;"
|
||||||
|
DEPENDS "sign_ts_revoked_${ext}"
|
||||||
|
WILL_FAIL TRUE)
|
||||||
|
list(APPEND ALL_TESTS "verify_ts_revoked_crldp_${ext}")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
### Cleanup ###
|
||||||
|
# Stop HTTP server
|
||||||
|
if(STOP_SERVER)
|
||||||
|
add_test(NAME "stop_server"
|
||||||
|
COMMAND ${Python3_EXECUTABLE} "${TEST_DIR}/client_http.py")
|
||||||
|
set_tests_properties("stop_server" PROPERTIES
|
||||||
|
DEPENDS "${ALL_TESTS}")
|
||||||
|
list(APPEND ALL_TESTS "stop_server")
|
||||||
|
else(STOP_SERVER)
|
||||||
|
message(STATUS "Keep HTTP server after tests")
|
||||||
|
endif(STOP_SERVER)
|
||||||
|
|
||||||
|
else(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
message(STATUS "CTest skips some tests")
|
||||||
|
endif(OPENSSL_VERSION VERSION_GREATER_EQUAL "3.0.0" OR CURL_FOUND)
|
||||||
|
|
||||||
|
# Delete test files
|
||||||
|
set(names "signed" "nested" "revoked" "removed" "added")
|
||||||
|
foreach(ext ${extensions_all})
|
||||||
|
foreach(name ${names})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${name}.${ext}")
|
||||||
|
endforeach(name ${names})
|
||||||
|
foreach(cert ${pem_certs})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/ts_${cert}.${ext}")
|
||||||
|
endforeach(cert ${pem_certs})
|
||||||
|
foreach(format ${formats})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/${ext}.${format}")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_${format}.${ext}")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/data_${ext}.${format}")
|
||||||
|
foreach(data_format ${formats})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/signed_data_${ext}_${format}.${data_format}")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/attached_data_${data_format}_${format}.${ext}")
|
||||||
|
endforeach(data_format ${formats})
|
||||||
|
endforeach(format ${formats})
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jreq.tsq")
|
||||||
|
set(OUTPUT_FILES ${OUTPUT_FILES} "${FILES}/jresp.tsr")
|
||||||
|
endforeach(ext ${extensions_all})
|
||||||
|
|
||||||
|
add_test(NAME "remove_files"
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E rm -f ${OUTPUT_FILES})
|
||||||
|
|
||||||
|
set_tests_properties("remove_files" PROPERTIES
|
||||||
|
DEPENDS "${ALL_TESTS}")
|
||||||
|
|
||||||
|
endif(Python3_FOUND AND NOT cryptography_error)
|
||||||
|
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
+21
-17
@@ -1,22 +1,26 @@
|
|||||||
include(CheckIncludeFile)
|
include(CheckIncludeFile)
|
||||||
include(CheckFunctionExists)
|
include(CheckFunctionExists)
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(UNIX)
|
||||||
check_function_exists(getpass HAVE_GETPASS)
|
check_function_exists(getpass HAVE_GETPASS)
|
||||||
check_include_file(termios.h HAVE_TERMIOS_H)
|
check_include_file(termios.h HAVE_TERMIOS_H)
|
||||||
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
|
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
|
||||||
if(HAVE_SYS_MMAN_H)
|
if(HAVE_SYS_MMAN_H)
|
||||||
check_function_exists(mmap HAVE_MMAP)
|
check_function_exists(mmap HAVE_MMAP)
|
||||||
if(NOT HAVE_MMAP)
|
endif(HAVE_SYS_MMAN_H)
|
||||||
message(FATAL_ERROR "Error: Need mmap to build.")
|
else(UNIX)
|
||||||
endif()
|
check_include_file(windows.h HAVE_MAPVIEWOFFILE)
|
||||||
endif()
|
endif(UNIX)
|
||||||
endif()
|
|
||||||
|
|
||||||
# include wincrypt.h in Windows.h
|
if(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
||||||
if(MSVC AND NOT CYGWIN)
|
|
||||||
check_include_file(windows.h HAVE_MAPVIEWOFFILE)
|
|
||||||
if(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
|
||||||
message(FATAL_ERROR "Error: Need file mapping function to build.")
|
message(FATAL_ERROR "Error: Need file mapping function to build.")
|
||||||
endif()
|
endif(NOT (HAVE_MMAP OR HAVE_MAPVIEWOFFILE))
|
||||||
endif()
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
@@ -1,13 +1,32 @@
|
|||||||
|
# This list describes the default variables included in the bash-completion package:
|
||||||
|
# BASH_COMPLETION_VERSION "@VERSION@"
|
||||||
|
# BASH_COMPLETION_PREFIX "@prefix@"
|
||||||
|
# BASH_COMPLETION_COMPATDIR "@sysconfdir@/bash_completion.d"
|
||||||
|
# BASH_COMPLETION_COMPLETIONSDIR "@datadir@/@PACKAGE@/completions"
|
||||||
|
# BASH_COMPLETION_HELPERSDIR "@datadir@/@PACKAGE@/helpers"
|
||||||
|
# BASH_COMPLETION_FOUND "TRUE"
|
||||||
|
# https://github.com/scop/bash-completion/blob/master/bash-completion-config.cmake.in
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
find_package(bash-completion QUIET)
|
if(BASH_COMPLETION_USER_DIR)
|
||||||
if(NOT BASH_COMPLETION_COMPLETIONSDIR)
|
set(BASH_COMPLETION_COMPLETIONSDIR "${BASH_COMPLETION_USER_DIR}/bash-completion/completions")
|
||||||
if(BASH_COMPLETION_COMPATDIR)
|
else(BASH_COMPLETION_USER_DIR)
|
||||||
set(BASH_COMPLETION_COMPLETIONSDIR ${BASH_COMPLETION_COMPATDIR})
|
find_package(bash-completion QUIET)
|
||||||
else()
|
if(NOT BASH_COMPLETION_FOUND)
|
||||||
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share")
|
set(SHAREDIR "${CMAKE_INSTALL_PREFIX}/share")
|
||||||
set(BASH_COMPLETION_COMPLETIONSDIR "${SHAREDIR}/bash-completion/completions")
|
set(BASH_COMPLETION_COMPLETIONSDIR "${SHAREDIR}/bash-completion/completions")
|
||||||
endif()
|
endif(NOT BASH_COMPLETION_FOUND)
|
||||||
endif()
|
endif(BASH_COMPLETION_USER_DIR)
|
||||||
message(STATUS "Using bash completions dir ${BASH_COMPLETION_COMPLETIONSDIR}")
|
|
||||||
install(FILES "osslsigncode.bash" DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR})
|
message(STATUS "Using bash completions dir ${BASH_COMPLETION_COMPLETIONSDIR}")
|
||||||
endif()
|
install(FILES "osslsigncode.bash" DESTINATION ${BASH_COMPLETION_COMPLETIONSDIR})
|
||||||
|
endif(NOT MSVC)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
+107
-100
@@ -3,109 +3,116 @@ include(CheckCCompilerFlag)
|
|||||||
set(CMAKE_REQUIRED_QUIET ON)
|
set(CMAKE_REQUIRED_QUIET ON)
|
||||||
|
|
||||||
function(add_debug_flag_if_supported flagname targets)
|
function(add_debug_flag_if_supported flagname targets)
|
||||||
check_c_compiler_flag("${flagname}" HAVE_FLAG_${flagname})
|
check_c_compiler_flag("${flagname}" HAVE_FLAG_${flagname})
|
||||||
if (HAVE_FLAG_${flagname})
|
if (HAVE_FLAG_${flagname})
|
||||||
foreach(target ${targets})
|
foreach(target ${targets})
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:${flagname}>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:${flagname}>)
|
||||||
endforeach()
|
endforeach(target ${targets})
|
||||||
endif()
|
endif(HAVE_FLAG_${flagname})
|
||||||
endfunction()
|
endfunction(add_debug_flag_if_supported flagname targets)
|
||||||
|
|
||||||
function(add_compile_flag_to_targets targets)
|
function(add_compile_flag_to_targets targets)
|
||||||
set(CHECKED_DEBUG_FLAGS
|
set(CHECKED_DEBUG_FLAGS
|
||||||
"-ggdb"
|
"-ggdb"
|
||||||
"-g"
|
"-g"
|
||||||
"-O2"
|
"-O2"
|
||||||
"-pedantic"
|
"-pedantic"
|
||||||
"-Wall"
|
"-Wall"
|
||||||
"-Wextra"
|
"-Wextra"
|
||||||
"-Wno-long-long"
|
"-Wno-long-long"
|
||||||
"-Wconversion"
|
"-Wconversion"
|
||||||
"-D_FORTIFY_SOURCE=2"
|
"-D_FORTIFY_SOURCE=2"
|
||||||
"-Wformat=2"
|
"-Wformat=2"
|
||||||
"-Wredundant-decls"
|
"-Wredundant-decls"
|
||||||
"-Wcast-qual"
|
"-Wcast-qual"
|
||||||
"-Wnull-dereference"
|
"-Wnull-dereference"
|
||||||
"-Wno-deprecated-declarations"
|
"-Wno-deprecated-declarations"
|
||||||
"-Wmissing-declarations"
|
"-Wmissing-declarations"
|
||||||
"-Wmissing-prototypes"
|
"-Wmissing-prototypes"
|
||||||
"-Wmissing-noreturn"
|
"-Wmissing-noreturn"
|
||||||
"-Wmissing-braces"
|
"-Wmissing-braces"
|
||||||
"-Wparentheses"
|
"-Wparentheses"
|
||||||
"-Wstrict-aliasing=3"
|
"-Wstrict-aliasing=3"
|
||||||
"-Wstrict-overflow=2"
|
"-Wstrict-overflow=2"
|
||||||
"-Wlogical-op"
|
"-Wlogical-op"
|
||||||
"-Wwrite-strings"
|
"-Wwrite-strings"
|
||||||
"-Wcast-align=strict"
|
"-Wcast-align=strict"
|
||||||
"-Wdisabled-optimization"
|
"-Wdisabled-optimization"
|
||||||
"-Wshift-overflow=2"
|
"-Wshift-overflow=2"
|
||||||
"-Wundef"
|
"-Wundef"
|
||||||
"-Wshadow"
|
"-Wshadow"
|
||||||
"-Wmisleading-indentation"
|
"-Wmisleading-indentation"
|
||||||
"-Wabsolute-value"
|
"-Wabsolute-value"
|
||||||
"-Wunused-parameter"
|
"-Wunused-parameter"
|
||||||
"-Wunused-function"
|
"-Wunused-function")
|
||||||
)
|
foreach(flag ${CHECKED_DEBUG_FLAGS})
|
||||||
foreach(flag ${CHECKED_DEBUG_FLAGS})
|
add_debug_flag_if_supported(${flag} ${targets})
|
||||||
add_debug_flag_if_supported(${flag} ${targets})
|
endforeach(flag ${CHECKED_DEBUG_FLAGS})
|
||||||
endforeach()
|
endfunction(add_compile_flag_to_targets targets)
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(add_compile_flags target)
|
function(add_compile_flags target)
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
# Enable parallel builds
|
# Enable parallel builds
|
||||||
target_compile_options(${target} PRIVATE /MP)
|
target_compile_options(${target} PRIVATE /MP)
|
||||||
# Use address space layout randomization, generate PIE code for ASLR (default on)
|
# Use address space layout randomization, generate PIE code for ASLR (default on)
|
||||||
target_link_options(${target} PRIVATE /DYNAMICBASE)
|
target_link_options(${target} PRIVATE /DYNAMICBASE)
|
||||||
# Create terminal server aware application (default on)
|
# Create terminal server aware application (default on)
|
||||||
target_link_options(${target} PRIVATE /TSAWARE)
|
target_link_options(${target} PRIVATE /TSAWARE)
|
||||||
# Mark the binary as compatible with Intel Control-flow Enforcement Technology (CET) Shadow Stack
|
# Mark the binary as compatible with Intel Control-flow Enforcement Technology (CET) Shadow Stack
|
||||||
target_link_options(${target} PRIVATE /CETCOMPAT)
|
target_link_options(${target} PRIVATE /CETCOMPAT)
|
||||||
# Enable compiler generation of Control Flow Guard security checks
|
# Enable compiler generation of Control Flow Guard security checks
|
||||||
target_compile_options(${target} PRIVATE /guard:cf)
|
target_compile_options(${target} PRIVATE /guard:cf)
|
||||||
target_link_options(${target} PRIVATE /guard:cf)
|
target_link_options(${target} PRIVATE /guard:cf)
|
||||||
# Buffer Security Check
|
# Buffer Security Check
|
||||||
target_compile_options(${target} PRIVATE /GS)
|
target_compile_options(${target} PRIVATE /GS)
|
||||||
# Suppress startup banner
|
# Suppress startup banner
|
||||||
target_link_options(${target} PRIVATE /NOLOGO)
|
target_link_options(${target} PRIVATE /NOLOGO)
|
||||||
# Generate debug info
|
# Generate debug info
|
||||||
target_link_options(${target} PRIVATE /DEBUG)
|
target_link_options(${target} PRIVATE /DEBUG)
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
# High entropy ASLR for 64 bits targets (default on)
|
# High entropy ASLR for 64 bits targets (default on)
|
||||||
target_link_options(${target} PRIVATE /HIGHENTROPYVA)
|
target_link_options(${target} PRIVATE /HIGHENTROPYVA)
|
||||||
# Enable generation of EH Continuation (EHCONT) metadata by the compiler
|
# Enable generation of EH Continuation (EHCONT) metadata by the compiler
|
||||||
#target_compile_options(${target} PRIVATE /guard:ehcont)
|
#target_compile_options(${target} PRIVATE /guard:ehcont)
|
||||||
#target_link_options(${target} PRIVATE /guard:ehcont)
|
#target_link_options(${target} PRIVATE /guard:ehcont)
|
||||||
else()
|
else("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
# Can handle addresses larger than 2 gigabytes
|
# Can handle addresses larger than 2 gigabytes
|
||||||
target_link_options(${target} PRIVATE /LARGEADDRESSAWARE)
|
target_link_options(${target} PRIVATE /LARGEADDRESSAWARE)
|
||||||
# Safe structured exception handlers (x86 only)
|
# Safe structured exception handlers (x86 only)
|
||||||
target_link_options(${target} PRIVATE /SAFESEH)
|
target_link_options(${target} PRIVATE /SAFESEH)
|
||||||
endif()
|
endif("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8")
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/D_FORTIFY_SOURCE=2>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/D_FORTIFY_SOURCE=2>)
|
||||||
# Unrecognized compiler options are errors
|
# Unrecognized compiler options are errors
|
||||||
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/options:strict>)
|
target_compile_options(${target} PRIVATE $<$<CONFIG:DEBUG>:/options:strict>)
|
||||||
else()
|
else(MSVC)
|
||||||
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
check_c_compiler_flag("-fstack-protector-all" HAVE_STACK_PROTECTOR_ALL)
|
||||||
if(HAVE_STACK_PROTECTOR_ALL)
|
if(HAVE_STACK_PROTECTOR_ALL)
|
||||||
target_link_options(${target} PRIVATE -fstack-protector-all)
|
target_link_options(${target} PRIVATE -fstack-protector-all)
|
||||||
else()
|
else(HAVE_STACK_PROTECTOR_ALL)
|
||||||
check_c_compiler_flag("-fstack-protector" HAVE_STACK_PROTECTOR)
|
check_c_compiler_flag("-fstack-protector" HAVE_STACK_PROTECTOR)
|
||||||
if(HAVE_STACK_PROTECTOR)
|
if(HAVE_STACK_PROTECTOR)
|
||||||
target_link_options(${target} PRIVATE -fstack-protector)
|
target_link_options(${target} PRIVATE -fstack-protector)
|
||||||
else()
|
else(HAVE_STACK_PROTECTOR)
|
||||||
message(WARNING "No stack protection supported")
|
message(WARNING "No stack protection supported")
|
||||||
endif()
|
endif(HAVE_STACK_PROTECTOR)
|
||||||
endif()
|
endif(HAVE_STACK_PROTECTOR_ALL)
|
||||||
# Support address space layout randomization (ASLR)
|
# Support address space layout randomization (ASLR) / PIE
|
||||||
target_compile_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-fPIE>)
|
if(UNIX AND NOT APPLE)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-fPIE -pie>)
|
target_compile_options(${target} PRIVATE -fPIE)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,relro>)
|
target_link_options(${target} PRIVATE -fPIE -pie -Wl,-z,relro,-z,now,-z,noexecstack)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,now>)
|
endif(UNIX AND NOT APPLE)
|
||||||
target_link_options(${target} PRIVATE $<$<NOT:$<C_COMPILER_ID:AppleClang>>:-Wl,-z,noexecstack>)
|
target_link_options(${target} PRIVATE -fstack-check)
|
||||||
target_link_options(${target} PRIVATE -fstack-check)
|
add_compile_flag_to_targets(${target})
|
||||||
add_compile_flag_to_targets(${target})
|
endif(MSVC)
|
||||||
endif()
|
endfunction(add_compile_flags target)
|
||||||
endfunction()
|
|
||||||
|
|
||||||
add_compile_flags(osslsigncode)
|
add_compile_flags(osslsigncode)
|
||||||
|
|
||||||
|
#[[
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
]]
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# uninstall target
|
||||||
|
#
|
||||||
|
# CMake does not provide a built-in uninstall target.
|
||||||
|
# This target removes files listed in install_manifest.txt,
|
||||||
|
# generated by the install step.
|
||||||
|
#
|
||||||
|
# cmake --build . --target uninstall
|
||||||
|
|
||||||
|
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
|
||||||
|
message(FATAL_ERROR "Cannot find install manifest")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
|
||||||
|
string(REPLACE "\n" ";" files "${files}")
|
||||||
|
|
||||||
|
foreach(file ${files})
|
||||||
|
message(STATUS "Removing ${file}")
|
||||||
|
|
||||||
|
if(EXISTS "${file}" OR IS_SYMLINK "${file}")
|
||||||
|
file(REMOVE "${file}")
|
||||||
|
else()
|
||||||
|
message(STATUS "File does not exist: ${file}")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
+9741
File diff suppressed because it is too large
Load Diff
Executable
+52
@@ -0,0 +1,52 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
# © 2024 Michal Trojnara
|
||||||
|
# This script downloads Microsoft code signing certificates
|
||||||
|
# Tor is required for this script to work
|
||||||
|
# Redirect the script output to a PEM file
|
||||||
|
|
||||||
|
from sys import stderr
|
||||||
|
from time import sleep
|
||||||
|
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):
|
||||||
|
if attempt > 0:
|
||||||
|
sleep(10)
|
||||||
|
try:
|
||||||
|
creds = f'{attempt}{hash}:{attempt}{hash}'
|
||||||
|
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', '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.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=10) as executor:
|
||||||
|
certs = executor.map(download_cert, hashes)
|
||||||
|
for cert in certs:
|
||||||
|
if cert is not None:
|
||||||
|
print(cert)
|
||||||
|
print('\nDone', file=stderr)
|
||||||
@@ -0,0 +1,987 @@
|
|||||||
|
/*
|
||||||
|
* osslsigncode support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
|
/* Prototypes */
|
||||||
|
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx);
|
||||||
|
static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] infile
|
||||||
|
* [returns] file size
|
||||||
|
*/
|
||||||
|
uint32_t get_file_size(const char *infile)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
#ifdef _WIN32
|
||||||
|
struct _stat64 st;
|
||||||
|
ret = _stat64(infile, &st);
|
||||||
|
#else
|
||||||
|
struct stat st;
|
||||||
|
ret = stat(infile, &st);
|
||||||
|
#endif
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Failed to open file: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size < 4) {
|
||||||
|
fprintf(stderr, "Unrecognized file type - file is too short: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (st.st_size > UINT32_MAX) {
|
||||||
|
fprintf(stderr, "Unsupported file - too large: %s\n", infile);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return (uint32_t)st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] infile: starting address for the new mapping
|
||||||
|
* [returns] pointer to the mapped area
|
||||||
|
*/
|
||||||
|
char *map_file(const char *infile, const size_t size)
|
||||||
|
{
|
||||||
|
char *indata = NULL;
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE fhandle, fmap;
|
||||||
|
(void)size;
|
||||||
|
fhandle = CreateFile(infile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
||||||
|
if (fhandle == INVALID_HANDLE_VALUE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
fmap = CreateFileMapping(fhandle, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||||
|
CloseHandle(fhandle);
|
||||||
|
if (fmap == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
indata = (char *)MapViewOfFile(fmap, FILE_MAP_READ, 0, 0, 0);
|
||||||
|
CloseHandle(fmap);
|
||||||
|
#else
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
int fd = open(infile, O_RDONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
indata = mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||||
|
if (indata == MAP_FAILED) {
|
||||||
|
close(fd);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
#else
|
||||||
|
fprintf(stderr, "No file mapping function\n");
|
||||||
|
return NULL;
|
||||||
|
#endif /* HAVE_SYS_MMAN_H */
|
||||||
|
#endif /* WIN32 */
|
||||||
|
return indata;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] indata: starting address space
|
||||||
|
* [in] size: mapped area length
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
void unmap_file(char *indata, const size_t size)
|
||||||
|
{
|
||||||
|
if (!indata)
|
||||||
|
return;
|
||||||
|
#ifdef WIN32
|
||||||
|
(void)size;
|
||||||
|
UnmapViewOfFile(indata);
|
||||||
|
#else
|
||||||
|
munmap(indata, size);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve a decoded PKCS#7 structure
|
||||||
|
* [in] data: encoded PEM or DER data
|
||||||
|
* [in] size: data size
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_read_data(char *data, uint32_t size)
|
||||||
|
{
|
||||||
|
PKCS7 *p7 = NULL;
|
||||||
|
BIO *bio;
|
||||||
|
const char pemhdr[] = "-----BEGIN PKCS7-----";
|
||||||
|
|
||||||
|
bio = BIO_new_mem_buf(data, (int)size);
|
||||||
|
if (size >= sizeof pemhdr && !memcmp(data, pemhdr, sizeof pemhdr - 1)) {
|
||||||
|
/* PEM format */
|
||||||
|
p7 = PEM_read_bio_PKCS7(bio, NULL, NULL, NULL);
|
||||||
|
} else { /* DER format */
|
||||||
|
p7 = d2i_PKCS7_bio(bio, NULL);
|
||||||
|
}
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: BIO outdata file
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
(void)BIO_reset(outdata);
|
||||||
|
if (ctx->options->output_pkcs7) {
|
||||||
|
/* PEM format */
|
||||||
|
ret = !PEM_write_bio_PKCS7(outdata, p7);
|
||||||
|
} else {
|
||||||
|
/* default DER format */
|
||||||
|
ret = !i2d_PKCS7_bio(outdata, p7);
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Unable to write pkcs7 object\n");
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate, set type, add content and return a new PKCS#7 signature
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
int i, signer = -1;
|
||||||
|
PKCS7_SIGNER_INFO *si = NULL;
|
||||||
|
STACK_OF(X509) *chain = NULL;
|
||||||
|
PKCS7 *p7 = PKCS7_new();
|
||||||
|
|
||||||
|
if (!p7)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
PKCS7_set_type(p7, NID_pkcs7_signed);
|
||||||
|
PKCS7_content_new(p7, NID_pkcs7_data);
|
||||||
|
|
||||||
|
/* find the signer's certificate located somewhere in the whole certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
|
||||||
|
X509 *signcert = sk_X509_value(ctx->options->certs, i);
|
||||||
|
|
||||||
|
if (X509_check_private_key(signcert, ctx->options->pkey)) {
|
||||||
|
si = PKCS7_add_signature(p7, signcert, ctx->options->pkey, ctx->options->md);
|
||||||
|
signer = i;
|
||||||
|
if (signer > 0)
|
||||||
|
printf("Warning: For optimal performance, consider placing the signer certificate at the beginning of the certificate chain.\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!si) {
|
||||||
|
fprintf(stderr, "Failed to checking the consistency of a private key: %s\n",
|
||||||
|
ctx->options->keyfile);
|
||||||
|
fprintf(stderr, " with a public key in any X509 certificate: %s\n\n",
|
||||||
|
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
ctx->options->certfile ? ctx->options->certfile : ctx->options->p11cert);
|
||||||
|
#else
|
||||||
|
ctx->options->certfile);
|
||||||
|
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!pkcs7_signer_info_add_signing_time(si, ctx)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if (!pkcs7_signer_info_add_purpose(si, ctx)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if ((ctx->options->desc || ctx->options->url) &&
|
||||||
|
!pkcs7_signer_info_add_spc_sp_opus_info(si, ctx)) {
|
||||||
|
fprintf(stderr, "Couldn't allocate memory for opus info\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
if ((ctx->options->nested_number >= 0) &&
|
||||||
|
!pkcs7_signer_info_add_sequence_number(si, ctx)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* create X509 chain sorted in ascending order by their DER encoding */
|
||||||
|
chain = X509_chain_get_sorted(ctx, signer);
|
||||||
|
if (!chain) {
|
||||||
|
fprintf(stderr, "Failed to create a sorted certificate chain\n");
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
/* add sorted certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(chain); i++) {
|
||||||
|
(void)PKCS7_add_certificate(p7, sk_X509_value(chain, i));
|
||||||
|
}
|
||||||
|
/* add crls */
|
||||||
|
if (ctx->options->crls) {
|
||||||
|
for (i=0; i<sk_X509_CRL_num(ctx->options->crls); i++)
|
||||||
|
(void)PKCS7_add_crl(p7, sk_X509_CRL_value(ctx->options->crls, i));
|
||||||
|
}
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return p7; /* OK */
|
||||||
|
|
||||||
|
err:
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE, MSI, CAB and APPX file specific
|
||||||
|
* Add "1.3.6.1.4.1.311.2.1.4" SPC_INDIRECT_DATA_OBJID signed attribute
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int add_indirect_data_object(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
STACK_OF(PKCS7_SIGNER_INFO) *signer_info;
|
||||||
|
PKCS7_SIGNER_INFO *si;
|
||||||
|
|
||||||
|
signer_info = PKCS7_get_signer_info(p7);
|
||||||
|
if (!signer_info)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
si = sk_PKCS7_SIGNER_INFO_value(signer_info, 0);
|
||||||
|
if (!si)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!PKCS7_add_signed_attribute(si, NID_pkcs9_contentType,
|
||||||
|
V_ASN1_OBJECT, OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1)))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE, MSI, CAB and APPX format specific
|
||||||
|
* Sign the MS Authenticode spcIndirectDataContent blob.
|
||||||
|
* The spcIndirectDataContent structure is used in Authenticode signatures
|
||||||
|
* to store the digest and other attributes of the signed file.
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] content: spcIndirectDataContent
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int sign_spc_indirect_data_content(PKCS7 *p7, ASN1_OCTET_STRING *content)
|
||||||
|
{
|
||||||
|
int len, inf, tag, class;
|
||||||
|
long plen;
|
||||||
|
const u_char *data, *p;
|
||||||
|
PKCS7 *td7;
|
||||||
|
|
||||||
|
p = data = ASN1_STRING_get0_data(content);
|
||||||
|
len = ASN1_STRING_length(content);
|
||||||
|
inf = ASN1_get_object(&p, &plen, &tag, &class, len);
|
||||||
|
if (inf != V_ASN1_CONSTRUCTED || tag != V_ASN1_SEQUENCE
|
||||||
|
|| !pkcs7_sign_content(p7, p, (int)plen)) {
|
||||||
|
fprintf(stderr, "Failed to sign spcIndirectDataContent\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
td7 = PKCS7_new();
|
||||||
|
if (!td7) {
|
||||||
|
fprintf(stderr, "PKCS7_new failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
td7->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1);
|
||||||
|
td7->d.other = ASN1_TYPE_new();
|
||||||
|
td7->d.other->type = V_ASN1_SEQUENCE;
|
||||||
|
td7->d.other->value.sequence = ASN1_STRING_new();
|
||||||
|
ASN1_STRING_set(td7->d.other->value.sequence, data, len);
|
||||||
|
if (!PKCS7_set_content(p7, td7)) {
|
||||||
|
fprintf(stderr, "PKCS7_set_content failed\n");
|
||||||
|
PKCS7_free(td7);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add encapsulated content to signed PKCS7 structure.
|
||||||
|
* [in] content: spcIndirectDataContent
|
||||||
|
* [returns] new PKCS#7 signature with encapsulated content
|
||||||
|
*/
|
||||||
|
PKCS7 *pkcs7_set_content(ASN1_OCTET_STRING *content)
|
||||||
|
{
|
||||||
|
PKCS7 *p7, *td7;
|
||||||
|
|
||||||
|
p7 = PKCS7_new();
|
||||||
|
if (!p7) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_set_type(p7, NID_pkcs7_signed)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!PKCS7_content_new(p7, NID_pkcs7_data)) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
td7 = PKCS7_new();
|
||||||
|
if (!td7) {
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
td7->type = OBJ_txt2obj(SPC_INDIRECT_DATA_OBJID, 1);
|
||||||
|
td7->d.other = ASN1_TYPE_new();
|
||||||
|
td7->d.other->type = V_ASN1_SEQUENCE;
|
||||||
|
td7->d.other->value.sequence = content;
|
||||||
|
if (!PKCS7_set_content(p7, td7)) {
|
||||||
|
PKCS7_free(td7);
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Retrieve the message digest and digest algorithm from PKCS7
|
||||||
|
* SpcIndirectDataContent.
|
||||||
|
*
|
||||||
|
* [in] p7: PKCS7 structure containing SPC_INDIRECT_DATA_OBJID content
|
||||||
|
* [out] mdbuf: message digest buffer, at least EVP_MAX_MD_SIZE bytes
|
||||||
|
* [out] mdtype: OpenSSL NID of the digest algorithm
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int pkcs7_get_content_digest(PKCS7 *p7, u_char *mdbuf, int *mdtype)
|
||||||
|
{
|
||||||
|
SpcIndirectDataContent *idc;
|
||||||
|
|
||||||
|
if (!mdbuf || !mdtype)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
|
||||||
|
*mdtype = -1;
|
||||||
|
|
||||||
|
idc = pkcs7_get_indirect_data_content(p7);
|
||||||
|
if (!idc) {
|
||||||
|
fprintf(stderr, "Failed to decode SpcIndirectDataContent\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
if (*mdtype == -1) {
|
||||||
|
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode SpcIndirectDataContent from a PKCS7 signedData content.
|
||||||
|
*
|
||||||
|
* [in] p7: PKCS7 structure containing SPC_INDIRECT_DATA_OBJID content
|
||||||
|
* [returns] newly allocated SpcIndirectDataContent, or NULL on error
|
||||||
|
*
|
||||||
|
* The caller is responsible for freeing the returned object with
|
||||||
|
* SpcIndirectDataContent_free().
|
||||||
|
*/
|
||||||
|
SpcIndirectDataContent *pkcs7_get_indirect_data_content(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
if (!is_content_type(p7, SPC_INDIRECT_DATA_OBJID))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if (!p7->d.sign || !p7->d.sign->contents || !p7->d.sign->contents->d.other)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return asn1_type_get_indirect_data_content(p7->d.sign->contents->d.other);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Decode SpcIndirectDataContent from an ASN1_TYPE object.
|
||||||
|
* The ASN1_TYPE is expected to contain a V_ASN1_SEQUENCE value.
|
||||||
|
*
|
||||||
|
* [in] content: ASN1_TYPE containing DER-encoded SpcIndirectDataContent
|
||||||
|
* [returns] newly allocated SpcIndirectDataContent, or NULL on error
|
||||||
|
*
|
||||||
|
* The caller is responsible for freeing the returned object with
|
||||||
|
* SpcIndirectDataContent_free().
|
||||||
|
*/
|
||||||
|
SpcIndirectDataContent *asn1_type_get_indirect_data_content(ASN1_TYPE *content)
|
||||||
|
{
|
||||||
|
ASN1_STRING *value;
|
||||||
|
const unsigned char *data;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
if (!content || content->type != V_ASN1_SEQUENCE)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
value = content->value.sequence;
|
||||||
|
if (!value)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
len = ASN1_STRING_length(value);
|
||||||
|
|
||||||
|
return d2i_SpcIndirectDataContent(NULL, &data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return spcIndirectDataContent.
|
||||||
|
* [in] hash: message digest BIO
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] content
|
||||||
|
*/
|
||||||
|
ASN1_OCTET_STRING *spc_indirect_data_content_get(BIO *hash, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
u_char mdbuf[5 * EVP_MAX_MD_SIZE + 24];
|
||||||
|
int mdlen, hashlen, len = 0;
|
||||||
|
u_char *data, *p = NULL;
|
||||||
|
|
||||||
|
content = ASN1_OCTET_STRING_new();
|
||||||
|
if (!content) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!spc_indirect_data_content_create(&p, &len, ctx)) {
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
hashlen = ctx->format->hash_length_get(ctx);
|
||||||
|
if (hashlen > EVP_MAX_MD_SIZE) {
|
||||||
|
/* APPX format specific */
|
||||||
|
mdlen = BIO_read(hash, (char*)mdbuf, hashlen);
|
||||||
|
} else {
|
||||||
|
mdlen = BIO_gets(hash, (char*)mdbuf, EVP_MAX_MD_SIZE);
|
||||||
|
}
|
||||||
|
data = OPENSSL_malloc((size_t)(len + mdlen));
|
||||||
|
memcpy(data, p, (size_t)len);
|
||||||
|
OPENSSL_free(p);
|
||||||
|
memcpy(data + len, mdbuf, (size_t)mdlen);
|
||||||
|
if (!ASN1_OCTET_STRING_set(content, data, len + mdlen)) {
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
OPENSSL_free(data);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(data);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Signs the data and place the signature in p7
|
||||||
|
* [in, out] p7: new PKCS#7 signature
|
||||||
|
* [in] data: content data
|
||||||
|
* [in] len: content length
|
||||||
|
*/
|
||||||
|
int pkcs7_sign_content(PKCS7 *p7, const u_char *data, int len)
|
||||||
|
{
|
||||||
|
BIO *p7bio;
|
||||||
|
|
||||||
|
if ((p7bio = PKCS7_dataInit(p7, NULL)) == NULL) {
|
||||||
|
fprintf(stderr, "PKCS7_dataInit failed\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_write(p7bio, data, len);
|
||||||
|
(void)BIO_flush(p7bio);
|
||||||
|
if (!PKCS7_dataFinal(p7, p7bio)) {
|
||||||
|
fprintf(stderr, "PKCS7_dataFinal failed\n");
|
||||||
|
BIO_free_all(p7bio);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
BIO_free_all(p7bio);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return the header length (tag and length octets) of the ASN.1 type
|
||||||
|
* [in] p: ASN.1 data
|
||||||
|
* [in] len: ASN.1 data length
|
||||||
|
* [returns] header length
|
||||||
|
*/
|
||||||
|
int asn1_simple_hdr_len(const u_char *p, int len)
|
||||||
|
{
|
||||||
|
if (len <= 2 || p[0] > 0x31)
|
||||||
|
return 0;
|
||||||
|
return (p[1]&0x80) ? (2 + (p[1]&0x7f)) : 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] hash: BIO with message digest method
|
||||||
|
* [in] indata: starting address space
|
||||||
|
* [in] idx: offset
|
||||||
|
* [in] fileend: the length of the hashed area
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int bio_hash_data(BIO *hash, char *indata, size_t idx, size_t fileend)
|
||||||
|
{
|
||||||
|
while (idx < fileend) {
|
||||||
|
size_t want, written;
|
||||||
|
want = fileend - idx;
|
||||||
|
if (want > SIZE_64K)
|
||||||
|
want = SIZE_64K;
|
||||||
|
if (!BIO_write_ex(hash, indata + idx, want, &written))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
idx += written;
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] descript1, descript2: descriptions
|
||||||
|
* [in] mdbuf: message digest
|
||||||
|
* [in] len: message digest length
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
void print_hash(const char *descript1, const char *descript2, const u_char *mdbuf, int len)
|
||||||
|
{
|
||||||
|
char *hexbuf = NULL;
|
||||||
|
int size, i, j = 0;
|
||||||
|
|
||||||
|
size = 2 * len + 1;
|
||||||
|
hexbuf = OPENSSL_malloc((size_t)size);
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
#ifdef WIN32
|
||||||
|
j += sprintf_s(hexbuf + j, size - j, "%02X", mdbuf[i]);
|
||||||
|
#else
|
||||||
|
j += sprintf(hexbuf + j, "%02X", mdbuf[i]);
|
||||||
|
#endif /* WIN32 */
|
||||||
|
}
|
||||||
|
printf("%s: %s %s\n", descript1, hexbuf, descript2);
|
||||||
|
OPENSSL_free(hexbuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [in] objid: Microsoft OID Authenticode
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int is_content_type(PKCS7 *p7, const char *objid)
|
||||||
|
{
|
||||||
|
ASN1_OBJECT *indir_objid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
indir_objid = OBJ_txt2obj(objid, 1);
|
||||||
|
if (!indir_objid) {
|
||||||
|
fprintf(stderr, "Invalid object identifier: %s\n", objid);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
ret = p7 && PKCS7_type_is_signed(p7) &&
|
||||||
|
!OBJ_cmp(p7->d.sign->contents->type, indir_objid) &&
|
||||||
|
(p7->d.sign->contents->d.other->type == V_ASN1_SEQUENCE ||
|
||||||
|
p7->d.sign->contents->d.other->type == V_ASN1_OCTET_STRING);
|
||||||
|
ASN1_OBJECT_free(indir_objid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] p7: new PKCS#7 signature
|
||||||
|
* [returns] pointer to MsCtlContent structure
|
||||||
|
*/
|
||||||
|
MsCtlContent *ms_ctl_content_get(PKCS7 *p7)
|
||||||
|
{
|
||||||
|
ASN1_STRING *value;
|
||||||
|
const u_char *data;
|
||||||
|
|
||||||
|
if (!is_content_type(p7, MS_CTL_OBJID)) {
|
||||||
|
fprintf(stderr, "Failed to find MS_CTL_OBJID\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
value = p7->d.sign->contents->d.other->value.sequence;
|
||||||
|
data = ASN1_STRING_get0_data(value);
|
||||||
|
return d2i_MsCtlContent(NULL, &data, ASN1_STRING_length(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] attribute: catalog attribute
|
||||||
|
* [returns] catalog content
|
||||||
|
*/
|
||||||
|
ASN1_TYPE *catalog_content_get(CatalogAuthAttr *attribute)
|
||||||
|
{
|
||||||
|
ASN1_STRING *value;
|
||||||
|
STACK_OF(ASN1_TYPE) *contents;
|
||||||
|
ASN1_TYPE *content;
|
||||||
|
const u_char *contents_data;
|
||||||
|
|
||||||
|
value = attribute->contents->value.sequence;
|
||||||
|
contents_data = ASN1_STRING_get0_data(value);
|
||||||
|
contents = d2i_ASN1_SET_ANY(NULL, &contents_data, ASN1_STRING_length(value));
|
||||||
|
if (!contents)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
content = sk_ASN1_TYPE_value(contents, 0);
|
||||||
|
sk_ASN1_TYPE_free(contents);
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PE and CAB format specific
|
||||||
|
* [in] none
|
||||||
|
* [returns] pointer to SpcLink
|
||||||
|
*/
|
||||||
|
SpcLink *spc_link_obsolete_get(void)
|
||||||
|
{
|
||||||
|
const u_char obsolete[] = {
|
||||||
|
0x00, 0x3c, 0x00, 0x3c, 0x00, 0x3c, 0x00, 0x4f,
|
||||||
|
0x00, 0x62, 0x00, 0x73, 0x00, 0x6f, 0x00, 0x6c,
|
||||||
|
0x00, 0x65, 0x00, 0x74, 0x00, 0x65, 0x00, 0x3e,
|
||||||
|
0x00, 0x3e, 0x00, 0x3e
|
||||||
|
};
|
||||||
|
SpcLink *link = SpcLink_new();
|
||||||
|
link->type = 2;
|
||||||
|
link->value.file = SpcString_new();
|
||||||
|
link->value.file->type = 0;
|
||||||
|
link->value.file->value.unicode = ASN1_BMPSTRING_new();
|
||||||
|
ASN1_STRING_set(link->value.file->value.unicode, obsolete, sizeof obsolete);
|
||||||
|
return link;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] mdbuf, cmdbuf: message digests
|
||||||
|
* [in] mdtype: message digest algorithm type
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
int compare_digests(u_char *mdbuf, u_char *cmdbuf, int mdtype)
|
||||||
|
{
|
||||||
|
int mdlen = EVP_MD_size(EVP_get_digestbynid(mdtype));
|
||||||
|
int mdok = !memcmp(mdbuf, cmdbuf, (size_t)mdlen);
|
||||||
|
printf("Message digest algorithm : %s\n", OBJ_nid2sn(mdtype));
|
||||||
|
print_hash("Current message digest ", "", mdbuf, mdlen);
|
||||||
|
print_hash("Calculated message digest ", mdok ? "\n" : " MISMATCH!!!\n", cmdbuf, mdlen);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *digest_asn1;
|
||||||
|
const unsigned char *digest_data;
|
||||||
|
int digest_len;
|
||||||
|
|
||||||
|
if (!idc || !idc->messageDigest || !idc->messageDigest->digest ||
|
||||||
|
!idc->messageDigest->digestAlgorithm) {
|
||||||
|
return -1; /* FAILED */
|
||||||
|
}
|
||||||
|
digest_asn1 = idc->messageDigest->digest;
|
||||||
|
digest_len = ASN1_STRING_length((ASN1_STRING *)digest_asn1);
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
}
|
||||||
|
|
||||||
|
digest_data = ASN1_STRING_get0_data((ASN1_STRING *)digest_asn1);
|
||||||
|
*mdtype = OBJ_obj2nid(idc->messageDigest->digestAlgorithm->algorithm);
|
||||||
|
memcpy(mdbuf, digest_data, (size_t)digest_len);
|
||||||
|
return digest_len; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] pointer to SpcSpOpusInfo structure
|
||||||
|
*/
|
||||||
|
static SpcSpOpusInfo *spc_sp_opus_info_create(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
SpcSpOpusInfo *info = SpcSpOpusInfo_new();
|
||||||
|
|
||||||
|
if (ctx->options->desc) {
|
||||||
|
info->programName = SpcString_new();
|
||||||
|
info->programName->type = 1;
|
||||||
|
info->programName->value.ascii = ASN1_IA5STRING_new();
|
||||||
|
ASN1_STRING_set((ASN1_STRING *)info->programName->value.ascii,
|
||||||
|
ctx->options->desc, (int)strlen(ctx->options->desc));
|
||||||
|
}
|
||||||
|
if (ctx->options->url) {
|
||||||
|
info->moreInfo = SpcLink_new();
|
||||||
|
info->moreInfo->type = 0;
|
||||||
|
info->moreInfo->value.url = ASN1_IA5STRING_new();
|
||||||
|
ASN1_STRING_set((ASN1_STRING *)info->moreInfo->value.url,
|
||||||
|
ctx->options->url, (int)strlen(ctx->options->url));
|
||||||
|
}
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [out] blob: SpcIndirectDataContent data
|
||||||
|
* [out] len: SpcIndirectDataContent data length
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int spc_indirect_data_content_create(u_char **blob, int *len, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
u_char *p = NULL;
|
||||||
|
int mdtype, hashlen, l = 0;
|
||||||
|
void *hash;
|
||||||
|
SpcIndirectDataContent *idc = SpcIndirectDataContent_new();
|
||||||
|
|
||||||
|
if (!ctx->format->data_blob_get || !ctx->format->hash_length_get) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->format->md_get) {
|
||||||
|
/* APPX file specific - use a hash algorithm specified in the AppxBlockMap.xml file */
|
||||||
|
mdtype = EVP_MD_nid(ctx->format->md_get(ctx));
|
||||||
|
} else {
|
||||||
|
mdtype = EVP_MD_nid(ctx->options->md);
|
||||||
|
}
|
||||||
|
idc->data->value = ASN1_TYPE_new();
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
if (!ASN1_STRING_set(idc->data->value->value.sequence, p, l)) {
|
||||||
|
OPENSSL_free(p);
|
||||||
|
SpcIndirectDataContent_free(idc);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(p);
|
||||||
|
idc->messageDigest->digestAlgorithm->algorithm = OBJ_nid2obj(mdtype);
|
||||||
|
idc->messageDigest->digestAlgorithm->parameters = ASN1_TYPE_new();
|
||||||
|
idc->messageDigest->digestAlgorithm->parameters->type = V_ASN1_NULL;
|
||||||
|
|
||||||
|
hashlen = ctx->format->hash_length_get(ctx);
|
||||||
|
hash = OPENSSL_zalloc((size_t)hashlen);
|
||||||
|
ASN1_OCTET_STRING_set(idc->messageDigest->digest, hash, hashlen);
|
||||||
|
OPENSSL_free(hash);
|
||||||
|
|
||||||
|
*len = i2d_SpcIndirectDataContent(idc, NULL);
|
||||||
|
*blob = OPENSSL_malloc((size_t)*len);
|
||||||
|
p = *blob;
|
||||||
|
i2d_SpcIndirectDataContent(idc, &p);
|
||||||
|
SpcIndirectDataContent_free(idc);
|
||||||
|
*len -= hashlen;
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: FILE_FORMAT_CTX structure
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_spc_sp_opus_info(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
SpcSpOpusInfo *opus;
|
||||||
|
ASN1_STRING *astr;
|
||||||
|
int len;
|
||||||
|
u_char *p = NULL;
|
||||||
|
|
||||||
|
opus = spc_sp_opus_info_create(ctx);
|
||||||
|
if ((len = i2d_SpcSpOpusInfo(opus, NULL)) <= 0
|
||||||
|
|| (p = OPENSSL_malloc((size_t)len)) == NULL) {
|
||||||
|
SpcSpOpusInfo_free(opus);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
i2d_SpcSpOpusInfo(opus, &p);
|
||||||
|
p -= len;
|
||||||
|
astr = ASN1_STRING_new();
|
||||||
|
ASN1_STRING_set(astr, p, len);
|
||||||
|
OPENSSL_free(p);
|
||||||
|
SpcSpOpusInfo_free(opus);
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(SPC_SP_OPUS_INFO_OBJID),
|
||||||
|
V_ASN1_SEQUENCE, astr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Add a custom, non-trusted time to the PKCS7 structure to prevent OpenSSL
|
||||||
|
* adding the _current_ time. This allows to create a deterministic signature
|
||||||
|
* when no trusted timestamp server was specified, making osslsigncode
|
||||||
|
* behaviour closer to signtool.exe (which doesn't include any non-trusted
|
||||||
|
* time in this case.)
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_signing_time(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (ctx->options->time == INVALID_TIME) /* -time option was not specified */
|
||||||
|
return 1; /* SUCCESS */
|
||||||
|
return PKCS7_add_signed_attribute(si, NID_pkcs9_signingTime, V_ASN1_UTCTIME,
|
||||||
|
ASN1_TIME_adj(NULL, ctx->options->time, 0, 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_purpose(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
static const u_char purpose_ind[] = {
|
||||||
|
0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
|
||||||
|
0x01, 0x82, 0x37, 0x02, 0x01, 0x15
|
||||||
|
};
|
||||||
|
static const u_char purpose_comm[] = {
|
||||||
|
0x30, 0x0c, 0x06, 0x0a, 0x2b, 0x06, 0x01, 0x04,
|
||||||
|
0x01, 0x82, 0x37, 0x02, 0x01, 0x16
|
||||||
|
};
|
||||||
|
ASN1_STRING *purpose = ASN1_STRING_new();
|
||||||
|
|
||||||
|
if (ctx->options->comm) {
|
||||||
|
ASN1_STRING_set(purpose, purpose_comm, sizeof purpose_comm);
|
||||||
|
} else {
|
||||||
|
ASN1_STRING_set(purpose, purpose_ind, sizeof purpose_ind);
|
||||||
|
}
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(SPC_STATEMENT_TYPE_OBJID),
|
||||||
|
V_ASN1_SEQUENCE, purpose);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* [in, out] si: PKCS7_SIGNER_INFO structure
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int pkcs7_signer_info_add_sequence_number(PKCS7_SIGNER_INFO *si, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
ASN1_INTEGER *number = ASN1_INTEGER_new();
|
||||||
|
|
||||||
|
if (!number)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!ASN1_INTEGER_set(number, ctx->options->nested_number + 1)) {
|
||||||
|
ASN1_INTEGER_free(number);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
return PKCS7_add_signed_attribute(si, OBJ_txt2nid(PKCS9_SEQUENCE_NUMBER),
|
||||||
|
V_ASN1_INTEGER, number);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create certificate chain sorted in ascending order by their DER encoding.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] signer: signer's certificate number in the certificate chain
|
||||||
|
* [returns] sorted certificate chain
|
||||||
|
*/
|
||||||
|
static STACK_OF(X509) *X509_chain_get_sorted(FILE_FORMAT_CTX *ctx, int signer)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
STACK_OF(X509) *chain = sk_X509_new(X509_compare);
|
||||||
|
|
||||||
|
if (signer != -1 && !sk_X509_push(chain, sk_X509_value(ctx->options->certs, signer))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
/* add the certificate chain */
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->certs); i++) {
|
||||||
|
if (i == signer)
|
||||||
|
continue;
|
||||||
|
if (!sk_X509_push(chain, sk_X509_value(ctx->options->certs, i))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* add all cross certificates */
|
||||||
|
if (ctx->options->xcerts) {
|
||||||
|
for (i=0; i<sk_X509_num(ctx->options->xcerts); i++) {
|
||||||
|
if (!sk_X509_push(chain, sk_X509_value(ctx->options->xcerts, i))) {
|
||||||
|
sk_X509_free(chain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* sort certificate chain using the supplied comparison function */
|
||||||
|
sk_X509_sort(chain);
|
||||||
|
/* remove duplicates */
|
||||||
|
sk_X509_remove_duplicates(chain);
|
||||||
|
|
||||||
|
return chain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* X.690-compliant certificate comparison function
|
||||||
|
* Windows requires catalog files to use PKCS#7
|
||||||
|
* content ordering specified in X.690 section 11.6
|
||||||
|
* https://support.microsoft.com/en-us/topic/october-13-2020-kb4580358-security-only-update-d3f6eb3c-d7c4-a9cb-0de6-759386bf7113
|
||||||
|
* This algorithm is different from X509_cmp()
|
||||||
|
* [in] a_ptr, b_ptr: pointers to X509 certificates
|
||||||
|
* [returns] certificates order
|
||||||
|
*/
|
||||||
|
static int X509_compare(const X509 *const *a, const X509 *const *b)
|
||||||
|
{
|
||||||
|
u_char *a_data, *b_data, *a_tmp, *b_tmp;
|
||||||
|
size_t a_len, b_len;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wincompatible-pointer-types-discards-qualifiers"
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers"
|
||||||
|
#endif
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
||||||
|
a_len = (size_t)i2d_X509(*a, NULL);
|
||||||
|
a_tmp = a_data = OPENSSL_malloc(a_len);
|
||||||
|
i2d_X509(*a, &a_tmp);
|
||||||
|
|
||||||
|
b_len = (size_t)i2d_X509(*b, NULL);
|
||||||
|
b_tmp = b_data = OPENSSL_malloc(b_len);
|
||||||
|
i2d_X509(*b, &b_tmp);
|
||||||
|
#if OPENSSL_VERSION_NUMBER<0x30000000L
|
||||||
|
#if defined(__clang__)
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER<0x30000000L */
|
||||||
|
|
||||||
|
ret = memcmp(a_data, b_data, MIN(a_len, b_len));
|
||||||
|
OPENSSL_free(a_data);
|
||||||
|
OPENSSL_free(b_data);
|
||||||
|
|
||||||
|
if (ret == 0 && a_len != b_len) /* identical up to the length of the shorter DER */
|
||||||
|
ret = a_len < b_len ? -1 : 1; /* shorter is smaller */
|
||||||
|
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
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* osslsigncode support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Common functions */
|
||||||
|
uint32_t get_file_size(const char *infile);
|
||||||
|
char *map_file(const char *infile, const size_t size);
|
||||||
|
void unmap_file(char *indata, const size_t size);
|
||||||
|
PKCS7 *pkcs7_read_data(char *indata, uint32_t size);
|
||||||
|
int data_write_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
PKCS7 *pkcs7_create(FILE_FORMAT_CTX *ctx);
|
||||||
|
int add_indirect_data_object(PKCS7 *p7);
|
||||||
|
int sign_spc_indirect_data_content(PKCS7 *p7, ASN1_OCTET_STRING *content);
|
||||||
|
PKCS7 *pkcs7_set_content(ASN1_OCTET_STRING *content);
|
||||||
|
int pkcs7_get_content_digest(PKCS7 *p7, u_char *mdbuf, int *mdtype);
|
||||||
|
SpcIndirectDataContent *pkcs7_get_indirect_data_content(PKCS7 *p7);
|
||||||
|
SpcIndirectDataContent *asn1_type_get_indirect_data_content(ASN1_TYPE *content);
|
||||||
|
ASN1_OCTET_STRING *spc_indirect_data_content_get(BIO *hash, FILE_FORMAT_CTX *ctx);
|
||||||
|
int pkcs7_sign_content(PKCS7 *p7, const u_char *data, int len);
|
||||||
|
int asn1_simple_hdr_len(const u_char *p, int len);
|
||||||
|
int bio_hash_data(BIO *hash, char *indata, size_t idx, size_t fileend);
|
||||||
|
void print_hash(const char *descript1, const char *descript2, const u_char *hashbuf, int length);
|
||||||
|
int is_content_type(PKCS7 *p7, const char *objid);
|
||||||
|
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:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
||||||
@@ -1,238 +0,0 @@
|
|||||||
/*
|
|
||||||
* MSI file support library
|
|
||||||
*
|
|
||||||
* Copyright (C) 2021 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
|
||||||
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
|
||||||
*
|
|
||||||
* Reference specifications:
|
|
||||||
* http://en.wikipedia.org/wiki/Compound_File_Binary_Format
|
|
||||||
* https://msdn.microsoft.com/en-us/library/dd942138.aspx
|
|
||||||
* https://github.com/microsoft/compoundfilereader
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <openssl/safestack.h>
|
|
||||||
#include <openssl/bio.h>
|
|
||||||
#include <openssl/crypto.h>
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#define MAXREGSECT 0xfffffffa /* maximum regular sector number */
|
|
||||||
#define DIFSECT 0xfffffffc /* specifies a DIFAT sector in the FAT */
|
|
||||||
#define FATSECT 0xfffffffd /* specifies a FAT sector in the FAT */
|
|
||||||
#define ENDOFCHAIN 0xfffffffe /* end of a linked chain of sectors */
|
|
||||||
#define NOSTREAM 0xffffffff /* terminator or empty pointer */
|
|
||||||
#define FREESECT 0xffffffff /* empty unallocated free sectors */
|
|
||||||
|
|
||||||
#define DIR_UNKNOWN 0
|
|
||||||
#define DIR_STORAGE 1
|
|
||||||
#define DIR_STREAM 2
|
|
||||||
#define DIR_ROOT 5
|
|
||||||
|
|
||||||
#define RED_COLOR 0
|
|
||||||
#define BLACK_COLOR 1
|
|
||||||
|
|
||||||
#define DIFAT_IN_HEADER 109
|
|
||||||
#define MINI_STREAM_CUTOFF_SIZE 0x00001000 /* 4096 bytes */
|
|
||||||
#define HEADER_SIZE 0x200 /* 512 bytes, independent of sector size */
|
|
||||||
#define MAX_SECTOR_SIZE 0x1000 /* 4096 bytes */
|
|
||||||
|
|
||||||
#define HEADER_SIGNATURE 0x00 /* 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 */
|
|
||||||
#define HEADER_CLSID 0x08 /* reserved and unused */
|
|
||||||
#define HEADER_MINOR_VER 0x18 /* SHOULD be set to 0x003E */
|
|
||||||
#define HEADER_MAJOR_VER 0x1a /* MUST be set to either 0x0003 (version 3) or 0x0004 (version 4) */
|
|
||||||
#define HEADER_BYTE_ORDER 0x1c /* 0xfe 0xff == Intel Little Endian */
|
|
||||||
#define HEADER_SECTOR_SHIFT 0x1e /* MUST be set to 0x0009, or 0x000c */
|
|
||||||
#define HEADER_MINI_SECTOR_SHIFT 0x20 /* MUST be set to 0x0006 */
|
|
||||||
#define RESERVED 0x22 /* reserved and unused */
|
|
||||||
#define HEADER_DIR_SECTORS_NUM 0x28
|
|
||||||
#define HEADER_FAT_SECTORS_NUM 0x2c
|
|
||||||
#define HEADER_DIR_SECTOR_LOC 0x30
|
|
||||||
#define HEADER_TRANSACTION 0x34
|
|
||||||
#define HEADER_MINI_STREAM_CUTOFF 0x38 /* 4096 bytes */
|
|
||||||
#define HEADER_MINI_FAT_SECTOR_LOC 0x3c
|
|
||||||
#define HEADER_MINI_FAT_SECTORS_NUM 0x40
|
|
||||||
#define HEADER_DIFAT_SECTOR_LOC 0x44
|
|
||||||
#define HEADER_DIFAT_SECTORS_NUM 0x48
|
|
||||||
#define HEADER_DIFAT 0x4c
|
|
||||||
|
|
||||||
#define DIRENT_SIZE 0x80 /* 128 bytes */
|
|
||||||
#define DIRENT_MAX_NAME_SIZE 0x40 /* 64 bytes */
|
|
||||||
|
|
||||||
#define DIRENT_NAME 0x00
|
|
||||||
#define DIRENT_NAME_LEN 0x40 /* length in bytes incl 0 terminator */
|
|
||||||
#define DIRENT_TYPE 0x42
|
|
||||||
#define DIRENT_COLOUR 0x43
|
|
||||||
#define DIRENT_LEFT_SIBLING_ID 0x44
|
|
||||||
#define DIRENT_RIGHT_SIBLING_ID 0x48
|
|
||||||
#define DIRENT_CHILD_ID 0x4c
|
|
||||||
#define DIRENT_CLSID 0x50
|
|
||||||
#define DIRENT_STATE_BITS 0x60
|
|
||||||
#define DIRENT_CREATE_TIME 0x64
|
|
||||||
#define DIRENT_MODIFY_TIME 0x6c
|
|
||||||
#define DIRENT_START_SECTOR_LOC 0x74
|
|
||||||
#define DIRENT_FILE_SIZE 0x78
|
|
||||||
|
|
||||||
#define GET_UINT8_LE(p) ((const u_char *)(p))[0]
|
|
||||||
|
|
||||||
#define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \
|
|
||||||
(((const u_char *)(p))[1] << 8))
|
|
||||||
|
|
||||||
#define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \
|
|
||||||
(((const u_char *)(p))[1] << 8) | \
|
|
||||||
(((const u_char *)(p))[2] << 16) | \
|
|
||||||
(((const u_char *)(p))[3] << 24))
|
|
||||||
|
|
||||||
#define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff);
|
|
||||||
|
|
||||||
#define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
|
||||||
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff)
|
|
||||||
|
|
||||||
#define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
|
||||||
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \
|
|
||||||
((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \
|
|
||||||
((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff)
|
|
||||||
|
|
||||||
#ifndef FALSE
|
|
||||||
#define FALSE 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TRUE
|
|
||||||
#define TRUE 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define SIZE_64K 65536 /* 2^16 */
|
|
||||||
#define SIZE_16M 16777216 /* 2^24 */
|
|
||||||
|
|
||||||
typedef unsigned char u_char;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char signature[8]; /* 0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1 */
|
|
||||||
u_char unused_clsid[16]; /* reserved and unused */
|
|
||||||
uint16_t minorVersion;
|
|
||||||
uint16_t majorVersion;
|
|
||||||
uint16_t byteOrder;
|
|
||||||
uint16_t sectorShift; /* power of 2 */
|
|
||||||
uint16_t miniSectorShift; /* power of 2 */
|
|
||||||
u_char reserved[6]; /* reserved and unused */
|
|
||||||
uint32_t numDirectorySector;
|
|
||||||
uint32_t numFATSector;
|
|
||||||
uint32_t firstDirectorySectorLocation;
|
|
||||||
uint32_t transactionSignatureNumber; /* reserved */
|
|
||||||
uint32_t miniStreamCutoffSize;
|
|
||||||
uint32_t firstMiniFATSectorLocation;
|
|
||||||
uint32_t numMiniFATSector;
|
|
||||||
uint32_t firstDIFATSectorLocation;
|
|
||||||
uint32_t numDIFATSector;
|
|
||||||
uint32_t headerDIFAT[DIFAT_IN_HEADER];
|
|
||||||
} MSI_FILE_HDR;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
u_char name[DIRENT_MAX_NAME_SIZE];
|
|
||||||
uint16_t nameLen;
|
|
||||||
uint8_t type;
|
|
||||||
uint8_t colorFlag;
|
|
||||||
uint32_t leftSiblingID;
|
|
||||||
uint32_t rightSiblingID;
|
|
||||||
uint32_t childID;
|
|
||||||
u_char clsid[16];
|
|
||||||
u_char stateBits[4];
|
|
||||||
u_char creationTime[8];
|
|
||||||
u_char modifiedTime[8];
|
|
||||||
uint32_t startSectorLocation;
|
|
||||||
u_char size[8];
|
|
||||||
} MSI_ENTRY;
|
|
||||||
|
|
||||||
typedef struct msi_dirent_struct {
|
|
||||||
u_char name[DIRENT_MAX_NAME_SIZE];
|
|
||||||
uint16_t nameLen;
|
|
||||||
uint8_t type;
|
|
||||||
MSI_ENTRY *entry;
|
|
||||||
STACK_OF(MSI_DIRENT) *children;
|
|
||||||
struct msi_dirent_struct *next; /* for cycle detection */
|
|
||||||
} MSI_DIRENT;
|
|
||||||
|
|
||||||
DEFINE_STACK_OF(MSI_DIRENT)
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
const u_char *m_buffer;
|
|
||||||
uint32_t m_bufferLen;
|
|
||||||
MSI_FILE_HDR *m_hdr;
|
|
||||||
uint32_t m_sectorSize;
|
|
||||||
uint32_t m_minisectorSize;
|
|
||||||
uint32_t m_miniStreamStartSector;
|
|
||||||
} MSI_FILE;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *header;
|
|
||||||
char *ministream;
|
|
||||||
char *minifat;
|
|
||||||
char *fat;
|
|
||||||
uint32_t dirtreeLen;
|
|
||||||
uint32_t miniStreamLen;
|
|
||||||
uint32_t minifatLen;
|
|
||||||
uint32_t fatLen;
|
|
||||||
uint32_t ministreamsMemallocCount;
|
|
||||||
uint32_t minifatMemallocCount;
|
|
||||||
uint32_t fatMemallocCount;
|
|
||||||
uint32_t dirtreeSectorsCount;
|
|
||||||
uint32_t minifatSectorsCount;
|
|
||||||
uint32_t fatSectorsCount;
|
|
||||||
uint32_t miniSectorNum;
|
|
||||||
uint32_t sectorNum;
|
|
||||||
uint32_t sectorSize;
|
|
||||||
} MSI_OUT;
|
|
||||||
|
|
||||||
static const u_char msi_magic[] = {
|
|
||||||
0xd0, 0xcf, 0x11, 0xe0, 0xa1, 0xb1, 0x1a, 0xe1
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char digital_signature[] = {
|
|
||||||
0x05, 0x00, 0x44, 0x00, 0x69, 0x00, 0x67, 0x00,
|
|
||||||
0x69, 0x00, 0x74, 0x00, 0x61, 0x00, 0x6C, 0x00,
|
|
||||||
0x53, 0x00, 0x69, 0x00, 0x67, 0x00, 0x6E, 0x00,
|
|
||||||
0x61, 0x00, 0x74, 0x00, 0x75, 0x00, 0x72, 0x00,
|
|
||||||
0x65, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char digital_signature_ex[] = {
|
|
||||||
0x05, 0x00, 0x4D, 0x00, 0x73, 0x00, 0x69, 0x00,
|
|
||||||
0x44, 0x00, 0x69, 0x00, 0x67, 0x00, 0x69, 0x00,
|
|
||||||
0x74, 0x00, 0x61, 0x00, 0x6C, 0x00, 0x53, 0x00,
|
|
||||||
0x69, 0x00, 0x67, 0x00, 0x6E, 0x00, 0x61, 0x00,
|
|
||||||
0x74, 0x00, 0x75, 0x00, 0x72, 0x00, 0x65, 0x00,
|
|
||||||
0x45, 0x00, 0x78, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char msi_root_entry[] = {
|
|
||||||
0x52, 0x00, 0x6F, 0x00, 0x6F, 0x00, 0x74, 0x00,
|
|
||||||
0x20, 0x00, 0x45, 0x00, 0x6E, 0x00, 0x74, 0x00,
|
|
||||||
0x72, 0x00, 0x79, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
static const u_char msi_zeroes[] = {
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
int msi_file_read(MSI_FILE *msi, MSI_ENTRY *entry, uint32_t offset, char *buffer, uint32_t len);
|
|
||||||
MSI_FILE *msi_file_new(char *buffer, uint32_t len);
|
|
||||||
void msi_file_free(MSI_FILE *msi);
|
|
||||||
MSI_ENTRY *msi_root_entry_get(MSI_FILE *msi);
|
|
||||||
int msi_dirent_new(MSI_FILE *msi, MSI_ENTRY *entry, MSI_DIRENT *parent, MSI_DIRENT **ret);
|
|
||||||
MSI_ENTRY *msi_signatures_get(MSI_DIRENT *dirent, MSI_ENTRY **dse);
|
|
||||||
void msi_dirent_free(MSI_DIRENT *dirent);
|
|
||||||
int msi_prehash_dir(MSI_DIRENT *dirent, BIO *hash, int is_root);
|
|
||||||
int msi_hash_dir(MSI_FILE *msi, MSI_DIRENT *dirent, BIO *hash, int is_root);
|
|
||||||
int msi_calc_digest(char *indata, int mdtype, u_char *mdbuf, uint32_t fileend);
|
|
||||||
int msi_dirent_delete(MSI_DIRENT *dirent, const u_char *name, uint16_t nameLen);
|
|
||||||
int msi_file_write(MSI_FILE *msi, MSI_DIRENT *dirent, u_char *p, uint32_t len,
|
|
||||||
u_char *p_msiex, uint32_t len_msiex, BIO *outdata);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Local Variables:
|
|
||||||
c-basic-offset: 4
|
|
||||||
tab-width: 4
|
|
||||||
indent-tabs-mode: t
|
|
||||||
End:
|
|
||||||
|
|
||||||
vim: set ts=4 noexpandtab:
|
|
||||||
*/
|
|
||||||
+5111
-5871
File diff suppressed because it is too large
Load Diff
+574
@@ -0,0 +1,574 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021-2023 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
* Author: Małgorzata Olszówka <Malgorzata.Olszowka@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define OPENSSL_API_COMPAT 0x10100000L
|
||||||
|
#define OPENSSL_NO_DEPRECATED
|
||||||
|
|
||||||
|
#if defined(_MSC_VER) || defined(__MINGW32__)
|
||||||
|
#define HAVE_WINDOWS_H
|
||||||
|
#endif /* _MSC_VER || __MINGW32__ */
|
||||||
|
|
||||||
|
#ifdef HAVE_WINDOWS_H
|
||||||
|
#define NOCRYPT
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <winsock2.h>
|
||||||
|
#endif /* HAVE_WINDOWS_H */
|
||||||
|
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
#include "config.h"
|
||||||
|
#endif /* HAVE_CONFIG_H */
|
||||||
|
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
#ifndef _WIN32
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#ifdef HAVE_SYS_MMAN_H
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#endif /* HAVE_SYS_MMAN_H */
|
||||||
|
#ifdef HAVE_TERMIOS_H
|
||||||
|
#include <termios.h>
|
||||||
|
#endif /* HAVE_TERMIOS_H */
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
#include <openssl/asn1t.h>
|
||||||
|
#include <openssl/bio.h>
|
||||||
|
#include <openssl/bn.h>
|
||||||
|
#include <openssl/cms.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/crypto.h>
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/objects.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/pkcs7.h>
|
||||||
|
#include <openssl/pkcs12.h>
|
||||||
|
#if OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
#include <openssl/provider.h>
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#include <openssl/safestack.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/store.h>
|
||||||
|
#include <openssl/ts.h>
|
||||||
|
#include <openssl/ui.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/x509v3.h> /* X509_PURPOSE */
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
#ifdef __CYGWIN__
|
||||||
|
#ifndef SOCKET
|
||||||
|
#define SOCKET UINT_PTR
|
||||||
|
#endif /* SOCKET */
|
||||||
|
#endif /* __CYGWIN__ */
|
||||||
|
#include <curl/curl.h>
|
||||||
|
#endif /* ENABLE_CURL */
|
||||||
|
|
||||||
|
/* Request nonce length, in bits (must be a multiple of 8). */
|
||||||
|
#define NONCE_LENGTH 64
|
||||||
|
#define MAX_TS_SERVERS 256
|
||||||
|
|
||||||
|
#if defined (HAVE_TERMIOS_H) || defined (HAVE_GETPASS)
|
||||||
|
#define PROVIDE_ASKPASS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
/* not WIN32, because strcasecmp exists in MinGW */
|
||||||
|
#define strcasecmp _stricmp
|
||||||
|
#define fseeko _fseeki64
|
||||||
|
#define ftello _ftelli64
|
||||||
|
#endif /* _MSC_VER */
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#define remove_file(filename) _unlink(filename)
|
||||||
|
#else
|
||||||
|
#define remove_file(filename) unlink(filename)
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
#define GET_UINT8_LE(p) ((const u_char *)(p))[0]
|
||||||
|
|
||||||
|
#define GET_UINT16_LE(p) (uint16_t)(((const u_char *)(p))[0] | \
|
||||||
|
(((const u_char *)(p))[1] << 8))
|
||||||
|
|
||||||
|
#define GET_UINT32_LE(p) (uint32_t)(((const u_char *)(p))[0] | \
|
||||||
|
(((const u_char *)(p))[1] << 8) | \
|
||||||
|
(((const u_char *)(p))[2] << 16) | \
|
||||||
|
(((const u_char *)(p))[3] << 24))
|
||||||
|
|
||||||
|
#define PUT_UINT8_LE(i, p) ((u_char *)(p))[0] = (u_char)((i) & 0xff);
|
||||||
|
|
||||||
|
#define PUT_UINT16_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
||||||
|
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff)
|
||||||
|
|
||||||
|
#define PUT_UINT32_LE(i,p) ((u_char *)(p))[0] = (u_char)((i) & 0xff); \
|
||||||
|
((u_char *)(p))[1] = (u_char)(((i) >> 8) & 0xff); \
|
||||||
|
((u_char *)(p))[2] = (u_char)(((i) >> 16) & 0xff); \
|
||||||
|
((u_char *)(p))[3] = (u_char)(((i) >> 24) & 0xff)
|
||||||
|
|
||||||
|
#ifndef FALSE
|
||||||
|
#define FALSE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef TRUE
|
||||||
|
#define TRUE 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SIZE_64K 65536 /* 2^16 */
|
||||||
|
#define SIZE_16M 16777216 /* 2^24 */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Macro names:
|
||||||
|
* linux: __BYTE_ORDER == __LITTLE_ENDIAN | __BIG_ENDIAN
|
||||||
|
* BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
|
||||||
|
* bsd: _BYTE_ORDER == _LITTLE_ENDIAN | _BIG_ENDIAN
|
||||||
|
* BYTE_ORDER == LITTLE_ENDIAN | BIG_ENDIAN
|
||||||
|
* solaris: _LITTLE_ENDIAN | _BIG_ENDIAN
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef BYTE_ORDER
|
||||||
|
#define LITTLE_ENDIAN 1234
|
||||||
|
#define BIG_ENDIAN 4321
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
#endif /* BYTE_ORDER */
|
||||||
|
|
||||||
|
#if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) || !defined(BIG_ENDIAN)
|
||||||
|
#error "Cannot determine the endian-ness of this platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOWORD
|
||||||
|
#define LOWORD(x) ((x) & 0xFFFF)
|
||||||
|
#endif /* LOWORD */
|
||||||
|
#ifndef HIWORD
|
||||||
|
#define HIWORD(x) (((x) >> 16) & 0xFFFF)
|
||||||
|
#endif /* HIWORD */
|
||||||
|
|
||||||
|
#if BYTE_ORDER == BIG_ENDIAN
|
||||||
|
#define LE_UINT16(x) ((((x) >> 8) & 0x00FF) | \
|
||||||
|
(((x) << 8) & 0xFF00))
|
||||||
|
#define LE_UINT32(x) (((x) >> 24) | \
|
||||||
|
(((x) & 0x00FF0000) >> 8) | \
|
||||||
|
(((x) & 0x0000FF00) << 8) | \
|
||||||
|
((x) << 24))
|
||||||
|
#else
|
||||||
|
#define LE_UINT16(x) (x)
|
||||||
|
#define LE_UINT32(x) (x)
|
||||||
|
#endif /* BYTE_ORDER == BIG_ENDIAN */
|
||||||
|
|
||||||
|
#define MIN(a,b) ((a) < (b) ? a : b)
|
||||||
|
#define INVALID_TIME ((time_t)-1)
|
||||||
|
|
||||||
|
/* Microsoft OID Authenticode */
|
||||||
|
#define SPC_INDIRECT_DATA_OBJID "1.3.6.1.4.1.311.2.1.4"
|
||||||
|
#define SPC_STATEMENT_TYPE_OBJID "1.3.6.1.4.1.311.2.1.11"
|
||||||
|
#define SPC_SP_OPUS_INFO_OBJID "1.3.6.1.4.1.311.2.1.12"
|
||||||
|
#define SPC_PE_IMAGE_DATA_OBJID "1.3.6.1.4.1.311.2.1.15"
|
||||||
|
#define SPC_CAB_DATA_OBJID "1.3.6.1.4.1.311.2.1.25"
|
||||||
|
#define SPC_SIPINFO_OBJID "1.3.6.1.4.1.311.2.1.30"
|
||||||
|
#define SPC_PE_IMAGE_PAGE_HASHES_V1 "1.3.6.1.4.1.311.2.3.1" /* SHA1 */
|
||||||
|
#define SPC_PE_IMAGE_PAGE_HASHES_V2 "1.3.6.1.4.1.311.2.3.2" /* SHA256 */
|
||||||
|
#define SPC_NESTED_SIGNATURE_OBJID "1.3.6.1.4.1.311.2.4.1"
|
||||||
|
/* Microsoft OID Time Stamping */
|
||||||
|
#define SPC_TIME_STAMP_REQUEST_OBJID "1.3.6.1.4.1.311.3.2.1"
|
||||||
|
#define SPC_RFC3161_OBJID "1.3.6.1.4.1.311.3.3.1"
|
||||||
|
/* Microsoft OID Crypto 2.0 */
|
||||||
|
#define MS_CTL_OBJID "1.3.6.1.4.1.311.10.1"
|
||||||
|
/* Microsoft OID Catalog */
|
||||||
|
#define CAT_NAMEVALUE_OBJID "1.3.6.1.4.1.311.12.2.1"
|
||||||
|
/* Microsoft OID Microsoft_Java */
|
||||||
|
#define MS_JAVA_SOMETHING "1.3.6.1.4.1.311.15.1"
|
||||||
|
|
||||||
|
#define SPC_UNAUTHENTICATED_DATA_BLOB_OBJID "1.3.6.1.4.1.42921.1.2.1"
|
||||||
|
|
||||||
|
/* Public Key Cryptography Standards PKCS#9 */
|
||||||
|
#define PKCS9_MESSAGE_DIGEST "1.2.840.113549.1.9.4"
|
||||||
|
#define PKCS9_SIGNING_TIME "1.2.840.113549.1.9.5"
|
||||||
|
#define PKCS9_COUNTER_SIGNATURE "1.2.840.113549.1.9.6"
|
||||||
|
#define PKCS9_SEQUENCE_NUMBER "1.2.840.113549.1.9.25.4"
|
||||||
|
|
||||||
|
/* WIN_CERTIFICATE structure declared in Wintrust.h */
|
||||||
|
#define WIN_CERT_REVISION_2_0 0x0200
|
||||||
|
#define WIN_CERT_TYPE_PKCS_SIGNED_DATA 0x0002
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FLAG_PREV_CABINET is set if the cabinet file is not the first in a set
|
||||||
|
* of cabinet files. When this bit is set, the szCabinetPrev and szDiskPrev
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_PREV_CABINET 0x0001
|
||||||
|
/*
|
||||||
|
* FLAG_NEXT_CABINET is set if the cabinet file is not the last in a set of
|
||||||
|
* cabinet files. When this bit is set, the szCabinetNext and szDiskNext
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_NEXT_CABINET 0x0002
|
||||||
|
/*
|
||||||
|
* FLAG_RESERVE_PRESENT is set if the cabinet file contains any reserved
|
||||||
|
* fields. When this bit is set, the cbCFHeader, cbCFFolder, and cbCFData
|
||||||
|
* fields are present in this CFHEADER.
|
||||||
|
*/
|
||||||
|
#define FLAG_RESERVE_PRESENT 0x0004
|
||||||
|
|
||||||
|
#define DO_EXIT_0(x) { fprintf(stderr, x); goto err_cleanup; }
|
||||||
|
#define DO_EXIT_1(x, y) { fprintf(stderr, x, y); goto err_cleanup; }
|
||||||
|
#define DO_EXIT_2(x, y, z) { fprintf(stderr, x, y, z); goto err_cleanup; }
|
||||||
|
|
||||||
|
/* Default policy if request did not specify it. */
|
||||||
|
#define TSA_POLICY1 "1.2.3.4.1"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CMD_SIGN,
|
||||||
|
CMD_EXTRACT,
|
||||||
|
CMD_EXTRACT_DATA,
|
||||||
|
CMD_REMOVE,
|
||||||
|
CMD_VERIFY,
|
||||||
|
CMD_ADD,
|
||||||
|
CMD_ATTACH,
|
||||||
|
CMD_HELP,
|
||||||
|
CMD_DEFAULT
|
||||||
|
} cmd_type_t;
|
||||||
|
|
||||||
|
typedef unsigned char u_char;
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OCTET_STRING *cmd;
|
||||||
|
ASN1_OCTET_STRING *param;
|
||||||
|
} EngineControl;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(EngineControl)
|
||||||
|
DEFINE_STACK_OF(EngineControl)
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *infile;
|
||||||
|
char *outfile;
|
||||||
|
char *sigfile;
|
||||||
|
char *certfile;
|
||||||
|
char *xcertfile;
|
||||||
|
char *keyfile;
|
||||||
|
char *pvkfile;
|
||||||
|
char *pkcs12file;
|
||||||
|
int output_pkcs7;
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
char *p11engine;
|
||||||
|
STACK_OF(EngineControl) *engine_ctrls;
|
||||||
|
int login;
|
||||||
|
#endif /* OPENSSL_NO_ENGINE */
|
||||||
|
#if !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
char *p11module;
|
||||||
|
char *p11cert;
|
||||||
|
#endif /* !defined(OPENSSL_NO_ENGINE) || OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
int askpass;
|
||||||
|
char *readpass;
|
||||||
|
char *pass;
|
||||||
|
int comm;
|
||||||
|
int pagehash;
|
||||||
|
char *desc;
|
||||||
|
const EVP_MD *md;
|
||||||
|
char *url;
|
||||||
|
time_t time;
|
||||||
|
char *turl[MAX_TS_SERVERS];
|
||||||
|
int nturl;
|
||||||
|
char *tsurl[MAX_TS_SERVERS];
|
||||||
|
int ntsurl;
|
||||||
|
char *proxy;
|
||||||
|
int noverifypeer;
|
||||||
|
int addBlob;
|
||||||
|
const char *blob_file;
|
||||||
|
int nest;
|
||||||
|
int index;
|
||||||
|
int ignore_timestamp;
|
||||||
|
int ignore_cdp;
|
||||||
|
int ignore_crl;
|
||||||
|
int verbose;
|
||||||
|
int add_msi_dse;
|
||||||
|
char *catalog;
|
||||||
|
char *cafile;
|
||||||
|
char *crlfile;
|
||||||
|
char *https_cafile;
|
||||||
|
char *https_crlfile;
|
||||||
|
char *tsa_cafile;
|
||||||
|
char *tsa_crlfile;
|
||||||
|
char *leafhash;
|
||||||
|
int jp;
|
||||||
|
#if OPENSSL_VERSION_NUMBER>=0x30000000L
|
||||||
|
int legacy;
|
||||||
|
char *provider;
|
||||||
|
#endif /* OPENSSL_VERSION_NUMBER>=0x30000000L */
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
STACK_OF(X509) *certs;
|
||||||
|
STACK_OF(X509) *xcerts;
|
||||||
|
STACK_OF(X509_CRL) *crls;
|
||||||
|
cmd_type_t cmd;
|
||||||
|
char *indata;
|
||||||
|
char *tsa_certfile;
|
||||||
|
char *tsa_keyfile;
|
||||||
|
time_t tsa_time;
|
||||||
|
int nested_number;
|
||||||
|
} GLOBAL_OPTIONS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ASN.1 definitions (more or less from official MS Authenticode docs)
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
int type;
|
||||||
|
union {
|
||||||
|
ASN1_BMPSTRING *unicode;
|
||||||
|
ASN1_IA5STRING *ascii;
|
||||||
|
} value;
|
||||||
|
} SpcString;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcString)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OCTET_STRING *classId;
|
||||||
|
ASN1_OCTET_STRING *serializedData;
|
||||||
|
} SpcSerializedObject;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSerializedObject)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int type;
|
||||||
|
union {
|
||||||
|
ASN1_IA5STRING *url;
|
||||||
|
SpcSerializedObject *moniker;
|
||||||
|
SpcString *file;
|
||||||
|
} value;
|
||||||
|
} SpcLink;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcLink)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpcString *programName;
|
||||||
|
SpcLink *moreInfo;
|
||||||
|
} SpcSpOpusInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSpOpusInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *a;
|
||||||
|
ASN1_OCTET_STRING *string;
|
||||||
|
ASN1_INTEGER *b;
|
||||||
|
ASN1_INTEGER *c;
|
||||||
|
ASN1_INTEGER *d;
|
||||||
|
ASN1_INTEGER *e;
|
||||||
|
ASN1_INTEGER *f;
|
||||||
|
} SpcSipInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcSipInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_TYPE *value;
|
||||||
|
} SpcAttributeTypeAndOptionalValue;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcAttributeTypeAndOptionalValue)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *algorithm;
|
||||||
|
ASN1_TYPE *parameters;
|
||||||
|
} AlgorithmIdentifier;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(AlgorithmIdentifier)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AlgorithmIdentifier *digestAlgorithm;
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
} DigestInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(DigestInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
SpcAttributeTypeAndOptionalValue *data;
|
||||||
|
DigestInfo *messageDigest;
|
||||||
|
} SpcIndirectDataContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(SpcIndirectDataContent)
|
||||||
|
|
||||||
|
typedef struct CatalogAuthAttr_st {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_TYPE *contents;
|
||||||
|
} CatalogAuthAttr;
|
||||||
|
|
||||||
|
DEFINE_STACK_OF(CatalogAuthAttr)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatalogAuthAttr)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
AlgorithmIdentifier *digestAlgorithm;
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
} MessageImprint;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(MessageImprint)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
ASN1_OCTET_STRING *signature;
|
||||||
|
} TimeStampRequestBlob;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampRequestBlob)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OBJECT *type;
|
||||||
|
TimeStampRequestBlob *blob;
|
||||||
|
} TimeStampRequest;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampRequest)
|
||||||
|
|
||||||
|
/* RFC3161 Time stamping */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *status;
|
||||||
|
STACK_OF(ASN1_UTF8STRING) *statusString;
|
||||||
|
ASN1_BIT_STRING *failInfo;
|
||||||
|
} PKIStatusInfo;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(PKIStatusInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PKIStatusInfo *status;
|
||||||
|
PKCS7 *token;
|
||||||
|
} TimeStampResp;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampResp)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *version;
|
||||||
|
MessageImprint *messageImprint;
|
||||||
|
ASN1_OBJECT *reqPolicy;
|
||||||
|
ASN1_INTEGER *nonce;
|
||||||
|
ASN1_BOOLEAN certReq;
|
||||||
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
|
} TimeStampReq;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampReq)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *seconds;
|
||||||
|
ASN1_INTEGER *millis;
|
||||||
|
ASN1_INTEGER *micros;
|
||||||
|
} TimeStampAccuracy;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampAccuracy)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_INTEGER *version;
|
||||||
|
ASN1_OBJECT *policy_id;
|
||||||
|
MessageImprint *messageImprint;
|
||||||
|
ASN1_INTEGER *serial;
|
||||||
|
ASN1_GENERALIZEDTIME *time;
|
||||||
|
TimeStampAccuracy *accuracy;
|
||||||
|
ASN1_BOOLEAN ordering;
|
||||||
|
ASN1_INTEGER *nonce;
|
||||||
|
GENERAL_NAME *tsa;
|
||||||
|
STACK_OF(X509_EXTENSION) *extensions;
|
||||||
|
} TimeStampToken;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(TimeStampToken)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ASN1_OCTET_STRING *digest;
|
||||||
|
STACK_OF(CatalogAuthAttr) *attributes;
|
||||||
|
} CatalogInfo;
|
||||||
|
|
||||||
|
DEFINE_STACK_OF(CatalogInfo)
|
||||||
|
DECLARE_ASN1_FUNCTIONS(CatalogInfo)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
/* 1.3.6.1.4.1.311.12.1.1 MS_CATALOG_LIST */
|
||||||
|
SpcAttributeTypeAndOptionalValue *type;
|
||||||
|
ASN1_OCTET_STRING *identifier;
|
||||||
|
ASN1_UTCTIME *time;
|
||||||
|
/* 1.3.6.1.4.1.311.12.1.2 CatalogVersion = 1
|
||||||
|
* 1.3.6.1.4.1.311.12.1.3 CatalogVersion = 2 */
|
||||||
|
SpcAttributeTypeAndOptionalValue *version;
|
||||||
|
STACK_OF(CatalogInfo) *header_attributes;
|
||||||
|
/* 1.3.6.1.4.1.311.12.2.1 CAT_NAMEVALUE_OBJID */
|
||||||
|
ASN1_TYPE *filename;
|
||||||
|
} MsCtlContent;
|
||||||
|
|
||||||
|
DECLARE_ASN1_FUNCTIONS(MsCtlContent)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *server;
|
||||||
|
const char *port;
|
||||||
|
int use_proxy;
|
||||||
|
int timeout;
|
||||||
|
SSL_CTX *ssl_ctx;
|
||||||
|
} HTTP_TLS_Info;
|
||||||
|
|
||||||
|
typedef struct file_format_st FILE_FORMAT;
|
||||||
|
|
||||||
|
typedef struct script_ctx_st SCRIPT_CTX;
|
||||||
|
typedef struct msi_ctx_st MSI_CTX;
|
||||||
|
typedef struct pe_ctx_st PE_CTX;
|
||||||
|
typedef struct cab_ctx_st CAB_CTX;
|
||||||
|
typedef struct cat_ctx_st CAT_CTX;
|
||||||
|
typedef struct appx_ctx_st APPX_CTX;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FILE_FORMAT *format;
|
||||||
|
GLOBAL_OPTIONS *options;
|
||||||
|
union {
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
MSI_CTX *msi_ctx;
|
||||||
|
PE_CTX *pe_ctx;
|
||||||
|
CAB_CTX *cab_ctx;
|
||||||
|
CAT_CTX *cat_ctx;
|
||||||
|
APPX_CTX *appx_ctx;
|
||||||
|
};
|
||||||
|
} FILE_FORMAT_CTX;
|
||||||
|
|
||||||
|
extern FILE_FORMAT file_format_script;
|
||||||
|
extern FILE_FORMAT file_format_msi;
|
||||||
|
extern FILE_FORMAT file_format_pe;
|
||||||
|
extern FILE_FORMAT file_format_cab;
|
||||||
|
extern FILE_FORMAT file_format_cat;
|
||||||
|
extern FILE_FORMAT file_format_appx;
|
||||||
|
|
||||||
|
struct file_format_st {
|
||||||
|
FILE_FORMAT_CTX *(*ctx_new) (GLOBAL_OPTIONS *option, BIO *hash, BIO *outdata);
|
||||||
|
const EVP_MD *(*md_get) (FILE_FORMAT_CTX *ctx);
|
||||||
|
ASN1_OBJECT *(*data_blob_get) (u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
PKCS7 *(*pkcs7_contents_get) (FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
|
int (*hash_length_get) (FILE_FORMAT_CTX *ctx);
|
||||||
|
u_char *(*digest_calc) (FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
int (*verify_digests) (FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
int (*verify_indirect_data) (FILE_FORMAT_CTX *ctx, SpcAttributeTypeAndOptionalValue *obj);
|
||||||
|
PKCS7 *(*pkcs7_extract) (FILE_FORMAT_CTX *ctx);
|
||||||
|
PKCS7 *(*pkcs7_extract_to_nest) (FILE_FORMAT_CTX *ctx);
|
||||||
|
int (*remove_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
int (*process_data) (FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
PKCS7 *(*pkcs7_signature_new) (FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
int (*append_pkcs7) (FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
void (*update_data_size) (FILE_FORMAT_CTX *data, BIO *outdata, PKCS7 *p7);
|
||||||
|
void (*bio_free) (BIO *hash, BIO *outdata);
|
||||||
|
void (*ctx_cleanup) (FILE_FORMAT_CTX *ctx);
|
||||||
|
int (*is_detaching_supported) (void);
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
||||||
+554
@@ -0,0 +1,554 @@
|
|||||||
|
---
|
||||||
|
title: osslsigncode
|
||||||
|
lang: en-US
|
||||||
|
---
|
||||||
|
|
||||||
|
# NAME
|
||||||
|
|
||||||
|
osslsigncode - Authenticode signing, timestamping, extraction, attachment, removal, and verification tool
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
`osslsigncode` [`--help`] [`--version`]
|
||||||
|
|
||||||
|
`osslsigncode` `sign`
|
||||||
|
[`-certs` *file* | `-spc` *file* | `-pkcs12` *file*]
|
||||||
|
[`-key` *file-or-URI*]
|
||||||
|
[`-ac` *file*]
|
||||||
|
[`-pass` *password* | `-readpass` *file* | `-askpass`]
|
||||||
|
[`-pkcs11module` *module*] [`-pkcs11cert` *URI*]
|
||||||
|
[`-engine` *engine*] [`-provider` *provider*]
|
||||||
|
[`-login`] [`-engineCtrl` *command*[:*parameter*]]
|
||||||
|
[`-h` *digest*]
|
||||||
|
[`-n` *description*] [`-i` *URL*]
|
||||||
|
[`-jp` `low`] [`-comm`] [`-ph`]
|
||||||
|
[`-t` *URL* ... | `-ts` *URL* ...]
|
||||||
|
[`-TSA-certs` *file* `-TSA-key` *file-or-URI* [`-TSA-time` *unix-time*]]
|
||||||
|
[`-HTTPS-CAfile` *file*] [`-HTTPS-CRLfile` *file*]
|
||||||
|
[`-time` *unix-time*]
|
||||||
|
[`-addUnauthenticatedBlob` [`-blobFile` *file*]]
|
||||||
|
[`-nest`] [`-add-msi-dse`] [`-verbose`] [`-pem`]
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `extract-data`
|
||||||
|
[`-pem`] [`-h` *digest*] [`-ph`] [`-add-msi-dse`]
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `add`
|
||||||
|
[`-addUnauthenticatedBlob` [`-blobFile` *file*]]
|
||||||
|
[`-t` *URL* ... | `-ts` *URL* ...]
|
||||||
|
[`-TSA-certs` *file* `-TSA-key` *file-or-URI* [`-TSA-time` *unix-time*]]
|
||||||
|
[`-HTTPS-CAfile` *file*] [`-HTTPS-CRLfile` *file*]
|
||||||
|
[`-h` *digest*] [`-index` *n*] [`-verbose`] [`-add-msi-dse`]
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `attach-signature`
|
||||||
|
`-sigin` *signature*
|
||||||
|
[`-h` *digest*] [`-nest`] [`-add-msi-dse`]
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `extract-signature`
|
||||||
|
[`-pem`]
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `remove-signature`
|
||||||
|
`-in` *input* `-out` *output*
|
||||||
|
|
||||||
|
`osslsigncode` `verify`
|
||||||
|
`-in` *input*
|
||||||
|
[`-c` | `-catalog` *catalog-file*]
|
||||||
|
[`-CAfile` *file*] [`-CRLfile` *file*]
|
||||||
|
[`-HTTPS-CAfile` *file*] [`-HTTPS-CRLfile` *file*]
|
||||||
|
[`-TSA-CAfile` *file*] [`-TSA-CRLfile` *file*]
|
||||||
|
[`-p` *proxy*] [`-index` *n*]
|
||||||
|
[`-ignore-timestamp`] [`-ignore-cdp`] [`-ignore-crl`]
|
||||||
|
[`-time` *unix-time*]
|
||||||
|
[`-require-leaf-hash` *alg*:*hex*]
|
||||||
|
[`-verbose`]
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
`osslsigncode` signs and verifies Microsoft Authenticode signatures on
|
||||||
|
supported file formats. It can also extract data for detached signing,
|
||||||
|
attach an externally produced signature, add timestamps or unauthenticated
|
||||||
|
blobs to an existing signature, and remove an embedded signature.
|
||||||
|
|
||||||
|
Supported input formats include PE files such as EXE, DLL, and SYS, CAB,
|
||||||
|
CAT, MSI, APPX, and several script file types, including `.ps1`, `.ps1xml`,
|
||||||
|
`.psc1`, `.psd1`, `.psm1`, `.cdxml`, `.mof`, and `.js`.
|
||||||
|
|
||||||
|
The program supports these common workflows:
|
||||||
|
|
||||||
|
- direct signing of an unsigned file
|
||||||
|
- detached signing via `extract-data`, `sign`, and `attach-signature`
|
||||||
|
- post-sign timestamping with `add`
|
||||||
|
- verification of embedded signatures or catalog signatures with `verify`
|
||||||
|
|
||||||
|
If no subcommand is given, `sign` is assumed.
|
||||||
|
|
||||||
|
# FORMATS
|
||||||
|
|
||||||
|
Support is not identical across all file formats.
|
||||||
|
|
||||||
|
In particular, detached-signature workflows, nested signatures, catalog-based
|
||||||
|
verification, and signature removal are format-dependent features. A command
|
||||||
|
that is valid for one supported file type may be unsupported for another.
|
||||||
|
|
||||||
|
CAT files are a special case. They are detached catalog containers for
|
||||||
|
hashes of other files, not ordinary embedded-signature payloads. A CAT
|
||||||
|
file is itself a PKCS#7 structure containing authenticated entries for one
|
||||||
|
or more external files. In practice, the catalog signs file digests
|
||||||
|
recorded in the catalog, rather than embedding a signature into each
|
||||||
|
covered file.
|
||||||
|
|
||||||
|
Because of this, CAT files behave differently from embedded-signature
|
||||||
|
formats. They do not support `attach-signature`, `remove-signature`,
|
||||||
|
`extract-data`, or nested signatures.
|
||||||
|
|
||||||
|
MSI files are also a special case. They support an extended signature mode
|
||||||
|
controlled by `-add-msi-dse`. In this mode, the MSI signature covers file
|
||||||
|
metadata as well as file content. Detached-signing workflows and any later
|
||||||
|
re-signing or nesting operations must use a mode consistent with the MSI
|
||||||
|
file's existing signature structure.
|
||||||
|
|
||||||
|
# COMMANDS
|
||||||
|
|
||||||
|
## `sign`
|
||||||
|
|
||||||
|
Create a new Authenticode signature.
|
||||||
|
|
||||||
|
This command can sign a normal unsigned file, or it can sign PKCS#7 data
|
||||||
|
previously produced by `extract-data`.
|
||||||
|
|
||||||
|
## `extract-data`
|
||||||
|
|
||||||
|
Extract the PKCS#7 content to be signed later. This is used for detached
|
||||||
|
signing workflows.
|
||||||
|
|
||||||
|
## `add`
|
||||||
|
|
||||||
|
Add unauthenticated attributes to an existing signature, typically an
|
||||||
|
Authenticode timestamp, an RFC 3161 timestamp, or an unauthenticated blob.
|
||||||
|
|
||||||
|
With `-index`, the selected signature in a multi-signature file is updated.
|
||||||
|
|
||||||
|
## `attach-signature`
|
||||||
|
|
||||||
|
Attach a detached PKCS#7 signature to an input file.
|
||||||
|
|
||||||
|
With `-nest`, the new signature is attached as a nested signature instead of
|
||||||
|
replacing the primary one, if the file format supports nested signatures.
|
||||||
|
|
||||||
|
## `extract-signature`
|
||||||
|
|
||||||
|
Extract the embedded PKCS#7 signature from a signed file.
|
||||||
|
|
||||||
|
## `remove-signature`
|
||||||
|
|
||||||
|
Remove the embedded signature from a signed file.
|
||||||
|
|
||||||
|
## `verify`
|
||||||
|
|
||||||
|
Verify an embedded signature or a catalog signature.
|
||||||
|
|
||||||
|
Verification may include digest consistency, certificate chain validation,
|
||||||
|
certificate revocation checking, timestamp validation, and optional checking
|
||||||
|
of the signer's leaf certificate hash.
|
||||||
|
|
||||||
|
When verifying that a file is covered by a catalog, use `verify -catalog
|
||||||
|
catalog.cat -in file`. Verifying the CAT file by itself validates the
|
||||||
|
catalog signature; verifying with `-catalog` checks whether the specified
|
||||||
|
input file is covered by that catalog.
|
||||||
|
|
||||||
|
# OPTIONS
|
||||||
|
|
||||||
|
Some options are available only in particular builds or OpenSSL versions.
|
||||||
|
In particular, `-askpass` is build-dependent, `-provider` and `-nolegacy`
|
||||||
|
require OpenSSL 3, and engine-related options depend on engine support in the
|
||||||
|
build.
|
||||||
|
|
||||||
|
## General options
|
||||||
|
|
||||||
|
`--help`
|
||||||
|
: Show help text. With a subcommand, show help for that subcommand.
|
||||||
|
|
||||||
|
`-v`, `--version`
|
||||||
|
: Show version information.
|
||||||
|
|
||||||
|
`-in` *file*
|
||||||
|
: Input file.
|
||||||
|
|
||||||
|
`-out` *file*
|
||||||
|
: Output file. Required for all commands except `verify`.
|
||||||
|
|
||||||
|
`-verbose`
|
||||||
|
: Produce more detailed diagnostic output.
|
||||||
|
|
||||||
|
## Signing material
|
||||||
|
|
||||||
|
`-pkcs12` *file*
|
||||||
|
: Read the signing certificate and private key from a PKCS#12 container.
|
||||||
|
|
||||||
|
`-certs`, `-spc` *file*
|
||||||
|
: Read the signing certificate chain. The historical alias `-spc` is accepted.
|
||||||
|
|
||||||
|
`-key` *file-or-URI*
|
||||||
|
: Read the private key. This may also be a store or PKCS#11 URI.
|
||||||
|
|
||||||
|
`-ac` *file*
|
||||||
|
: Add extra certificates to the signature block.
|
||||||
|
|
||||||
|
`-pass` *password*
|
||||||
|
: Password or PIN for the key, token, or PKCS#12 container.
|
||||||
|
|
||||||
|
`-readpass` *file*
|
||||||
|
: Read the password or PIN from *file*. Use `-` to read from standard input.
|
||||||
|
|
||||||
|
`-askpass`
|
||||||
|
: Prompt for the password interactively.
|
||||||
|
|
||||||
|
## PKCS#11, engines, and providers
|
||||||
|
|
||||||
|
`-pkcs11module` *module*
|
||||||
|
: Path to a PKCS#11 module.
|
||||||
|
|
||||||
|
`-pkcs11cert` *URI*
|
||||||
|
: PKCS#11 URI identifying the certificate object.
|
||||||
|
|
||||||
|
`-provider` *provider*
|
||||||
|
: OpenSSL 3 provider to load. This is the preferred modern interface for
|
||||||
|
provider-based PKCS#11 use.
|
||||||
|
|
||||||
|
`-engine`, `-pkcs11engine` *engine*
|
||||||
|
: OpenSSL engine identifier or path to a dynamic engine module. This
|
||||||
|
interface is retained for compatibility with builds and deployments that
|
||||||
|
still support engines.
|
||||||
|
|
||||||
|
`-login`
|
||||||
|
: Force login to the token for engine-based PKCS#11 use.
|
||||||
|
|
||||||
|
`-engineCtrl` *command*[:*parameter*]
|
||||||
|
: Pass a control command to the selected engine.
|
||||||
|
|
||||||
|
`-nolegacy`
|
||||||
|
: On OpenSSL 3 builds, do not automatically load the legacy provider.
|
||||||
|
|
||||||
|
## Signature contents and digest control
|
||||||
|
|
||||||
|
`-h` `md5` | `sha1` | `sha2` | `sha256` | `sha384` | `sha512`
|
||||||
|
: Select the digest algorithm. The default is `sha256`. `sha2` and
|
||||||
|
`sha256` are equivalent.
|
||||||
|
|
||||||
|
`-n` *description*
|
||||||
|
: Description of the signed content.
|
||||||
|
|
||||||
|
`-i` *URL*
|
||||||
|
: Informational URL associated with the signed content.
|
||||||
|
|
||||||
|
`-comm`
|
||||||
|
: Use Microsoft Commercial Code Signing purpose instead of the default
|
||||||
|
individual purpose.
|
||||||
|
|
||||||
|
`-jp` `low`
|
||||||
|
: Add the Java CAB permission attribute. Only `low` is currently supported.
|
||||||
|
|
||||||
|
`-ph`
|
||||||
|
: Generate page hashes for executable files.
|
||||||
|
|
||||||
|
`-add-msi-dse`
|
||||||
|
: For MSI files, enable the `MsiDigitalSignatureEx` signing mode. In this
|
||||||
|
mode, the signature covers MSI metadata as well as file content. The
|
||||||
|
metadata portion includes stream names, sizes, and selected timestamps in
|
||||||
|
the MSI structure. This option changes the MSI signature format and should
|
||||||
|
be used consistently in any detached-signing workflow involving
|
||||||
|
`extract-data`, `sign`, `attach-signature`, or `add`.
|
||||||
|
|
||||||
|
For a newly signed MSI, this mode is generally preferred because it extends
|
||||||
|
signing coverage beyond file content alone. For an already signed MSI,
|
||||||
|
however, the chosen mode must match the file's existing signature
|
||||||
|
structure. Switching between basic MSI signing and `MsiDigitalSignatureEx`
|
||||||
|
during re-signing or nested-signature operations can invalidate the
|
||||||
|
existing signature.
|
||||||
|
|
||||||
|
`-pem`
|
||||||
|
: Write PKCS#7 output in PEM format instead of DER.
|
||||||
|
|
||||||
|
## Timestamping and network options
|
||||||
|
|
||||||
|
The following timestamping modes are **mutually exclusive** within a single
|
||||||
|
`sign` or `add` invocation:
|
||||||
|
|
||||||
|
- Authenticode timestamping with `-t`
|
||||||
|
- RFC 3161 timestamping with `-ts`
|
||||||
|
- built-in RFC 3161 timestamp generation with `-TSA-certs` and `-TSA-key`
|
||||||
|
|
||||||
|
`-t` *URL*
|
||||||
|
: Add an Authenticode timestamp from the specified URL. May be repeated.
|
||||||
|
|
||||||
|
`-ts` *URL*
|
||||||
|
: Add an RFC 3161 timestamp from the specified URL. May be repeated.
|
||||||
|
|
||||||
|
`-p` *proxy*
|
||||||
|
: Proxy used for timestamp or CRL retrieval.
|
||||||
|
|
||||||
|
`-noverifypeer`
|
||||||
|
: Do not verify the TLS certificate of the remote timestamp service.
|
||||||
|
|
||||||
|
`-HTTPS-CAfile` *file*
|
||||||
|
: PEM bundle used to verify HTTPS peers contacted by `osslsigncode`.
|
||||||
|
|
||||||
|
`-HTTPS-CRLfile` *file*
|
||||||
|
: PEM CRL file used while verifying HTTPS peers.
|
||||||
|
|
||||||
|
`-TSA-certs` *file*
|
||||||
|
: PEM certificate chain for locally generated RFC 3161 timestamps.
|
||||||
|
|
||||||
|
`-TSA-key` *file-or-URI*
|
||||||
|
: Private key for locally generated RFC 3161 timestamps.
|
||||||
|
|
||||||
|
`-TSA-time` *unix-time*
|
||||||
|
: Timestamp time for locally generated RFC 3161 responses.
|
||||||
|
|
||||||
|
## Nested signatures and indexed operations
|
||||||
|
|
||||||
|
`-nest`
|
||||||
|
: Add a nested signature instead of replacing the primary signature.
|
||||||
|
|
||||||
|
`-index` *n*
|
||||||
|
: Select a signature by index for `add` or `verify`. Index 0 is the primary
|
||||||
|
signature.
|
||||||
|
|
||||||
|
## Unauthenticated blob options
|
||||||
|
|
||||||
|
`-addUnauthenticatedBlob`
|
||||||
|
: Add an unauthenticated blob to the signature.
|
||||||
|
|
||||||
|
`-blobFile` *file*
|
||||||
|
: Read blob contents from *file*. If omitted, a placeholder blob is created.
|
||||||
|
|
||||||
|
## Verification options
|
||||||
|
|
||||||
|
`-c`, `-catalog` *file*
|
||||||
|
: Verify the input file against the specified catalog file.
|
||||||
|
|
||||||
|
`-CAfile` *file*
|
||||||
|
: PEM bundle of trusted CA certificates for signer validation.
|
||||||
|
|
||||||
|
`-CRLfile` *file*
|
||||||
|
: PEM file containing CRLs for signer validation.
|
||||||
|
|
||||||
|
`-TSA-CAfile`, `-untrusted` *file*
|
||||||
|
: PEM bundle of trusted CA certificates for timestamp validation.
|
||||||
|
|
||||||
|
`-TSA-CRLfile`, `-CRLuntrusted` *file*
|
||||||
|
: PEM file containing CRLs for timestamp validation.
|
||||||
|
|
||||||
|
`-time`, `-st` *unix-time*
|
||||||
|
: Verification time. If a valid timestamp is present and used, chain
|
||||||
|
validation is normally performed at the timestamp time.
|
||||||
|
|
||||||
|
`-ignore-timestamp`
|
||||||
|
: Skip verification of the timestamp signature.
|
||||||
|
|
||||||
|
`-ignore-cdp`
|
||||||
|
: Do not fetch CRLs from CRL Distribution Points.
|
||||||
|
|
||||||
|
`-ignore-crl`
|
||||||
|
: Disable CRL retrieval and CRL validation.
|
||||||
|
|
||||||
|
`-require-leaf-hash` *alg*:*hex*
|
||||||
|
: Require the signer's leaf certificate to hash to the specified value.
|
||||||
|
The hash is computed over the DER encoding of the leaf certificate.
|
||||||
|
|
||||||
|
# EXIT STATUS
|
||||||
|
|
||||||
|
`0`
|
||||||
|
: Success.
|
||||||
|
|
||||||
|
non-zero
|
||||||
|
: Failure.
|
||||||
|
|
||||||
|
# DIAGNOSTICS
|
||||||
|
|
||||||
|
Common causes of failure include:
|
||||||
|
|
||||||
|
missing CA trust bundle
|
||||||
|
: On Unix-like systems, `verify` expects a readable CA bundle, either from
|
||||||
|
`-CAfile` or from a detected system default.
|
||||||
|
|
||||||
|
detached-signing mismatch
|
||||||
|
: `extract-data`, `sign`, and `attach-signature` must use compatible
|
||||||
|
digest-affecting options such as `-h`, and where relevant `-ph` and
|
||||||
|
`-add-msi-dse`.
|
||||||
|
|
||||||
|
unsupported format feature
|
||||||
|
: Some file formats do not support every subcommand or every signature mode.
|
||||||
|
|
||||||
|
missing TSA trust chain
|
||||||
|
: Timestamp verification may fail unless the appropriate TSA trust anchors
|
||||||
|
are supplied with `-TSA-CAfile`, and where needed `-TSA-CRLfile`.
|
||||||
|
|
||||||
|
conflicting timestamp modes
|
||||||
|
: `-t`, `-ts`, and built-in TSA signing cannot be combined in one command.
|
||||||
|
|
||||||
|
MSI signature mode mismatch
|
||||||
|
: Re-signing or nesting an MSI signature must be consistent with whether the
|
||||||
|
file already uses `MsiDigitalSignatureEx`. Mixing modes may invalidate the
|
||||||
|
existing signature.
|
||||||
|
|
||||||
|
# ENVIRONMENT
|
||||||
|
|
||||||
|
`HTTP_PROXY`, `http_proxy`
|
||||||
|
: Default proxy for HTTP access if `-p` is not given.
|
||||||
|
|
||||||
|
`HTTPS_PROXY`, `https_proxy`
|
||||||
|
: Default proxy for HTTPS access if `-p` is not given.
|
||||||
|
|
||||||
|
`OPENSSL_ENGINES`
|
||||||
|
: May help OpenSSL find engine modules.
|
||||||
|
|
||||||
|
# FILES
|
||||||
|
|
||||||
|
On Unix-like systems, `osslsigncode` tries common CA bundle locations for
|
||||||
|
its default `-CAfile`, including:
|
||||||
|
|
||||||
|
- `/etc/ssl/certs/ca-certificates.crt`
|
||||||
|
- `/etc/pki/tls/certs/ca-bundle.crt`
|
||||||
|
- `/usr/share/ssl/certs/ca-bundle.crt`
|
||||||
|
- `/usr/local/share/certs/ca-root-nss.crt`
|
||||||
|
- `/etc/ssl/cert.pem`
|
||||||
|
|
||||||
|
If no readable CA bundle is available, `verify` may require an explicit
|
||||||
|
`-CAfile`.
|
||||||
|
|
||||||
|
# NOTES
|
||||||
|
|
||||||
|
Use `extract-data` when you need to create a new detached signature object.
|
||||||
|
Use `extract-signature` when you need to copy an existing embedded PKCS#7
|
||||||
|
signature out of a file.
|
||||||
|
|
||||||
|
For safer secret handling, prefer `-readpass` or `-askpass` over `-pass`.
|
||||||
|
|
||||||
|
Data added with `-addUnauthenticatedBlob` is not protected by the signature
|
||||||
|
and must not be treated as trusted.
|
||||||
|
|
||||||
|
For new MSI signatures, `-add-msi-dse` is generally preferred because it
|
||||||
|
extends signing coverage to MSI metadata as well as file content. However,
|
||||||
|
it is format-affecting rather than cosmetic, so existing signed MSI files
|
||||||
|
should be re-signed only in a mode consistent with their current signature
|
||||||
|
structure.
|
||||||
|
|
||||||
|
Output files are not overwritten.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
## Sign and verify a file
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 signer.p12 \
|
||||||
|
-readpass p12-pass.txt \
|
||||||
|
-n "Example Application" \
|
||||||
|
-i "https://example.com/" \
|
||||||
|
-ts "https://tsa.example.net/" \
|
||||||
|
-in app.exe \
|
||||||
|
-out app-signed.exe
|
||||||
|
|
||||||
|
osslsigncode verify \
|
||||||
|
-CAfile ca-bundle.pem \
|
||||||
|
-TSA-CAfile tsa-ca-bundle.pem \
|
||||||
|
-in app-signed.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Detached signing workflow
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode extract-data \
|
||||||
|
-h sha384 \
|
||||||
|
-ph \
|
||||||
|
-in app.exe \
|
||||||
|
-out app-data.der
|
||||||
|
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 signer.p12 \
|
||||||
|
-readpass p12-pass.txt \
|
||||||
|
-h sha384 \
|
||||||
|
-in app-data.der \
|
||||||
|
-out app-sig.der
|
||||||
|
|
||||||
|
osslsigncode attach-signature \
|
||||||
|
-h sha384 \
|
||||||
|
-sigin app-sig.der \
|
||||||
|
-in app.exe \
|
||||||
|
-out app-signed.exe
|
||||||
|
|
||||||
|
osslsigncode verify \
|
||||||
|
-CAfile ca-bundle.pem \
|
||||||
|
-in app-signed.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sign a new MSI with extended MSI metadata coverage
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode sign \
|
||||||
|
-pkcs12 signer.p12 \
|
||||||
|
-readpass p12-pass.txt \
|
||||||
|
-add-msi-dse \
|
||||||
|
-in installer.msi \
|
||||||
|
-out installer-signed.msi
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use a PKCS#11 provider
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode sign \
|
||||||
|
-provider /path/to/pkcs11prov.so \
|
||||||
|
-pkcs11module /path/to/opensc-pkcs11.so \
|
||||||
|
-pkcs11cert 'pkcs11:token=my-token;object=cert' \
|
||||||
|
-key 'pkcs11:token=my-token;object=key' \
|
||||||
|
-readpass pin.txt \
|
||||||
|
-in app.exe \
|
||||||
|
-out app-signed.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add a timestamp to an already signed file
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode add \
|
||||||
|
-ts "https://tsa.example.net/" \
|
||||||
|
-in app-signed.exe \
|
||||||
|
-out app-signed-ts.exe
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verify that a file is covered by a catalog
|
||||||
|
|
||||||
|
```sh
|
||||||
|
osslsigncode verify \
|
||||||
|
-catalog drivers.cat \
|
||||||
|
-CAfile ca-bundle.pem \
|
||||||
|
-CRLfile ca-crl.pem \
|
||||||
|
-in driver.sys
|
||||||
|
```
|
||||||
|
|
||||||
|
# REPORTING BUGS
|
||||||
|
|
||||||
|
Report bugs and suspected issues via the project issue tracker:
|
||||||
|
|
||||||
|
<https://github.com/mtrojnar/osslsigncode/issues>
|
||||||
|
|
||||||
|
# AUTHORS
|
||||||
|
|
||||||
|
Originally written by Per Allansson.
|
||||||
|
|
||||||
|
Maintained and extended by Michał Trojnara.
|
||||||
|
|
||||||
|
Major contributions by Małgorzata Olszówka.
|
||||||
|
|
||||||
|
Additional contributions by other project contributors.
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
|
||||||
|
**OpenSSL** Library
|
||||||
|
|
||||||
|
<https://openssl-library.org/>
|
||||||
|
|
||||||
@@ -0,0 +1,892 @@
|
|||||||
|
/*
|
||||||
|
* Script file support library
|
||||||
|
*
|
||||||
|
* Copyright (C) 2021-2024 Michał Trojnara <Michal.Trojnara@stunnel.org>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "osslsigncode.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
#include "utf.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
comment_hash,
|
||||||
|
comment_xml,
|
||||||
|
comment_c,
|
||||||
|
comment_js,
|
||||||
|
comment_not_found
|
||||||
|
} COMMENT_STYLE;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *extension;
|
||||||
|
COMMENT_STYLE comment;
|
||||||
|
} SCRIPT_FORMAT;
|
||||||
|
|
||||||
|
const SCRIPT_FORMAT supported_formats[] = {
|
||||||
|
{".ps1", comment_hash},
|
||||||
|
{".ps1xml", comment_xml},
|
||||||
|
{".psc1", comment_xml},
|
||||||
|
{".psd1", comment_hash},
|
||||||
|
{".psm1", comment_hash},
|
||||||
|
{".cdxml", comment_xml},
|
||||||
|
{".mof", comment_c},
|
||||||
|
{".js", comment_js},
|
||||||
|
{NULL, comment_not_found},
|
||||||
|
};
|
||||||
|
|
||||||
|
#define header_hash "SIG # Begin signature block"
|
||||||
|
#define footer_hash "SIG # End signature block"
|
||||||
|
#define header_js "Begin signature block"
|
||||||
|
#define footer_js "End signature block"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *open, *close, *header, *footer;
|
||||||
|
} SCRIPT_COMMENT;
|
||||||
|
|
||||||
|
const SCRIPT_COMMENT comment_text[] = {
|
||||||
|
[comment_hash] = {"# ", "", header_hash, footer_hash},
|
||||||
|
[comment_xml] = {"<!-- ", " -->", header_hash, footer_hash},
|
||||||
|
[comment_c] = {"/* ", " */", header_hash, footer_hash},
|
||||||
|
[comment_js] = {"// SIG // ", "", header_js, footer_js}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct script_ctx_st {
|
||||||
|
const SCRIPT_COMMENT *comment_text;
|
||||||
|
int utf;
|
||||||
|
uint32_t sigpos;
|
||||||
|
uint32_t fileend;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LINE_MAX_LEN 100
|
||||||
|
|
||||||
|
/* FILE_FORMAT method prototypes */
|
||||||
|
static FILE_FORMAT_CTX *script_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata);
|
||||||
|
static ASN1_OBJECT *script_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *script_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md);
|
||||||
|
static int script_hash_length_get(FILE_FORMAT_CTX *ctx);
|
||||||
|
static u_char *script_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7);
|
||||||
|
static PKCS7 *script_pkcs7_extract(FILE_FORMAT_CTX *ctx);
|
||||||
|
static PKCS7 *script_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int script_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static int script_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata);
|
||||||
|
static PKCS7 *script_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash);
|
||||||
|
static int script_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7);
|
||||||
|
static void script_bio_free(BIO *hash, BIO *outdata);
|
||||||
|
static void script_ctx_cleanup(FILE_FORMAT_CTX *ctx);
|
||||||
|
static int script_is_detaching_supported(void);
|
||||||
|
|
||||||
|
FILE_FORMAT file_format_script = {
|
||||||
|
.ctx_new = script_ctx_new,
|
||||||
|
.data_blob_get = script_spc_sip_info_get,
|
||||||
|
.pkcs7_contents_get = script_pkcs7_contents_get,
|
||||||
|
.hash_length_get = script_hash_length_get,
|
||||||
|
.digest_calc = script_digest_calc,
|
||||||
|
.verify_digests = script_verify_digests,
|
||||||
|
.pkcs7_extract = script_pkcs7_extract,
|
||||||
|
.pkcs7_extract_to_nest = script_pkcs7_extract_to_nest,
|
||||||
|
.remove_pkcs7 = script_remove_pkcs7,
|
||||||
|
.process_data = script_process_data,
|
||||||
|
.pkcs7_signature_new = script_pkcs7_signature_new,
|
||||||
|
.append_pkcs7 = script_append_pkcs7,
|
||||||
|
.bio_free = script_bio_free,
|
||||||
|
.ctx_cleanup = script_ctx_cleanup,
|
||||||
|
.is_detaching_supported = script_is_detaching_supported
|
||||||
|
};
|
||||||
|
|
||||||
|
/* helper functions */
|
||||||
|
static SCRIPT_CTX *script_ctx_get(char *indata, uint32_t filesize, const SCRIPT_COMMENT *comment, int utf);
|
||||||
|
static int write_commented(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *data, size_t length);
|
||||||
|
static int write_in_encoding(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *line, size_t length);
|
||||||
|
static size_t utf8_to_utf16(const char *data, size_t len, uint16_t **out_utf16);
|
||||||
|
static size_t utf16_to_utf8(const uint16_t *data, size_t len, char **out_utf8);
|
||||||
|
static BIO *script_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md);
|
||||||
|
static int script_digest_convert(BIO *hash, FILE_FORMAT_CTX *ctx, size_t len);
|
||||||
|
static int script_write_bio(BIO *data, char *indata, size_t len);
|
||||||
|
static int script_check_file(FILE_FORMAT_CTX *ctx);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a script file format context.
|
||||||
|
* [in, out] options: structure holds the input data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [in] outdata: outdata file BIO (unused)
|
||||||
|
* [returns] pointer to script file format context
|
||||||
|
*/
|
||||||
|
static FILE_FORMAT_CTX *script_ctx_new(GLOBAL_OPTIONS *options, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
FILE_FORMAT_CTX *ctx;
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
const SCRIPT_FORMAT *fmt;
|
||||||
|
uint32_t filesize;
|
||||||
|
const uint8_t utf16_bom[] = {0xff, 0xfe};
|
||||||
|
size_t name_len;
|
||||||
|
int utf;
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)outdata;
|
||||||
|
|
||||||
|
/* find out whether our format is supported */
|
||||||
|
name_len = strlen(options->infile);
|
||||||
|
for (fmt = supported_formats; fmt->comment != comment_not_found; fmt++) {
|
||||||
|
size_t ext_len = strlen(fmt->extension);
|
||||||
|
if(name_len > ext_len && !strcasecmp(options->infile + name_len - ext_len, fmt->extension))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fmt->comment == comment_not_found)
|
||||||
|
return NULL;
|
||||||
|
printf("Script file format: %s\n", fmt->extension);
|
||||||
|
|
||||||
|
filesize = get_file_size(options->infile);
|
||||||
|
if (filesize == 0)
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
|
||||||
|
options->indata = map_file(options->infile, filesize);
|
||||||
|
if (!options->indata) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
utf = memcmp(options->indata, utf16_bom, sizeof utf16_bom) ? 8 : 16;
|
||||||
|
|
||||||
|
/* initialize script context */
|
||||||
|
script_ctx = script_ctx_get(options->indata, filesize, comment_text + fmt->comment, utf);
|
||||||
|
if (!script_ctx) {
|
||||||
|
unmap_file(options->indata, filesize);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* initialize file format context */
|
||||||
|
ctx = OPENSSL_malloc(sizeof(FILE_FORMAT_CTX));
|
||||||
|
memset(ctx, 0, sizeof(FILE_FORMAT_CTX));
|
||||||
|
ctx->format = &file_format_script;
|
||||||
|
ctx->options = options;
|
||||||
|
ctx->script_ctx = script_ctx;
|
||||||
|
|
||||||
|
if (hash)
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
|
||||||
|
/* FIXME: user interface logic belongs to osslsigncode.c */
|
||||||
|
if (options->pagehash == 1)
|
||||||
|
printf("Warning: -ph option is only valid for PE files\n");
|
||||||
|
if (options->jp >= 0)
|
||||||
|
printf("Warning: -jp option is only valid for CAB files\n");
|
||||||
|
return ctx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return SpcSipInfo object.
|
||||||
|
* Subject Interface Package (SIP) is an internal Microsoft API for
|
||||||
|
* transforming arbitrary files into a digestible stream.
|
||||||
|
* These ClassIDs are found in the indirect data section and identify
|
||||||
|
* the type of processor needed to validate the signature.
|
||||||
|
* https://github.com/sassoftware/relic/blob/620d0b75ec67c0158a8a9120950abe04327d922f/lib/authenticode/structs.go#L154
|
||||||
|
* [out] p: SpcSipInfo data
|
||||||
|
* [out] plen: SpcSipInfo data length
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to ASN1_OBJECT structure corresponding to SPC_SIPINFO_OBJID
|
||||||
|
*/
|
||||||
|
static ASN1_OBJECT *script_spc_sip_info_get(u_char **p, int *plen, FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
const u_char SpcUUIDSipInfoPs[] = {
|
||||||
|
0x1f, 0xcc, 0x3b, 0x60, 0x59, 0x4b, 0x08, 0x4e,
|
||||||
|
0xb7, 0x24, 0xd2, 0xc6, 0x29, 0x7e, 0xf3, 0x51
|
||||||
|
};
|
||||||
|
ASN1_OBJECT *dtype;
|
||||||
|
SpcSipInfo *si = SpcSipInfo_new();
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)ctx;
|
||||||
|
|
||||||
|
ASN1_INTEGER_set(si->a, 65536);
|
||||||
|
ASN1_INTEGER_set(si->b, 0);
|
||||||
|
ASN1_INTEGER_set(si->c, 0);
|
||||||
|
ASN1_INTEGER_set(si->d, 0);
|
||||||
|
ASN1_INTEGER_set(si->e, 0);
|
||||||
|
ASN1_INTEGER_set(si->f, 0);
|
||||||
|
ASN1_OCTET_STRING_set(si->string, SpcUUIDSipInfoPs, sizeof SpcUUIDSipInfoPs);
|
||||||
|
*plen = i2d_SpcSipInfo(si, NULL);
|
||||||
|
*p = OPENSSL_malloc((size_t)*plen);
|
||||||
|
i2d_SpcSipInfo(si, p);
|
||||||
|
*p -= *plen;
|
||||||
|
dtype = OBJ_txt2obj(SPC_SIPINFO_OBJID, 1);
|
||||||
|
SpcSipInfo_free(si);
|
||||||
|
return dtype; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate and return a data content to be signed.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] hash: message digest BIO
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] data content
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_contents_get(FILE_FORMAT_CTX *ctx, BIO *hash, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
BIO *bhash;
|
||||||
|
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)hash;
|
||||||
|
|
||||||
|
bhash = script_digest_calc_bio(ctx, md);
|
||||||
|
if (!bhash) {
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(bhash, ctx);
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
return pkcs7_set_content(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_hash_length_get(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return EVP_MD_size(ctx->options->md);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a simple sha1/sha256 message digest of the MSI file
|
||||||
|
* for use with a catalog file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] pointer to calculated message digest
|
||||||
|
*/
|
||||||
|
static u_char *script_digest_calc(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
u_char *mdbuf;
|
||||||
|
BIO *hash = BIO_new(BIO_f_md());
|
||||||
|
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||||
|
#endif
|
||||||
|
if (!BIO_set_md(hash, md)) {
|
||||||
|
fprintf(stderr, "Unable to set the message digest of BIO\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
if (!script_write_bio(hash, ctx->options->indata, ctx->script_ctx->fileend)) {
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
mdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
||||||
|
BIO_gets(hash, (char*)mdbuf, EVP_MD_size(md));
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return mdbuf; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate the hash and compare to PKCS#7 signedData.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_verify_digests(FILE_FORMAT_CTX *ctx, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
int mdtype = -1;
|
||||||
|
u_char mdbuf[EVP_MAX_MD_SIZE];
|
||||||
|
u_char *cmdbuf = NULL;
|
||||||
|
const EVP_MD *md;
|
||||||
|
BIO *bhash;
|
||||||
|
|
||||||
|
if (!pkcs7_get_content_digest(p7, mdbuf, &mdtype)) {
|
||||||
|
fprintf(stderr, "Failed to extract current message digest\n\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
md = EVP_get_digestbynid(mdtype);
|
||||||
|
bhash = script_digest_calc_bio(ctx, md);
|
||||||
|
if (!bhash)
|
||||||
|
return 0; /* FAILED */
|
||||||
|
|
||||||
|
cmdbuf = OPENSSL_malloc((size_t)EVP_MD_size(md));
|
||||||
|
BIO_gets(bhash, (char*)cmdbuf, EVP_MD_size(md));
|
||||||
|
BIO_free_all(bhash);
|
||||||
|
|
||||||
|
if (!compare_digests(mdbuf, cmdbuf, mdtype)) {
|
||||||
|
fprintf(stderr, "Signature verification: failed\n\n");
|
||||||
|
OPENSSL_free(cmdbuf);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(cmdbuf);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_extract(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
const char *signature_data = ctx->options->indata + ctx->script_ctx->sigpos;
|
||||||
|
size_t signature_len = ctx->script_ctx->fileend - ctx->script_ctx->sigpos;
|
||||||
|
size_t base64_len;
|
||||||
|
char *ptr;
|
||||||
|
BIO *bio_mem, *bio_b64 = NULL;
|
||||||
|
char *base64_data = NULL;
|
||||||
|
char *clean_base64 = NULL;
|
||||||
|
int clean_base64_len = 0;
|
||||||
|
const char *open_tag = ctx->script_ctx->comment_text->open;
|
||||||
|
const char *close_tag = ctx->script_ctx->comment_text->close;
|
||||||
|
size_t open_tag_len = strlen(open_tag);
|
||||||
|
size_t close_tag_len = strlen(close_tag);
|
||||||
|
size_t header_len = strlen(ctx->script_ctx->comment_text->header);
|
||||||
|
size_t footer_len = strlen(ctx->script_ctx->comment_text->footer);
|
||||||
|
PKCS7 *retval = NULL;
|
||||||
|
|
||||||
|
if (!script_check_file(ctx)) {
|
||||||
|
return NULL; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
/* extract Base64 signature */
|
||||||
|
if (ctx->script_ctx->utf == 8) {
|
||||||
|
base64_len = signature_len;
|
||||||
|
base64_data = OPENSSL_malloc(base64_len);
|
||||||
|
if (!base64_data)
|
||||||
|
return NULL; /* memory allocation failed */
|
||||||
|
memcpy(base64_data, signature_data, base64_len);
|
||||||
|
} else {
|
||||||
|
base64_len = utf16_to_utf8((const void *)signature_data,
|
||||||
|
signature_len, &base64_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate memory for cleaned Base64 */
|
||||||
|
clean_base64 = OPENSSL_malloc(base64_len);
|
||||||
|
if (!clean_base64) {
|
||||||
|
fprintf(stderr, "Malloc failed\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* copy clean Base64 data */
|
||||||
|
for (ptr = base64_data;;) {
|
||||||
|
/* find the opening tag */
|
||||||
|
for(;;) {
|
||||||
|
if (ptr + open_tag_len >= base64_data + base64_len) {
|
||||||
|
fprintf(stderr, "Signature line too long\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (!memcmp(ptr, open_tag, (size_t)open_tag_len)) {
|
||||||
|
ptr += open_tag_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ptr++;
|
||||||
|
}
|
||||||
|
/* process header and footer */
|
||||||
|
if (ptr + header_len < base64_data + base64_len &&
|
||||||
|
!memcmp(ptr, ctx->script_ctx->comment_text->header, header_len))
|
||||||
|
ptr += header_len;
|
||||||
|
if (ptr + footer_len <= base64_data + base64_len &&
|
||||||
|
!memcmp(ptr, ctx->script_ctx->comment_text->footer, footer_len))
|
||||||
|
break; /* success */
|
||||||
|
|
||||||
|
/* copy until the closing tag */
|
||||||
|
for(;;) {
|
||||||
|
if (ptr + close_tag_len >= base64_data + base64_len) {
|
||||||
|
fprintf(stderr, "Signature line too long\n");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
if (close_tag_len) {
|
||||||
|
if (!memcmp(ptr, close_tag, (size_t)close_tag_len)) {
|
||||||
|
ptr += close_tag_len;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (*ptr == '\r') {
|
||||||
|
ptr++;
|
||||||
|
} else if (*ptr == '\n') {
|
||||||
|
ptr++;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
clean_base64[clean_base64_len++] = *ptr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare for Base64 decoding */
|
||||||
|
bio_mem = BIO_new_mem_buf(clean_base64, clean_base64_len);
|
||||||
|
bio_b64 = BIO_new(BIO_f_base64());
|
||||||
|
BIO_push(bio_b64, bio_mem);
|
||||||
|
BIO_set_flags(bio_b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
|
||||||
|
/* decode DER */
|
||||||
|
retval = d2i_PKCS7_bio(bio_b64, NULL);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
OPENSSL_free(base64_data);
|
||||||
|
OPENSSL_free(clean_base64);
|
||||||
|
BIO_free_all(bio_b64);
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Extract existing signature in DER format.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_extract_to_nest(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
return script_pkcs7_extract(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove existing signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_remove_pkcs7(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
/* squash the unused parameter warning */
|
||||||
|
(void)hash;
|
||||||
|
if (!script_check_file(ctx)) {
|
||||||
|
return 1; /* FAILED, no signature */
|
||||||
|
}
|
||||||
|
if (!script_write_bio(outdata, ctx->options->indata, ctx->script_ctx->sigpos)) {
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
return 0; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Initialize outdata file and calculate a hash (message digest) of data.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_process_data(FILE_FORMAT_CTX *ctx, BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
if (ctx->script_ctx->sigpos > 0) {
|
||||||
|
/* Strip current signature */
|
||||||
|
ctx->script_ctx->fileend = ctx->script_ctx->sigpos;
|
||||||
|
}
|
||||||
|
if (!script_write_bio(outdata, ctx->options->indata, ctx->script_ctx->fileend))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
if (!script_digest_convert(hash, ctx, ctx->script_ctx->fileend))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a new PKCS#7 signature.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [returns] pointer to PKCS#7 structure
|
||||||
|
*/
|
||||||
|
static PKCS7 *script_pkcs7_signature_new(FILE_FORMAT_CTX *ctx, BIO *hash)
|
||||||
|
{
|
||||||
|
ASN1_OCTET_STRING *content;
|
||||||
|
PKCS7 *p7 = pkcs7_create(ctx);
|
||||||
|
|
||||||
|
if (!p7) {
|
||||||
|
fprintf(stderr, "Creating a new signature failed\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!add_indirect_data_object(p7)) {
|
||||||
|
fprintf(stderr, "Adding SPC_INDIRECT_DATA_OBJID failed\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
content = spc_indirect_data_content_get(hash, ctx);
|
||||||
|
if (!content) {
|
||||||
|
fprintf(stderr, "Failed to get spcIndirectDataContent\n");
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
if (!sign_spc_indirect_data_content(p7, content)) {
|
||||||
|
fprintf(stderr, "Failed to set signed content\n");
|
||||||
|
PKCS7_free(p7);
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
ASN1_OCTET_STRING_free(content);
|
||||||
|
return p7;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Append signature to the outfile.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [in] p7: PKCS#7 signature
|
||||||
|
* [returns] 1 on error or 0 on success
|
||||||
|
*/
|
||||||
|
static int script_append_pkcs7(FILE_FORMAT_CTX *ctx, BIO *outdata, PKCS7 *p7)
|
||||||
|
{
|
||||||
|
BIO *bio, *b64;
|
||||||
|
BUF_MEM *buffer;
|
||||||
|
size_t i;
|
||||||
|
static const char crlf[] = {0x0d, 0x0a};
|
||||||
|
int ret = 1;
|
||||||
|
|
||||||
|
/* convert to BASE64 */
|
||||||
|
b64 = BIO_new(BIO_f_base64()); /* BIO for base64 encoding */
|
||||||
|
if (!b64)
|
||||||
|
return 1; /* FAILED */
|
||||||
|
BIO_set_flags(b64, BIO_FLAGS_BASE64_NO_NL);
|
||||||
|
bio = BIO_new(BIO_s_mem()); /* BIO to hold the base64 data */
|
||||||
|
if (!bio) {
|
||||||
|
BIO_free(b64);
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
bio = BIO_push(b64, bio); /* chain base64 BIO onto memory BIO */
|
||||||
|
if (!i2d_PKCS7_bio(bio, p7)) {
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return 1; /* FAILED */
|
||||||
|
}
|
||||||
|
(void)BIO_flush(bio);
|
||||||
|
BIO_get_mem_ptr(bio, &buffer);
|
||||||
|
(void)BIO_set_close(bio, BIO_NOCLOSE);
|
||||||
|
|
||||||
|
/* split to individual lines and write to outdata */
|
||||||
|
if (!write_commented(ctx, outdata,
|
||||||
|
ctx->script_ctx->comment_text->header,
|
||||||
|
strlen(ctx->script_ctx->comment_text->header)))
|
||||||
|
goto cleanup;
|
||||||
|
for (i = 0; i < buffer->length; i += 64) {
|
||||||
|
if (!write_commented(ctx, outdata, buffer->data + i,
|
||||||
|
buffer->length - i < 64 ? buffer->length - i : 64)) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!write_commented(ctx, outdata,
|
||||||
|
ctx->script_ctx->comment_text->footer,
|
||||||
|
strlen(ctx->script_ctx->comment_text->footer)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* signtool expects CRLF terminator at the end of the text file */
|
||||||
|
if (!write_in_encoding(ctx, outdata, crlf, sizeof crlf))
|
||||||
|
goto cleanup;
|
||||||
|
ret = 0; /* OK */
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
BUF_MEM_free(buffer);
|
||||||
|
BIO_free_all(bio);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free up an entire outdata BIO chain.
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void script_bio_free(BIO *hash, BIO *outdata)
|
||||||
|
{
|
||||||
|
BIO_free_all(hash);
|
||||||
|
BIO_free_all(outdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Deallocate a FILE_FORMAT_CTX structure and script format specific structures.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [out] hash: message digest BIO
|
||||||
|
* [out] outdata: outdata file BIO
|
||||||
|
* [returns] none
|
||||||
|
*/
|
||||||
|
static void script_ctx_cleanup(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
unmap_file(ctx->options->indata, ctx->script_ctx->fileend);
|
||||||
|
OPENSSL_free(ctx->script_ctx);
|
||||||
|
OPENSSL_free(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int script_is_detaching_supported(void)
|
||||||
|
{
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Script helper functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
static SCRIPT_CTX *script_ctx_get(char *indata, uint32_t filesize, const SCRIPT_COMMENT *comment, int utf)
|
||||||
|
{
|
||||||
|
SCRIPT_CTX *script_ctx;
|
||||||
|
|
||||||
|
const char *input_pos, *signature_pos, *ptr;
|
||||||
|
uint32_t line[LINE_MAX_LEN], commented_header[40], cr, lf;
|
||||||
|
size_t sig_pos = 0, line_pos = 0, commented_header_len = 0;
|
||||||
|
size_t commented_header_size = sizeof commented_header / sizeof(uint32_t);
|
||||||
|
|
||||||
|
utf8DecodeRune("\r", 1, &cr);
|
||||||
|
utf8DecodeRune("\n", 1, &lf);
|
||||||
|
|
||||||
|
/* compute runes for the commented signature header */
|
||||||
|
for (ptr = comment->open;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
for (ptr = comment->header;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
for (ptr = comment->close;
|
||||||
|
*ptr && commented_header_len < commented_header_size;
|
||||||
|
commented_header_len++)
|
||||||
|
ptr = utf8DecodeRune(ptr, 1, commented_header + commented_header_len);
|
||||||
|
|
||||||
|
/* find the signature header */
|
||||||
|
for (signature_pos = input_pos = indata; input_pos < indata + filesize; ) {
|
||||||
|
const char *input_prev = input_pos;
|
||||||
|
|
||||||
|
input_pos = utf == 8 ?
|
||||||
|
utf8DecodeRune(input_pos,
|
||||||
|
(size_t)(indata + filesize - input_pos),
|
||||||
|
line + line_pos) :
|
||||||
|
(const char *)utf16DecodeRune((const void *)input_pos,
|
||||||
|
(size_t)(indata + filesize - input_pos)/2,
|
||||||
|
line + line_pos);
|
||||||
|
|
||||||
|
if (!memcmp(line + line_pos, &lf, sizeof lf)) {
|
||||||
|
if (line_pos >= commented_header_len &&
|
||||||
|
!memcmp(line, commented_header, commented_header_len * sizeof(uint32_t))) {
|
||||||
|
sig_pos = (size_t)(signature_pos - indata);
|
||||||
|
if (!memcmp(line + line_pos - 1, &cr, sizeof cr))
|
||||||
|
sig_pos -= (size_t)utf / 8;
|
||||||
|
break; /* SUCCEEDED */
|
||||||
|
}
|
||||||
|
line_pos = 0;
|
||||||
|
signature_pos = input_prev; /* previous line */
|
||||||
|
} else if (line_pos < LINE_MAX_LEN - 1) {
|
||||||
|
line_pos++; /* we can ignore lines longer than our buffer */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Signature position: %zu\n", sig_pos);
|
||||||
|
|
||||||
|
script_ctx = OPENSSL_malloc(sizeof(SCRIPT_CTX));
|
||||||
|
script_ctx->comment_text = comment;
|
||||||
|
script_ctx->utf = utf;
|
||||||
|
script_ctx->fileend = filesize;
|
||||||
|
script_ctx->sigpos = (uint32_t)sig_pos;
|
||||||
|
return script_ctx; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* write a commented line to the bio:
|
||||||
|
* - prepend with CRLF ("\r\n")
|
||||||
|
* - add opening/closing comment tags
|
||||||
|
* - adjust encoding if needed
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int write_commented(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *data, size_t length)
|
||||||
|
{
|
||||||
|
const char *open_tag = ctx->script_ctx->comment_text->open;
|
||||||
|
const char *close_tag = ctx->script_ctx->comment_text->close;
|
||||||
|
size_t open_tag_len = strlen(open_tag);
|
||||||
|
size_t close_tag_len = strlen(close_tag);
|
||||||
|
char *line;
|
||||||
|
|
||||||
|
/* the buffer needs to be long enough for:
|
||||||
|
* - CRLF ("\r\n")
|
||||||
|
* - opening tag
|
||||||
|
* - up to 64 bytes of data
|
||||||
|
* - closing tag
|
||||||
|
* - trailing NUL ("\0") */
|
||||||
|
line = OPENSSL_malloc(2 + open_tag_len + length + close_tag_len + 1);
|
||||||
|
if (!line)
|
||||||
|
return 0; /* memory allocation failed */
|
||||||
|
strcpy(line, "\r\n");
|
||||||
|
strcat(line, open_tag);
|
||||||
|
memcpy(line + 2 + open_tag_len, data, length);
|
||||||
|
line[2 + open_tag_len + length] = '\0';
|
||||||
|
strcat(line, close_tag);
|
||||||
|
|
||||||
|
/* adjust encoding */
|
||||||
|
if (!write_in_encoding(ctx, outdata, line, strlen(line))) {
|
||||||
|
OPENSSL_free(line);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(line);
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* adjust encoding if needed
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int write_in_encoding(FILE_FORMAT_CTX *ctx, BIO *outdata, const char *line, size_t length)
|
||||||
|
{
|
||||||
|
size_t written;
|
||||||
|
if (ctx->script_ctx->utf == 8) {
|
||||||
|
if (!BIO_write_ex(outdata, line, length, &written)
|
||||||
|
|| written != length) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
uint16_t *utf16_data = NULL;
|
||||||
|
size_t utf16_len = utf8_to_utf16(line, length, &utf16_data);
|
||||||
|
|
||||||
|
if (!BIO_write_ex(outdata, utf16_data, utf16_len, &written)
|
||||||
|
|| written != utf16_len) {
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert len bytes of UTF-8 to UTF-16
|
||||||
|
* return the number of output bytes
|
||||||
|
*/
|
||||||
|
static size_t utf8_to_utf16(const char *data, size_t len, uint16_t **out_utf16)
|
||||||
|
{
|
||||||
|
size_t utf16_len = utf8UTF16Count(data, len);
|
||||||
|
*out_utf16 = OPENSSL_malloc(utf16_len * sizeof(uint16_t));
|
||||||
|
if (!*out_utf16)
|
||||||
|
return 0; /* memory allocation failed */
|
||||||
|
|
||||||
|
const char *s = data;
|
||||||
|
uint16_t *d = *out_utf16;
|
||||||
|
uint32_t rune;
|
||||||
|
size_t remaining_len = len;
|
||||||
|
|
||||||
|
while (remaining_len > 0) {
|
||||||
|
s = utf8DecodeRune(s, remaining_len, &rune);
|
||||||
|
if (!s || s < data)
|
||||||
|
break; /* invalid UTF-8 sequence */
|
||||||
|
size_t consumed = (size_t)(s - data);
|
||||||
|
|
||||||
|
remaining_len -= consumed;
|
||||||
|
data = s;
|
||||||
|
d += utf16EncodeRune(rune, d);
|
||||||
|
}
|
||||||
|
return (size_t)(2 * (d - *out_utf16));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert len bytes of UTF-16 to UTF-8
|
||||||
|
* return the number of output bytes
|
||||||
|
*/
|
||||||
|
static size_t utf16_to_utf8(const uint16_t *data, size_t len, char **out_utf8)
|
||||||
|
{
|
||||||
|
size_t utf8_len = utf16UTF8Count(data, len/2);
|
||||||
|
*out_utf8 = OPENSSL_malloc(utf8_len);
|
||||||
|
if (!*out_utf8)
|
||||||
|
return 0; /* memory allocation failed */
|
||||||
|
|
||||||
|
const uint16_t *s = data;
|
||||||
|
char *d = *out_utf8;
|
||||||
|
uint32_t rune;
|
||||||
|
size_t remaining_len = len/2;
|
||||||
|
|
||||||
|
while (remaining_len > 0) {
|
||||||
|
s = utf16DecodeRune(s, remaining_len, &rune);
|
||||||
|
if (!s || s < data)
|
||||||
|
break; /* invalid UTF-16 sequence */
|
||||||
|
size_t consumed = (size_t)(s - data);
|
||||||
|
|
||||||
|
remaining_len -= consumed;
|
||||||
|
data = s;
|
||||||
|
d += utf8EncodeRune(rune, d);
|
||||||
|
}
|
||||||
|
return (size_t)(d - *out_utf8);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value of a signed or unsigned script file.
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] md: message digest algorithm
|
||||||
|
* [returns] calculated message digest BIO
|
||||||
|
*/
|
||||||
|
static BIO *script_digest_calc_bio(FILE_FORMAT_CTX *ctx, const EVP_MD *md)
|
||||||
|
{
|
||||||
|
size_t fileend;
|
||||||
|
BIO *hash = BIO_new(BIO_f_md());
|
||||||
|
|
||||||
|
if (ctx->script_ctx->sigpos)
|
||||||
|
fileend = ctx->script_ctx->sigpos;
|
||||||
|
else
|
||||||
|
fileend = ctx->script_ctx->fileend;
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#pragma GCC diagnostic ignored "-Wcast-qual"
|
||||||
|
#endif
|
||||||
|
if (!BIO_set_md(hash, md)) {
|
||||||
|
fprintf(stderr, "Unable to set the message digest of BIO\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
#if defined(__GNUC__)
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
BIO_push(hash, BIO_new(BIO_s_null()));
|
||||||
|
if (!script_digest_convert(hash, ctx, fileend)) {
|
||||||
|
fprintf(stderr, "Unable calc a message digest value\n");
|
||||||
|
BIO_free_all(hash);
|
||||||
|
return NULL; /* FAILED */
|
||||||
|
}
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute a message digest value
|
||||||
|
* [in, out] hash: message digest BIO
|
||||||
|
* [in] ctx: structure holds input and output data
|
||||||
|
* [in] len: mapped file length
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_digest_convert(BIO *hash, FILE_FORMAT_CTX *ctx, size_t len)
|
||||||
|
{
|
||||||
|
if (ctx->script_ctx->utf == 8) { /* need to convert to UTF-16 */
|
||||||
|
uint16_t *utf16_data = NULL;
|
||||||
|
size_t utf16_len = utf8_to_utf16(ctx->options->indata,
|
||||||
|
len, &utf16_data);
|
||||||
|
|
||||||
|
if (!script_write_bio(hash, (char *)utf16_data, utf16_len)) {
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
OPENSSL_free(utf16_data);
|
||||||
|
} else { /* already UTF-16 -> no need to convert */
|
||||||
|
if (!script_write_bio(hash, ctx->options->indata, len)) {
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Write len bytes from data to BIO
|
||||||
|
* [in, out] bio: message digest or outdata BIO
|
||||||
|
* [in] indata: mapped file
|
||||||
|
* [in] len: indata length
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_write_bio(BIO *bio, char *indata, size_t len)
|
||||||
|
{
|
||||||
|
size_t i = 0, written;
|
||||||
|
|
||||||
|
while (len > 0) {
|
||||||
|
if (!BIO_write_ex(bio, indata + i, len, &written))
|
||||||
|
return 0; /* FAILED */
|
||||||
|
len -= written;
|
||||||
|
i += written;
|
||||||
|
}
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if the signature exists.
|
||||||
|
* [in, out] ctx: structure holds input and output data
|
||||||
|
* [returns] 0 on error or 1 on success
|
||||||
|
*/
|
||||||
|
static int script_check_file(FILE_FORMAT_CTX *ctx)
|
||||||
|
{
|
||||||
|
if (!ctx) {
|
||||||
|
fprintf(stderr, "Init error\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
if (ctx->script_ctx->sigpos == 0
|
||||||
|
|| ctx->script_ctx->sigpos > ctx->script_ctx->fileend) {
|
||||||
|
fprintf(stderr, "No signature found\n");
|
||||||
|
return 0; /* FAILED */
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1; /* OK */
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
*/
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
__pycache__
|
||||||
|
.pylintrc
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDoTCCAomgAwIBAgIUOK8lwJ8A1Oqw8jDAb3TF06ve+PcwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTcwMTAxMDAwMDAwWhcNMjYxMTEwMDAwMDAwWjBYMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEQMA4GA1UEAwwHUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
|
|
||||||
AQoCggEBAKzObJwYq4t9Y/OOQLqUNLU8RDXq284L8zQgRLkvApF87FNN7kozIgC9
|
|
||||||
/HAgJSho/Lup5lzkCWa3fjkYm1EBrL+JihesSaCxxe7LOg6tRaY+WxikwMUnlkNE
|
|
||||||
s3R+DogeGVsla4q0FEcICiz3FHTfSAUVmrN3Nj1ll7npJXrqmXxfCuO3slgjUkHq
|
|
||||||
tdZ5t1rSWwbiUhGIQKLzo3/uw2XoOI28qpoOw+0/y8AyjWs8My3u8GrYFr+qh5fx
|
|
||||||
Y0Zp0EhhAJo23Xd43XmeVKjuKIOaHu3JiM8sp9K1WFsTvFNAO27TBRn/X0mJCeDX
|
|
||||||
T117dQxhWOCcQ/uRGuXICT4ign8MLtUCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB
|
|
||||||
/zAdBgNVHQ4EFgQU6ewx3DIpbR8OptEmDFlYNELRqP4wHwYDVR0jBBgwFoAU6ewx
|
|
||||||
3DIpbR8OptEmDFlYNELRqP4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUA
|
|
||||||
A4IBAQAhRMun0IzPmHVFM+SOfSCPVAgogWpqR5XlBAFlS+Aen6v3ukQAQjEhfBbE
|
|
||||||
dZG6ye9i0ebf9qXYTvSq5wfaqP7FGb2/Z96uPXNMXPi796KjLW2CG578DitORPb7
|
|
||||||
x1eV3UGrQX2bMQ0JbGkBU+DIdIRBqDfad/kjLtm5eHyCbaodSWdaZO4LSUIy3MBx
|
|
||||||
2UeBj2qD4RTA0Dt7hG7RA5QdTxHlZyLIk8HX3krZ+il5RmSbOnQs/XqK5DJp4J5p
|
|
||||||
122sIO4Y9ki+Wewzx8f3/7mcVbcMo67GwRHo8bk3GjWE74pczyrzfP68vDQ4tn85
|
|
||||||
NcLPeLClfSziJD09z+Iyp94EQeKX
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
-----BEGIN X509 CRL-----
|
|
||||||
MIIB9zCB4AIBATANBgkqhkiG9w0BAQsFADBgMQswCQYDVQQGEwJQTDEVMBMGA1UE
|
|
||||||
CgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
|
|
||||||
eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBFw0xOTAxMDEwMDAwMDBaFw00MzAx
|
|
||||||
MDEwMDAwMDBaMCcwJQIUOpY5wp7DtqsdxII7sxculedk0PYXDTIyMDcyNjEzMDk1
|
|
||||||
NlqgIzAhMB8GA1UdIwQYMBaAFJ4FrAtb4UB/ag702URPiid97ziLMA0GCSqGSIb3
|
|
||||||
DQEBCwUAA4IBAQA4Kw0vEJrtjjMam16iN/stOMxJDgkp1IQzA3narxr9fEjX5Ynk
|
|
||||||
JztuEExtowPIDOLGWCySXNEMmxCzXNAMvlUq+UQvnWrwgHQ9R7TBYIcAY+VRmzKz
|
|
||||||
T4PXvDSL2WMuJ1dLWoIcL2D0wEdti7YMvAnCrOC8HAPGgke5QcOgSfMSAYSAtpiw
|
|
||||||
PZAFgcuo53AodlCw9J+CPcHPYw+C2QExOy8s8q6d8Xgjg+Ge7v3RxLWy74sNPl0u
|
|
||||||
uZ79vcLNEeqEXxKaw5abqDqIDcUKIT3b62KsSxkak9IGNMLcTASw1V+YaKVLSYNW
|
|
||||||
NTuc5WJblfZi/q7WUMKkmRERzvdg2rf0CSH1
|
|
||||||
-----END X509 CRL-----
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN PRIVATE KEY-----
|
|
||||||
MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCivbbTCnbOqPoV
|
|
||||||
7VVP/KJzgslx8yfX9laGwTsvzqStQtG8j40ljR85WD/bgy3I5duebudg7JhOVH2f
|
|
||||||
aSqbh8SCzP4YNDFcseDIuHdoXi54POgW3S/wbe8l8P7g3btcBgnlXh/izhUlEMib
|
|
||||||
Q/8G8UZj0n/MgKMLzcXc4t2eQ4Pzw7xAPqoXBZ20Fg2rFBfUsDDLc5F7lpO5t1WQ
|
|
||||||
dXTYmF0oAL/HLmd+HKe5Xgp9jJ6XacesjWLnhRdZ06uUP9cgo+Jem4QZxeFhOtMe
|
|
||||||
KAf7JH3Juz2Gi0a+4dMSNzES4m8RAlf6pXh4kAh7EhMNb/Ir6ZpY8uKM7dtn38mh
|
|
||||||
1f59EKc9AgMBAAECggEAK5zB0P695hYcpyGqOjxO4LvM9m+eXt7SQ1ynWuF6+j+s
|
|
||||||
62ZhAg42rux6eH5IF82ZtHSuJyhgjKVR4RWS6IlS3WbINX5PODMnNUNSJLMQqwJP
|
|
||||||
hEkUXs9nRni2JVbmrfukTUaTLvnhasR7rjhjsN2Z6ohv3UMf7rrfapmVoKMhSoLd
|
|
||||||
jqvZ2ZoaT5mfTiK/5PDyWqrt/vmvE4VlipAsvudwozG5vQDEsCNDNUTg5OTGnPUU
|
|
||||||
i0xeQTioqzCcweIlEaWhj/eMHx/eAeZ6V0Evid/YwTDlbTqVDWZGLJ/phOnKJs3V
|
|
||||||
j+eOv7E2d1ga7149SPDIv5Y0YZ91v3M06ICk5o66gQKBgQDSM+YyR5YOJTSAuAcI
|
|
||||||
uKTc33wwCbPiJF/F1zLJDdPp2IamZQbuNIX/8fOG3Gho+OnfNAykMcr3rFrug2vi
|
|
||||||
9GhWDQqguYGh16xos+2zNan6P/s0/rQ4OfPIsTEGC8X3fJeMzZUNMvnyN/FXzzus
|
|
||||||
020o29gu59esEfGHEsvAupC3IQKBgQDGMqGLgrU4oW/5mmm4BZlwwkZJNMmFH49u
|
|
||||||
Qe4Ylj87SQduExJMmTfrmANqQXu7RXG0IxLcvhwMLVCCYAkvuBv1awsbg2yfP1Pn
|
|
||||||
Wb/K+5CaHaxnpwSpRiGaN6fnAPDl8PnALMVXtQGru2MMcISxOIFQ9slHth0lmaMo
|
|
||||||
odIPIL1YnQKBgAOSskUEhn5zD3NorWXujY7blabTY2VirOYWBFz6iTGeZpuJeBaw
|
|
||||||
ed6h5DvUn0m5gXAz2EsqNYMEQP9w6HKRKPzdd+LHhHaVze5xsIatUNhaIhECi1mx
|
|
||||||
Un2E1Yp+xLyyN3lDPVdeGHWPkeCmOyNy7JYXNpOFiVr5axuarC/4e+FBAoGAeuRR
|
|
||||||
/mshaufOwnnYK15tcdlEM4gjnAOhr7/5ng0rT9tMXBg/NHeckNxE4dGQouHASu2k
|
|
||||||
eHL4eSRv0ycxCwGhdF7XGEw5QdTGdaDUp0ussaLMj8ijv0HY/AKefUG8HRd6BIq+
|
|
||||||
Ik/9pTofhEsQO8LJjCY5T9m/4NyOqlcMJI0sWpECgYBvPLnutbBXYONVAE3jL05K
|
|
||||||
hWwenKpv5Aaa11ahqzhil2Tj+VOMtmvhsSc5loSG83qp5LtN4LxyR0Vn9AGN7Z+d
|
|
||||||
Ut6LHeZ/DMW3/RPT+1MIKm6WLNxgk5YvuCxprdpfE5tTmV9/t+t3Uao7TRsLPl2o
|
|
||||||
qAKz8Fvq0el5RW3EtAgd4A==
|
|
||||||
-----END PRIVATE KEY-----
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEzTCCA7WgAwIBAgIUfRjXKciCGA4XbhbhxbAwfpcLGmowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xODAxMDEwMDAwMDBaFw0yODAxMDEwMDAwMDBaMFUxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxHDAaBgNVBAsME1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkxETAPBgNVBAMMCFRlc3QgVFNBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
|
||||||
AQ8AMIIBCgKCAQEAor220wp2zqj6Fe1VT/yic4LJcfMn1/ZWhsE7L86krULRvI+N
|
|
||||||
JY0fOVg/24MtyOXbnm7nYOyYTlR9n2kqm4fEgsz+GDQxXLHgyLh3aF4ueDzoFt0v
|
|
||||||
8G3vJfD+4N27XAYJ5V4f4s4VJRDIm0P/BvFGY9J/zICjC83F3OLdnkOD88O8QD6q
|
|
||||||
FwWdtBYNqxQX1LAwy3ORe5aTubdVkHV02JhdKAC/xy5nfhynuV4KfYyel2nHrI1i
|
|
||||||
54UXWdOrlD/XIKPiXpuEGcXhYTrTHigH+yR9ybs9hotGvuHTEjcxEuJvEQJX+qV4
|
|
||||||
eJAIexITDW/yK+maWPLijO3bZ9/JodX+fRCnPQIDAQABo4IBiDCCAYQwDAYDVR0T
|
|
||||||
AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAdBgNVHQ4EFgQUKWCqogni
|
|
||||||
6SseJ/P6LXo0M2cK++QwHwYDVR0jBBgwFoAU/5nNuG4Tm4v2y9uKf428/4fVQesw
|
|
||||||
gYQGCCsGAQUFBwEBBHgwdjA5BggrBgEFBQcwAoYtaHR0cDovL1RTQUNBLnRpbWVz
|
|
||||||
dGFtcGF1dGhvcml0eS5jb20vVFNBQ0EuY3J0MDkGCCsGAQUFBzABhi1odHRwOi8v
|
|
||||||
b2NzcC5UU0FDQS50aW1lc3RhbXBhdXRob3JpdHkuY29tOjkwODAwPgYDVR0fBDcw
|
|
||||||
NTAzoDGgL4YtaHR0cDovL1RTQUNBLnRpbWVzdGFtcGF1dGhvcml0eS5jb20vVFNB
|
|
||||||
Q0EuY3JsMFUGA1UdHgROMEygGDAKggh0ZXN0LmNvbTAKggh0ZXN0Lm9yZ6EwMAqH
|
|
||||||
CAAAAAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0G
|
|
||||||
CSqGSIb3DQEBCwUAA4IBAQB4YXa5nVWUzWSsUDMfYFTEETOe8boUErwfrDNBuj6z
|
|
||||||
B5en20FhI49i6PCYEfNq3vrAtPOEFJj+KPomN3C46VLxbUEvqWLdq6EyzWvVVmXK
|
|
||||||
VLeC0qV0m6CFM8GplaWzZdfFTQaaLUhgY08ZU2gp4QsoS2YjAosxlZrNSm6pBbv3
|
|
||||||
q+Og1KeSK8gKS0V89k+6e3LOEF6KaNWKSkoz5xDniQY//mTjiDcNmYUh0KhHfhdU
|
|
||||||
eO92M82uJSaDqnRs5HsWPs6z6qdfpuvj++OtQ1VCM2p5SEH2sEomdeN3YYChuG4h
|
|
||||||
yzn0mYAdbTyGJHlFm17AH+SQRbVqCKYdHDaqsMb+fWzi
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDkDCCAnigAwIBAgIUJ0nfE+EVsIThltlY2LHVWMJVIq4wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xNzAxMDEwMDAwMDBaFw0yNjExMTAwMDAwMDBaMGAxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxJDAiBgNVBAsMG1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkgUm9vdCBDQTEUMBIGA1UEAwwLVFNBIFJvb3QgQ0EwggEiMA0GCSqG
|
|
||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGOTX1f9dmtUiyzlsUInRIGfRMya338SVx
|
|
||||||
vYGeOwdpTSSGlYUVwR9AuFewQF5+klelstCJe+SoUG0AdzS30mRWlQrhip4UdvdW
|
|
||||||
T2gkNKbSn6DQzlWoQej9izqRLxAsbuszgkvnLOBEmPaLimDsCgu0bAN95Hp0Hls9
|
|
||||||
O/fVmzh8VuV4iscxc7q13ZB7CylWgwd55CFEGd/jpJ6kMwSHbOLoBWp4GQ3KxR+c
|
|
||||||
ASAo0FapU2WSZB2EYWszRiyq91X+AvIYN4ypTv7RccgfUvnZ2qFykJAkf/wgkynu
|
|
||||||
Qg7rCUNfUEpDc7jlqtDWR7iLrtHBkA17C3IU8ymmKQYWfw3ZyBwvAgMBAAGjQjBA
|
|
||||||
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP+ZzbhuE5uL9svbin+NvP+H1UHr
|
|
||||||
MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAbj3aFwIUxvzwgywO
|
|
||||||
gj01JM8GNbw1E4MGdkaNI8rgeY8ay15ZXhR9NpRWWb6Y7IXPq5XhuEktVte5Z4Kf
|
|
||||||
XLBrr7Xe9VVqJL9zd1tMzOEM/zG77rZf/iXBTZLkCtQc/GOEY4TTWKNEl5hiWVE0
|
|
||||||
po97GX5XHoeyHlWQ75sd9z6MxFxmvdp9/uyYD700e9sd5gcD8LGvHw2DNy8vntYV
|
|
||||||
ia9h95N9i1umffxU460o8W5GoIcsD13B3YftvnWhGSXqovBRFgcPAQZ4eW9Qh/zA
|
|
||||||
4zQBQrRvmREPihXVdgtWVpbRchP99oSZBrYr7Hh/P69rycklquqxJl1ol1wbT6dK
|
|
||||||
S5Gmng==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
Binary file not shown.
Binary file not shown.
@@ -1,46 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIID7jCCAtagAwIBAgIUdLInHjkevRVCr7I78r5++6eSrZ0wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMIGdMQswCQYDVQQG
|
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEUMBIGA1UEAwwL
|
|
||||||
Q2VydGlmaWNhdGUxJzAlBgkqhkiG9w0BCQEWGG9zc2xzaWduY29kZUBleGFtcGxl
|
|
||||||
LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJLJ3Vty2lgJw+5
|
|
||||||
ouAV4ZqkIwvfWPcE7zD1CfQIL2802jVuCSTkN9cfFVYMKFEPJxQWJAKoCzr/Ux8z
|
|
||||||
Yt9BXO5o39+z7umLKmc6pfrZJ6kG4msrMjZv36LsCQyfjUc1O9H1aiOQEvRQY2pF
|
|
||||||
2v5dfqRMrAqH1ESQHCggUBjElWj9oMFax8jyO7JxTzuttOb6mhDmqz4q2u4LwZGH
|
|
||||||
lBofgOAB54Mlv41x7dDh85i/jayXuYYmsjRwCuBAn14+D2zImyPDx5UaUJJMzujo
|
|
||||||
QriOZ4KU2dHRgy0+vd7ZbrL1kRY1axyNQ+jBk7UHnlZZ2CCkhBoZIM6ez3ljPwgr
|
|
||||||
cpg0RtcCAwEAAaNiMGAwCQYDVR0TBAIwADAdBgNVHQ4EFgQUBxPEs09WXDxGqb+D
|
|
||||||
WTFgcUQd0AEwHwYDVR0jBBgwFoAUngWsC1vhQH9qDvTZRE+KJ33vOIswEwYDVR0l
|
|
||||||
BAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQELBQADggEBAKK2e1s1puUFbNjglopi
|
|
||||||
mKZ4Pks2zb6LVUGG6Q4XQ1dWe25ovt68jWv56HFyCMI1N+L8q0+Ku2eOfLObS7Ej
|
|
||||||
FFRUWEIXDgipryDTGzoWRM380fuYpL/j7Rt1/xmIHWTFibf/6gK/naRXsFH3dEbb
|
|
||||||
7DDWQ5pAd2d60dB+ThUEIZQTQd/926Kuk5oESvP08fXMYTuiYARypG1gmiuvxQ9N
|
|
||||||
mDJP6CHxyJR/LB4tb0RAqnLkVsXVBDnRYWdEvkuhoqTtbhVzVbL3mPeEmVYypxxd
|
|
||||||
NdrHpU5zmxFSin2T3F0TneNcT+MDV+dQcWyTGNYs/fnmo85LsiakJixGv1qx8PTs
|
|
||||||
8iE=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
Binary file not shown.
@@ -1,23 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDzjCCAragAwIBAgIUGjZdQYlcAtlqZOsQ7eWRimQ9PIcwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwbzELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEMMAoGA1UE
|
|
||||||
CwwDQ1NQMRIwEAYDVQQDDAljcm9zc2NlcnQxJzAlBgkqhkiG9w0BCQEWGG9zc2xz
|
|
||||||
aWduY29kZUBleGFtcGxlLmNvbTAeFw0xODAxMDEwMDAwMDBaFw0yMDA2MTkwMDAw
|
|
||||||
MDBaMG8xCzAJBgNVBAYTAlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNV
|
|
||||||
BAsMA0NTUDESMBAGA1UEAwwJY3Jvc3NjZXJ0MScwJQYJKoZIhvcNAQkBFhhvc3Ns
|
|
||||||
c2lnbmNvZGVAZXhhbXBsZS5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
|
|
||||||
AoIBAQDJU6WNMOEoErLYb5Qc7jsvVgruPM7DJTZ4vUpJNYAyprSDHciaKSa4SiYS
|
|
||||||
84Mxc6tzBoJvKOAwpxzzONOqPVWUd5J244urgvfHgSGWsbA8bakiIYlETopnecFk
|
|
||||||
B3ZELR33CPqIbpYYMYujhPGFa1xxZxFykJ1iBhZ8Gh3W4wHi/2kW6hTQkihMtUPP
|
|
||||||
Xxc2XWACj/tz22OSdgNZcIfhXiy2HOuPch+0UlDR4UmlJIR5aet1y832hHoeeevo
|
|
||||||
qfhfGOm9rRf9nyxKDwTyaN7JVOb7A1k6KJEJoe1zfIwT56mgoA433iUWFMLB6hKU
|
|
||||||
be3zV1vGjk77Kk7atcvEMTRq+rwHAgMBAAGjYjBgMAkGA1UdEwQCMAAwHQYDVR0O
|
|
||||||
BBYEFEXgglEcDh+8oCCvjlxrN/Y7C4YwMB8GA1UdIwQYMBaAFEXgglEcDh+8oCCv
|
|
||||||
jlxrN/Y7C4YwMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBCwUAA4IB
|
|
||||||
AQBo8UqUEjxGQCVU/IgphwKA8Rb/uAyBYm+AjqFDs82lA6ze0n08Bj+eciVkxscA
|
|
||||||
0deivOC1sDD88QkLzSQ9CPk4e7+m7nx5SFUnUWY+o3ln+cTbGSM0jW9hme0LtHXX
|
|
||||||
QxDSKDBhQonRQk7lQ+TwFR7ol+y5SdZy7YQ+v/25qO6MMQgSPykJIa4vF7lwrYhu
|
|
||||||
qL+1MJx/ryTbCUExcKNNkWHZJRc9ZvtdWEHYpBSZl5xmJdKMLnHAu5uv8N2pezzp
|
|
||||||
PfujldZky7bnERaTM+bf/LvKXS8RfQGrCLu9QjgPVa6ysZV6gXTsEtwYh64vucjS
|
|
||||||
s7IhdLxfiT0xYkK4JWrRLc38
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIID6jCCAtKgAwIBAgIUdtBZJAw8/6JVNMiQpN3PEROI8rowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0xOTAxMDEwMDAwMDBaMIGZMQswCQYDVQQG
|
|
||||||
EwJQTDEZMBcGA1UECAwQTWF6b3ZpYSBQcm92aW5jZTEPMA0GA1UEBwwGV2Fyc2F3
|
|
||||||
MRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UEAwwH
|
|
||||||
RXhwaXJlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUuY29t
|
|
||||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsksndW3LaWAnD7mi4BXh
|
|
||||||
mqQjC99Y9wTvMPUJ9AgvbzTaNW4JJOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi30Fc
|
|
||||||
7mjf37Pu6YsqZzql+tknqQbiaysyNm/fouwJDJ+NRzU70fVqI5AS9FBjakXa/l1+
|
|
||||||
pEysCofURJAcKCBQGMSVaP2gwVrHyPI7snFPO6205vqaEOarPira7gvBkYeUGh+A
|
|
||||||
4AHngyW/jXHt0OHzmL+NrJe5hiayNHAK4ECfXj4PbMibI8PHlRpQkkzO6OhCuI5n
|
|
||||||
gpTZ0dGDLT693tlusvWRFjVrHI1D6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCtymDRG
|
|
||||||
1wIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQHE8SzT1ZcPEapv4NZMWBx
|
|
||||||
RB3QATAfBgNVHSMEGDAWgBSeBawLW+FAf2oO9NlET4onfe84izATBgNVHSUEDDAK
|
|
||||||
BggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAX1Ar7jRAXdcA0Wu37yRi58QN
|
|
||||||
hpa1VLXadqfB+i5Y4e3DzqnMbpkLWsFzreC1AG0RjLe52s4PRUE6boGlpUeAyfFC
|
|
||||||
Qu2Gl/REVWwMCYV8bq3vQZkYQjklAXCQLWFk5TrzuDmBcV8+fY518nWw+xmcYwW5
|
|
||||||
5oehLsvB4nxoBzlHgcdDwS5b2dmpCKCbZFLU9aA9DjAVvY/9B8emyj7Sh2sEK0Yf
|
|
||||||
xwHlATTVq5O0/9tvVZQmYsbpS0iCRGBM+spTEhDT4WGsaRO6wP+Ucgp6Ym3ahMvz
|
|
||||||
tHME3uUanKWVoDb69sguGZ6KlnZZZdIX1AJ3dlTXCrzEO9xsoAzqzsxVJGrraQ==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
Binary file not shown.
@@ -1,27 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
MIIEogIBAAKCAQEAsksndW3LaWAnD7mi4BXhmqQjC99Y9wTvMPUJ9AgvbzTaNW4J
|
|
||||||
JOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi30Fc7mjf37Pu6YsqZzql+tknqQbiaysy
|
|
||||||
Nm/fouwJDJ+NRzU70fVqI5AS9FBjakXa/l1+pEysCofURJAcKCBQGMSVaP2gwVrH
|
|
||||||
yPI7snFPO6205vqaEOarPira7gvBkYeUGh+A4AHngyW/jXHt0OHzmL+NrJe5hiay
|
|
||||||
NHAK4ECfXj4PbMibI8PHlRpQkkzO6OhCuI5ngpTZ0dGDLT693tlusvWRFjVrHI1D
|
|
||||||
6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCtymDRG1wIDAQABAoIBACR/jgxT9ZgUvupR
|
|
||||||
Li6BTDXD9AiyKBwpPm3fO7JhGpTBVQorBGQw891t14hN5NLzLyTFg4mnrOTe770r
|
|
||||||
X8okL0n+3hWFWBsnCf8n2mKHob7QUfluVlEehcFsYE3dO6agFybb/mZZUAgDjNZs
|
|
||||||
hnAb45juuSlOtP10Is90DfGEDLH5IeY1xjzc7Qv/CFxCffIAC8QmQYUTihJ2m5aE
|
|
||||||
7Hvs79oEcSvbRJDYbykzrJ0eeIaEvfOxkWJnnJHrhiONzb8qgj3DLiZdX1qeo1Ao
|
|
||||||
ldNxEG9n3Axd6M0nhajz0qbDV11S8YiKfP10XRQh5xv7lZi7MjvrRxFTFYpSrXwi
|
|
||||||
YYyFNoECgYEA6YnIYg1nIe3qaI3Me1RQQTGRl8M/dQc2d98Pz5mez9vN3TIW6nEs
|
|
||||||
QYw/9OKG1ercbD+YnuaV+1izuAcA3mNlSDReTtzInAotJjTH1V3WYqvBTVUZSb6T
|
|
||||||
5qSBfRDC3AULFvHeX5c5wqgfB3U9KLDfVBfaHnMerg6dAGsYZPhPMrkCgYEAw3Eg
|
|
||||||
5BRTzbqG0WXF25rycTeHCcylMZRjI+TVcIa8AGqNSCK4HgAWp89XPIV3WceVqe2R
|
|
||||||
Lyn1jtA2MgGGcMBDFlOWF+h9j2/j27Z+pyIbBF9LAraJuBOG6dezd50y5Ur6HK/f
|
|
||||||
e5lnjvElIYdz+RX+rmw8NFcIUbSAfE7rGinDvg8CgYBDx86VzsgJC/FFySn4/X6R
|
|
||||||
fV6BSpTHVYGUhvQiz7ZNI8F7GoeWIaSznY4OeBSkT5cL/+U+8TPEkHkQx0+UPArw
|
|
||||||
Suq4PtImn7l85kK9hY+scacX18QQKDTq8wH2F4BGtVwDm81rtwt3mK3wzzEh9zvK
|
|
||||||
P2X6AnV8FReyQGMDIyJxWQKBgD6nu9WitqMTkzj6GY4nhGXLWV1I4ASe/5F4QPzM
|
|
||||||
FOVFQ3nGt6PWf2zYyay7VOHRXCeX451tJC3ejiFF3+WxnVBBB7Muc2JSiofbX4sR
|
|
||||||
Ifwq2I9MGaaLjArXfc9w8+oSOVCNCWZEbbCjmjW/iOxnorgkNsDIzf/zj+VKH5DJ
|
|
||||||
ptj9AoGAUpB6nPES3Nnj8DsbpHCnShYMl/rFxzxg2pJJosXzuS/ttuBT2DlT5eiY
|
|
||||||
aZcL1DGSp2CD4QXbVuDHPkQMPzVfZzKAuCZlotEMR9byK46aYIkQueym45e0PGZP
|
|
||||||
djKZm+cxF+W55jBkBBhV6wSOLNRWCUYiIIq3RmwWjkopNvSlwY4=
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
Binary file not shown.
@@ -1,30 +0,0 @@
|
|||||||
-----BEGIN RSA PRIVATE KEY-----
|
|
||||||
Proc-Type: 4,ENCRYPTED
|
|
||||||
DEK-Info: DES-EDE3-CBC,6DB255395263EDD5
|
|
||||||
|
|
||||||
A83CH4mv7u89RbT8Tpz4gxImKGBw69Zr3LstRXlliGYobby5YBx/YimkA9wFCZK/
|
|
||||||
B1eitWwy0F6axDZQYHKi+yvUJDPB9arXtClvYknMhwrHV1GHLSYeqb9oZJeqNyDZ
|
|
||||||
Qd3lxTbUtkMVJgJNrl2kOezm6/srnAw4uA7NyAvrs2vEzB48q4VlysrJq+f9mLXj
|
|
||||||
vCmrfUwY999lSifRmoxqeWlqNUQ2tgHHXYMNagpvxYXsfe1UvEH9aa6+UsO9S0py
|
|
||||||
7dyfSu95QpWyVNqkWi1VAtNbo2VpjJ6NJLAk+dy/rNqN3a4KnWeIzkYssWTsKB08
|
|
||||||
VyHrRLePPx5qdarsczZtf+M2PxhHHnl/09+Nrp5BUcMV31j3v3VSM0K+CHEucAk7
|
|
||||||
95rUtSUNywKUQeSgXrG1eLX7kXwRQ7PPCz3sPtvmJRIvQlGgLiTbKPsG52m3kAIw
|
|
||||||
zgXPcH2lYb3855occznl72jMUucxXq8gq0bC4xbEg/yJV8p1IuUEFhLGI9s9T4JV
|
|
||||||
cO9NKwmSjpHFo1ULhB7o6uMmV2rYDK+5GbQHxZgHj3ES+i53eFMWGubPEEOmqSh3
|
|
||||||
9K7gtW9y971tNfhp9ba8RnYXT6xW2nMTM4koO9b4ptdwRo5bMKFvWY8eecXfsDAG
|
|
||||||
OJ+aXkDr8jsn1Xauq1m4TM71wn2wUx95KaCpL55UNBEn7aH9qlNFfxdyzXMPYS36
|
|
||||||
zgWK44BV3PTSIGgW61NVwHwzi3bFfymortVxGpelzy2dggWVvI3uzKocLFQ8f4oe
|
|
||||||
Y0HWSmGVPF3uFHNCZtCB/Tpbz6YwP/YYStqAcryeS5Yo9Hdkh8pBVnYiKdTFEUW2
|
|
||||||
RbClgeB2MV+zttsqvmodfkviS4BjWgoIV5szxWOePnO8kQAHA/Ml3CyDPOX6rqI5
|
|
||||||
lDKiUojEMLgir/3YWWcmigEIgRsyF3CL1s+kTR3S8e9QRe8RiliRUKW5gXrLEa6j
|
|
||||||
eUjs4kgCrvmQvwyZYJjWl+r7ycmk+yB/EZs8P39KRR/pfeZDUCZIOx8vkJBt57hC
|
|
||||||
oTNJ5llFzRcmEraElXmDOAuvmj3Lx/4qzY545rtzll3mFHJEX4qITslIX1ksZz1p
|
|
||||||
DncuqgIECzmZIeHPbnw7Nkv6EkoPzTOlccqnCH/SumFr2fhctv9x13gGcO4kSsqO
|
|
||||||
63yZCFHjMz/mos3l51aIAizj5wQO3BOo+RyKoSQohvPzVtSgjhYMZsAPzXKxF0/H
|
|
||||||
9VH0DekEb1WwPSbGZw8kpx9ePlglGqOBinTL6QW8YmFPbjy9RDd1di+fxh4Qe024
|
|
||||||
8gERZpdSsMoZ+NP0nr/TSbDISFPqcLzzMpC+V8Fc/QkNvSkR1GLlNQrxLoyfK0VX
|
|
||||||
0evysXDxqIWK9+TH7hIS1lf3i2gMkLMppMso1v2Cqf0zRj1oM3MI743QE9XTXKRz
|
|
||||||
iAwaEDDPZWS/00T9fqNrHgtSPNpsbeYZQPYaC2lq1kTIEOlUfZZvMy5lxVPVZ8y2
|
|
||||||
foit+0DewZsqLDJwbjZ3wYMERVEY7KagoInQa3A1ZC9SkFiCb4fNEbRF13gfjrSz
|
|
||||||
muRbKAhEhkzJDFRocIaTKZPIWdvC73tAW66v1Zha74mxuckgnQPPqQ==
|
|
||||||
-----END RSA PRIVATE KEY-----
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
passme
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDvTCCAqWgAwIBAgIUOpY5wp7DtqsdxII7sxculedk0PYwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxGDAWBgNVBAMMD0ludGVybWVkaWF0
|
|
||||||
ZSBDQTAeFw0xODAxMDEwMDAwMDBaFw0yNDEyMzEwMDAwMDBaMG0xCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxDDAKBgNVBAsMA0NTUDEQMA4GA1UE
|
|
||||||
AwwHUmV2b2tlZDEnMCUGCSqGSIb3DQEJARYYb3NzbHNpZ25jb2RlQGV4YW1wbGUu
|
|
||||||
Y29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsksndW3LaWAnD7mi
|
|
||||||
4BXhmqQjC99Y9wTvMPUJ9AgvbzTaNW4JJOQ31x8VVgwoUQ8nFBYkAqgLOv9THzNi
|
|
||||||
30Fc7mjf37Pu6YsqZzql+tknqQbiaysyNm/fouwJDJ+NRzU70fVqI5AS9FBjakXa
|
|
||||||
/l1+pEysCofURJAcKCBQGMSVaP2gwVrHyPI7snFPO6205vqaEOarPira7gvBkYeU
|
|
||||||
Gh+A4AHngyW/jXHt0OHzmL+NrJe5hiayNHAK4ECfXj4PbMibI8PHlRpQkkzO6OhC
|
|
||||||
uI5ngpTZ0dGDLT693tlusvWRFjVrHI1D6MGTtQeeVlnYIKSEGhkgzp7PeWM/CCty
|
|
||||||
mDRG1wIDAQABo2IwYDAJBgNVHRMEAjAAMB0GA1UdDgQWBBQHE8SzT1ZcPEapv4NZ
|
|
||||||
MWBxRB3QATAfBgNVHSMEGDAWgBSeBawLW+FAf2oO9NlET4onfe84izATBgNVHSUE
|
|
||||||
DDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQsFAAOCAQEAYVJiPrkACW/tK487fYS/
|
|
||||||
gYzU3fYVCTfHpAv3njarNzy8UBNqBYr0kDg0DLoOWqGV7ogTtlbQP4IIjAQI/kW6
|
|
||||||
cEreW8yU5VxO+kxDo+7oG9VEbR85i6kQW2ubJsXV6yBtf5aAbXEqImYrtjh7UObb
|
|
||||||
BbQiUI1ll2dXWqvZGxr3Fz1uz8nPMYlBpVjpCh6JF8otdWwABmxRnqUvoLO6BZbH
|
|
||||||
/gdUkouXfio9BlWkWaJXJGXMW8B7ozpjuCHSHyfvGKDA3YIfa7++A1BIKxW72jIF
|
|
||||||
jRJDw/rwnV59tiEcBWmp2T6vV+rD8yaS+LotRPYD/ck/jEj/mV+N077KLmuZpdJF
|
|
||||||
ag==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDrDCCApSgAwIBAgIUUPCDF21g2spK7557HZUhqSxBltMwDQYJKoZIhvcNAQEL
|
|
||||||
BQAwWDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEgMB4GA1UE
|
|
||||||
CwwXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEDAOBgNVBAMMB1Jvb3QgQ0EwHhcN
|
|
||||||
MTgwMTAxMDAwMDAwWhcNMjYwMTAxMDAwMDAwWjBgMQswCQYDVQQGEwJQTDEVMBMG
|
|
||||||
A1UECgwMb3NzbHNpZ25jb2RlMSAwHgYDVQQLDBdDZXJ0aWZpY2F0aW9uIEF1dGhv
|
|
||||||
cml0eTEYMBYGA1UEAwwPSW50ZXJtZWRpYXRlIENBMIIBIjANBgkqhkiG9w0BAQEF
|
|
||||||
AAOCAQ8AMIIBCgKCAQEAyMs1XoC0NUT5YgydibOrE5SWBKk5C47B6tv6gA4t3zZJ
|
|
||||||
wejaiPkj+aTIU3Ww5DO/Gpz0GuqCHNBczIw92Cfvv8kyWzUy46bRkpBJLFav0JXS
|
|
||||||
B3xQaPlHWeXqMfVAGuM5ExT4CjjYKFsrgV1Q300thCHBhvr8TPekDIf+6J7NSz1P
|
|
||||||
062pYgypfqsA8OwKaQbgOL9v4QRmHoolnEDc1dK/FS4f3p9dlifl7kcSVGQK0yit
|
|
||||||
7Uncn250icCxMxS3MOE2NfuplUOSN6h6poWNGUsx00O7Dy9nUndUwJRpFfKXTV3v
|
|
||||||
GtlmFLNoho+ss/usnxjxggWBcRtKhqd8nGSJUlzs0wIDAQABo2YwZDASBgNVHRMB
|
|
||||||
Af8ECDAGAQH/AgEAMB0GA1UdDgQWBBSeBawLW+FAf2oO9NlET4onfe84izAfBgNV
|
|
||||||
HSMEGDAWgBTp7DHcMiltHw6m0SYMWVg0QtGo/jAOBgNVHQ8BAf8EBAMCAYYwDQYJ
|
|
||||||
KoZIhvcNAQELBQADggEBAD/FBa4stJGd/Acg2E2soI071B/l9B7FiqIRpCFuLVC4
|
|
||||||
1m7TIcjioIpZrxXwE1Egf8A9/6D/kKZtWnOljcxtPBEb+1/gB61M381RIgoMQ/Pf
|
|
||||||
7XX2yakk6mscUjbSTR//Mj1sYOs2r6ueZBp0whzF9nVvA43G6WMpf6XZqmhlg/oV
|
|
||||||
ynytW1Iu1SPoru3y8dX/lsukvKCak7MAp1eBcuUJxS56DnKcV9xgC30m3g+CErI3
|
|
||||||
qsOJ7lcfDP6fDjy7MfBsZBiY64MqwlDjjn7+Pleo69JedMwurHLhKnfm07DBPy8X
|
|
||||||
+EnQk61xHEjQtTsddXyQGQV3yjqylOF2AgsAf256uuA=
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
Binary file not shown.
@@ -1,50 +0,0 @@
|
|||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIEzTCCA7WgAwIBAgIUfRjXKciCGA4XbhbhxbAwfpcLGmowDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xODAxMDEwMDAwMDBaFw0yODAxMDEwMDAwMDBaMFUxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxHDAaBgNVBAsME1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkxETAPBgNVBAMMCFRlc3QgVFNBMIIBIjANBgkqhkiG9w0BAQEFAAOC
|
|
||||||
AQ8AMIIBCgKCAQEAor220wp2zqj6Fe1VT/yic4LJcfMn1/ZWhsE7L86krULRvI+N
|
|
||||||
JY0fOVg/24MtyOXbnm7nYOyYTlR9n2kqm4fEgsz+GDQxXLHgyLh3aF4ueDzoFt0v
|
|
||||||
8G3vJfD+4N27XAYJ5V4f4s4VJRDIm0P/BvFGY9J/zICjC83F3OLdnkOD88O8QD6q
|
|
||||||
FwWdtBYNqxQX1LAwy3ORe5aTubdVkHV02JhdKAC/xy5nfhynuV4KfYyel2nHrI1i
|
|
||||||
54UXWdOrlD/XIKPiXpuEGcXhYTrTHigH+yR9ybs9hotGvuHTEjcxEuJvEQJX+qV4
|
|
||||||
eJAIexITDW/yK+maWPLijO3bZ9/JodX+fRCnPQIDAQABo4IBiDCCAYQwDAYDVR0T
|
|
||||||
AQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDAdBgNVHQ4EFgQUKWCqogni
|
|
||||||
6SseJ/P6LXo0M2cK++QwHwYDVR0jBBgwFoAU/5nNuG4Tm4v2y9uKf428/4fVQesw
|
|
||||||
gYQGCCsGAQUFBwEBBHgwdjA5BggrBgEFBQcwAoYtaHR0cDovL1RTQUNBLnRpbWVz
|
|
||||||
dGFtcGF1dGhvcml0eS5jb20vVFNBQ0EuY3J0MDkGCCsGAQUFBzABhi1odHRwOi8v
|
|
||||||
b2NzcC5UU0FDQS50aW1lc3RhbXBhdXRob3JpdHkuY29tOjkwODAwPgYDVR0fBDcw
|
|
||||||
NTAzoDGgL4YtaHR0cDovL1RTQUNBLnRpbWVzdGFtcGF1dGhvcml0eS5jb20vVFNB
|
|
||||||
Q0EuY3JsMFUGA1UdHgROMEygGDAKggh0ZXN0LmNvbTAKggh0ZXN0Lm9yZ6EwMAqH
|
|
||||||
CAAAAAAAAAAAMCKHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMA0G
|
|
||||||
CSqGSIb3DQEBCwUAA4IBAQB4YXa5nVWUzWSsUDMfYFTEETOe8boUErwfrDNBuj6z
|
|
||||||
B5en20FhI49i6PCYEfNq3vrAtPOEFJj+KPomN3C46VLxbUEvqWLdq6EyzWvVVmXK
|
|
||||||
VLeC0qV0m6CFM8GplaWzZdfFTQaaLUhgY08ZU2gp4QsoS2YjAosxlZrNSm6pBbv3
|
|
||||||
q+Og1KeSK8gKS0V89k+6e3LOEF6KaNWKSkoz5xDniQY//mTjiDcNmYUh0KhHfhdU
|
|
||||||
eO92M82uJSaDqnRs5HsWPs6z6qdfpuvj++OtQ1VCM2p5SEH2sEomdeN3YYChuG4h
|
|
||||||
yzn0mYAdbTyGJHlFm17AH+SQRbVqCKYdHDaqsMb+fWzi
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIDkDCCAnigAwIBAgIUJ0nfE+EVsIThltlY2LHVWMJVIq4wDQYJKoZIhvcNAQEL
|
|
||||||
BQAwYDELMAkGA1UEBhMCUEwxFTATBgNVBAoMDG9zc2xzaWduY29kZTEkMCIGA1UE
|
|
||||||
CwwbVGltZXN0YW1wIEF1dGhvcml0eSBSb290IENBMRQwEgYDVQQDDAtUU0EgUm9v
|
|
||||||
dCBDQTAeFw0xNzAxMDEwMDAwMDBaFw0yNjExMTAwMDAwMDBaMGAxCzAJBgNVBAYT
|
|
||||||
AlBMMRUwEwYDVQQKDAxvc3Nsc2lnbmNvZGUxJDAiBgNVBAsMG1RpbWVzdGFtcCBB
|
|
||||||
dXRob3JpdHkgUm9vdCBDQTEUMBIGA1UEAwwLVFNBIFJvb3QgQ0EwggEiMA0GCSqG
|
|
||||||
SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGOTX1f9dmtUiyzlsUInRIGfRMya338SVx
|
|
||||||
vYGeOwdpTSSGlYUVwR9AuFewQF5+klelstCJe+SoUG0AdzS30mRWlQrhip4UdvdW
|
|
||||||
T2gkNKbSn6DQzlWoQej9izqRLxAsbuszgkvnLOBEmPaLimDsCgu0bAN95Hp0Hls9
|
|
||||||
O/fVmzh8VuV4iscxc7q13ZB7CylWgwd55CFEGd/jpJ6kMwSHbOLoBWp4GQ3KxR+c
|
|
||||||
ASAo0FapU2WSZB2EYWszRiyq91X+AvIYN4ypTv7RccgfUvnZ2qFykJAkf/wgkynu
|
|
||||||
Qg7rCUNfUEpDc7jlqtDWR7iLrtHBkA17C3IU8ymmKQYWfw3ZyBwvAgMBAAGjQjBA
|
|
||||||
MA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP+ZzbhuE5uL9svbin+NvP+H1UHr
|
|
||||||
MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAQEAbj3aFwIUxvzwgywO
|
|
||||||
gj01JM8GNbw1E4MGdkaNI8rgeY8ay15ZXhR9NpRWWb6Y7IXPq5XhuEktVte5Z4Kf
|
|
||||||
XLBrr7Xe9VVqJL9zd1tMzOEM/zG77rZf/iXBTZLkCtQc/GOEY4TTWKNEl5hiWVE0
|
|
||||||
po97GX5XHoeyHlWQ75sd9z6MxFxmvdp9/uyYD700e9sd5gcD8LGvHw2DNy8vntYV
|
|
||||||
ia9h95N9i1umffxU460o8W5GoIcsD13B3YftvnWhGSXqovBRFgcPAQZ4eW9Qh/zA
|
|
||||||
4zQBQrRvmREPihXVdgtWVpbRchP99oSZBrYr7Hh/P69rycklquqxJl1ol1wbT6dK
|
|
||||||
S5Gmng==
|
|
||||||
-----END CERTIFICATE-----
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Check cryptography module."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
try:
|
||||||
|
import cryptography
|
||||||
|
print(cryptography.__version__, end="")
|
||||||
|
except ModuleNotFoundError as ierr:
|
||||||
|
print("Module not installed: {}".format(ierr))
|
||||||
|
sys.exit(1)
|
||||||
|
except ImportError as ierr:
|
||||||
|
print("Module not found: {}".format(ierr))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
class UnsupportedVersion(Exception):
|
||||||
|
"""Unsupported version"""
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Check python3-cryptography version"""
|
||||||
|
try:
|
||||||
|
version = tuple(int(num) for num in cryptography.__version__.split('.'))
|
||||||
|
if version < (37, 0, 2):
|
||||||
|
raise UnsupportedVersion("unsupported python3-cryptography version")
|
||||||
|
except UnsupportedVersion as err:
|
||||||
|
print(" {}".format(err), end="")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of an HTTP client"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import http.client
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Creating a POST Request"""
|
||||||
|
ret = 0
|
||||||
|
try:
|
||||||
|
file_path = os.path.join(RESULT_PATH, "./Testing/logs/url.log")
|
||||||
|
with open(file_path, mode="r", encoding="utf-8") as file:
|
||||||
|
url = file.readline()
|
||||||
|
host, port = url.split(":")
|
||||||
|
conn = http.client.HTTPConnection(host, port)
|
||||||
|
conn.request('POST', '/kill_server')
|
||||||
|
response = conn.getresponse()
|
||||||
|
print("HTTP status code:", response.getcode(), end=', ')
|
||||||
|
try:
|
||||||
|
text = response.read()
|
||||||
|
print(text.decode("UTF-8"), end='', flush=True)
|
||||||
|
except OSError as err:
|
||||||
|
print(f"Warning: {err}")
|
||||||
|
conn.close()
|
||||||
|
except OSError as err:
|
||||||
|
print(f"OSError: {err}")
|
||||||
|
ret = err.errno
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print(f"HTTP client error: {err}")
|
||||||
|
ret = err
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""
|
||||||
|
Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -1,260 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
result=0
|
|
||||||
|
|
||||||
test_result() {
|
|
||||||
if test "$1" -eq 0
|
|
||||||
then
|
|
||||||
printf "Succeeded\n" >> "makecerts.log"
|
|
||||||
else
|
|
||||||
printf "Failed\n" >> "makecerts.log"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
make_certs() {
|
|
||||||
password=passme
|
|
||||||
result_path=$(pwd)
|
|
||||||
cd $(dirname "$0")
|
|
||||||
script_path=$(pwd)
|
|
||||||
cd "${result_path}"
|
|
||||||
mkdir "tmp/"
|
|
||||||
rm -rf "../certs"
|
|
||||||
|
|
||||||
# OpenSSL settings
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
if test -n "$1"
|
|
||||||
then
|
|
||||||
OPENSSL="$1/bin/openssl"
|
|
||||||
export LD_LIBRARY_PATH="$1/lib:$1/lib64"
|
|
||||||
else
|
|
||||||
OPENSSL=openssl
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir "CA/" 2>> "makecerts.log" 1>&2
|
|
||||||
touch "CA/index.txt"
|
|
||||||
echo -n "unique_subject = no" > "CA/index.txt.attr"
|
|
||||||
$OPENSSL rand -hex 16 > "CA/serial"
|
|
||||||
$OPENSSL rand -hex 16 > "tsa-serial"
|
|
||||||
echo 1001 > "CA/crlnumber"
|
|
||||||
date > "makecerts.log"
|
|
||||||
"$OPENSSL" version 2>> "makecerts.log" 1>&2
|
|
||||||
echo -n "$password" > tmp/password.txt
|
|
||||||
|
|
||||||
printf "\nGenerate root CA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/CA.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_root.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/CA.key -out tmp/CACert.pem \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Root CA" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate intermediate CA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/intermediate.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/intermediate.key -out CA/intermediate.csr \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=Certification Authority/CN=Intermediate CA" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_root.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/intermediate.csr -out CA/intermediate.cer \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/intermediate.cer -out tmp/intermediate.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate private RSA encrypted key\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -des3 -out CA/private.key -passout pass:"$password" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
cat CA/private.key >> tmp/keyp.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate private RSA decrypted key\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in CA/private.key -passin pass:"$password" -out tmp/key.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate a certificate to revoke\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/revoked.csr \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=CSP/CN=Revoked/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/revoked.csr -out CA/revoked.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/revoked.cer -out tmp/revoked.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nRevoke above certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -revoke CA/revoked.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to revoked certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/revoked.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate CRL file\n" >> "makecerts.log"
|
|
||||||
TZ=GMT faketime -f '@2019-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -gencrl -crldays 8766 -out tmp/CACertCRL.pem \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert revoked certificate to SPC format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" crl2pkcs7 -in tmp/CACertCRL.pem -certfile tmp/revoked.pem -outform DER -out tmp/revoked.spc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate CSP Cross-Certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/cross.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2018-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_intermediate.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 900 -key CA/cross.key -out tmp/crosscert.pem \
|
|
||||||
-subj "/C=PL/O=osslsigncode/OU=CSP/CN=crosscert/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate code signing certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/cert.csr \
|
|
||||||
-subj "/C=PL/ST=Mazovia Province/L=Warsaw/O=osslsigncode/OU=CSP/CN=Certificate/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/cert.csr -out CA/cert.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/cert.cer -out tmp/cert.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the key to DER format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in tmp/key.pem -outform DER -out tmp/key.der -passout pass:"$password" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the key to PVK format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" rsa -in tmp/key.pem -outform PVK -out tmp/key.pvk -pvk-none \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate to DER format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" x509 -in tmp/cert.pem -outform DER -out tmp/cert.der \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to code signing certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/cert.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate to SPC format\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" crl2pkcs7 -nocrl -certfile tmp/cert.pem -outform DER -out tmp/cert.spc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nConvert the certificate and the key into a PKCS#12 container\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" pkcs12 -export -in tmp/cert.pem -inkey tmp/key.pem -out tmp/cert.p12 -passout pass:"$password" \
|
|
||||||
-keypbe aes-256-cbc -certpbe aes-256-cbc \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate expired certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -key CA/private.key -passin pass:"$password" -out CA/expired.csr \
|
|
||||||
-subj "/C=PL/ST=Mazovia Province/L=Warsaw/O=osslsigncode/OU=CSP/CN=Expired/emailAddress=osslsigncode@example.com" \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" ca -config "$CONF" -enddate "190101000000Z" -batch -in CA/expired.csr -out CA/expired.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/expired.cer -out tmp/expired.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nAttach intermediate certificate to expired certificate\n" >> "makecerts.log"
|
|
||||||
cat tmp/intermediate.pem >> tmp/expired.pem 2>> "makecerts.log"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate Root CA TSA certificate\n" >> "makecerts.log"
|
|
||||||
"$OPENSSL" genrsa -out CA/TSACA.key \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
TZ=GMT faketime -f '@2017-01-01 00:00:00' /bin/bash -c '
|
|
||||||
script_path=$(pwd)
|
|
||||||
OPENSSL="$0"
|
|
||||||
export LD_LIBRARY_PATH="$1"
|
|
||||||
CONF="${script_path}/openssl_tsa_root.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -x509 -days 3600 -key CA/TSACA.key -out tmp/TSACA.pem \
|
|
||||||
2>> "makecerts.log" 1>&2' "$OPENSSL" "$LD_LIBRARY_PATH"
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nGenerate TSA certificate\n" >> "makecerts.log"
|
|
||||||
CONF="${script_path}/openssl_tsa.cnf"
|
|
||||||
"$OPENSSL" req -config "$CONF" -new -nodes -keyout tmp/TSA.key -out CA/TSA.csr \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
CONF="${script_path}/openssl_tsa_root.cnf"
|
|
||||||
"$OPENSSL" ca -config "$CONF" -batch -in CA/TSA.csr -out CA/TSA.cer \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
"$OPENSSL" x509 -in CA/TSA.cer -out tmp/TSA.pem \
|
|
||||||
2>> "makecerts.log" 1>&2
|
|
||||||
test_result $?
|
|
||||||
|
|
||||||
printf "\nSave the chain to be included in the TSA response\n" >> "makecerts.log"
|
|
||||||
cat tmp/TSA.pem tmp/TSACA.pem > tmp/tsa-chain.pem 2>> "makecerts.log"
|
|
||||||
|
|
||||||
# copy new files
|
|
||||||
if test -s tmp/intermediate.pem -a -s tmp/CACert.pem -a -s tmp/CACertCRL.pem \
|
|
||||||
-a -s tmp/key.pem -a -s tmp/keyp.pem -a -s tmp/key.der -a -s tmp/key.pvk \
|
|
||||||
-a -s tmp/cert.pem -a -s tmp/cert.p12 -a -s tmp/cert.der -a -s tmp/cert.spc \
|
|
||||||
-a -s tmp/crosscert.pem -a -s tmp/expired.pem -a -s tmp/revoked.pem -a -s tmp/revoked.spc \
|
|
||||||
-a -s tmp/TSA.pem -a -s tmp/TSA.key -a -s tmp/tsa-chain.pem
|
|
||||||
then
|
|
||||||
mkdir "../certs"
|
|
||||||
cp tmp/* ../certs
|
|
||||||
printf "%s" "keys & certificates successfully generated"
|
|
||||||
else
|
|
||||||
printf "%s" "error logs ${result_path}/makecerts.log"
|
|
||||||
result=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# remove the working directory
|
|
||||||
rm -rf "CA/"
|
|
||||||
rm -rf "tmp/"
|
|
||||||
|
|
||||||
exit "$result"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Tests requirement
|
|
||||||
if test -n "$(command -v faketime)"
|
|
||||||
then
|
|
||||||
make_certs "$1"
|
|
||||||
result=$?
|
|
||||||
else
|
|
||||||
printf "%s" "faketime not found in \$PATH, please install faketime package"
|
|
||||||
result=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit "$result"
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
# OpenSSL intermediate CA configuration file
|
|
||||||
|
|
||||||
[ default ]
|
|
||||||
name = intermediate
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
# Directory and file locations
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/$name.key
|
|
||||||
certificate = $dir/tmp/$name.pem
|
|
||||||
crl_extensions = crl_ext
|
|
||||||
default_md = sha256
|
|
||||||
preserve = no
|
|
||||||
policy = policy_loose
|
|
||||||
default_startdate = 180101000000Z
|
|
||||||
default_enddate = 241231000000Z
|
|
||||||
x509_extensions = v3_req
|
|
||||||
email_in_dn = yes
|
|
||||||
default_days = 2200
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
encrypt_key = no
|
|
||||||
default_bits = 2048
|
|
||||||
default_md = sha256
|
|
||||||
string_mask = utf8only
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
x509_extensions = usr_extensions
|
|
||||||
|
|
||||||
[ crl_ext ]
|
|
||||||
# Extension for CRLs
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
|
|
||||||
[ usr_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid, issuer
|
|
||||||
extendedKeyUsage = codeSigning
|
|
||||||
|
|
||||||
[ v3_req ]
|
|
||||||
basicConstraints = CA:FALSE
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid, issuer
|
|
||||||
extendedKeyUsage = codeSigning
|
|
||||||
|
|
||||||
[ policy_loose ]
|
|
||||||
# Allow the intermediate CA to sign a more diverse range of certificates.
|
|
||||||
# See the POLICY FORMAT section of the `ca` man page.
|
|
||||||
countryName = optional
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
localityName = optional
|
|
||||||
organizationName = optional
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
stateOrProvinceName = State or Province Name
|
|
||||||
localityName = Locality Name
|
|
||||||
0.organizationName = Organization Name
|
|
||||||
organizationalUnitName = Organizational Unit Name
|
|
||||||
commonName = Common Name
|
|
||||||
emailAddress = Email Address
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# OpenSSL root CA configuration file
|
|
||||||
|
|
||||||
[ ca ]
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
# Directory and file locations.
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/CA.key
|
|
||||||
certificate = $dir/tmp/CACert.pem
|
|
||||||
crl_extensions = crl_ext
|
|
||||||
default_md = sha256
|
|
||||||
preserve = no
|
|
||||||
policy = policy_match
|
|
||||||
default_startdate = 180101000000Z
|
|
||||||
default_enddate = 260101000000Z
|
|
||||||
x509_extensions = v3_intermediate_ca
|
|
||||||
email_in_dn = yes
|
|
||||||
default_days = 3000
|
|
||||||
unique_subject = no
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
encrypt_key = no
|
|
||||||
default_bits = 2048
|
|
||||||
default_md = sha256
|
|
||||||
string_mask = utf8only
|
|
||||||
x509_extensions = ca_extensions
|
|
||||||
distinguished_name = req_distinguished_name
|
|
||||||
|
|
||||||
[ ca_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = critical, CA:true
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always,issuer
|
|
||||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
||||||
|
|
||||||
[ v3_intermediate_ca ]
|
|
||||||
# Extensions for a typical intermediate CA (`man x509v3_config`)
|
|
||||||
basicConstraints = critical, CA:true, pathlen:0
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always,issuer
|
|
||||||
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
|
|
||||||
|
|
||||||
[ policy_match ]
|
|
||||||
countryName = match
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ req_distinguished_name ]
|
|
||||||
countryName = Country Name (2 letter code)
|
|
||||||
stateOrProvinceName = State or Province Name
|
|
||||||
localityName = Locality Name
|
|
||||||
0.organizationName = Organization Name
|
|
||||||
organizationalUnitName = Organizational Unit Name
|
|
||||||
commonName = Common Name
|
|
||||||
emailAddress = Email Address
|
|
||||||
@@ -44,3 +44,4 @@ ordering = yes
|
|||||||
tsa_name = yes
|
tsa_name = yes
|
||||||
ess_cert_id_chain = yes
|
ess_cert_id_chain = yes
|
||||||
ess_cert_id_alg = sha256
|
ess_cert_id_alg = sha256
|
||||||
|
crypto_device = builtin
|
||||||
|
|||||||
@@ -1,83 +0,0 @@
|
|||||||
# OpenSSL Root Timestamp Authority configuration file
|
|
||||||
|
|
||||||
[ default ]
|
|
||||||
name = TSACA
|
|
||||||
domain_suffix = timestampauthority.com
|
|
||||||
aia_url = http://$name.$domain_suffix/$name.crt
|
|
||||||
crl_url = http://$name.$domain_suffix/$name.crl
|
|
||||||
ocsp_url = http://ocsp.$name.$domain_suffix:9080
|
|
||||||
name_opt = utf8, esc_ctrl, multiline, lname, align
|
|
||||||
default_ca = CA_default
|
|
||||||
|
|
||||||
[ CA_default ]
|
|
||||||
dir = .
|
|
||||||
certs = $dir/CA
|
|
||||||
crl_dir = $dir/CA
|
|
||||||
new_certs_dir = $dir/CA
|
|
||||||
database = $dir/CA/index.txt
|
|
||||||
serial = $dir/CA/serial
|
|
||||||
crlnumber = $dir/CA/crlnumber
|
|
||||||
rand_serial = yes
|
|
||||||
private_key = $dir/CA/$name.key
|
|
||||||
certificate = $dir/tmp/$name.pem
|
|
||||||
default_md = sha256
|
|
||||||
default_days = 3650
|
|
||||||
default_crl_days = 365
|
|
||||||
policy = policy_match
|
|
||||||
default_startdate = 20180101000000Z
|
|
||||||
default_enddate = 20280101000000Z
|
|
||||||
unique_subject = no
|
|
||||||
x509_extensions = tsa_extensions
|
|
||||||
|
|
||||||
[ policy_match ]
|
|
||||||
countryName = match
|
|
||||||
stateOrProvinceName = optional
|
|
||||||
organizationName = match
|
|
||||||
organizationalUnitName = optional
|
|
||||||
commonName = supplied
|
|
||||||
emailAddress = optional
|
|
||||||
|
|
||||||
[ tsa_extensions ]
|
|
||||||
basicConstraints = critical, CA:false
|
|
||||||
extendedKeyUsage = critical, timeStamping
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
authorityKeyIdentifier = keyid:always
|
|
||||||
authorityInfoAccess = @issuer_info
|
|
||||||
crlDistributionPoints = @crl_info
|
|
||||||
nameConstraints = @name_constraints
|
|
||||||
|
|
||||||
[ issuer_info ]
|
|
||||||
caIssuers;URI.0 = $aia_url
|
|
||||||
OCSP;URI.0 = $ocsp_url
|
|
||||||
|
|
||||||
[ crl_info ]
|
|
||||||
URI.0 = $crl_url
|
|
||||||
|
|
||||||
[ name_constraints ]
|
|
||||||
permitted;DNS.0=test.com
|
|
||||||
permitted;DNS.1=test.org
|
|
||||||
excluded;IP.0=0.0.0.0/0.0.0.0
|
|
||||||
excluded;IP.1=0:0:0:0:0:0:0:0/0:0:0:0:0:0:0:0
|
|
||||||
|
|
||||||
[ req ]
|
|
||||||
# Options for the `req` tool
|
|
||||||
default_bits = 2048
|
|
||||||
encrypt_key = yes
|
|
||||||
default_md = sha256
|
|
||||||
utf8 = yes
|
|
||||||
string_mask = utf8only
|
|
||||||
prompt = no
|
|
||||||
distinguished_name = ca_distinguished_name
|
|
||||||
x509_extensions = ca_extensions
|
|
||||||
|
|
||||||
[ ca_distinguished_name ]
|
|
||||||
countryName = "PL"
|
|
||||||
organizationName = "osslsigncode"
|
|
||||||
organizationalUnitName = "Timestamp Authority Root CA"
|
|
||||||
commonName = "TSA Root CA"
|
|
||||||
|
|
||||||
[ ca_extensions ]
|
|
||||||
# Extension to add when the -x509 option is used
|
|
||||||
basicConstraints = critical, CA:true
|
|
||||||
subjectKeyIdentifier = hash
|
|
||||||
keyUsage = critical, keyCertSign, cRLSign
|
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of a single ctest script."""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
|
||||||
|
|
||||||
|
def parse(value):
|
||||||
|
"""Read parameter from file."""
|
||||||
|
prefix = 'FILE '
|
||||||
|
if value.startswith(prefix):
|
||||||
|
with open(value[len(prefix):], mode="r", encoding="utf-8") as file:
|
||||||
|
return file.read().strip()
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Run osslsigncode with its options."""
|
||||||
|
if len(sys.argv) > 1:
|
||||||
|
try:
|
||||||
|
params = map(parse, sys.argv[1:])
|
||||||
|
proc = Popen(params, stdout=PIPE, stderr=PIPE, text=True)
|
||||||
|
stdout, stderr = proc.communicate()
|
||||||
|
print(stdout, file=sys.stderr)
|
||||||
|
if stderr:
|
||||||
|
print("Error:\n" + "-" * 58 + "\n" + stderr, file=sys.stderr)
|
||||||
|
sys.exit(proc.returncode)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
# all exceptions are critical
|
||||||
|
print(err, file=sys.stderr)
|
||||||
|
else:
|
||||||
|
print("Usage:\n\t{} COMMAND [ARG]...".format(sys.argv[0]), file=sys.stderr)
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
Binary file not shown.
Binary file not shown.
Executable → Regular
BIN
Binary file not shown.
Executable → Regular
@@ -0,0 +1 @@
|
|||||||
|
console.log("Hello, world!");
|
||||||
Binary file not shown.
@@ -0,0 +1,2 @@
|
|||||||
|
cls
|
||||||
|
Write-Host "żółć"
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<PSConsoleFile ConsoleSchemaVersion="1.0">
|
||||||
|
<PSVersion>5.1.19041.3930</PSVersion>
|
||||||
|
<PSSnapIns />
|
||||||
|
</PSConsoleFile>
|
||||||
@@ -0,0 +1,593 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Make test certificates"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import datetime
|
||||||
|
import cryptography
|
||||||
|
|
||||||
|
# Explicit imports of cryptography submodules
|
||||||
|
import cryptography.x509
|
||||||
|
import cryptography.x509.oid
|
||||||
|
import cryptography.hazmat.primitives.hashes
|
||||||
|
import cryptography.hazmat.primitives.asymmetric.rsa
|
||||||
|
import cryptography.hazmat.primitives.serialization
|
||||||
|
import cryptography.hazmat.primitives.serialization.pkcs12
|
||||||
|
|
||||||
|
# Import classes and functions from the cryptography module
|
||||||
|
from cryptography.x509 import (
|
||||||
|
AuthorityKeyIdentifier,
|
||||||
|
BasicConstraints,
|
||||||
|
Certificate,
|
||||||
|
CertificateBuilder,
|
||||||
|
CertificateRevocationListBuilder,
|
||||||
|
CRLDistributionPoints,
|
||||||
|
CRLNumber,
|
||||||
|
CRLReason,
|
||||||
|
DistributionPoint,
|
||||||
|
DNSName,
|
||||||
|
ExtendedKeyUsage,
|
||||||
|
KeyUsage,
|
||||||
|
Name,
|
||||||
|
NameAttribute,
|
||||||
|
NameConstraints,
|
||||||
|
random_serial_number,
|
||||||
|
RevokedCertificateBuilder,
|
||||||
|
ReasonFlags,
|
||||||
|
SubjectKeyIdentifier,
|
||||||
|
UniformResourceIdentifier
|
||||||
|
)
|
||||||
|
from cryptography.x509.oid import (
|
||||||
|
ExtendedKeyUsageOID,
|
||||||
|
NameOID
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives.hashes import SHA256
|
||||||
|
from cryptography.hazmat.primitives.asymmetric.rsa import (
|
||||||
|
generate_private_key,
|
||||||
|
RSAPrivateKey
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives.serialization import (
|
||||||
|
BestAvailableEncryption,
|
||||||
|
Encoding,
|
||||||
|
NoEncryption,
|
||||||
|
PrivateFormat
|
||||||
|
)
|
||||||
|
from cryptography.hazmat.primitives.serialization.pkcs12 import serialize_key_and_certificates
|
||||||
|
|
||||||
|
try:
|
||||||
|
if cryptography.__version__ >= '38.0.0':
|
||||||
|
from cryptography.hazmat.primitives.serialization.pkcs12 import PBES
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
|
||||||
|
date_20170101 = datetime.datetime(2017, 1, 1)
|
||||||
|
date_20180101 = datetime.datetime(2018, 1, 1)
|
||||||
|
date_20190101 = datetime.datetime(2019, 1, 1)
|
||||||
|
|
||||||
|
PASSWORD='passme'
|
||||||
|
|
||||||
|
|
||||||
|
class X509Extensions():
|
||||||
|
"""Base class for X509 Extensions"""
|
||||||
|
|
||||||
|
def __init__(self, unit_name, cdp_port, cdp_name):
|
||||||
|
self.unit_name = unit_name
|
||||||
|
self.port = cdp_port
|
||||||
|
self.name = cdp_name
|
||||||
|
|
||||||
|
def create_x509_name(self, common_name) -> Name:
|
||||||
|
"""Return x509.Name"""
|
||||||
|
return Name(
|
||||||
|
[
|
||||||
|
NameAttribute(NameOID.COUNTRY_NAME, "PL"),
|
||||||
|
NameAttribute(NameOID.STATE_OR_PROVINCE_NAME, "Mazovia Province"),
|
||||||
|
NameAttribute(NameOID.LOCALITY_NAME, "Warsaw"),
|
||||||
|
NameAttribute(NameOID.ORGANIZATION_NAME, "osslsigncode"),
|
||||||
|
NameAttribute(NameOID.ORGANIZATIONAL_UNIT_NAME, self.unit_name),
|
||||||
|
NameAttribute(NameOID.COMMON_NAME, common_name)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_crldp(self) -> CRLDistributionPoints:
|
||||||
|
"""Return x509.CRLDistributionPoints"""
|
||||||
|
return CRLDistributionPoints(
|
||||||
|
[
|
||||||
|
DistributionPoint(
|
||||||
|
full_name=[UniformResourceIdentifier(
|
||||||
|
"http://127.0.0.1:" + str(self.port) + "/" + str(self.name))
|
||||||
|
],
|
||||||
|
relative_name=None,
|
||||||
|
reasons=None,
|
||||||
|
crl_issuer=None
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_x509_name_constraints(self) -> NameConstraints:
|
||||||
|
"""Return x509.NameConstraints"""
|
||||||
|
return NameConstraints(
|
||||||
|
permitted_subtrees = [DNSName('test.com'), DNSName('test.org')],
|
||||||
|
excluded_subtrees = None
|
||||||
|
)
|
||||||
|
|
||||||
|
class IntermediateCACertificate(X509Extensions):
|
||||||
|
"""Base class for Intermediate CA certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key):
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
super().__init__("Certification Authority", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (Certificate, RSAPrivateKey):
|
||||||
|
"""Generate intermediate CA certificate"""
|
||||||
|
key = generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
key_public = key.public_key()
|
||||||
|
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=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name("Intermediate CA"))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(key_public)
|
||||||
|
.serial_number(random_serial_number())
|
||||||
|
.not_valid_before(date_20180101)
|
||||||
|
.not_valid_after(date_20180101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(BasicConstraints(ca=True, path_length=0), critical=True)
|
||||||
|
.add_extension(SubjectKeyIdentifier.from_public_key(key_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(key_usage, critical=True)
|
||||||
|
.sign(self.issuer_key, SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "intermediateCA.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
return cert, key
|
||||||
|
|
||||||
|
|
||||||
|
class RootCACertificate(X509Extensions):
|
||||||
|
"""Base class for Root CA certificate"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.key_usage = KeyUsage(
|
||||||
|
digital_signature=True,
|
||||||
|
content_commitment=False,
|
||||||
|
key_encipherment=False,
|
||||||
|
data_encipherment=False,
|
||||||
|
key_agreement=False,
|
||||||
|
key_cert_sign=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
super().__init__("Certification Authority", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (Certificate, RSAPrivateKey):
|
||||||
|
"""Generate CA certificates"""
|
||||||
|
ca_root, root_key = self.make_ca_cert("Trusted Root CA", "CAroot.pem")
|
||||||
|
ca_cert, ca_key = self.make_ca_cert("Root CA", "CACert.pem")
|
||||||
|
self.make_cross_cert(ca_root, root_key, ca_cert, ca_key)
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def make_ca_cert(self, common_name, file_name) -> None:
|
||||||
|
"""Generate self-signed root CA certificate"""
|
||||||
|
ca_key = generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
|
||||||
|
name = self.create_x509_name(common_name)
|
||||||
|
ca_cert = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(name)
|
||||||
|
.issuer_name(name)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(random_serial_number())
|
||||||
|
.not_valid_before(date_20170101)
|
||||||
|
.not_valid_after(date_20170101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(self.key_usage, critical=True)
|
||||||
|
.sign(ca_key, SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, file_name)
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def make_cross_cert(self, ca_root, root_key, ca_cert, ca_key) -> None:
|
||||||
|
"""Generate cross-signed root CA certificate"""
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
ca_root.extensions.get_extension_for_class(SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
ca_cross = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(ca_cert.subject)
|
||||||
|
.issuer_name(ca_root.subject)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(ca_cert.serial_number)
|
||||||
|
.not_valid_before(date_20180101)
|
||||||
|
.not_valid_after(date_20180101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(self.key_usage, critical=True)
|
||||||
|
.sign(root_key, SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "CAcross.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cross.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
def write_key(self, key, file_name) -> None:
|
||||||
|
"""Write a private RSA key"""
|
||||||
|
# Write password
|
||||||
|
file_path = os.path.join(CERTS_PATH, "password.txt")
|
||||||
|
with open(file_path, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("{}".format(PASSWORD))
|
||||||
|
|
||||||
|
# Write encrypted key in PEM format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + "p.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=Encoding.PEM,
|
||||||
|
format=PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=BestAvailableEncryption(PASSWORD.encode())
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Write decrypted key in PEM format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=Encoding.PEM,
|
||||||
|
format=PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
# Write the key in DER format
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=Encoding.DER,
|
||||||
|
format=PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TSARootCACertificate(X509Extensions):
|
||||||
|
"""Base class for TSA certificates"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__("Timestamp Authority Root CA", 0, None)
|
||||||
|
|
||||||
|
def make_cert(self) -> (Certificate, RSAPrivateKey):
|
||||||
|
"""Generate a Time Stamp Authority certificate"""
|
||||||
|
ca_key = generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
ca_public = ca_key.public_key()
|
||||||
|
authority_key = AuthorityKeyIdentifier.from_issuer_public_key(ca_public)
|
||||||
|
name = self.create_x509_name("TSA Root CA")
|
||||||
|
key_usage = KeyUsage(
|
||||||
|
digital_signature=False,
|
||||||
|
content_commitment=False,
|
||||||
|
key_encipherment=False,
|
||||||
|
data_encipherment=False,
|
||||||
|
key_agreement=False,
|
||||||
|
key_cert_sign=True,
|
||||||
|
crl_sign=True,
|
||||||
|
encipher_only=False,
|
||||||
|
decipher_only=False
|
||||||
|
)
|
||||||
|
ca_cert = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(name)
|
||||||
|
.issuer_name(name)
|
||||||
|
.public_key(ca_public)
|
||||||
|
.serial_number(random_serial_number())
|
||||||
|
.not_valid_before(date_20170101)
|
||||||
|
.not_valid_after(date_20170101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(BasicConstraints(ca=True, path_length=None), critical=True)
|
||||||
|
.add_extension(SubjectKeyIdentifier.from_public_key(ca_public), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(key_usage, critical=True)
|
||||||
|
.sign(ca_key, SHA256())
|
||||||
|
)
|
||||||
|
file_path=os.path.join(CERTS_PATH, "TSACA.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(ca_cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
return ca_cert, ca_key
|
||||||
|
|
||||||
|
def write_key(self, key, file_name) -> None:
|
||||||
|
"""Write decrypted private RSA key into PEM format"""
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".key")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(key.private_bytes(
|
||||||
|
encoding=Encoding.PEM,
|
||||||
|
format=PrivateFormat.PKCS8,
|
||||||
|
encryption_algorithm=NoEncryption()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class LeafCertificate(X509Extensions):
|
||||||
|
"""Base class for a leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, unit_name, common_name, cdp_port, cdp_name):
|
||||||
|
#pylint: disable=too-many-arguments
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
self.common_name = common_name
|
||||||
|
super().__init__(unit_name, cdp_port, cdp_name)
|
||||||
|
|
||||||
|
def make_cert(self, public_key, not_before, days) -> Certificate:
|
||||||
|
"""Generate a leaf certificate"""
|
||||||
|
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]
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name(self.common_name))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(public_key)
|
||||||
|
.serial_number(random_serial_number())
|
||||||
|
.not_valid_before(not_before)
|
||||||
|
.not_valid_after(not_before + datetime.timedelta(days=days))
|
||||||
|
.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())
|
||||||
|
)
|
||||||
|
# Write PEM file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
file.write(self.issuer_cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
return cert
|
||||||
|
|
||||||
|
def revoke_cert(self, serial_number, file_name) -> None:
|
||||||
|
"""Revoke a certificate"""
|
||||||
|
revoked = (
|
||||||
|
RevokedCertificateBuilder()
|
||||||
|
.serial_number(serial_number)
|
||||||
|
.revocation_date(date_20190101)
|
||||||
|
.add_extension(CRLReason(ReasonFlags.superseded), critical=False)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
# Generate CRL
|
||||||
|
authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
crl = (
|
||||||
|
CertificateRevocationListBuilder()
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.last_update(date_20190101)
|
||||||
|
.next_update(date_20190101 + datetime.timedelta(days=7300))
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(CRLNumber(4097), critical=False)
|
||||||
|
.add_revoked_certificate(revoked)
|
||||||
|
.sign(self.issuer_key, SHA256())
|
||||||
|
)
|
||||||
|
# Write CRL file
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(crl.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name + ".der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(crl.public_bytes(encoding=Encoding.DER))
|
||||||
|
|
||||||
|
|
||||||
|
class LeafCACertificate(LeafCertificate):
|
||||||
|
"""Base class for a leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, common, cdp_port):
|
||||||
|
super().__init__(issuer_cert, issuer_key, "CSP", common, cdp_port, "intermediateCA")
|
||||||
|
|
||||||
|
|
||||||
|
class LeafTSACertificate(LeafCertificate):
|
||||||
|
"""Base class for a TSA leaf certificate"""
|
||||||
|
|
||||||
|
def __init__(self, issuer_cert, issuer_key, common, cdp_port):
|
||||||
|
self.issuer_cert = issuer_cert
|
||||||
|
self.issuer_key = issuer_key
|
||||||
|
self.common_name = common
|
||||||
|
super().__init__(issuer_cert, issuer_key, "Timestamp Root CA", common, cdp_port, "TSACA")
|
||||||
|
|
||||||
|
def make_cert(self, public_key, not_before, days) -> Certificate:
|
||||||
|
"""Generate a TSA leaf certificate"""
|
||||||
|
|
||||||
|
authority_key = AuthorityKeyIdentifier.from_issuer_subject_key_identifier(
|
||||||
|
self.issuer_cert.extensions.get_extension_for_class(SubjectKeyIdentifier).value
|
||||||
|
)
|
||||||
|
|
||||||
|
# The TSA signing certificate must have exactly one extended key usage
|
||||||
|
# assigned to it: timeStamping. The extended key usage must also be critical,
|
||||||
|
# otherwise the certificate is going to be refused.
|
||||||
|
extended_key_usage = ExtendedKeyUsage(
|
||||||
|
[ExtendedKeyUsageOID.TIME_STAMPING]
|
||||||
|
)
|
||||||
|
cert = (
|
||||||
|
CertificateBuilder()
|
||||||
|
.subject_name(self.create_x509_name(self.common_name))
|
||||||
|
.issuer_name(self.issuer_cert.subject)
|
||||||
|
.public_key(public_key)
|
||||||
|
.serial_number(random_serial_number())
|
||||||
|
.not_valid_before(not_before)
|
||||||
|
.not_valid_after(not_before + datetime.timedelta(days=days))
|
||||||
|
.add_extension(BasicConstraints(ca=False, path_length=None), critical=True)
|
||||||
|
.add_extension(SubjectKeyIdentifier.from_public_key(public_key), critical=False)
|
||||||
|
.add_extension(authority_key, critical=False)
|
||||||
|
.add_extension(extended_key_usage, critical=True)
|
||||||
|
.add_extension(self.create_x509_crldp(), critical=False)
|
||||||
|
.add_extension(self.create_x509_name_constraints(), critical=False)
|
||||||
|
.sign(self.issuer_key, SHA256())
|
||||||
|
)
|
||||||
|
# Write PEM file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, self.common_name + ".pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
file.write(self.issuer_cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
return cert
|
||||||
|
|
||||||
|
|
||||||
|
class CertificateMaker():
|
||||||
|
"""Base class for test certificates"""
|
||||||
|
|
||||||
|
def __init__(self, cdp_port, logs):
|
||||||
|
self.cdp_port = cdp_port
|
||||||
|
self.logs = logs
|
||||||
|
|
||||||
|
def make_certs(self) -> None:
|
||||||
|
"""Make test certificates"""
|
||||||
|
try:
|
||||||
|
self.make_ca_certs()
|
||||||
|
self.make_tsa_certs()
|
||||||
|
logs = os.path.join(CERTS_PATH, "./cert.log")
|
||||||
|
with open(logs, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("Test certificates generation succeeded")
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
with open(self.logs, mode="a", encoding="utf-8") as file:
|
||||||
|
file.write("Error: {}".format(err))
|
||||||
|
|
||||||
|
def make_ca_certs(self):
|
||||||
|
"""Make test certificates"""
|
||||||
|
|
||||||
|
# Generate root CA certificate
|
||||||
|
root = RootCACertificate()
|
||||||
|
ca_cert, ca_key = root.make_cert()
|
||||||
|
|
||||||
|
# Generate intermediate root CA certificate
|
||||||
|
intermediate = IntermediateCACertificate(ca_cert, ca_key)
|
||||||
|
issuer_cert, issuer_key = intermediate.make_cert()
|
||||||
|
|
||||||
|
# Generate private RSA key
|
||||||
|
private_key = generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
root.write_key(key=private_key, file_name="key")
|
||||||
|
|
||||||
|
# Generate expired certificate
|
||||||
|
expired = LeafCACertificate(issuer_cert, issuer_key, "expired", self.cdp_port)
|
||||||
|
expired.make_cert(public_key, date_20180101, 365)
|
||||||
|
|
||||||
|
# Generate revoked certificate
|
||||||
|
revoked = LeafCACertificate(issuer_cert, issuer_key, "revoked", self.cdp_port)
|
||||||
|
cert = revoked.make_cert(public_key, date_20180101, 5840)
|
||||||
|
revoked.revoke_cert(cert.serial_number, "CACertCRL")
|
||||||
|
|
||||||
|
# Generate code signing certificate
|
||||||
|
signer = LeafCACertificate(issuer_cert, issuer_key, "cert", self.cdp_port)
|
||||||
|
cert = signer.make_cert(public_key, date_20180101, 5840)
|
||||||
|
|
||||||
|
# Write a certificate and a key into PKCS#12 container
|
||||||
|
self.write_pkcs12_container(
|
||||||
|
cert=cert,
|
||||||
|
key=private_key,
|
||||||
|
issuer=issuer_cert
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write DER file and attach intermediate certificate
|
||||||
|
file_path = os.path.join(CERTS_PATH, "cert.der")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=Encoding.DER))
|
||||||
|
|
||||||
|
def make_tsa_certs(self):
|
||||||
|
"""Make test TSA certificates"""
|
||||||
|
|
||||||
|
# Time Stamp Authority certificate
|
||||||
|
root = TSARootCACertificate()
|
||||||
|
issuer_cert, issuer_key = root.make_cert()
|
||||||
|
|
||||||
|
# Generate private RSA key
|
||||||
|
private_key = generate_private_key(public_exponent=65537, key_size=2048)
|
||||||
|
public_key = private_key.public_key()
|
||||||
|
root.write_key(key=private_key, file_name="TSA")
|
||||||
|
|
||||||
|
# Generate revoked TSA certificate
|
||||||
|
revoked = LeafTSACertificate(issuer_cert, issuer_key, "TSA_revoked", self.cdp_port)
|
||||||
|
cert = revoked.make_cert(public_key, date_20180101, 7300)
|
||||||
|
revoked.revoke_cert(cert.serial_number, "TSACertCRL")
|
||||||
|
|
||||||
|
# Generate TSA certificate
|
||||||
|
signer = LeafTSACertificate(issuer_cert, issuer_key, "TSA", self.cdp_port)
|
||||||
|
cert = signer.make_cert(public_key, date_20180101, 7300)
|
||||||
|
|
||||||
|
# Save the chain to be included in the TSA response
|
||||||
|
file_path = os.path.join(CERTS_PATH, "tsa-chain.pem")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
file.write(issuer_cert.public_bytes(encoding=Encoding.PEM))
|
||||||
|
|
||||||
|
|
||||||
|
def write_pkcs12_container(self, cert, key, issuer) -> None:
|
||||||
|
"""Write a certificate and a key into a PKCS#12 container"""
|
||||||
|
|
||||||
|
# Set an encryption algorithm
|
||||||
|
if cryptography.__version__ >= "38.0.0":
|
||||||
|
# For OpenSSL legacy mode use the default algorithm for certificate
|
||||||
|
# and private key encryption: DES-EDE3-CBC (vel 3DES_CBC)
|
||||||
|
# pylint: disable=no-member
|
||||||
|
encryption = (
|
||||||
|
PrivateFormat.PKCS12.encryption_builder()
|
||||||
|
.key_cert_algorithm(PBES.PBESv1SHA1And3KeyTripleDESCBC)
|
||||||
|
.kdf_rounds(5000)
|
||||||
|
.build(PASSWORD.encode())
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
encryption = BestAvailableEncryption(PASSWORD.encode())
|
||||||
|
|
||||||
|
# Generate PKCS#12 struct
|
||||||
|
pkcs12 = serialize_key_and_certificates(
|
||||||
|
name=b'certificate',
|
||||||
|
key=key,
|
||||||
|
cert=cert,
|
||||||
|
cas=(issuer,),
|
||||||
|
encryption_algorithm=encryption
|
||||||
|
)
|
||||||
|
|
||||||
|
# Write into a PKCS#12 container
|
||||||
|
file_path = os.path.join(CERTS_PATH, "cert.p12")
|
||||||
|
with open(file_path, mode="wb") as file:
|
||||||
|
file.write(pkcs12)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Implementation of an HTTP server"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from http.server import SimpleHTTPRequestHandler, HTTPServer
|
||||||
|
from socketserver import ThreadingMixIn
|
||||||
|
from make_certificates import CertificateMaker
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
||||||
|
RESPONSE = os.path.join(FILES_PATH, "./jresp.tsr")
|
||||||
|
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
URL_LOG = os.path.join(LOGS_PATH, "./url.log")
|
||||||
|
|
||||||
|
OPENSSL_TS = ["openssl", "ts",
|
||||||
|
"-reply", "-config", OPENSSL_CONF,
|
||||||
|
"-passin", "pass:passme",
|
||||||
|
"-queryfile", REQUEST,
|
||||||
|
"-out", RESPONSE]
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadingHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
|
"""This variant of HTTPServer creates a new thread for every connection"""
|
||||||
|
daemon_threads = True
|
||||||
|
|
||||||
|
|
||||||
|
class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
|
"""Handle the HTTP POST request that arrive at the server"""
|
||||||
|
|
||||||
|
def __init__(self, request, client_address, server):
|
||||||
|
# Save the server handle
|
||||||
|
self.server = server
|
||||||
|
SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
|
||||||
|
|
||||||
|
def do_GET(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the GET request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/pkix-crl")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
# Read the file and send the contents
|
||||||
|
if url.path == "/intermediateCA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./CACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
if url.path == "/TSACA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./TSACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the POST request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
if url.path == "/kill_server":
|
||||||
|
self.log_message(f"Deleting file: {URL_LOG}")
|
||||||
|
os.remove(f"{URL_LOG}")
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(bytes('Shutting down HTTP server', 'utf-8'))
|
||||||
|
self.server.shutdown()
|
||||||
|
else:
|
||||||
|
content_length = int(self.headers['Content-Length'])
|
||||||
|
post_data = self.rfile.read(content_length)
|
||||||
|
with open(REQUEST, mode="wb") as file:
|
||||||
|
file.write(post_data)
|
||||||
|
openssl = subprocess.run(OPENSSL_TS, check=True, universal_newlines=True)
|
||||||
|
openssl.check_returncode()
|
||||||
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
with open(RESPONSE, mode="rb") as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServerThread():
|
||||||
|
"""TSA server thread handler"""
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
|
||||||
|
def start_server(self, port) -> (int):
|
||||||
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
|
self.server = ThreadingHTTPServer(('127.0.0.1', port), RequestHandler)
|
||||||
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
|
self.server_thread.start()
|
||||||
|
hostname, port = self.server.server_address[:2]
|
||||||
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Start HTTP server, make test certificates."""
|
||||||
|
|
||||||
|
ret = 0
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="port number"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
server = HttpServerThread()
|
||||||
|
port = server.start_server(args.port)
|
||||||
|
with open(URL_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("127.0.0.1:{}".format(port))
|
||||||
|
tests = CertificateMaker(port, SERVER_LOG)
|
||||||
|
tests.make_certs()
|
||||||
|
except OSError as err:
|
||||||
|
print("OSError: {}".format(err))
|
||||||
|
ret = err.errno
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("Error: {}".format(err))
|
||||||
|
ret = 1
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
try:
|
||||||
|
fpid = os.fork()
|
||||||
|
if fpid > 0:
|
||||||
|
sys.exit(0)
|
||||||
|
with open(SERVER_LOG, mode='w', encoding='utf-8') as log:
|
||||||
|
os.dup2(log.fileno(), sys.stdout.fileno())
|
||||||
|
os.dup2(log.fileno(), sys.stderr.fileno())
|
||||||
|
except OSError as ferr:
|
||||||
|
print("Fork #1 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
fpid = os.fork()
|
||||||
|
if fpid > 0:
|
||||||
|
sys.exit(0)
|
||||||
|
except OSError as ferr:
|
||||||
|
print("Fork #2 failed: {} {}".format(ferr.errno, ferr.strerror))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Start the daemon main loop
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -0,0 +1,149 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Windows: Implementation of an HTTP server"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import threading
|
||||||
|
from urllib.parse import urlparse
|
||||||
|
from http.server import SimpleHTTPRequestHandler, ThreadingHTTPServer
|
||||||
|
from make_certificates import CertificateMaker
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
||||||
|
RESPONSE = os.path.join(FILES_PATH, "./jresp.tsr")
|
||||||
|
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
URL_LOG = os.path.join(LOGS_PATH, "./url.log")
|
||||||
|
|
||||||
|
|
||||||
|
OPENSSL_TS = ["openssl", "ts",
|
||||||
|
"-reply", "-config", OPENSSL_CONF,
|
||||||
|
"-passin", "pass:passme",
|
||||||
|
"-queryfile", REQUEST,
|
||||||
|
"-out", RESPONSE]
|
||||||
|
|
||||||
|
|
||||||
|
class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
|
"""Handle the HTTP POST request that arrive at the server"""
|
||||||
|
|
||||||
|
def __init__(self, request, client_address, server):
|
||||||
|
# Save the server handle
|
||||||
|
self.server = server
|
||||||
|
SimpleHTTPRequestHandler.__init__(self, request, client_address, server)
|
||||||
|
|
||||||
|
def do_GET(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the GET request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header("Content-type", "application/pkix-crl")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
# Read the file and send the contents
|
||||||
|
if url.path == "/intermediateCA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./CACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
if url.path == "/TSACA":
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./TSACertCRL.der")
|
||||||
|
with open(file_path, 'rb') as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP GET request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
def do_POST(self): # pylint: disable=invalid-name
|
||||||
|
""""Serves the POST request type"""
|
||||||
|
try:
|
||||||
|
url = urlparse(self.path)
|
||||||
|
self.send_response(200)
|
||||||
|
if url.path == "/kill_server":
|
||||||
|
self.log_message(f"Deleting file: {URL_LOG}")
|
||||||
|
os.remove(f"{URL_LOG}")
|
||||||
|
self.send_header('Content-type', 'text/plain')
|
||||||
|
self.end_headers()
|
||||||
|
self.wfile.write(bytes('Shutting down HTTP server', 'utf-8'))
|
||||||
|
self.server.shutdown()
|
||||||
|
else:
|
||||||
|
content_length = int(self.headers['Content-Length'])
|
||||||
|
post_data = self.rfile.read(content_length)
|
||||||
|
with open(REQUEST, mode="wb") as file:
|
||||||
|
file.write(post_data)
|
||||||
|
openssl = subprocess.run(OPENSSL_TS,
|
||||||
|
check=True, universal_newlines=True)
|
||||||
|
openssl.check_returncode()
|
||||||
|
self.send_header("Content-type", "application/timestamp-reply")
|
||||||
|
self.end_headers()
|
||||||
|
resp_data = b''
|
||||||
|
with open(RESPONSE, mode="rb") as file:
|
||||||
|
resp_data = file.read()
|
||||||
|
self.wfile.write(resp_data)
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
print("HTTP POST request error: {}".format(err))
|
||||||
|
|
||||||
|
|
||||||
|
class HttpServerThread():
|
||||||
|
"""TSA server thread handler"""
|
||||||
|
# pylint: disable=too-few-public-methods
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self.server = None
|
||||||
|
self.server_thread = None
|
||||||
|
|
||||||
|
def start_server(self, port) -> (int):
|
||||||
|
"""Starting HTTP server on 127.0.0.1 and a random available port for binding"""
|
||||||
|
self.server = ThreadingHTTPServer(('127.0.0.1', port), RequestHandler)
|
||||||
|
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
||||||
|
self.server_thread.start()
|
||||||
|
hostname, port = self.server.server_address[:2]
|
||||||
|
print("HTTP server started, URL http://{}:{}".format(hostname, port))
|
||||||
|
return port
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Start HTTP server"""
|
||||||
|
|
||||||
|
ret = 0
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--port",
|
||||||
|
type=int,
|
||||||
|
default=0,
|
||||||
|
help="port number"
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
sys.stdout = open(SERVER_LOG, "w")
|
||||||
|
sys.stderr = open(SERVER_LOG, "a")
|
||||||
|
server = HttpServerThread()
|
||||||
|
port = server.start_server(args.port)
|
||||||
|
with open(URL_LOG, mode="w") as file:
|
||||||
|
file.write("127.0.0.1:{}".format(port))
|
||||||
|
tests = CertificateMaker(port, SERVER_LOG)
|
||||||
|
tests.make_certs()
|
||||||
|
except OSError as err:
|
||||||
|
print("OSError: {}".format(err))
|
||||||
|
ret = err.errno
|
||||||
|
finally:
|
||||||
|
sys.exit(ret)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
# https://learn.microsoft.com/en-us/windows/win32/seccrypto/makecat
|
||||||
|
# makecat -v CatalogDefinitionFileName.cdf
|
||||||
|
|
||||||
|
# Define information about the entire catalog file.
|
||||||
|
[CatalogHeader]
|
||||||
|
|
||||||
|
# Name of the catalog file, including its extension.
|
||||||
|
Name=unsigned.cat
|
||||||
|
|
||||||
|
# Directory where the created unsigned.cat file will be placed.
|
||||||
|
ResultDir=..\files
|
||||||
|
|
||||||
|
# This option is not supported. Default value 1 is used.
|
||||||
|
PublicVersion=0x0000001
|
||||||
|
|
||||||
|
# Catalog version.
|
||||||
|
# If the version is set to 2, the HashAlgorithms option must contain SHA256.
|
||||||
|
CatalogVersion=2
|
||||||
|
|
||||||
|
# Name of the hashing algorithm used.
|
||||||
|
HashAlgorithms=SHA256
|
||||||
|
|
||||||
|
# Specifies whether to hash the files listed in the <HASH> option in the [CatalogFiles] section
|
||||||
|
PageHashes=true
|
||||||
|
|
||||||
|
# Type of message encoding used.
|
||||||
|
# The default EncodingType is PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0x00010001
|
||||||
|
EncodingType=0x00010001
|
||||||
|
|
||||||
|
# Specify an attribute of the catalog file.
|
||||||
|
# Set 1.3.6.1.4.1.311.12.2.1 CAT_NAMEVALUE_OBJID
|
||||||
|
# CATATTR1={type}:{oid}:{value} (optional)
|
||||||
|
# The OSAttr attribute specifies the target Windows version
|
||||||
|
CATATTR1=0x11010001:OSAttr:2:6.0
|
||||||
|
|
||||||
|
# Define each member of the catalog file.
|
||||||
|
[CatalogFiles]
|
||||||
|
|
||||||
|
<HASH>PEfile=..\files\unsigned.exe
|
||||||
|
# 0x00010000 Attribute is represented in plaintext. No conversion will be done.
|
||||||
|
<HASH>PEfileATTR1=0x11010001:File:unsigned.exe
|
||||||
|
|
||||||
|
<HASH>MSIfile=..\files\unsigned.msi
|
||||||
|
# 0x00020000 Attribute is represented in base-64 encoding.
|
||||||
|
<HASH>MSIfileATTR1=0x11020001:File:dW5zaWduZWQubXNp
|
||||||
|
|
||||||
|
<HASH>CABfile=..\files\unsigned.ex_
|
||||||
|
<HASH>CABfileATTR1=0x11010001:File:unsigned.ex_
|
||||||
|
|
||||||
|
<HASH>PS1file=..\files\unsigned.ps1
|
||||||
|
<HASH>PS1fileATTR1=0x11010001:File:unsigned.ps1
|
||||||
|
|
||||||
|
<HASH>PSC1file=..\files\unsigned.psc1
|
||||||
|
<HASH>PSC1fileATTR1=0x11010001:File:unsigned.psc1
|
||||||
|
|
||||||
|
<HASH>MOFfile=..\files\unsigned.mof
|
||||||
|
<HASH>MOFfileATTR1=0x11010001:File:unsigned.mof
|
||||||
|
|
||||||
|
<HASH>JSfile=..\files\unsigned.js
|
||||||
|
<HASH>JSfileATTR1=0x11010001:File:unsigned.js
|
||||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/python3
|
||||||
|
"""Wait for all tests certificate, compute leafhash"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import binascii
|
||||||
|
import hashlib
|
||||||
|
import os
|
||||||
|
import pathlib
|
||||||
|
import platform
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
RESULT_PATH = os.getcwd()
|
||||||
|
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
||||||
|
LOGS_PATH = os.path.join(RESULT_PATH, "./Testing/logs/")
|
||||||
|
SERVER_LOG = os.path.join(LOGS_PATH, "./server.log")
|
||||||
|
if platform.system() == 'Windows':
|
||||||
|
DEFAULT_PYTHON = "C:/Program Files/Python/Python311/pythonw.exe"
|
||||||
|
DEFAULT_PROG = os.path.join(RESULT_PATH, "./Testing/server_http.pyw")
|
||||||
|
else:
|
||||||
|
DEFAULT_PYTHON = "/usr/bin/python3"
|
||||||
|
DEFAULT_PROG = os.path.join(RESULT_PATH, "./Testing/server_http.py")
|
||||||
|
|
||||||
|
|
||||||
|
def compute_sha256(file_name) -> str:
|
||||||
|
"""Compute a SHA256 hash of the leaf certificate (in DER form)"""
|
||||||
|
|
||||||
|
sha256_hash = hashlib.sha256()
|
||||||
|
file_path = os.path.join(CERTS_PATH, file_name)
|
||||||
|
with open(file_path, mode="rb") as file:
|
||||||
|
for bajt in iter(lambda: file.read(4096),b""):
|
||||||
|
sha256_hash.update(bajt)
|
||||||
|
return sha256_hash.hexdigest()
|
||||||
|
|
||||||
|
def clear_catalog(certs_path) -> None:
|
||||||
|
""""Clear a test certificates catalog."""
|
||||||
|
|
||||||
|
if os.path.exists(certs_path):
|
||||||
|
#Remove old test certificates
|
||||||
|
for root, _, files in os.walk(certs_path):
|
||||||
|
for file in files:
|
||||||
|
os.remove(os.path.join(root, file))
|
||||||
|
else:
|
||||||
|
os.mkdir(certs_path)
|
||||||
|
|
||||||
|
# Generate 16 random bytes and convert to hex
|
||||||
|
random_hex = binascii.b2a_hex(os.urandom(16)).decode()
|
||||||
|
serial = os.path.join(certs_path, "./tsa-serial")
|
||||||
|
with open(serial, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write(random_hex)
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Wait for all test certificates and compute leaf hash"""
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument(
|
||||||
|
"--exe",
|
||||||
|
type=pathlib.Path,
|
||||||
|
default=DEFAULT_PYTHON,
|
||||||
|
help=f"the path to the python3 executable to use"
|
||||||
|
f"(default: {DEFAULT_PYTHON})",
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
"--script",
|
||||||
|
type=pathlib.Path,
|
||||||
|
default=DEFAULT_PROG,
|
||||||
|
help=f"the path to the python script to run"
|
||||||
|
f"(default: {DEFAULT_PROG})",
|
||||||
|
)
|
||||||
|
args = parser.parse_args()
|
||||||
|
try:
|
||||||
|
clear_catalog(CERTS_PATH)
|
||||||
|
#pylint: disable=consider-using-with
|
||||||
|
subprocess.Popen([str(args.exe), str(args.script)])
|
||||||
|
|
||||||
|
cert_log = os.path.join(CERTS_PATH, "./cert.log")
|
||||||
|
while not (os.path.exists(cert_log) and os.path.getsize(cert_log) > 0):
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
leafhash = compute_sha256("cert.der")
|
||||||
|
file_path = os.path.join(CERTS_PATH, "./leafhash.txt")
|
||||||
|
with open(file_path, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("SHA256:{}".format(leafhash))
|
||||||
|
|
||||||
|
except OSError as err:
|
||||||
|
with open(SERVER_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("OSError: {}".format(err))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
except Exception as err: # pylint: disable=broad-except
|
||||||
|
with open(SERVER_LOG, mode="w", encoding="utf-8") as file:
|
||||||
|
file.write("Error: {}".format(err))
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=pointless-string-statement
|
||||||
|
"""Local Variables:
|
||||||
|
c-basic-offset: 4
|
||||||
|
tab-width: 4
|
||||||
|
indent-tabs-mode: nil
|
||||||
|
End:
|
||||||
|
vim: set ts=4 expandtab:
|
||||||
|
"""
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
"""Implementation of a Time Stamping Authority HTTP server"""
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import contextlib
|
|
||||||
import os
|
|
||||||
import pathlib
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import threading
|
|
||||||
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
||||||
|
|
||||||
RESULT_PATH = os.getcwd()
|
|
||||||
FILES_PATH = os.path.join(RESULT_PATH, "./Testing/files/")
|
|
||||||
CERTS_PATH = os.path.join(RESULT_PATH, "./Testing/certs/")
|
|
||||||
CONF_PATH = os.path.join(RESULT_PATH, "./Testing/conf/")
|
|
||||||
DEFAULT_IN = os.path.join(FILES_PATH, "./unsigned.exe")
|
|
||||||
DEFAULT_OUT = os.path.join(FILES_PATH, "./ts.exe")
|
|
||||||
DEFAULT_CERT = os.path.join(CERTS_PATH, "./cert.pem")
|
|
||||||
DEFAULT_KEY = os.path.join(CERTS_PATH, "./key.pem")
|
|
||||||
DEFAULT_CROSSCERT = os.path.join(CERTS_PATH, "./crosscert.pem")
|
|
||||||
OPENSSL_CONF = os.path.join(CONF_PATH, "./openssl_tsa.cnf")
|
|
||||||
REQUEST = os.path.join(FILES_PATH, "./jreq.tsq")
|
|
||||||
RESPONS = os.path.join(FILES_PATH, "./jresp.tsr")
|
|
||||||
|
|
||||||
if os.path.exists(os.path.join(RESULT_PATH, "./Release/")):
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./Release/osslsigncode")
|
|
||||||
elif os.path.exists(os.path.join(RESULT_PATH, "./Debug/")):
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./Debug/osslsigncode")
|
|
||||||
else:
|
|
||||||
OSSLSIGNCODE_FILE = os.path.join(RESULT_PATH, "./osslsigncode")
|
|
||||||
|
|
||||||
DEFAULT_OPENSSL = ["openssl", "ts",
|
|
||||||
"-reply", "-config", OPENSSL_CONF,
|
|
||||||
"-passin", "pass:passme",
|
|
||||||
"-queryfile", REQUEST,
|
|
||||||
"-out", RESPONS]
|
|
||||||
|
|
||||||
|
|
||||||
class RequestHandler(BaseHTTPRequestHandler):
|
|
||||||
"""Handle the HTTP POST request that arrive at the server"""
|
|
||||||
|
|
||||||
def do_POST(self):
|
|
||||||
""""Serves the POST request type"""
|
|
||||||
try:
|
|
||||||
content_length = int(self.headers['Content-Length'])
|
|
||||||
post_data = self.rfile.read(content_length)
|
|
||||||
with open(REQUEST, mode="wb") as file:
|
|
||||||
file.write(post_data)
|
|
||||||
openssl = subprocess.run(DEFAULT_OPENSSL, check=True, text=True)
|
|
||||||
openssl.check_returncode()
|
|
||||||
self.send_response(200)
|
|
||||||
self.send_header("Content-type", "application/timestamp-reply")
|
|
||||||
self.end_headers()
|
|
||||||
resp_data = None
|
|
||||||
with open(RESPONS, mode="rb") as file:
|
|
||||||
resp_data = file.read()
|
|
||||||
self.wfile.write(resp_data)
|
|
||||||
except Exception as err: # pylint: disable=broad-except
|
|
||||||
print(f"HTTP POST request error: {err}")
|
|
||||||
|
|
||||||
|
|
||||||
class HttpServerThread():
|
|
||||||
"""TSA server thread handler"""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.server = None
|
|
||||||
self.server_thread = None
|
|
||||||
|
|
||||||
def start_server(self) -> (str, int):
|
|
||||||
"""Starting TSA server on localhost and a first available port"""
|
|
||||||
self.server = HTTPServer(("127.0.0.1", 0), RequestHandler)
|
|
||||||
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
|
||||||
self.server_thread.start()
|
|
||||||
hostname, port = self.server.server_address[:2]
|
|
||||||
print(f"Timestamp server started, URL: http://{hostname}:{port}")
|
|
||||||
return hostname, port
|
|
||||||
|
|
||||||
def shut_down(self):
|
|
||||||
"""Shutting down the server"""
|
|
||||||
if self.server:
|
|
||||||
self.server.shutdown()
|
|
||||||
self.server_thread.join()
|
|
||||||
print("Server is down")
|
|
||||||
|
|
||||||
|
|
||||||
def parse_args() -> str:
|
|
||||||
"""Parse the command-line arguments."""
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
"--input",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_IN,
|
|
||||||
help="input file"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--output",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_OUT,
|
|
||||||
help="output file"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--certs",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_CERT,
|
|
||||||
help="signing certificate"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--key",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_KEY,
|
|
||||||
help="private key"
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
"--crosscert",
|
|
||||||
type=pathlib.Path,
|
|
||||||
default=DEFAULT_CROSSCERT,
|
|
||||||
help="additional certificates"
|
|
||||||
)
|
|
||||||
args = parser.parse_args()
|
|
||||||
program = [OSSLSIGNCODE_FILE, "sign", "-in", args.input, "-out", args.output,
|
|
||||||
"-certs", args.certs, "-key", args.key,
|
|
||||||
"-addUnauthenticatedBlob", "-add-msi-dse", "-comm", "-ph", "-jp", "low",
|
|
||||||
"-h", "sha384", "-time", "1556668800", "-i", "https://www.osslsigncode.com/",
|
|
||||||
"-n", "osslsigncode", "-ac", args.crosscert, "-ts"]
|
|
||||||
return program
|
|
||||||
|
|
||||||
def main() -> None:
|
|
||||||
"""Main program"""
|
|
||||||
ret = 0
|
|
||||||
program = parse_args()
|
|
||||||
server = HttpServerThread()
|
|
||||||
hostname, port = server.start_server()
|
|
||||||
program.append(f"{hostname}:{port}")
|
|
||||||
try:
|
|
||||||
osslsigncode = subprocess.run(program, check=True, text=True)
|
|
||||||
osslsigncode.check_returncode()
|
|
||||||
except subprocess.CalledProcessError as err:
|
|
||||||
ret = err.returncode
|
|
||||||
except OSError as err:
|
|
||||||
print(f"OSError: {err}")
|
|
||||||
ret = err.errno
|
|
||||||
except Exception as err: # pylint: disable=broad-except
|
|
||||||
print(f"osslsigncode error: {err}")
|
|
||||||
ret = 1
|
|
||||||
finally:
|
|
||||||
server.shut_down()
|
|
||||||
sys.exit(ret)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
main()
|
|
||||||
@@ -0,0 +1,347 @@
|
|||||||
|
// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/
|
||||||
|
// 10 november 2016
|
||||||
|
#include "utf.h"
|
||||||
|
|
||||||
|
// this code imitates Go's unicode/utf8 and unicode/utf16
|
||||||
|
// the biggest difference is that a rune is unsigned instead of signed (because Go guarantees what a right shift on a signed number will do, whereas C does not)
|
||||||
|
// it is also an imitation so we can license it under looser terms than the Go source
|
||||||
|
#define badrune 0xFFFD
|
||||||
|
|
||||||
|
// encoded must be at most 4 bytes
|
||||||
|
// TODO clean this code up somehow
|
||||||
|
size_t utf8EncodeRune(uint32_t rune, char *encoded)
|
||||||
|
{
|
||||||
|
uint8_t b, c, d, e;
|
||||||
|
size_t n;
|
||||||
|
|
||||||
|
// not in the valid range for Unicode
|
||||||
|
if (rune > 0x10FFFF)
|
||||||
|
rune = badrune;
|
||||||
|
// surrogate runes cannot be encoded
|
||||||
|
if (rune >= 0xD800 && rune < 0xE000)
|
||||||
|
rune = badrune;
|
||||||
|
|
||||||
|
if (rune < 0x80) { // ASCII bytes represent themselves
|
||||||
|
b = (uint8_t) (rune & 0xFF);
|
||||||
|
n = 1;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (rune < 0x800) { // two-byte encoding
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x1F);
|
||||||
|
b |= 0xC0;
|
||||||
|
n = 2;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
if (rune < 0x10000) { // three-byte encoding
|
||||||
|
d = (uint8_t) (rune & 0x3F);
|
||||||
|
d |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x0F);
|
||||||
|
b |= 0xE0;
|
||||||
|
n = 3;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
// otherwise use a four-byte encoding
|
||||||
|
e = (uint8_t) (rune & 0x3F);
|
||||||
|
e |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
d = (uint8_t) (rune & 0x3F);
|
||||||
|
d |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
c = (uint8_t) (rune & 0x3F);
|
||||||
|
c |= 0x80;
|
||||||
|
rune >>= 6;
|
||||||
|
b = (uint8_t) (rune & 0x07);
|
||||||
|
b |= 0xF0;
|
||||||
|
n = 4;
|
||||||
|
|
||||||
|
done:
|
||||||
|
encoded[0] = (char)b;
|
||||||
|
if (n > 1)
|
||||||
|
encoded[1] = (char)c;
|
||||||
|
if (n > 2)
|
||||||
|
encoded[2] = (char)d;
|
||||||
|
if (n > 3)
|
||||||
|
encoded[3] = (char)e;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
uint8_t b, c;
|
||||||
|
uint8_t lowestAllowed, highestAllowed;
|
||||||
|
size_t i, expected;
|
||||||
|
int bad;
|
||||||
|
|
||||||
|
b = (uint8_t) (*s);
|
||||||
|
if (b < 0x80) { // ASCII bytes represent themselves
|
||||||
|
*rune = b;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
// 0xC0 and 0xC1 cover 2-byte overlong equivalents
|
||||||
|
// 0xF5 to 0xFD cover values > 0x10FFFF
|
||||||
|
// 0xFE and 0xFF were never defined (always illegal)
|
||||||
|
if (b < 0xC2 || b > 0xF4) { // invalid
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this determines the range of allowed first continuation bytes
|
||||||
|
lowestAllowed = 0x80;
|
||||||
|
highestAllowed = 0xBF;
|
||||||
|
switch (b) {
|
||||||
|
case 0xE0:
|
||||||
|
// disallow 3-byte overlong equivalents
|
||||||
|
lowestAllowed = 0xA0;
|
||||||
|
break;
|
||||||
|
case 0xED:
|
||||||
|
// disallow surrogate characters
|
||||||
|
highestAllowed = 0x9F;
|
||||||
|
break;
|
||||||
|
case 0xF0:
|
||||||
|
// disallow 4-byte overlong equivalents
|
||||||
|
lowestAllowed = 0x90;
|
||||||
|
break;
|
||||||
|
case 0xF4:
|
||||||
|
// disallow values > 0x10FFFF
|
||||||
|
highestAllowed = 0x8F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and this determines how many continuation bytes are expected
|
||||||
|
expected = 1;
|
||||||
|
if (b >= 0xE0)
|
||||||
|
expected++;
|
||||||
|
if (b >= 0xF0)
|
||||||
|
expected++;
|
||||||
|
if (nElem != 0) { // are there enough bytes?
|
||||||
|
nElem--;
|
||||||
|
if (nElem < expected) { // nope
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure that everything is correct
|
||||||
|
// if not, **only** consume the initial byte
|
||||||
|
bad = 0;
|
||||||
|
for (i = 0; i < expected; i++) {
|
||||||
|
c = (uint8_t) (s[1 + i]);
|
||||||
|
if (c < lowestAllowed || c > highestAllowed) {
|
||||||
|
bad = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// the old lowestAllowed and highestAllowed is only for the first continuation byte
|
||||||
|
lowestAllowed = 0x80;
|
||||||
|
highestAllowed = 0xBF;
|
||||||
|
}
|
||||||
|
if (bad) {
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// now do the topmost bits
|
||||||
|
if (b < 0xE0)
|
||||||
|
*rune = b & 0x1F;
|
||||||
|
else if (b < 0xF0)
|
||||||
|
*rune = b & 0x0F;
|
||||||
|
else
|
||||||
|
*rune = b & 0x07;
|
||||||
|
s++; // we can finally move on
|
||||||
|
|
||||||
|
// now do the continuation bytes
|
||||||
|
for (; expected; expected--) {
|
||||||
|
c = (uint8_t) (*s);
|
||||||
|
s++;
|
||||||
|
c &= 0x3F; // strip continuation bits
|
||||||
|
*rune <<= 6;
|
||||||
|
*rune |= c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// encoded must have at most 2 elements
|
||||||
|
size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded)
|
||||||
|
{
|
||||||
|
uint16_t low, high;
|
||||||
|
|
||||||
|
// not in the valid range for Unicode
|
||||||
|
if (rune > 0x10FFFF)
|
||||||
|
rune = badrune;
|
||||||
|
// surrogate runes cannot be encoded
|
||||||
|
if (rune >= 0xD800 && rune < 0xE000)
|
||||||
|
rune = badrune;
|
||||||
|
|
||||||
|
if (rune < 0x10000) {
|
||||||
|
encoded[0] = (uint16_t) rune;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rune -= 0x10000;
|
||||||
|
low = (uint16_t) (rune & 0x3FF);
|
||||||
|
rune >>= 10;
|
||||||
|
high = (uint16_t) (rune & 0x3FF);
|
||||||
|
encoded[0] = high | 0xD800;
|
||||||
|
encoded[1] = low | 0xDC00;
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO see if this can be cleaned up somehow
|
||||||
|
const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
uint16_t high, low;
|
||||||
|
|
||||||
|
if (*s < 0xD800 || *s >= 0xE000) {
|
||||||
|
// self-representing character
|
||||||
|
*rune = *s;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (*s >= 0xDC00) {
|
||||||
|
// out-of-order surrogates
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
if (nElem == 1) { // not enough elements
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
high = *s;
|
||||||
|
high &= 0x3FF;
|
||||||
|
if (s[1] < 0xDC00 || s[1] >= 0xE000) {
|
||||||
|
// bad surrogate pair
|
||||||
|
*rune = badrune;
|
||||||
|
s++;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
s++;
|
||||||
|
low = *s;
|
||||||
|
s++;
|
||||||
|
low &= 0x3FF;
|
||||||
|
*rune = high;
|
||||||
|
*rune <<= 10;
|
||||||
|
*rune |= low;
|
||||||
|
*rune += 0x10000;
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO find a way to reduce the code in all of these somehow
|
||||||
|
// TODO find a way to remove u as well
|
||||||
|
size_t utf8RuneCount(const char *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const char *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf8DecodeRune(t, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf8DecodeRune(s, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf8UTF16Count(const char *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
uint16_t encoded[2];
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const char *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf8DecodeRune(t, nElem, &rune);
|
||||||
|
len += utf16EncodeRune(rune, encoded);
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf8DecodeRune(s, nElem, &rune);
|
||||||
|
len += utf16EncodeRune(rune, encoded);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf16RuneCount(const uint16_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const uint16_t *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf16DecodeRune(t, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf16DecodeRune(s, nElem, &rune);
|
||||||
|
len++;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t utf16UTF8Count(const uint16_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
size_t len;
|
||||||
|
uint32_t rune;
|
||||||
|
char encoded[4];
|
||||||
|
|
||||||
|
if (nElem != 0) {
|
||||||
|
const uint16_t *t, *u;
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
t = s;
|
||||||
|
while (nElem != 0) {
|
||||||
|
u = utf16DecodeRune(t, nElem, &rune);
|
||||||
|
len += utf8EncodeRune(rune, encoded);
|
||||||
|
nElem -= (size_t)(u - t);
|
||||||
|
t = u;
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
len = 0;
|
||||||
|
while (*s) {
|
||||||
|
s = utf16DecodeRune(s, nElem, &rune);
|
||||||
|
len += utf8EncodeRune(rune, encoded);
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
// utf by pietro gagliardi (andlabs) — https://github.com/andlabs/utf/
|
||||||
|
// 10 november 2016
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
// if nElem == 0, assume the buffer has no upper limit and is '\0' terminated
|
||||||
|
// otherwise, assume buffer is NOT '\0' terminated but is bounded by nElem *elements*
|
||||||
|
|
||||||
|
extern size_t utf8EncodeRune(uint32_t rune, char *encoded);
|
||||||
|
extern const char *utf8DecodeRune(const char *s, size_t nElem, uint32_t *rune);
|
||||||
|
extern size_t utf16EncodeRune(uint32_t rune, uint16_t *encoded);
|
||||||
|
extern const uint16_t *utf16DecodeRune(const uint16_t *s, size_t nElem, uint32_t *rune);
|
||||||
|
|
||||||
|
extern size_t utf8RuneCount(const char *s, size_t nElem);
|
||||||
|
extern size_t utf8UTF16Count(const char *s, size_t nElem);
|
||||||
|
extern size_t utf16RuneCount(const uint16_t *s, size_t nElem);
|
||||||
|
extern size_t utf16UTF8Count(const uint16_t *s, size_t nElem);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
|
||||||
|
// Provide overloads on Windows for using these functions with wchar_t and WCHAR when wchar_t is a keyword in C++ mode (the default).
|
||||||
|
// Otherwise, you'd need to cast to pass a wchar_t pointer, WCHAR pointer, or equivalent to these functions.
|
||||||
|
// We use __wchar_t to be independent of the setting; see https://blogs.msdn.microsoft.com/oldnewthing/20161201-00/?p=94836 (ironically posted one day after I initially wrote this code!).
|
||||||
|
// TODO check this on MinGW-w64
|
||||||
|
// TODO check this under /Wall
|
||||||
|
// TODO C-style casts enough? or will that fail in /Wall?
|
||||||
|
// TODO same for UniChar/unichar on Mac? if both are unsigned then we have nothing to worry about
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
|
||||||
|
inline size_t utf16EncodeRune(uint32_t rune, __wchar_t *encoded)
|
||||||
|
{
|
||||||
|
return utf16EncodeRune(rune, reinterpret_cast<uint16_t *>(encoded));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const __wchar_t *utf16DecodeRune(const __wchar_t *s, size_t nElem, uint32_t *rune)
|
||||||
|
{
|
||||||
|
const uint16_t *ret;
|
||||||
|
|
||||||
|
ret = utf16DecodeRune(reinterpret_cast<const uint16_t *>(s), nElem, rune);
|
||||||
|
return reinterpret_cast<const __wchar_t *>(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t utf16RuneCount(const __wchar_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
return utf16RuneCount(reinterpret_cast<const uint16_t *>(s), nElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline size_t utf16UTF8Count(const __wchar_t *s, size_t nElem)
|
||||||
|
{
|
||||||
|
return utf16UTF8Count(reinterpret_cast<const uint16_t *>(s), nElem);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
+3
-6
@@ -3,10 +3,7 @@
|
|||||||
"version-string": "2.4",
|
"version-string": "2.4",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
"openssl",
|
"openssl",
|
||||||
"curl",
|
"zlib"
|
||||||
{
|
],
|
||||||
"name": "python3",
|
"builtin-baseline": "9edb1b8e590cc086563301d735cae4b6e732d2d2"
|
||||||
"platform": "!(windows & static) & !osx"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user