Change default key encryption padding algorithm to RSA-OAEP (#56023)

The key encryption padding algorithm is now configurable, the default
being changed to OAEP. It's possible to set the default through
./configure with:

    --with-default-key-encryption-method=[rsa-pkcs1|rsa-oaep]

at initialization time with an environment variable:

    LASSO_DEFAULT_KEY_ENCRYPTION_METHOD=[rsa-pkcs1|rsa-oaep]

or at runtime for a service provider:

    lasso_provider_set_key_encryption_method(LassoProvider *provider,
        LassoKeyEncryptionMethod key_encryption_method)

The setting is global for all encrypted nodes (Assertion or NameID).
This commit is contained in:
Benjamin Dauvergne 2021-09-03 07:48:35 +02:00
parent 1e718bd3aa
commit 53b0bd3569
15 changed files with 242 additions and 11 deletions

View File

@ -304,6 +304,58 @@ class LoginTestCase(unittest.TestCase):
idp_login.buildAssertion("None", "None", "None", "None", "None")
idp_login.buildAuthnResponseMsg()
def test08(self):
'''Verify KeyEncryptionMethod support'''
sp_server = server('sp5-saml2', lasso.PROVIDER_ROLE_IDP, 'idp5-saml2')
idp_server = server('idp5-saml2', lasso.PROVIDER_ROLE_SP, 'sp5-saml2')
def run(key_encryption_method=None):
sp_login = lasso.Login(sp_server)
sp_login.initAuthnRequest(None, lasso.HTTP_METHOD_REDIRECT)
sp_login.buildAuthnRequestMsg()
provider = idp_server.getProvider('http://sp5/metadata')
provider.setEncryptionMode(lasso.ENCRYPTION_MODE_ASSERTION)
if key_encryption_method:
provider.setKeyEncryptionMethod(key_encryption_method)
idp_login = lasso.Login(idp_server)
idp_login.processAuthnRequestMsg(sp_login.msgUrl.split('?')[1])
idp_login.protocolProfile = lasso.LOGIN_PROTOCOL_PROFILE_BRWS_POST
idp_login.validateRequestMsg(True, True)
idp_login.buildAssertion("None", "None", "None", "None", "None")
idp_login.buildAuthnResponseMsg()
sp_login.setSignatureVerifyHint(lasso.PROFILE_SIGNATURE_VERIFY_HINT_FORCE)
sp_login.processAuthnResponseMsg(idp_login.msgBody)
sp_login.acceptSso()
return sp_login.response.debug()
os.environ['LASSO_DEFAULT_KEY_ENCRYPTION_METHOD'] = 'rsa-pkcs1'
lasso.init()
assert 'xmlenc#rsa-1_5' in run()
assert 'xmlenc#rsa-oaep-mgf1p' not in run()
os.environ['LASSO_DEFAULT_KEY_ENCRYPTION_METHOD'] = 'rsa-oaep'
lasso.init()
assert 'xmlenc#rsa-1_5' not in run()
assert 'xmlenc#rsa-oaep-mgf1p' in run()
lasso.setDefaultKeyEncryptionMethod(lasso.KEY_ENCRYPTION_METHOD_PKCS1)
assert 'xmlenc#rsa-1_5' in run()
assert 'xmlenc#rsa-oaep-mgf1p' not in run()
lasso.setDefaultKeyEncryptionMethod(lasso.KEY_ENCRYPTION_METHOD_OAEP)
assert 'xmlenc#rsa-1_5' not in run()
assert 'xmlenc#rsa-oaep-mgf1p' in run()
assert 'xmlenc#rsa-1_5' in run(key_encryption_method=lasso.KEY_ENCRYPTION_METHOD_PKCS1)
assert 'xmlenc#rsa-oaep-mgf1p' not in run(key_encryption_method=lasso.KEY_ENCRYPTION_METHOD_PKCS1)
assert 'xmlenc#rsa-1_5' not in run(key_encryption_method=lasso.KEY_ENCRYPTION_METHOD_OAEP)
assert 'xmlenc#rsa-oaep-mgf1p' in run(key_encryption_method=lasso.KEY_ENCRYPTION_METHOD_OAEP)
class LogoutTestCase(unittest.TestCase):
def test01(self):

View File

@ -804,6 +804,24 @@ fi
AC_DEFINE_UNQUOTED(MIN_HASH_ALGO, "$MIN_HASH_ALGO", ["The minimal hash algorithm"])
AC_ARG_WITH([default-key-encryption-method],
[AS_HELP_STRING([--with-default-key-encryption-method=[rsa-pkcs1|rsa-oaep]],
[Default key encryption method (rsa-oaep)]
)
]
)
KEY_ENCRYPTION_METHOD=rsa-oaep
if test x"$with_default_" != x; then
if test ! "$with_default_key_encryption_method" = "rsa-pkcs1" -a ! "$with_default_key_encryption_method" = "rsa-oaep"; then
AC_MSG_ERROR("Default key encryption method must be either rsa-pkcs1 or rsa-oaep")
else
SIGNING_ALGO=$with_default_key_encryption_method
fi
fi
AC_DEFINE_UNQUOTED(DEFAULT_KEY_ENCRYPTION_METHOD, "$KEY_ENCRYPTION_METHOD", ["The default key encryption method"])
dnl ==========================================================================
dnl Pedantic compilation
@ -935,4 +953,5 @@ Crypto settings
---------------
Default signature: ${SIGNING_ALGO}
Minimal accepted hash: ${MIN_HASH_ALGO}
Key encryption method: ${KEY_ENCRYPTION_METHOD}
)

