func GetPKCS11Signer()

in aws_signing_helper/pkcs11_signer.go [1198:1328]


func GetPKCS11Signer(libPkcs11 string, cert *x509.Certificate, certChain []*x509.Certificate, privateKeyId string, certificateId string, reusePin bool) (signer Signer, signingAlgorithm string, err error) {
	var (
		module             *pkcs11.Ctx
		certObj            CertObjInfo
		session            pkcs11.SessionHandle
		loggedIn           bool
		keyType            uint
		contextSpecificPin string
		userPin            string
		alwaysAuth         uint
		certSlotNr         uint
		certUri            *pkcs11uri.Pkcs11URI
		keyUri             *pkcs11uri.Pkcs11URI
		slots              []SlotIdInfo
		certSlot           SlotIdInfo
		noKeyUri           bool
	)

	module, err = initializePKCS11Module(libPkcs11)
	if err != nil {
		goto fail
	}

	// If a PKCS#11 URI was provided for the certificate, find it.
	if cert == nil && certificateId != "" {
		certUri = pkcs11uri.New()
		err = certUri.Parse(certificateId)
		if err != nil {
			goto fail
		}
		userPin, _ = certUri.GetQueryAttribute("pin-value", false)
		certSlot, slots, session, loggedIn, certObj, err = getCertificate(module, certUri, userPin)
		if err != nil {
			goto fail
		}
		certSlotNr = certSlot.id
		cert = certObj.cert

		// So that hunting for the certificate can be more efficient in the future,
		// update the cert URI that has CKA_ID and CKA_VALUE appropriately set.
		crtAttributes := []*pkcs11.Attribute{
			pkcs11.NewAttribute(pkcs11.CKA_ID, 0),
		}
		crtAttributes, err = module.GetAttributeValue(session, certObj.certObject, crtAttributes)
		if err == nil {
			certUri.SetPathAttribute("id", escapeAll(crtAttributes[0].Value))
		}

		crtAttributes = []*pkcs11.Attribute{
			pkcs11.NewAttribute(pkcs11.CKA_LABEL, 0),
		}
		crtAttributes, err = module.GetAttributeValue(session, certObj.certObject, crtAttributes)
		if err == nil {
			certUri.SetPathAttribute("object", escapeAll(crtAttributes[0].Value))
		}

		if certChain == nil {
			certChain, err = getCertificateChain(module, session, cert)
			if err != nil {
				goto fail
			}
		}
	} else if cert != nil {
		// Populate certObj, so that it can be used to find the matching private key.
		certObj = CertObjInfo{nil, nil, cert, 0}
	}

	// If an explicit private-key option was given, use it. Otherwise
	// we look in the same place as the certificate URI as directed by
	// http://david.woodhou.se/draft-woodhouse-cert-best-practice.html#rfc.section.8.2
	if privateKeyId != "" {
		keyUri = pkcs11uri.New()
		err = keyUri.Parse(privateKeyId)
		if err != nil {
			goto fail
		}
	} else {
		certUriStr, _ := certUri.Format()
		keyUri = pkcs11uri.New()
		keyUri.Parse(certUriStr)
		noKeyUri = true
	}
	if _userPin, ok := keyUri.GetQueryAttribute("pin-value", false); ok {
		userPin = _userPin
	}

	// If the certificate's PKCS#11 URI wasn't provided, enumerate slots.
	if certificateId == "" {
		slots, err = enumerateSlotsInPKCS11Module(module)
		if err != nil {
			goto fail
		}
	}

	session, userPin, keyUri, keyType, _, _, alwaysAuth, contextSpecificPin, err = getPKCS11Key(module, session, loggedIn, certUri, keyUri, noKeyUri, certSlotNr, certObj, userPin, "", reusePin, slots)
	if err != nil {
		goto fail
	}

	switch keyType {
	case pkcs11.CKK_EC:
		signingAlgorithm = aws4_x509_ecdsa_sha256
	case pkcs11.CKK_RSA:
		signingAlgorithm = aws4_x509_rsa_sha256
	default:
		return nil, "", errors.New("unsupported algorithm")
	}

	if session != 0 {
		if loggedIn {
			module.Logout(session)
		}
		module.CloseSession(session)
	}

	return &PKCS11Signer{cert, certChain, module, userPin, alwaysAuth, contextSpecificPin, certUri, keyUri, reusePin}, signingAlgorithm, nil

fail:
	if module != nil {
		if session != 0 {
			if loggedIn {
				module.Logout(session)
			}
			module.CloseSession(session)
		}
		module.Finalize()
		module.Destroy()
	}

	return nil, "", err
}