Example #1
0
int
esp_rijndael_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
{
	keyInstance *k;

	k = (keyInstance *)sav->sched;
	if (rijndael_makeKey(&k[0], DIR_DECRYPT, _KEYLEN(sav->key_enc) * 8,
	    _KEYBUF(sav->key_enc)) < 0)
		return -1;
	if (rijndael_makeKey(&k[1], DIR_ENCRYPT, _KEYLEN(sav->key_enc) * 8,
	    _KEYBUF(sav->key_enc)) < 0)
		return -1;
	return 0;
}
Example #2
0
int
esp_aes_schedule(
	__unused const struct esp_algorithm *algo,
	struct secasvar *sav)
{

	lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
	aes_ctx *ctx = (aes_ctx*)sav->sched;
	
	aes_decrypt_key((const unsigned char *) _KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc), &ctx->decrypt);
	aes_encrypt_key((const unsigned char *) _KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc), &ctx->encrypt);
	
	return 0;
}
Example #3
0
static int
esp_cast128_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
{

    cast128_setkey((cast128_key *)sav->sched, _KEYBUF(sav->key_enc),
                   _KEYLEN(sav->key_enc));
    return 0;
}
Example #4
0
static int
esp_blowfish_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
{

    BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
               _KEYBUF(sav->key_enc));
    return 0;
}
Example #5
0
static int
esp_des_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
{

    if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
                      *(des_key_schedule *)sav->sched))
        return EINVAL;
    else
        return 0;
}
/*
 * Paranoia.
 */
static int
esp_zeroize(struct secasvar *sav)
{
    /* NB: ah_zerorize free's the crypto session state */
    int error = ah_zeroize(sav);

    if (sav->key_enc)
        memset(_KEYBUF(sav->key_enc), 0, _KEYLEN(sav->key_enc));
    sav->tdb_encalgxform = NULL;
    sav->tdb_xform = NULL;
    return error;
}
Example #7
0
File: esp_core.c Project: argp/xnu
static int
esp_3des_schedule(
	__unused const struct esp_algorithm *algo,
	struct secasvar *sav)
{
	LCK_MTX_ASSERT(sadb_mutex, LCK_MTX_ASSERT_OWNED);

	if (des3_ecb_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
	    (des3_ecb_key_schedule *)sav->sched))
		return EINVAL;
	else
		return 0;
}
Example #8
0
/*
 * Paranoia.
 */
static int
esp_zeroize(struct secasvar *sav)
{
	/* NB: ah_zerorize free's the crypto session state */
	int error = ah_zeroize(sav);

	if (sav->key_enc)
		bzero(_KEYBUF(sav->key_enc), _KEYLEN(sav->key_enc));
	/* NB: sav->iv is freed elsewhere, even though we malloc it! */
	sav->tdb_encalgxform = NULL;
	sav->tdb_xform = NULL;
	return error;
}
Example #9
0
/*
 * Paranoia.
 *
 * NB: public for use by esp_zeroize (XXX).
 */
int
ah_zeroize(struct secasvar *sav)
{
	int err;

	if (sav->key_auth)
		bzero(_KEYBUF(sav->key_auth), _KEYLEN(sav->key_auth));

	err = crypto_freesession(sav->tdb_cryptoid);
	sav->tdb_cryptoid = 0;
	sav->tdb_authalgxform = NULL;
	sav->tdb_xform = NULL;
	return err;
}
Example #10
0
/*
 * NB: public for use by esp_init.
 */
int
ah_init0(struct secasvar *sav, const struct xformsw *xsp,
	 struct cryptoini *cria)
{
	const struct auth_hash *thash;
	int keylen;