View File

@ -390,6 +390,7 @@ lasso_login_build_assertion(LassoLogin *login,
LASSO_NODE(ss->Subject->NameIdentifier),
lasso_provider_get_encryption_public_key(provider),
lasso_provider_get_encryption_sym_key_type(provider),
lasso_provider_get_key_encryption_method(provider),
provider->ProviderID));
if (encrypted_element != NULL) {
lasso_assign_new_gobject(ss->Subject->EncryptedNameIdentifier, encrypted_element);

View File

@ -903,6 +903,7 @@ instance_init(LassoProvider *provider)
provider->private_data->encryption_public_keys = NULL;
provider->private_data->encryption_mode = LASSO_ENCRYPTION_MODE_NONE;
provider->private_data->encryption_sym_key_type = LASSO_ENCRYPTION_SYM_KEY_TYPE_AES_128;
provider->private_data->key_encryption_method = LASSO_KEY_ENCRYPTION_METHOD_DEFAULT;
provider->private_data->signature_context = LASSO_SIGNATURE_CONTEXT_NONE;
/* no value_destroy_func since it shouldn't destroy the GList on insert */
@ -1535,6 +1536,43 @@ lasso_provider_get_encryption_sym_key_type(const LassoProvider *provider)
return LASSO_ENCRYPTION_SYM_KEY_TYPE_DEFAULT;
}
/**
* lasso_provider_set_key_encryption_method:
* @provider: provider to set encryption for
* @key_encryption_method: enum type for encrypting generated symetric key
*
* Set the type of the encryption of the generated encryption symetric key
**/
void
lasso_provider_set_key_encryption_method(LassoProvider *provider,
LassoKeyEncryptionMethod key_encryption_method)
{
g_return_if_fail(LASSO_IS_PROVIDER(provider));
if (key_encryption_method == LASSO_KEY_ENCRYPTION_METHOD_DEFAULT) {
key_encryption_method = lasso_get_default_key_encryption_method();
}
provider->private_data->key_encryption_method = key_encryption_method;;
}
/**
* lasso_provider_get_key_encryption_method:
* @provider: a #LassoProvider object
*
* Return the type of the encryption of the generated encryption symetric key
*
* Return value: a #LassoKeyEncryptionMethod value.
*/
LassoKeyEncryptionMethod
lasso_provider_get_key_encryption_method(const LassoProvider *provider)
{
if (LASSO_IS_PROVIDER(provider) && provider->private_data)
if (provider->private_data->key_encryption_method != LASSO_KEY_ENCRYPTION_METHOD_DEFAULT)
return provider->private_data->key_encryption_method;
return lasso_get_default_key_encryption_method();
}
/**
* lasso_provider_verify_query_signature:
* @provider: the #LassoProvider for the the provider issuing the query

View File

@ -281,6 +281,12 @@ LASSO_EXPORT lasso_error_t lasso_provider_add_key(LassoProvider *provider, Lasso
LASSO_EXPORT int lasso_provider_verify_signature(LassoProvider *provider,
const char *message, const char *id_attr_name, LassoMessageFormat format);
LASSO_EXPORT void lasso_provider_set_key_encryption_method(
LassoProvider *provider, LassoKeyEncryptionMethod method);
LASSO_EXPORT LassoKeyEncryptionMethod lasso_provider_get_key_encryption_method();
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -78,6 +78,7 @@ struct _LassoProviderPrivate
GList *encryption_public_keys;
LassoEncryptionMode encryption_mode;
LassoEncryptionSymKeyType encryption_sym_key_type;
LassoKeyEncryptionMethod key_encryption_method;
char *valid_until;
char *cache_duration;
GList *endpoints; /* of EndpointType_s */
@ -91,6 +92,7 @@ gboolean lasso_provider_load_public_key(LassoProvider *provider,
GList* lasso_provider_get_public_keys(const LassoProvider *provider);
xmlSecKey* lasso_provider_get_encryption_public_key(const LassoProvider *provider);
LassoEncryptionSymKeyType lasso_provider_get_encryption_sym_key_type(const LassoProvider* provider);
LassoKeyEncryptionMethod lasso_provider_get_key_encryption_method(const LassoProvider* provider);
int lasso_provider_verify_saml_signature(LassoProvider *provider, xmlNode *signed_node, xmlDoc *doc);
int lasso_provider_verify_query_signature(LassoProvider *provider, const char *message);
void _lasso_provider_load_key_descriptor(LassoProvider *provider, xmlNode *key_descriptor);

View File

@ -108,6 +108,8 @@ gboolean lasso_flag_pem_public_key = FALSE;
#define LASSO_FLAG_ENV_VAR "LASSO_FLAG"
#endif
#define LASSO_DEFAULT_KEY_ENCRYPTION_METHOD_ENV_VAR "LASSO_DEFAULT_KEY_ENCRYPTION_METHOD"
#if defined _MSC_VER
HINSTANCE g_hModule = NULL;
@ -187,6 +189,34 @@ set_min_allowed_hash_algo()
return rv;
}
static int
set_default_key_encryption_method()
{
char *env_encryption_sym_key_encryption_algo = getenv(LASSO_DEFAULT_KEY_ENCRYPTION_METHOD_ENV_VAR);
if (env_encryption_sym_key_encryption_algo) {
LassoKeyEncryptionMethod method = lasso_parse_key_encryption_method(
env_encryption_sym_key_encryption_algo);
if (method == -1) {
message(G_LOG_LEVEL_CRITICAL, "Unsupported key encryption "
"method %s configured in environment variable " LASSO_DEFAULT_KEY_ENCRYPTION_METHOD_ENV_VAR,
env_encryption_sym_key_encryption_algo);
return LASSO_ERROR_UNDEFINED;
}
lasso_set_default_key_encryption_method(method);
return 0;
}
LassoKeyEncryptionMethod method = lasso_parse_key_encryption_method(DEFAULT_KEY_ENCRYPTION_METHOD);
if (method != -1) {
lasso_set_default_key_encryption_method(method);
return 0;
} else {
message(G_LOG_LEVEL_CRITICAL, "Unsupported key encryption "
"method "DEFAULT_KEY_ENCRYPTION_METHOD" configured");
return LASSO_ERROR_UNDEFINED;
}
}
/**
* lasso_init:
*
@ -214,6 +244,9 @@ int lasso_init()
return LASSO_ERROR_UNDEFINED;
}
if (set_default_key_encryption_method() != 0) {
return LASSO_ERROR_UNDEFINED;
}
/* Init Lasso classes */
for (i=0; functions[i]; i++)

