- const Credential* KEK = metadataProvider.resolve(&criteria);
- if (!KEK)
- throw EncryptionException("No key encryption credential found.");
-
- // Try and find EncryptionMethod information surrounding the credential.
- const MetadataCredentialContext* metaCtx = dynamic_cast<const MetadataCredentialContext*>(KEK->getCredentalContext());
- if (metaCtx) {
- const vector<EncryptionMethod*> encMethods = metaCtx->getKeyDescriptor().getEncryptionMethods();
- if (!encMethods.empty())
- algorithm = encMethods.front()->getAlgorithm();
+ vector<const Credential*> creds;
+ if (metadataProvider.resolve(creds, &criteria) == 0)
+ throw EncryptionException("No peer encryption credential found.");
+
+ const XMLCh* dataalg;
+ const XMLCh* keyalg;
+ const Credential* KEK = nullptr;
+
+ for (vector<const Credential*>::const_iterator c = creds.begin(); !KEK && c != creds.end(); ++c) {
+ // Try and find EncryptionMethod information surrounding the credential.
+ // All we're doing if they're present is setting algorithms where possible to
+ // the algorithms preferred by the credential, if we support them.
+ // The problem is that if we don't support them, the only case we can detect
+ // is if neither algorithm type is set *and* there's an EncryptionMethod present.
+ dataalg = keyalg = nullptr;
+ const MetadataCredentialContext* metaCtx = dynamic_cast<const MetadataCredentialContext*>((*c)->getCredentalContext());
+ if (metaCtx) {
+ const vector<EncryptionMethod*>& encMethods = metaCtx->getKeyDescriptor().getEncryptionMethods();
+ for (vector<EncryptionMethod*>::const_iterator meth = encMethods.begin(); meth != encMethods.end(); ++meth) {
+ if ((*meth)->getAlgorithm()) {
+ if (!dataalg && conf.isXMLAlgorithmSupported((*meth)->getAlgorithm(), XMLToolingConfig::ALGTYPE_ENCRYPT))
+ dataalg = (*meth)->getAlgorithm();
+ else if (!keyalg && conf.isXMLAlgorithmSupported((*meth)->getAlgorithm(), XMLToolingConfig::ALGTYPE_KEYENCRYPT))
+ keyalg = (*meth)->getAlgorithm();
+ }
+ }
+
+ if (!dataalg && !keyalg && !encMethods.empty()) {
+ // We know nothing, and something was specified that we don't support, so keep looking.
+ continue;
+ }
+ }
+
+ if (!keyalg && !(keyalg = Encrypter::getKeyTransportAlgorithm(*(*c), algorithm ? algorithm : dataalg))) {
+ // We can't derive a supported algorithm from the credential, so it will fail later anyway.
+ continue;
+ }
+
+ // Use this key.
+ KEK = *c;