[core] add the HMAC-SHA1 shared secret signature method
This commit is contained in:
parent
6c7114d5ce
commit
5ba292521b
|
@ -49,6 +49,7 @@
|
|||
|
||||
#define RSA_SHA1 "RSA_SHA1"
|
||||
#define DSA_SHA1 "DSA_SHA1"
|
||||
#define HMAC_SHA1 "HMAC_SHA1"
|
||||
|
||||
/*****************************************************************************/
|
||||
/* public methods */
|
||||
|
@ -273,7 +274,7 @@ static xmlNode*
|
|||
get_xmlNode(LassoNode *node, gboolean lasso_dump)
|
||||
{
|
||||
LassoServer *server = LASSO_SERVER(node);
|
||||
char *signature_methods[] = { NULL, "RSA_SHA1", "DSA_SHA1"};
|
||||
char *signature_methods[] = { NULL, RSA_SHA1, DSA_SHA1, HMAC_SHA1};
|
||||
xmlNode *xmlnode = NULL, *ret_xmlnode = NULL;
|
||||
|
||||
xmlnode = parent_class->get_xmlNode(node, lasso_dump);
|
||||
|
@ -327,6 +328,8 @@ init_from_xml(LassoNode *node, xmlNode *xmlnode)
|
|||
server->signature_method = LASSO_SIGNATURE_METHOD_RSA_SHA1;
|
||||
else if (lasso_strisequal((char*) s, DSA_SHA1))
|
||||
server->signature_method = LASSO_SIGNATURE_METHOD_DSA_SHA1;
|
||||
else if (lasso_strisequal((char*) s, HMAC_SHA1))
|
||||
server->signature_method = LASSO_SIGNATURE_METHOD_HMAC_SHA1;
|
||||
else {
|
||||
warning("Unable to rebuild a LassoServer object from XML, bad SignatureMethod: %s",
|
||||
s);
|
||||
|
|
|
@ -264,6 +264,12 @@ void lasso_node_get_encryption(LassoNode *node, xmlSecKey **encryption_public_ke
|
|||
LassoEncryptionSymKeyType *encryption_sym_key_type);
|
||||
gboolean lasso_base64_decode(const char *from, char **buffer, int *buffer_len);
|
||||
|
||||
xmlSecKeyPtr
|
||||
lasso_create_hmac_key(const xmlSecByte * buf, xmlSecSize size);
|
||||
|
||||
lasso_error_t
|
||||
lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size);
|
||||
|
||||
LassoSignatureContext lasso_make_signature_context_from_buffer(const char *buffer, size_t length,
|
||||
const char *password, LassoSignatureMethod signature_method,
|
||||
const char *certificate);
|
||||
|
|
|
@ -479,6 +479,9 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
|||
char *new_query = NULL, *s_new_query = NULL;
|
||||
int status = 0;
|
||||
const xmlChar *algo_href = NULL;
|
||||
char *hmac_key;
|
||||
size_t hmac_key_length;
|
||||
const EVP_MD *md;
|
||||
xmlSecKey *key;
|
||||
xmlSecKeyData *key_data;
|
||||
unsigned int sigret_size = 0;
|
||||
|
@ -500,6 +503,9 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
|||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
algo_href = xmlSecHrefDsaSha1;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
algo_href = xmlSecHrefHmacSha1;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_NONE:
|
||||
case LASSO_SIGNATURE_METHOD_LAST:
|
||||
g_assert_not_reached();
|
||||
|
@ -531,6 +537,18 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
|||
/* alloc memory for sigret */
|
||||
sigret_size = DSA_size(dsa);
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
lasso_get_hmac_key(key, (void**)&hmac_key,
|
||||
&hmac_key_length);
|
||||
g_assert(hmac_key);
|
||||
md = EVP_sha1();
|
||||
sigret_size = EVP_MD_size(md);
|
||||
/* key should be at least 128 bits long */
|
||||
if (hmac_key_length < 16) {
|
||||
critical("HMAC key should be at least 128 bits long");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -546,6 +564,11 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
|||
status = DSA_sign(NID_sha1, (unsigned char*)digest, 20, sigret,
|
||||
&siglen, dsa);
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
HMAC(md, hmac_key, hmac_key_length, (unsigned char *)new_query,
|
||||
strlen(new_query), sigret, &siglen);
|
||||
status = 1;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_LAST:
|
||||
case LASSO_SIGNATURE_METHOD_NONE:
|
||||
g_assert_not_reached();
|
||||
|
@ -566,6 +589,7 @@ lasso_query_sign(char *query, LassoSignatureContext context)
|
|||
switch (sign_method) {
|
||||
case LASSO_SIGNATURE_METHOD_RSA_SHA1:
|
||||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
s_new_query = g_strdup_printf("%s&Signature=%s", new_query, (char*)
|
||||
e_b64_sigret);
|
||||
break;
|
||||
|
@ -613,6 +637,9 @@ lasso_query_verify_helper(const char *signed_content, const char *b64_signature,
|
|||
char *digest = NULL;
|
||||
xmlSecByte *signature = NULL;
|
||||
int key_size = 0;
|
||||
unsigned char *hmac_key = NULL;
|
||||
unsigned int hmac_key_length = 0;
|
||||
const EVP_MD *md = NULL;
|
||||
lasso_error_t rc = 0;
|
||||
LassoSignatureMethod method = LASSO_SIGNATURE_METHOD_NONE;
|
||||
|
||||
|
@ -627,6 +654,11 @@ lasso_query_verify_helper(const char *signed_content, const char *b64_signature,
|
|||
dsa = xmlSecOpenSSLKeyDataDsaGetDsa(key->value);
|
||||
key_size = DSA_size(dsa);
|
||||
method = LASSO_SIGNATURE_METHOD_DSA_SHA1;
|
||||
} else if (lasso_strisequal(algorithm, (char*)xmlSecHrefHmacSha1)) {
|
||||
lasso_check_good_rc(lasso_get_hmac_key(key, (void**)&hmac_key, &hmac_key_length));
|
||||
md = EVP_sha1();
|
||||
key_size = EVP_MD_size(md);
|
||||
method = LASSO_SIGNATURE_METHOD_HMAC_SHA1;
|
||||
} else {
|
||||
goto_cleanup_with_rc(LASSO_DS_ERROR_INVALID_SIGALG);
|
||||
}
|
||||
|
@ -665,6 +697,15 @@ lasso_query_verify_helper(const char *signed_content, const char *b64_signature,
|
|||
key_size, dsa) == 1,
|
||||
LASSO_DS_ERROR_INVALID_SIGNATURE);
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
digest = g_malloc(key_size);
|
||||
HMAC(md, hmac_key, hmac_key_length, (unsigned char*)signed_content,
|
||||
strlen(signed_content), (unsigned char*)digest, NULL);
|
||||
|
||||
goto_cleanup_if_fail_with_rc(lasso_crypto_memequal(digest, signature,
|
||||
key_size),
|
||||
LASSO_DS_ERROR_INVALID_SIGNATURE);
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_NONE:
|
||||
case LASSO_SIGNATURE_METHOD_LAST:
|
||||
g_assert_not_reached();
|
||||
|
@ -1164,6 +1205,7 @@ lasso_saml_constrain_dsigctxt(xmlSecDSigCtxPtr dsigCtx) {
|
|||
if((xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformInclC14NId) < 0) ||
|
||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformExclC14NId) < 0) ||
|
||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformSha1Id) < 0) ||
|
||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformHmacSha1Id) < 0) ||
|
||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformDsaSha1Id) < 0) ||
|
||||
(xmlSecDSigCtxEnableSignatureTransform(dsigCtx, xmlSecTransformRsaSha1Id) < 0)) {
|
||||
|
||||
|
@ -1181,6 +1223,7 @@ lasso_saml_constrain_dsigctxt(xmlSecDSigCtxPtr dsigCtx) {
|
|||
|
||||
/* Limit possible key info to X509, RSA and DSA */
|
||||
if((xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataX509Id) < 0) ||
|
||||
(xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataHmacId) < 0) ||
|
||||
(xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataRsaId) < 0) ||
|
||||
(xmlSecPtrListAdd(&(dsigCtx->keyInfoReadCtx.enabledKeyData), BAD_CAST xmlSecKeyDataDsaId) < 0)) {
|
||||
message(G_LOG_LEVEL_CRITICAL, "Error: failed to limit allowed key data");
|
||||
|
@ -1912,6 +1955,12 @@ _lasso_xmlsec_load_key_from_buffer(const char *buffer, size_t length, const char
|
|||
key_formats[i], password, NULL, NULL);
|
||||
}
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
private_key = xmlSecKeyReadMemory(xmlSecKeyDataHmacId, (xmlSecByte*)buffer, length);
|
||||
if (private_key) {
|
||||
xmlSecKeySetName(private_key, BAD_CAST "shared");
|
||||
}
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_LAST:
|
||||
case LASSO_SIGNATURE_METHOD_NONE:
|
||||
g_assert_not_reached();
|
||||
|
@ -2264,6 +2313,40 @@ lasso_log_remove_handler(guint handler_id)
|
|||
g_log_remove_handler(LASSO_LOG_DOMAIN, handler_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_get_hmac_key:
|
||||
* @key: an #xmlSecKey object
|
||||
* @buffer: a byte buffer of size @size
|
||||
* @size: the size of @buffer as bytes
|
||||
*
|
||||
* Extract the symetric HMAC key from the #xmlSecKey structure and place a pointer to i into the
|
||||
* buffer variable.
|
||||
*
|
||||
* Return value: 0 if successful, an error code otherwise.
|
||||
*/
|
||||
lasso_error_t
|
||||
lasso_get_hmac_key(const xmlSecKey *key, void **buffer, size_t *size)
|
||||
{
|
||||
xmlSecKeyDataPtr key_data;
|
||||
xmlSecBufferPtr key_data_buffer;
|
||||
|
||||
lasso_null_param(key);
|
||||
lasso_null_param(buffer);
|
||||
lasso_null_param(size);
|
||||
|
||||
if (key->value->id != xmlSecKeyDataHmacId) {
|
||||
return LASSO_PARAM_ERROR_INVALID_VALUE;
|
||||
}
|
||||
key_data = xmlSecKeyGetValue((xmlSecKeyPtr)key);
|
||||
g_return_val_if_fail(key_data, LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
key_data_buffer = xmlSecKeyDataBinaryValueGetBuffer(key_data);
|
||||
g_return_val_if_fail(key_data_buffer, LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
*buffer = xmlSecBufferGetData(key_data_buffer);
|
||||
*size = xmlSecBufferGetSize(key_data_buffer);
|
||||
g_return_val_if_fail(*buffer && *size, LASSO_PARAM_ERROR_INVALID_VALUE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lasso_make_signature_context_from_buffer:
|
||||
* @buffer: a byte buffer of size @length
|
||||
|
|
|
@ -2758,6 +2758,9 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
|
|||
case LASSO_SIGNATURE_METHOD_DSA_SHA1:
|
||||
transform_id = xmlSecTransformDsaSha1Id;
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
transform_id = xmlSecTransformHmacSha1Id;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
@ -2789,6 +2792,13 @@ lasso_node_add_signature_template(LassoNode *node, xmlNode *xmlnode,
|
|||
xmlSecTmplKeyInfoAddKeyValue(key_info);
|
||||
}
|
||||
break;
|
||||
case LASSO_SIGNATURE_METHOD_HMAC_SHA1:
|
||||
if (context.signature_key->name) {
|
||||
key_info = xmlSecTmplSignatureEnsureKeyInfo(signature, NULL);
|
||||
xmlSecTmplKeyInfoAddKeyName(key_info, NULL);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ typedef enum {
|
|||
* LassoSignatureMethod:
|
||||
* @LASSO_SIGNATURE_METHOD_RSA_SHA1: sign using a RSA private key
|
||||
* @LASSO_SIGNATURE_METHOD_DSA_SHA1: sign using a DSA private key
|
||||
* @LASSO_SIGNATURE_METHOD_HMAC_SHA1: sign using a an HMAC-SHA1 secret key
|
||||
*
|
||||
* Signature method.
|
||||
**/
|
||||
|
@ -100,6 +101,7 @@ typedef enum {
|
|||
LASSO_SIGNATURE_METHOD_NONE = 0,
|
||||
LASSO_SIGNATURE_METHOD_RSA_SHA1,
|
||||
LASSO_SIGNATURE_METHOD_DSA_SHA1,
|
||||
LASSO_SIGNATURE_METHOD_HMAC_SHA1,
|
||||
LASSO_SIGNATURE_METHOD_LAST
|
||||
} LassoSignatureMethod;
|
||||
|
||||
|
|
|
@ -900,6 +900,103 @@ START_TEST(test06_sso_sp_with_key_rollover)
|
|||
}
|
||||
END_TEST
|
||||
|
||||
#define test07_make_context(ctx, server_prefix, provider_role, provider_prefix, key) \
|
||||
ctx = lasso_server_new( \
|
||||
TESTSDATADIR server_prefix "/metadata.xml", \
|
||||
NULL, \
|
||||
NULL, /* Secret key to unlock private key */ \
|
||||
NULL); \
|
||||
check_not_null(ctx); \
|
||||
check_good_rc(lasso_server_add_provider( \
|
||||
ctx, \
|
||||
provider_role, \
|
||||
TESTSDATADIR provider_prefix "/metadata.xml", \
|
||||
NULL, \
|
||||
NULL)); \
|
||||
providers = g_hash_table_get_values(ctx->providers); \
|
||||
check_not_null(providers); \
|
||||
lasso_provider_set_specific_signing_key(LASSO_PROVIDER(providers->data), \
|
||||
key); \
|
||||
lasso_provider_add_key(LASSO_PROVIDER(providers->data), key, FALSE); \
|
||||
g_list_free(providers);
|
||||
|
||||
static void
|
||||
sso_initiated_by_sp(LassoServer *idp_context, LassoServer *sp_context)
|
||||
{
|
||||
LassoLogin *idp_login_context;
|
||||
LassoLogin *sp_login_context;
|
||||
char *authn_request_query;
|
||||
|
||||
check_not_null(idp_login_context = lasso_login_new(idp_context));
|
||||
check_not_null(sp_login_context = lasso_login_new(sp_context))
|
||||
|
||||
/* Create response */
|
||||
check_good_rc(lasso_login_init_authn_request(sp_login_context, NULL, LASSO_HTTP_METHOD_REDIRECT));
|
||||
|
||||
lasso_assign_string(LASSO_SAMLP2_AUTHN_REQUEST(sp_login_context->parent.request)->ProtocolBinding,
|
||||
LASSO_SAML2_METADATA_BINDING_POST);
|
||||
lasso_assign_string(LASSO_SAMLP2_AUTHN_REQUEST(sp_login_context->parent.request)->NameIDPolicy->Format,
|
||||
LASSO_SAML2_NAME_IDENTIFIER_FORMAT_PERSISTENT);
|
||||
LASSO_SAMLP2_AUTHN_REQUEST(sp_login_context->parent.request)->NameIDPolicy->AllowCreate = 1;
|
||||
check_good_rc(lasso_login_build_authn_request_msg(sp_login_context));
|
||||
check_not_null(sp_login_context->parent.msg_url);
|
||||
printf("authn_request: %s", sp_login_context->parent.msg_url);
|
||||
authn_request_query = strchr(sp_login_context->parent.msg_url, '?');
|
||||
check_not_null(authn_request_query);
|
||||
authn_request_query += 1;
|
||||
check_good_rc(lasso_login_process_authn_request_msg(idp_login_context, authn_request_query));
|
||||
|
||||
check_good_rc(lasso_login_validate_request_msg(idp_login_context,
|
||||
1, /* authentication_result */
|
||||
0 /* is_consent_obtained */
|
||||
));
|
||||
|
||||
check_good_rc(lasso_login_build_assertion(idp_login_context,
|
||||
LASSO_SAML_AUTHENTICATION_METHOD_PASSWORD,
|
||||
"FIXME: authenticationInstant",
|
||||
"FIXME: reauthenticateOnOrAfter",
|
||||
"FIXME: notBefore",
|
||||
"FIXME: notOnOrAfter"));
|
||||
check_good_rc(lasso_login_build_authn_response_msg(idp_login_context));
|
||||
check_not_null(idp_login_context->parent.msg_body);
|
||||
check_not_null(idp_login_context->parent.msg_url);
|
||||
printf("Xml Response: %s\n", lasso_node_export_to_xml(idp_login_context->parent.response));
|
||||
|
||||
/* Process response */
|
||||
check_good_rc(lasso_login_process_authn_response_msg(sp_login_context,
|
||||
idp_login_context->parent.msg_body));
|
||||
check_good_rc(lasso_login_accept_sso(sp_login_context));
|
||||
|
||||
/* Cleanup */
|
||||
lasso_release_gobject(idp_login_context);
|
||||
lasso_release_gobject(sp_login_context);
|
||||
}
|
||||
|
||||
START_TEST(test07_sso_sp_with_hmac_sha1_signatures)
|
||||
{
|
||||
LassoServer *idp_context = NULL;
|
||||
LassoServer *sp_context = NULL;
|
||||
GList *providers;
|
||||
LassoKey *key = NULL;
|
||||
|
||||
/* Create the shared key */
|
||||
key = lasso_key_new_for_signature_from_memory("xxxxxxxxxxxxxxxx", 16,
|
||||
NULL, LASSO_SIGNATURE_METHOD_HMAC_SHA1, NULL);
|
||||
check_true(LASSO_IS_KEY(key));
|
||||
|
||||
/* Create an IdP context for IdP initiated SSO with provider metadata 1 */
|
||||
test07_make_context(idp_context, "idp6-saml2", LASSO_PROVIDER_ROLE_SP, "sp6-saml2", key)
|
||||
test07_make_context(sp_context, "sp6-saml2", LASSO_PROVIDER_ROLE_IDP, "idp6-saml2", key)
|
||||
|
||||
sso_initiated_by_sp(idp_context, sp_context);
|
||||
|
||||
/* Cleanup */
|
||||
lasso_release_gobject(idp_context);
|
||||
lasso_release_gobject(sp_context);
|
||||
lasso_release_gobject(key);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite*
|
||||
login_saml2_suite()
|
||||
{
|
||||
|
@ -910,18 +1007,21 @@ login_saml2_suite()
|
|||
TCase *tc_spSloSoap = tcase_create("Login initiated by service provider without key loading and with SLO SOAP");
|
||||
TCase *tc_idpKeyRollover = tcase_create("Login initiated by idp, idp use two differents signing keys (simulate key roll-over)");
|
||||
TCase *tc_spKeyRollover = tcase_create("Login initiated by idp, sp use two differents encrypting keys (simulate key roll-over)");
|
||||
TCase *tc_hmacSignature = tcase_create("Login initiated by sp, using shared-key signature");
|
||||
suite_add_tcase(s, tc_generate);
|
||||
suite_add_tcase(s, tc_spLogin);
|
||||
suite_add_tcase(s, tc_spLoginMemory);
|
||||
suite_add_tcase(s, tc_spSloSoap);
|
||||
suite_add_tcase(s, tc_idpKeyRollover);
|
||||
suite_add_tcase(s, tc_spKeyRollover);
|
||||
suite_add_tcase(s, tc_hmacSignature);
|
||||
tcase_add_test(tc_generate, test01_saml2_generateServersContextDumps);
|
||||
tcase_add_test(tc_spLogin, test02_saml2_serviceProviderLogin);
|
||||
tcase_add_test(tc_spLoginMemory, test03_saml2_serviceProviderLogin);
|
||||
tcase_add_test(tc_spSloSoap, test04_sso_then_slo_soap);
|
||||
tcase_add_test(tc_idpKeyRollover, test05_sso_idp_with_key_rollover);
|
||||
tcase_add_test(tc_spKeyRollover, test06_sso_sp_with_key_rollover);
|
||||
tcase_add_test(tc_hmacSignature, test07_sso_sp_with_hmac_sha1_signatures);
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue