]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netinet6/esp_core.c
xnu-1504.3.12.tar.gz
[apple/xnu.git] / bsd / netinet6 / esp_core.c
index 21daa3f4187aff46d91a29789722c9743fccc2a6..3bae5bd183447ff322a679ef88cc702aa71c8059 100644 (file)
@@ -1,3 +1,31 @@
+/*
+ * Copyright (c) 2008 Apple Inc. All rights reserved.
+ *
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
+ * 
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. The rights granted to you under the License
+ * may not be used to create, or enable the creation or redistribution of,
+ * unlawful or unlicensed copies of an Apple operating system, or to
+ * circumvent, violate, or enable the circumvention or violation of, any
+ * terms of an Apple operating system software license agreement.
+ * 
+ * Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
+ * 
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ * 
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
+ */
+
 /*     $FreeBSD: src/sys/netinet6/esp_core.c,v 1.1.2.4 2002/03/26 10:12:29 ume Exp $   */
 /*     $KAME: esp_core.c,v 1.50 2000/11/02 12:27:38 itojun Exp $       */
 
@@ -102,6 +130,7 @@ static int esp_des_blockdecrypt(const struct esp_algorithm *,
 static int esp_des_blockencrypt(const struct esp_algorithm *,
        struct secasvar *, u_int8_t *, u_int8_t *);
 static int esp_cbc_mature(struct secasvar *);
+#if ALLCRYPTO
 static int esp_blowfish_schedule(const struct esp_algorithm *,
        struct secasvar *);
 static int esp_blowfish_schedlen(const struct esp_algorithm *);
@@ -116,6 +145,7 @@ static int esp_cast128_blockdecrypt(const struct esp_algorithm *,
        struct secasvar *, u_int8_t *, u_int8_t *);
 static int esp_cast128_blockencrypt(const struct esp_algorithm *,
        struct secasvar *, u_int8_t *, u_int8_t *);
+#endif /* ALLCRYPTO */
 static int esp_3des_schedule(const struct esp_algorithm *,
        struct secasvar *);
 static int esp_3des_schedlen(const struct esp_algorithm *);
@@ -132,34 +162,51 @@ static int esp_cbc_encrypt(struct mbuf *, size_t, size_t,
 
 #define MAXIVLEN       16
 
-static const struct esp_algorithm esp_algorithms[] = {
+static const struct esp_algorithm des_cbc =
        { 8, -1, esp_descbc_mature, 64, 64, esp_des_schedlen,
                "des-cbc",
                esp_descbc_ivlen, esp_cbc_decrypt,
                esp_cbc_encrypt, esp_des_schedule,
-               esp_des_blockdecrypt, esp_des_blockencrypt, },
+               esp_des_blockdecrypt, esp_des_blockencrypt, };
+static const struct esp_algorithm des3_cbc =
        { 8, 8, esp_cbc_mature, 192, 192, esp_3des_schedlen,
                "3des-cbc",
                esp_common_ivlen, esp_cbc_decrypt,
                esp_cbc_encrypt, esp_3des_schedule,
-               esp_3des_blockdecrypt, esp_3des_blockencrypt, },
+               esp_3des_blockdecrypt, esp_3des_blockencrypt, };
+static const struct esp_algorithm null_esp =
        { 1, 0, esp_null_mature, 0, 2048, 0, "null",
                esp_common_ivlen, esp_null_decrypt,
-               esp_null_encrypt, NULL, },
+               esp_null_encrypt, NULL, NULL, NULL };
+#if ALLCRYPTO
+static const struct esp_algorithm blowfish_cbc =
        { 8, 8, esp_cbc_mature, 40, 448, esp_blowfish_schedlen, "blowfish-cbc",
                esp_common_ivlen, esp_cbc_decrypt,
                esp_cbc_encrypt, esp_blowfish_schedule,
-               esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, },
+               esp_blowfish_blockdecrypt, esp_blowfish_blockencrypt, };
+static const struct esp_algorithm cast128_cbc =
        { 8, 8, esp_cbc_mature, 40, 128, esp_cast128_schedlen,
                "cast128-cbc",
                esp_common_ivlen, esp_cbc_decrypt,
                esp_cbc_encrypt, esp_cast128_schedule,
-               esp_cast128_blockdecrypt, esp_cast128_blockencrypt, },
+               esp_cast128_blockdecrypt, esp_cast128_blockencrypt, };
+#endif /* ALLCRYPTO */
+static const struct esp_algorithm aes_cbc =
        { 16, 16, esp_cbc_mature, 128, 256, esp_aes_schedlen,
                "aes-cbc",
                esp_common_ivlen, esp_cbc_decrypt_aes,
                esp_cbc_encrypt_aes, esp_aes_schedule,
-               0, 0 },
+               0, 0 };
+
+static const struct esp_algorithm *esp_algorithms[] = {
+       &des_cbc,
+       &des3_cbc,
+       &null_esp,
+#if ALLCRYPTO
+       &blowfish_cbc,
+       &cast128_cbc,
+#endif /* ALLCRYPTO */
+       &aes_cbc
 };
 
 const struct esp_algorithm *
