Module Name: src Committed By: christos Date: Mon Apr 10 14:19:23 UTC 2017
Modified Files: src/sys/netipsec: xform_esp.c Log Message: PR/52150: Ryota Ozaki: ipsec: kernel panic on adding a key with an invalid length. To generate a diff of this commit: cvs rdiff -u -r1.47 -r1.48 src/sys/netipsec/xform_esp.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/netipsec/xform_esp.c diff -u src/sys/netipsec/xform_esp.c:1.47 src/sys/netipsec/xform_esp.c:1.48 --- src/sys/netipsec/xform_esp.c:1.47 Thu Apr 6 05:20:07 2017 +++ src/sys/netipsec/xform_esp.c Mon Apr 10 10:19:22 2017 @@ -1,4 +1,4 @@ -/* $NetBSD: xform_esp.c,v 1.47 2017/04/06 09:20:07 ozaki-r Exp $ */ +/* $NetBSD: xform_esp.c,v 1.48 2017/04/10 14:19:22 christos Exp $ */ /* $FreeBSD: src/sys/netipsec/xform_esp.c,v 1.2.2.1 2003/01/24 05:11:36 sam Exp $ */ /* $OpenBSD: ip_esp.c,v 1.69 2001/06/26 06:18:59 angelos Exp $ */ @@ -39,7 +39,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.47 2017/04/06 09:20:07 ozaki-r Exp $"); +__KERNEL_RCSID(0, "$NetBSD: xform_esp.c,v 1.48 2017/04/10 14:19:22 christos Exp $"); #if defined(_KERNEL_OPT) #include "opt_inet.h" @@ -183,31 +183,31 @@ static int esp_init(struct secasvar *sav, const struct xformsw *xsp) { const struct enc_xform *txform; - struct cryptoini cria, crie; + struct cryptoini cria, crie, *cr; 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)); + DPRINTF(("%s: unsupported encryption algorithm %d\n", __func__, + sav->alg_enc)); return EINVAL; } if (sav->key_enc == NULL) { - DPRINTF(("esp_init: no encoding key for %s algorithm\n", - txform->name)); + 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(("esp_init: 4-byte IV not supported with protocol\n")); + 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(("esp_init: invalid key length %u, must be in " - "the range [%u..%u] for algorithm %s\n", - keylen, txform->minkey, txform->maxkey, - txform->name)); + 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; } @@ -226,8 +226,9 @@ esp_init(struct secasvar *sav, const str sav->tdb_xform = xsp; sav->tdb_encalgxform = txform; - if (sav->alg_enc == SADB_X_EALG_AESGCM16 || - sav->alg_enc == SADB_X_EALG_AESGMAC) { + switch (sav->alg_enc) { + case SADB_X_EALG_AESGCM16: + case SADB_X_EALG_AESGMAC: switch (keylen) { case 20: sav->alg_auth = SADB_X_AALG_AES128GMAC; @@ -241,11 +242,19 @@ esp_init(struct secasvar *sav, const str sav->alg_auth = SADB_X_AALG_AES256GMAC; sav->tdb_authalgxform = &auth_hash_gmac_aes_256; break; - } + default: + DPRINTF(("%s: invalid key length %u, must be either of " + "20, 28 or 36\n", __func__, keylen)); + return EINVAL; + } + 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); + break; + default: + break; } /* Initialize crypto session. */ @@ -258,20 +267,19 @@ esp_init(struct secasvar *sav, const str if (sav->tdb_authalgxform && sav->tdb_encalgxform) { /* init both auth & enc */ crie.cri_next = &cria; - error = crypto_newsession(&sav->tdb_cryptoid, - &crie, crypto_support); + cr = &crie; } else if (sav->tdb_encalgxform) { - error = crypto_newsession(&sav->tdb_cryptoid, - &crie, crypto_support); + cr = &crie; } else if (sav->tdb_authalgxform) { - error = crypto_newsession(&sav->tdb_cryptoid, - &cria, crypto_support); + cr = &cria; } else { /* XXX cannot happen? */ - DPRINTF(("esp_init: no encoding OR authentication xform!\n")); - error = EINVAL; + DPRINTF(("%s: no encoding OR authentication xform!\n", + __func__)); + return EINVAL; } - return error; + + return crypto_newsession(&sav->tdb_cryptoid, cr, crypto_support); } /*