in aws_signing_helper/pkcs11_signer.go [318:429]
func getMatchingCerts(module *pkcs11.Ctx, slots []SlotIdInfo, uri *pkcs11uri.Pkcs11URI, userPin string, single bool) (matchedSlot SlotIdInfo, session pkcs11.SessionHandle, loggedIn bool, matchingCerts []CertObjInfo, err error) {
var (
errNoMatchingCerts error
)
errNoMatchingCerts = errors.New("no matching certificates")
if uri != nil {
slots = matchSlots(slots, uri)
}
// http://david.woodhou.se/draft-woodhouse-cert-best-practice.html#rfc.section.8.1
//
// "For locating certificates, applications first iterate over the
// available tokens without logging in to them. In each token which
// matches the provided PKCS#11 URI, a search is performed for
// matching certificate objects."
for _, slot := range slots {
curSession, err := module.OpenSession(slot.id, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKS_RO_PUBLIC_SESSION)
if err != nil {
if Debug {
log.Printf("unable to open session in slot %d"+
" (%s)\n", slot.id, err)
}
module.CloseSession(curSession)
continue
}
curMatchingCerts, err := getCertsInSession(module, slot.id, curSession, uri)
if err == nil && len(curMatchingCerts) > 0 {
matchingCerts = append(matchingCerts, curMatchingCerts...)
// We only care about this value when there is a single matching
// certificate found.
if matchedSlot == (SlotIdInfo{}) {
matchedSlot = slot
session = curSession
goto skipCloseSession
}
}
module.CloseSession(curSession)
skipCloseSession:
}
if len(matchingCerts) >= 1 {
goto foundCert
}
// http://david.woodhou.se/draft-woodhouse-cert-best-practice.html#rfc.section.8.1
//
// "If no match is found, and precisely one token was matched by the
// specified URI, then the application attempts to log in to that
// token using a PIN [...]. Another search is performed for matching
// objects, which this time will return even any certificate objects
// with the CKA_PRIVATE attribute. Is it important to note that the
// login should only be attempted if there is precisely one token
// which matches the URI, and not if there are multiple possible
// tokens in which the object could reside."
if len(slots) == 1 {
if userPin != "" {
curSession, err := module.OpenSession(slots[0].id, pkcs11.CKF_SERIAL_SESSION|pkcs11.CKS_RO_PUBLIC_SESSION)
if err != nil {
err = errNoMatchingCerts
goto fail
}
err = module.Login(curSession, pkcs11.CKU_USER, userPin)
if err != nil {
err = errNoMatchingCerts
goto fail
}
curMatchingCerts, err := getCertsInSession(module, slots[0].id, curSession, uri)
if err == nil && len(curMatchingCerts) > 0 {
matchingCerts = append(matchingCerts, curMatchingCerts...)
// We only care about this value when there is a single matching
// certificate found.
if session == 0 {
loggedIn = true
matchedSlot = slots[0]
session = curSession
goto foundCert
}
}
} else {
err = errors.New("one matching slot, but no user PIN provided")
goto fail
}
} else if len(slots) == 0 {
err = errors.New("no matching slots")
goto fail
} else {
err = errors.New("multiple matching slots")
goto fail
}
foundCert:
if single && len(matchingCerts) > 1 {
err = errors.New("multiple matching certificates")
goto fail
}
// Exactly one matching certificate after logging in to the appropriate token
// iff single is true (otherwise there can be multiple matching certificates).
return matchedSlot, session, loggedIn, matchingCerts, nil
fail:
if session != 0 {
module.Logout(session)
module.CloseSession(session)
}
return SlotIdInfo{}, session, false, nil, err
}