@@ -169,17 +216,19 @@ esp_algorithm_lookup(idx)
 
        switch (idx) {
        case SADB_EALG_DESCBC:
-               return &esp_algorithms[0];
+               return &des_cbc;
        case SADB_EALG_3DESCBC:
-               return &esp_algorithms[1];
+               return &des3_cbc;
        case SADB_EALG_NULL:
-               return &esp_algorithms[2];
+               return &null_esp;
+#if ALLCRYPTO
        case SADB_X_EALG_BLOWFISHCBC:
-               return &esp_algorithms[3];
+               return &blowfish_cbc;
        case SADB_X_EALG_CAST128CBC:
-               return &esp_algorithms[4];
+               return &cast128_cbc;
+#endif /* ALLCRYPTO */
        case SADB_X_EALG_RIJNDAELCBC:
-               return &esp_algorithms[5];
+               return &aes_cbc;
        default:
                return NULL;
        }
@@ -194,8 +243,8 @@ esp_max_ivlen()
        ivlen = 0;
        for (idx = 0; idx < sizeof(esp_algorithms)/sizeof(esp_algorithms[0]);
             idx++) {
-               if (esp_algorithms[idx].ivlenval > ivlen)
-                       ivlen = esp_algorithms[idx].ivlenval;
+               if (esp_algorithms[idx]->ivlenval > ivlen)
+                       ivlen = esp_algorithms[idx]->ivlenval;
        }
 
        return ivlen;
@@ -218,21 +267,29 @@ esp_schedule(algo, sav)
                return EINVAL;
        }
 
+       lck_mtx_lock(sadb_mutex);
        /* already allocated */
-       if (sav->sched && sav->schedlen != 0)
+       if (sav->sched && sav->schedlen != 0) {
+               lck_mtx_unlock(sadb_mutex);
                return 0;
+       }
        /* no schedule necessary */
-       if (!algo->schedule || !algo->schedlen)
+       if (!algo->schedule || !algo->schedlen) {
+               lck_mtx_unlock(sadb_mutex);
                return 0;
-
+       }
+        
        sav->schedlen = (*algo->schedlen)(algo);
-       if (sav->schedlen < 0)
+       if ((signed) sav->schedlen < 0) {
+               lck_mtx_unlock(sadb_mutex);
                return EINVAL;
+       }
 
 //#### that malloc should be replaced by a saved buffer...
        sav->sched = _MALLOC(sav->schedlen, M_SECA, M_DONTWAIT);
        if (!sav->sched) {
                sav->schedlen = 0;
+               lck_mtx_unlock(sadb_mutex);
                return ENOBUFS;
        }
 
@@ -245,12 +302,13 @@ esp_schedule(algo, sav)
                sav->sched = NULL;
                sav->schedlen = 0;
        }
+       lck_mtx_unlock(sadb_mutex);
        return error;
 }
 
 static int
-esp_null_mature(sav)
-       struct secasvar *sav;
+esp_null_mature(
+       __unused struct secasvar *sav)
 {
 
        /* anything is okay */
@@ -258,25 +316,25 @@ esp_null_mature(sav)
 }
 
 static int
-esp_null_decrypt(m, off, sav, algo, ivlen)
-       struct mbuf *m;
-       size_t off;             /* offset to ESP header */
-       struct secasvar *sav;
-       const struct esp_algorithm *algo;
-       int ivlen;
+esp_null_decrypt(
+       __unused struct mbuf *m,
+       __unused size_t off,            /* offset to ESP header */
+       __unused struct secasvar *sav,
+       __unused const struct esp_algorithm *algo,
+       __unused int ivlen)
 {
 
        return 0; /* do nothing */
 }
 
 static int
-esp_null_encrypt(m, off, plen, sav, algo, ivlen)
-       struct mbuf *m;
-       size_t off;     /* offset to ESP header */
-       size_t plen;    /* payload length (to be encrypted) */
-       struct secasvar *sav;
-       const struct esp_algorithm *algo;
-       int ivlen;
+esp_null_encrypt(
+       __unused struct mbuf *m,
+       __unused size_t off,    /* offset to ESP header */
+       __unused size_t plen,   /* payload length (to be encrypted) */
+       __unused struct secasvar *sav,
+       __unused const struct esp_algorithm *algo,
+       __unused int ivlen)
 {
 
        return 0; /* do nothing */
@@ -325,9 +383,9 @@ esp_descbc_mature(sav)
 }
 
 static int
-esp_descbc_ivlen(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_descbc_ivlen(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav)
 {
 
        if (!sav)
@@ -340,19 +398,20 @@ esp_descbc_ivlen(algo, sav)
 }
 
 static int
-esp_des_schedlen(algo)
-       const struct esp_algorithm *algo;
+esp_des_schedlen(
+       __unused const struct esp_algorithm *algo)
 {
 
        return sizeof(des_key_schedule);
 }
 
 static int
-esp_des_schedule(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_des_schedule(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav)
 {
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
        if (des_key_sched((des_cblock *)_KEYBUF(sav->key_enc),
            *(des_key_schedule *)sav->sched))
                return EINVAL;
@@ -361,11 +420,11 @@ esp_des_schedule(algo, sav)
 }
 
 static int
-esp_des_blockdecrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_des_blockdecrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
 
        /* assumption: d has a good alignment */
@@ -376,11 +435,11 @@ esp_des_blockdecrypt(algo, sav, s, d)
 }
 
 static int
-esp_des_blockencrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_des_blockencrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
 
        /* assumption: d has a good alignment */
@@ -456,31 +515,33 @@ esp_cbc_mature(sav)
        return 0;
 }
 
+#if ALLCRYPTO
 static int
-esp_blowfish_schedlen(algo)
-       const struct esp_algorithm *algo;
+esp_blowfish_schedlen(
+       __unused const struct esp_algorithm *algo)
 {
 
        return sizeof(BF_KEY);
 }
 
 static int
-esp_blowfish_schedule(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_blowfish_schedule(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav)
 {
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
        BF_set_key((BF_KEY *)sav->sched, _KEYLEN(sav->key_enc),
-           _KEYBUF(sav->key_enc));
+           (u_int8_t *) _KEYBUF(sav->key_enc));
        return 0;
 }
 
 static int
-esp_blowfish_blockdecrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_blowfish_blockdecrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
        /* HOLY COW!  BF_decrypt() takes values in host byteorder */
        BF_LONG t[2];
@@ -496,11 +557,11 @@ esp_blowfish_blockdecrypt(algo, sav, s, d)
 }
 
 static int
-esp_blowfish_blockencrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_blowfish_blockencrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
        /* HOLY COW!  BF_encrypt() takes values in host byteorder */
        BF_LONG t[2];
@@ -516,30 +577,30 @@ esp_blowfish_blockencrypt(algo, sav, s, d)
 }
 
 static int
