in aws_signing_helper/cert_store_signer_windows.go [471:540]
func (signer *WindowsCertStoreSigner) cngSignHash(digest []byte, hash crypto.Hash) ([]byte, error) {
if len(digest) != hash.Size() {
return nil, errors.New("bad digest for hash")
}
var (
// Input
padPtr = unsafe.Pointer(nil)
digestPtr = (*C.BYTE)(&digest[0])
digestLen = C.DWORD(len(digest))
flags = C.DWORD(0)
// Output
sigLen = C.DWORD(0)
)
// Set up pkcs1v1.5 padding for RSA
privateKey, _ := signer.getPrivateKey()
if _, isRSA := privateKey.publicKey.(*rsa.PublicKey); isRSA {
flags |= C.BCRYPT_PAD_PKCS1
padInfo := C.BCRYPT_PKCS1_PADDING_INFO{}
padPtr = unsafe.Pointer(&padInfo)
switch hash {
case crypto.SHA1:
padInfo.pszAlgId = C.GET_BCRYPT_SHA1_ALGORITHM()
case crypto.SHA256:
padInfo.pszAlgId = C.GET_BCRYPT_SHA256_ALGORITHM()
case crypto.SHA384:
padInfo.pszAlgId = C.GET_BCRYPT_SHA384_ALGORITHM()
case crypto.SHA512:
padInfo.pszAlgId = C.GET_BCRYPT_SHA512_ALGORITHM()
default:
return nil, ErrUnsupportedHash
}
}
// Get C.NCRYPT_KEY_HANDLE in order to do the signature
cngKeyHandle := (*C.NCRYPT_KEY_HANDLE)(unsafe.Pointer(&privateKey.cngKeyHandle))
// Get signature length
if err := checkStatus(C.NCryptSignHash(*cngKeyHandle, padPtr, digestPtr, digestLen, nil, 0, &sigLen, flags)); err != nil {
return nil, fmt.Errorf("failed to get signature length: %w", err)
}
// Get signature
sig := make([]byte, sigLen)
sigPtr := (*C.BYTE)(&sig[0])
if err := checkStatus(C.NCryptSignHash(*cngKeyHandle, padPtr, digestPtr, digestLen, sigPtr, sigLen, &sigLen, flags|C.NCRYPT_SILENT_FLAG)); err != nil {
if err == ErrRequiresUI {
if err = checkStatus(C.NCryptSignHash(*cngKeyHandle, padPtr, digestPtr, digestLen, sigPtr, sigLen, &sigLen, flags)); err == nil {
goto got_signature
}
}
return nil, fmt.Errorf("failed to sign digest: %w", err)
}
got_signature:
// CNG returns a raw ECDSA signature, but we want ASN.1 DER encoding
if _, isEC := privateKey.publicKey.(*ecdsa.PublicKey); isEC {
if len(sig)%2 != 0 {
return nil, errors.New("bad ecdsa signature from CNG")
}
return encodeEcdsaSigValue(sig)
}
return sig, nil
}