FreeBSD/sys/netipsec/key.c
/*
 * XXX reorder combinations by preference
 * XXX no idea if the user wants ESP authentication or not
 */
XXX reorder combinations by preference
XXX no idea if the user wants ESP authentication or not
XXX reorder combinations by preference XXX no idea if the user wants ESP authentication or not
static struct mbuf *
key_getcomb_esp()
{
	struct sadb_comb *comb;
	struct enc_xform *algo;
	struct mbuf *result = NULL, *m, *n;
	int encmin;
	int i, off, o;
	int totlen;
	const int l = PFKEY_ALIGN8(sizeof(struct sadb_comb));
	m = NULL;
	for (i = 1; i <= SADB_EALG_MAX; i++) {
		algo = esp_algorithm_lookup(i);
		if (algo == NULL)
			continue;
		if (_BITS(algo->maxkey) < V_ipsec_esp_keymin)
			continue;
		if (_BITS(algo->minkey) < V_ipsec_esp_keymin)
			encmin = V_ipsec_esp_keymin;
		else
			encmin = _BITS(algo->minkey);
		if (V_ipsec_esp_auth)
			m = key_getcomb_ah();
		else {
			IPSEC_ASSERT(l <= MLEN,
				("l=%u > MLEN=%lu", l, (u_long) MLEN));
			MGET(m, M_NOWAIT, MT_DATA);
			if (m) {
				M_ALIGN(m, l);
				m->m_len = l;
				m->m_next = NULL;
				bzero(mtod(m, caddr_t), m->m_len);
			}
		}
		if (!m)
			goto fail;
		totlen = 0;
		for (n = m; n; n = n->m_next)
			totlen += n->m_len;
		IPSEC_ASSERT((totlen % l) == 0, ("totlen=%u, l=%u", totlen, l));
		for (off = 0; off < totlen; off += l) {
			n = m_pulldown(m, off, l, &o);
			if (!n) {
				goto fail;
			}
			comb = (struct sadb_comb *)(mtod(n, caddr_t) + o);
			bzero(comb, sizeof(*comb));
			key_getcomb_setlifetime(comb);
			comb->sadb_comb_encrypt = i;
			comb->sadb_comb_encrypt_minbits = encmin;
			comb->sadb_comb_encrypt_maxbits = _BITS(algo->maxkey);
		}
		if (!result)
			result = m;
		else
			m_cat(result, m);
	}
	return result;
 fail:
	if (result)
		m_freem(result);
	return NULL;
}
static struct mbuf * key_getcomb_esp ( ) { struct sadb_comb * comb ; struct enc_xform * algo ; struct mbuf * result = NULL , * m , * n ; int encmin ; int i , off , o ; int totlen ; const int l = PFKEY_ALIGN8 ( sizeof ( struct sadb_comb ) ) ; m = NULL ; for ( i = 1 ; i <= SADB_EALG_MAX ; i ++ ) { algo = esp_algorithm_lookup ( i ) ; if ( algo == NULL ) continue ; if ( _BITS ( algo -> maxkey ) < V_ipsec_esp_keymin ) continue ; if ( _BITS ( algo -> minkey ) < V_ipsec_esp_keymin ) encmin = V_ipsec_esp_keymin ; else encmin = _BITS ( algo -> minkey ) ; if ( V_ipsec_esp_auth ) m = key_getcomb_ah ( ) ; else { IPSEC_ASSERT ( l <= MLEN , ( " " , l , ( u_long ) MLEN ) ) ; MGET ( m , M_NOWAIT , MT_DATA ) ; if ( m ) { M_ALIGN ( m , l ) ; m -> m_len = l ; m -> m_next = NULL ; bzero ( mtod ( m , caddr_t ) , m -> m_len ) ; } } if ( ! m ) goto fail ; totlen = 0 ; for ( n = m ; n ; n = n -> m_next ) totlen += n -> m_len ; IPSEC_ASSERT ( ( totlen % l ) == 0 , ( " " , totlen , l ) ) ; for ( off = 0 ; off < totlen ; off += l ) { n = m_pulldown ( m , off , l , & o ) ; if ( ! n ) { goto fail ; } comb = ( struct sadb_comb * ) ( mtod ( n , caddr_t ) + o ) ; bzero ( comb , sizeof ( * comb ) ) ; key_getcomb_setlifetime ( comb ) ; comb -> sadb_comb_encrypt = i ; comb -> sadb_comb_encrypt_minbits = encmin ; comb -> sadb_comb_encrypt_maxbits = _BITS ( algo -> maxkey ) ; } if ( ! result ) result = m ; else m_cat ( result , m ) ; } return result ; fail : if ( result ) m_freem ( result ) ; return NULL ; }
XXX reorder combinations by preference
 XXX no idea if the user wants ESP authentication or not
XXX reorder combinations by preference XXX no idea if the user wants ESP authentication or not
/* discard algorithms with key size smaller than system min */ /* m is already freed */