-esp_cast128_schedlen(algo)
-       const struct esp_algorithm *algo;
+esp_cast128_schedlen(
+       __unused const struct esp_algorithm *algo)
 {
 
        return sizeof(u_int32_t) * 32;
 }
 
 static int
-esp_cast128_schedule(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_cast128_schedule(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav)
 {
-
-       set_cast128_subkey((u_int32_t *)sav->sched, _KEYBUF(sav->key_enc),
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
+       set_cast128_subkey((u_int32_t *)sav->sched, (u_int8_t *) _KEYBUF(sav->key_enc),
                _KEYLEN(sav->key_enc));
        return 0;
 }
 
 static int
-esp_cast128_blockdecrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_cast128_blockdecrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
 
        if (_KEYLEN(sav->key_enc) <= 80 / 8)
@@ -550,11 +611,11 @@ esp_cast128_blockdecrypt(algo, sav, s, d)
 }
 
 static int
-esp_cast128_blockencrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_cast128_blockencrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
 
        if (_KEYLEN(sav->key_enc) <= 80 / 8)
@@ -563,25 +624,27 @@ esp_cast128_blockencrypt(algo, sav, s, d)
                cast128_encrypt_round16(d, s, (u_int32_t *)sav->sched);
        return 0;
 }
+#endif /* ALLCRYPTO */
 
 static int
-esp_3des_schedlen(algo)
-       const struct esp_algorithm *algo;
+esp_3des_schedlen(
+       __unused const struct esp_algorithm *algo)
 {
 
        return sizeof(des_key_schedule) * 3;
 }
 
 static int
-esp_3des_schedule(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_3des_schedule(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav)
 {
        int error;
        des_key_schedule *p;
        int i;
        char *k;
 
+       lck_mtx_assert(sadb_mutex, LCK_MTX_ASSERT_OWNED);
        p = (des_key_schedule *)sav->sched;
        k = _KEYBUF(sav->key_enc);
        for (i = 0; i < 3; i++) {
@@ -593,11 +656,11 @@ esp_3des_schedule(algo, sav)
 }
 
 static int
-esp_3des_blockdecrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_3des_blockdecrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
        des_key_schedule *p;
 
@@ -610,11 +673,11 @@ esp_3des_blockdecrypt(algo, sav, s, d)
 }
 
 static int
-esp_3des_blockencrypt(algo, sav, s, d)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
-       u_int8_t *s;
-       u_int8_t *d;
+esp_3des_blockencrypt(
+       __unused const struct esp_algorithm *algo,
+       struct secasvar *sav,
+       u_int8_t *s,
+       u_int8_t *d)
 {
        des_key_schedule *p;
 
@@ -627,9 +690,9 @@ esp_3des_blockencrypt(algo, sav, s, d)
 }
 
 static int
-esp_common_ivlen(algo, sav)
-       const struct esp_algorithm *algo;
-       struct secasvar *sav;
+esp_common_ivlen(
+       const struct esp_algorithm *algo,
+       __unused struct secasvar *sav)
 {
 
        if (!algo)
@@ -702,7 +765,7 @@ esp_cbc_decrypt(m, off, sav, algo, ivlen)
        }
 
        /* grab iv */
-       m_copydata(m, ivoff, ivlen, iv);
+       m_copydata(m, ivoff, ivlen, (caddr_t) iv);
 
        /* extend iv */
        if (ivlen == blocklen)
@@ -723,7 +786,7 @@ esp_cbc_decrypt(m, off, sav, algo, ivlen)
 
        if (m->m_pkthdr.len < bodyoff) {
                ipseclog((LOG_ERR, "esp_cbc_decrypt %s: bad len %d/%lu\n",
-                   algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
+                   algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
                m_freem(m);
                return EINVAL;
        }
@@ -764,7 +827,7 @@ esp_cbc_decrypt(m, off, sav, algo, ivlen)
                        sp = mtod(s, u_int8_t *) + sn;
                } else {
                        /* body is non-continuous */
-                       m_copydata(s, sn, blocklen, sbuf);
+                       m_copydata(s, sn, blocklen, (caddr_t) sbuf);
                        sp = sbuf;
                }
 
@@ -837,13 +900,13 @@ esp_cbc_decrypt(m, off, sav, algo, ivlen)
 }
 
 static int
-esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
-       struct mbuf *m;
-       size_t off;
-       size_t plen;
-       struct secasvar *sav;
-       const struct esp_algorithm *algo;
-       int ivlen;
+esp_cbc_encrypt(
+       struct mbuf *m,
+       size_t off,
+       __unused size_t plen,
+       struct secasvar *sav,
+       const struct esp_algorithm *algo,
+       int ivlen)
 {
        struct mbuf *s;
        struct mbuf *d, *d0, *dp;
@@ -903,11 +966,11 @@ esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
 
        /* put iv into the packet.  if we are in derived mode, use seqno. */
        if (derived)
-               m_copydata(m, ivoff, ivlen, iv);
+               m_copydata(m, ivoff, ivlen, (caddr_t) iv);
        else {
                bcopy(sav->iv, iv, ivlen);
                /* maybe it is better to overwrite dest, not source */
-               m_copyback(m, ivoff, ivlen, iv);
+               m_copyback(m, ivoff, ivlen, (caddr_t) iv);
        }
 
        /* extend iv */
@@ -929,14 +992,14 @@ esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
 
        if (m->m_pkthdr.len < bodyoff) {
                ipseclog((LOG_ERR, "esp_cbc_encrypt %s: bad len %d/%lu\n",
-                   algo->name, m->m_pkthdr.len, (unsigned long)bodyoff));
+                   algo->name, m->m_pkthdr.len, (u_int32_t)bodyoff));
                m_freem(m);
                return EINVAL;
        }
        if ((m->m_pkthdr.len - bodyoff) % blocklen) {
                ipseclog((LOG_ERR, "esp_cbc_encrypt %s: "
                    "payload length must be multiple of %lu\n",
-                   algo->name, (unsigned long)algo->padbound));
+                   algo->name, (u_int32_t)algo->padbound));
                m_freem(m);
                return EINVAL;
        }
