Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
workflow_dispatch:
inputs:
version:
description: Release version to build/publish (for example 0.6.2)
description: Release version to build/publish (for example 0.6.3)
required: true
type: string
publish_nuget:
Expand Down
18 changes: 9 additions & 9 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ repository = "https://github.com/Devolutions/psign"

[package]
name = "psign"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Rust port of the Windows SDK signtool.exe (Authenticode sign/verify/timestamp) with portable digest helpers."
license.workspace = true
Expand All @@ -46,7 +46,6 @@ default = [
]
## Azure Key Vault signing (`AuthenticatorDigestSign` callback + REST); enables Azure-shaped CLI flags on `sign`.
azure-kv-sign = [
"dep:psign-portable-core",
"dep:psign-azure-kv-rest",
"dep:reqwest",
"psign-digest-cli/azure-kv-sign-portable",
Expand All @@ -55,7 +54,6 @@ azure-kv-sign = [
## Azure Artifact Signing / Trusted Signing **data-plane** hash signing (REST LRO); experimental helper command `artifact-signing-submit`.
artifact-signing-rest = [
"dep:psign-codesigning-rest",
"dep:psign-portable-core",
"psign-digest-cli/artifact-signing-rest",
"psign-portable-core/artifact-signing-rest",
]
Expand All @@ -69,7 +67,7 @@ psign-sip-digest = { path = "crates/psign-sip-digest" }
psign-authenticode-trust = { path = "crates/psign-authenticode-trust" }
psign-digest-cli = { path = "crates/psign-digest-cli" }
psign-opc-sign = { path = "crates/psign-opc-sign" }
psign-portable-core = { path = "crates/psign-portable-core", optional = true }
psign-portable-core = { path = "crates/psign-portable-core" }
anyhow = "1"
clap = { version = "4", features = ["derive"] }
serde = { version = "1", features = ["derive"] }
Expand Down
2 changes: 1 addition & 1 deletion PowerShell/Devolutions.Psign/Devolutions.Psign.psd1
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
@{
RootModule = 'Devolutions.Psign.psm1'
ModuleVersion = '0.6.2'
ModuleVersion = '0.6.3'
GUID = 'e6e50e4b-bf25-4ed6-a343-49f904e79f8f'
Author = 'Devolutions'
CompanyName = 'Devolutions'
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ dotnet tool run psign-tool -- --help
Create local dotnet tool packages from prebuilt release artifacts:

```powershell
pwsh ./nuget/pack-psign-dotnet-tool.ps1 -Version 0.6.2 -ArtifactsRoot ./dist -OutputDir ./dist/nuget
pwsh ./nuget/pack-psign-dotnet-tool.ps1 -Version 0.6.3 -ArtifactsRoot ./dist -OutputDir ./dist/nuget
```

The package is built from native `psign-tool` artifacts for `win-x64`, `win-arm64`, `linux-x64`, `linux-arm64`, `osx-x64`, and `osx-arm64`, plus an `any` fallback package for unsupported runtimes.
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-authenticode-trust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-authenticode-trust"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Portable Authenticode PKCS#7 trust verification (anchors, chain, EKU) using picky-rs"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-azure-kv-rest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-azure-kv-rest"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Azure Key Vault certificate metadata + keys/sign REST (portable, blocking HTTP)"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-codesigning-rest/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-codesigning-rest"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Azure Code Signing data-plane CertificateProfileOperations Sign LRO (portable, blocking HTTP)"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-digest-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-digest-cli"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Linux/macOS-friendly CLI over portable Authenticode SIP digests (psign-sip-digest)"
license.workspace = true
Expand Down
110 changes: 83 additions & 27 deletions crates/psign-digest-cli/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,8 @@ enum Command {
},
/// Attach an RFC3161 timestamp token to an existing embedded PE Authenticode signature.
///
/// Accepts either a raw `timeStampToken` `ContentInfo` DER file or a `TimeStampResp` DER file containing one.
/// Accepts a raw `timeStampToken` `ContentInfo` DER file, a `TimeStampResp` DER file containing one,
/// or posts a request to a TSA with `--rfc3161-url` and `--digest`.
TimestampPeRfc3161 {
/// Signed PE path to mutate.
#[arg(value_name = "PATH")]
Expand All @@ -2165,11 +2166,17 @@ enum Command {
#[arg(long, default_value_t = 0)]
signer_index: usize,
/// Raw RFC3161 timeStampToken ContentInfo DER.
#[arg(long, value_name = "PATH", conflicts_with = "response")]
#[arg(long, value_name = "PATH", conflicts_with_all = ["response", "rfc3161_url"])]
token: Option<PathBuf>,
/// RFC3161 TimeStampResp DER containing a granted timeStampToken.
#[arg(long, value_name = "PATH", conflicts_with = "token")]
#[arg(long, value_name = "PATH", conflicts_with_all = ["token", "rfc3161_url"])]
response: Option<PathBuf>,
/// RFC3161 TSA endpoint. Requires `--digest` and the `timestamp-http` feature.
#[arg(long, visible_alias = "tr", conflicts_with_all = ["token", "response"])]
rfc3161_url: Option<String>,
/// RFC3161 timestamp message-imprint digest. Required with `--rfc3161-url`.
#[arg(long, visible_alias = "td", value_enum, requires = "rfc3161_url")]
digest: Option<HashAlg>,
/// Output PE path.
#[arg(long, value_name = "PATH")]
output: PathBuf,
Expand Down Expand Up @@ -4783,14 +4790,34 @@ where
signer_index,
token,
response,
rfc3161_url,
digest,
output,
} => {
let pe = std::fs::read(&path).with_context(|| format!("read {}", path.display()))?;
let token_der = match (token, response) {
(Some(token), None) => {
std::fs::read(&token).with_context(|| format!("read {}", token.display()))?
let pkcs7_der = verify_pe::pe_nth_pkcs7_signed_data_der(&pe, index)
.with_context(|| format!("extract PE PKCS#7 row {index} from {}", path.display()))?;
let stamped_pkcs7 = match (token, response, rfc3161_url) {
(Some(token), None, None) => {
let token_der =
std::fs::read(&token).with_context(|| format!("read {}", token.display()))?;
let sd = pkcs7::parse_pkcs7_signed_data_der(&pkcs7_der).with_context(|| {
format!("parse PE PKCS#7 row {index} from {}", path.display())
})?;
let stamped = pkcs7::signed_data_add_rfc3161_timestamp_token(
&sd,
signer_index,
&token_der,
)
.with_context(|| {
format!(
"attach RFC3161 timestamp to {} row {index} signer {signer_index}",
path.display()
)
})?;
pkcs7::encode_pkcs7_content_info_signed_data_der(&stamped)?
}
(None, Some(response)) => {
(None, Some(response), None) => {
let bytes = std::fs::read(&response)
.with_context(|| format!("read {}", response.display()))?;
let parsed = parse_time_stamp_resp_der(&bytes).ok_or_else(|| {
Expand All @@ -4802,29 +4829,58 @@ where
parsed.pki_status.as_raw_integer()
));
}
parsed
let token_der = parsed
.time_stamp_token
.map(|t| t.to_vec())
.ok_or_else(|| anyhow!("TimeStampResp has no timeStampToken"))?
.ok_or_else(|| anyhow!("TimeStampResp has no timeStampToken"))?;
let sd = pkcs7::parse_pkcs7_signed_data_der(&pkcs7_der).with_context(|| {
format!("parse PE PKCS#7 row {index} from {}", path.display())
})?;
let stamped = pkcs7::signed_data_add_rfc3161_timestamp_token(
&sd,
signer_index,
token_der,
)
.with_context(|| {
format!(
"attach RFC3161 timestamp to {} row {index} signer {signer_index}",
path.display()
)
})?;
pkcs7::encode_pkcs7_content_info_signed_data_der(&stamped)?
}
(None, None, Some(url)) => {
if signer_index != 0 {
return Err(anyhow!(
"timestamp-pe-rfc3161 RFC3161 HTTP timestamping supports only signer_index 0"
));
}
let digest = digest.ok_or_else(|| {
anyhow!("timestamp-pe-rfc3161 requires --digest with --rfc3161-url")
})?;
#[cfg(feature = "timestamp-http")]
{
timestamp_pkcs7_der_rfc3161(
&pkcs7_der,
&url,
digest,
Rfc3161TimestampAttribute::MicrosoftAuthenticode,
)
.context("request and attach RFC3161 timestamp")?
}
#[cfg(not(feature = "timestamp-http"))]
{
let _ = (url, digest);
return Err(anyhow!(
"timestamp-pe-rfc3161 RFC3161 timestamping requires the timestamp-http feature"
));
}
}
_ => {
return Err(anyhow!(
"provide exactly one of --token, --response, or --rfc3161-url with --digest"
));
}
_ => return Err(anyhow!("provide exactly one of --token or --response")),
};
let pkcs7_der = verify_pe::pe_nth_pkcs7_signed_data_der(&pe, index)
.with_context(|| format!("extract PE PKCS#7 row {index} from {}", path.display()))?;
let sd = pkcs7::parse_pkcs7_signed_data_der(&pkcs7_der)
.with_context(|| format!("parse PE PKCS#7 row {index} from {}", path.display()))?;
let stamped = pkcs7::signed_data_add_rfc3161_timestamp_token(
&sd,
signer_index,
&token_der,
)
.with_context(|| {
format!(
"attach RFC3161 timestamp to {} row {index} signer {signer_index}",
path.display()
)
})?;
let stamped_pkcs7 = pkcs7::encode_pkcs7_content_info_signed_data_der(&stamped)?;
let out_image =
pe_embed::pe_replace_authenticode_pkcs7_certificate_at(pe, index, &stamped_pkcs7)
.with_context(|| {
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-opc-sign/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-opc-sign"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Portable OPC, VSIX, and NuGet package signing primitives"
license.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/psign-portable-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "psign-portable-core"
version = "0.6.2"
version = "0.6.3"
edition = "2024"
description = "Reusable portable Authenticode signing and inspection APIs for psign"
license.workspace = true
Expand Down
Loading