ebourg / jsign

Java implementation of Microsoft Authenticode for signing Windows executables, installers & scripts
https://ebourg.github.io/jsign
Apache License 2.0
259 stars 108 forks source link

Support for token synchronization #107

Open MushyMiddle opened 2 years ago

MushyMiddle commented 2 years ago

This may be an enhancement request, or possibly just a rant about the truly junk driver supplied for SafeNet tokens. Our build environment currently uses a variety of tools, including jsign 2.0 and osslsigncode. I'd like to move to just jsign 4, which seems feasible. We use osslsigncode just for MSI files, so that's no longer needed with jsign (yay!).

One problem we have is instability having to do with, as mentioned, the junk driver supplied with SafeNet tokens. It has two issues that I've experienced:

  1. Once the token is used for signing and then closed, there is a period (measured in many MS to a second+) where the token is unavailable, and any attempt to open it during this period will fail.
  2. If more than one signing request is made at the same time, one or both requests will fail - in other words, the token driver does not serialize/synchronize access to the token (!).

These two issues happen regardless of the tool used. GlobalSign made a poor choice of token vendors when they went with SafeNet, frankly - their drivers are really designed for logins, not for code signing. I've tried getting SafeNet to address these issues, but they're not interested. (The SafeNet drivers also drag-in large parts of X11 - not something I really want on a build server, but I'm sure their monolithic driver for logins needs X11).

Both issues are (mostly) solvable externally by using a mutex (# 2) and artificially delaying requests or retrying (# 1). That is, as long as nothing else outside of the build process tries to use the token. For the ant part of our build, e.g., we use sem (this part never runs in conjunction with jsign, but uses osslsigncode).

That said, I only have direct experience with SafeNet tokens. I don't know how widespread these synchronization issues are with other vendors' tokens, but with any automated build environment using tokens, something is going to need to at least synchronize access to individual tokens, I'd think.

I wonder if there is enough general need for some level of built-in support to warrant changes to jsign. Obviously, in a mixed environment with multiple tools, either the driver needs to handle this, or some external process needs to, but with jsign gaining more and more support for file types, the need for other tools should be reduced.

Thus, it might be worth jsign having a per-token (or slot) mutex, at least. I don't think I'd similarly suggest that jsign also do some kind of kludgy inter-signing delay, but to the degree that it makes sense, perhaps built-in retries on open, if there isn't already some kind of support for handling token access issues in the the PKCS#11 stack.

I'm happy to supply more details and/or do some further testing/diagnosis. I've been dealing with these issues for several years, and while I have a semi-viable workaround, it would be nice if I didn't have to do quite as much to make signing with tokens stable.

ebourg commented 2 years ago

I don't have a SafeNet token so I'm unable to reproduce this unfortunately. This looks clearly like a driver bug, the best I could do at the Jsgin level is a retry mechanism on the signing operation (similar to the retry on the timestamping).

Could you paste the exception thrown when the token is unavailable (with Jsign 4.0 preferably) ?

ebourg commented 1 year ago

@MushyMiddle if you are still around, do you think you could post a stacktrace of the exception thrown?

ebourg commented 1 year ago

If Jenkins is used as a build server, it may be possible to work around this issue by using a lockable resource such that only one build job at a time can access the token.