View File

@ -900,6 +900,7 @@ lasso_saml20_login_build_assertion(LassoLogin *login,
(LassoNode*)assertion->Subject->NameID,
lasso_provider_get_encryption_public_key(provider),
lasso_provider_get_encryption_sym_key_type(provider),
lasso_provider_get_key_encryption_method(provider),
provider->ProviderID);
goto_cleanup_if_fail_with_rc(assertion->Subject->EncryptedID != NULL,
LASSO_DS_ERROR_ENCRYPTION_FAILED);
@ -910,7 +911,8 @@ lasso_saml20_login_build_assertion(LassoLogin *login,
if (do_encrypt_assertion) {
lasso_node_set_encryption((LassoNode*)assertion,
lasso_provider_get_encryption_public_key(provider),
lasso_provider_get_encryption_sym_key_type(provider));
lasso_provider_get_encryption_sym_key_type(provider),
lasso_provider_get_key_encryption_method(provider));
}
response = LASSO_SAMLP2_RESPONSE(profile->response);

View File

@ -1684,6 +1684,7 @@ lasso_saml20_profile_setup_encrypted_node(LassoProvider *provider,
encrypted_node = (LassoNode*)lasso_node_encrypt(*node_to_encrypt,
lasso_provider_get_encryption_public_key(provider),
lasso_provider_get_encryption_sym_key_type(provider),
lasso_provider_get_key_encryption_method(provider),
provider->ProviderID);
if (! encrypted_node) {
return LASSO_DS_ERROR_ENCRYPTION_FAILED;

View File

@ -885,6 +885,7 @@ lasso_provider_saml2_node_encrypt(const LassoProvider *provider, LassoNode *lass
saml2_encrypted_element = lasso_node_encrypt(lasso_node,
lasso_provider_get_encryption_public_key(provider),
lasso_provider_get_encryption_sym_key_type(provider),
lasso_provider_get_key_encryption_method(provider),
provider->ProviderID);
return saml2_encrypted_element;

View File

@ -252,7 +252,10 @@ gboolean lasso_node_init_from_deflated_query_part(LassoNode *node, char *deflate
xmlNode* lasso_node_get_xmlnode_for_any_type(LassoNode *node, xmlNode *cur);
LassoSaml2EncryptedElement* lasso_node_encrypt(LassoNode *lasso_node,
xmlSecKey *encryption_public_key, LassoEncryptionSymKeyType encryption_sym_key_type, const char *recipient);
xmlSecKey *encryption_public_key,
LassoEncryptionSymKeyType encryption_sym_key_type,
LassoKeyEncryptionMethod key_encryption_method,
const char *recipient);
int lasso_node_decrypt_xmlnode(xmlNode* encrypted_element, GList *encrypted_key,
xmlSecKey *encryption_private_key, LassoNode **output);
@ -305,10 +308,12 @@ int lasso_node_set_signature(LassoNode *node, LassoSignatureContext context);
LassoSignatureContext lasso_node_get_signature(LassoNode *node);
void lasso_node_set_encryption(LassoNode *node, xmlSecKey *encryption_public_key,
LassoEncryptionSymKeyType encryption_sym_key_type);
LassoEncryptionSymKeyType encryption_sym_key_type,
LassoKeyEncryptionMethod key_encryption_method);
void lasso_node_get_encryption(LassoNode *node, xmlSecKey **encryption_public_key,
LassoEncryptionSymKeyType *encryption_sym_key_type);
LassoEncryptionSymKeyType *encryption_sym_key_type,
LassoKeyEncryptionMethod *key_encryption_method);
gboolean lasso_base64_decode(const char *from, char **buffer, int *buffer_len);
xmlSecKeyPtr

View File

@ -709,17 +709,18 @@ LassoNode*
lasso_assertion_encrypt(LassoSaml2Assertion *assertion, char *recipient)
{
xmlSecKey *encryption_public_key = NULL;
LassoEncryptionSymKeyType encryption_sym_key_type = 0;
LassoEncryptionSymKeyType encryption_sym_key_type;
LassoKeyEncryptionMethod key_encryption_method;
LassoNode *ret = NULL;
lasso_node_get_encryption((LassoNode*)assertion, &encryption_public_key,
&encryption_sym_key_type);
&encryption_sym_key_type, &key_encryption_method);
if (! encryption_public_key) {
return NULL;
}
ret = LASSO_NODE(lasso_node_encrypt(LASSO_NODE(assertion),
encryption_public_key, encryption_sym_key_type, recipient));
encryption_public_key, encryption_sym_key_type, key_encryption_method, recipient));
lasso_release_sec_key(encryption_public_key);
return ret;

