in aws_signing_helper/cert_store_signer_windows.go [543:623]
func (signer *WindowsCertStoreSigner) cryptoSignHash(digest []byte, hash crypto.Hash) ([]byte, error) {
if len(digest) != hash.Size() {
return nil, errors.New("bad digest for hash")
}
// Figure out which CryptoAPI hash algorithm we're using
var hash_alg C.ALG_ID
switch hash {
case crypto.SHA1:
hash_alg = C.CALG_SHA1
case crypto.SHA256:
hash_alg = C.CALG_SHA_256
case crypto.SHA384:
hash_alg = C.CALG_SHA_384
case crypto.SHA512:
hash_alg = C.CALG_SHA_512
default:
return nil, ErrUnsupportedHash
}
// Instantiate a CryptoAPI hash object
var cryptoHash C.HCRYPTHASH
privateKey, _ := signer.getPrivateKey()
cspHandle := (*C.HCRYPTPROV)(unsafe.Pointer(&privateKey.cspHandle))
if ok := C.CryptCreateHash(*cspHandle, hash_alg, 0, 0, &cryptoHash); ok == WIN_FALSE {
if err := lastError("failed to create hash"); errCause(err) == errCode(NTE_BAD_ALGID) {
return nil, ErrUnsupportedHash
} else {
return nil, err
}
}
defer C.CryptDestroyHash(cryptoHash)
// Make sure the hash size matches
var (
hashSize C.DWORD
hashSizePtr = (*C.BYTE)(unsafe.Pointer(&hashSize))
hashSizeLen = C.DWORD(unsafe.Sizeof(hashSize))
)
if ok := C.CryptGetHashParam(cryptoHash, C.HP_HASHSIZE, hashSizePtr, &hashSizeLen, 0); ok == WIN_FALSE {
return nil, lastError("failed to get hash size")
}
if hash.Size() != int(hashSize) {
return nil, errors.New("invalid CryptoAPI hash")
}
// Put our digest into the hash object
digestPtr := (*C.BYTE)(unsafe.Pointer(&digest[0]))
if ok := C.CryptSetHashParam(cryptoHash, C.HP_HASHVAL, digestPtr, 0); ok == WIN_FALSE {
return nil, lastError("failed to set hash digest")
}
// Get signature length
var sigLen C.DWORD
if ok := C.CryptSignHash(cryptoHash, C.ulong(privateKey.keySpec), nil, 0, nil, &sigLen); ok == WIN_FALSE {
return nil, lastError("failed to get signature length")
}
// Get signature
var (
sig = make([]byte, int(sigLen))
sigPtr = (*C.BYTE)(unsafe.Pointer(&sig[0]))
)
if ok := C.CryptSignHash(cryptoHash, C.ulong(privateKey.keySpec), nil, 0, sigPtr, &sigLen); ok == WIN_FALSE {
return nil, lastError("failed to sign digest")
}
// Reversing signature since it is little endian, but we want big endian
for i := len(sig)/2 - 1; i >= 0; i-- {
opp := len(sig) - 1 - i
sig[i], sig[opp] = sig[opp], sig[i]
}
return sig, nil
}