YubiHSM Code-signing exporting certificate - windows

I followed the tutorial for generating a code-signing certificate using the YubiHSM Key Storage provider available here. After creating the Certificate Signing Request (CSR) with certreq -new sign.inf sign.req a new asymmetric key is created in the YubiHSM together with an association between this key and the certificate in the YubiHSM Key Storage Provider (KSP). After that, I am able to sign my binaries using something like signtool sign /sha1 <certificate hash> <binary name>.
However, when I export this certificate and import it to a different machine the certificate does not have an associated private key. Typing certutil -repairstore my <certificate hash> does not help. As far as I understand, the KSP only stores a link to the YubiHSM, not the actual private key itself. So I suppose I need to somehow create this association in the KSP.

I finally managed to solve the issue as follows:
After installing and configuring the YubiHSM KSP, install your exported certificate. After installing the certificate check its validity with:
certutil -verifystore my <certificate hash>
If you still cannot see the installed certificate try adding it manually using:
certutil -addstore -f "My" "MyCertificate.cer"
Once you can find the imported certificate, you need to manually bind the certificate to the private key. This is because the key is not stored with the certificate and Windows doesn’t automatically create an association between the two.
certutil -repairstore my <certificate hash>
Now you should be able to see the correct key label in the Key Container field using the certutil -verifystore command.
After that you should be able to start signing your binaries with signtool. However, I had to add the /sm flag to make it work.
signtool sign /sm /a /n "<CertificateName>" /fd sha256 path-to-binary-to-sign.exe

Related

Add intermediate certificates to signatures in signtool

I'm trying to sign an executable using Microsoft's signtool.exe
The private key lives in an HSM and can not be taken out. So, i had to get the "public" part of the certificate in a .cer file and used below command to sign
signtool.exe sign /v /f .\SigningCert.pem /csp "HSM Key Storage Provider" /k "KEYID" /tr http://timestamp.digicert.com /fd sha256 /td sha256 .\App.exe
Since the machine i used for signing did not have the intermediate certificate added to Windows trust store, the signed executable could not be verified.
SignTool Error: WinVerifyTrust returned error: 0x800B010A
A certificate chain could not be built to a trusted root authority.
That being said, I used below command to add the intermediate certificate using /ac switch
signtool.exe sign /v /f .\SigningCert.pem /csp "HSM Key Storage Provider" /k "KEYID" /ac .\Intermediate.pem /tr http://timestamp.digicert.com /fd sha256 /td sha256 .\App.exe
The executable could be verified properly. So far so good.
Now, if my certificate chain has more than one intermediate certs, how could i add them to signatures?
Example chain:
Leaf Cert -> Intermediate 1 -> Intermediate 2 -> Root Cert
I tried merging all the intermediate certs into a single pem file and using it with /ac switch. Apparently, Signtool takes only the first certificate from the pem file and ignores the rest.
Also, If i want to add cross certificates from Microsoft apart from my intermediate certificates, how would i add them?
As far as i read, I can put all the certs into a pfx file and use it with signtool. But, as i mentioned, i don't have access to the private key. I do not think building a pfx file is an option for me.

Invalid provider type specified error in code signing the vsto outlook application

I brought a code signing certificate from GoDaddy generated a .pfx file from it. But when I use this file to code sign the clickonce manifest of my outlook vsto application I get this error in visual studio
An error occurred while signing: Invalid provider type specified.
What could be the problem here?
Thanks.
The signing identity stored in the .pfx container are most likely older "Cryptographic Service Providers" (CSP) style. The environment you are using to sign your package looks like required "Cryptography API: Next Generation" (CNG) provider type. The solution would be to convert your existing container to use CNG Storage Provider. This should be done by the following steps ...
Import the PFX into your personal store
Export the public key from the store by going through export wizard
Export the private key using OpenSSL into .pem format
openssl.exe pkcs12 -in <original pfx file>.pfx -nocerts -out <pem file location>.pem
Convert to PVK
pvk.exe -in <pem file location>.pem -topvk -strong -out <pvk file location>.pvk
Merge the Public and Private keys
pvk2pfx.exe -pvk <pvk file location>.pvk -pi <pvk password> -spc <pvk file location>.cer -pfx <new pfx file location>.pfx -po <pfx password>
Now you can import the newly created pfx file into the Certificate Manager. Make sure you remove the old certificate first from the Certificate Manager. Once the certificate is in place you can use certutil again to validate if the certificate is now correct.
If it now shows the provider as "Microsoft Strong Cryptographic Provider" you know the operation has been successful.
The credits goes to Remy's Blog, where you may find the full explanation on the issue with examples and verification steps... Converting Certificate to use CSP Storage Provider in stead of CNG Storage Provider.

