示例#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;
}
示例#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;
}
示例#3
0
/*
 * Initialize a TCP-MD5 SA. Called when the SA is being set up.
 *
 * We don't need to set up the tdb prefixed fields, as we don't use the
 * opencrypto code; we just perform a key length check.
 *
 * XXX: Currently we only allow a single 'magic' SPI to be used.
 *
 * This allows per-host granularity without affecting the userland
 * interface, which is a simple socket option toggle switch,
 * TCP_SIGNATURE_ENABLE.
 *
 * To allow per-service granularity requires that we have a means
 * of mapping port to SPI. The mandated way of doing this is to
 * use SPD entries to specify packet flows which get the TCP-MD5
 * treatment, however the code to do this is currently unstable
 * and unsuitable for production use.
 *
 * Therefore we use this compromise in the meantime.
 */
static int
tcpsignature_init(struct secasvar *sav, struct xformsw *xsp)
{
	int keylen;

	if (sav->spi != htonl(TCP_SIG_SPI)) {
		DPRINTF(("%s: SPI must be TCP_SIG_SPI (0x1000)\n",
		    __func__));
		return (EINVAL);
	}
	if (sav->alg_auth != SADB_X_AALG_TCP_MD5) {
		DPRINTF(("%s: unsupported authentication algorithm %u\n",
		    __func__, sav->alg_auth));
		return (EINVAL);
	}
	if (sav->key_auth == NULL) {
		DPRINTF(("%s: no authentication key present\n", __func__));
		return (EINVAL);
	}
	keylen = _KEYLEN(sav->key_auth);
	if ((keylen < TCP_KEYLEN_MIN) || (keylen > TCP_KEYLEN_MAX)) {
		DPRINTF(("%s: invalid key length %u\n", __func__, keylen));
		return (EINVAL);
	}

	return (0);
}
示例#4
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;
}
示例#5
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;
}
示例#6
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(sav->key_enc->key_data, _KEYLEN(sav->key_enc));
	sav->tdb_encalgxform = NULL;
	sav->tdb_xform = NULL;
	return error;
}
示例#7
0
/*
 * Paranoia.
 *
 * Called when the SA is deleted.
 */
static int
tcpsignature_zeroize(struct secasvar *sav)
{

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

	sav->tdb_cryptoid = 0;
	sav->tdb_authalgxform = NULL;
	sav->tdb_xform = NULL;

	return (0);
}
示例#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;
}
示例#9
0
/*
 * Paranoia.
 *
 * NB: public for use by esp_zeroize (XXX).
 */