	thash = ah_algorithm_lookup(sav->alg_auth);
	if (thash == NULL) {
		DPRINTF(("ah_init: unsupported authentication algorithm %u\n",
			sav->alg_auth));
		return EINVAL;
	}
	/*
	 * Verify the replay state block allocation is consistent with
	 * the protocol type.  We check here so we can make assumptions
	 * later during protocol processing.
	 */
	/* NB: replay state is setup elsewhere (sigh) */
	if (((sav->flags&SADB_X_EXT_OLD) == 0) ^ (sav->replay != NULL)) {
		DPRINTF(("ah_init: replay state block inconsistency, "
			"%s algorithm %s replay state\n",
			(sav->flags & SADB_X_EXT_OLD) ? "old" : "new",
			sav->replay == NULL ? "without" : "with"));
		return EINVAL;
	}
	if (sav->key_auth == NULL) {
		DPRINTF(("ah_init: no authentication key for %s "
			"algorithm\n", thash->name));
		return EINVAL;
	}
	keylen = _KEYLEN(sav->key_auth);
	if (keylen != thash->keysize && thash->keysize != 0) {
		DPRINTF(("ah_init: invalid keylength %d, algorithm "
			 "%s requires keysize %d\n",
			 keylen, thash->name, thash->keysize));
		return EINVAL;
	}

	sav->tdb_xform = xsp;
	sav->tdb_authalgxform = thash;

	/* Initialize crypto session. */
	memset(cria, 0, sizeof (*cria));
	cria->cri_alg = sav->tdb_authalgxform->type;
	cria->cri_klen = _KEYBITS(sav->key_auth);
	cria->cri_key = _KEYBUF(sav->key_auth);

	return 0;
}
Example #11
0
static int
esp_3des_schedule(const struct esp_algorithm *algo, struct secasvar *sav)
{
    int error;
    des_key_schedule *p;
    int i;
    u_int8_t *k;

    p = (des_key_schedule *)sav->sched;
    k = _KEYBUF(sav->key_enc);
    for (i = 0; i < 3; i++) {
        error = des_key_sched((des_cblock *)(k + 8 * i), p[i]);
        if (error)
            return EINVAL;
    }
    return 0;
}
Example #12
0
File: esp_core.c Project: argp/xnu
static int
esp_descbc_mature(struct secasvar *sav)
{
	const struct esp_algorithm *algo;

	if (!(sav->flags & SADB_X_EXT_OLD) && (sav->flags & SADB_X_EXT_IV4B)) {
		ipseclog((LOG_ERR, "esp_cbc_mature: "
		    "algorithm incompatible with 4 octets IV length\n"));
		return 1;
	}

	if (!sav->key_enc) {
		ipseclog((LOG_ERR, "esp_descbc_mature: no key is given.\n"));
		return 1;
	}

	algo = esp_algorithm_lookup(sav->alg_enc);
	if (!algo) {
		ipseclog((LOG_ERR,
		    "esp_descbc_mature: unsupported algorithm.\n"));
		return 1;
	}

	if (_KEYBITS(sav->key_enc) < algo->keymin ||
	    _KEYBITS(sav->key_enc) > algo->keymax) {
		ipseclog((LOG_ERR,
		    "esp_descbc_mature: invalid key length %d.\n",
		    _KEYBITS(sav->key_enc)));
		return 1;
	}

	/* weak key check */
	if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc))) {
		ipseclog((LOG_ERR,
		    "esp_descbc_mature: weak key was passed.\n"));
		return 1;
	}

	return 0;
}
Example #13
0
/*
 * ESP output routine, called by ipsec[46]_process_packet().
 */