Unable to access key in HSM for sh256 signing but can for sha1 signing

How can I enable access to key in HSM when signing as sha256?
When I sign as sha1 sign tool properly pulls the cert key out of the HSM but if I change to "/fd sha256" the key can't be found within the container. I'm sure signtool can access the container, but some policy must be blocking this in the sha256 case.
My Error:
SignTool Error: The specified private key container was not found.
Sha256 command:
signtool.exe sign /f mycert.crt
/csp "Luna Cryptographic Services for Microsoft Windows"
/kc mycontainer /tr http://timestamp.digicert.com /td sha256
/fd sha256 signed-file.exe
Sha256 command, which works:
signtool.exe sign /f mycert.crt
/csp "Luna Cryptographic Services for Microsoft Windows"
/kc mycontainer /tr http://timestamp.digicert.com /td sha256
/fd sha1 signed-file.exe
/debug and /v options offer no additional information.
If I use makecert to generate a new self signed cert it the command generates a container which CSP can use for sha1 or sha256. Luna's CSP\keymap.exe tool allows me to manage containers and keys. I can create new ones for signing or exchange and then associate keys with them.
Generate Cert and upload kes to HSM
# Create Cert and store keys on HSM in a container called "noi1-501706key"
makecert -sk noi1-501706key -sp "Luna Cryptographic Services for Microsoft Windows" -r
-n "CN=noi1- 501706" -ss TestStore noi1-501706.cer
# make self signed
Cert2Spc noi1-501706.cer noi1-501706.spc
Use Program Files\Safenet\Luna Client\CSP\keymap
create new container
associate pub/private with new container
using new container sha1 works and sha256 fails. All attempts to view the two containers show them as identical.
Check the KeyContainer,public and private key objects labels (cmu.exe list or keymap.exe Browse Objects).Public and private key labels should be in following format:
Container name: ContainerName
Private key: S-ContainerName
Public key: S-ContainerName
Use cmu.exe setattribute to change the label.
According to the chapter 7 "Integrating Microsoft HCK (Windows Server 2012) with Luna HSM" I noticed the following which makes me think the creation of the CSR via an HSM tool on linux instead of makecert we are blocked from KSP/CNG.
So, we will never get Luna client to find the key for the cert. We need to either get a new cert or migrate to a new HSM and get a new cert. This is because AWS CloudHSM Classic uses hardware configured to block export of keys regardless of policy. No change to escrow the keys here.
In order to integrate the Luna SA Hardware Security Module with Microsoft HCK, the Luna CSP “Luna Cryptographic Services for Microsoft Windows” must be used to generate the certificate. The
certificate must be signed and the signer certificate must be present in the “Trusted Root Certificate Authority”. You can use the CA signed certificate of self-signed certificate both.

CertUtil importpfx Keyset does not exist