@@ -970,7 +1033,7 @@ esp_cbc_encrypt(m, off, plen, sav, algo, ivlen)
                        sp = mtod(s, u_int8_t *) + sn;
                } else {
                        /* body is non-continuous */
-                       m_copydata(s, sn, blocklen, sbuf);
+                       m_copydata(s, sn, blocklen, (caddr_t) sbuf);
                        sp = sbuf;
                }
 
@@ -1101,7 +1164,7 @@ esp_auth(m0, skip, length, sav, sum)
        if (sizeof(sumbuf) < siz) {
                ipseclog((LOG_DEBUG,
                    "esp_auth: AH_MAXSUMSIZE is too small: siz=%lu\n",
-                   (u_long)siz));
+                   (u_int32_t)siz));
                KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 4,0,0,0,0);
                return EINVAL;
        }
@@ -1125,25 +1188,23 @@ esp_auth(m0, skip, length, sav, sum)
                KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 5,0,0,0,0);
                return error;
        }
-       lck_mtx_unlock(sadb_mutex);
        while (0 < length) {
                if (!m)
                        panic("mbuf chain?");
 
                if (m->m_len - off < length) {
-                       (*algo->update)(&s, mtod(m, u_char *) + off,
+                       (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off),
                                m->m_len - off);
                        length -= m->m_len - off;
                        m = m->m_next;
                        off = 0;
                } else {
-                       (*algo->update)(&s, mtod(m, u_char *) + off, length);
+                       (*algo->update)(&s, (caddr_t)(mtod(m, u_char *) + off), length);
                        break;
                }
        }
-       (*algo->result)(&s, sumbuf);
+       (*algo->result)(&s, (caddr_t) sumbuf);
        bcopy(sumbuf, sum, siz);        /*XXX*/
-       lck_mtx_lock(sadb_mutex);
        KERNEL_DEBUG(DBG_FNC_ESPAUTH | DBG_FUNC_END, 6,0,0,0,0);
        return 0;
 }