ikev2: Move code in pubkey authenticator's build() method into separate functions

This commit is contained in:
Tobias Brunner 2015-03-09 14:50:34 +01:00
parent 03a340c6c6
commit 708dff0700
1 changed files with 123 additions and 85 deletions

View File

@ -197,108 +197,153 @@ static array_t *select_signature_schemes(keymat_v2_t *keymat,
return selected;
}
/**
* Create a signature using RFC 7427 signature authentication
*/
static status_t sign_signature_auth(private_pubkey_authenticator_t *this,
auth_cfg_t *auth, private_key_t *private,
identification_t *id, chunk_t *auth_data)
{
enumerator_t *enumerator;
keymat_v2_t *keymat;
signature_scheme_t scheme = SIGN_UNKNOWN, *schemep;
array_t *schemes;
chunk_t octets = chunk_empty;
status_t status = FAILED;
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
schemes = select_signature_schemes(keymat, auth, private);
if (!array_count(schemes))
{
DBG1(DBG_IKE, "no common hash algorithm found to create signature "
"with %N key", key_type_names, private->get_type(private));
array_destroy(schemes);
return FAILED;
}
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, id, this->reserved, &octets))
{
enumerator = array_create_enumerator(schemes);
while (enumerator->enumerate(enumerator, &schemep))
{
scheme = *schemep;
if (private->sign(private, scheme, octets, auth_data) &&
build_signature_auth_data(auth_data, scheme))
{
status = SUCCESS;
break;
}
else
{
DBG2(DBG_IKE, "unable to create %N signature for %N key",
signature_scheme_names, scheme, key_type_names,
private->get_type(private));
}
}
enumerator->destroy(enumerator);
}
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
signature_scheme_names, scheme,
status == SUCCESS ? "successful" : "failed");
array_destroy(schemes);
chunk_free(&octets);
return status;
}
/**
* Create a classic IKEv2 signature
*/
static status_t sign_classic(private_pubkey_authenticator_t *this,
auth_cfg_t *auth, private_key_t *private,
identification_t *id, auth_method_t *auth_method,
chunk_t *auth_data)
{
signature_scheme_t scheme;
keymat_v2_t *keymat;
chunk_t octets = chunk_empty;
status_t status = FAILED;
switch (private->get_type(private))
{
case KEY_RSA:
scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
*auth_method = AUTH_RSA;
break;
case KEY_ECDSA:
/* deduct the signature scheme from the keysize */
switch (private->get_keysize(private))
{
case 256:
scheme = SIGN_ECDSA_256;
*auth_method = AUTH_ECDSA_256;
break;
case 384:
scheme = SIGN_ECDSA_384;
*auth_method = AUTH_ECDSA_384;
break;
case 521:
scheme = SIGN_ECDSA_521;
*auth_method = AUTH_ECDSA_521;
break;
default:
DBG1(DBG_IKE, "%d bit ECDSA private key size not supported",
private->get_keysize(private));
return FAILED;
}
break;
default:
DBG1(DBG_IKE, "private key of type %N not supported",
key_type_names, private->get_type(private));
return FAILED;
}
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, id, this->reserved, &octets) &&
private->sign(private, scheme, octets, auth_data))
{
status = SUCCESS;
}
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
auth_method_names, *auth_method,
status == SUCCESS ? "successful" : "failed");
chunk_free(&octets);
return status;
}
METHOD(authenticator_t, build, status_t,
private_pubkey_authenticator_t *this, message_t *message)
{
enumerator_t *enumerator;
chunk_t octets = chunk_empty, auth_data;
status_t status = FAILED;
private_key_t *private;
identification_t *id;
auth_cfg_t *auth;
chunk_t auth_data;
status_t status;
auth_payload_t *auth_payload;
auth_method_t auth_method;
signature_scheme_t scheme = SIGN_UNKNOWN, *schemep;
keymat_v2_t *keymat;
array_t *schemes;
id = this->ike_sa->get_my_id(this->ike_sa);
auth = this->ike_sa->get_auth_cfg(this->ike_sa, TRUE);
private = lib->credmgr->get_private(lib->credmgr, KEY_ANY, id, auth);
if (private == NULL)
if (!private)
{
DBG1(DBG_IKE, "no private key found for '%Y'", id);
return NOT_FOUND;
}
keymat = (keymat_v2_t*)this->ike_sa->get_keymat(this->ike_sa);
if (this->ike_sa->supports_extension(this->ike_sa, EXT_SIGNATURE_AUTH))
{
schemes = select_signature_schemes(keymat, auth, private);
if (!array_count(schemes))
{
DBG1(DBG_IKE, "no common hash algorithm found to create signature "
"with %N key", key_type_names, private->get_type(private));
array_destroy(schemes);
return status;
}
auth_method = AUTH_DS;
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, id, this->reserved, &octets))
{
enumerator = array_create_enumerator(schemes);
while (enumerator->enumerate(enumerator, &schemep))
{
scheme = *schemep;
if (private->sign(private, scheme, octets, &auth_data) &&
build_signature_auth_data(&auth_data, scheme))
{
status = SUCCESS;
break;
}
else
{
DBG2(DBG_IKE, "unable to create %N signature for %N key",
signature_scheme_names, scheme, key_type_names,
private->get_type(private));
}
}
enumerator->destroy(enumerator);
}
array_destroy(schemes);
status = sign_signature_auth(this, auth, private, id, &auth_data);
}
else
{
switch (private->get_type(private))
{
case KEY_RSA:
scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
auth_method = AUTH_RSA;
break;
case KEY_ECDSA:
/* deduct the signature scheme from the keysize */
switch (private->get_keysize(private))
{
case 256:
scheme = SIGN_ECDSA_256;
auth_method = AUTH_ECDSA_256;
break;
case 384:
scheme = SIGN_ECDSA_384;
auth_method = AUTH_ECDSA_384;
break;
case 521:
scheme = SIGN_ECDSA_521;
auth_method = AUTH_ECDSA_521;
break;
default:
DBG1(DBG_IKE, "%d bit ECDSA private key size not "
"supported", private->get_keysize(private));
return status;
}
break;
default:
DBG1(DBG_IKE, "private key of type %N not supported",
key_type_names, private->get_type(private));
return status;
}
if (keymat->get_auth_octets(keymat, FALSE, this->ike_sa_init,
this->nonce, id, this->reserved, &octets) &&
private->sign(private, scheme, octets, &auth_data))
{
status = SUCCESS;
}
status = sign_classic(this, auth, private, id, &auth_method,
&auth_data);
}
private->destroy(private);
if (status == SUCCESS)
{
auth_payload = auth_payload_create();
@ -307,13 +352,6 @@ METHOD(authenticator_t, build, status_t,
chunk_free(&auth_data);
message->add_payload(message, (payload_t*)auth_payload);
}
DBG1(DBG_IKE, "authentication of '%Y' (myself) with %N %s", id,
auth_method == AUTH_DS ? signature_scheme_names : auth_method_names,
auth_method == AUTH_DS ? scheme : auth_method,
status == SUCCESS ? "successful" : "failed");
chunk_free(&octets);
private->destroy(private);
return status;
}