I have a p12 file, 'test.p12,' that has a certificate, the CA cert (self-signed), and private key for the certificate. The p12 file is generated using the BouncyCastle's C# API.
When trying to import the certificate by using 'CertUtil', i.e., 'CertUtil -f -p password -importpfx test.p12,' CertUtil generates the following error:
CertUtil: -importPFX command FAILED: 0x80090016 (-2146893802 NTE_BAD_KEYSET)
CertUtil: Keyset does not exist
Any clues as to what may be wrong? (I'm using Windows 10)
Using openssl, I can see that 'test.p12' does include the certificate, CA cert, and private key. The certificate is using an EC keypair, but I doubt that's a problem since I have a reference p12 file that uses the same algorithm and is imported by CertUtil without problem. Unfortunately, I have no detail on how the reference file is generated.
In my google searches, many seem to suggest that this may be a permission problem, but I doubt that's the case as I'm running the CertUtil as the Administrator.
When importing the same file using 'MMC' with the certificate snap-ins, the certificate is "successfully" imported if I force the MMC to store it in a specific store, e.g., Personal; otherwise, it prompts to select a Smart Card for the certificate. Could this be a related problem?
Thanks,
--Hyong

How to create PFX with my chain of certificates?

i'm applying a digital signature to my executable. Using signtool on Windows XP or Windows Vista:
>signtool.exe sign /f "avatar.pfx" MyApp.exe
automatically included the entire certification chain in the digital signature.
Starting with Windows 7 the entire certification chain is no longer included. You must manually include the certificate that:
signed your key
signed the certificate that signed your key
...
...until there are no more certificates to include
i am told that i have to do this using the /ac switch with the signtool utility.
From MSDN documentation of signtool:
/ac FileName
Specifies a file that contains an additional certificate to add to the signature block.
How do i get the filename of the certificate that signed my certificate?
It's more confusing because i don't have any such file. i have my digitally signed executable with no embedded certification chain:
Stackoverflow user davidcl had the same question. In this self-answered answer he says that i need to
do the signing using a PFX file that contains the root certificate, intermediate certificate, developer certificate, and private key.
After creating the appropriate PFX file - which was an odyssey in itself...
But he doesn't give how he created the PFX that contains the entire certification chain.
See also
How can I sign an ActiveX control with a code signing certificate and be a verified publisher?
Signing WinForms ClickOnce app with Certificate Chain
ClickOnce: Certificate cannot be validated
How to include entire certification path when signing code with signtool?
Install OpenSSL for Windows. Once accomplished, you have the openssl.exe executable somewhere on your system.
Now proceed as follows.
openssl pkcs12 -in avatar.pfx -out avatar.pem -nodes
(You need to enter the .pfx password here)
openssl pkcs12 -in avatar.pfx -out mycert.pem -nodes -clcerts
(again the PW)
openssl x509 -in mycert.pem -out mycert.cer -outform DER
Now open your Explorer and double-click on the mycert.cer. View the details and somewhere it will talk about an issuer. This is the company that issued your key store, your next goal is to get their intermediate certificates and the final root certificate. If you are lucky, there is an extension called "Authority Information Access" in your certificate that tells you where to get the issuing certificate directly. If you are not so lucky, then you will find a URL for OCSP access in the "Authority Information Access" or a URL for CRLs in the extension "CRL Distribution Points". These should at least give you a vague idea of the vendor's "homepage". In case of doubt, just google around, or ask me again :)
If you are on the vendor's page, you will have to watch out for "CA certificates" or "Intermediate Certificates". You need to download the one whose name is exactly the same as what you found in the "Issuer" field of your own certificate.
Now the funny part: The certificate you just found will again have an "Issuer" field. Lucky you if the issuer is the same company (typically the case for large CAs such as VeriSign), then you will find the corresponding certificate on the same site you are currently on. If not, repeat the previous steps.
Repeat this cumbersome procedure until you're at a point where you have found a certificate whose "Subject" field is exactly the same as its "Issuer" field. You're done then. This is a so-called "self-signed root certificate".
Most of these certificates will come in "DER"/"ASN.1"/"X.509" format - if you have the choice, download "PEM" format, otherwise you will first need to convert the certificates into "PEM" format by
openssl x509 -in cert.der -inform DER -out cert.pem
Once you have all the missing certificates in PEM format
open the initial file created in step 1, avatar.pem, in a text editor.
open the missing certificate PEM files in separate windows
copy the missing certificates (the entire file, including the "----- BEGIN CERTIFICATE -----" and "----- END CERTIFICATE -----") and append them to avatar.pem
save the result
issue
openssl pkcs12 -export -in avatar.pem -out newavatar.pfx -name ""
You will have to enter a new password that is to be used with the new file.
Minor addendum to Ian's comment above "In the end I had a much easier way to get a .cer...". These days when you export your code signing pfx from the Thawte webpage, you can specify that you want the entire chain included. Hence you can import the pfx with certmgr.msc and then export the single Thawte intermediate certificate as a codesign.cer file. Then use that with the signtool /ac switch. No need to have an old signed app. Be sure to delete your temp certificate in the store, so your test of the newly signed app is valid. --William Croft

Resources