int
ah_zeroize(struct secasvar *sav)
{
	int err;

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

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

	thash = ah_algorithm_lookup(sav->alg_auth);
	if (thash == NULL) {
		DPRINTF(("%s: unsupported authentication algorithm %u\n",
			__func__, 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(("%s: replay state block inconsistency, "
			"%s algorithm %s replay state\n", __func__,
			(sav->flags & SADB_X_EXT_OLD) ? "old" : "new",
			sav->replay == NULL ? "without" : "with"));
		return EINVAL;
	}
	if (sav->key_auth == NULL) {
		DPRINTF(("%s: no authentication key for %s algorithm\n",
			__func__, thash->name));
		return EINVAL;
	}
	keylen = _KEYLEN(sav->key_auth);
	if (keylen != thash->keysize && thash->keysize != 0) {
		DPRINTF(("%s: invalid keylength %d, algorithm %s requires "
			"keysize %d\n", __func__,
			 keylen, thash->name, thash->keysize));
		return EINVAL;
	}

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

	/* Initialize crypto session. */
	bzero(cria, sizeof (*cria));
	cria->cri_alg = sav->tdb_authalgxform->type;
	cria->cri_klen = _KEYBITS(sav->key_auth);
	cria->cri_key = sav->key_auth->key_data;
	cria->cri_mlen = AUTHSIZE(sav);

	return 0;
}
示例#11
0
/*
 * ESP input processing, called (eventually) through the protocol switch.
 */
static int
esp_input(struct mbuf *m, struct secasvar *sav, int skip, int protoff)
{
	char buf[128];
	struct auth_hash *esph;
	struct enc_xform *espx;
	struct tdb_crypto *tc;
	uint8_t *ivp;
	int plen, alen, hlen;
	struct newesp *esp;
	struct cryptodesc *crde;
	struct cryptop *crp;

	IPSEC_ASSERT(sav != NULL, ("null SA"));
	IPSEC_ASSERT(sav->tdb_encalgxform != NULL, ("null encoding xform"));

	/* Valid IP Packet length ? */
	if ( (skip&3) || (m->m_pkthdr.len&3) ){
		DPRINTF(("%s: misaligned packet, skip %u pkt len %u",
				__func__, skip, m->m_pkthdr.len));
		ESPSTAT_INC(esps_badilen);
		m_freem(m);
		return EINVAL;
	}
	/* 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 and auth length */
	if (sav->flags & SADB_X_EXT_OLD)
		hlen = sizeof (struct esp) + sav->ivlen;
	else
		hlen = sizeof (struct newesp) + sav->ivlen;

	alen = xform_ah_authsize(esph);

	/*
	 * 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(("%s: payload of %d octets not a multiple of %d octets,"
		    "  SA %s/%08lx\n", __func__, plen, espx->blocksize,
		    ipsec_address(&sav->sah->saidx.dst, buf, sizeof(buf)),
		    (u_long)ntohl(sav->spi)));
		ESPSTAT_INC(esps_badilen);
		m_freem(m);
		return EINVAL;
	}

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

	/* Update the counters */
	ESPSTAT_ADD(esps_ibytes, m->m_pkthdr.len - (skip + hlen + alen));

	/* Get crypto descriptors */
	crp = crypto_getreq(esph && espx ? 2 : 1);
	if (crp == NULL) {
		DPRINTF(("%s: failed to acquire crypto descriptors\n",
			__func__));
		ESPSTAT_INC(esps_crypto);
		m_freem(m);
		return ENOBUFS;
	}

	/* Get IPsec-specific opaque pointer */
	tc = (struct tdb_crypto *) malloc(sizeof(struct tdb_crypto) + alen,
	    M_XDATA, M_NOWAIT | M_ZERO);
	if (tc == NULL) {
		crypto_freereq(crp);
		DPRINTF(("%s: failed to allocate tdb_crypto\n", __func__));
		ESPSTAT_INC(esps_crypto);
		m_freem(m);
		return ENOBUFS;
	}

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

		IPSEC_ASSERT(crda != NULL, ("null ah crypto descriptor"));

		/* Authentication descriptor */
		crda->crd_skip = skip;
		if (SAV_ISGCM(sav))
			crda->crd_len = 8;	/* RFC4106 5, SPI + SN */
		else
			crda->crd_len = m->m_pkthdr.len - (skip + alen);
		crda->crd_inject = m->m_pkthdr.len - alen;

		crda->crd_alg = esph->type;

		/* Copy the authenticator */
		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 | CRYPTO_F_CBIFSYNC;
	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;
	KEY_ADDREFSA(sav);
	tc->tc_sav = sav;

	/* Decryption descriptor */
	IPSEC_ASSERT(crde != NULL, ("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;

	if (SAV_ISCTRORGCM(sav)) {
		ivp = &crde->crd_iv[0];

		/* GCM IV Format: RFC4106 4 */
		/* CTR IV Format: RFC3686 4 */
		/* Salt is last four bytes of key, RFC4106 8.1 */
		/* Nonce is last four bytes of key, RFC3686 5.1 */
		memcpy(ivp, sav->key_enc->key_data +
		    _KEYLEN(sav->key_enc) - 4, 4);

		if (SAV_ISCTR(sav)) {
			/* Initial block counter is 1, RFC3686 4 */
			be32enc(&ivp[sav->ivlen + 4], 1);
		}

		m_copydata(m, skip + hlen - sav->ivlen, sav->ivlen, &ivp[4]);
		crde->crd_flags |= CRD_F_IV_EXPLICIT;
	}

	crde->crd_alg = espx->type;

	return (crypto_dispatch(crp));
}
示例#12
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(("%s: unsupported encryption algorithm %d\n",
			__func__, sav->alg_enc));
		return EINVAL;
	}
	if (sav->key_enc == NULL) {
		DPRINTF(("%s: no encoding key for %s algorithm\n",
			 __func__, txform->name));
		return EINVAL;
	}
	if ((sav->flags & (SADB_X_EXT_OLD | SADB_X_EXT_IV4B)) ==
	    SADB_X_EXT_IV4B) {
		DPRINTF(("%s: 4-byte IV not supported with protocol\n",
			__func__));
		return EINVAL;
	}
	/* subtract off the salt, RFC4106, 8.1 and RFC3686, 5.1 */
	keylen = _KEYLEN(sav->key_enc) - SAV_ISCTRORGCM(sav) * 4;
	if (txform->minkey > keylen || keylen > txform->maxkey) {
		DPRINTF(("%s: invalid key length %u, must be in the range "
			"[%u..%u] for algorithm %s\n", __func__,
			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.
	 */
	if (SAV_ISCTRORGCM(sav))
		sav->ivlen = 8;	/* RFC4106 3.1 and RFC3686 3.1 */
	else
		sav->ivlen = (txform == &enc_xform_null ? 0 : 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;

	/*
	 * Whenever AES-GCM is used for encryption, one
	 * of the AES authentication algorithms is chosen
	 * as well, based on the key size.
	 */
	if (sav->alg_enc == SADB_X_EALG_AESGCM16) {
		switch (keylen) {
		case AES_128_GMAC_KEY_LEN:
			sav->alg_auth = SADB_X_AALG_AES128GMAC;
			sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_128;
			break;
		case AES_192_GMAC_KEY_LEN:
			sav->alg_auth = SADB_X_AALG_AES192GMAC;
			sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_192;
			break;
		case AES_256_GMAC_KEY_LEN:
			sav->alg_auth = SADB_X_AALG_AES256GMAC;
			sav->tdb_authalgxform = &auth_hash_nist_gmac_aes_256;
			break;
		default:
			DPRINTF(("%s: invalid key length %u"
				 "for algorithm %s\n", __func__,
				 keylen, txform->name));
			return EINVAL;
		}
		bzero(&cria, sizeof(cria));
		cria.cri_alg = sav->tdb_authalgxform->type;
		cria.cri_key = sav->key_enc->key_data;
		cria.cri_klen = _KEYBITS(sav->key_enc) - SAV_ISGCM(sav) * 32;
	}

	/* Initialize crypto session. */
	bzero(&crie, sizeof(crie));
	crie.cri_alg = sav->tdb_encalgxform->type;
	crie.cri_key = sav->key_enc->key_data;
	crie.cri_klen = _KEYBITS(sav->key_enc) - SAV_ISCTRORGCM(sav) * 32;

	if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
		/* init both auth & enc */
		crie.cri_next = &cria;
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, V_crypto_support);
	} else if (sav->tdb_encalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, V_crypto_support);
	} else if (sav->tdb_authalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &cria, V_crypto_support);
	} else {
		/* XXX cannot happen? */
		DPRINTF(("%s: no encoding OR authentication xform!\n",
			__func__));
		error = EINVAL;
	}
	return error;
}
示例#13
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(("%s: unsupported encryption algorithm %d\n",
			__func__, sav->alg_enc));
		return EINVAL;
	}
	if (sav->key_enc == NULL) {
		DPRINTF(("%s: no encoding key for %s algorithm\n",
			 __func__, txform->name));
		return EINVAL;
	}
	if ((sav->flags&(SADB_X_EXT_OLD|SADB_X_EXT_IV4B)) == SADB_X_EXT_IV4B) {
		DPRINTF(("%s: 4-byte IV not supported with protocol\n",
			__func__));
		return EINVAL;
	}
	keylen = _KEYLEN(sav->key_enc);
	if (txform->minkey > keylen || keylen > txform->maxkey) {
		DPRINTF(("%s: invalid key length %u, must be in the range "
			"[%u..%u] for algorithm %s\n", __func__,
			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(("%s: no memory for IV\n", __func__));
		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 = sav->key_enc->key_data;
	/* XXX Rounds ? */

	if (sav->tdb_authalgxform && sav->tdb_encalgxform) {
		/* init both auth & enc */
		crie.cri_next = &cria;
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, V_crypto_support);
	} else if (sav->tdb_encalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &crie, V_crypto_support);
	} else if (sav->tdb_authalgxform) {
		error = crypto_newsession(&sav->tdb_cryptoid,
					  &cria, V_crypto_support);
	} else {
		/* XXX cannot happen? */
		DPRINTF(("%s: no encoding OR authentication xform!\n",
			__func__));
		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;
}