in aws_signing_helper/pkcs11_signer.go [599:709]
func signHelper(module *pkcs11.Ctx, session pkcs11.SessionHandle, privateKeyObj KeyObjInfo, slot SlotIdInfo, userPin string, alwaysAuth uint, contextSpecificPin string, reusePin bool, keyType uint, digest []byte, hashFunc crypto.Hash) (_contextSpecificPin string, signature []byte, err error) {
// XXX: If you use this outside the context of IAM RA, be aware that
// you'll want to use something other than SHA256 in many cases.
// For TLSv1.3 the hash needs to precisely match the bit size of the
// curve, IIRC. And you'll need RSA-PSS too. You might find that
// ThalesIgnite/crypto11 has some of that.
// e.g. https://github.com/ThalesIgnite/crypto11/blob/master/rsa.go#L230
var (
mechanism uint
keyUri *pkcs11uri.Pkcs11URI
keyUriStr string
)
if keyType == pkcs11.CKK_EC {
switch hashFunc {
case crypto.SHA256:
hash := sha256.Sum256(digest)
digest = hash[:]
case crypto.SHA384:
hash := sha512.Sum384(digest)
digest = hash[:]
case crypto.SHA512:
hash := sha512.Sum512(digest)
digest = hash[:]
default:
return "", nil, ErrUnsupportedHash
}
mechanism = pkcs11.CKM_ECDSA
} else {
switch hashFunc {
case crypto.SHA256:
mechanism = pkcs11.CKM_SHA256_RSA_PKCS
case crypto.SHA384:
mechanism = pkcs11.CKM_SHA384_RSA_PKCS
case crypto.SHA512:
mechanism = pkcs11.CKM_SHA512_RSA_PKCS
default:
return "", nil, ErrUnsupportedHash
}
}
err = module.SignInit(session, []*pkcs11.Mechanism{pkcs11.NewMechanism(mechanism, nil)}, privateKeyObj.keyObject)
if err != nil {
return "", nil, fmt.Errorf("signing initiation failed (%s)", err.Error())
}
if alwaysAuth != 0 {
// Set the value for the context-specific PIN used to do the signing
// operation with this key. If the context-specific PIN wasn't specified
// in the input, and the "reuse PIN" option was set, try to use the
// user PIN as the context-specific PIN.
if contextSpecificPin == "" && userPin != "" && reusePin {
contextSpecificPin = userPin
}
if contextSpecificPin != "" {
err = module.Login(session, pkcs11.CKU_CONTEXT_SPECIFIC, contextSpecificPin)
if err == nil {
goto afterContextSpecificLogin
} else {
if Debug {
log.Printf("user re-authentication attempt failed (%s)\n", err.Error())
}
}
}
// If the context-specific PIN couldn't be derived, prompt the user for
// the context-specific PIN for this object.
keyUri = pkcs11uri.New()
keyUri.AddPathAttribute("model", slot.tokInfo.Model)
keyUri.AddPathAttribute("manufacturer", slot.tokInfo.ManufacturerID)
keyUri.AddPathAttribute("serial", slot.tokInfo.SerialNumber)
keyUri.AddPathAttribute("slot-description", slot.info.SlotDescription)
keyUri.AddPathAttribute("slot-manufacturer", slot.info.ManufacturerID)
if privateKeyObj.id != nil {
keyUri.AddPathAttribute("id", string(privateKeyObj.id[:]))
}
if privateKeyObj.label != nil {
keyUri.AddPathAttribute("object", string(privateKeyObj.label[:]))
}
keyUri.AddPathAttribute("type", "private")
keyUriStr, err = keyUri.Format() // nosemgrep
if err != nil {
keyUriStr = ""
}
passwordName := "context-specific PIN"
if keyUriStr != "" {
passwordName = fmt.Sprintf("context-specific PIN for private key object (%s)", keyUriStr)
}
finalAuthErrMsg := "user re-authentication failed (%s)"
contextSpecificPin, err = pkcs11PasswordPrompt(module, session, pkcs11.CKU_CONTEXT_SPECIFIC, passwordName, finalAuthErrMsg)
if err != nil {
return "", nil, err
}
}
afterContextSpecificLogin:
sig, err := module.Sign(session, digest)
if err != nil {
return contextSpecificPin, nil, fmt.Errorf("signing failed (%s)", err.Error())
}
// Yay, we have to do the ASN.1 encoding of the R, S values ourselves.
if mechanism == pkcs11.CKM_ECDSA {
sig, err = encodeEcdsaSigValue(sig)
if err != nil {
return contextSpecificPin, nil, err
}
}
return contextSpecificPin, sig, nil
}