View File

@ -83,6 +83,7 @@ static void lasso_node_remove_original_xmlnode(LassoNode *node, SnippetType type
static LassoSignatureMethod default_signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
static LassoSignatureMethod min_signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
static LassoKeyEncryptionMethod default_encryption_key_encryption_method = LASSO_KEY_ENCRYPTION_METHOD_OAEP;
/*****************************************************************************/
/* virtual public methods */
@ -472,7 +473,9 @@ lasso_node_export_to_soap_with_headers(LassoNode *node, GList *headers)
**/
LassoSaml2EncryptedElement*
lasso_node_encrypt(LassoNode *lasso_node, xmlSecKey *encryption_public_key,
LassoEncryptionSymKeyType encryption_sym_key_type, const char *recipient)
LassoEncryptionSymKeyType encryption_sym_key_type,
LassoKeyEncryptionMethod key_encryption_method,
const char *recipient)
{
xmlDocPtr doc = NULL;
xmlNodePtr orig_node = NULL;
@ -484,6 +487,7 @@ lasso_node_encrypt(LassoNode *lasso_node, xmlSecKey *encryption_public_key,
xmlNodePtr key_info_node2 = NULL;
xmlSecEncCtxPtr enc_ctx = NULL;
xmlSecTransformId xmlsec_encryption_sym_key_type;
xmlSecTransformId xmlsec_key_encryption_method;
xmlSecKey *duplicate = NULL;
if (encryption_public_key == NULL || !xmlSecKeyIsValid(encryption_public_key)) {
@ -510,6 +514,17 @@ lasso_node_encrypt(LassoNode *lasso_node, xmlSecKey *encryption_public_key,
break;
}
/* Get the symetric key encryption type */
switch(key_encryption_method) {
case LASSO_KEY_ENCRYPTION_METHOD_PKCS1:
xmlsec_key_encryption_method = xmlSecTransformRsaPkcs1Id;
break;
case LASSO_KEY_ENCRYPTION_METHOD_OAEP:
default:
xmlsec_key_encryption_method = xmlSecTransformRsaOaepId;
break;
}
/* Create encryption template for a specific symetric key type */
/* saml-core 2.2.4 line 498:
* The Type attribute SHOULD be present and, if present, MUST contain a value of
@ -560,7 +575,8 @@ lasso_node_encrypt(LassoNode *lasso_node, xmlSecKey *encryption_public_key,
/* add <enc:EncryptedKey/> to store the encrypted session key */
encrypted_key_node = xmlSecTmplKeyInfoAddEncryptedKey(key_info_node,
xmlSecTransformRsaPkcs1Id, NULL, NULL, (xmlChar*)recipient);
xmlsec_key_encryption_method,
NULL, NULL, (xmlChar*)recipient);
if (encrypted_key_node == NULL) {
message(G_LOG_LEVEL_WARNING, "Failed to add encrypted key");
goto cleanup;
@ -915,6 +931,7 @@ struct _CustomElement {
LassoSignatureContext signature_context;
xmlSecKey *encryption_public_key;
LassoEncryptionSymKeyType encryption_sym_key_type;
LassoKeyEncryptionMethod key_encryption_method;
};
static struct _CustomElement *
@ -1061,7 +1078,8 @@ lasso_node_get_signature(LassoNode *node)
*/
void
lasso_node_set_encryption(LassoNode *node, xmlSecKey *encryption_public_key,
LassoEncryptionSymKeyType encryption_sym_key_type)
LassoEncryptionSymKeyType encryption_sym_key_type,
LassoKeyEncryptionMethod key_encryption_method)
{
struct _CustomElement *custom_element;
@ -1086,6 +1104,12 @@ lasso_node_set_encryption(LassoNode *node, xmlSecKey *encryption_public_key,
} else {
custom_element->encryption_sym_key_type = LASSO_ENCRYPTION_SYM_KEY_TYPE_DEFAULT;
}
if (LASSO_KEY_ENCRYPTION_METHOD_DEFAULT < key_encryption_method
&& key_encryption_method < LASSO_KEY_ENCRYPTION_METHOD_LAST) {
custom_element->key_encryption_method = key_encryption_method;
} else {
custom_element->key_encryption_method = lasso_get_default_key_encryption_method();
}
}
/**
@ -1099,7 +1123,8 @@ lasso_node_set_encryption(LassoNode *node, xmlSecKey *encryption_public_key,
*/
void
lasso_node_get_encryption(LassoNode *node, xmlSecKey **encryption_public_key,
LassoEncryptionSymKeyType *encryption_sym_key_type)
LassoEncryptionSymKeyType *encryption_sym_key_type,
LassoKeyEncryptionMethod *key_encryption_method)
{
struct _CustomElement *custom_element;
@ -1109,6 +1134,7 @@ lasso_node_get_encryption(LassoNode *node, xmlSecKey **encryption_public_key,
lasso_assign_sec_key(*encryption_public_key,
custom_element->encryption_public_key);
*encryption_sym_key_type = custom_element->encryption_sym_key_type;
*key_encryption_method = custom_element->key_encryption_method;
}
}
@ -3581,3 +3607,25 @@ void
lasso_set_min_signature_method(LassoSignatureMethod meth) {
min_signature_method = meth;
}
LassoKeyEncryptionMethod
lasso_parse_key_encryption_method(char *str) {
if (lasso_strisequal(str, "rsa-pkcs1")) {
return LASSO_KEY_ENCRYPTION_METHOD_PKCS1;
} else if (lasso_strisequal(str, "rsa-oaep")) {
return LASSO_KEY_ENCRYPTION_METHOD_OAEP;
}
return LASSO_KEY_ENCRYPTION_METHOD_INVALID;
}
LassoKeyEncryptionMethod
lasso_get_default_key_encryption_method() {
return default_encryption_key_encryption_method;
}
void
lasso_set_default_key_encryption_method(LassoKeyEncryptionMethod method)
{
default_encryption_key_encryption_method = method;
}

View File

@ -40,6 +40,7 @@ extern "C" {
#include "../export.h"
#include "../errors.h"
#include "strings.h"
#include "xml_enc.h"
#define LASSO_TYPE_NODE (lasso_node_get_type())
#define LASSO_NODE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), LASSO_TYPE_NODE, LassoNode))
@ -235,6 +236,12 @@ struct _LassoKey;
LASSO_EXPORT char* lasso_node_export_to_saml2_query(LassoNode *node, const char *param_name, const
char *url, struct _LassoKey *key);
LASSO_EXPORT LassoKeyEncryptionMethod lasso_parse_key_encryption_method(char *str);
LASSO_EXPORT LassoKeyEncryptionMethod lasso_get_default_key_encryption_method();
LASSO_EXPORT void lasso_set_default_key_encryption_method(LassoKeyEncryptionMethod method);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -49,6 +49,21 @@ typedef enum {
LASSO_ENCRYTPION_SYM_KEY_TYPE_LAST
} LassoEncryptionSymKeyType;
/**
* LassoKeyEncryptionMethod:
* @LASSO_KEY_ENCRYPTION_METHOD_PKCS1 : RSA PKCS1.5 padding
* @LASSO_KEY_ENCRYPTION_METHOD_OAEP : RSA OAEP padding
*
* Encryption symetric key encryption type.
**/
typedef enum {
LASSO_KEY_ENCRYPTION_METHOD_DEFAULT,
LASSO_KEY_ENCRYPTION_METHOD_PKCS1,
LASSO_KEY_ENCRYPTION_METHOD_OAEP,
LASSO_KEY_ENCRYPTION_METHOD_LAST,
LASSO_KEY_ENCRYPTION_METHOD_INVALID = -1
} LassoKeyEncryptionMethod;
#ifdef __cplusplus
}
#endif /* __cplusplus */