static int
esp_output(
	struct mbuf *m,
	struct ipsecrequest *isr,
	struct mbuf **mp,
	int skip,
	int protoff
)
{
	struct enc_xform *espx;
	struct auth_hash *esph;
	int hlen, rlen, plen, padding, blks, alen, i, roff;
	struct mbuf *mo = (struct mbuf *) NULL;
	struct tdb_crypto *tc;
	struct secasvar *sav;
	struct secasindex *saidx;
	unsigned char *pad;
	u_int8_t prot;
	int error, maxpacketsize;

	struct cryptodesc *crde = NULL, *crda = NULL;
	struct cryptop *crp;

	SPLASSERT(net, "esp_output");

	sav = isr->sav;
	KASSERT(sav != NULL, ("esp_output: null SA"));
	esph = sav->tdb_authalgxform;
	espx = sav->tdb_encalgxform;
	KASSERT(espx != NULL, ("esp_output: null encoding xform"));

	if (sav->flags & SADB_X_EXT_OLD)
		hlen = sizeof (struct esp) + sav->ivlen;
	else
		hlen = sizeof (struct newesp) + sav->ivlen;

	rlen = m->m_pkthdr.len - skip;	/* Raw payload length. */
	/*
	 * NB: The null encoding transform has a blocksize of 4
	 *     so that headers are properly aligned.
	 */
	blks = espx->blocksize;		/* IV blocksize */

	/* XXX clamp padding length a la KAME??? */
	padding = ((blks - ((rlen + 2) % blks)) % blks) + 2;
	plen = rlen + padding;		/* Padded payload length. */

	if (esph)
		alen = AH_HMAC_HASHLEN;
	else
		alen = 0;

	espstat.esps_output++;

	saidx = &sav->sah->saidx;
	/* Check for maximum packet size violations. */
	switch (saidx->dst.sa.sa_family) {
#ifdef INET
	case AF_INET:
		maxpacketsize = IP_MAXPACKET;
		break;
#endif /* INET */
#ifdef INET6
	case AF_INET6:
		maxpacketsize = IPV6_MAXPACKET;
		break;
#endif /* INET6 */
	default:
		DPRINTF(("esp_output: unknown/unsupported protocol "
		    "family %d, SA %s/%08lx\n",
		    saidx->dst.sa.sa_family, ipsec_address(&saidx->dst),
		    (u_long) ntohl(sav->spi)));
		espstat.esps_nopf++;
		error = EPFNOSUPPORT;
		goto bad;
	}
	if (skip + hlen + rlen + padding + alen > maxpacketsize) {
		DPRINTF(("esp_output: packet in SA %s/%08lx got too big "
		    "(len %u, max len %u)\n",
		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi),
		    skip + hlen + rlen + padding + alen, maxpacketsize));
		espstat.esps_toobig++;
		error = EMSGSIZE;
		goto bad;
	}

	/* Update the counters. */
	espstat.esps_obytes += m->m_pkthdr.len - skip;

	m = m_clone(m);
	if (m == NULL) {
		DPRINTF(("esp_output: cannot clone mbuf chain, SA %s/%08lx\n",
		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi)));
		espstat.esps_hdrops++;
		error = ENOBUFS;
		goto bad;
	}

	/* Inject ESP header. */
	mo = m_makespace(m, skip, hlen, &roff);
	if (mo == NULL) {
		DPRINTF(("esp_output: failed to inject %u byte ESP hdr for SA "
		    "%s/%08lx\n",
		    hlen, ipsec_address(&saidx->dst),
		    (u_long) ntohl(sav->spi)));
		espstat.esps_hdrops++;		/* XXX diffs from openbsd */
		error = ENOBUFS;
		goto bad;
	}

	/* Initialize ESP header. */
	bcopy((caddr_t) &sav->spi, mtod(mo, caddr_t) + roff, sizeof(u_int32_t));
	if (sav->replay) {
		u_int32_t replay = htonl(++(sav->replay->count));
		bcopy((caddr_t) &replay,
		    mtod(mo, caddr_t) + roff + sizeof(u_int32_t),
		    sizeof(u_int32_t));
	}

	/*
	 * Add padding -- better to do it ourselves than use the crypto engine,
	 * although if/when we support compression, we'd have to do that.
	 */
	pad = (u_char *) m_pad(m, padding + alen);
	if (pad == NULL) {
		DPRINTF(("esp_output: m_pad failed for SA %s/%08lx\n",
		    ipsec_address(&saidx->dst), (u_long) ntohl(sav->spi)));
		m = NULL;		/* NB: free'd by m_pad */
		error = ENOBUFS;
		goto bad;
	}

	/*
	 * Add padding: random, zero, or self-describing.
	 * XXX catch unexpected setting
	 */
	switch (sav->flags & SADB_X_EXT_PMASK) {
	case SADB_X_EXT_PRAND:
		(void) read_random(pad, padding - 2);
		break;
	case SADB_X_EXT_PZERO:
		bzero(pad, padding - 2);
		break;
	case SADB_X_EXT_PSEQ:
		for (i = 0; i < padding - 2; i++)
			pad[i] = i+1;
		break;
	}

	/* Fix padding length and Next Protocol in padding itself. */
	pad[padding - 2] = padding - 2;
	m_copydata(m, protoff, sizeof(u_int8_t), pad + padding - 1);

	/* Fix Next Protocol in IPv4/IPv6 header. */
	prot = IPPROTO_ESP;
	m_copyback(m, protoff, sizeof(u_int8_t), (u_char *) &prot);

	/* Get crypto descriptors. */
	crp = crypto_getreq(esph && espx ? 2 : 1);
	if (crp == NULL) {
		DPRINTF(("esp_output: failed to acquire crypto descriptors\n"));
		espstat.esps_crypto++;
		error = ENOBUFS;
		goto bad;
	}

	if (espx) {
		crde = crp->crp_desc;
		crda = crde->crd_next;

		/* Encryption descriptor. */
		crde->crd_skip = skip + hlen;
		crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
		crde->crd_flags = CRD_F_ENCRYPT;
		crde->crd_inject = skip + hlen - sav->ivlen;

		/* Encryption operation. */
		crde->crd_alg = espx->type;
		crde->crd_key = _KEYBUF(sav->key_enc);
		crde->crd_klen = _KEYBITS(sav->key_enc);
		/* XXX Rounds ? */
	} else
		crda = crp->crp_desc;

	/* IPsec-specific opaque crypto info. */
	tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto),
		M_XDATA, M_NOWAIT|M_ZERO);
	if (tc == NULL) {
		crypto_freereq(crp);
		DPRINTF(("esp_output: failed to allocate tdb_crypto\n"));
		espstat.esps_crypto++;
		error = ENOBUFS;
		goto bad;
	}

	/* Callback parameters */
	tc->tc_isr = isr;
	tc->tc_spi = sav->spi;
	tc->tc_dst = saidx->dst;
	tc->tc_proto = saidx->proto;

	/* Crypto operation descriptor. */
	crp->crp_ilen = m->m_pkthdr.len; /* Total input length. */
	crp->crp_flags = CRYPTO_F_IMBUF;
	crp->crp_buf = (caddr_t) m;
	crp->crp_callback = esp_output_cb;
	crp->crp_opaque = (caddr_t) tc;
	crp->crp_sid = sav->tdb_cryptoid;

	if (esph) {
		/* Authentication descriptor. */
		crda->crd_skip = skip;
		crda->crd_len = m->m_pkthdr.len - (skip + alen);
		crda->crd_inject = m->m_pkthdr.len - alen;

		/* Authentication operation. */
		crda->crd_alg = esph->type;
		crda->crd_key = _KEYBUF(sav->key_auth);
		crda->crd_klen = _KEYBITS(sav->key_auth);
	}

	return crypto_dispatch(crp);
