File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libsimaka / simaka_crypto.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:43 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2009-2011 Martin Willi
    3:  * HSR Hochschule fuer Technik Rapperswil
    4:  *
    5:  * This program is free software; you can redistribute it and/or modify it
    6:  * under the terms of the GNU General Public License as published by the
    7:  * Free Software Foundation; either version 2 of the License, or (at your
    8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
    9:  *
   10:  * This program is distributed in the hope that it will be useful, but
   11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   13:  * for more details.
   14:  */
   15: 
   16: #include "simaka_crypto.h"
   17: 
   18: #include "simaka_manager.h"
   19: 
   20: #include <utils/debug.h>
   21: 
   22: /** length of the k_encr key */
   23: #define KENCR_LEN 16
   24: /** length of the k_auth key */
   25: #define KAUTH_LEN 16
   26: /** length of the MSK */
   27: #define MSK_LEN 64
   28: /** length of the EMSK */
   29: #define EMSK_LEN 64
   30: 
   31: typedef struct private_simaka_crypto_t private_simaka_crypto_t;
   32: 
   33: /**
   34:  * Private data of an simaka_crypto_t object.
   35:  */
   36: struct private_simaka_crypto_t {
   37: 
   38: 	/**
   39: 	 * Public simaka_crypto_t interface.
   40: 	 */
   41: 	simaka_crypto_t public;
   42: 
   43: 	/**
   44: 	 * EAP type this crypto is used, SIM or AKA
   45: 	 */
   46: 	eap_type_t type;
   47: 
   48: 	/**
   49: 	 * signer to create/verify AT_MAC
   50: 	 */
   51: 	signer_t *signer;
   52: 
   53: 	/**
   54: 	 * crypter to encrypt/decrypt AT_ENCR_DATA
   55: 	 */
   56: 	crypter_t *crypter;
   57: 
   58: 	/**
   59: 	 * hasher used in key derivation
   60: 	 */
   61: 	hasher_t *hasher;
   62: 
   63: 	/**
   64: 	 * PRF function used in key derivation
   65: 	 */
   66: 	prf_t *prf;
   67: 
   68: 	/**
   69: 	 * Random number generator to generate nonces
   70: 	 */
   71: 	rng_t *rng;
   72: 
   73: 	/**
   74: 	 * Have k_encr/k_auth been derived?
   75: 	 */
   76: 	bool derived;
   77: };
   78: 
   79: METHOD(simaka_crypto_t, get_signer, signer_t*,
   80: 	private_simaka_crypto_t *this)
   81: {
   82: 	return this->derived ? this->signer : NULL;
   83: }
   84: 
   85: METHOD(simaka_crypto_t, get_crypter, crypter_t*,
   86: 	private_simaka_crypto_t *this)
   87: {
   88: 	return this->derived ? this->crypter : NULL;
   89: }
   90: 
   91: METHOD(simaka_crypto_t, get_rng, rng_t*,
   92: 	private_simaka_crypto_t *this)
   93: {
   94: 	return this->rng;
   95: }
   96: 
   97: /**
   98:  * Call SIM/AKA key hook
   99:  */
  100: static void call_hook(private_simaka_crypto_t *this, chunk_t encr, chunk_t auth)
  101: {
  102: 	simaka_manager_t *mgr;
  103: 
  104: 	switch (this->type)
  105: 	{
  106: 		case EAP_SIM:
  107: 			mgr = lib->get(lib, "sim-manager");
  108: 			break;
  109: 		case EAP_AKA:
  110: 			mgr = lib->get(lib, "aka-manager");
  111: 			break;
  112: 		default:
  113: 			return;
  114: 	}
  115: 	mgr->key_hook(mgr, encr, auth);
  116: }
  117: 
  118: METHOD(simaka_crypto_t, derive_keys_full, bool,
  119: 	private_simaka_crypto_t *this, identification_t *id,
  120: 	chunk_t data, chunk_t *mk, chunk_t *msk)
  121: {
  122: 	chunk_t str, k_encr, k_auth;
  123: 	int i;
  124: 
  125: 	/* For SIM: MK = SHA1(Identity|n*Kc|NONCE_MT|Version List|Selected Version)
  126: 	 * For AKA: MK = SHA1(Identity|IK|CK) */
  127: 	if (!this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL) ||
  128: 		!this->hasher->allocate_hash(this->hasher, data, mk))
  129: 	{
  130: 		return FALSE;
  131: 	}
  132: 	DBG3(DBG_LIB, "MK %B", mk);
  133: 
  134: 	/* K_encr | K_auth | MSK | EMSK = prf() | prf() | prf() | prf() */
  135: 	if (!this->prf->set_key(this->prf, *mk))
  136: 	{
  137: 		chunk_clear(mk);
  138: 		return FALSE;
  139: 	}
  140: 	str = chunk_alloca(this->prf->get_block_size(this->prf) * 3);
  141: 	for (i = 0; i < 3; i++)
  142: 	{
  143: 		if (!this->prf->get_bytes(this->prf, chunk_empty,
  144: 								  str.ptr + str.len / 3 * i))
  145: 		{
  146: 			chunk_clear(mk);
  147: 			return FALSE;
  148: 		}
  149: 	}
  150: 
  151: 	k_encr = chunk_create(str.ptr, KENCR_LEN);
  152: 	k_auth = chunk_create(str.ptr + KENCR_LEN, KAUTH_LEN);
  153: 
  154: 	if (!this->signer->set_key(this->signer, k_auth) ||
  155: 		!this->crypter->set_key(this->crypter, k_encr))
  156: 	{
  157: 		chunk_clear(mk);
  158: 		return FALSE;
  159: 	}
  160: 
  161: 	*msk = chunk_clone(chunk_create(str.ptr + KENCR_LEN + KAUTH_LEN, MSK_LEN));
  162: 	DBG3(DBG_LIB, "K_encr %B\nK_auth %B\nMSK %B", &k_encr, &k_auth, msk);
  163: 
  164: 	call_hook(this, k_encr, k_auth);
  165: 
  166: 	this->derived = TRUE;
  167: 	return TRUE;
  168: }
  169: 
  170: METHOD(simaka_crypto_t, derive_keys_reauth, bool,
  171: 	private_simaka_crypto_t *this, chunk_t mk)
  172: {
  173: 	chunk_t str, k_encr, k_auth;
  174: 	int i;
  175: 
  176: 	/* K_encr | K_auth = prf() | prf() */
  177: 	if (!this->prf->set_key(this->prf, mk))
  178: 	{
  179: 		return FALSE;
  180: 	}
  181: 	str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
  182: 	for (i = 0; i < 2; i++)
  183: 	{
  184: 		if (!this->prf->get_bytes(this->prf, chunk_empty,
  185: 								  str.ptr + str.len / 2 * i))
  186: 		{
  187: 			return FALSE;
  188: 		}
  189: 	}
  190: 	k_encr = chunk_create(str.ptr, KENCR_LEN);
  191: 	k_auth = chunk_create(str.ptr + KENCR_LEN, KAUTH_LEN);
  192: 	DBG3(DBG_LIB, "K_encr %B\nK_auth %B", &k_encr, &k_auth);
  193: 
  194: 	if (!this->signer->set_key(this->signer, k_auth) ||
  195: 		!this->crypter->set_key(this->crypter, k_encr))
  196: 	{
  197: 		return FALSE;
  198: 	}
  199: 
  200: 	call_hook(this, k_encr, k_auth);
  201: 
  202: 	this->derived = TRUE;
  203: 	return TRUE;
  204: }
  205: 
  206: METHOD(simaka_crypto_t, derive_keys_reauth_msk, bool,
  207: 	private_simaka_crypto_t *this, identification_t *id, chunk_t counter,
  208: 	chunk_t nonce_s, chunk_t mk, chunk_t *msk)
  209: {
  210: 	char xkey[HASH_SIZE_SHA1];
  211: 	chunk_t str;
  212: 	int i;
  213: 
  214: 	if (!this->hasher->get_hash(this->hasher, id->get_encoding(id), NULL) ||
  215: 		!this->hasher->get_hash(this->hasher, counter, NULL) ||
  216: 		!this->hasher->get_hash(this->hasher, nonce_s, NULL) ||
  217: 		!this->hasher->get_hash(this->hasher, mk, xkey))
  218: 	{
  219: 		return FALSE;
  220: 	}
  221: 
  222: 	/* MSK | EMSK = prf() | prf() | prf() | prf() */
  223: 	if (!this->prf->set_key(this->prf, chunk_create(xkey, sizeof(xkey))))
  224: 	{
  225: 		return FALSE;
  226: 	}
  227: 	str = chunk_alloca(this->prf->get_block_size(this->prf) * 2);
  228: 	for (i = 0; i < 2; i++)
  229: 	{
  230: 		if (!this->prf->get_bytes(this->prf, chunk_empty,
  231: 								  str.ptr + str.len / 2 * i))
  232: 		{
  233: 			return FALSE;
  234: 		}
  235: 	}
  236: 	*msk = chunk_clone(chunk_create(str.ptr, MSK_LEN));
  237: 	DBG3(DBG_LIB, "MSK %B", msk);
  238: 
  239: 	return TRUE;
  240: }
  241: 
  242: METHOD(simaka_crypto_t, clear_keys, void,
  243: 	private_simaka_crypto_t *this)
  244: {
  245: 	this->derived = FALSE;
  246: }
  247: 
  248: METHOD(simaka_crypto_t, destroy, void,
  249: 	private_simaka_crypto_t *this)
  250: {
  251: 	DESTROY_IF(this->rng);
  252: 	DESTROY_IF(this->hasher);
  253: 	DESTROY_IF(this->prf);
  254: 	DESTROY_IF(this->signer);
  255: 	DESTROY_IF(this->crypter);
  256: 	free(this);
  257: }
  258: 
  259: /**
  260:  * See header
  261:  */
  262: simaka_crypto_t *simaka_crypto_create(eap_type_t type)
  263: {
  264: 	private_simaka_crypto_t *this;
  265: 
  266: 	INIT(this,
  267: 		.public = {
  268: 			.get_signer = _get_signer,
  269: 			.get_crypter = _get_crypter,
  270: 			.get_rng = _get_rng,
  271: 			.derive_keys_full = _derive_keys_full,
  272: 			.derive_keys_reauth = _derive_keys_reauth,
  273: 			.derive_keys_reauth_msk = _derive_keys_reauth_msk,
  274: 			.clear_keys = _clear_keys,
  275: 			.destroy = _destroy,
  276: 		},
  277: 		.type = type,
  278: 		.rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK),
  279: 		.hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1),
  280: 		.prf = lib->crypto->create_prf(lib->crypto, PRF_FIPS_SHA1_160),
  281: 		.signer = lib->crypto->create_signer(lib->crypto, AUTH_HMAC_SHA1_128),
  282: 		.crypter = lib->crypto->create_crypter(lib->crypto, ENCR_AES_CBC, 16),
  283: 	);
  284: 	if (!this->rng || !this->hasher || !this->prf ||
  285: 		!this->signer || !this->crypter)
  286: 	{
  287: 		DBG1(DBG_LIB, "unable to use %N, missing algorithms",
  288: 			 eap_type_names, type);
  289: 		destroy(this);
  290: 		return NULL;
  291: 	}
  292: 	return &this->public;
  293: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>