func signHelper()

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
}