bad:
	if (m)
		m_freem(m);
	return (error);
}
Example #14
0
/*
 * ESP input processing, called (eventually) through the protocol switch.
 */
static int
esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
{
	struct auth_hash *esph;
	struct enc_xform *espx;
	struct tdb_ident *tdbi;
	struct tdb_crypto *tc;
	int plen, alen, hlen;
	struct m_tag *mtag;
	struct newesp *esp;

	struct cryptodesc *crde;
	struct cryptop *crp;

	SPLASSERT(net, "esp_input");

	KASSERT(sav != NULL, ("esp_input: null SA"));
	KASSERT(sav->tdb_encalgxform != NULL,
		("esp_input: null encoding xform"));
	KASSERT((skip&3) == 0 && (m->m_pkthdr.len&3) == 0,
		("esp_input: misaligned packet, skip %u pkt len %u",
			skip, m->m_pkthdr.len));

	/* XXX don't pullup, just copy header */
	IP6_EXTHDR_GET(esp, struct newesp *, m, skip, sizeof (struct newesp));

	esph = sav->tdb_authalgxform;
	espx = sav->tdb_encalgxform;

	/* Determine the ESP header length */
	if (sav->flags & SADB_X_EXT_OLD)
		hlen = sizeof (struct esp) + sav->ivlen;
	else
		hlen = sizeof (struct newesp) + sav->ivlen;
	/* Authenticator hash size */
	alen = esph ? AH_HMAC_HASHLEN : 0;

	/*
	 * Verify payload length is multiple of encryption algorithm
	 * block size.
	 *
	 * NB: This works for the null algorithm because the blocksize
	 *     is 4 and all packets must be 4-byte aligned regardless
	 *     of the algorithm.
	 */
	plen = m->m_pkthdr.len - (skip + hlen + alen);
	if ((plen & (espx->blocksize - 1)) || (plen <= 0)) {
		DPRINTF(("esp_input: "
		    "payload of %d octets not a multiple of %d octets,"
		    "  SA %s/%08lx\n",
		    plen, espx->blocksize,
		    ipsec_address(&sav->sah->saidx.dst),
		    (u_long) ntohl(sav->spi)));
		espstat.esps_badilen++;
		m_freem(m);
		return EINVAL;
	}

	/*
	 * Check sequence number.
	 */
	if (esph && sav->replay && !ipsec_chkreplay(ntohl(esp->esp_seq), sav)) {
		DPRINTF(("esp_input: packet replay check for %s\n",
		    ipsec_logsastr(sav)));	/*XXX*/
		espstat.esps_replay++;
		m_freem(m);
		return ENOBUFS;		/*XXX*/
	}

	/* Update the counters */
	espstat.esps_ibytes += m->m_pkthdr.len - skip - hlen - alen;

	/* Find out if we've already done crypto */
	for (mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, NULL);
	     mtag != NULL;
	     mtag = m_tag_find(m, PACKET_TAG_IPSEC_IN_CRYPTO_DONE, mtag)) {
		tdbi = (struct tdb_ident *) (mtag + 1);
		if (tdbi->proto == sav->sah->saidx.proto &&
		    tdbi->spi == sav->spi &&
		    !bcmp(&tdbi->dst, &sav->sah->saidx.dst,
			  sizeof(union sockaddr_union)))
			break;
	}

	/* Get crypto descriptors */
	crp = crypto_getreq(esph && espx ? 2 : 1);
	if (crp == NULL) {
		DPRINTF(("esp_input: failed to acquire crypto descriptors\n"));
		espstat.esps_crypto++;
		m_freem(m);
		return ENOBUFS;
	}

	/* Get IPsec-specific opaque pointer */
	if (esph == NULL || mtag != NULL)
		tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto),
		    M_XDATA, M_NOWAIT|M_ZERO);
	else
		tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen,
		    M_XDATA, M_NOWAIT|M_ZERO);
	if (tc == NULL) {
		crypto_freereq(crp);
		DPRINTF(("esp_input: failed to allocate tdb_crypto\n"));
		espstat.esps_crypto++;
		m_freem(m);
		return ENOBUFS;
	}

	tc->tc_ptr = (caddr_t) mtag;

	if (esph) {
		struct cryptodesc *crda = crp->crp_desc;

		KASSERT(crda != NULL, ("esp_input: null ah crypto descriptor"));

		/* Authentication descriptor */
		crda->crd_skip = skip;
		crda->crd_len = m->m_pkthdr.len - (skip + alen);
		crda->crd_inject = m->m_pkthdr.len - alen;

		crda->crd_alg = esph->type;
		crda->crd_key = _KEYBUF(sav->key_auth);
		crda->crd_klen = _KEYBITS(sav->key_auth);

		/* Copy the authenticator */
		if (mtag == NULL)
			m_copydata(m, m->m_pkthdr.len - alen, alen,
				   (caddr_t) (tc + 1));

		/* Chain authentication request */
		crde = crda->crd_next;
	} else {
		crde = crp->crp_desc;
	}

	/* Crypto operation descriptor */
	crp->crp_ilen = m->m_pkthdr.len; /* Total input length */
	crp->crp_flags = CRYPTO_F_IMBUF;
	crp->crp_buf = (caddr_t) m;
	crp->crp_callback = esp_input_cb;
	crp->crp_sid = sav->tdb_cryptoid;
	crp->crp_opaque = (caddr_t) tc;

	/* These are passed as-is to the callback */
	tc->tc_spi = sav->spi;
	tc->tc_dst = sav->sah->saidx.dst;
	tc->tc_proto = sav->sah->saidx.proto;
	tc->tc_protoff = protoff;
	tc->tc_skip = skip;

	/* Decryption descriptor */
	if (espx) {
		KASSERT(crde != NULL, ("esp_input: null esp crypto descriptor"));
		crde->crd_skip = skip + hlen;
		crde->crd_len = m->m_pkthdr.len - (skip + hlen + alen);
		crde->crd_inject = skip + hlen - sav->ivlen;

		crde->crd_alg = espx->type;
		crde->crd_key = _KEYBUF(sav->key_enc);
		crde->crd_klen = _KEYBITS(sav->key_enc);
		/* XXX Rounds ? */
	}

	if (mtag == NULL)
		return crypto_dispatch(crp);
	else
		return esp_input_cb(crp);
}
Example #15
0
/*
 * esp_init() is called when an SPI is being set up.
 */
static int
esp_init(struct secasvar *sav, struct xformsw *xsp)
{
	struct enc_xform *txform;
	struct cryptoini cria, crie;
	int keylen;
	int error;

	txform = esp_algorithm_lookup(sav->alg_enc);
	if (txform == NULL) {
		DPRINTF(("esp_init: unsupported encryption algorithm %d\n",
			sav->alg_enc));
		return EINVAL;
	}
	if (sav->key_enc == NULL) {
		DPRINTF(("esp_init: no encoding key for %s algorithm\n",
			 txform->name));
		return EINVAL;
	}
	if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) {
		DPRINTF(("esp_init: 4-byte IV not supported with protocol\n"));
		return EINVAL;
	}
	keylen = _KEYLEN(sav->key_enc);
	if (txform->minkey > keylen || keylen > txform->maxkey) {
		DPRINTF(("esp_init: invalid key length %u, must be in "
			"the range [%u..%u] for algorithm %s\n",
			keylen, txform->minkey, txform->maxkey,
			txform->name));
		return EINVAL;
	}

	/*
	 * NB: The null xform needs a non-zero blocksize to keep the
	 *      crypto code happy but if we use it to set ivlen then
	 *      the ESP header will be processed incorrectly.  The
	 *      compromise is to force it to zero here.
	 */
	sav->ivlen = (txform == &enc_xform_null ? 0 : txform->blocksize);
	sav->iv = (caddr_t) malloc(sav->ivlen, M_XDATA, M_WAITOK);
	if (sav->iv == NULL) {
		DPRINTF(("esp_init: no memory for IV\n"));
		return EINVAL;
	}
	key_randomfill(sav->iv, sav->ivlen);	/*XXX*/

	/*
	 * Setup AH-related state.
	 */
	if (sav->alg_auth != 0) {
		error = ah_init0(sav, xsp, &cria);
		if (error)
			return error;
	}

	/* NB: override anything set in ah_init0 */
	sav->tdb_xform = xsp;
	sav->tdb_encalgxform = txform;

	/* Initialize crypto session. */
	bzero(&crie, sizeof (crie));
	crie.cri_alg = sav->tdb_encalgxform->type;
	crie.cri_klen = _KEYBITS(sav->key_enc);
	crie.cri_key = _KEYBUF(sav->key_enc);
	/* XXX Rounds ? */

	if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
		/* init both auth & enc */
		crie.cri_next = &cria;
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, crypto_support);
	} else if (sav->tdb_encalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, crypto_support);
	} else if (sav->tdb_authalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &cria, crypto_support);
	} else {
		/* XXX cannot happen? */
		DPRINTF(("esp_init: no encoding OR authentication xform!\n"));
		error = EINVAL;
	}
	return error;
}
/*
 * esp_init() is called when an SPI is being set up.
 */
static int
esp_init(struct secasvar *sav, const struct xformsw *xsp)
{
    const struct enc_xform *txform;
    struct cryptoini cria, crie;
    int keylen;
    int error;

    txform = esp_algorithm_lookup(sav->alg_enc);
    if (txform == NULL) {
        DPRINTF(("esp_init: unsupported encryption algorithm %d\n",
                 sav->alg_enc));
        return EINVAL;
    }
    if (sav->key_enc == NULL) {
        DPRINTF(("esp_init: no encoding key for %s algorithm\n",
                 txform->name));
        return EINVAL;
    }
    if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) {
        DPRINTF(("esp_init: 4-byte IV not supported with protocol\n"));
        return EINVAL;
    }
    keylen = _KEYLEN(sav->key_enc);
    if (txform->minkey > keylen || keylen > txform->maxkey) {
        DPRINTF(("esp_init: invalid key length %u, must be in "
                 "the range [%u..%u] for algorithm %s\n",
                 keylen, txform->minkey, txform->maxkey,
                 txform->name));
        return EINVAL;
    }

    sav->ivlen = txform->ivsize;

    /*
     * Setup AH-related state.
     */
    if (sav->alg_auth != 0) {
        error = ah_init0(sav, xsp, &cria);
        if (error)
            return error;
    }

    /* NB: override anything set in ah_init0 */
    sav->tdb_xform = xsp;
    sav->tdb_encalgxform = txform;

    if (sav->alg_enc == SADB_X_EALG_AESGCM16 ||
            sav->alg_enc == SADB_X_EALG_AESGMAC) {
        switch (keylen) {
        case 20:
            sav->alg_auth = SADB_X_AALG_AES128GMAC;
            sav->tdb_authalgxform = &auth_hash_gmac_aes_128;
            break;
        case 28:
            sav->alg_auth = SADB_X_AALG_AES192GMAC;
            sav->tdb_authalgxform = &auth_hash_gmac_aes_192;
            break;
        case 36:
            sav->alg_auth = SADB_X_AALG_AES256GMAC;
            sav->tdb_authalgxform = &auth_hash_gmac_aes_256;
            break;
        }
        memset(&cria, 0, sizeof(cria));
        cria.cri_alg = sav->tdb_authalgxform->type;
        cria.cri_klen = _KEYBITS(sav->key_enc);
        cria.cri_key = _KEYBUF(sav->key_enc);
    }

    /* Initialize crypto session. */
    memset(&crie, 0, sizeof (crie));
    crie.cri_alg = sav->tdb_encalgxform->type;
    crie.cri_klen = _KEYBITS(sav->key_enc);
    crie.cri_key = _KEYBUF(sav->key_enc);
    /* XXX Rounds ? */

    if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
        /* init both auth & enc */
        crie.cri_next = &cria;
        error = crypto_newsession(&sav->tdb_cryptoid,
                                  &crie, crypto_support);
    } else if (sav->tdb_encalgxform) {
        error = crypto_newsession(&sav->tdb_cryptoid,
                                  &crie, crypto_support);
    } else if (sav->tdb_authalgxform) {
        error = crypto_newsession(&sav->tdb_cryptoid,
                                  &cria, crypto_support);
    } else {
        /* XXX cannot happen? */
        DPRINTF(("esp_init: no encoding OR authentication xform!\n"));
        error = EINVAL;
    }
    return error;
}
Example #17
0
File: esp_core.c Project: argp/xnu
static int
esp_cbc_mature(struct secasvar *sav)
{
	int keylen;
	const struct esp_algorithm *algo;

	if (sav->flags & SADB_X_EXT_OLD) {
		ipseclog((LOG_ERR,
		    "esp_cbc_mature: algorithm incompatible with esp-old\n"));
		return 1;
	}
	if (sav->flags & SADB_X_EXT_DERIV) {
		ipseclog((LOG_ERR,
		    "esp_cbc_mature: algorithm incompatible with derived\n"));
		return 1;
	}

	if (!sav->key_enc) {
		ipseclog((LOG_ERR, "esp_cbc_mature: no key is given.\n"));
		return 1;
	}

	algo = esp_algorithm_lookup(sav->alg_enc);
	if (!algo) {
		ipseclog((LOG_ERR,
		    "esp_cbc_mature: unsupported algorithm.\n"));
		return 1;
	}

	keylen = sav->key_enc->sadb_key_bits;
	if (keylen < algo->keymin || algo->keymax < keylen) {
		ipseclog((LOG_ERR,
		    "esp_cbc_mature %s: invalid key length %d.\n",
		    algo->name, sav->key_enc->sadb_key_bits));
		return 1;
	}
	switch (sav->alg_enc) {
	case SADB_EALG_3DESCBC:
		/* weak key check */
		if (des_is_weak_key((des_cblock *)_KEYBUF(sav->key_enc)) ||
		    des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 8)) ||
		    des_is_weak_key((des_cblock *)(_KEYBUF(sav->key_enc) + 16))) {
			ipseclog((LOG_ERR,
			    "esp_cbc_mature %s: weak key was passed.\n",
			    algo->name));
			return 1;
		}
		break;
	case SADB_X_EALG_RIJNDAELCBC:
		/* allows specific key sizes only */
		if (!(keylen == 128 || keylen == 192 || keylen == 256)) {
			ipseclog((LOG_ERR,
			    "esp_cbc_mature %s: invalid key length %d.\n",
			    algo->name, keylen));
			return 1;
		}
		break;
	}

	return 0;
}